s3:smb2_server: use req->xconn in smbd_smb2_request_error_ex()
[obnox/samba/samba-obnox.git] / source3 / smbd / smb2_server.c
1 /*
2    Unix SMB/CIFS implementation.
3    Core SMB2 server
4
5    Copyright (C) Stefan Metzmacher 2009
6    Copyright (C) Jeremy Allison 2010
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../libcli/smb/smb_common.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "../lib/util/tevent_ntstatus.h"
28 #include "smbprofile.h"
29 #include "../lib/util/bitmap.h"
30 #include "../librpc/gen_ndr/krb5pac.h"
31 #include "auth.h"
32
33 static void smbd_smb2_connection_handler(struct tevent_context *ev,
34                                          struct tevent_fd *fde,
35                                          uint16_t flags,
36                                          void *private_data);
37 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn);
38
39 static const struct smbd_smb2_dispatch_table {
40         uint16_t opcode;
41         const char *name;
42         bool need_session;
43         bool need_tcon;
44         bool as_root;
45         uint16_t fileid_ofs;
46         bool allow_invalid_fileid;
47 } smbd_smb2_table[] = {
48 #define _OP(o) .opcode = o, .name = #o
49         {
50                 _OP(SMB2_OP_NEGPROT),
51                 .as_root = true,
52         },{
53                 _OP(SMB2_OP_SESSSETUP),
54                 .as_root = true,
55         },{
56                 _OP(SMB2_OP_LOGOFF),
57                 .need_session = true,
58                 .as_root = true,
59         },{
60                 _OP(SMB2_OP_TCON),
61                 .need_session = true,
62                 /*
63                  * This call needs to be run as root.
64                  *
65                  * smbd_smb2_request_process_tcon()
66                  * calls make_connection_snum(), which will call
67                  * change_to_user(), when needed.
68                  */
69                 .as_root = true,
70         },{
71                 _OP(SMB2_OP_TDIS),
72                 .need_session = true,
73                 .need_tcon = true,
74                 .as_root = true,
75         },{
76                 _OP(SMB2_OP_CREATE),
77                 .need_session = true,
78                 .need_tcon = true,
79         },{
80                 _OP(SMB2_OP_CLOSE),
81                 .need_session = true,
82                 .need_tcon = true,
83                 .fileid_ofs = 0x08,
84         },{
85                 _OP(SMB2_OP_FLUSH),
86                 .need_session = true,
87                 .need_tcon = true,
88                 .fileid_ofs = 0x08,
89         },{
90                 _OP(SMB2_OP_READ),
91                 .need_session = true,
92                 .need_tcon = true,
93                 .fileid_ofs = 0x10,
94         },{
95                 _OP(SMB2_OP_WRITE),
96                 .need_session = true,
97                 .need_tcon = true,
98                 .fileid_ofs = 0x10,
99         },{
100                 _OP(SMB2_OP_LOCK),
101                 .need_session = true,
102                 .need_tcon = true,
103                 .fileid_ofs = 0x08,
104         },{
105                 _OP(SMB2_OP_IOCTL),
106                 .need_session = true,
107                 .need_tcon = true,
108                 .fileid_ofs = 0x08,
109                 .allow_invalid_fileid = true,
110         },{
111                 _OP(SMB2_OP_CANCEL),
112                 .as_root = true,
113         },{
114                 _OP(SMB2_OP_KEEPALIVE),
115                 .as_root = true,
116         },{
117                 _OP(SMB2_OP_FIND),
118                 .need_session = true,
119                 .need_tcon = true,
120                 .fileid_ofs = 0x08,
121         },{
122                 _OP(SMB2_OP_NOTIFY),
123                 .need_session = true,
124                 .need_tcon = true,
125                 .fileid_ofs = 0x08,
126         },{
127                 _OP(SMB2_OP_GETINFO),
128                 .need_session = true,
129                 .need_tcon = true,
130                 .fileid_ofs = 0x18,
131         },{
132                 _OP(SMB2_OP_SETINFO),
133                 .need_session = true,
134                 .need_tcon = true,
135                 .fileid_ofs = 0x10,
136         },{
137                 _OP(SMB2_OP_BREAK),
138                 .need_session = true,
139                 .need_tcon = true,
140                 /*
141                  * we do not set
142                  * .fileid_ofs here
143                  * as LEASE breaks does not
144                  * have a file id
145                  */
146         }
147 };
148
149 const char *smb2_opcode_name(uint16_t opcode)
150 {
151         if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
152                 return "Bad SMB2 opcode";
153         }
154         return smbd_smb2_table[opcode].name;
155 }
156
157 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
158 {
159         const struct smbd_smb2_dispatch_table *ret = NULL;
160
161         if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
162                 return NULL;
163         }
164
165         ret = &smbd_smb2_table[opcode];
166
167         SMB_ASSERT(ret->opcode == opcode);
168
169         return ret;
170 }
171
172 static void print_req_vectors(const struct smbd_smb2_request *req)
173 {
174         int i;
175
176         for (i = 0; i < req->in.vector_count; i++) {
177                 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
178                         (unsigned int)i,
179                         (unsigned int)req->in.vector[i].iov_len);
180         }
181         for (i = 0; i < req->out.vector_count; i++) {
182                 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
183                         (unsigned int)i,
184                         (unsigned int)req->out.vector[i].iov_len);
185         }
186 }
187
188 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
189 {
190         if (size < (4 + SMB2_HDR_BODY)) {
191                 return false;
192         }
193
194         if (IVAL(inbuf, 4) != SMB2_MAGIC) {
195                 return false;
196         }
197
198         return true;
199 }
200
201 static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn)
202 {
203         TALLOC_FREE(xconn->transport.fde);
204
205         xconn->smb2.credits.seq_low = 0;
206         xconn->smb2.credits.seq_range = 1;
207         xconn->smb2.credits.granted = 1;
208         xconn->smb2.credits.max = lp_smb2_max_credits();
209         xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
210                                                    xconn->smb2.credits.max);
211         if (xconn->smb2.credits.bitmap == NULL) {
212                 return NT_STATUS_NO_MEMORY;
213         }
214
215         xconn->transport.fde = tevent_add_fd(xconn->ev_ctx,
216                                         xconn,
217                                         xconn->transport.sock,
218                                         TEVENT_FD_READ,
219                                         smbd_smb2_connection_handler,
220                                         xconn);
221         if (xconn->transport.fde == NULL) {
222                 return NT_STATUS_NO_MEMORY;
223         }
224
225         /* Ensure child is set to non-blocking mode */
226         set_blocking(xconn->transport.sock, false);
227         return NT_STATUS_OK;
228 }
229
230 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
231 #define _smb2_setlen(_buf,len) do { \
232         uint8_t *buf = (uint8_t *)_buf; \
233         buf[0] = 0; \
234         buf[1] = ((len)&0xFF0000)>>16; \
235         buf[2] = ((len)&0xFF00)>>8; \
236         buf[3] = (len)&0xFF; \
237 } while (0)
238
239 static void smb2_setup_nbt_length(struct iovec *vector, int count)
240 {
241         size_t len = 0;
242         int i;
243
244         for (i=1; i < count; i++) {
245                 len += vector[i].iov_len;
246         }
247
248         _smb2_setlen(vector[0].iov_base, len);
249 }
250
251 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
252 {
253         if (req->first_key.length > 0) {
254                 data_blob_clear_free(&req->first_key);
255         }
256         if (req->last_key.length > 0) {
257                 data_blob_clear_free(&req->last_key);
258         }
259         return 0;
260 }
261
262 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
263 {
264         TALLOC_CTX *mem_pool;
265         struct smbd_smb2_request *req;
266
267 #if 0
268         /* Enable this to find subtle valgrind errors. */
269         mem_pool = talloc_init("smbd_smb2_request_allocate");
270 #else
271         mem_pool = talloc_tos();
272 #endif
273         if (mem_pool == NULL) {
274                 return NULL;
275         }
276
277         req = talloc_zero(mem_pool, struct smbd_smb2_request);
278         if (req == NULL) {
279                 talloc_free(mem_pool);
280                 return NULL;
281         }
282         talloc_reparent(mem_pool, mem_ctx, req);
283 #if 0
284         TALLOC_FREE(mem_pool);
285 #endif
286
287         req->last_session_id = UINT64_MAX;
288         req->last_tid = UINT32_MAX;
289
290         talloc_set_destructor(req, smbd_smb2_request_destructor);
291
292         return req;
293 }
294
295 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
296                                                NTTIME now,
297                                                uint8_t *buf,
298                                                size_t buflen,
299                                                struct smbd_smb2_request *req,
300                                                struct iovec **piov,
301                                                int *pnum_iov)
302 {
303         TALLOC_CTX *mem_ctx = req;
304         struct iovec *iov;
305         int num_iov = 1;
306         size_t taken = 0;
307         uint8_t *first_hdr = buf;
308         size_t verified_buflen = 0;
309         uint8_t *tf = NULL;
310         size_t tf_len = 0;
311
312         /*
313          * Note: index '0' is reserved for the transport protocol
314          */
315         iov = req->in._vector;
316
317         while (taken < buflen) {
318                 size_t len = buflen - taken;
319                 uint8_t *hdr = first_hdr + taken;
320                 struct iovec *cur;
321                 size_t full_size;
322                 size_t next_command_ofs;
323                 uint16_t body_size;
324                 uint8_t *body = NULL;
325                 uint32_t dyn_size;
326                 uint8_t *dyn = NULL;
327                 struct iovec *iov_alloc = NULL;
328
329                 if (iov != req->in._vector) {
330                         iov_alloc = iov;
331                 }
332
333                 if (verified_buflen > taken) {
334                         len = verified_buflen - taken;
335                 } else {
336                         tf = NULL;
337                         tf_len = 0;
338                 }
339
340                 if (len < 4) {
341                         DEBUG(10, ("%d bytes left, expected at least %d\n",
342                                    (int)len, 4));
343                         goto inval;
344                 }
345                 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
346                         struct smbXsrv_session *s = NULL;
347                         uint64_t uid;
348                         struct iovec tf_iov[2];
349                         NTSTATUS status;
350                         size_t enc_len;
351
352                         if (xconn->protocol < PROTOCOL_SMB2_24) {
353                                 DEBUG(10, ("Got SMB2_TRANSFORM header, "
354                                            "but dialect[0x%04X] is used\n",
355                                            xconn->smb2.server.dialect));
356                                 goto inval;
357                         }
358
359                         if (!(xconn->smb2.server.capabilities & SMB2_CAP_ENCRYPTION)) {
360                                 DEBUG(10, ("Got SMB2_TRANSFORM header, "
361                                            "but not negotiated "
362                                            "client[0x%08X] server[0x%08X]\n",
363                                            xconn->smb2.client.capabilities,
364                                            xconn->smb2.server.capabilities));
365                                 goto inval;
366                         }
367
368                         if (len < SMB2_TF_HDR_SIZE) {
369                                 DEBUG(1, ("%d bytes left, expected at least %d\n",
370                                            (int)len, SMB2_TF_HDR_SIZE));
371                                 goto inval;
372                         }
373                         tf = hdr;
374                         tf_len = SMB2_TF_HDR_SIZE;
375                         taken += tf_len;
376
377                         hdr = first_hdr + taken;
378                         enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
379                         uid = BVAL(tf, SMB2_TF_SESSION_ID);
380
381                         if (len < SMB2_TF_HDR_SIZE + enc_len) {
382                                 DEBUG(1, ("%d bytes left, expected at least %d\n",
383                                            (int)len,
384                                            (int)(SMB2_TF_HDR_SIZE + enc_len)));
385                                 goto inval;
386                         }
387
388                         status = smb2srv_session_lookup(xconn, uid, now, &s);
389                         if (s == NULL) {
390                                 DEBUG(1, ("invalid session[%llu] in "
391                                           "SMB2_TRANSFORM header\n",
392                                            (unsigned long long)uid));
393                                 TALLOC_FREE(iov_alloc);
394                                 return NT_STATUS_USER_SESSION_DELETED;
395                         }
396
397                         tf_iov[0].iov_base = (void *)tf;
398                         tf_iov[0].iov_len = tf_len;
399                         tf_iov[1].iov_base = (void *)hdr;
400                         tf_iov[1].iov_len = enc_len;
401
402                         status = smb2_signing_decrypt_pdu(s->global->decryption_key,
403                                                           xconn->protocol,
404                                                           tf_iov, 2);
405                         if (!NT_STATUS_IS_OK(status)) {
406                                 TALLOC_FREE(iov_alloc);
407                                 return status;
408                         }
409
410                         verified_buflen = taken + enc_len;
411                         len = enc_len;
412                 }
413
414                 /*
415                  * We need the header plus the body length field
416                  */
417
418                 if (len < SMB2_HDR_BODY + 2) {
419                         DEBUG(10, ("%d bytes left, expected at least %d\n",
420                                    (int)len, SMB2_HDR_BODY));
421                         goto inval;
422                 }
423                 if (IVAL(hdr, 0) != SMB2_MAGIC) {
424                         DEBUG(10, ("Got non-SMB2 PDU: %x\n",
425                                    IVAL(hdr, 0)));
426                         goto inval;
427                 }
428                 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
429                         DEBUG(10, ("Got HDR len %d, expected %d\n",
430                                    SVAL(hdr, 4), SMB2_HDR_BODY));
431                         goto inval;
432                 }
433
434                 full_size = len;
435                 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
436                 body_size = SVAL(hdr, SMB2_HDR_BODY);
437
438                 if (next_command_ofs != 0) {
439                         if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
440                                 goto inval;
441                         }
442                         if (next_command_ofs > full_size) {
443                                 goto inval;
444                         }
445                         full_size = next_command_ofs;
446                 }
447                 if (body_size < 2) {
448                         goto inval;
449                 }
450                 body_size &= 0xfffe;
451
452                 if (body_size > (full_size - SMB2_HDR_BODY)) {
453                         /*
454                          * let the caller handle the error
455                          */
456                         body_size = full_size - SMB2_HDR_BODY;
457                 }
458                 body = hdr + SMB2_HDR_BODY;
459                 dyn = body + body_size;
460                 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
461
462                 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
463                         struct iovec *iov_tmp = NULL;
464
465                         iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
466                                                  struct iovec,
467                                                  num_iov +
468                                                  SMBD_SMB2_NUM_IOV_PER_REQ);
469                         if (iov_tmp == NULL) {
470                                 TALLOC_FREE(iov_alloc);
471                                 return NT_STATUS_NO_MEMORY;
472                         }
473
474                         if (iov_alloc == NULL) {
475                                 memcpy(iov_tmp,
476                                        req->in._vector,
477                                        sizeof(req->in._vector));
478                         }
479
480                         iov = iov_tmp;
481                 }
482                 cur = &iov[num_iov];
483                 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
484
485                 cur[SMBD_SMB2_TF_IOV_OFS].iov_base   = tf;
486                 cur[SMBD_SMB2_TF_IOV_OFS].iov_len    = tf_len;
487                 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base  = hdr;
488                 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len   = SMB2_HDR_BODY;
489                 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
490                 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len  = body_size;
491                 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base  = dyn;
492                 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len   = dyn_size;
493
494                 taken += full_size;
495         }
496
497         *piov = iov;
498         *pnum_iov = num_iov;
499         return NT_STATUS_OK;
500
501 inval:
502         if (iov != req->in._vector) {
503                 TALLOC_FREE(iov);
504         }
505         return NT_STATUS_INVALID_PARAMETER;
506 }
507
508 static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
509                                          uint8_t *inbuf, size_t size,
510                                          struct smbd_smb2_request **_req)
511 {
512         struct smbd_server_connection *sconn = xconn->sconn;
513         struct smbd_smb2_request *req;
514         uint32_t protocol_version;
515         const uint8_t *inhdr = NULL;
516         uint16_t cmd;
517         uint32_t next_command_ofs;
518         NTSTATUS status;
519         NTTIME now;
520
521         if (size < (4 + SMB2_HDR_BODY + 2)) {
522                 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
523                 return NT_STATUS_INVALID_PARAMETER;
524         }
525
526         inhdr = inbuf + 4;
527
528         protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
529         if (protocol_version != SMB2_MAGIC) {
530                 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
531                          protocol_version));
532                 return NT_STATUS_INVALID_PARAMETER;
533         }
534
535         cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
536         if (cmd != SMB2_OP_NEGPROT) {
537                 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
538                          cmd));
539                 return NT_STATUS_INVALID_PARAMETER;
540         }
541
542         next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
543         if (next_command_ofs != 0) {
544                 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
545                          next_command_ofs));
546                 return NT_STATUS_INVALID_PARAMETER;
547         }
548
549         req = smbd_smb2_request_allocate(xconn);
550         if (req == NULL) {
551                 return NT_STATUS_NO_MEMORY;
552         }
553         req->sconn = sconn;
554         req->xconn = xconn;
555
556         talloc_steal(req, inbuf);
557
558         req->request_time = timeval_current();
559         now = timeval_to_nttime(&req->request_time);
560
561         status = smbd_smb2_inbuf_parse_compound(xconn,
562                                                 now,
563                                                 inbuf + NBT_HDR_SIZE,
564                                                 size - NBT_HDR_SIZE,
565                                                 req, &req->in.vector,
566                                                 &req->in.vector_count);
567         if (!NT_STATUS_IS_OK(status)) {
568                 TALLOC_FREE(req);
569                 return status;
570         }
571
572         req->current_idx = 1;
573
574         *_req = req;
575         return NT_STATUS_OK;
576 }
577
578 static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
579                                           uint64_t message_id, uint64_t seq_id)
580 {
581         struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
582         unsigned int offset;
583         uint64_t seq_tmp;
584
585         seq_tmp = xconn->smb2.credits.seq_low;
586         if (seq_id < seq_tmp) {
587                 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
588                         "%llu (sequence id %llu) "
589                         "(granted = %u, low = %llu, range = %u)\n",
590                         (unsigned long long)message_id,
591                         (unsigned long long)seq_id,
592                         (unsigned int)xconn->smb2.credits.granted,
593                         (unsigned long long)xconn->smb2.credits.seq_low,
594                         (unsigned int)xconn->smb2.credits.seq_range));
595                 return false;
596         }
597
598         seq_tmp += xconn->smb2.credits.seq_range;
599         if (seq_id >= seq_tmp) {
600                 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
601                         "%llu (sequence id %llu) "
602                         "(granted = %u, low = %llu, range = %u)\n",
603                         (unsigned long long)message_id,
604                         (unsigned long long)seq_id,
605                         (unsigned int)xconn->smb2.credits.granted,
606                         (unsigned long long)xconn->smb2.credits.seq_low,
607                         (unsigned int)xconn->smb2.credits.seq_range));
608                 return false;
609         }
610
611         offset = seq_id % xconn->smb2.credits.max;
612
613         if (bitmap_query(credits_bm, offset)) {
614                 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
615                         "%llu (sequence id %llu) "
616                         "(granted = %u, low = %llu, range = %u) "
617                         "(bm offset %u)\n",
618                         (unsigned long long)message_id,
619                         (unsigned long long)seq_id,
620                         (unsigned int)xconn->smb2.credits.granted,
621                         (unsigned long long)xconn->smb2.credits.seq_low,
622                         (unsigned int)xconn->smb2.credits.seq_range,
623                         offset));
624                 return false;
625         }
626
627         /* Mark the message_ids as seen in the bitmap. */
628         bitmap_set(credits_bm, offset);
629
630         if (seq_id != xconn->smb2.credits.seq_low) {
631                 return true;
632         }
633
634         /*
635          * Move the window forward by all the message_id's
636          * already seen.
637          */
638         while (bitmap_query(credits_bm, offset)) {
639                 DEBUG(10,("smb2_validate_sequence_number: clearing "
640                           "id %llu (position %u) from bitmap\n",
641                           (unsigned long long)(xconn->smb2.credits.seq_low),
642                           offset));
643                 bitmap_clear(credits_bm, offset);
644
645                 xconn->smb2.credits.seq_low += 1;
646                 xconn->smb2.credits.seq_range -= 1;
647                 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
648         }
649
650         return true;
651 }
652
653 static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
654                                      const uint8_t *inhdr)
655 {
656         uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
657         uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
658         uint16_t credit_charge = 1;
659         uint64_t i;
660
661         if (opcode == SMB2_OP_CANCEL) {
662                 /* SMB2_CANCEL requests by definition resend messageids. */
663                 return true;
664         }
665
666         if (xconn->smb2.credits.multicredit) {
667                 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
668                 credit_charge = MAX(credit_charge, 1);
669         }
670
671         DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
672                    "credits_granted %llu, "
673                    "seqnum low/range: %llu/%llu\n",
674                    (unsigned long long) message_id,
675                    (unsigned long long) credit_charge,
676                    (unsigned long long) xconn->smb2.credits.granted,
677                    (unsigned long long) xconn->smb2.credits.seq_low,
678                    (unsigned long long) xconn->smb2.credits.seq_range));
679
680         if (xconn->smb2.credits.granted < credit_charge) {
681                 DEBUG(0, ("smb2_validate_message_id: client used more "
682                           "credits than granted, mid %llu, charge %llu, "
683                           "credits_granted %llu, "
684                           "seqnum low/range: %llu/%llu\n",
685                           (unsigned long long) message_id,
686                           (unsigned long long) credit_charge,
687                           (unsigned long long) xconn->smb2.credits.granted,
688                           (unsigned long long) xconn->smb2.credits.seq_low,
689                           (unsigned long long) xconn->smb2.credits.seq_range));
690                 return false;
691         }
692
693         /*
694          * now check the message ids
695          *
696          * for multi-credit requests we need to check all current mid plus
697          * the implicit mids caused by the credit charge
698          * e.g. current mid = 15, charge 5 => mark 15-19 as used
699          */
700
701         for (i = 0; i <= (credit_charge-1); i++) {
702                 uint64_t id = message_id + i;
703                 bool ok;
704
705                 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
706                            (unsigned long long)message_id,
707                            credit_charge,
708                            (unsigned long long)id));
709
710                 ok = smb2_validate_sequence_number(xconn, message_id, id);
711                 if (!ok) {
712                         return false;
713                 }
714         }
715
716         /* substract used credits */
717         xconn->smb2.credits.granted -= credit_charge;
718
719         return true;
720 }
721
722 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
723 {
724         int count;
725         int idx;
726
727         count = req->in.vector_count;
728
729         if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
730                 /* It's not a SMB2 request */
731                 return NT_STATUS_INVALID_PARAMETER;
732         }
733
734         for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
735                 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
736                 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
737                 const uint8_t *inhdr = NULL;
738
739                 if (hdr->iov_len != SMB2_HDR_BODY) {
740                         return NT_STATUS_INVALID_PARAMETER;
741                 }
742
743                 if (body->iov_len < 2) {
744                         return NT_STATUS_INVALID_PARAMETER;
745                 }
746
747                 inhdr = (const uint8_t *)hdr->iov_base;
748
749                 /* Check the SMB2 header */
750                 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
751                         return NT_STATUS_INVALID_PARAMETER;
752                 }
753
754                 if (!smb2_validate_message_id(req->xconn, inhdr)) {
755                         return NT_STATUS_INVALID_PARAMETER;
756                 }
757         }
758
759         return NT_STATUS_OK;
760 }
761
762 static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
763                                       const struct iovec *in_vector,
764                                       struct iovec *out_vector)
765 {
766         struct smbd_server_connection *sconn = xconn->sconn;
767         const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
768         uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
769         uint16_t credit_charge = 1;
770         uint16_t credits_requested;
771         uint32_t out_flags;
772         uint16_t cmd;
773         NTSTATUS out_status;
774         uint16_t credits_granted = 0;
775         uint64_t credits_possible;
776         uint16_t current_max_credits;
777
778         /*
779          * first we grant only 1/16th of the max range.
780          *
781          * Windows also starts with the 1/16th and then grants
782          * more later. I was only able to trigger higher
783          * values, when using a very high credit charge.
784          *
785          * TODO: scale up depending on load, free memory
786          *       or other stuff.
787          *       Maybe also on the relationship between number
788          *       of requests and the used sequence number.
789          *       Which means we would grant more credits
790          *       for client which use multi credit requests.
791          */
792         current_max_credits = xconn->smb2.credits.max / 16;
793         current_max_credits = MAX(current_max_credits, 1);
794
795         if (xconn->smb2.credits.multicredit) {
796                 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
797                 credit_charge = MAX(credit_charge, 1);
798         }
799
800         cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
801         credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
802         out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
803         out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
804
805         SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
806
807         if (xconn->smb2.credits.max < credit_charge) {
808                 smbd_server_connection_terminate(sconn,
809                         "client error: credit charge > max credits\n");
810                 return;
811         }
812
813         if (out_flags & SMB2_HDR_FLAG_ASYNC) {
814                 /*
815                  * In case we already send an async interim
816                  * response, we should not grant
817                  * credits on the final response.
818                  */
819                 credits_granted = 0;
820         } else if (credits_requested > 0) {
821                 uint16_t additional_max = 0;
822                 uint16_t additional_credits = credits_requested - 1;
823
824                 switch (cmd) {
825                 case SMB2_OP_NEGPROT:
826                         break;
827                 case SMB2_OP_SESSSETUP:
828                         /*
829                          * Windows 2012 RC1 starts to grant
830                          * additional credits
831                          * with a successful session setup
832                          */
833                         if (NT_STATUS_IS_OK(out_status)) {
834                                 additional_max = 32;
835                         }
836                         break;
837                 default:
838                         /*
839                          * We match windows and only grant additional credits
840                          * in chunks of 32.
841                          */
842                         additional_max = 32;
843                         break;
844                 }
845
846                 additional_credits = MIN(additional_credits, additional_max);
847
848                 credits_granted = credit_charge + additional_credits;
849         } else if (xconn->smb2.credits.granted == 0) {
850                 /*
851                  * Make sure the client has always at least one credit
852                  */
853                 credits_granted = 1;
854         }
855
856         /*
857          * sequence numbers should not wrap
858          *
859          * 1. calculate the possible credits until
860          *    the sequence numbers start to wrap on 64-bit.
861          *
862          * 2. UINT64_MAX is used for Break Notifications.
863          *
864          * 2. truncate the possible credits to the maximum
865          *    credits we want to grant to the client in total.
866          *
867          * 3. remove the range we'll already granted to the client
868          *    this makes sure the client consumes the lowest sequence
869          *    number, before we can grant additional credits.
870          */
871         credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
872         if (credits_possible > 0) {
873                 /* remove UINT64_MAX */
874                 credits_possible -= 1;
875         }
876         credits_possible = MIN(credits_possible, current_max_credits);
877         credits_possible -= xconn->smb2.credits.seq_range;
878
879         credits_granted = MIN(credits_granted, credits_possible);
880
881         SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
882         xconn->smb2.credits.granted += credits_granted;
883         xconn->smb2.credits.seq_range += credits_granted;
884
885         DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
886                 "granted %u, current possible/max %u/%u, "
887                 "total granted/max/low/range %u/%u/%llu/%u\n",
888                 (unsigned int)credits_requested,
889                 (unsigned int)credit_charge,
890                 (unsigned int)credits_granted,
891                 (unsigned int)credits_possible,
892                 (unsigned int)current_max_credits,
893                 (unsigned int)xconn->smb2.credits.granted,
894                 (unsigned int)xconn->smb2.credits.max,
895                 (unsigned long long)xconn->smb2.credits.seq_low,
896                 (unsigned int)xconn->smb2.credits.seq_range));
897 }
898
899 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
900                                 struct smbd_smb2_request *outreq)
901 {
902         int count, idx;
903         uint16_t total_credits = 0;
904
905         count = outreq->out.vector_count;
906
907         for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
908                 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
909                 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
910                 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
911
912                 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
913
914                 /* To match Windows, count up what we
915                    just granted. */
916                 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
917                 /* Set to zero in all but the last reply. */
918                 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
919                         SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
920                 } else {
921                         SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
922                 }
923         }
924 }
925
926 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
927 {
928         if (req->current_idx <= 1) {
929                 if (size <= sizeof(req->out._body)) {
930                         return data_blob_const(req->out._body, size);
931                 }
932         }
933
934         return data_blob_talloc(req, NULL, size);
935 }
936
937 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
938 {
939         struct smbXsrv_connection *xconn = req->xconn;
940         TALLOC_CTX *mem_ctx;
941         struct iovec *vector;
942         int count;
943         int idx;
944
945         count = req->in.vector_count;
946         if (count <= ARRAY_SIZE(req->out._vector)) {
947                 mem_ctx = req;
948                 vector = req->out._vector;
949         } else {
950                 vector = talloc_zero_array(req, struct iovec, count);
951                 if (vector == NULL) {
952                         return NT_STATUS_NO_MEMORY;
953                 }
954                 mem_ctx = vector;
955         }
956
957         vector[0].iov_base      = req->out.nbt_hdr;
958         vector[0].iov_len       = 4;
959         SIVAL(req->out.nbt_hdr, 0, 0);
960
961         for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
962                 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
963                 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
964                 uint8_t *outhdr = NULL;
965                 uint8_t *outbody = NULL;
966                 uint32_t next_command_ofs = 0;
967                 struct iovec *current = &vector[idx];
968
969                 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
970                         /* we have a next command -
971                          * setup for the error case. */
972                         next_command_ofs = SMB2_HDR_BODY + 9;
973                 }
974
975                 if (idx == 1) {
976                         outhdr = req->out._hdr;
977                 } else {
978                         outhdr = talloc_zero_array(mem_ctx, uint8_t,
979                                                    OUTVEC_ALLOC_SIZE);
980                         if (outhdr == NULL) {
981                                 return NT_STATUS_NO_MEMORY;
982                         }
983                 }
984
985                 outbody = outhdr + SMB2_HDR_BODY;
986
987                 /*
988                  * SMBD_SMB2_TF_IOV_OFS might be used later
989                  */
990                 current[SMBD_SMB2_TF_IOV_OFS].iov_base   = NULL;
991                 current[SMBD_SMB2_TF_IOV_OFS].iov_len    = 0;
992
993                 current[SMBD_SMB2_HDR_IOV_OFS].iov_base  = (void *)outhdr;
994                 current[SMBD_SMB2_HDR_IOV_OFS].iov_len   = SMB2_HDR_BODY;
995
996                 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
997                 current[SMBD_SMB2_BODY_IOV_OFS].iov_len  = 8;
998
999                 current[SMBD_SMB2_DYN_IOV_OFS].iov_base  = NULL;
1000                 current[SMBD_SMB2_DYN_IOV_OFS].iov_len   = 0;
1001
1002                 /* setup the SMB2 header */
1003                 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID,     SMB2_MAGIC);
1004                 SSVAL(outhdr, SMB2_HDR_LENGTH,          SMB2_HDR_BODY);
1005                 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1006                       SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1007                 SIVAL(outhdr, SMB2_HDR_STATUS,
1008                       NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1009                 SSVAL(outhdr, SMB2_HDR_OPCODE,
1010                       SVAL(inhdr, SMB2_HDR_OPCODE));
1011                 SIVAL(outhdr, SMB2_HDR_FLAGS,
1012                       IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1013                 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND,    next_command_ofs);
1014                 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1015                       BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1016                 SIVAL(outhdr, SMB2_HDR_PID,
1017                       IVAL(inhdr, SMB2_HDR_PID));
1018                 SIVAL(outhdr, SMB2_HDR_TID,
1019                       IVAL(inhdr, SMB2_HDR_TID));
1020                 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1021                       BVAL(inhdr, SMB2_HDR_SESSION_ID));
1022                 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1023                        inhdr + SMB2_HDR_SIGNATURE, 16);
1024
1025                 /* setup error body header */
1026                 SSVAL(outbody, 0x00, 0x08 + 1);
1027                 SSVAL(outbody, 0x02, 0);
1028                 SIVAL(outbody, 0x04, 0);
1029         }
1030
1031         req->out.vector = vector;
1032         req->out.vector_count = count;
1033
1034         /* setup the length of the NBT packet */
1035         smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1036
1037         DLIST_ADD_END(xconn->smb2.requests, req, struct smbd_smb2_request *);
1038
1039         return NT_STATUS_OK;
1040 }
1041
1042 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
1043                                          const char *reason,
1044                                          const char *location)
1045 {
1046         DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1047                   reason, location));
1048         exit_server_cleanly(reason);
1049 }
1050
1051 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1052                         struct iovec *outvec,
1053                         const struct iovec *srcvec)
1054 {
1055         const uint8_t *srctf;
1056         size_t srctf_len;
1057         const uint8_t *srchdr;
1058         size_t srchdr_len;
1059         const uint8_t *srcbody;
1060         size_t srcbody_len;
1061         const uint8_t *expected_srcbody;
1062         const uint8_t *srcdyn;
1063         size_t srcdyn_len;
1064         const uint8_t *expected_srcdyn;
1065         uint8_t *dsttf;
1066         uint8_t *dsthdr;
1067         uint8_t *dstbody;
1068         uint8_t *dstdyn;
1069
1070         srctf  = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1071         srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1072         srchdr  = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1073         srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1074         srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1075         srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1076         expected_srcbody = srchdr + SMB2_HDR_BODY;
1077         srcdyn  = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1078         srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1079         expected_srcdyn = srcbody + 8;
1080
1081         if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1082                 return false;
1083         }
1084
1085         if (srchdr_len != SMB2_HDR_BODY) {
1086                 return false;
1087         }
1088
1089         if (srctf_len == SMB2_TF_HDR_SIZE) {
1090                 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1091                 if (dsttf == NULL) {
1092                         return false;
1093                 }
1094         } else {
1095                 dsttf = NULL;
1096         }
1097         outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1098         outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1099
1100         /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1101          * be allocated with size OUTVEC_ALLOC_SIZE. */
1102
1103         dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1104         if (dsthdr == NULL) {
1105                 return false;
1106         }
1107         outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1108         outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1109
1110         /*
1111          * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1112          * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1113          * then duplicate this. Else use talloc_memdup().
1114          */
1115
1116         if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1117                 dstbody = dsthdr + SMB2_HDR_BODY;
1118         } else {
1119                 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1120                 if (dstbody == NULL) {
1121                         return false;
1122                 }
1123         }
1124         outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1125         outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1126
1127         /*
1128          * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1129          * pointing to
1130          * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1131          * then duplicate this. Else use talloc_memdup().
1132          */
1133
1134         if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1135                 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1136         } else if (srcdyn == NULL) {
1137                 dstdyn = NULL;
1138         } else {
1139                 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1140                 if (dstdyn == NULL) {
1141                         return false;
1142                 }
1143         }
1144         outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1145         outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1146
1147         return true;
1148 }
1149
1150 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1151 {
1152         struct smbd_smb2_request *newreq = NULL;
1153         struct iovec *outvec = NULL;
1154         int count = req->out.vector_count;
1155         int i;
1156
1157         newreq = smbd_smb2_request_allocate(req->xconn);
1158         if (!newreq) {
1159                 return NULL;
1160         }
1161
1162         newreq->sconn = req->sconn;
1163         newreq->xconn = req->xconn;
1164         newreq->session = req->session;
1165         newreq->do_encryption = req->do_encryption;
1166         newreq->do_signing = req->do_signing;
1167         newreq->current_idx = req->current_idx;
1168
1169         outvec = talloc_zero_array(newreq, struct iovec, count);
1170         if (!outvec) {
1171                 TALLOC_FREE(newreq);
1172                 return NULL;
1173         }
1174         newreq->out.vector = outvec;
1175         newreq->out.vector_count = count;
1176
1177         /* Setup the outvec's identically to req. */
1178         outvec[0].iov_base = newreq->out.nbt_hdr;
1179         outvec[0].iov_len = 4;
1180         memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1181
1182         /* Setup the vectors identically to the ones in req. */
1183         for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1184                 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1185                         break;
1186                 }
1187         }
1188
1189         if (i < count) {
1190                 /* Alloc failed. */
1191                 TALLOC_FREE(newreq);
1192                 return NULL;
1193         }
1194
1195         smb2_setup_nbt_length(newreq->out.vector,
1196                 newreq->out.vector_count);
1197
1198         return newreq;
1199 }
1200
1201 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1202 {
1203         struct smbXsrv_connection *xconn = req->xconn;
1204         int first_idx = 1;
1205         struct iovec *firsttf = NULL;
1206         struct iovec *outhdr_v = NULL;
1207         uint8_t *outhdr = NULL;
1208         struct smbd_smb2_request *nreq = NULL;
1209         NTSTATUS status;
1210
1211         /* Create a new smb2 request we'll use
1212            for the interim return. */
1213         nreq = dup_smb2_req(req);
1214         if (!nreq) {
1215                 return NT_STATUS_NO_MEMORY;
1216         }
1217
1218         /* Lose the last X out vectors. They're the
1219            ones we'll be using for the async reply. */
1220         nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1221
1222         smb2_setup_nbt_length(nreq->out.vector,
1223                 nreq->out.vector_count);
1224
1225         /* Step back to the previous reply. */
1226         nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1227         firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1228         outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1229         outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1230         /* And end the chain. */
1231         SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1232
1233         /* Calculate outgoing credits */
1234         smb2_calculate_credits(req, nreq);
1235
1236         if (DEBUGLEVEL >= 10) {
1237                 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1238                         (unsigned int)nreq->current_idx );
1239                 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1240                         (unsigned int)nreq->out.vector_count );
1241                 print_req_vectors(nreq);
1242         }
1243
1244         /*
1245          * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1246          * we need to sign/encrypt here with the last/first key we remembered
1247          */
1248         if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1249                 status = smb2_signing_encrypt_pdu(req->first_key,
1250                                         xconn->protocol,
1251                                         firsttf,
1252                                         nreq->out.vector_count - first_idx);
1253                 if (!NT_STATUS_IS_OK(status)) {
1254                         return status;
1255                 }
1256         } else if (req->last_key.length > 0) {
1257                 status = smb2_signing_sign_pdu(req->last_key,
1258                                                xconn->protocol,
1259                                                outhdr_v,
1260                                                SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1261                 if (!NT_STATUS_IS_OK(status)) {
1262                         return status;
1263                 }
1264         }
1265
1266         nreq->queue_entry.mem_ctx = nreq;
1267         nreq->queue_entry.vector = nreq->out.vector;
1268         nreq->queue_entry.count = nreq->out.vector_count;
1269         DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry, NULL);
1270         xconn->smb2.send_queue_len++;
1271
1272         status = smbd_smb2_flush_send_queue(xconn);
1273         if (!NT_STATUS_IS_OK(status)) {
1274                 return status;
1275         }
1276
1277         return NT_STATUS_OK;
1278 }
1279
1280 struct smbd_smb2_request_pending_state {
1281         struct smbd_smb2_send_queue queue_entry;
1282         uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1283         struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1284 };
1285
1286 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1287                                             struct tevent_timer *te,
1288                                             struct timeval current_time,
1289                                             void *private_data);
1290
1291 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1292                                          struct tevent_req *subreq,
1293                                          uint32_t defer_time)
1294 {
1295         NTSTATUS status;
1296         struct timeval defer_endtime;
1297         uint8_t *outhdr = NULL;
1298         uint32_t flags;
1299
1300         if (!tevent_req_is_in_progress(subreq)) {
1301                 /*
1302                  * This is a performance optimization,
1303                  * it avoids one tevent_loop iteration,
1304                  * which means we avoid one
1305                  * talloc_stackframe_pool/talloc_free pair.
1306                  */
1307                 tevent_req_notify_callback(subreq);
1308                 return NT_STATUS_OK;
1309         }
1310
1311         req->subreq = subreq;
1312         subreq = NULL;
1313
1314         if (req->async_te) {
1315                 /* We're already async. */
1316                 return NT_STATUS_OK;
1317         }
1318
1319         outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1320         flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1321         if (flags & SMB2_HDR_FLAG_ASYNC) {
1322                 /* We're already async. */
1323                 return NT_STATUS_OK;
1324         }
1325
1326         if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1327                 /*
1328                  * We're trying to go async in a compound
1329                  * request chain.
1330                  * This is only allowed for opens that
1331                  * cause an oplock break, otherwise it
1332                  * is not allowed. See [MS-SMB2].pdf
1333                  * note <194> on Section 3.3.5.2.7.
1334                  */
1335                 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1336
1337                 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1338                         /*
1339                          * Cancel the outstanding request.
1340                          */
1341                         bool ok = tevent_req_cancel(req->subreq);
1342                         if (ok) {
1343                                 return NT_STATUS_OK;
1344                         }
1345                         TALLOC_FREE(req->subreq);
1346                         return smbd_smb2_request_error(req,
1347                                 NT_STATUS_INTERNAL_ERROR);
1348                 }
1349         }
1350
1351         if (DEBUGLEVEL >= 10) {
1352                 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1353                         (unsigned int)req->current_idx );
1354                 print_req_vectors(req);
1355         }
1356
1357         if (req->current_idx > 1) {
1358                 /*
1359                  * We're going async in a compound
1360                  * chain after the first request has
1361                  * already been processed. Send an
1362                  * interim response containing the
1363                  * set of replies already generated.
1364                  */
1365                 int idx = req->current_idx;
1366
1367                 status = smb2_send_async_interim_response(req);
1368                 if (!NT_STATUS_IS_OK(status)) {
1369                         return status;
1370                 }
1371                 if (req->first_key.length > 0) {
1372                         data_blob_clear_free(&req->first_key);
1373                 }
1374
1375                 req->current_idx = 1;
1376
1377                 /*
1378                  * Re-arrange the in.vectors to remove what
1379                  * we just sent.
1380                  */
1381                 memmove(&req->in.vector[1],
1382                         &req->in.vector[idx],
1383                         sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1384                 req->in.vector_count = 1 + (req->in.vector_count - idx);
1385
1386                 /* Re-arrange the out.vectors to match. */
1387                 memmove(&req->out.vector[1],
1388                         &req->out.vector[idx],
1389                         sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1390                 req->out.vector_count = 1 + (req->out.vector_count - idx);
1391
1392                 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1393                         /*
1394                          * We only have one remaining request as
1395                          * we've processed everything else.
1396                          * This is no longer a compound request.
1397                          */
1398                         req->compound_related = false;
1399                         outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1400                         flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1401                         SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1402                 }
1403         }
1404         if (req->last_key.length > 0) {
1405                 data_blob_clear_free(&req->last_key);
1406         }
1407
1408         defer_endtime = timeval_current_ofs_usec(defer_time);
1409         req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1410                                          req, defer_endtime,
1411                                          smbd_smb2_request_pending_timer,
1412                                          req);
1413         if (req->async_te == NULL) {
1414                 return NT_STATUS_NO_MEMORY;
1415         }
1416
1417         return NT_STATUS_OK;
1418 }
1419
1420 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1421                                             struct tevent_timer *te,
1422                                             struct timeval current_time,
1423                                             void *private_data)
1424 {
1425         struct smbd_smb2_request *req =
1426                 talloc_get_type_abort(private_data,
1427                 struct smbd_smb2_request);
1428         struct smbXsrv_connection *xconn = req->xconn;
1429         struct smbd_smb2_request_pending_state *state = NULL;
1430         uint8_t *outhdr = NULL;
1431         const uint8_t *inhdr = NULL;
1432         uint8_t *tf = NULL;
1433         size_t tf_len = 0;
1434         uint8_t *hdr = NULL;
1435         uint8_t *body = NULL;
1436         uint8_t *dyn = NULL;
1437         uint32_t flags = 0;
1438         uint64_t session_id = 0;
1439         uint64_t message_id = 0;
1440         uint64_t nonce_high = 0;
1441         uint64_t nonce_low = 0;
1442         uint64_t async_id = 0;
1443         NTSTATUS status;
1444
1445         TALLOC_FREE(req->async_te);
1446
1447         /* Ensure our final reply matches the interim one. */
1448         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1449         outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1450         flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1451         message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1452         session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1453
1454         async_id = message_id; /* keep it simple for now... */
1455
1456         SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1457         SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1458
1459         DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1460                 "going async\n",
1461                 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1462                 (unsigned long long)async_id ));
1463
1464         /*
1465          * What we send is identical to a smbd_smb2_request_error
1466          * packet with an error status of STATUS_PENDING. Make use
1467          * of this fact sometime when refactoring. JRA.
1468          */
1469
1470         state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
1471         if (state == NULL) {
1472                 smbd_server_connection_terminate(req->sconn,
1473                                                  nt_errstr(NT_STATUS_NO_MEMORY));
1474                 return;
1475         }
1476
1477         tf = state->buf + NBT_HDR_SIZE;
1478         tf_len = SMB2_TF_HDR_SIZE;
1479
1480         hdr = tf + SMB2_TF_HDR_SIZE;
1481         body = hdr + SMB2_HDR_BODY;
1482         dyn = body + 8;
1483
1484         if (req->do_encryption) {
1485                 struct smbXsrv_session *x = req->session;
1486
1487                 nonce_high = x->nonce_high;
1488                 nonce_low = x->nonce_low;
1489
1490                 x->nonce_low += 1;
1491                 if (x->nonce_low == 0) {
1492                         x->nonce_low += 1;
1493                         x->nonce_high += 1;
1494                 }
1495         }
1496
1497         SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1498         SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1499         SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1500         SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1501
1502         SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1503         SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1504         SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1505         SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1506         SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1507
1508         SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1509         SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1510         SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1511         SBVAL(hdr, SMB2_HDR_PID, async_id);
1512         SBVAL(hdr, SMB2_HDR_SESSION_ID,
1513                 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1514         memcpy(hdr+SMB2_HDR_SIGNATURE,
1515                outhdr+SMB2_HDR_SIGNATURE, 16);
1516
1517         SSVAL(body, 0x00, 0x08 + 1);
1518
1519         SCVAL(body, 0x02, 0);
1520         SCVAL(body, 0x03, 0);
1521         SIVAL(body, 0x04, 0);
1522         /* Match W2K8R2... */
1523         SCVAL(dyn,  0x00, 0x21);
1524
1525         state->vector[0].iov_base = (void *)state->buf;
1526         state->vector[0].iov_len = NBT_HDR_SIZE;
1527
1528         if (req->do_encryption) {
1529                 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base   = tf;
1530                 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len    = tf_len;
1531         } else {
1532                 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base   = NULL;
1533                 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len    = 0;
1534         }
1535
1536         state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base  = hdr;
1537         state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len   = SMB2_HDR_BODY;
1538
1539         state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1540         state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len  = 8;
1541
1542         state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base  = dyn;
1543         state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len   = 1;
1544
1545         smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1546
1547         /* Ensure we correctly go through crediting. Grant
1548            the credits now, and zero credits on the final
1549            response. */
1550         smb2_set_operation_credit(req->xconn,
1551                         SMBD_SMB2_IN_HDR_IOV(req),
1552                         &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1553
1554         SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1555
1556         if (DEBUGLVL(10)) {
1557                 int i;
1558
1559                 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1560                         dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1561                                 (unsigned int)i,
1562                                 (unsigned int)ARRAY_SIZE(state->vector),
1563                                 (unsigned int)state->vector[i].iov_len);
1564                 }
1565         }
1566
1567         if (req->do_encryption) {
1568                 struct smbXsrv_session *x = req->session;
1569                 DATA_BLOB encryption_key = x->global->encryption_key;
1570
1571                 status = smb2_signing_encrypt_pdu(encryption_key,
1572                                         xconn->protocol,
1573                                         &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1574                                         SMBD_SMB2_NUM_IOV_PER_REQ);
1575                 if (!NT_STATUS_IS_OK(status)) {
1576                         smbd_server_connection_terminate(req->sconn,
1577                                                 nt_errstr(status));
1578                         return;
1579                 }
1580         } else if (req->do_signing) {
1581                 struct smbXsrv_session *x = req->session;
1582                 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1583
1584                 status = smb2_signing_sign_pdu(signing_key,
1585                                         xconn->protocol,
1586                                         &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1587                                         SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1588                 if (!NT_STATUS_IS_OK(status)) {
1589                         smbd_server_connection_terminate(req->sconn,
1590                                                 nt_errstr(status));
1591                         return;
1592                 }
1593         }
1594
1595         state->queue_entry.mem_ctx = state;
1596         state->queue_entry.vector = state->vector;
1597         state->queue_entry.count = ARRAY_SIZE(state->vector);
1598         DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
1599         xconn->smb2.send_queue_len++;
1600
1601         status = smbd_smb2_flush_send_queue(xconn);
1602         if (!NT_STATUS_IS_OK(status)) {
1603                 smbd_server_connection_terminate(req->sconn,
1604                                                  nt_errstr(status));
1605                 return;
1606         }
1607 }
1608
1609 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1610 {
1611         struct smbXsrv_connection *xconn = req->xconn;
1612         struct smbd_smb2_request *cur;
1613         const uint8_t *inhdr;
1614         uint32_t flags;
1615         uint64_t search_message_id;
1616         uint64_t search_async_id;
1617         uint64_t found_id;
1618
1619         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1620
1621         flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1622         search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1623         search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1624
1625         /*
1626          * we don't need the request anymore
1627          * cancel requests never have a response
1628          */
1629         DLIST_REMOVE(xconn->smb2.requests, req);
1630         TALLOC_FREE(req);
1631
1632         for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1633                 const uint8_t *outhdr;
1634                 uint64_t message_id;
1635                 uint64_t async_id;
1636
1637                 if (cur->compound_related) {
1638                         /*
1639                          * Never cancel anything in a compound request.
1640                          * Way too hard to deal with the result.
1641                          */
1642                         continue;
1643                 }
1644
1645                 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1646
1647                 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1648                 async_id = BVAL(outhdr, SMB2_HDR_PID);
1649
1650                 if (flags & SMB2_HDR_FLAG_ASYNC) {
1651                         if (search_async_id == async_id) {
1652                                 found_id = async_id;
1653                                 break;
1654                         }
1655                 } else {
1656                         if (search_message_id == message_id) {
1657                                 found_id = message_id;
1658                                 break;
1659                         }
1660                 }
1661         }
1662
1663         if (cur && cur->subreq) {
1664                 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1665                 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1666                         "cancel opcode[%s] mid %llu\n",
1667                         smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1668                         (unsigned long long)found_id ));
1669                 tevent_req_cancel(cur->subreq);
1670         }
1671
1672         return NT_STATUS_OK;
1673 }
1674
1675 /*************************************************************
1676  Ensure an incoming tid is a valid one for us to access.
1677  Change to the associated uid credentials and chdir to the
1678  valid tid directory.
1679 *************************************************************/
1680
1681 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1682 {
1683         const uint8_t *inhdr;
1684         uint32_t in_flags;
1685         uint32_t in_tid;
1686         struct smbXsrv_tcon *tcon;
1687         NTSTATUS status;
1688         NTTIME now = timeval_to_nttime(&req->request_time);
1689
1690         req->tcon = NULL;
1691
1692         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1693
1694         in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1695         in_tid = IVAL(inhdr, SMB2_HDR_TID);
1696
1697         if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1698                 in_tid = req->last_tid;
1699         }
1700
1701         req->last_tid = 0;
1702
1703         status = smb2srv_tcon_lookup(req->session,
1704                                      in_tid, now, &tcon);
1705         if (!NT_STATUS_IS_OK(status)) {
1706                 return status;
1707         }
1708
1709         if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1710                 return NT_STATUS_ACCESS_DENIED;
1711         }
1712
1713         /* should we pass FLAG_CASELESS_PATHNAMES here? */
1714         if (!set_current_service(tcon->compat, 0, true)) {
1715                 return NT_STATUS_ACCESS_DENIED;
1716         }
1717
1718         req->tcon = tcon;
1719         req->last_tid = in_tid;
1720
1721         return NT_STATUS_OK;
1722 }
1723
1724 /*************************************************************
1725  Ensure an incoming session_id is a valid one for us to access.
1726 *************************************************************/
1727
1728 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1729 {
1730         const uint8_t *inhdr;
1731         uint32_t in_flags;
1732         uint16_t in_opcode;
1733         uint64_t in_session_id;
1734         struct smbXsrv_session *session = NULL;
1735         struct auth_session_info *session_info;
1736         NTSTATUS status;
1737         NTTIME now = timeval_to_nttime(&req->request_time);
1738
1739         req->session = NULL;
1740         req->tcon = NULL;
1741
1742         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1743
1744         in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1745         in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1746         in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1747
1748         if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1749                 in_session_id = req->last_session_id;
1750         }
1751
1752         req->last_session_id = 0;
1753
1754         /* lookup an existing session */
1755         status = smb2srv_session_lookup(req->xconn,
1756                                         in_session_id, now,
1757                                         &session);
1758         if (session) {
1759                 req->session = session;
1760                 req->last_session_id = in_session_id;
1761         }
1762         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1763                 switch (in_opcode) {
1764                 case SMB2_OP_SESSSETUP:
1765                         status = NT_STATUS_OK;
1766                         break;
1767                 default:
1768                         break;
1769                 }
1770         }
1771         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1772                 switch (in_opcode) {
1773                 case SMB2_OP_TCON:
1774                 case SMB2_OP_CREATE:
1775                 case SMB2_OP_GETINFO:
1776                 case SMB2_OP_SETINFO:
1777                         return NT_STATUS_INVALID_HANDLE;
1778                 default:
1779                         /*
1780                          * Notice the check for
1781                          * (session_info == NULL)
1782                          * below.
1783                          */
1784                         status = NT_STATUS_OK;
1785                         break;
1786                 }
1787         }
1788         if (!NT_STATUS_IS_OK(status)) {
1789                 return status;
1790         }
1791
1792         session_info = session->global->auth_session_info;
1793         if (session_info == NULL) {
1794                 return NT_STATUS_INVALID_HANDLE;
1795         }
1796
1797         if (in_session_id != req->xconn->last_session_id) {
1798                 req->xconn->last_session_id = in_session_id;
1799                 set_current_user_info(session_info->unix_info->sanitized_username,
1800                                       session_info->unix_info->unix_name,
1801                                       session_info->info->domain_name);
1802         }
1803
1804         return NT_STATUS_OK;
1805 }
1806
1807 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1808                                                 uint32_t data_length)
1809 {
1810         struct smbXsrv_connection *xconn = req->xconn;
1811         uint16_t needed_charge;
1812         uint16_t credit_charge = 1;
1813         const uint8_t *inhdr;
1814
1815         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1816
1817         if (xconn->smb2.credits.multicredit) {
1818                 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1819                 credit_charge = MAX(credit_charge, 1);
1820         }
1821
1822         needed_charge = (data_length - 1)/ 65536 + 1;
1823
1824         DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1825                    (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1826                    credit_charge, needed_charge));
1827
1828         if (needed_charge > credit_charge) {
1829                 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1830                           credit_charge, needed_charge));
1831                 return NT_STATUS_INVALID_PARAMETER;
1832         }
1833
1834         return NT_STATUS_OK;
1835 }
1836
1837 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1838                                         size_t expected_body_size)
1839 {
1840         struct iovec *inhdr_v;
1841         const uint8_t *inhdr;
1842         uint16_t opcode;
1843         const uint8_t *inbody;
1844         size_t body_size;
1845         size_t min_dyn_size = expected_body_size & 0x00000001;
1846         int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1847
1848         /*
1849          * The following should be checked already.
1850          */
1851         if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1852                 return NT_STATUS_INTERNAL_ERROR;
1853         }
1854         if (req->current_idx > max_idx) {
1855                 return NT_STATUS_INTERNAL_ERROR;
1856         }
1857
1858         inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1859         if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1860                 return NT_STATUS_INTERNAL_ERROR;
1861         }
1862         if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1863                 return NT_STATUS_INTERNAL_ERROR;
1864         }
1865
1866         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1867         opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1868
1869         switch (opcode) {
1870         case SMB2_OP_IOCTL:
1871         case SMB2_OP_GETINFO:
1872                 min_dyn_size = 0;
1873                 break;
1874         case SMB2_OP_WRITE:
1875                 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
1876                         if (req->smb1req->unread_bytes < min_dyn_size) {
1877                                 return NT_STATUS_INVALID_PARAMETER;
1878                         }
1879
1880                         min_dyn_size = 0;
1881                 }
1882                 break;
1883         }
1884
1885         /*
1886          * Now check the expected body size,
1887          * where the last byte might be in the
1888          * dynamic section..
1889          */
1890         if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1891                 return NT_STATUS_INVALID_PARAMETER;
1892         }
1893         if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1894                 return NT_STATUS_INVALID_PARAMETER;
1895         }
1896
1897         inbody = SMBD_SMB2_IN_BODY_PTR(req);
1898
1899         body_size = SVAL(inbody, 0x00);
1900         if (body_size != expected_body_size) {
1901                 return NT_STATUS_INVALID_PARAMETER;
1902         }
1903
1904         return NT_STATUS_OK;
1905 }
1906
1907 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1908 {
1909         struct smbXsrv_connection *xconn = req->xconn;
1910         const struct smbd_smb2_dispatch_table *call = NULL;
1911         const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1912         const uint8_t *inhdr;
1913         uint16_t opcode;
1914         uint32_t flags;
1915         uint64_t mid;
1916         NTSTATUS status;
1917         NTSTATUS session_status;
1918         uint32_t allowed_flags;
1919         NTSTATUS return_value;
1920         struct smbXsrv_session *x = NULL;
1921         bool signing_required = false;
1922         bool encryption_required = false;
1923
1924         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1925
1926         /* TODO: verify more things */
1927
1928         flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1929         opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1930         mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1931         DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1932                 smb2_opcode_name(opcode),
1933                 (unsigned long long)mid));
1934
1935         if (xconn->protocol >= PROTOCOL_SMB2_02) {
1936                 /*
1937                  * once the protocol is negotiated
1938                  * SMB2_OP_NEGPROT is not allowed anymore
1939                  */
1940                 if (opcode == SMB2_OP_NEGPROT) {
1941                         /* drop the connection */
1942                         return NT_STATUS_INVALID_PARAMETER;
1943                 }
1944         } else {
1945                 /*
1946                  * if the protocol is not negotiated yet
1947                  * only SMB2_OP_NEGPROT is allowed.
1948                  */
1949                 if (opcode != SMB2_OP_NEGPROT) {
1950                         /* drop the connection */
1951                         return NT_STATUS_INVALID_PARAMETER;
1952                 }
1953         }
1954
1955         /*
1956          * Check if the client provided a valid session id,
1957          * if so smbd_smb2_request_check_session() calls
1958          * set_current_user_info().
1959          *
1960          * As some command don't require a valid session id
1961          * we defer the check of the session_status
1962          */
1963         session_status = smbd_smb2_request_check_session(req);
1964         x = req->session;
1965         if (x != NULL) {
1966                 signing_required = x->global->signing_required;
1967                 encryption_required = x->global->encryption_required;
1968
1969                 if (opcode == SMB2_OP_SESSSETUP &&
1970                     x->global->channels[0].signing_key.length) {
1971                         signing_required = true;
1972                 }
1973         }
1974
1975         req->do_signing = false;
1976         req->do_encryption = false;
1977         if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
1978                 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
1979                 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
1980
1981                 if (x != NULL && x->global->session_wire_id != tf_session_id) {
1982                         DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1983                                  "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1984                                  (unsigned long long)x->global->session_wire_id,
1985                                  (unsigned long long)tf_session_id));
1986                         /*
1987                          * TODO: windows allows this...
1988                          * should we drop the connection?
1989                          *
1990                          * For now we just return ACCESS_DENIED
1991                          * (Windows clients never trigger this)
1992                          * and wait for an update of [MS-SMB2].
1993                          */
1994                         return smbd_smb2_request_error(req,
1995                                         NT_STATUS_ACCESS_DENIED);
1996                 }
1997
1998                 req->do_encryption = true;
1999         }
2000
2001         if (encryption_required && !req->do_encryption) {
2002                 return smbd_smb2_request_error(req,
2003                                 NT_STATUS_ACCESS_DENIED);
2004         }
2005
2006         call = smbd_smb2_call(opcode);
2007         if (call == NULL) {
2008                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2009         }
2010
2011         allowed_flags = SMB2_HDR_FLAG_CHAINED |
2012                         SMB2_HDR_FLAG_SIGNED |
2013                         SMB2_HDR_FLAG_DFS;
2014         if (opcode == SMB2_OP_CANCEL) {
2015                 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2016         }
2017         if ((flags & ~allowed_flags) != 0) {
2018                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2019         }
2020
2021         if (flags & SMB2_HDR_FLAG_CHAINED) {
2022                 /*
2023                  * This check is mostly for giving the correct error code
2024                  * for compounded requests.
2025                  */
2026                 if (!NT_STATUS_IS_OK(session_status)) {
2027                         return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2028                 }
2029         } else {
2030                 req->compat_chain_fsp = NULL;
2031         }
2032
2033         if (req->do_encryption) {
2034                 signing_required = false;
2035         } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2036                 DATA_BLOB signing_key;
2037
2038                 if (x == NULL) {
2039                         /*
2040                          * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2041                          * If the SMB2 header of the SMB2 NEGOTIATE
2042                          * request has the SMB2_FLAGS_SIGNED bit set in the
2043                          * Flags field, the server MUST fail the request
2044                          * with STATUS_INVALID_PARAMETER.
2045                          *
2046                          * Microsoft test tool checks this.
2047                          */
2048
2049                         if ((opcode == SMB2_OP_NEGPROT) &&
2050                                         (flags & SMB2_HDR_FLAG_SIGNED)) {
2051                                 status = NT_STATUS_INVALID_PARAMETER;
2052                         } else {
2053                                 status = NT_STATUS_USER_SESSION_DELETED;
2054                         }
2055                         return smbd_smb2_request_error(req, status);
2056                 }
2057
2058                 signing_key = x->global->channels[0].signing_key;
2059
2060                 /*
2061                  * If we have a signing key, we should
2062                  * sign the response
2063                  */
2064                 if (signing_key.length > 0) {
2065                         req->do_signing = true;
2066                 }
2067
2068                 status = smb2_signing_check_pdu(signing_key,
2069                                                 xconn->protocol,
2070                                                 SMBD_SMB2_IN_HDR_IOV(req),
2071                                                 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2072                 if (!NT_STATUS_IS_OK(status)) {
2073                         return smbd_smb2_request_error(req, status);
2074                 }
2075
2076                 /*
2077                  * Now that we know the request was correctly signed
2078                  * we have to sign the response too.
2079                  */
2080                 req->do_signing = true;
2081
2082                 if (!NT_STATUS_IS_OK(session_status)) {
2083                         return smbd_smb2_request_error(req, session_status);
2084                 }
2085         } else if (opcode == SMB2_OP_CANCEL) {
2086                 /* Cancel requests are allowed to skip the signing */
2087         } else if (signing_required) {
2088                 /*
2089                  * If signing is required we try to sign
2090                  * a possible error response
2091                  */
2092                 req->do_signing = true;
2093                 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2094         }
2095
2096         if (flags & SMB2_HDR_FLAG_CHAINED) {
2097                 req->compound_related = true;
2098         }
2099
2100         if (call->need_session) {
2101                 if (!NT_STATUS_IS_OK(session_status)) {
2102                         return smbd_smb2_request_error(req, session_status);
2103                 }
2104         }
2105
2106         if (call->need_tcon) {
2107                 SMB_ASSERT(call->need_session);
2108
2109                 /*
2110                  * This call needs to be run as user.
2111                  *
2112                  * smbd_smb2_request_check_tcon()
2113                  * calls change_to_user() on success.
2114                  */
2115                 status = smbd_smb2_request_check_tcon(req);
2116                 if (!NT_STATUS_IS_OK(status)) {
2117                         return smbd_smb2_request_error(req, status);
2118                 }
2119                 if (req->tcon->global->encryption_required) {
2120                         encryption_required = true;
2121                 }
2122                 if (encryption_required && !req->do_encryption) {
2123                         return smbd_smb2_request_error(req,
2124                                 NT_STATUS_ACCESS_DENIED);
2125                 }
2126         }
2127
2128         if (call->fileid_ofs != 0) {
2129                 size_t needed = call->fileid_ofs + 16;
2130                 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2131                 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2132                 uint64_t file_id_persistent;
2133                 uint64_t file_id_volatile;
2134                 struct files_struct *fsp;
2135
2136                 SMB_ASSERT(call->need_tcon);
2137
2138                 if (needed > body_size) {
2139                         return smbd_smb2_request_error(req,
2140                                         NT_STATUS_INVALID_PARAMETER);
2141                 }
2142
2143                 file_id_persistent      = BVAL(body, call->fileid_ofs + 0);
2144                 file_id_volatile        = BVAL(body, call->fileid_ofs + 8);
2145
2146                 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2147                 if (fsp == NULL) {
2148                         if (!call->allow_invalid_fileid) {
2149                                 return smbd_smb2_request_error(req,
2150                                                 NT_STATUS_FILE_CLOSED);
2151                         }
2152
2153                         if (file_id_persistent != UINT64_MAX) {
2154                                 return smbd_smb2_request_error(req,
2155                                                 NT_STATUS_FILE_CLOSED);
2156                         }
2157                         if (file_id_volatile != UINT64_MAX) {
2158                                 return smbd_smb2_request_error(req,
2159                                                 NT_STATUS_FILE_CLOSED);
2160                         }
2161                 }
2162         }
2163
2164         if (call->as_root) {
2165                 SMB_ASSERT(call->fileid_ofs == 0);
2166                 /* This call needs to be run as root */
2167                 change_to_root_user();
2168         } else {
2169                 SMB_ASSERT(call->need_tcon);
2170         }
2171
2172         switch (opcode) {
2173         case SMB2_OP_NEGPROT:
2174                 {
2175                         START_PROFILE(smb2_negprot);
2176                         return_value = smbd_smb2_request_process_negprot(req);
2177                         END_PROFILE(smb2_negprot);
2178                 }
2179                 break;
2180
2181         case SMB2_OP_SESSSETUP:
2182                 {
2183                         START_PROFILE(smb2_sesssetup);
2184                         return_value = smbd_smb2_request_process_sesssetup(req);
2185                         END_PROFILE(smb2_sesssetup);
2186                 }
2187                 break;
2188
2189         case SMB2_OP_LOGOFF:
2190                 {
2191                         START_PROFILE(smb2_logoff);
2192                         return_value = smbd_smb2_request_process_logoff(req);
2193                         END_PROFILE(smb2_logoff);
2194                 }
2195                 break;
2196
2197         case SMB2_OP_TCON:
2198                 {
2199                         START_PROFILE(smb2_tcon);
2200                         return_value = smbd_smb2_request_process_tcon(req);
2201                         END_PROFILE(smb2_tcon);
2202                 }
2203                 break;
2204
2205         case SMB2_OP_TDIS:
2206                 {
2207                         START_PROFILE(smb2_tdis);
2208                         return_value = smbd_smb2_request_process_tdis(req);
2209                         END_PROFILE(smb2_tdis);
2210                 }
2211                 break;
2212
2213         case SMB2_OP_CREATE:
2214                 {
2215                         START_PROFILE(smb2_create);
2216                         return_value = smbd_smb2_request_process_create(req);
2217                         END_PROFILE(smb2_create);
2218                 }
2219                 break;
2220
2221         case SMB2_OP_CLOSE:
2222                 {
2223                         START_PROFILE(smb2_close);
2224                         return_value = smbd_smb2_request_process_close(req);
2225                         END_PROFILE(smb2_close);
2226                 }
2227                 break;
2228
2229         case SMB2_OP_FLUSH:
2230                 {
2231                         START_PROFILE(smb2_flush);
2232                         return_value = smbd_smb2_request_process_flush(req);
2233                         END_PROFILE(smb2_flush);
2234                 }
2235                 break;
2236
2237         case SMB2_OP_READ:
2238                 {
2239                         START_PROFILE(smb2_read);
2240                         return_value = smbd_smb2_request_process_read(req);
2241                         END_PROFILE(smb2_read);
2242                 }
2243                 break;
2244
2245         case SMB2_OP_WRITE:
2246                 {
2247                         START_PROFILE(smb2_write);
2248                         return_value = smbd_smb2_request_process_write(req);
2249                         END_PROFILE(smb2_write);
2250                 }
2251                 break;
2252
2253         case SMB2_OP_LOCK:
2254                 {
2255                         START_PROFILE(smb2_lock);
2256                         return_value = smbd_smb2_request_process_lock(req);
2257                         END_PROFILE(smb2_lock);
2258                 }
2259                 break;
2260
2261         case SMB2_OP_IOCTL:
2262                 {
2263                         START_PROFILE(smb2_ioctl);
2264                         return_value = smbd_smb2_request_process_ioctl(req);
2265                         END_PROFILE(smb2_ioctl);
2266                 }
2267                 break;
2268
2269         case SMB2_OP_CANCEL:
2270                 {
2271                         START_PROFILE(smb2_cancel);
2272                         return_value = smbd_smb2_request_process_cancel(req);
2273                         END_PROFILE(smb2_cancel);
2274                 }
2275                 break;
2276
2277         case SMB2_OP_KEEPALIVE:
2278                 {
2279                         START_PROFILE(smb2_keepalive);
2280                         return_value = smbd_smb2_request_process_keepalive(req);
2281                         END_PROFILE(smb2_keepalive);
2282                 }
2283                 break;
2284
2285         case SMB2_OP_FIND:
2286                 {
2287                         START_PROFILE(smb2_find);
2288                         return_value = smbd_smb2_request_process_find(req);
2289                         END_PROFILE(smb2_find);
2290                 }
2291                 break;
2292
2293         case SMB2_OP_NOTIFY:
2294                 {
2295                         START_PROFILE(smb2_notify);
2296                         return_value = smbd_smb2_request_process_notify(req);
2297                         END_PROFILE(smb2_notify);
2298                 }
2299                 break;
2300
2301         case SMB2_OP_GETINFO:
2302                 {
2303                         START_PROFILE(smb2_getinfo);
2304                         return_value = smbd_smb2_request_process_getinfo(req);
2305                         END_PROFILE(smb2_getinfo);
2306                 }
2307                 break;
2308
2309         case SMB2_OP_SETINFO:
2310                 {
2311                         START_PROFILE(smb2_setinfo);
2312                         return_value = smbd_smb2_request_process_setinfo(req);
2313                         END_PROFILE(smb2_setinfo);
2314                 }
2315                 break;
2316
2317         case SMB2_OP_BREAK:
2318                 {
2319                         START_PROFILE(smb2_break);
2320                         return_value = smbd_smb2_request_process_break(req);
2321                         END_PROFILE(smb2_break);
2322                 }
2323                 break;
2324
2325         default:
2326                 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2327                 break;
2328         }
2329         return return_value;
2330 }
2331
2332 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2333 {
2334         struct smbXsrv_connection *xconn = req->xconn;
2335         int first_idx = 1;
2336         struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2337         struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2338         struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2339         NTSTATUS status;
2340
2341         req->subreq = NULL;
2342         TALLOC_FREE(req->async_te);
2343
2344         if (req->do_encryption &&
2345             (firsttf->iov_len == 0) &&
2346             (req->first_key.length == 0) &&
2347             (req->session != NULL) &&
2348             (req->session->global->encryption_key.length != 0))
2349         {
2350                 DATA_BLOB encryption_key = req->session->global->encryption_key;
2351                 uint8_t *tf;
2352                 uint64_t session_id = req->session->global->session_wire_id;
2353                 struct smbXsrv_session *x = req->session;
2354                 uint64_t nonce_high;
2355                 uint64_t nonce_low;
2356
2357                 nonce_high = x->nonce_high;
2358                 nonce_low = x->nonce_low;
2359
2360                 x->nonce_low += 1;
2361                 if (x->nonce_low == 0) {
2362                         x->nonce_low += 1;
2363                         x->nonce_high += 1;
2364                 }
2365
2366                 /*
2367                  * We need to place the SMB2_TRANSFORM header before the
2368                  * first SMB2 header
2369                  */
2370
2371                 /*
2372                  * we need to remember the encryption key
2373                  * and defer the signing/encryption until
2374                  * we are sure that we do not change
2375                  * the header again.
2376                  */
2377                 req->first_key = data_blob_dup_talloc(req, encryption_key);
2378                 if (req->first_key.data == NULL) {
2379                         return NT_STATUS_NO_MEMORY;
2380                 }
2381
2382                 tf = talloc_zero_array(req, uint8_t,
2383                                        SMB2_TF_HDR_SIZE);
2384                 if (tf == NULL) {
2385                         return NT_STATUS_NO_MEMORY;
2386                 }
2387
2388                 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2389                 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2390                 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2391                 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2392
2393                 firsttf->iov_base = (void *)tf;
2394                 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2395         }
2396
2397         if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2398             (req->last_key.length > 0) &&
2399             (firsttf->iov_len == 0))
2400         {
2401                 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2402                 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2403
2404                 /*
2405                  * As we are sure the header of the last request in the
2406                  * compound chain will not change, we can to sign here
2407                  * with the last signing key we remembered.
2408                  */
2409                 status = smb2_signing_sign_pdu(req->last_key,
2410                                                xconn->protocol,
2411                                                lasthdr,
2412                                                SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2413                 if (!NT_STATUS_IS_OK(status)) {
2414                         return status;
2415                 }
2416         }
2417         if (req->last_key.length > 0) {
2418                 data_blob_clear_free(&req->last_key);
2419         }
2420
2421         req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2422
2423         if (req->current_idx < req->out.vector_count) {
2424                 /*
2425                  * We must process the remaining compound
2426                  * SMB2 requests before any new incoming SMB2
2427                  * requests. This is because incoming SMB2
2428                  * requests may include a cancel for a
2429                  * compound request we haven't processed
2430                  * yet.
2431                  */
2432                 struct tevent_immediate *im = tevent_create_immediate(req);
2433                 if (!im) {
2434                         return NT_STATUS_NO_MEMORY;
2435                 }
2436
2437                 if (req->do_signing && firsttf->iov_len == 0) {
2438                         struct smbXsrv_session *x = req->session;
2439                         DATA_BLOB signing_key = x->global->channels[0].signing_key;
2440
2441                         /*
2442                          * we need to remember the signing key
2443                          * and defer the signing until
2444                          * we are sure that we do not change
2445                          * the header again.
2446                          */
2447                         req->last_key = data_blob_dup_talloc(req, signing_key);
2448                         if (req->last_key.data == NULL) {
2449                                 return NT_STATUS_NO_MEMORY;
2450                         }
2451                 }
2452
2453                 tevent_schedule_immediate(im,
2454                                         req->sconn->ev_ctx,
2455                                         smbd_smb2_request_dispatch_immediate,
2456                                         req);
2457                 return NT_STATUS_OK;
2458         }
2459
2460         if (req->compound_related) {
2461                 req->compound_related = false;
2462         }
2463
2464         smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2465
2466         /* Set credit for these operations (zero credits if this
2467            is a final reply for an async operation). */
2468         smb2_calculate_credits(req, req);
2469
2470         /*
2471          * now check if we need to sign the current response
2472          */
2473         if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2474                 status = smb2_signing_encrypt_pdu(req->first_key,
2475                                         xconn->protocol,
2476                                         firsttf,
2477                                         req->out.vector_count - first_idx);
2478                 if (!NT_STATUS_IS_OK(status)) {
2479                         return status;
2480                 }
2481         } else if (req->do_signing) {
2482                 struct smbXsrv_session *x = req->session;
2483                 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2484
2485                 status = smb2_signing_sign_pdu(signing_key,
2486                                                xconn->protocol,
2487                                                outhdr,
2488                                                SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2489                 if (!NT_STATUS_IS_OK(status)) {
2490                         return status;
2491                 }
2492         }
2493         if (req->first_key.length > 0) {
2494                 data_blob_clear_free(&req->first_key);
2495         }
2496
2497         /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2498         if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2499             outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2500                 /* Dynamic part is NULL. Chop it off,
2501                    We're going to send it via sendfile. */
2502                 req->out.vector_count -= 1;
2503         }
2504
2505         /*
2506          * We're done with this request -
2507          * move it off the "being processed" queue.
2508          */
2509         DLIST_REMOVE(xconn->smb2.requests, req);
2510
2511         req->queue_entry.mem_ctx = req;
2512         req->queue_entry.vector = req->out.vector;
2513         req->queue_entry.count = req->out.vector_count;
2514         DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry, NULL);
2515         xconn->smb2.send_queue_len++;
2516
2517         status = smbd_smb2_flush_send_queue(xconn);
2518         if (!NT_STATUS_IS_OK(status)) {
2519                 return status;
2520         }
2521
2522         return NT_STATUS_OK;
2523 }
2524
2525 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
2526
2527 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2528                                         struct tevent_immediate *im,
2529                                         void *private_data)
2530 {
2531         struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2532                                         struct smbd_smb2_request);
2533         struct smbd_server_connection *sconn = req->sconn;
2534         struct smbXsrv_connection *xconn = req->xconn;
2535         NTSTATUS status;
2536
2537         TALLOC_FREE(im);
2538
2539         if (DEBUGLEVEL >= 10) {
2540                 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2541                         req->current_idx, req->in.vector_count));
2542                 print_req_vectors(req);
2543         }
2544
2545         status = smbd_smb2_request_dispatch(req);
2546         if (!NT_STATUS_IS_OK(status)) {
2547                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2548                 return;
2549         }
2550
2551         status = smbd_smb2_request_next_incoming(xconn);
2552         if (!NT_STATUS_IS_OK(status)) {
2553                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2554                 return;
2555         }
2556 }
2557
2558 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2559                                    NTSTATUS status,
2560                                    DATA_BLOB body, DATA_BLOB *dyn,
2561                                    const char *location)
2562 {
2563         uint8_t *outhdr;
2564         struct iovec *outbody_v;
2565         struct iovec *outdyn_v;
2566         uint32_t next_command_ofs;
2567
2568         DEBUG(10,("smbd_smb2_request_done_ex: "
2569                   "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2570                   req->current_idx, nt_errstr(status), (unsigned int)body.length,
2571                   dyn ? "yes": "no",
2572                   (unsigned int)(dyn ? dyn->length : 0),
2573                   location));
2574
2575         if (body.length < 2) {
2576                 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2577         }
2578
2579         if ((body.length % 2) != 0) {
2580                 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2581         }
2582
2583         outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2584         outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2585         outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2586
2587         next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2588         SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2589
2590         outbody_v->iov_base = (void *)body.data;
2591         outbody_v->iov_len = body.length;
2592
2593         if (dyn) {
2594                 outdyn_v->iov_base = (void *)dyn->data;
2595                 outdyn_v->iov_len = dyn->length;
2596         } else {
2597                 outdyn_v->iov_base = NULL;
2598                 outdyn_v->iov_len = 0;
2599         }
2600
2601         /* see if we need to recalculate the offset to the next response */
2602         if (next_command_ofs > 0) {
2603                 next_command_ofs  = SMB2_HDR_BODY;
2604                 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2605                 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2606         }
2607
2608         if ((next_command_ofs % 8) != 0) {
2609                 size_t pad_size = 8 - (next_command_ofs % 8);
2610                 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2611                         /*
2612                          * if the dyn buffer is empty
2613                          * we can use it to add padding
2614                          */
2615                         uint8_t *pad;
2616
2617                         pad = talloc_zero_array(req,
2618                                                 uint8_t, pad_size);
2619                         if (pad == NULL) {
2620                                 return smbd_smb2_request_error(req,
2621                                                 NT_STATUS_NO_MEMORY);
2622                         }
2623
2624                         outdyn_v->iov_base = (void *)pad;
2625                         outdyn_v->iov_len = pad_size;
2626                 } else {
2627                         /*
2628                          * For now we copy the dynamic buffer
2629                          * and add the padding to the new buffer
2630                          */
2631                         size_t old_size;
2632                         uint8_t *old_dyn;
2633                         size_t new_size;
2634                         uint8_t *new_dyn;
2635
2636                         old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2637                         old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2638
2639                         new_size = old_size + pad_size;
2640                         new_dyn = talloc_zero_array(req,
2641                                                uint8_t, new_size);
2642                         if (new_dyn == NULL) {
2643                                 return smbd_smb2_request_error(req,
2644                                                 NT_STATUS_NO_MEMORY);
2645                         }
2646
2647                         memcpy(new_dyn, old_dyn, old_size);
2648                         memset(new_dyn + old_size, 0, pad_size);
2649
2650                         outdyn_v->iov_base = (void *)new_dyn;
2651                         outdyn_v->iov_len = new_size;
2652                 }
2653                 next_command_ofs += pad_size;
2654         }
2655
2656         SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2657
2658         return smbd_smb2_request_reply(req);
2659 }
2660
2661 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2662                                     NTSTATUS status,
2663                                     DATA_BLOB *info,
2664                                     const char *location)
2665 {
2666         struct smbXsrv_connection *xconn = req->xconn;
2667         DATA_BLOB body;
2668         DATA_BLOB _dyn;
2669         uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2670         size_t unread_bytes = smbd_smb2_unread_bytes(req);
2671
2672         DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2673                   req->current_idx, nt_errstr(status), info ? " +info" : "",
2674                   location));
2675
2676         if (unread_bytes) {
2677                 /* Recvfile error. Drain incoming socket. */
2678                 size_t ret;
2679
2680                 errno = 0;
2681                 ret = drain_socket(xconn->transport.sock, unread_bytes);
2682                 if (ret != unread_bytes) {
2683                         NTSTATUS error;
2684
2685                         if (errno == 0) {
2686                                 error = NT_STATUS_IO_DEVICE_ERROR;
2687                         } else {
2688                                 error = map_nt_error_from_unix_common(errno);
2689                         }
2690
2691                         DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2692                                   "ret[%u] errno[%d] => %s\n",
2693                                   (unsigned)unread_bytes,
2694                                   (unsigned)ret, errno, nt_errstr(error)));
2695                         return error;
2696                 }
2697         }
2698
2699         body.data = outhdr + SMB2_HDR_BODY;
2700         body.length = 8;
2701         SSVAL(body.data, 0, 9);
2702
2703         if (info) {
2704                 SIVAL(body.data, 0x04, info->length);
2705         } else {
2706                 /* Allocated size of req->out.vector[i].iov_base
2707                  * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2708                  * 1 byte without having to do an alloc.
2709                  */
2710                 info = &_dyn;
2711                 info->data = ((uint8_t *)outhdr) +
2712                         OUTVEC_ALLOC_SIZE - 1;
2713                 info->length = 1;
2714                 SCVAL(info->data, 0, 0);
2715         }
2716
2717         /*
2718          * Note: Even if there is an error, continue to process the request.
2719          * per MS-SMB2.
2720          */
2721
2722         return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2723 }
2724
2725
2726 struct smbd_smb2_send_break_state {
2727         struct smbd_server_connection *sconn;
2728         struct smbd_smb2_send_queue queue_entry;
2729         uint8_t nbt_hdr[NBT_HDR_SIZE];
2730         uint8_t tf[SMB2_TF_HDR_SIZE];
2731         uint8_t hdr[SMB2_HDR_BODY];
2732         struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2733         uint8_t body[1];
2734 };
2735
2736 static NTSTATUS smbd_smb2_send_break(struct smbd_server_connection *sconn,
2737                                      struct smbXsrv_session *session,
2738                                      struct smbXsrv_tcon *tcon,
2739                                      const uint8_t *body,
2740                                      size_t body_len)
2741 {
2742         struct smbd_smb2_send_break_state *state;
2743         struct smbXsrv_connection *xconn = sconn->conn;
2744         bool do_encryption = session->global->encryption_required;
2745         uint64_t nonce_high = 0;
2746         uint64_t nonce_low = 0;
2747         NTSTATUS status;
2748         size_t statelen;
2749
2750         if (tcon->global->encryption_required) {
2751                 do_encryption = true;
2752         }
2753
2754         statelen = offsetof(struct smbd_smb2_send_break_state, body) +
2755                 body_len;
2756
2757         state = talloc_zero_size(sconn, statelen);
2758         if (state == NULL) {
2759                 return NT_STATUS_NO_MEMORY;
2760         }
2761         talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
2762         state->sconn = sconn;
2763
2764         if (do_encryption) {
2765                 nonce_high = session->nonce_high;
2766                 nonce_low = session->nonce_low;
2767
2768                 session->nonce_low += 1;
2769                 if (session->nonce_low == 0) {
2770                         session->nonce_low += 1;
2771                         session->nonce_high += 1;
2772                 }
2773         }
2774
2775         SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2776         SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
2777         SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
2778         SBVAL(state->tf, SMB2_TF_SESSION_ID, session->global->session_wire_id);
2779
2780         SIVAL(state->hdr, 0,                            SMB2_MAGIC);
2781         SSVAL(state->hdr, SMB2_HDR_LENGTH,              SMB2_HDR_BODY);
2782         SSVAL(state->hdr, SMB2_HDR_EPOCH,               0);
2783         SIVAL(state->hdr, SMB2_HDR_STATUS,              0);
2784         SSVAL(state->hdr, SMB2_HDR_OPCODE,              SMB2_OP_BREAK);
2785         SSVAL(state->hdr, SMB2_HDR_CREDIT,              0);
2786         SIVAL(state->hdr, SMB2_HDR_FLAGS,               SMB2_HDR_FLAG_REDIRECT);
2787         SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND,        0);
2788         SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID,          UINT64_MAX);
2789         SIVAL(state->hdr, SMB2_HDR_PID,         0);
2790         SIVAL(state->hdr, SMB2_HDR_TID,         0);
2791         SBVAL(state->hdr, SMB2_HDR_SESSION_ID,          0);
2792         memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
2793
2794         state->vector[0] = (struct iovec) {
2795                 .iov_base = state->nbt_hdr,
2796                 .iov_len  = sizeof(state->nbt_hdr)
2797         };
2798
2799         if (do_encryption) {
2800                 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2801                         .iov_base = state->tf,
2802                         .iov_len  = sizeof(state->tf)
2803                 };
2804         } else {
2805                 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2806                         .iov_base = NULL,
2807                         .iov_len  = 0
2808                 };
2809         }
2810
2811         state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
2812                 .iov_base = state->hdr,
2813                 .iov_len  = sizeof(state->hdr)
2814         };
2815
2816         memcpy(state->body, body, body_len);
2817
2818         state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
2819                 .iov_base = state->body,
2820                 .iov_len  = body_len /* no sizeof(state->body) .. :-) */
2821         };
2822
2823         /*
2824          * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
2825          */
2826
2827         smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2828
2829         if (do_encryption) {
2830                 DATA_BLOB encryption_key = session->global->encryption_key;
2831
2832                 status = smb2_signing_encrypt_pdu(encryption_key,
2833                                         xconn->protocol,
2834                                         &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2835                                         SMBD_SMB2_NUM_IOV_PER_REQ);
2836                 if (!NT_STATUS_IS_OK(status)) {
2837                         return status;
2838                 }
2839         }
2840
2841         state->queue_entry.mem_ctx = state;
2842         state->queue_entry.vector = state->vector;
2843         state->queue_entry.count = ARRAY_SIZE(state->vector);
2844         DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
2845         xconn->smb2.send_queue_len++;
2846
2847         status = smbd_smb2_flush_send_queue(xconn);
2848         if (!NT_STATUS_IS_OK(status)) {
2849                 return status;
2850         }
2851
2852         return NT_STATUS_OK;
2853 }
2854
2855 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2856                                      struct smbXsrv_session *session,
2857                                      struct smbXsrv_tcon *tcon,
2858                                      struct smbXsrv_open *op,
2859                                      uint8_t oplock_level)
2860 {
2861         uint8_t body[0x18];
2862
2863         SSVAL(body, 0x00, sizeof(body));
2864         SCVAL(body, 0x02, oplock_level);
2865         SCVAL(body, 0x03, 0);           /* reserved */
2866         SIVAL(body, 0x04, 0);           /* reserved */
2867         SBVAL(body, 0x08, op->global->open_persistent_id);
2868         SBVAL(body, 0x10, op->global->open_volatile_id);
2869
2870         return smbd_smb2_send_break(sconn, session, tcon, body, sizeof(body));
2871 }
2872
2873 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2874 {
2875         NTSTATUS status;
2876         uint32_t flags;
2877         uint64_t file_id_persistent;
2878         uint64_t file_id_volatile;
2879         struct smbXsrv_open *op = NULL;
2880         struct files_struct *fsp = NULL;
2881         const uint8_t *body = NULL;
2882
2883         /*
2884          * This is only called with a pktbuf
2885          * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
2886          * bytes
2887          */
2888
2889         if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
2890                 /* Transform header. Cannot recvfile. */
2891                 return false;
2892         }
2893         if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
2894                 /* Not SMB2. Normal error path will cope. */
2895                 return false;
2896         }
2897         if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
2898                 /* Not SMB2. Normal error path will cope. */
2899                 return false;
2900         }
2901         if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
2902                 /* Needs to be a WRITE. */
2903                 return false;
2904         }
2905         if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
2906                 /* Chained. Cannot recvfile. */
2907                 return false;
2908         }
2909         flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
2910         if (flags & SMB2_HDR_FLAG_CHAINED) {
2911                 /* Chained. Cannot recvfile. */
2912                 return false;
2913         }
2914         if (flags & SMB2_HDR_FLAG_SIGNED) {
2915                 /* Signed. Cannot recvfile. */
2916                 return false;
2917         }
2918
2919         body = &state->pktbuf[SMB2_HDR_BODY];
2920
2921         file_id_persistent      = BVAL(body, 0x10);
2922         file_id_volatile        = BVAL(body, 0x18);
2923
2924         status = smb2srv_open_lookup(state->req->sconn->conn,
2925                                      file_id_persistent,
2926                                      file_id_volatile,
2927                                      0, /* now */
2928                                      &op);
2929         if (!NT_STATUS_IS_OK(status)) {
2930                 return false;
2931         }
2932
2933         fsp = op->compat;
2934         if (fsp == NULL) {
2935                 return false;
2936         }
2937         if (fsp->conn == NULL) {
2938                 return false;
2939         }
2940
2941         if (IS_IPC(fsp->conn)) {
2942                 return false;
2943         }
2944         if (IS_PRINT(fsp->conn)) {
2945                 return false;
2946         }
2947
2948         DEBUG(10,("Doing recvfile write len = %u\n",
2949                 (unsigned int)(state->pktfull - state->pktlen)));
2950
2951         return true;
2952 }
2953
2954 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
2955 {
2956         struct smbd_server_connection *sconn = xconn->sconn;
2957         struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
2958         size_t max_send_queue_len;
2959         size_t cur_send_queue_len;
2960
2961         if (!NT_STATUS_IS_OK(xconn->transport.status)) {
2962                 /*
2963                  * we're not supposed to do any io
2964                  */
2965                 return NT_STATUS_OK;
2966         }
2967
2968         if (state->req != NULL) {
2969                 /*
2970                  * if there is already a tstream_readv_pdu
2971                  * pending, we are done.
2972                  */
2973                 return NT_STATUS_OK;
2974         }
2975
2976         max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
2977         cur_send_queue_len = xconn->smb2.send_queue_len;
2978
2979         if (cur_send_queue_len > max_send_queue_len) {
2980                 /*
2981                  * if we have a lot of requests to send,
2982                  * we wait until they are on the wire until we
2983                  * ask for the next request.
2984                  */
2985                 return NT_STATUS_OK;
2986         }
2987
2988         /* ask for the next request */
2989         ZERO_STRUCTP(state);
2990         state->req = smbd_smb2_request_allocate(xconn);
2991         if (state->req == NULL) {
2992                 return NT_STATUS_NO_MEMORY;
2993         }
2994         state->req->sconn = sconn;
2995         state->req->xconn = xconn;
2996         state->min_recv_size = lp_min_receive_file_size();
2997
2998         TEVENT_FD_READABLE(xconn->transport.fde);
2999
3000         return NT_STATUS_OK;
3001 }
3002
3003 void smbd_smb2_first_negprot(struct smbXsrv_connection *xconn,
3004                              uint8_t *inbuf, size_t size)
3005 {
3006         struct smbd_server_connection *sconn = xconn->sconn;
3007         NTSTATUS status;
3008         struct smbd_smb2_request *req = NULL;
3009
3010         DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3011                  (unsigned int)size));
3012
3013         status = smbd_initialize_smb2(xconn);
3014         if (!NT_STATUS_IS_OK(status)) {
3015                 smbd_server_connection_terminate(sconn, nt_errstr(status));
3016                 return;
3017         }
3018
3019         status = smbd_smb2_request_create(xconn, inbuf, size, &req);
3020         if (!NT_STATUS_IS_OK(status)) {
3021                 smbd_server_connection_terminate(sconn, nt_errstr(status));
3022                 return;
3023         }
3024
3025         status = smbd_smb2_request_validate(req);
3026         if (!NT_STATUS_IS_OK(status)) {
3027                 smbd_server_connection_terminate(sconn, nt_errstr(status));
3028                 return;
3029         }
3030
3031         status = smbd_smb2_request_setup_out(req);
3032         if (!NT_STATUS_IS_OK(status)) {
3033                 smbd_server_connection_terminate(sconn, nt_errstr(status));
3034                 return;
3035         }
3036
3037         status = smbd_smb2_request_dispatch(req);
3038         if (!NT_STATUS_IS_OK(status)) {
3039                 smbd_server_connection_terminate(sconn, nt_errstr(status));
3040                 return;
3041         }
3042
3043         status = smbd_smb2_request_next_incoming(xconn);
3044         if (!NT_STATUS_IS_OK(status)) {
3045                 smbd_server_connection_terminate(sconn, nt_errstr(status));
3046                 return;
3047         }
3048
3049         sconn->num_requests++;
3050 }
3051
3052 static int socket_error_from_errno(int ret,
3053                                    int sys_errno,
3054                                    bool *retry)
3055 {
3056         *retry = false;
3057
3058         if (ret >= 0) {
3059                 return 0;
3060         }
3061
3062         if (ret != -1) {
3063                 return EIO;
3064         }
3065
3066         if (sys_errno == 0) {
3067                 return EIO;
3068         }
3069
3070         if (sys_errno == EINTR) {
3071                 *retry = true;
3072                 return sys_errno;
3073         }
3074
3075         if (sys_errno == EINPROGRESS) {
3076                 *retry = true;
3077                 return sys_errno;
3078         }
3079
3080         if (sys_errno == EAGAIN) {
3081                 *retry = true;
3082                 return sys_errno;
3083         }
3084
3085         /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3086         if (sys_errno == ENOMEM) {
3087                 *retry = true;
3088                 return sys_errno;
3089         }
3090
3091 #ifdef EWOULDBLOCK
3092 #if EWOULDBLOCK != EAGAIN
3093         if (sys_errno == EWOULDBLOCK) {
3094                 *retry = true;
3095                 return sys_errno;
3096         }
3097 #endif
3098 #endif
3099
3100         return sys_errno;
3101 }
3102
3103 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3104 {
3105         int ret;
3106         int err;
3107         bool retry;
3108
3109         if (xconn->smb2.send_queue == NULL) {
3110                 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3111                 return NT_STATUS_OK;
3112         }
3113
3114         while (xconn->smb2.send_queue != NULL) {
3115                 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3116
3117                 if (e->sendfile_header != NULL) {
3118                         size_t size = 0;
3119                         size_t i = 0;
3120                         uint8_t *buf;
3121
3122                         for (i=0; i < e->count; i++) {
3123                                 size += e->vector[i].iov_len;
3124                         }
3125
3126                         if (size <= e->sendfile_header->length) {
3127                                 buf = e->sendfile_header->data;
3128                         } else {
3129                                 buf = talloc_array(e->mem_ctx, uint8_t, size);
3130                                 if (buf == NULL) {
3131                                         return NT_STATUS_NO_MEMORY;
3132                                 }
3133                         }
3134
3135                         size = 0;
3136                         for (i=0; i < e->count; i++) {
3137                                 memcpy(buf+size,
3138                                        e->vector[i].iov_base,
3139                                        e->vector[i].iov_len);
3140                                 size += e->vector[i].iov_len;
3141                         }
3142
3143                         e->sendfile_header->data = buf;
3144                         e->sendfile_header->length = size;
3145                         e->count = 0;
3146
3147                         xconn->smb2.send_queue_len--;
3148                         DLIST_REMOVE(xconn->smb2.send_queue, e);
3149                         /*
3150                          * This triggers the sendfile path via
3151                          * the destructor.
3152                          */
3153                         talloc_free(e->mem_ctx);
3154                         continue;
3155                 }
3156
3157                 ret = writev(xconn->transport.sock, e->vector, e->count);
3158                 if (ret == 0) {
3159                         /* propagate end of file */
3160                         return NT_STATUS_INTERNAL_ERROR;
3161                 }
3162                 err = socket_error_from_errno(ret, errno, &retry);
3163                 if (retry) {
3164                         /* retry later */
3165                         TEVENT_FD_WRITEABLE(xconn->transport.fde);
3166                         return NT_STATUS_OK;
3167                 }
3168                 if (err != 0) {
3169                         return map_nt_error_from_unix_common(err);
3170                 }
3171                 while (ret > 0) {
3172                         if (ret < e->vector[0].iov_len) {
3173                                 uint8_t *base;
3174                                 base = (uint8_t *)e->vector[0].iov_base;
3175                                 base += ret;
3176                                 e->vector[0].iov_base = (void *)base;
3177                                 e->vector[0].iov_len -= ret;
3178                                 break;
3179                         }
3180                         ret -= e->vector[0].iov_len;
3181                         e->vector += 1;
3182                         e->count -= 1;
3183                 }
3184
3185                 /*
3186                  * there're maybe some empty vectors at the end
3187                  * which we need to skip, otherwise we would get
3188                  * ret == 0 from the readv() call and return EPIPE
3189                  */
3190                 while (e->count > 0) {
3191                         if (e->vector[0].iov_len > 0) {
3192                                 break;
3193                         }
3194                         e->vector += 1;
3195                         e->count -= 1;
3196                 }
3197
3198                 if (e->count > 0) {
3199                         /* we have more to write */
3200                         TEVENT_FD_WRITEABLE(xconn->transport.fde);
3201                         return NT_STATUS_OK;
3202                 }
3203
3204                 xconn->smb2.send_queue_len--;
3205                 DLIST_REMOVE(xconn->smb2.send_queue, e);
3206                 talloc_free(e->mem_ctx);
3207         }
3208
3209         return NT_STATUS_OK;
3210 }
3211
3212 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3213                                      uint16_t fde_flags)
3214 {
3215         struct smbd_server_connection *sconn = xconn->sconn;
3216         struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3217         struct smbd_smb2_request *req = NULL;
3218         size_t min_recvfile_size = UINT32_MAX;
3219         int ret;
3220         int err;
3221         bool retry;
3222         NTSTATUS status;
3223         NTTIME now;
3224
3225         if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3226                 /*
3227                  * we're not supposed to do any io
3228                  */
3229                 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3230                 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3231                 return NT_STATUS_OK;
3232         }
3233
3234         if (fde_flags & TEVENT_FD_WRITE) {
3235                 status = smbd_smb2_flush_send_queue(xconn);
3236                 if (!NT_STATUS_IS_OK(status)) {
3237                         return status;
3238                 }
3239         }
3240
3241         if (!(fde_flags & TEVENT_FD_READ)) {
3242                 return NT_STATUS_OK;
3243         }
3244
3245         if (state->req == NULL) {
3246                 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3247                 return NT_STATUS_OK;
3248         }
3249
3250 again:
3251         if (!state->hdr.done) {
3252                 state->hdr.done = true;
3253
3254                 state->vector.iov_base = (void *)state->hdr.nbt;
3255                 state->vector.iov_len = NBT_HDR_SIZE;
3256         }
3257
3258         ret = readv(xconn->transport.sock, &state->vector, 1);
3259         if (ret == 0) {
3260                 /* propagate end of file */
3261                 return NT_STATUS_END_OF_FILE;
3262         }
3263         err = socket_error_from_errno(ret, errno, &retry);
3264         if (retry) {
3265                 /* retry later */
3266                 TEVENT_FD_READABLE(xconn->transport.fde);
3267                 return NT_STATUS_OK;
3268         }
3269         if (err != 0) {
3270                 return map_nt_error_from_unix_common(err);
3271         }
3272
3273         if (ret < state->vector.iov_len) {
3274                 uint8_t *base;
3275                 base = (uint8_t *)state->vector.iov_base;
3276                 base += ret;
3277                 state->vector.iov_base = (void *)base;
3278                 state->vector.iov_len -= ret;
3279                 /* we have more to read */
3280                 TEVENT_FD_READABLE(xconn->transport.fde);
3281                 return NT_STATUS_OK;
3282         }
3283
3284         if (state->pktlen > 0) {
3285                 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3286                         /*
3287                          * Not a possible receivefile write.
3288                          * Read the rest of the data.
3289                          */
3290                         state->doing_receivefile = false;
3291
3292                         state->pktbuf = talloc_realloc(state->req,
3293                                                        state->pktbuf,
3294                                                        uint8_t,
3295                                                        state->pktfull);
3296                         if (state->pktbuf == NULL) {
3297                                 return NT_STATUS_NO_MEMORY;
3298                         }
3299
3300                         state->vector.iov_base = (void *)(state->pktbuf +
3301                                 state->pktlen);
3302                         state->vector.iov_len = (state->pktfull -
3303                                 state->pktlen);
3304
3305                         state->pktlen = state->pktfull;
3306                         goto again;
3307                 }
3308
3309                 /*
3310                  * Either this is a receivefile write so we've
3311                  * done a short read, or if not we have all the data.
3312                  */
3313                 goto got_full;
3314         }
3315
3316         /*
3317          * Now we analyze the NBT header
3318          */
3319         if (state->hdr.nbt[0] != 0x00) {
3320                 state->min_recv_size = 0;
3321         }
3322         state->pktfull = smb2_len(state->hdr.nbt);
3323         if (state->pktfull == 0) {
3324                 goto got_full;
3325         }
3326
3327         if (state->min_recv_size != 0) {
3328                 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3329                 min_recvfile_size += state->min_recv_size;
3330         }
3331
3332         if (state->pktfull > min_recvfile_size) {
3333                 /*
3334                  * Might be a receivefile write. Read the SMB2 HEADER +
3335                  * SMB2_WRITE header first. Set 'doing_receivefile'
3336                  * as we're *attempting* receivefile write. If this
3337                  * turns out not to be a SMB2_WRITE request or otherwise
3338                  * not suitable then we'll just read the rest of the data
3339                  * the next time this function is called.
3340                  */
3341                 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3342                 state->doing_receivefile = true;
3343         } else {
3344                 state->pktlen = state->pktfull;
3345         }
3346
3347         state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3348         if (state->pktbuf == NULL) {
3349                 return NT_STATUS_NO_MEMORY;
3350         }
3351
3352         state->vector.iov_base = (void *)state->pktbuf;
3353         state->vector.iov_len = state->pktlen;
3354
3355         goto again;
3356
3357 got_full:
3358
3359         if (state->hdr.nbt[0] != 0x00) {
3360                 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3361                          state->hdr.nbt[0]));
3362
3363                 req = state->req;
3364                 ZERO_STRUCTP(state);
3365                 state->req = req;
3366                 state->min_recv_size = lp_min_receive_file_size();
3367                 req = NULL;
3368                 goto again;
3369         }
3370
3371         req = state->req;
3372         state->req = NULL;
3373
3374         req->request_time = timeval_current();
3375         now = timeval_to_nttime(&req->request_time);
3376
3377         status = smbd_smb2_inbuf_parse_compound(xconn,
3378                                                 now,
3379                                                 state->pktbuf,
3380                                                 state->pktlen,
3381                                                 req,
3382                                                 &req->in.vector,
3383                                                 &req->in.vector_count);
3384         if (!NT_STATUS_IS_OK(status)) {
3385                 return status;
3386         }
3387
3388         if (state->doing_receivefile) {
3389                 req->smb1req = talloc_zero(req, struct smb_request);
3390                 if (req->smb1req == NULL) {
3391                         return NT_STATUS_NO_MEMORY;
3392                 }
3393                 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3394         }
3395
3396         ZERO_STRUCTP(state);
3397
3398         req->current_idx = 1;
3399
3400         DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3401                  req->current_idx, req->in.vector_count));
3402
3403         status = smbd_smb2_request_validate(req);
3404         if (!NT_STATUS_IS_OK(status)) {
3405                 return status;
3406         }
3407
3408         status = smbd_smb2_request_setup_out(req);
3409         if (!NT_STATUS_IS_OK(status)) {
3410                 return status;
3411         }
3412
3413         status = smbd_smb2_request_dispatch(req);
3414         if (!NT_STATUS_IS_OK(status)) {
3415                 return status;
3416         }
3417
3418         sconn->num_requests++;
3419
3420         /* The timeout_processing function isn't run nearly
3421            often enough to implement 'max log size' without
3422            overrunning the size of the file by many megabytes.
3423            This is especially true if we are running at debug
3424            level 10.  Checking every 50 SMB2s is a nice
3425            tradeoff of performance vs log file size overrun. */
3426
3427         if ((sconn->num_requests % 50) == 0 &&
3428             need_to_check_log_size()) {
3429                 change_to_root_user();
3430                 check_log_size();
3431         }
3432
3433         status = smbd_smb2_request_next_incoming(xconn);
3434         if (!NT_STATUS_IS_OK(status)) {
3435                 return status;
3436         }
3437
3438         return NT_STATUS_OK;
3439 }
3440
3441 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3442                                          struct tevent_fd *fde,
3443                                          uint16_t flags,
3444                                          void *private_data)
3445 {
3446         struct smbXsrv_connection *xconn =
3447                 talloc_get_type_abort(private_data,
3448                 struct smbXsrv_connection);
3449         struct smbd_server_connection *sconn = xconn->sconn;
3450         NTSTATUS status;
3451
3452         status = smbd_smb2_io_handler(xconn, flags);
3453         if (!NT_STATUS_IS_OK(status)) {
3454                 smbd_server_connection_terminate(sconn, nt_errstr(status));
3455                 return;
3456         }
3457 }