75c818bcda52904412ec59b1affa76261b43ba04
[kai/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
441                 /* Remember what we gave out. */
442                 req->sconn->smb2.credits_granted += creds;
443
444                 SIVAL(outhdr, SMB2_HDR_FLAGS,
445                       IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
446                 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND,    next_command_ofs);
447                 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
448                       BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
449                 SIVAL(outhdr, SMB2_HDR_PID,
450                       IVAL(inhdr, SMB2_HDR_PID));
451                 SIVAL(outhdr, SMB2_HDR_TID,
452                       IVAL(inhdr, SMB2_HDR_TID));
453                 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
454                       BVAL(inhdr, SMB2_HDR_SESSION_ID));
455                 memset(outhdr + SMB2_HDR_SIGNATURE, 0, 16);
456
457                 /* setup error body header */
458                 SSVAL(outbody, 0x00, 0x08 + 1);
459                 SSVAL(outbody, 0x02, 0);
460                 SIVAL(outbody, 0x04, 0);
461         }
462
463         req->out.vector = vector;
464         req->out.vector_count = count;
465
466         /* setup the length of the NBT packet */
467         smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
468
469         DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
470
471         return NT_STATUS_OK;
472 }
473
474 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
475                                          const char *reason,
476                                          const char *location)
477 {
478         DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
479                   reason, location));
480         exit_server_cleanly(reason);
481 }
482
483 static bool dup_smb2_vec(struct iovec *dstvec,
484                         const struct iovec *srcvec,
485                         int offset)
486 {
487
488         if (srcvec[offset].iov_len &&
489                         srcvec[offset].iov_base) {
490                 dstvec[offset].iov_base = talloc_memdup(dstvec,
491                                         srcvec[offset].iov_base,
492                                         srcvec[offset].iov_len);
493                 if (!dstvec[offset].iov_base) {
494                         return false;
495                 }
496                 dstvec[offset].iov_len = srcvec[offset].iov_len;
497         } else {
498                 dstvec[offset].iov_base = NULL;
499                 dstvec[offset].iov_len = 0;
500         }
501         return true;
502 }
503
504 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
505 {
506         struct smbd_smb2_request *newreq = NULL;
507         struct iovec *outvec = NULL;
508         int count = req->out.vector_count;
509         int i;
510
511         newreq = smbd_smb2_request_allocate(req->sconn);
512         if (!newreq) {
513                 return NULL;
514         }
515
516         newreq->sconn = req->sconn;
517         newreq->do_signing = req->do_signing;
518         newreq->current_idx = req->current_idx;
519         newreq->async = false;
520         newreq->cancelled = false;
521
522         outvec = talloc_zero_array(newreq, struct iovec, count);
523         if (!outvec) {
524                 TALLOC_FREE(newreq);
525                 return NULL;
526         }
527         newreq->out.vector = outvec;
528         newreq->out.vector_count = count;
529
530         /* Setup the outvec's identically to req. */
531         outvec[0].iov_base = newreq->out.nbt_hdr;
532         outvec[0].iov_len = 4;
533         memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
534
535         for (i = 1; i < count; i += 3) {
536                 /* i + 0 and i + 1 are always
537                  * boilerplate. */
538                 outvec[i].iov_base = talloc_memdup(outvec,
539                                                 req->out.vector[i].iov_base,
540                                                 OUTVEC_ALLOC_SIZE);
541                 if (!outvec[i].iov_base) {
542                         break;
543                 }
544                 outvec[i].iov_len = SMB2_HDR_BODY;
545
546                 outvec[i+1].iov_base = ((uint8_t *)outvec[i].iov_base) +
547                                                 SMB2_HDR_BODY;
548                 outvec[i+1].iov_len = 8;
549
550                 if (req->out.vector[i+2].iov_base ==
551                                 ((uint8_t *)req->out.vector[i].iov_base) +
552                                         (OUTVEC_ALLOC_SIZE - 1) &&
553                                 req->out.vector[i+2].iov_len == 1) {
554                         /* Common SMB2 error packet case. */
555                         outvec[i+2].iov_base = ((uint8_t *)outvec[i].iov_base) +
556                                 (OUTVEC_ALLOC_SIZE - 1);
557                         outvec[i+2].iov_len = 1;
558                 } else if (!dup_smb2_vec(outvec,
559                                 req->out.vector,
560                                 i)) {
561                         break;
562                 }
563         }
564
565         if (i < count) {
566                 /* Alloc failed. */
567                 TALLOC_FREE(newreq);
568                 return NULL;
569         }
570
571         smb2_setup_nbt_length(newreq->out.vector,
572                 newreq->out.vector_count);
573
574         return newreq;
575 }
576
577 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
578
579 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
580 {
581         int i = 0;
582         uint8_t *outhdr = NULL;
583         struct smbd_smb2_request *nreq = NULL;
584
585         /* Create a new smb2 request we'll use
586            for the interim return. */
587         nreq = dup_smb2_req(req);
588         if (!nreq) {
589                 return NT_STATUS_NO_MEMORY;
590         }
591
592         /* Lose the last 3 out vectors. They're the
593            ones we'll be using for the async reply. */
594         nreq->out.vector_count -= 3;
595
596         smb2_setup_nbt_length(nreq->out.vector,
597                 nreq->out.vector_count);
598
599         /* Step back to the previous reply. */
600         i = nreq->current_idx - 3;
601         outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
602         /* And end the chain. */
603         SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
604
605         /* Re-sign if needed. */
606         if (nreq->do_signing) {
607                 NTSTATUS status;
608                 status = smb2_signing_sign_pdu(nreq->session->session_key,
609                                         &nreq->out.vector[i], 3);
610                 if (!NT_STATUS_IS_OK(status)) {
611                         return status;
612                 }
613         }
614         if (DEBUGLEVEL >= 10) {
615                 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
616                         (unsigned int)nreq->current_idx );
617                 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
618                         (unsigned int)nreq->out.vector_count );
619                 print_req_vectors(nreq);
620         }
621         nreq->subreq = tstream_writev_queue_send(nreq,
622                                         nreq->sconn->smb2.event_ctx,
623                                         nreq->sconn->smb2.stream,
624                                         nreq->sconn->smb2.send_queue,
625                                         nreq->out.vector,
626                                         nreq->out.vector_count);
627
628         if (nreq->subreq == NULL) {
629                 return NT_STATUS_NO_MEMORY;
630         }
631
632         tevent_req_set_callback(nreq->subreq,
633                         smbd_smb2_request_writev_done,
634                         nreq);
635
636         return NT_STATUS_OK;
637 }
638
639 struct smbd_smb2_request_pending_state {
640         struct smbd_server_connection *sconn;
641         uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
642         struct iovec vector[3];
643 };
644
645 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
646 {
647         struct smbd_smb2_request_pending_state *state =
648                 tevent_req_callback_data(subreq,
649                         struct smbd_smb2_request_pending_state);
650         struct smbd_server_connection *sconn = state->sconn;
651         int ret;
652         int sys_errno;
653
654         ret = tstream_writev_queue_recv(subreq, &sys_errno);
655         TALLOC_FREE(subreq);
656         if (ret == -1) {
657                 NTSTATUS status = map_nt_error_from_unix(sys_errno);
658                 smbd_server_connection_terminate(sconn, nt_errstr(status));
659                 return;
660         }
661
662         TALLOC_FREE(state);
663 }
664
665 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
666                                          struct tevent_req *subreq)
667 {
668         NTSTATUS status;
669         struct smbd_smb2_request_pending_state *state = NULL;
670         int i = req->current_idx;
671         uint8_t *reqhdr = NULL;
672         uint8_t *hdr = NULL;
673         uint8_t *body = NULL;
674         uint32_t flags = 0;
675         uint64_t message_id = 0;
676         uint64_t async_id = 0;
677         struct iovec *outvec = NULL;
678
679         if (!tevent_req_is_in_progress(subreq)) {
680                 return NT_STATUS_OK;
681         }
682
683         if (req->async) {
684                 /* We're already async. */
685                 return NT_STATUS_OK;
686         }
687
688         if (req->in.vector_count > i + 3) {
689                 /*
690                  * We're trying to go async in a compound
691                  * request chain. This is not allowed.
692                  * Cancel the outstanding request.
693                  */
694                 tevent_req_cancel(subreq);
695                 return smbd_smb2_request_error(req,
696                         NT_STATUS_INSUFFICIENT_RESOURCES);
697         }
698
699         req->subreq = subreq;
700         subreq = NULL;
701
702         if (DEBUGLEVEL >= 10) {
703                 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
704                         (unsigned int)req->current_idx );
705                 print_req_vectors(req);
706         }
707
708         if (req->out.vector_count > 4) {
709                 /* This is a compound reply. We
710                  * must do an interim response
711                  * followed by the async response
712                  * to match W2K8R2.
713                  */
714                 status = smb2_send_async_interim_response(req);
715                 if (!NT_STATUS_IS_OK(status)) {
716                         return status;
717                 }
718         }
719
720         /* Don't return an intermediate packet on a pipe read/write. */
721         if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
722                 return NT_STATUS_OK;
723         }
724
725         reqhdr = (uint8_t *)req->out.vector[i].iov_base;
726         flags = (IVAL(reqhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
727         message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
728         async_id = message_id; /* keep it simple for now... */
729
730         /*
731          * What we send is identical to a smbd_smb2_request_error
732          * packet with an error status of STATUS_PENDING. Make use
733          * of this fact sometime when refactoring. JRA.
734          */
735
736         state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
737         if (state == NULL) {
738                 return NT_STATUS_NO_MEMORY;
739         }
740         state->sconn = req->sconn;
741
742         state->vector[0].iov_base = (void *)state->buf;
743         state->vector[0].iov_len = 4;
744
745         state->vector[1].iov_base = state->buf + 4;
746         state->vector[1].iov_len = SMB2_HDR_BODY;
747
748         state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
749         state->vector[2].iov_len = 9;
750
751         smb2_setup_nbt_length(state->vector, 3);
752
753         hdr = (uint8_t *)state->vector[1].iov_base;
754         body = (uint8_t *)state->vector[2].iov_base;
755
756         SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
757         SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
758         SSVAL(hdr, SMB2_HDR_EPOCH, 0);
759         SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
760         SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(reqhdr, SMB2_HDR_OPCODE));
761         SSVAL(hdr, SMB2_HDR_CREDIT, 5);
762
763         req->sconn->smb2.credits_granted += 5;
764
765         SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
766         SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
767         SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
768         SBVAL(hdr, SMB2_HDR_PID, async_id);
769         SBVAL(hdr, SMB2_HDR_SESSION_ID,
770                 BVAL(reqhdr, SMB2_HDR_SESSION_ID));
771         memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
772
773         SSVAL(body, 0x00, 0x08 + 1);
774
775         SCVAL(body, 0x02, 0);
776         SCVAL(body, 0x03, 0);
777         SIVAL(body, 0x04, 0);
778         /* Match W2K8R2... */
779         SCVAL(body, 0x08, 0x21);
780
781         if (req->do_signing) {
782                 status = smb2_signing_sign_pdu(req->session->session_key,
783                                         state->vector, 3);
784                 if (!NT_STATUS_IS_OK(status)) {
785                         return status;
786                 }
787         }
788
789         subreq = tstream_writev_queue_send(state,
790                                         req->sconn->smb2.event_ctx,
791                                         req->sconn->smb2.stream,
792                                         req->sconn->smb2.send_queue,
793                                         state->vector,
794                                         3);
795
796         if (subreq == NULL) {
797                 return NT_STATUS_NO_MEMORY;
798         }
799
800         tevent_req_set_callback(subreq,
801                         smbd_smb2_request_pending_writev_done,
802                         state);
803
804         /* Note we're going async with this request. */
805         req->async = true;
806
807         /*
808          * Now manipulate req so that the outstanding async request
809          * is the only one left in the struct smbd_smb2_request.
810          */
811
812         if (req->current_idx == 1) {
813                 /* There was only one. */
814                 goto out;
815         }
816
817         /* Re-arrange the in.vectors. */
818         req->in.vector[1] = req->in.vector[i];
819         req->in.vector[2] = req->in.vector[i+1];
820         req->in.vector[3] = req->in.vector[i+2];
821         req->in.vector_count = 4;
822         /* Reset the new in size. */
823         smb2_setup_nbt_length(req->in.vector, 4);
824
825         /* Now recreate the out.vectors. */
826         outvec = talloc_zero_array(req, struct iovec, 4);
827         if (!outvec) {
828                 return NT_STATUS_NO_MEMORY;
829         }
830         outvec[0].iov_base = req->out.nbt_hdr;
831         outvec[0].iov_len = 4;
832         SIVAL(req->out.nbt_hdr, 0, 0);
833
834         outvec[1].iov_base = talloc_memdup(outvec,
835                                 req->out.vector[i].iov_base,
836                                 OUTVEC_ALLOC_SIZE);
837         if (!outvec[1].iov_base) {
838                 return NT_STATUS_NO_MEMORY;
839         }
840         outvec[1].iov_len = SMB2_HDR_BODY;
841
842         outvec[2].iov_base = ((uint8_t *)outvec[1].iov_base) +
843                                 SMB2_HDR_BODY;
844         outvec[2].iov_len = 8;
845
846         if (req->out.vector[i+2].iov_base &&
847                         req->out.vector[i+2].iov_len) {
848                 if (req->out.vector[i+2].iov_base ==
849                                 ((uint8_t *)req->out.vector[i].iov_base) +
850                                         (OUTVEC_ALLOC_SIZE - 1) &&
851                                 req->out.vector[i].iov_len == 1) {
852                         /* Common SMB2 error packet case. */
853                         outvec[3].iov_base = ((uint8_t *)outvec[1].iov_base) +
854                                 (OUTVEC_ALLOC_SIZE - 1);
855                 } else {
856                         outvec[3].iov_base = talloc_memdup(outvec,
857                                         req->out.vector[i+2].iov_base,
858                                         req->out.vector[i+2].iov_len);
859                         if (!outvec[3].iov_base) {
860                                 return NT_STATUS_NO_MEMORY;
861                         }
862                 }
863                 outvec[3].iov_len = req->out.vector[i+2].iov_len;
864         } else {
865                 outvec[3].iov_base = NULL;
866                 outvec[3].iov_len = 0;
867         }
868
869         TALLOC_FREE(req->out.vector);
870
871         req->out.vector = outvec;
872
873         req->current_idx = 1;
874         req->out.vector_count = 4;
875
876   out:
877
878         smb2_setup_nbt_length(req->out.vector,
879                 req->out.vector_count);
880
881         /* Ensure our final reply matches the interim one. */
882         reqhdr = (uint8_t *)req->out.vector[1].iov_base;
883         SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
884         SBVAL(reqhdr, SMB2_HDR_PID, async_id);
885
886         {
887                 const uint8_t *inhdr =
888                         (const uint8_t *)req->in.vector[1].iov_base;
889                 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
890                         "going async\n",
891                         smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
892                         (unsigned long long)async_id ));
893         }
894         return NT_STATUS_OK;
895 }
896
897 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
898 {
899         struct smbd_server_connection *sconn = req->sconn;
900         struct smbd_smb2_request *cur;
901         const uint8_t *inhdr;
902         int i = req->current_idx;
903         uint32_t flags;
904         uint64_t search_message_id;
905         uint64_t search_async_id;
906         uint64_t found_id;
907
908         inhdr = (const uint8_t *)req->in.vector[i].iov_base;
909
910         flags = IVAL(inhdr, SMB2_HDR_FLAGS);
911         search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
912         search_async_id = BVAL(inhdr, SMB2_HDR_PID);
913
914         /*
915          * we don't need the request anymore
916          * cancel requests never have a response
917          */
918         TALLOC_FREE(req);
919
920         for (cur = sconn->smb2.requests; cur; cur = cur->next) {
921                 const uint8_t *outhdr;
922                 uint64_t message_id;
923                 uint64_t async_id;
924
925                 i = cur->current_idx;
926
927                 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
928
929                 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
930                 async_id = BVAL(outhdr, SMB2_HDR_PID);
931
932                 if (flags & SMB2_HDR_FLAG_ASYNC) {
933                         if (search_async_id == async_id) {
934                                 found_id = async_id;
935                                 break;
936                         }
937                 } else {
938                         if (search_message_id == message_id) {
939                                 found_id = message_id;
940                                 break;
941                         }
942                 }
943         }
944
945         if (cur && cur->subreq) {
946                 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
947                 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
948                         "cancel opcode[%s] mid %llu\n",
949                         smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
950                         (unsigned long long)found_id ));
951                 tevent_req_cancel(cur->subreq);
952         }
953
954         return NT_STATUS_OK;
955 }
956
957 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
958 {
959         const uint8_t *inhdr;
960         int i = req->current_idx;
961         uint16_t opcode;
962         uint32_t flags;
963         uint64_t mid;
964         NTSTATUS status;
965         NTSTATUS session_status;
966         uint32_t allowed_flags;
967
968         inhdr = (const uint8_t *)req->in.vector[i].iov_base;
969
970         /* TODO: verify more things */
971
972         flags = IVAL(inhdr, SMB2_HDR_FLAGS);
973         opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
974         mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
975         DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
976                 smb2_opcode_name(opcode),
977                 (unsigned long long)mid));
978
979         allowed_flags = SMB2_HDR_FLAG_CHAINED |
980                         SMB2_HDR_FLAG_SIGNED |
981                         SMB2_HDR_FLAG_DFS;
982         if (opcode == SMB2_OP_CANCEL) {
983                 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
984         }
985         if ((flags & ~allowed_flags) != 0) {
986                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
987         }
988
989         session_status = smbd_smb2_request_check_session(req);
990
991         req->do_signing = false;
992         if (flags & SMB2_HDR_FLAG_SIGNED) {
993                 if (!NT_STATUS_IS_OK(session_status)) {
994                         return smbd_smb2_request_error(req, session_status);
995                 }
996
997                 req->do_signing = true;
998                 status = smb2_signing_check_pdu(req->session->session_key,
999                                                 &req->in.vector[i], 3);
1000                 if (!NT_STATUS_IS_OK(status)) {
1001                         return smbd_smb2_request_error(req, status);
1002                 }
1003         } else if (req->session && req->session->do_signing) {
1004                 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1005         }
1006
1007         if (flags & SMB2_HDR_FLAG_CHAINED) {
1008                 /*
1009                  * This check is mostly for giving the correct error code
1010                  * for compounded requests.
1011                  *
1012                  * TODO: we may need to move this after the session
1013                  *       and tcon checks.
1014                  */
1015                 if (!NT_STATUS_IS_OK(req->next_status)) {
1016                         return smbd_smb2_request_error(req, req->next_status);
1017                 }
1018         } else {
1019                 req->compat_chain_fsp = NULL;
1020         }
1021
1022         switch (opcode) {
1023         case SMB2_OP_NEGPROT:
1024                 return smbd_smb2_request_process_negprot(req);
1025
1026         case SMB2_OP_SESSSETUP:
1027                 return smbd_smb2_request_process_sesssetup(req);
1028
1029         case SMB2_OP_LOGOFF:
1030                 if (!NT_STATUS_IS_OK(session_status)) {
1031                         return smbd_smb2_request_error(req, session_status);
1032                 }
1033                 return smbd_smb2_request_process_logoff(req);
1034
1035         case SMB2_OP_TCON:
1036                 if (!NT_STATUS_IS_OK(session_status)) {
1037                         return smbd_smb2_request_error(req, session_status);
1038                 }
1039                 status = smbd_smb2_request_check_session(req);
1040                 if (!NT_STATUS_IS_OK(status)) {
1041                         return smbd_smb2_request_error(req, status);
1042                 }
1043                 return smbd_smb2_request_process_tcon(req);
1044
1045         case SMB2_OP_TDIS:
1046                 if (!NT_STATUS_IS_OK(session_status)) {
1047                         return smbd_smb2_request_error(req, session_status);
1048                 }
1049                 status = smbd_smb2_request_check_tcon(req);
1050                 if (!NT_STATUS_IS_OK(status)) {
1051                         return smbd_smb2_request_error(req, status);
1052                 }
1053                 return smbd_smb2_request_process_tdis(req);
1054
1055         case SMB2_OP_CREATE:
1056                 if (!NT_STATUS_IS_OK(session_status)) {
1057                         return smbd_smb2_request_error(req, session_status);
1058                 }
1059                 status = smbd_smb2_request_check_tcon(req);
1060                 if (!NT_STATUS_IS_OK(status)) {
1061                         return smbd_smb2_request_error(req, status);
1062                 }
1063                 return smbd_smb2_request_process_create(req);
1064
1065         case SMB2_OP_CLOSE:
1066                 if (!NT_STATUS_IS_OK(session_status)) {
1067                         return smbd_smb2_request_error(req, session_status);
1068                 }
1069                 status = smbd_smb2_request_check_tcon(req);
1070                 if (!NT_STATUS_IS_OK(status)) {
1071                         return smbd_smb2_request_error(req, status);
1072                 }
1073                 return smbd_smb2_request_process_close(req);
1074
1075         case SMB2_OP_FLUSH:
1076                 if (!NT_STATUS_IS_OK(session_status)) {
1077                         return smbd_smb2_request_error(req, session_status);
1078                 }
1079                 status = smbd_smb2_request_check_tcon(req);
1080                 if (!NT_STATUS_IS_OK(status)) {
1081                         return smbd_smb2_request_error(req, status);
1082                 }
1083                 return smbd_smb2_request_process_flush(req);
1084
1085         case SMB2_OP_READ:
1086                 if (!NT_STATUS_IS_OK(session_status)) {
1087                         return smbd_smb2_request_error(req, session_status);
1088                 }
1089                 status = smbd_smb2_request_check_tcon(req);
1090                 if (!NT_STATUS_IS_OK(status)) {
1091                         return smbd_smb2_request_error(req, status);
1092                 }
1093                 return smbd_smb2_request_process_read(req);
1094
1095         case SMB2_OP_WRITE:
1096                 if (!NT_STATUS_IS_OK(session_status)) {
1097                         return smbd_smb2_request_error(req, session_status);
1098                 }
1099                 status = smbd_smb2_request_check_tcon(req);
1100                 if (!NT_STATUS_IS_OK(status)) {
1101                         return smbd_smb2_request_error(req, status);
1102                 }
1103                 return smbd_smb2_request_process_write(req);
1104
1105         case SMB2_OP_LOCK:
1106                 if (!NT_STATUS_IS_OK(session_status)) {
1107                         /* Too ugly to live ? JRA. */
1108                         if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1109                                 session_status = NT_STATUS_FILE_CLOSED;
1110                         }
1111                         return smbd_smb2_request_error(req, session_status);
1112                 }
1113                 status = smbd_smb2_request_check_tcon(req);
1114                 if (!NT_STATUS_IS_OK(status)) {
1115                         /* Too ugly to live ? JRA. */
1116                         if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1117                                 status = NT_STATUS_FILE_CLOSED;
1118                         }
1119                         return smbd_smb2_request_error(req, status);
1120                 }
1121                 return smbd_smb2_request_process_lock(req);
1122
1123         case SMB2_OP_IOCTL:
1124                 if (!NT_STATUS_IS_OK(session_status)) {
1125                         return smbd_smb2_request_error(req, session_status);
1126                 }
1127                 status = smbd_smb2_request_check_tcon(req);
1128                 if (!NT_STATUS_IS_OK(status)) {
1129                         return smbd_smb2_request_error(req, status);
1130                 }
1131                 return smbd_smb2_request_process_ioctl(req);
1132
1133         case SMB2_OP_CANCEL:
1134                 return smbd_smb2_request_process_cancel(req);
1135
1136         case SMB2_OP_KEEPALIVE:
1137                 return smbd_smb2_request_process_keepalive(req);
1138
1139         case SMB2_OP_FIND:
1140                 if (!NT_STATUS_IS_OK(session_status)) {
1141                         return smbd_smb2_request_error(req, session_status);
1142                 }
1143                 status = smbd_smb2_request_check_tcon(req);
1144                 if (!NT_STATUS_IS_OK(status)) {
1145                         return smbd_smb2_request_error(req, status);
1146                 }
1147                 return smbd_smb2_request_process_find(req);
1148
1149         case SMB2_OP_NOTIFY:
1150                 if (!NT_STATUS_IS_OK(session_status)) {
1151                         return smbd_smb2_request_error(req, session_status);
1152                 }
1153                 status = smbd_smb2_request_check_tcon(req);
1154                 if (!NT_STATUS_IS_OK(status)) {
1155                         return smbd_smb2_request_error(req, status);
1156                 }
1157                 return smbd_smb2_request_process_notify(req);
1158
1159         case SMB2_OP_GETINFO:
1160                 if (!NT_STATUS_IS_OK(session_status)) {
1161                         return smbd_smb2_request_error(req, session_status);
1162                 }
1163                 status = smbd_smb2_request_check_tcon(req);
1164                 if (!NT_STATUS_IS_OK(status)) {
1165                         return smbd_smb2_request_error(req, status);
1166                 }
1167                 return smbd_smb2_request_process_getinfo(req);
1168
1169         case SMB2_OP_SETINFO:
1170                 if (!NT_STATUS_IS_OK(session_status)) {
1171                         return smbd_smb2_request_error(req, session_status);
1172                 }
1173                 status = smbd_smb2_request_check_tcon(req);
1174                 if (!NT_STATUS_IS_OK(status)) {
1175                         return smbd_smb2_request_error(req, status);
1176                 }
1177                 return smbd_smb2_request_process_setinfo(req);
1178
1179         case SMB2_OP_BREAK:
1180                 if (!NT_STATUS_IS_OK(session_status)) {
1181                         return smbd_smb2_request_error(req, session_status);
1182                 }
1183                 status = smbd_smb2_request_check_tcon(req);
1184                 if (!NT_STATUS_IS_OK(status)) {
1185                         return smbd_smb2_request_error(req, status);
1186                 }
1187                 return smbd_smb2_request_process_break(req);
1188         }
1189
1190         return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1191 }
1192
1193 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1194 {
1195         struct tevent_req *subreq;
1196
1197         req->subreq = NULL;
1198
1199         smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1200
1201         if (req->do_signing) {
1202                 int i = req->current_idx;
1203                 NTSTATUS status;
1204                 status = smb2_signing_sign_pdu(req->session->session_key,
1205                                                &req->out.vector[i], 3);
1206                 if (!NT_STATUS_IS_OK(status)) {
1207                         return status;
1208                 }
1209         }
1210
1211         req->current_idx += 3;
1212
1213         if (req->current_idx < req->out.vector_count) {
1214                 /*
1215                  * We must process the remaining compound
1216                  * SMB2 requests before any new incoming SMB2
1217                  * requests. This is because incoming SMB2
1218                  * requests may include a cancel for a
1219                  * compound request we haven't processed
1220                  * yet.
1221                  */
1222                 struct tevent_immediate *im = tevent_create_immediate(req);
1223                 if (!im) {
1224                         return NT_STATUS_NO_MEMORY;
1225                 }
1226                 tevent_schedule_immediate(im,
1227                                         req->sconn->smb2.event_ctx,
1228                                         smbd_smb2_request_dispatch_immediate,
1229                                         req);
1230                 return NT_STATUS_OK;
1231         }
1232
1233         if (DEBUGLEVEL >= 10) {
1234                 dbgtext("smbd_smb2_request_reply: sending...\n");
1235                 print_req_vectors(req);
1236         }
1237
1238         subreq = tstream_writev_queue_send(req,
1239                                            req->sconn->smb2.event_ctx,
1240                                            req->sconn->smb2.stream,
1241                                            req->sconn->smb2.send_queue,
1242                                            req->out.vector,
1243                                            req->out.vector_count);
1244         if (subreq == NULL) {
1245                 return NT_STATUS_NO_MEMORY;
1246         }
1247         tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1248
1249         return NT_STATUS_OK;
1250 }
1251
1252 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1253                                         struct tevent_immediate *im,
1254                                         void *private_data)
1255 {
1256         struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1257                                         struct smbd_smb2_request);
1258         struct smbd_server_connection *sconn = req->sconn;
1259         NTSTATUS status;
1260
1261         TALLOC_FREE(im);
1262
1263         if (DEBUGLEVEL >= 10) {
1264                 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1265                         req->current_idx, req->in.vector_count));
1266                 print_req_vectors(req);
1267         }
1268
1269         status = smbd_smb2_request_dispatch(req);
1270         if (!NT_STATUS_IS_OK(status)) {
1271                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1272                 return;
1273         }
1274 }
1275
1276 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1277 {
1278         struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1279                                         struct smbd_smb2_request);
1280         struct smbd_server_connection *sconn = req->sconn;
1281         int ret;
1282         int sys_errno;
1283
1284         ret = tstream_writev_queue_recv(subreq, &sys_errno);
1285         TALLOC_FREE(subreq);
1286         TALLOC_FREE(req);
1287         if (ret == -1) {
1288                 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1289                 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1290                         nt_errstr(status)));
1291                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1292                 return;
1293         }
1294 }
1295
1296 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1297                                    NTSTATUS status,
1298                                    DATA_BLOB body, DATA_BLOB *dyn,
1299                                    const char *location)
1300 {
1301         uint8_t *outhdr;
1302         int i = req->current_idx;
1303         uint32_t next_command_ofs;
1304
1305         DEBUG(10,("smbd_smb2_request_done_ex: "
1306                   "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1307                   i, nt_errstr(status), (unsigned int)body.length,
1308                   dyn ? "yes": "no",
1309                   (unsigned int)(dyn ? dyn->length : 0),
1310                   location));
1311
1312         if (body.length < 2) {
1313                 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1314         }
1315
1316         if ((body.length % 2) != 0) {
1317                 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1318         }
1319
1320         outhdr = (uint8_t *)req->out.vector[i].iov_base;
1321
1322         next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1323         SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1324
1325         req->out.vector[i+1].iov_base = (void *)body.data;
1326         req->out.vector[i+1].iov_len = body.length;
1327
1328         if (dyn) {
1329                 req->out.vector[i+2].iov_base   = (void *)dyn->data;
1330                 req->out.vector[i+2].iov_len    = dyn->length;
1331         } else {
1332                 req->out.vector[i+2].iov_base = NULL;
1333                 req->out.vector[i+2].iov_len = 0;
1334         }
1335
1336         /* see if we need to recalculate the offset to the next response */
1337         if (next_command_ofs > 0) {
1338                 next_command_ofs  = SMB2_HDR_BODY;
1339                 next_command_ofs += req->out.vector[i+1].iov_len;
1340                 next_command_ofs += req->out.vector[i+2].iov_len;
1341         }
1342
1343         if ((next_command_ofs % 8) != 0) {
1344                 size_t pad_size = 8 - (next_command_ofs % 8);
1345                 if (req->out.vector[i+2].iov_len == 0) {
1346                         /*
1347                          * if the dyn buffer is empty
1348                          * we can use it to add padding
1349                          */
1350                         uint8_t *pad;
1351
1352                         pad = talloc_zero_array(req->out.vector,
1353                                                 uint8_t, pad_size);
1354                         if (pad == NULL) {
1355                                 return smbd_smb2_request_error(req,
1356                                                 NT_STATUS_NO_MEMORY);
1357                         }
1358
1359                         req->out.vector[i+2].iov_base = (void *)pad;
1360                         req->out.vector[i+2].iov_len = pad_size;
1361                 } else {
1362                         /*
1363                          * For now we copy the dynamic buffer
1364                          * and add the padding to the new buffer
1365                          */
1366                         size_t old_size;
1367                         uint8_t *old_dyn;
1368                         size_t new_size;
1369                         uint8_t *new_dyn;
1370
1371                         old_size = req->out.vector[i+2].iov_len;
1372                         old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
1373
1374                         new_size = old_size + pad_size;
1375                         new_dyn = talloc_zero_array(req->out.vector,
1376                                                uint8_t, new_size);
1377                         if (new_dyn == NULL) {
1378                                 return smbd_smb2_request_error(req,
1379                                                 NT_STATUS_NO_MEMORY);
1380                         }
1381
1382                         memcpy(new_dyn, old_dyn, old_size);
1383                         memset(new_dyn + old_size, 0, pad_size);
1384
1385                         req->out.vector[i+2].iov_base = (void *)new_dyn;
1386                         req->out.vector[i+2].iov_len = new_size;
1387                 }
1388                 next_command_ofs += pad_size;
1389         }
1390
1391         SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1392
1393         return smbd_smb2_request_reply(req);
1394 }
1395
1396 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
1397                                     NTSTATUS status,
1398                                     DATA_BLOB *info,
1399                                     const char *location)
1400 {
1401         DATA_BLOB body;
1402         int i = req->current_idx;
1403         uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
1404
1405         DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1406                   i, nt_errstr(status), info ? " +info" : "",
1407                   location));
1408
1409         body.data = outhdr + SMB2_HDR_BODY;
1410         body.length = 8;
1411         SSVAL(body.data, 0, 9);
1412
1413         if (info) {
1414                 SIVAL(body.data, 0x04, info->length);
1415         } else {
1416                 /* Allocated size of req->out.vector[i].iov_base
1417                  * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
1418                  * 1 byte without having to do an alloc.
1419                  */
1420                 info = talloc_zero_array(req->out.vector,
1421                                         DATA_BLOB,
1422                                         1);
1423                 if (!info) {
1424                         return NT_STATUS_NO_MEMORY;
1425                 }
1426                 info->data = ((uint8_t *)outhdr) +
1427                         OUTVEC_ALLOC_SIZE - 1;
1428                 info->length = 1;
1429                 SCVAL(info->data, 0, 0);
1430         }
1431
1432         /*
1433          * if a request fails, all other remaining
1434          * compounded requests should fail too
1435          */
1436         req->next_status = NT_STATUS_INVALID_PARAMETER;
1437
1438         return smbd_smb2_request_done_ex(req, status, body, info, __location__);
1439 }
1440
1441
1442 struct smbd_smb2_send_oplock_break_state {
1443         struct smbd_server_connection *sconn;
1444         uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
1445         struct iovec vector;
1446 };
1447
1448 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
1449
1450 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
1451                                      uint64_t file_id_volatile,
1452                                      uint8_t oplock_level)
1453 {
1454         struct smbd_smb2_send_oplock_break_state *state;
1455         struct tevent_req *subreq;
1456         uint8_t *hdr;
1457         uint8_t *body;
1458
1459         state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
1460         if (state == NULL) {
1461                 return NT_STATUS_NO_MEMORY;
1462         }
1463         state->sconn = sconn;
1464
1465         state->vector.iov_base = (void *)state->buf;
1466         state->vector.iov_len = sizeof(state->buf);
1467
1468         _smb2_setlen(state->buf, sizeof(state->buf) - 4);
1469         hdr = state->buf + 4;
1470         body = hdr + SMB2_HDR_BODY;
1471
1472         SIVAL(hdr, 0,                           SMB2_MAGIC);
1473         SSVAL(hdr, SMB2_HDR_LENGTH,             SMB2_HDR_BODY);
1474         SSVAL(hdr, SMB2_HDR_EPOCH,              0);
1475         SIVAL(hdr, SMB2_HDR_STATUS,             0);
1476         SSVAL(hdr, SMB2_HDR_OPCODE,             SMB2_OP_BREAK);
1477         SSVAL(hdr, SMB2_HDR_CREDIT,             0);
1478         SIVAL(hdr, SMB2_HDR_FLAGS,              SMB2_HDR_FLAG_REDIRECT);
1479         SIVAL(hdr, SMB2_HDR_NEXT_COMMAND,       0);
1480         SBVAL(hdr, SMB2_HDR_MESSAGE_ID,         UINT64_MAX);
1481         SIVAL(hdr, SMB2_HDR_PID,                0);
1482         SIVAL(hdr, SMB2_HDR_TID,                0);
1483         SBVAL(hdr, SMB2_HDR_SESSION_ID,         0);
1484         memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
1485
1486         SSVAL(body, 0x00, 0x18);
1487
1488         SCVAL(body, 0x02, oplock_level);
1489         SCVAL(body, 0x03, 0);           /* reserved */
1490         SIVAL(body, 0x04, 0);           /* reserved */
1491         SBVAL(body, 0x08, 0);           /* file_id_persistent */
1492         SBVAL(body, 0x10, file_id_volatile);
1493
1494         subreq = tstream_writev_queue_send(state,
1495                                            sconn->smb2.event_ctx,
1496                                            sconn->smb2.stream,
1497                                            sconn->smb2.send_queue,
1498                                            &state->vector, 1);
1499         if (subreq == NULL) {
1500                 return NT_STATUS_NO_MEMORY;
1501         }
1502         tevent_req_set_callback(subreq,
1503                                 smbd_smb2_oplock_break_writev_done,
1504                                 state);
1505
1506         return NT_STATUS_OK;
1507 }
1508
1509 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
1510 {
1511         struct smbd_smb2_send_oplock_break_state *state =
1512                 tevent_req_callback_data(subreq,
1513                 struct smbd_smb2_send_oplock_break_state);
1514         struct smbd_server_connection *sconn = state->sconn;
1515         int ret;
1516         int sys_errno;
1517
1518         ret = tstream_writev_queue_recv(subreq, &sys_errno);
1519         TALLOC_FREE(subreq);
1520         if (ret == -1) {
1521                 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1522                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1523                 return;
1524         }
1525
1526         TALLOC_FREE(state);
1527 }
1528
1529 struct smbd_smb2_request_read_state {
1530         size_t missing;
1531         bool asked_for_header;
1532         struct smbd_smb2_request *smb2_req;
1533 };
1534
1535 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1536                                          void *private_data,
1537                                          TALLOC_CTX *mem_ctx,
1538                                          struct iovec **_vector,
1539                                          size_t *_count);
1540 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
1541
1542 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
1543                                         struct tevent_context *ev,
1544                                         struct smbd_server_connection *sconn)
1545 {
1546         struct tevent_req *req;
1547         struct smbd_smb2_request_read_state *state;
1548         struct tevent_req *subreq;
1549
1550         req = tevent_req_create(mem_ctx, &state,
1551                                 struct smbd_smb2_request_read_state);
1552         if (req == NULL) {
1553                 return NULL;
1554         }
1555         state->missing = 0;
1556         state->asked_for_header = false;
1557
1558         state->smb2_req = smbd_smb2_request_allocate(state);
1559         if (tevent_req_nomem(state->smb2_req, req)) {
1560                 return tevent_req_post(req, ev);
1561         }
1562         state->smb2_req->sconn = sconn;
1563
1564         subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
1565                                               sconn->smb2.recv_queue,
1566                                               smbd_smb2_request_next_vector,
1567                                               state);
1568         if (tevent_req_nomem(subreq, req)) {
1569                 return tevent_req_post(req, ev);
1570         }
1571         tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
1572
1573         return req;
1574 }
1575
1576 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1577                                          void *private_data,
1578                                          TALLOC_CTX *mem_ctx,
1579                                          struct iovec **_vector,
1580                                          size_t *_count)
1581 {
1582         struct smbd_smb2_request_read_state *state =
1583                 talloc_get_type_abort(private_data,
1584                 struct smbd_smb2_request_read_state);
1585         struct smbd_smb2_request *req = state->smb2_req;
1586         struct iovec *vector;
1587         int idx = req->in.vector_count;
1588         size_t len = 0;
1589         uint8_t *buf = NULL;
1590
1591         if (req->in.vector_count == 0) {
1592                 /*
1593                  * first we need to get the NBT header
1594                  */
1595                 req->in.vector = talloc_array(req, struct iovec,
1596                                               req->in.vector_count + 1);
1597                 if (req->in.vector == NULL) {
1598                         return -1;
1599                 }
1600                 req->in.vector_count += 1;
1601
1602                 req->in.vector[idx].iov_base    = (void *)req->in.nbt_hdr;
1603                 req->in.vector[idx].iov_len     = 4;
1604
1605                 vector = talloc_array(mem_ctx, struct iovec, 1);
1606                 if (vector == NULL) {
1607                         return -1;
1608                 }
1609
1610                 vector[0] = req->in.vector[idx];
1611
1612                 *_vector = vector;
1613                 *_count = 1;
1614                 return 0;
1615         }
1616
1617         if (req->in.vector_count == 1) {
1618                 /*
1619                  * Now we analyze the NBT header
1620                  */
1621                 state->missing = smb2_len(req->in.vector[0].iov_base);
1622
1623                 if (state->missing == 0) {
1624                         /* if there're no remaining bytes, we're done */
1625                         *_vector = NULL;
1626                         *_count = 0;
1627                         return 0;
1628                 }
1629
1630                 req->in.vector = talloc_realloc(req, req->in.vector,
1631                                                 struct iovec,
1632                                                 req->in.vector_count + 1);
1633                 if (req->in.vector == NULL) {
1634                         return -1;
1635                 }
1636                 req->in.vector_count += 1;
1637
1638                 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
1639                         /*
1640                          * it's a special NBT message,
1641                          * so get all remaining bytes
1642                          */
1643                         len = state->missing;
1644                 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
1645                         /*
1646                          * it's an invalid message, just read what we can get
1647                          * and let the caller handle the error
1648                          */
1649                         len = state->missing;
1650                 } else {
1651                         /*
1652                          * We assume it's a SMB2 request,
1653                          * and we first get the header and the
1654                          * first 2 bytes (the struct size) of the body
1655                          */
1656                         len = SMB2_HDR_BODY + 2;
1657
1658                         state->asked_for_header = true;
1659                 }
1660
1661                 state->missing -= len;
1662
1663                 buf = talloc_array(req->in.vector, uint8_t, len);
1664                 if (buf == NULL) {
1665                         return -1;
1666                 }
1667
1668                 req->in.vector[idx].iov_base    = (void *)buf;
1669                 req->in.vector[idx].iov_len     = len;
1670
1671                 vector = talloc_array(mem_ctx, struct iovec, 1);
1672                 if (vector == NULL) {
1673                         return -1;
1674                 }
1675
1676                 vector[0] = req->in.vector[idx];
1677
1678                 *_vector = vector;
1679                 *_count = 1;
1680                 return 0;
1681         }
1682
1683         if (state->missing == 0) {
1684                 /* if there're no remaining bytes, we're done */
1685                 *_vector = NULL;
1686                 *_count = 0;
1687                 return 0;
1688         }
1689
1690         if (state->asked_for_header) {
1691                 const uint8_t *hdr;
1692                 size_t full_size;
1693                 size_t next_command_ofs;
1694                 size_t body_size;
1695                 uint8_t *body;
1696                 size_t dyn_size;
1697                 uint8_t *dyn;
1698                 bool invalid = false;
1699
1700                 state->asked_for_header = false;
1701
1702                 /*
1703                  * We got the SMB2 header and the first 2 bytes
1704                  * of the body. We fix the size to just the header
1705                  * and manually copy the 2 first bytes to the body section
1706                  */
1707                 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
1708                 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
1709
1710                 /* allocate vectors for body and dynamic areas */
1711                 req->in.vector = talloc_realloc(req, req->in.vector,
1712                                                 struct iovec,
1713                                                 req->in.vector_count + 2);
1714                 if (req->in.vector == NULL) {
1715                         return -1;
1716                 }
1717                 req->in.vector_count += 2;
1718
1719                 full_size = state->missing + SMB2_HDR_BODY + 2;
1720                 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
1721                 body_size = SVAL(hdr, SMB2_HDR_BODY);
1722
1723                 if (next_command_ofs != 0) {
1724                         if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
1725                                 /*
1726                                  * this is invalid, just return a zero
1727                                  * body and let the caller deal with the error
1728                                  */
1729                                 invalid = true;
1730                         } else if (next_command_ofs > full_size) {
1731                                 /*
1732                                  * this is invalid, just return a zero
1733                                  * body and let the caller deal with the error
1734                                  */
1735                                 invalid = true;
1736                         } else {
1737                                 full_size = next_command_ofs;
1738                         }
1739                 }
1740
1741                 if (!invalid) {
1742                         if (body_size < 2) {
1743                                 /*
1744                                  * this is invalid, just return a zero
1745                                  * body and let the caller deal with the error
1746                                  */
1747                                 invalid = true;
1748                         }
1749
1750                         if ((body_size % 2) != 0) {
1751                                 body_size -= 1;
1752                         }
1753
1754                         if (body_size > (full_size - SMB2_HDR_BODY)) {
1755                                 /*
1756                                  * this is invalid, just return a zero
1757                                  * body and let the caller deal with the error
1758                                  */
1759                                 invalid = true;
1760                         }
1761                 }
1762
1763                 if (invalid) {
1764                         /* the caller should check this */
1765                         body_size = 2;
1766                 }
1767
1768                 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
1769
1770                 state->missing -= (body_size - 2) + dyn_size;
1771
1772                 body = talloc_array(req->in.vector, uint8_t, body_size);
1773                 if (body == NULL) {
1774                         return -1;
1775                 }
1776
1777                 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
1778                 if (dyn == NULL) {
1779                         return -1;
1780                 }
1781
1782                 req->in.vector[idx].iov_base    = (void *)body;
1783                 req->in.vector[idx].iov_len     = body_size;
1784                 req->in.vector[idx+1].iov_base  = (void *)dyn;
1785                 req->in.vector[idx+1].iov_len   = dyn_size;
1786
1787                 vector = talloc_array(mem_ctx, struct iovec, 2);
1788                 if (vector == NULL) {
1789                         return -1;
1790                 }
1791
1792                 /*
1793                  * the first 2 bytes of the body were already fetched
1794                  * together with the header
1795                  */
1796                 memcpy(body, hdr + SMB2_HDR_BODY, 2);
1797                 vector[0].iov_base = body + 2;
1798                 vector[0].iov_len = body_size - 2;
1799
1800                 vector[1] = req->in.vector[idx+1];
1801
1802                 *_vector = vector;
1803                 *_count = 2;
1804                 return 0;
1805         }
1806
1807         /*
1808          * when we endup here, we're looking for a new SMB2 request
1809          * next. And we ask for its header and the first 2 bytes of
1810          * the body (like we did for the first SMB2 request).
1811          */
1812
1813         req->in.vector = talloc_realloc(req, req->in.vector,
1814                                         struct iovec,
1815                                         req->in.vector_count + 1);
1816         if (req->in.vector == NULL) {
1817                 return -1;
1818         }
1819         req->in.vector_count += 1;
1820
1821         /*
1822          * We assume it's a SMB2 request,
1823          * and we first get the header and the
1824          * first 2 bytes (the struct size) of the body
1825          */
1826         len = SMB2_HDR_BODY + 2;
1827
1828         if (len > state->missing) {
1829                 /* let the caller handle the error */
1830                 len = state->missing;
1831         }
1832
1833         state->missing -= len;
1834         state->asked_for_header = true;
1835
1836         buf = talloc_array(req->in.vector, uint8_t, len);
1837         if (buf == NULL) {
1838                 return -1;
1839         }
1840
1841         req->in.vector[idx].iov_base    = (void *)buf;
1842         req->in.vector[idx].iov_len     = len;
1843
1844         vector = talloc_array(mem_ctx, struct iovec, 1);
1845         if (vector == NULL) {
1846                 return -1;
1847         }
1848
1849         vector[0] = req->in.vector[idx];
1850
1851         *_vector = vector;
1852         *_count = 1;
1853         return 0;
1854 }
1855
1856 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
1857 {
1858         struct tevent_req *req =
1859                 tevent_req_callback_data(subreq,
1860                 struct tevent_req);
1861         int ret;
1862         int sys_errno;
1863         NTSTATUS status;
1864
1865         ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
1866         if (ret == -1) {
1867                 status = map_nt_error_from_unix(sys_errno);
1868                 tevent_req_nterror(req, status);
1869                 return;
1870         }
1871
1872         tevent_req_done(req);
1873 }
1874
1875 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
1876                                             TALLOC_CTX *mem_ctx,
1877                                             struct smbd_smb2_request **_smb2_req)
1878 {
1879         struct smbd_smb2_request_read_state *state =
1880                 tevent_req_data(req,
1881                 struct smbd_smb2_request_read_state);
1882         NTSTATUS status;
1883
1884         if (tevent_req_is_nterror(req, &status)) {
1885                 tevent_req_received(req);
1886                 return status;
1887         }
1888
1889         talloc_steal(mem_ctx, state->smb2_req->mem_pool);
1890         *_smb2_req = state->smb2_req;
1891         tevent_req_received(req);
1892         return NT_STATUS_OK;
1893 }
1894
1895 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
1896
1897 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
1898                              const uint8_t *inbuf, size_t size)
1899 {
1900         NTSTATUS status;
1901         struct smbd_smb2_request *req;
1902         struct tevent_req *subreq;
1903
1904         DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
1905                  (unsigned int)size));
1906
1907         status = smbd_initialize_smb2(sconn);
1908         if (!NT_STATUS_IS_OK(status)) {
1909                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1910                 return;
1911         }
1912
1913         status = smbd_smb2_request_create(sconn, inbuf, size, &req);
1914         if (!NT_STATUS_IS_OK(status)) {
1915                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1916                 return;
1917         }
1918
1919         status = smbd_smb2_request_setup_out(req, 1);
1920         if (!NT_STATUS_IS_OK(status)) {
1921                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1922                 return;
1923         }
1924
1925         status = smbd_smb2_request_dispatch(req);
1926         if (!NT_STATUS_IS_OK(status)) {
1927                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1928                 return;
1929         }
1930
1931         /* ask for the next request */
1932         subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
1933         if (subreq == NULL) {
1934                 smbd_server_connection_terminate(sconn, "no memory for reading");
1935                 return;
1936         }
1937         tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
1938 }
1939
1940 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
1941 {
1942         uint16_t creds_requested = 0;
1943         struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
1944                                                struct smbd_server_connection);
1945         NTSTATUS status;
1946         struct smbd_smb2_request *req = NULL;
1947
1948         status = smbd_smb2_request_read_recv(subreq, sconn, &req);
1949         TALLOC_FREE(subreq);
1950         if (!NT_STATUS_IS_OK(status)) {
1951                 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
1952                         nt_errstr(status)));
1953                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1954                 return;
1955         }
1956
1957         if (req->in.nbt_hdr[0] != 0x00) {
1958                 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
1959                          req->in.nbt_hdr[0]));
1960                 TALLOC_FREE(req);
1961                 goto next;
1962         }
1963
1964         req->current_idx = 1;
1965
1966         DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
1967                  req->current_idx, req->in.vector_count));
1968
1969         status = smbd_smb2_request_validate(req, &creds_requested);
1970         if (!NT_STATUS_IS_OK(status)) {
1971                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1972                 return;
1973         }
1974
1975         status = smbd_smb2_request_setup_out(req, 5);
1976         if (!NT_STATUS_IS_OK(status)) {
1977                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1978                 return;
1979         }
1980
1981         status = smbd_smb2_request_dispatch(req);
1982         if (!NT_STATUS_IS_OK(status)) {
1983                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1984                 return;
1985         }
1986
1987 next:
1988         /* ask for the next request (this constructs the main loop) */
1989         subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
1990         if (subreq == NULL) {
1991                 smbd_server_connection_terminate(sconn, "no memory for reading");
1992                 return;
1993         }
1994         tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
1995 }