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