First part of fix for bug #7331 - Compound async SMB 2 requests don't work right.
[metze/samba/wip.git] / source3 / smbd / smb2_server.c
1 /*
2    Unix SMB/CIFS implementation.
3    Core SMB2 server
4
5    Copyright (C) Stefan Metzmacher 2009
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "smbd/globals.h"
23 #include "../libcli/smb/smb_common.h"
24 #include "../lib/tsocket/tsocket.h"
25
26 static const char *smb2_names[] = {
27         "SMB2_NEGPROT",
28         "SMB2_SESSSETUP",
29         "SMB2_LOGOFF",
30         "SMB2_TCON",
31         "SMB2_TDIS",
32         "SMB2_CREATE",
33         "SMB2_CLOSE",
34         "SMB2_FLUSH",
35         "SMB2_READ",
36         "SMB2_WRITE",
37         "SMB2_LOCK",
38         "SMB2_IOCTL",
39         "SMB2_CANCEL",
40         "SMB2_KEEPALIVE",
41         "SMB2_FIND",
42         "SMB2_NOTIFY",
43         "SMB2_GETINFO",
44         "SMB2_SETINFO",
45         "SMB2_BREAK"
46 };
47
48 const char *smb2_opcode_name(uint16_t opcode)
49 {
50         if (opcode >= 0x12) {
51                 return "Bad SMB2 opcode";
52         }
53         return smb2_names[opcode];
54 }
55
56 static void print_req_vectors(struct smbd_smb2_request *req)
57 {
58         int i;
59
60         for (i = 0; i < req->in.vector_count; i++) {
61                 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
62                         (unsigned int)i,
63                         (unsigned int)req->in.vector[i].iov_len);
64         }
65         for (i = 0; i < req->out.vector_count; i++) {
66                 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
67                         (unsigned int)i,
68                         (unsigned int)req->out.vector[i].iov_len);
69         }
70 }
71
72 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
73 {
74         if (size < (4 + SMB2_HDR_BODY)) {
75                 return false;
76         }
77
78         if (IVAL(inbuf, 4) != SMB2_MAGIC) {
79                 return false;
80         }
81
82         return true;
83 }
84
85 static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
86 {
87         NTSTATUS status;
88         int ret;
89
90         TALLOC_FREE(sconn->smb1.fde);
91
92         sconn->smb2.event_ctx = smbd_event_context();
93
94         sconn->smb2.recv_queue = tevent_queue_create(sconn, "smb2 recv queue");
95         if (sconn->smb2.recv_queue == NULL) {
96                 return NT_STATUS_NO_MEMORY;
97         }
98
99         sconn->smb2.send_queue = tevent_queue_create(sconn, "smb2 send queue");
100         if (sconn->smb2.send_queue == NULL) {
101                 return NT_STATUS_NO_MEMORY;
102         }
103
104         sconn->smb2.sessions.idtree = idr_init(sconn);
105         if (sconn->smb2.sessions.idtree == NULL) {
106                 return NT_STATUS_NO_MEMORY;
107         }
108         sconn->smb2.sessions.limit = 0x0000FFFE;
109         sconn->smb2.sessions.list = NULL;
110
111         ret = tstream_bsd_existing_socket(sconn, smbd_server_fd(),
112                                           &sconn->smb2.stream);
113         if (ret == -1) {
114                 status = map_nt_error_from_unix(errno);
115                 return status;
116         }
117
118         /* Ensure child is set to non-blocking mode */
119         set_blocking(smbd_server_fd(),false);
120         return NT_STATUS_OK;
121 }
122
123 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
124 #define _smb2_setlen(_buf,len) do { \
125         uint8_t *buf = (uint8_t *)_buf; \
126         buf[0] = 0; \
127         buf[1] = ((len)&0xFF0000)>>16; \
128         buf[2] = ((len)&0xFF00)>>8; \
129         buf[3] = (len)&0xFF; \
130 } while (0)
131
132 static void smb2_setup_nbt_length(struct iovec *vector, int count)
133 {
134         size_t len = 0;
135         int i;
136
137         for (i=1; i < count; i++) {
138                 len += vector[i].iov_len;
139         }
140
141         _smb2_setlen(vector[0].iov_base, len);
142 }
143
144 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request **req)
145 {
146         if (*req) {
147                 (*req)->parent = NULL;
148                 (*req)->mem_pool = NULL;
149         }
150
151         return 0;
152 }
153
154 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
155 {
156         if (req->out.vector) {
157                 DLIST_REMOVE(req->sconn->smb2.requests, req);
158         }
159
160         if (req->parent) {
161                 *req->parent = NULL;
162                 talloc_free(req->mem_pool);
163         }
164
165         return 0;
166 }
167
168 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
169 {
170         TALLOC_CTX *mem_pool;
171         struct smbd_smb2_request **parent;
172         struct smbd_smb2_request *req;
173
174         mem_pool = talloc_pool(mem_ctx, 8192);
175         if (mem_pool == NULL) {
176                 return NULL;
177         }
178
179         parent = talloc(mem_pool, struct smbd_smb2_request *);
180         if (parent == NULL) {
181                 talloc_free(mem_pool);
182                 return NULL;
183         }
184
185         req = talloc_zero(parent, struct smbd_smb2_request);
186         if (req == NULL) {
187                 talloc_free(mem_pool);
188                 return NULL;
189         }
190         *parent         = req;
191         req->mem_pool   = mem_pool;
192         req->parent     = parent;
193
194         talloc_set_destructor(parent, smbd_smb2_request_parent_destructor);
195         talloc_set_destructor(req, smbd_smb2_request_destructor);
196
197         return req;
198 }
199
200 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
201                                          const uint8_t *inbuf, size_t size,
202                                          struct smbd_smb2_request **_req)
203 {
204         struct smbd_smb2_request *req;
205         uint32_t protocol_version;
206         const uint8_t *inhdr = NULL;
207         off_t ofs = 0;
208         uint16_t cmd;
209         uint32_t next_command_ofs;
210
211         if (size < (4 + SMB2_HDR_BODY + 2)) {
212                 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
213                 return NT_STATUS_INVALID_PARAMETER;
214         }
215
216         inhdr = inbuf + 4;
217
218         protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
219         if (protocol_version != SMB2_MAGIC) {
220                 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
221                          protocol_version));
222                 return NT_STATUS_INVALID_PARAMETER;
223         }
224
225         cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
226         if (cmd != SMB2_OP_NEGPROT) {
227                 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
228                          cmd));
229                 return NT_STATUS_INVALID_PARAMETER;
230         }
231
232         next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
233         if (next_command_ofs != 0) {
234                 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
235                          next_command_ofs));
236                 return NT_STATUS_INVALID_PARAMETER;
237         }
238
239         req = smbd_smb2_request_allocate(sconn);
240         if (req == NULL) {
241                 return NT_STATUS_NO_MEMORY;
242         }
243         req->sconn = sconn;
244
245         talloc_steal(req, inbuf);
246
247         req->in.vector = talloc_array(req, struct iovec, 4);
248         if (req->in.vector == NULL) {
249                 TALLOC_FREE(req);
250                 return NT_STATUS_NO_MEMORY;
251         }
252         req->in.vector_count = 4;
253
254         memcpy(req->in.nbt_hdr, inbuf, 4);
255
256         ofs = 0;
257         req->in.vector[0].iov_base      = (void *)req->in.nbt_hdr;
258         req->in.vector[0].iov_len       = 4;
259         ofs += req->in.vector[0].iov_len;
260
261         req->in.vector[1].iov_base      = (void *)(inbuf + ofs);
262         req->in.vector[1].iov_len       = SMB2_HDR_BODY;
263         ofs += req->in.vector[1].iov_len;
264
265         req->in.vector[2].iov_base      = (void *)(inbuf + ofs);
266         req->in.vector[2].iov_len       = SVAL(inbuf, ofs) & 0xFFFE;
267         ofs += req->in.vector[2].iov_len;
268
269         if (ofs > size) {
270                 return NT_STATUS_INVALID_PARAMETER;
271         }
272
273         req->in.vector[3].iov_base      = (void *)(inbuf + ofs);
274         req->in.vector[3].iov_len       = size - ofs;
275         ofs += req->in.vector[3].iov_len;
276
277         req->current_idx = 1;
278
279         *_req = req;
280         return NT_STATUS_OK;
281 }
282
283 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req,
284                                 uint16_t *p_creds_requested)
285 {
286         int count;
287         int idx;
288         bool compound_related = false;
289
290         *p_creds_requested = 0;
291         count = req->in.vector_count;
292
293         if (count < 4) {
294                 /* It's not a SMB2 request */
295                 return NT_STATUS_INVALID_PARAMETER;
296         }
297
298         for (idx=1; idx < count; idx += 3) {
299                 uint16_t creds_requested = 0;
300                 const uint8_t *inhdr = NULL;
301                 uint32_t flags;
302
303                 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
304                         return NT_STATUS_INVALID_PARAMETER;
305                 }
306
307                 if (req->in.vector[idx+1].iov_len < 2) {
308                         return NT_STATUS_INVALID_PARAMETER;
309                 }
310
311                 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
312
313                 /* setup the SMB2 header */
314                 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
315                         return NT_STATUS_INVALID_PARAMETER;
316                 }
317
318                 creds_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
319                 if (*p_creds_requested + creds_requested < creds_requested) {
320                         *p_creds_requested = 65535;
321                 } else {
322                         *p_creds_requested += creds_requested;
323                 }
324
325                 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
326                 if (idx == 1) {
327                         /*
328                          * the 1st request should never have the
329                          * SMB2_HDR_FLAG_CHAINED flag set
330                          */
331                         if (flags & SMB2_HDR_FLAG_CHAINED) {
332                                 req->next_status = NT_STATUS_INVALID_PARAMETER;
333                                 return NT_STATUS_OK;
334                         }
335                 } else if (idx == 4) {
336                         /*
337                          * the 2nd request triggers related vs. unrelated
338                          * compounded requests
339                          */
340                         if (flags & SMB2_HDR_FLAG_CHAINED) {
341                                 compound_related = true;
342                         }
343                 } else if (idx > 4) {
344 #if 0
345                         /*
346                          * It seems the this tests are wrong
347                          * see the SMB2-COMPOUND test
348                          */
349
350                         /*
351                          * all other requests should match the 2nd one
352                          */
353                         if (flags & SMB2_HDR_FLAG_CHAINED) {
354                                 if (!compound_related) {
355                                         req->next_status =
356                                                 NT_STATUS_INVALID_PARAMETER;
357                                         return NT_STATUS_OK;
358                                 }
359                         } else {
360                                 if (compound_related) {
361                                         req->next_status =
362                                                 NT_STATUS_INVALID_PARAMETER;
363                                         return NT_STATUS_OK;
364                                 }
365                         }
366 #endif
367                 }
368         }
369
370         return NT_STATUS_OK;
371 }
372
373 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req, uint16_t creds)
374 {
375         struct iovec *vector;
376         int count;
377         int idx;
378
379         count = req->in.vector_count;
380         vector = talloc_array(req, struct iovec, count);
381         if (vector == NULL) {
382                 return NT_STATUS_NO_MEMORY;
383         }
384
385         vector[0].iov_base      = req->out.nbt_hdr;
386         vector[0].iov_len       = 4;
387         SIVAL(req->out.nbt_hdr, 0, 0);
388
389         for (idx=1; idx < count; idx += 3) {
390                 const uint8_t *inhdr = NULL;
391                 uint32_t in_flags;
392                 uint8_t *outhdr = NULL;
393                 uint8_t *outbody = NULL;
394                 uint32_t next_command_ofs = 0;
395                 struct iovec *current = &vector[idx];
396
397                 if ((idx + 3) < count) {
398                         /* we have a next command */
399                         next_command_ofs = SMB2_HDR_BODY + 8;
400                 }
401
402                 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
403                 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
404
405                 outhdr = talloc_array(vector, uint8_t,
406                                       SMB2_HDR_BODY + 8);
407                 if (outhdr == NULL) {
408                         return NT_STATUS_NO_MEMORY;
409                 }
410
411                 outbody = outhdr + SMB2_HDR_BODY;
412
413                 current[0].iov_base     = (void *)outhdr;
414                 current[0].iov_len      = SMB2_HDR_BODY;
415
416                 current[1].iov_base     = (void *)outbody;
417                 current[1].iov_len      = 8;
418
419                 current[2].iov_base     = NULL;
420                 current[2].iov_len      = 0;
421
422                 /* setup the SMB2 header */
423                 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID,     SMB2_MAGIC);
424                 SSVAL(outhdr, SMB2_HDR_LENGTH,          SMB2_HDR_BODY);
425                 SSVAL(outhdr, SMB2_HDR_EPOCH,           0);
426                 SIVAL(outhdr, SMB2_HDR_STATUS,
427                       NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
428                 SSVAL(outhdr, SMB2_HDR_OPCODE,
429                       SVAL(inhdr, SMB2_HDR_OPCODE));
430                 SSVAL(outhdr, SMB2_HDR_CREDIT,          creds);
431                 SIVAL(outhdr, SMB2_HDR_FLAGS,
432                       IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
433                 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND,    next_command_ofs);
434                 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
435                       BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
436                 SIVAL(outhdr, SMB2_HDR_PID,
437                       IVAL(inhdr, SMB2_HDR_PID));
438                 SIVAL(outhdr, SMB2_HDR_TID,
439                       IVAL(inhdr, SMB2_HDR_TID));
440                 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
441                       BVAL(inhdr, SMB2_HDR_SESSION_ID));
442                 memset(outhdr + SMB2_HDR_SIGNATURE, 0, 16);
443
444                 /* setup error body header */
445                 SSVAL(outbody, 0x00, 0x08 + 1);
446                 SSVAL(outbody, 0x02, 0);
447                 SIVAL(outbody, 0x04, 0);
448         }
449
450         req->out.vector = vector;
451         req->out.vector_count = count;
452
453         /* setup the length of the NBT packet */
454         smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
455
456         DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
457
458         return NT_STATUS_OK;
459 }
460
461 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
462                                          const char *reason,
463                                          const char *location)
464 {
465         DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
466                   reason, location));
467         exit_server_cleanly(reason);
468 }
469
470 static bool dup_smb2_vec(struct iovec *dstvec,
471                         const struct iovec *srcvec,
472                         int offset)
473 {
474
475         if (srcvec[offset].iov_len &&
476                         srcvec[offset].iov_base) {
477                 dstvec[offset].iov_base = talloc_memdup(dstvec,
478                                         srcvec[offset].iov_base,
479                                         srcvec[offset].iov_len);
480                 if (!dstvec[offset].iov_base) {
481                         return false;
482                 }
483                 dstvec[offset].iov_len = srcvec[offset].iov_len;
484         } else {
485                 dstvec[offset].iov_base = NULL;
486                 dstvec[offset].iov_len = 0;
487         }
488         return true;
489 }
490
491 static struct smbd_smb2_request *dup_smb2_req(struct smbd_smb2_request *req)
492 {
493         struct smbd_smb2_request *newreq = NULL;
494         struct iovec *outvec = NULL;
495         int count = req->out.vector_count;
496         int i;
497
498         newreq = smbd_smb2_request_allocate(req->sconn);
499         if (!newreq) {
500                 return NULL;
501         }
502
503         newreq->sconn = req->sconn;
504         newreq->do_signing = req->do_signing;
505         newreq->current_idx = req->current_idx;
506         newreq->async = false;
507         newreq->cancelled = false;
508
509         outvec = talloc_array(newreq, struct iovec, count);
510         if (!outvec) {
511                 TALLOC_FREE(newreq);
512                 return NULL;
513         }
514         newreq->out.vector = outvec;
515         newreq->out.vector_count = count;
516
517         /* Setup the outvec's identically to req. */
518         outvec[0].iov_base = newreq->out.nbt_hdr;
519         outvec[0].iov_len = 4;
520         memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
521                 
522         for (i = 1; i < count; i++) {
523                 if (!dup_smb2_vec(outvec,
524                                 req->out.vector,
525                                 i)) {
526                         TALLOC_FREE(newreq);
527                         return NULL;
528                 }
529         }
530
531         smb2_setup_nbt_length(newreq->out.vector,
532                 newreq->out.vector_count);
533
534         return newreq;
535 }
536
537 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
538
539 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
540                                          struct tevent_req *subreq)
541 {
542         int i = req->current_idx;
543         struct smbd_smb2_request *nreq = NULL;
544         uint8_t *outhdr = NULL;
545         uint8_t *outbody = NULL;
546         uint32_t flags = 0;
547         uint64_t message_id = 0;
548         uint64_t async_id = 0;
549         struct iovec *outvec = NULL;
550
551         if (!tevent_req_is_in_progress(subreq)) {
552                 return NT_STATUS_OK;
553         }
554
555         if (req->async) {
556                 /* We're already async. */
557                 return NT_STATUS_OK;
558         }
559
560         if (req->in.vector_count > i + 3) {
561                 /*
562                  * We're trying to go async in a compound
563                  * request chain. This is not allowed.
564                  * Cancel the outstanding request.
565                  */
566                 tevent_req_cancel(subreq);
567                 return smbd_smb2_request_error(req,
568                         NT_STATUS_INSUFFICIENT_RESOURCES);
569         }
570
571         req->subreq = subreq;
572         subreq = NULL;
573
574         if (DEBUGLEVEL >= 10) {
575                 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
576                         (unsigned int)req->current_idx );
577                 print_req_vectors(req);
578         }
579
580         /* Create a new smb2 request we'll use to return. */
581         nreq = dup_smb2_req(req);
582         if (!nreq) {
583                 return NT_STATUS_NO_MEMORY;
584         }
585
586         outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
587
588         flags = IVAL(outhdr, SMB2_HDR_FLAGS);
589         message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
590
591         async_id = message_id; /* keep it simple for now... */
592         SIVAL(outhdr, SMB2_HDR_FLAGS,   flags | SMB2_HDR_FLAG_ASYNC);
593         SBVAL(outhdr, SMB2_HDR_PID,     async_id);
594         SIVAL(outhdr, SMB2_HDR_STATUS,  NT_STATUS_V(STATUS_PENDING));
595
596         nreq->out.vector[i+1].iov_base = talloc_zero_array(nreq->out.vector,
597                                                         uint8_t,
598                                                         9);
599         if (!nreq->out.vector[i+1].iov_base) {
600                 return NT_STATUS_NO_MEMORY;
601         }
602         nreq->out.vector[i+1].iov_len = 9;
603         outbody = (uint8_t *)nreq->out.vector[i+1].iov_base;
604
605         /* setup error body header */
606         SSVAL(outbody, 0x00, 0x08 + 1);
607         SSVAL(outbody, 0x02, 0);
608         SIVAL(outbody, 0x04, 0);
609         /* Match W2K8R2... */
610         SCVAL(outbody, 8, 0x21);
611
612         nreq->out.vector[i+2].iov_base = NULL;
613         nreq->out.vector[i+2].iov_len = 0;
614
615         smb2_setup_nbt_length(nreq->out.vector,
616                 nreq->out.vector_count);
617
618         if (nreq->do_signing) {
619                 NTSTATUS status;
620                 status = smb2_signing_sign_pdu(nreq->session->session_key,
621                                         &nreq->out.vector[i], 3);
622                 if (!NT_STATUS_IS_OK(status)) {
623                         return status;
624                 }
625         }
626
627         if (DEBUGLEVEL >= 10) {
628                 dbgtext("smbd_smb2_request_pending_queue: nreq->current_idx = %u\n",
629                         (unsigned int)nreq->current_idx );
630                 dbgtext("smbd_smb2_request_pending_queue: returning %u vectors\n",
631                         (unsigned int)nreq->out.vector_count );
632                 print_req_vectors(nreq);
633         }
634
635         nreq->subreq = tstream_writev_queue_send(nreq,
636                                         nreq->sconn->smb2.event_ctx,
637                                         nreq->sconn->smb2.stream,
638                                         nreq->sconn->smb2.send_queue,
639                                         nreq->out.vector,
640                                         nreq->out.vector_count);
641
642         if (nreq->subreq == NULL) {
643                 return NT_STATUS_NO_MEMORY;
644         }
645
646         tevent_req_set_callback(nreq->subreq,
647                         smbd_smb2_request_writev_done,
648                         nreq);
649
650         /* Note we're going async with this request. */
651         req->async = true;
652
653         /*
654          * Now manipulate req so that the outstanding async request
655          * is the only one left in the struct smbd_smb2_request.
656          */
657
658         if (req->current_idx == 1) {
659                 /* There was only one. */
660                 goto out;
661         }
662
663         /* Re-arrange the in.vectors. */
664         req->in.vector[1] = req->in.vector[i];
665         req->in.vector[2] = req->in.vector[i+1];
666         req->in.vector[3] = req->in.vector[i+2];
667         req->in.vector_count = 4;
668         /* Reset the new in size. */
669         smb2_setup_nbt_length(req->in.vector, 4);
670
671         /* Now recreate the out.vectors. */
672         outvec = talloc_array(req, struct iovec, 4);
673         if (!outvec) {
674                 return NT_STATUS_NO_MEMORY;
675         }
676         outvec[0].iov_base = req->out.nbt_hdr;
677         outvec[0].iov_len = 4;
678         SIVAL(req->out.nbt_hdr, 0, 0);
679
680         outvec[1].iov_base = talloc_memdup(outvec,
681                                 req->out.vector[i].iov_base,
682                                 SMB2_HDR_BODY + 8);
683         if (!outvec[1].iov_base) {
684                 return NT_STATUS_NO_MEMORY;
685         }
686         outvec[1].iov_len = SMB2_HDR_BODY;
687
688         outvec[2].iov_base = ((uint8_t *)outvec[1].iov_base) +
689                                 SMB2_HDR_BODY;
690         outvec[2].iov_len = 8;
691
692         if (req->out.vector[i+2].iov_base &&
693                         req->out.vector[i+2].iov_len) {
694                 outvec[3].iov_base = talloc_memdup(outvec,
695                                         req->out.vector[i+2].iov_base,
696                                         req->out.vector[i+2].iov_len);
697                 if (!outvec[3].iov_base) {
698                         return NT_STATUS_NO_MEMORY;
699                 }
700                 outvec[3].iov_len = req->out.vector[i+2].iov_len;
701         } else {
702                 outvec[3].iov_base = NULL;
703                 outvec[3].iov_len = 0;
704         }
705
706         TALLOC_FREE(req->out.vector);
707
708         req->out.vector = outvec;
709
710         req->current_idx = 1;
711         req->out.vector_count = 4;
712
713   out:
714
715         smb2_setup_nbt_length(req->out.vector,
716                 req->out.vector_count);
717
718         /* Ensure our final reply matches the interim one. */
719         outhdr = (uint8_t *)req->out.vector[1].iov_base;
720         SIVAL(outhdr, SMB2_HDR_FLAGS,   flags | SMB2_HDR_FLAG_ASYNC);
721         SBVAL(outhdr, SMB2_HDR_PID,     async_id);
722
723         {
724                 const uint8_t *inhdr =
725                         (const uint8_t *)req->in.vector[1].iov_base;
726                 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
727                         "going async\n",
728                         smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
729                         (unsigned long long)async_id ));
730         }
731         return NT_STATUS_OK;
732 }
733
734 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
735 {
736         struct smbd_server_connection *sconn = req->sconn;
737         struct smbd_smb2_request *cur;
738         const uint8_t *inhdr;
739         int i = req->current_idx;
740         uint32_t flags;
741         uint64_t search_message_id;
742         uint64_t search_async_id;
743         uint64_t found_id;
744
745         inhdr = (const uint8_t *)req->in.vector[i].iov_base;
746
747         flags = IVAL(inhdr, SMB2_HDR_FLAGS);
748         search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
749         search_async_id = BVAL(inhdr, SMB2_HDR_PID);
750
751         /*
752          * we don't need the request anymore
753          * cancel requests never have a response
754          */
755         TALLOC_FREE(req);
756
757         for (cur = sconn->smb2.requests; cur; cur = cur->next) {
758                 const uint8_t *outhdr;
759                 uint64_t message_id;
760                 uint64_t async_id;
761
762                 i = cur->current_idx;
763
764                 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
765
766                 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
767                 async_id = BVAL(outhdr, SMB2_HDR_PID);
768
769                 if (flags & SMB2_HDR_FLAG_ASYNC) {
770                         if (search_async_id == async_id) {
771                                 found_id = async_id;
772                                 break;
773                         }
774                 } else {
775                         if (search_message_id == message_id) {
776                                 found_id = message_id;
777                                 break;
778                         }
779                 }
780         }
781
782         if (cur && cur->subreq) {
783                 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
784                 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
785                         "cancel opcode[%s] mid %llu\n",
786                         smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
787                         (unsigned long long)found_id ));
788                 tevent_req_cancel(cur->subreq);
789                 TALLOC_FREE(cur->subreq);
790                 TALLOC_FREE(cur);
791         }
792
793         return NT_STATUS_OK;
794 }
795
796 static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
797 {
798         const uint8_t *inhdr;
799         int i = req->current_idx;
800         uint16_t opcode;
801         uint32_t flags;
802         uint64_t mid;
803         NTSTATUS status;
804         NTSTATUS session_status;
805         uint32_t allowed_flags;
806
807         inhdr = (const uint8_t *)req->in.vector[i].iov_base;
808
809         /* TODO: verify more things */
810
811         flags = IVAL(inhdr, SMB2_HDR_FLAGS);
812         opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
813         mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
814         DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
815                 smb2_opcode_name(opcode),
816                 (unsigned long long)mid));
817
818         allowed_flags = SMB2_HDR_FLAG_CHAINED |
819                         SMB2_HDR_FLAG_SIGNED |
820                         SMB2_HDR_FLAG_DFS;
821         if (opcode == SMB2_OP_CANCEL) {
822                 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
823         }
824         if ((flags & ~allowed_flags) != 0) {
825                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
826         }
827
828         session_status = smbd_smb2_request_check_session(req);
829
830         req->do_signing = false;
831         if (flags & SMB2_HDR_FLAG_SIGNED) {
832                 if (!NT_STATUS_IS_OK(session_status)) {
833                         return smbd_smb2_request_error(req, session_status);
834                 }
835
836                 req->do_signing = true;
837                 status = smb2_signing_check_pdu(req->session->session_key,
838                                                 &req->in.vector[i], 3);
839                 if (!NT_STATUS_IS_OK(status)) {
840                         return smbd_smb2_request_error(req, status);
841                 }
842         } else if (req->session && req->session->do_signing) {
843                 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
844         }
845
846         if (flags & SMB2_HDR_FLAG_CHAINED) {
847                 /*
848                  * This check is mostly for giving the correct error code
849                  * for compounded requests.
850                  *
851                  * TODO: we may need to move this after the session
852                  *       and tcon checks.
853                  */
854                 if (!NT_STATUS_IS_OK(req->next_status)) {
855                         return smbd_smb2_request_error(req, req->next_status);
856                 }
857         } else {
858                 req->compat_chain_fsp = NULL;
859         }
860
861         switch (opcode) {
862         case SMB2_OP_NEGPROT:
863                 return smbd_smb2_request_process_negprot(req);
864
865         case SMB2_OP_SESSSETUP:
866                 return smbd_smb2_request_process_sesssetup(req);
867
868         case SMB2_OP_LOGOFF:
869                 if (!NT_STATUS_IS_OK(session_status)) {
870                         return smbd_smb2_request_error(req, session_status);
871                 }
872                 return smbd_smb2_request_process_logoff(req);
873
874         case SMB2_OP_TCON:
875                 if (!NT_STATUS_IS_OK(session_status)) {
876                         return smbd_smb2_request_error(req, session_status);
877                 }
878                 status = smbd_smb2_request_check_session(req);
879                 if (!NT_STATUS_IS_OK(status)) {
880                         return smbd_smb2_request_error(req, status);
881                 }
882                 return smbd_smb2_request_process_tcon(req);
883
884         case SMB2_OP_TDIS:
885                 if (!NT_STATUS_IS_OK(session_status)) {
886                         return smbd_smb2_request_error(req, session_status);
887                 }
888                 status = smbd_smb2_request_check_tcon(req);
889                 if (!NT_STATUS_IS_OK(status)) {
890                         return smbd_smb2_request_error(req, status);
891                 }
892                 return smbd_smb2_request_process_tdis(req);
893
894         case SMB2_OP_CREATE:
895                 if (!NT_STATUS_IS_OK(session_status)) {
896                         return smbd_smb2_request_error(req, session_status);
897                 }
898                 status = smbd_smb2_request_check_tcon(req);
899                 if (!NT_STATUS_IS_OK(status)) {
900                         return smbd_smb2_request_error(req, status);
901                 }
902                 return smbd_smb2_request_process_create(req);
903
904         case SMB2_OP_CLOSE:
905                 if (!NT_STATUS_IS_OK(session_status)) {
906                         return smbd_smb2_request_error(req, session_status);
907                 }
908                 status = smbd_smb2_request_check_tcon(req);
909                 if (!NT_STATUS_IS_OK(status)) {
910                         return smbd_smb2_request_error(req, status);
911                 }
912                 return smbd_smb2_request_process_close(req);
913
914         case SMB2_OP_FLUSH:
915                 if (!NT_STATUS_IS_OK(session_status)) {
916                         return smbd_smb2_request_error(req, session_status);
917                 }
918                 status = smbd_smb2_request_check_tcon(req);
919                 if (!NT_STATUS_IS_OK(status)) {
920                         return smbd_smb2_request_error(req, status);
921                 }
922                 return smbd_smb2_request_process_flush(req);
923
924         case SMB2_OP_READ:
925                 if (!NT_STATUS_IS_OK(session_status)) {
926                         return smbd_smb2_request_error(req, session_status);
927                 }
928                 status = smbd_smb2_request_check_tcon(req);
929                 if (!NT_STATUS_IS_OK(status)) {
930                         return smbd_smb2_request_error(req, status);
931                 }
932                 return smbd_smb2_request_process_read(req);
933
934         case SMB2_OP_WRITE:
935                 if (!NT_STATUS_IS_OK(session_status)) {
936                         return smbd_smb2_request_error(req, session_status);
937                 }
938                 status = smbd_smb2_request_check_tcon(req);
939                 if (!NT_STATUS_IS_OK(status)) {
940                         return smbd_smb2_request_error(req, status);
941                 }
942                 return smbd_smb2_request_process_write(req);
943
944         case SMB2_OP_LOCK:
945                 if (!NT_STATUS_IS_OK(session_status)) {
946                         return smbd_smb2_request_error(req, session_status);
947                 }
948                 status = smbd_smb2_request_check_tcon(req);
949                 if (!NT_STATUS_IS_OK(status)) {
950                         return smbd_smb2_request_error(req, status);
951                 }
952                 return smbd_smb2_request_process_lock(req);
953
954         case SMB2_OP_IOCTL:
955                 if (!NT_STATUS_IS_OK(session_status)) {
956                         return smbd_smb2_request_error(req, session_status);
957                 }
958                 status = smbd_smb2_request_check_tcon(req);
959                 if (!NT_STATUS_IS_OK(status)) {
960                         return smbd_smb2_request_error(req, status);
961                 }
962                 return smbd_smb2_request_process_ioctl(req);
963
964         case SMB2_OP_CANCEL:
965                 return smbd_smb2_request_process_cancel(req);
966
967         case SMB2_OP_KEEPALIVE:
968                 return smbd_smb2_request_process_keepalive(req);
969
970         case SMB2_OP_FIND:
971                 if (!NT_STATUS_IS_OK(session_status)) {
972                         return smbd_smb2_request_error(req, session_status);
973                 }
974                 status = smbd_smb2_request_check_tcon(req);
975                 if (!NT_STATUS_IS_OK(status)) {
976                         return smbd_smb2_request_error(req, status);
977                 }
978                 return smbd_smb2_request_process_find(req);
979
980         case SMB2_OP_NOTIFY:
981                 if (!NT_STATUS_IS_OK(session_status)) {
982                         return smbd_smb2_request_error(req, session_status);
983                 }
984                 status = smbd_smb2_request_check_tcon(req);
985                 if (!NT_STATUS_IS_OK(status)) {
986                         return smbd_smb2_request_error(req, status);
987                 }
988                 return smbd_smb2_request_process_notify(req);
989
990         case SMB2_OP_GETINFO:
991                 if (!NT_STATUS_IS_OK(session_status)) {
992                         return smbd_smb2_request_error(req, session_status);
993                 }
994                 status = smbd_smb2_request_check_tcon(req);
995                 if (!NT_STATUS_IS_OK(status)) {
996                         return smbd_smb2_request_error(req, status);
997                 }
998                 return smbd_smb2_request_process_getinfo(req);
999
1000         case SMB2_OP_SETINFO:
1001                 if (!NT_STATUS_IS_OK(session_status)) {
1002                         return smbd_smb2_request_error(req, session_status);
1003                 }
1004                 status = smbd_smb2_request_check_tcon(req);
1005                 if (!NT_STATUS_IS_OK(status)) {
1006                         return smbd_smb2_request_error(req, status);
1007                 }
1008                 return smbd_smb2_request_process_setinfo(req);
1009
1010         case SMB2_OP_BREAK:
1011                 if (!NT_STATUS_IS_OK(session_status)) {
1012                         return smbd_smb2_request_error(req, session_status);
1013                 }
1014                 status = smbd_smb2_request_check_tcon(req);
1015                 if (!NT_STATUS_IS_OK(status)) {
1016                         return smbd_smb2_request_error(req, status);
1017                 }
1018                 return smbd_smb2_request_process_break(req);
1019         }
1020
1021         return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1022 }
1023
1024 static void smbd_smb2_request_dispatch_compound(struct tevent_context *ctx,
1025                                         struct tevent_immediate *im,
1026                                         void *private_data);
1027
1028 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1029 {
1030         struct tevent_req *subreq;
1031
1032         req->subreq = NULL;
1033
1034         smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1035
1036         if (req->do_signing) {
1037                 int i = req->current_idx;
1038                 NTSTATUS status;
1039                 status = smb2_signing_sign_pdu(req->session->session_key,
1040                                                &req->out.vector[i], 3);
1041                 if (!NT_STATUS_IS_OK(status)) {
1042                         return status;
1043                 }
1044         }
1045
1046         req->current_idx += 3;
1047
1048         if (req->current_idx < req->out.vector_count) {
1049                 /*
1050                  * We must process the remaining compound
1051                  * SMB2 requests before any new incoming SMB2
1052                  * requests. This is because incoming SMB2
1053                  * requests may include a cancel for a
1054                  * compound request we haven't processed
1055                  * yet.
1056                  */
1057                 struct tevent_immediate *im = tevent_create_immediate(req);
1058                 if (!im) {
1059                         return NT_STATUS_NO_MEMORY;
1060                 }
1061                 tevent_schedule_immediate(im,
1062                                         req->sconn->smb2.event_ctx,
1063                                         smbd_smb2_request_dispatch_compound,
1064                                         req);
1065                 return NT_STATUS_OK;
1066         }
1067
1068         if (DEBUGLEVEL >= 10) {
1069                 dbgtext("smbd_smb2_request_reply: sending...\n");
1070                 print_req_vectors(req);
1071         }
1072
1073         subreq = tstream_writev_queue_send(req,
1074                                            req->sconn->smb2.event_ctx,
1075                                            req->sconn->smb2.stream,
1076                                            req->sconn->smb2.send_queue,
1077                                            req->out.vector,
1078                                            req->out.vector_count);
1079         if (subreq == NULL) {
1080                 return NT_STATUS_NO_MEMORY;
1081         }
1082         tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1083
1084         return NT_STATUS_OK;
1085 }
1086
1087 static void smbd_smb2_request_dispatch_compound(struct tevent_context *ctx,
1088                                         struct tevent_immediate *im,
1089                                         void *private_data)
1090 {
1091         struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1092                                         struct smbd_smb2_request);
1093         struct smbd_server_connection *sconn = req->sconn;
1094         NTSTATUS status;
1095
1096         TALLOC_FREE(im);
1097
1098         if (DEBUGLEVEL >= 10) {
1099                 DEBUG(10,("smbd_smb2_request_dispatch_compound: idx[%d] of %d vectors\n",
1100                         req->current_idx, req->in.vector_count));
1101                 print_req_vectors(req);
1102         }
1103
1104         status = smbd_smb2_request_dispatch(req);
1105         if (!NT_STATUS_IS_OK(status)) {
1106                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1107                 return;
1108         }
1109 }
1110
1111 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1112 {
1113         struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1114                                         struct smbd_smb2_request);
1115         struct smbd_server_connection *sconn = req->sconn;
1116         int ret;
1117         int sys_errno;
1118
1119         ret = tstream_writev_queue_recv(subreq, &sys_errno);
1120         TALLOC_FREE(subreq);
1121         TALLOC_FREE(req);
1122         if (ret == -1) {
1123                 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1124                 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1125                         nt_errstr(status)));
1126                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1127                 return;
1128         }
1129 }
1130
1131 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
1132                                     NTSTATUS status,
1133                                     DATA_BLOB *info,
1134                                     const char *location)
1135 {
1136         uint8_t *outhdr;
1137         uint8_t *outbody;
1138         int i = req->current_idx;
1139
1140         DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1141                   i, nt_errstr(status), info ? " +info" : "",
1142                   location));
1143
1144         outhdr = (uint8_t *)req->out.vector[i].iov_base;
1145
1146         SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1147
1148         outbody = outhdr + SMB2_HDR_BODY;
1149
1150         req->out.vector[i+1].iov_base = (void *)outbody;
1151         req->out.vector[i+1].iov_len = 8;
1152
1153         if (info) {
1154                 SIVAL(outbody, 0x04, info->length);
1155                 req->out.vector[i+2].iov_base   = (void *)info->data;
1156                 req->out.vector[i+2].iov_len    = info->length;
1157         } else {
1158                 req->out.vector[i+2].iov_base = NULL;
1159                 req->out.vector[i+2].iov_len = 0;
1160         }
1161
1162         /*
1163          * if a request fails, all other remaining
1164          * compounded requests should fail too
1165          */
1166         req->next_status = NT_STATUS_INVALID_PARAMETER;
1167
1168         return smbd_smb2_request_reply(req);
1169 }
1170
1171 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1172                                    NTSTATUS status,
1173                                    DATA_BLOB body, DATA_BLOB *dyn,
1174                                    const char *location)
1175 {
1176         uint8_t *outhdr;
1177         uint8_t *outdyn;
1178         int i = req->current_idx;
1179         uint32_t next_command_ofs;
1180
1181         DEBUG(10,("smbd_smb2_request_done_ex: "
1182                   "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1183                   i, nt_errstr(status), (unsigned int)body.length,
1184                   dyn ? "yes": "no",
1185                   (unsigned int)(dyn ? dyn->length : 0),
1186                   location));
1187
1188         if (body.length < 2) {
1189                 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1190         }
1191
1192         if ((body.length % 2) != 0) {
1193                 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1194         }
1195
1196         outhdr = (uint8_t *)req->out.vector[i].iov_base;
1197         /* the fallback dynamic buffer */
1198         outdyn = outhdr + SMB2_HDR_BODY + 8;
1199
1200         next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1201         SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1202
1203         req->out.vector[i+1].iov_base = (void *)body.data;
1204         req->out.vector[i+1].iov_len = body.length;
1205
1206         if (dyn) {
1207                 req->out.vector[i+2].iov_base   = (void *)dyn->data;
1208                 req->out.vector[i+2].iov_len    = dyn->length;
1209         } else {
1210                 req->out.vector[i+2].iov_base = NULL;
1211                 req->out.vector[i+2].iov_len = 0;
1212         }
1213
1214         /* see if we need to recalculate the offset to the next response */
1215         if (next_command_ofs > 0) {
1216                 next_command_ofs  = SMB2_HDR_BODY;
1217                 next_command_ofs += req->out.vector[i+1].iov_len;
1218                 next_command_ofs += req->out.vector[i+2].iov_len;
1219         }
1220
1221         if ((next_command_ofs % 8) != 0) {
1222                 size_t pad_size = 8 - (next_command_ofs % 8);
1223                 if (req->out.vector[i+2].iov_len == 0) {
1224                         /*
1225                          * if the dyn buffer is empty
1226                          * we can use it to add padding
1227                          */
1228                         uint8_t *pad;
1229
1230                         pad = talloc_zero_array(req->out.vector,
1231                                                 uint8_t, pad_size);
1232                         if (pad == NULL) {
1233                                 return smbd_smb2_request_error(req,
1234                                                 NT_STATUS_NO_MEMORY);
1235                         }
1236
1237                         req->out.vector[i+2].iov_base = (void *)pad;
1238                         req->out.vector[i+2].iov_len = pad_size;
1239                 } else {
1240                         /*
1241                          * For now we copy the dynamic buffer
1242                          * and add the padding to the new buffer
1243                          */
1244                         size_t old_size;
1245                         uint8_t *old_dyn;
1246                         size_t new_size;
1247                         uint8_t *new_dyn;
1248
1249                         old_size = req->out.vector[i+2].iov_len;
1250                         old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
1251
1252                         new_size = old_size + pad_size;
1253                         new_dyn = talloc_array(req->out.vector,
1254                                                uint8_t, new_size);
1255                         if (new_dyn == NULL) {
1256                                 return smbd_smb2_request_error(req,
1257                                                 NT_STATUS_NO_MEMORY);
1258                         }
1259
1260                         memcpy(new_dyn, old_dyn, old_size);
1261                         memset(new_dyn + old_size, 0, pad_size);
1262
1263                         req->out.vector[i+2].iov_base = (void *)new_dyn;
1264                         req->out.vector[i+2].iov_len = new_size;
1265
1266                         TALLOC_FREE(old_dyn);
1267                 }
1268                 next_command_ofs += pad_size;
1269         }
1270
1271         SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1272
1273         return smbd_smb2_request_reply(req);
1274 }
1275
1276 struct smbd_smb2_send_oplock_break_state {
1277         struct smbd_server_connection *sconn;
1278         uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
1279         struct iovec vector;
1280 };
1281
1282 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
1283
1284 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
1285                                      uint64_t file_id_persistent,
1286                                      uint64_t file_id_volatile,
1287                                      uint8_t oplock_level)
1288 {
1289         struct smbd_smb2_send_oplock_break_state *state;
1290         struct tevent_req *subreq;
1291         uint8_t *hdr;
1292         uint8_t *body;
1293
1294         state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
1295         if (state == NULL) {
1296                 return NT_STATUS_NO_MEMORY;
1297         }
1298         state->sconn = sconn;
1299
1300         state->vector.iov_base = (void *)state->buf;
1301         state->vector.iov_len = sizeof(state->buf);
1302
1303         _smb2_setlen(state->buf, sizeof(state->buf) - 4);
1304         hdr = state->buf + 4;
1305         body = hdr + SMB2_HDR_BODY;
1306
1307         SIVAL(hdr, 0,                           SMB2_MAGIC);
1308         SSVAL(hdr, SMB2_HDR_LENGTH,             SMB2_HDR_BODY);
1309         SSVAL(hdr, SMB2_HDR_EPOCH,              0);
1310         SIVAL(hdr, SMB2_HDR_STATUS,             0);
1311         SSVAL(hdr, SMB2_HDR_OPCODE,             SMB2_OP_BREAK);
1312         SSVAL(hdr, SMB2_HDR_CREDIT,             0);
1313         SIVAL(hdr, SMB2_HDR_FLAGS,              SMB2_HDR_FLAG_REDIRECT);
1314         SIVAL(hdr, SMB2_HDR_NEXT_COMMAND,       0);
1315         SBVAL(hdr, SMB2_HDR_MESSAGE_ID,         UINT64_MAX);
1316         SIVAL(hdr, SMB2_HDR_PID,                0);
1317         SIVAL(hdr, SMB2_HDR_TID,                0);
1318         SBVAL(hdr, SMB2_HDR_SESSION_ID,         0);
1319         memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
1320
1321         SSVAL(body, 0x00, 0x18);
1322
1323         SCVAL(body, 0x02, oplock_level);
1324         SCVAL(body, 0x03, 0);           /* reserved */
1325         SIVAL(body, 0x04, 0);           /* reserved */
1326         SBVAL(body, 0x08, file_id_persistent);
1327         SBVAL(body, 0x10, file_id_volatile);
1328
1329         subreq = tstream_writev_queue_send(state,
1330                                            sconn->smb2.event_ctx,
1331                                            sconn->smb2.stream,
1332                                            sconn->smb2.send_queue,
1333                                            &state->vector, 1);
1334         if (subreq == NULL) {
1335                 return NT_STATUS_NO_MEMORY;
1336         }
1337         tevent_req_set_callback(subreq,
1338                                 smbd_smb2_oplock_break_writev_done,
1339                                 state);
1340
1341         return NT_STATUS_OK;
1342 }
1343
1344 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
1345 {
1346         struct smbd_smb2_send_oplock_break_state *state =
1347                 tevent_req_callback_data(subreq,
1348                 struct smbd_smb2_send_oplock_break_state);
1349         struct smbd_server_connection *sconn = state->sconn;
1350         int ret;
1351         int sys_errno;
1352
1353         ret = tstream_writev_queue_recv(subreq, &sys_errno);
1354         TALLOC_FREE(subreq);
1355         if (ret == -1) {
1356                 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1357                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1358                 return;
1359         }
1360
1361         TALLOC_FREE(state);
1362 }
1363
1364 struct smbd_smb2_request_read_state {
1365         size_t missing;
1366         bool asked_for_header;
1367         struct smbd_smb2_request *smb2_req;
1368 };
1369
1370 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1371                                          void *private_data,
1372                                          TALLOC_CTX *mem_ctx,
1373                                          struct iovec **_vector,
1374                                          size_t *_count);
1375 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
1376
1377 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
1378                                         struct tevent_context *ev,
1379                                         struct smbd_server_connection *sconn)
1380 {
1381         struct tevent_req *req;
1382         struct smbd_smb2_request_read_state *state;
1383         struct tevent_req *subreq;
1384
1385         req = tevent_req_create(mem_ctx, &state,
1386                                 struct smbd_smb2_request_read_state);
1387         if (req == NULL) {
1388                 return NULL;
1389         }
1390         state->missing = 0;
1391         state->asked_for_header = false;
1392
1393         state->smb2_req = smbd_smb2_request_allocate(state);
1394         if (tevent_req_nomem(state->smb2_req, req)) {
1395                 return tevent_req_post(req, ev);
1396         }
1397         state->smb2_req->sconn = sconn;
1398
1399         subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
1400                                               sconn->smb2.recv_queue,
1401                                               smbd_smb2_request_next_vector,
1402                                               state);
1403         if (tevent_req_nomem(subreq, req)) {
1404                 return tevent_req_post(req, ev);
1405         }
1406         tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
1407
1408         return req;
1409 }
1410
1411 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1412                                          void *private_data,
1413                                          TALLOC_CTX *mem_ctx,
1414                                          struct iovec **_vector,
1415                                          size_t *_count)
1416 {
1417         struct smbd_smb2_request_read_state *state =
1418                 talloc_get_type_abort(private_data,
1419                 struct smbd_smb2_request_read_state);
1420         struct smbd_smb2_request *req = state->smb2_req;
1421         struct iovec *vector;
1422         int idx = req->in.vector_count;
1423         size_t len = 0;
1424         uint8_t *buf = NULL;
1425
1426         if (req->in.vector_count == 0) {
1427                 /*
1428                  * first we need to get the NBT header
1429                  */
1430                 req->in.vector = talloc_array(req, struct iovec,
1431                                               req->in.vector_count + 1);
1432                 if (req->in.vector == NULL) {
1433                         return -1;
1434                 }
1435                 req->in.vector_count += 1;
1436
1437                 req->in.vector[idx].iov_base    = (void *)req->in.nbt_hdr;
1438                 req->in.vector[idx].iov_len     = 4;
1439
1440                 vector = talloc_array(mem_ctx, struct iovec, 1);
1441                 if (vector == NULL) {
1442                         return -1;
1443                 }
1444
1445                 vector[0] = req->in.vector[idx];
1446
1447                 *_vector = vector;
1448                 *_count = 1;
1449                 return 0;
1450         }
1451
1452         if (req->in.vector_count == 1) {
1453                 /*
1454                  * Now we analyze the NBT header
1455                  */
1456                 state->missing = smb2_len(req->in.vector[0].iov_base);
1457
1458                 if (state->missing == 0) {
1459                         /* if there're no remaining bytes, we're done */
1460                         *_vector = NULL;
1461                         *_count = 0;
1462                         return 0;
1463                 }
1464
1465                 req->in.vector = talloc_realloc(req, req->in.vector,
1466                                                 struct iovec,
1467                                                 req->in.vector_count + 1);
1468                 if (req->in.vector == NULL) {
1469                         return -1;
1470                 }
1471                 req->in.vector_count += 1;
1472
1473                 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
1474                         /*
1475                          * it's a special NBT message,
1476                          * so get all remaining bytes
1477                          */
1478                         len = state->missing;
1479                 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
1480                         /*
1481                          * it's an invalid message, just read what we can get
1482                          * and let the caller handle the error
1483                          */
1484                         len = state->missing;
1485                 } else {
1486                         /*
1487                          * We assume it's a SMB2 request,
1488                          * and we first get the header and the
1489                          * first 2 bytes (the struct size) of the body
1490                          */
1491                         len = SMB2_HDR_BODY + 2;
1492
1493                         state->asked_for_header = true;
1494                 }
1495
1496                 state->missing -= len;
1497
1498                 buf = talloc_array(req->in.vector, uint8_t, len);
1499                 if (buf == NULL) {
1500                         return -1;
1501                 }
1502
1503                 req->in.vector[idx].iov_base    = (void *)buf;
1504                 req->in.vector[idx].iov_len     = len;
1505
1506                 vector = talloc_array(mem_ctx, struct iovec, 1);
1507                 if (vector == NULL) {
1508                         return -1;
1509                 }
1510
1511                 vector[0] = req->in.vector[idx];
1512
1513                 *_vector = vector;
1514                 *_count = 1;
1515                 return 0;
1516         }
1517
1518         if (state->missing == 0) {
1519                 /* if there're no remaining bytes, we're done */
1520                 *_vector = NULL;
1521                 *_count = 0;
1522                 return 0;
1523         }
1524
1525         if (state->asked_for_header) {
1526                 const uint8_t *hdr;
1527                 size_t full_size;
1528                 size_t next_command_ofs;
1529                 size_t body_size;
1530                 uint8_t *body;
1531                 size_t dyn_size;
1532                 uint8_t *dyn;
1533                 bool invalid = false;
1534
1535                 state->asked_for_header = false;
1536
1537                 /*
1538                  * We got the SMB2 header and the first 2 bytes
1539                  * of the body. We fix the size to just the header
1540                  * and manually copy the 2 first bytes to the body section
1541                  */
1542                 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
1543                 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
1544
1545                 /* allocate vectors for body and dynamic areas */
1546                 req->in.vector = talloc_realloc(req, req->in.vector,
1547                                                 struct iovec,
1548                                                 req->in.vector_count + 2);
1549                 if (req->in.vector == NULL) {
1550                         return -1;
1551                 }
1552                 req->in.vector_count += 2;
1553
1554                 full_size = state->missing + SMB2_HDR_BODY + 2;
1555                 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
1556                 body_size = SVAL(hdr, SMB2_HDR_BODY);
1557
1558                 if (next_command_ofs != 0) {
1559                         if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
1560                                 /*
1561                                  * this is invalid, just return a zero
1562                                  * body and let the caller deal with the error
1563                                  */
1564                                 invalid = true;
1565                         } else if (next_command_ofs > full_size) {
1566                                 /*
1567                                  * this is invalid, just return a zero
1568                                  * body and let the caller deal with the error
1569                                  */
1570                                 invalid = true;
1571                         } else {
1572                                 full_size = next_command_ofs;
1573                         }
1574                 }
1575
1576                 if (!invalid) {
1577                         if (body_size < 2) {
1578                                 /*
1579                                  * this is invalid, just return a zero
1580                                  * body and let the caller deal with the error
1581                                  */
1582                                 invalid = true;
1583                         }
1584
1585                         if ((body_size % 2) != 0) {
1586                                 body_size -= 1;
1587                         }
1588
1589                         if (body_size > (full_size - SMB2_HDR_BODY)) {
1590                                 /*
1591                                  * this is invalid, just return a zero
1592                                  * body and let the caller deal with the error
1593                                  */
1594                                 invalid = true;
1595                         }
1596                 }
1597
1598                 if (invalid) {
1599                         /* the caller should check this */
1600                         body_size = 2;
1601                 }
1602
1603                 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
1604
1605                 state->missing -= (body_size - 2) + dyn_size;
1606
1607                 body = talloc_array(req->in.vector, uint8_t, body_size);
1608                 if (body == NULL) {
1609                         return -1;
1610                 }
1611
1612                 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
1613                 if (dyn == NULL) {
1614                         return -1;
1615                 }
1616
1617                 req->in.vector[idx].iov_base    = (void *)body;
1618                 req->in.vector[idx].iov_len     = body_size;
1619                 req->in.vector[idx+1].iov_base  = (void *)dyn;
1620                 req->in.vector[idx+1].iov_len   = dyn_size;
1621
1622                 vector = talloc_array(mem_ctx, struct iovec, 2);
1623                 if (vector == NULL) {
1624                         return -1;
1625                 }
1626
1627                 /*
1628                  * the first 2 bytes of the body were already fetched
1629                  * together with the header
1630                  */
1631                 memcpy(body, hdr + SMB2_HDR_BODY, 2);
1632                 vector[0].iov_base = body + 2;
1633                 vector[0].iov_len = body_size - 2;
1634
1635                 vector[1] = req->in.vector[idx+1];
1636
1637                 *_vector = vector;
1638                 *_count = 2;
1639                 return 0;
1640         }
1641
1642         /*
1643          * when we endup here, we're looking for a new SMB2 request
1644          * next. And we ask for its header and the first 2 bytes of
1645          * the body (like we did for the first SMB2 request).
1646          */
1647
1648         req->in.vector = talloc_realloc(req, req->in.vector,
1649                                         struct iovec,
1650                                         req->in.vector_count + 1);
1651         if (req->in.vector == NULL) {
1652                 return -1;
1653         }
1654         req->in.vector_count += 1;
1655
1656         /*
1657          * We assume it's a SMB2 request,
1658          * and we first get the header and the
1659          * first 2 bytes (the struct size) of the body
1660          */
1661         len = SMB2_HDR_BODY + 2;
1662
1663         if (len > state->missing) {
1664                 /* let the caller handle the error */
1665                 len = state->missing;
1666         }
1667
1668         state->missing -= len;
1669         state->asked_for_header = true;
1670
1671         buf = talloc_array(req->in.vector, uint8_t, len);
1672         if (buf == NULL) {
1673                 return -1;
1674         }
1675
1676         req->in.vector[idx].iov_base    = (void *)buf;
1677         req->in.vector[idx].iov_len     = len;
1678
1679         vector = talloc_array(mem_ctx, struct iovec, 1);
1680         if (vector == NULL) {
1681                 return -1;
1682         }
1683
1684         vector[0] = req->in.vector[idx];
1685
1686         *_vector = vector;
1687         *_count = 1;
1688         return 0;
1689 }
1690
1691 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
1692 {
1693         struct tevent_req *req =
1694                 tevent_req_callback_data(subreq,
1695                 struct tevent_req);
1696         int ret;
1697         int sys_errno;
1698         NTSTATUS status;
1699
1700         ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
1701         if (ret == -1) {
1702                 status = map_nt_error_from_unix(sys_errno);
1703                 tevent_req_nterror(req, status);
1704                 return;
1705         }
1706
1707         tevent_req_done(req);
1708 }
1709
1710 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
1711                                             TALLOC_CTX *mem_ctx,
1712                                             struct smbd_smb2_request **_smb2_req)
1713 {
1714         struct smbd_smb2_request_read_state *state =
1715                 tevent_req_data(req,
1716                 struct smbd_smb2_request_read_state);
1717         NTSTATUS status;
1718
1719         if (tevent_req_is_nterror(req, &status)) {
1720                 tevent_req_received(req);
1721                 return status;
1722         }
1723
1724         talloc_steal(mem_ctx, state->smb2_req->mem_pool);
1725         *_smb2_req = state->smb2_req;
1726         tevent_req_received(req);
1727         return NT_STATUS_OK;
1728 }
1729
1730 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
1731
1732 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
1733                              const uint8_t *inbuf, size_t size)
1734 {
1735         NTSTATUS status;
1736         struct smbd_smb2_request *req;
1737         struct tevent_req *subreq;
1738
1739         DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
1740                  (unsigned int)size));
1741
1742         status = smbd_initialize_smb2(sconn);
1743         if (!NT_STATUS_IS_OK(status)) {
1744                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1745                 return;
1746         }
1747
1748         status = smbd_smb2_request_create(sconn, inbuf, size, &req);
1749         if (!NT_STATUS_IS_OK(status)) {
1750                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1751                 return;
1752         }
1753
1754         status = smbd_smb2_request_setup_out(req, (uint16_t)lp_maxmux());
1755         if (!NT_STATUS_IS_OK(status)) {
1756                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1757                 return;
1758         }
1759
1760         status = smbd_smb2_request_dispatch(req);
1761         if (!NT_STATUS_IS_OK(status)) {
1762                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1763                 return;
1764         }
1765
1766         /* ask for the next request */
1767         subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
1768         if (subreq == NULL) {
1769                 smbd_server_connection_terminate(sconn, "no memory for reading");
1770                 return;
1771         }
1772         tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
1773 }
1774
1775 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
1776 {
1777         uint16_t creds_requested = 0;
1778         struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
1779                                                struct smbd_server_connection);
1780         NTSTATUS status;
1781         struct smbd_smb2_request *req = NULL;
1782
1783         status = smbd_smb2_request_read_recv(subreq, sconn, &req);
1784         TALLOC_FREE(subreq);
1785         if (!NT_STATUS_IS_OK(status)) {
1786                 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
1787                         nt_errstr(status)));
1788                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1789                 return;
1790         }
1791
1792         if (req->in.nbt_hdr[0] != 0x00) {
1793                 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
1794                          req->in.nbt_hdr[0]));
1795                 TALLOC_FREE(req);
1796                 goto next;
1797         }
1798
1799         req->current_idx = 1;
1800
1801         DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
1802                  req->current_idx, req->in.vector_count));
1803
1804         status = smbd_smb2_request_validate(req, &creds_requested);
1805         if (!NT_STATUS_IS_OK(status)) {
1806                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1807                 return;
1808         }
1809
1810         status = smbd_smb2_request_setup_out(req, 5);
1811         if (!NT_STATUS_IS_OK(status)) {
1812                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1813                 return;
1814         }
1815
1816         status = smbd_smb2_request_dispatch(req);
1817         if (!NT_STATUS_IS_OK(status)) {
1818                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1819                 return;
1820         }
1821
1822 next:
1823         /* ask for the next request (this constructs the main loop) */
1824         subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
1825         if (subreq == NULL) {
1826                 smbd_server_connection_terminate(sconn, "no memory for reading");
1827                 return;
1828         }
1829         tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
1830 }