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