s3:smb2_server: only allocate the required buffer in the smb2 recvfile() code path
[mat/samba.git] / source3 / smbd / smb2_server.c
1 /*
2    Unix SMB/CIFS implementation.
3    Core SMB2 server
4
5    Copyright (C) Stefan Metzmacher 2009
6    Copyright (C) Jeremy Allison 2010
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "smbd/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, NULL, size);
932 }
933
934 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
935 {
936         TALLOC_CTX *mem_ctx;
937         struct iovec *vector;
938         int count;
939         int idx;
940
941         count = req->in.vector_count;
942         if (count <= ARRAY_SIZE(req->out._vector)) {
943                 mem_ctx = req;
944                 vector = req->out._vector;
945         } else {
946                 vector = talloc_zero_array(req, struct iovec, count);
947                 if (vector == NULL) {
948                         return NT_STATUS_NO_MEMORY;
949                 }
950                 mem_ctx = vector;
951         }
952
953         vector[0].iov_base      = req->out.nbt_hdr;
954         vector[0].iov_len       = 4;
955         SIVAL(req->out.nbt_hdr, 0, 0);
956
957         for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
958                 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
959                 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
960                 uint8_t *outhdr = NULL;
961                 uint8_t *outbody = NULL;
962                 uint32_t next_command_ofs = 0;
963                 struct iovec *current = &vector[idx];
964
965                 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
966                         /* we have a next command -
967                          * setup for the error case. */
968                         next_command_ofs = SMB2_HDR_BODY + 9;
969                 }
970
971                 if (idx == 1) {
972                         outhdr = req->out._hdr;
973                 } else {
974                         outhdr = talloc_zero_array(mem_ctx, uint8_t,
975                                                    OUTVEC_ALLOC_SIZE);
976                         if (outhdr == NULL) {
977                                 return NT_STATUS_NO_MEMORY;
978                         }
979                 }
980
981                 outbody = outhdr + SMB2_HDR_BODY;
982
983                 /*
984                  * SMBD_SMB2_TF_IOV_OFS might be used later
985                  */
986                 current[SMBD_SMB2_TF_IOV_OFS].iov_base   = NULL;
987                 current[SMBD_SMB2_TF_IOV_OFS].iov_len    = 0;
988
989                 current[SMBD_SMB2_HDR_IOV_OFS].iov_base  = (void *)outhdr;
990                 current[SMBD_SMB2_HDR_IOV_OFS].iov_len   = SMB2_HDR_BODY;
991
992                 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
993                 current[SMBD_SMB2_BODY_IOV_OFS].iov_len  = 8;
994
995                 current[SMBD_SMB2_DYN_IOV_OFS].iov_base  = NULL;
996                 current[SMBD_SMB2_DYN_IOV_OFS].iov_len   = 0;
997
998                 /* setup the SMB2 header */
999                 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID,     SMB2_MAGIC);
1000                 SSVAL(outhdr, SMB2_HDR_LENGTH,          SMB2_HDR_BODY);
1001                 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1002                       SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1003                 SIVAL(outhdr, SMB2_HDR_STATUS,
1004                       NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1005                 SSVAL(outhdr, SMB2_HDR_OPCODE,
1006                       SVAL(inhdr, SMB2_HDR_OPCODE));
1007                 SIVAL(outhdr, SMB2_HDR_FLAGS,
1008                       IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1009                 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND,    next_command_ofs);
1010                 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1011                       BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1012                 SIVAL(outhdr, SMB2_HDR_PID,
1013                       IVAL(inhdr, SMB2_HDR_PID));
1014                 SIVAL(outhdr, SMB2_HDR_TID,
1015                       IVAL(inhdr, SMB2_HDR_TID));
1016                 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1017                       BVAL(inhdr, SMB2_HDR_SESSION_ID));
1018                 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1019                        inhdr + SMB2_HDR_SIGNATURE, 16);
1020
1021                 /* setup error body header */
1022                 SSVAL(outbody, 0x00, 0x08 + 1);
1023                 SSVAL(outbody, 0x02, 0);
1024                 SIVAL(outbody, 0x04, 0);
1025         }
1026
1027         req->out.vector = vector;
1028         req->out.vector_count = count;
1029
1030         /* setup the length of the NBT packet */
1031         smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1032
1033         DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
1034
1035         return NT_STATUS_OK;
1036 }
1037
1038 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
1039                                          const char *reason,
1040                                          const char *location)
1041 {
1042         DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1043                   reason, location));
1044         exit_server_cleanly(reason);
1045 }
1046
1047 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1048                         struct iovec *outvec,
1049                         const struct iovec *srcvec)
1050 {
1051         const uint8_t *srctf;
1052         size_t srctf_len;
1053         const uint8_t *srchdr;
1054         size_t srchdr_len;
1055         const uint8_t *srcbody;
1056         size_t srcbody_len;
1057         const uint8_t *expected_srcbody;
1058         const uint8_t *srcdyn;
1059         size_t srcdyn_len;
1060         const uint8_t *expected_srcdyn;
1061         uint8_t *dsttf;
1062         uint8_t *dsthdr;
1063         uint8_t *dstbody;
1064         uint8_t *dstdyn;
1065
1066         srctf  = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1067         srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1068         srchdr  = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1069         srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1070         srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1071         srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1072         expected_srcbody = srchdr + SMB2_HDR_BODY;
1073         srcdyn  = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1074         srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1075         expected_srcdyn = srcbody + 8;
1076
1077         if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1078                 return false;
1079         }
1080
1081         if (srchdr_len != SMB2_HDR_BODY) {
1082                 return false;
1083         }
1084
1085         if (srctf_len == SMB2_TF_HDR_SIZE) {
1086                 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1087                 if (dsttf == NULL) {
1088                         return false;
1089                 }
1090         } else {
1091                 dsttf = NULL;
1092         }
1093         outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1094         outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1095
1096         /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1097          * be allocated with size OUTVEC_ALLOC_SIZE. */
1098
1099         dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1100         if (dsthdr == NULL) {
1101                 return false;
1102         }
1103         outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1104         outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1105
1106         /*
1107          * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1108          * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1109          * then duplicate this. Else use talloc_memdup().
1110          */
1111
1112         if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1113                 dstbody = dsthdr + SMB2_HDR_BODY;
1114         } else {
1115                 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1116                 if (dstbody == NULL) {
1117                         return false;
1118                 }
1119         }
1120         outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1121         outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1122
1123         /*
1124          * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1125          * pointing to
1126          * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1127          * then duplicate this. Else use talloc_memdup().
1128          */
1129
1130         if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1131                 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1132         } else if (srcdyn == NULL) {
1133                 dstdyn = NULL;
1134         } else {
1135                 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1136                 if (dstdyn == NULL) {
1137                         return false;
1138                 }
1139         }
1140         outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1141         outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1142
1143         return true;
1144 }
1145
1146 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1147 {
1148         struct smbd_smb2_request *newreq = NULL;
1149         struct iovec *outvec = NULL;
1150         int count = req->out.vector_count;
1151         int i;
1152
1153         newreq = smbd_smb2_request_allocate(req->sconn);
1154         if (!newreq) {
1155                 return NULL;
1156         }
1157
1158         newreq->sconn = req->sconn;
1159         newreq->session = req->session;
1160         newreq->do_encryption = req->do_encryption;
1161         newreq->do_signing = req->do_signing;
1162         newreq->current_idx = req->current_idx;
1163
1164         outvec = talloc_zero_array(newreq, struct iovec, count);
1165         if (!outvec) {
1166                 TALLOC_FREE(newreq);
1167                 return NULL;
1168         }
1169         newreq->out.vector = outvec;
1170         newreq->out.vector_count = count;
1171
1172         /* Setup the outvec's identically to req. */
1173         outvec[0].iov_base = newreq->out.nbt_hdr;
1174         outvec[0].iov_len = 4;
1175         memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1176
1177         /* Setup the vectors identically to the ones in req. */
1178         for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1179                 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1180                         break;
1181                 }
1182         }
1183
1184         if (i < count) {
1185                 /* Alloc failed. */
1186                 TALLOC_FREE(newreq);
1187                 return NULL;
1188         }
1189
1190         smb2_setup_nbt_length(newreq->out.vector,
1191                 newreq->out.vector_count);
1192
1193         return newreq;
1194 }
1195
1196 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1197 {
1198         struct smbd_server_connection *sconn = req->sconn;
1199         struct smbXsrv_connection *conn = req->sconn->conn;
1200         int first_idx = 1;
1201         struct iovec *firsttf = NULL;
1202         struct iovec *outhdr_v = NULL;
1203         uint8_t *outhdr = NULL;
1204         struct smbd_smb2_request *nreq = NULL;
1205         NTSTATUS status;
1206
1207         /* Create a new smb2 request we'll use
1208            for the interim return. */
1209         nreq = dup_smb2_req(req);
1210         if (!nreq) {
1211                 return NT_STATUS_NO_MEMORY;
1212         }
1213
1214         /* Lose the last X out vectors. They're the
1215            ones we'll be using for the async reply. */
1216         nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1217
1218         smb2_setup_nbt_length(nreq->out.vector,
1219                 nreq->out.vector_count);
1220
1221         /* Step back to the previous reply. */
1222         nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1223         firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1224         outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1225         outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1226         /* And end the chain. */
1227         SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1228
1229         /* Calculate outgoing credits */
1230         smb2_calculate_credits(req, nreq);
1231
1232         if (DEBUGLEVEL >= 10) {
1233                 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1234                         (unsigned int)nreq->current_idx );
1235                 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1236                         (unsigned int)nreq->out.vector_count );
1237                 print_req_vectors(nreq);
1238         }
1239
1240         /*
1241          * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1242          * we need to sign/encrypt here with the last/first key we remembered
1243          */
1244         if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1245                 status = smb2_signing_encrypt_pdu(req->first_key,
1246                                         conn->protocol,
1247                                         firsttf,
1248                                         nreq->out.vector_count - first_idx);
1249                 if (!NT_STATUS_IS_OK(status)) {
1250                         return status;
1251                 }
1252         } else if (req->last_key.length > 0) {
1253                 status = smb2_signing_sign_pdu(req->last_key,
1254                                                conn->protocol,
1255                                                outhdr_v,
1256                                                SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1257                 if (!NT_STATUS_IS_OK(status)) {
1258                         return status;
1259                 }
1260         }
1261
1262         nreq->queue_entry.mem_ctx = nreq;
1263         nreq->queue_entry.vector = nreq->out.vector;
1264         nreq->queue_entry.count = nreq->out.vector_count;
1265         DLIST_ADD_END(nreq->sconn->smb2.send_queue, &nreq->queue_entry, NULL);
1266         nreq->sconn->smb2.send_queue_len++;
1267
1268         status = smbd_smb2_io_handler(sconn, TEVENT_FD_WRITE);
1269         if (!NT_STATUS_IS_OK(status)) {
1270                 return status;
1271         }
1272
1273         return NT_STATUS_OK;
1274 }
1275
1276 struct smbd_smb2_request_pending_state {
1277         struct smbd_server_connection *sconn;
1278         struct smbd_smb2_send_queue queue_entry;
1279         uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1280         struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1281 };
1282
1283 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1284                                             struct tevent_timer *te,
1285                                             struct timeval current_time,
1286                                             void *private_data);
1287
1288 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1289                                          struct tevent_req *subreq,
1290                                          uint32_t defer_time)
1291 {
1292         NTSTATUS status;
1293         struct timeval defer_endtime;
1294         uint8_t *outhdr = NULL;
1295         uint32_t flags;
1296
1297         if (!tevent_req_is_in_progress(subreq)) {
1298                 /*
1299                  * This is a performance optimization,
1300                  * it avoids one tevent_loop iteration,
1301                  * which means we avoid one
1302                  * talloc_stackframe_pool/talloc_free pair.
1303                  */
1304                 tevent_req_notify_callback(subreq);
1305                 return NT_STATUS_OK;
1306         }
1307
1308         req->subreq = subreq;
1309         subreq = NULL;
1310
1311         if (req->async_te) {
1312                 /* We're already async. */
1313                 return NT_STATUS_OK;
1314         }
1315
1316         outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1317         flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1318         if (flags & SMB2_HDR_FLAG_ASYNC) {
1319                 /* We're already async. */
1320                 return NT_STATUS_OK;
1321         }
1322
1323         if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1324                 /*
1325                  * We're trying to go async in a compound
1326                  * request chain.
1327                  * This is only allowed for opens that
1328                  * cause an oplock break, otherwise it
1329                  * is not allowed. See [MS-SMB2].pdf
1330                  * note <194> on Section 3.3.5.2.7.
1331                  */
1332                 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1333
1334                 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1335                         /*
1336                          * Cancel the outstanding request.
1337                          */
1338                         bool ok = tevent_req_cancel(req->subreq);
1339                         if (ok) {
1340                                 return NT_STATUS_OK;
1341                         }
1342                         TALLOC_FREE(req->subreq);
1343                         return smbd_smb2_request_error(req,
1344                                 NT_STATUS_INTERNAL_ERROR);
1345                 }
1346         }
1347
1348         if (DEBUGLEVEL >= 10) {
1349                 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1350                         (unsigned int)req->current_idx );
1351                 print_req_vectors(req);
1352         }
1353
1354         if (req->current_idx > 1) {
1355                 /*
1356                  * We're going async in a compound
1357                  * chain after the first request has
1358                  * already been processed. Send an
1359                  * interim response containing the
1360                  * set of replies already generated.
1361                  */
1362                 int idx = req->current_idx;
1363
1364                 status = smb2_send_async_interim_response(req);
1365                 if (!NT_STATUS_IS_OK(status)) {
1366                         return status;
1367                 }
1368                 if (req->first_key.length > 0) {
1369                         data_blob_clear_free(&req->first_key);
1370                 }
1371
1372                 req->current_idx = 1;
1373
1374                 /*
1375                  * Re-arrange the in.vectors to remove what
1376                  * we just sent.
1377                  */
1378                 memmove(&req->in.vector[1],
1379                         &req->in.vector[idx],
1380                         sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1381                 req->in.vector_count = 1 + (req->in.vector_count - idx);
1382
1383                 /* Re-arrange the out.vectors to match. */
1384                 memmove(&req->out.vector[1],
1385                         &req->out.vector[idx],
1386                         sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1387                 req->out.vector_count = 1 + (req->out.vector_count - idx);
1388
1389                 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1390                         /*
1391                          * We only have one remaining request as
1392                          * we've processed everything else.
1393                          * This is no longer a compound request.
1394                          */
1395                         req->compound_related = false;
1396                         outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1397                         flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1398                         SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1399                 }
1400         }
1401         if (req->last_key.length > 0) {
1402                 data_blob_clear_free(&req->last_key);
1403         }
1404
1405         defer_endtime = timeval_current_ofs_usec(defer_time);
1406         req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1407                                          req, defer_endtime,
1408                                          smbd_smb2_request_pending_timer,
1409                                          req);
1410         if (req->async_te == NULL) {
1411                 return NT_STATUS_NO_MEMORY;
1412         }
1413
1414         return NT_STATUS_OK;
1415 }
1416
1417 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1418                                             struct tevent_timer *te,
1419                                             struct timeval current_time,
1420                                             void *private_data)
1421 {
1422         struct smbd_smb2_request *req =
1423                 talloc_get_type_abort(private_data,
1424                 struct smbd_smb2_request);
1425         struct smbd_server_connection *sconn = req->sconn;
1426         struct smbd_smb2_request_pending_state *state = NULL;
1427         uint8_t *outhdr = NULL;
1428         const uint8_t *inhdr = NULL;
1429         uint8_t *tf = NULL;
1430         size_t tf_len = 0;
1431         uint8_t *hdr = NULL;
1432         uint8_t *body = NULL;
1433         uint8_t *dyn = NULL;
1434         uint32_t flags = 0;
1435         uint64_t session_id = 0;
1436         uint64_t message_id = 0;
1437         uint64_t nonce_high = 0;
1438         uint64_t nonce_low = 0;
1439         uint64_t async_id = 0;
1440         NTSTATUS status;
1441
1442         TALLOC_FREE(req->async_te);
1443
1444         /* Ensure our final reply matches the interim one. */
1445         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1446         outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1447         flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1448         message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1449         session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1450
1451         async_id = message_id; /* keep it simple for now... */
1452
1453         SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1454         SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1455
1456         DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1457                 "going async\n",
1458                 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1459                 (unsigned long long)async_id ));
1460
1461         /*
1462          * What we send is identical to a smbd_smb2_request_error
1463          * packet with an error status of STATUS_PENDING. Make use
1464          * of this fact sometime when refactoring. JRA.
1465          */
1466
1467         state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1468         if (state == NULL) {
1469                 smbd_server_connection_terminate(req->sconn,
1470                                                  nt_errstr(NT_STATUS_NO_MEMORY));
1471                 return;
1472         }
1473         state->sconn = req->sconn;
1474
1475         tf = state->buf + NBT_HDR_SIZE;
1476         tf_len = SMB2_TF_HDR_SIZE;
1477
1478         hdr = tf + SMB2_TF_HDR_SIZE;
1479         body = hdr + SMB2_HDR_BODY;
1480         dyn = body + 8;
1481
1482         if (req->do_encryption) {
1483                 struct smbXsrv_session *x = req->session;
1484
1485                 nonce_high = x->nonce_high;
1486                 nonce_low = x->nonce_low;
1487
1488                 x->nonce_low += 1;
1489                 if (x->nonce_low == 0) {
1490                         x->nonce_low += 1;
1491                         x->nonce_high += 1;
1492                 }
1493         }
1494
1495         SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1496         SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1497         SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1498         SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1499
1500         SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1501         SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1502         SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1503         SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1504         SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1505
1506         SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1507         SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1508         SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1509         SBVAL(hdr, SMB2_HDR_PID, async_id);
1510         SBVAL(hdr, SMB2_HDR_SESSION_ID,
1511                 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1512         memcpy(hdr+SMB2_HDR_SIGNATURE,
1513                outhdr+SMB2_HDR_SIGNATURE, 16);
1514
1515         SSVAL(body, 0x00, 0x08 + 1);
1516
1517         SCVAL(body, 0x02, 0);
1518         SCVAL(body, 0x03, 0);
1519         SIVAL(body, 0x04, 0);
1520         /* Match W2K8R2... */
1521         SCVAL(dyn,  0x00, 0x21);
1522
1523         state->vector[0].iov_base = (void *)state->buf;
1524         state->vector[0].iov_len = NBT_HDR_SIZE;
1525
1526         if (req->do_encryption) {
1527                 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base   = tf;
1528                 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len    = tf_len;
1529         } else {
1530                 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base   = NULL;
1531                 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len    = 0;
1532         }
1533
1534         state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base  = hdr;
1535         state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len   = SMB2_HDR_BODY;
1536
1537         state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1538         state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len  = 8;
1539
1540         state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base  = dyn;
1541         state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len   = 1;
1542
1543         smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1544
1545         /* Ensure we correctly go through crediting. Grant
1546            the credits now, and zero credits on the final
1547            response. */
1548         smb2_set_operation_credit(req->sconn,
1549                         SMBD_SMB2_IN_HDR_IOV(req),
1550                         &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1551
1552         SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1553
1554         if (DEBUGLVL(10)) {
1555                 int i;
1556
1557                 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1558                         dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1559                                 (unsigned int)i,
1560                                 (unsigned int)ARRAY_SIZE(state->vector),
1561                                 (unsigned int)state->vector[i].iov_len);
1562                 }
1563         }
1564
1565         if (req->do_encryption) {
1566                 struct smbXsrv_session *x = req->session;
1567                 struct smbXsrv_connection *conn = x->connection;
1568                 DATA_BLOB encryption_key = x->global->encryption_key;
1569
1570                 status = smb2_signing_encrypt_pdu(encryption_key,
1571                                         conn->protocol,
1572                                         &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1573                                         SMBD_SMB2_NUM_IOV_PER_REQ);
1574                 if (!NT_STATUS_IS_OK(status)) {
1575                         smbd_server_connection_terminate(req->sconn,
1576                                                 nt_errstr(status));
1577                         return;
1578                 }
1579         } else if (req->do_signing) {
1580                 struct smbXsrv_session *x = req->session;
1581                 struct smbXsrv_connection *conn = x->connection;
1582                 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1583
1584                 status = smb2_signing_sign_pdu(signing_key,
1585                                         conn->protocol,
1586                                         &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1587                                         SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1588                 if (!NT_STATUS_IS_OK(status)) {
1589                         smbd_server_connection_terminate(req->sconn,
1590                                                 nt_errstr(status));
1591                         return;
1592                 }
1593         }
1594
1595         state->queue_entry.mem_ctx = state;
1596         state->queue_entry.vector = state->vector;
1597         state->queue_entry.count = ARRAY_SIZE(state->vector);
1598         DLIST_ADD_END(sconn->smb2.send_queue, &state->queue_entry, NULL);
1599         sconn->smb2.send_queue_len++;
1600
1601         status = smbd_smb2_io_handler(sconn, TEVENT_FD_WRITE);
1602         if (!NT_STATUS_IS_OK(status)) {
1603                 smbd_server_connection_terminate(sconn,
1604                                                  nt_errstr(status));
1605                 return;
1606         }
1607 }
1608
1609 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1610 {
1611         struct smbd_server_connection *sconn = req->sconn;
1612         struct smbd_smb2_request *cur;
1613         const uint8_t *inhdr;
1614         uint32_t flags;
1615         uint64_t search_message_id;
1616         uint64_t search_async_id;
1617         uint64_t found_id;
1618
1619         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1620
1621         flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1622         search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1623         search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1624
1625         /*
1626          * we don't need the request anymore
1627          * cancel requests never have a response
1628          */
1629         DLIST_REMOVE(req->sconn->smb2.requests, req);
1630         TALLOC_FREE(req);
1631
1632         for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1633                 const uint8_t *outhdr;
1634                 uint64_t message_id;
1635                 uint64_t async_id;
1636
1637                 if (cur->compound_related) {
1638                         /*
1639                          * Never cancel anything in a compound request.
1640                          * Way too hard to deal with the result.
1641                          */
1642                         continue;
1643                 }
1644
1645                 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1646
1647                 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1648                 async_id = BVAL(outhdr, SMB2_HDR_PID);
1649
1650                 if (flags & SMB2_HDR_FLAG_ASYNC) {
1651                         if (search_async_id == async_id) {
1652                                 found_id = async_id;
1653                                 break;
1654                         }
1655                 } else {
1656                         if (search_message_id == message_id) {
1657                                 found_id = message_id;
1658                                 break;
1659                         }
1660                 }
1661         }
1662
1663         if (cur && cur->subreq) {
1664                 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1665                 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1666                         "cancel opcode[%s] mid %llu\n",
1667                         smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1668                         (unsigned long long)found_id ));
1669                 tevent_req_cancel(cur->subreq);
1670         }
1671
1672         return NT_STATUS_OK;
1673 }
1674
1675 /*************************************************************
1676  Ensure an incoming tid is a valid one for us to access.
1677  Change to the associated uid credentials and chdir to the
1678  valid tid directory.
1679 *************************************************************/
1680
1681 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1682 {
1683         const uint8_t *inhdr;
1684         uint32_t in_flags;
1685         uint32_t in_tid;
1686         struct smbXsrv_tcon *tcon;
1687         NTSTATUS status;
1688         NTTIME now = timeval_to_nttime(&req->request_time);
1689
1690         req->tcon = NULL;
1691
1692         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1693
1694         in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1695         in_tid = IVAL(inhdr, SMB2_HDR_TID);
1696
1697         if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1698                 in_tid = req->last_tid;
1699         }
1700
1701         req->last_tid = 0;
1702
1703         status = smb2srv_tcon_lookup(req->session,
1704                                      in_tid, now, &tcon);
1705         if (!NT_STATUS_IS_OK(status)) {
1706                 return status;
1707         }
1708
1709         if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1710                 return NT_STATUS_ACCESS_DENIED;
1711         }
1712
1713         /* should we pass FLAG_CASELESS_PATHNAMES here? */
1714         if (!set_current_service(tcon->compat, 0, true)) {
1715                 return NT_STATUS_ACCESS_DENIED;
1716         }
1717
1718         req->tcon = tcon;
1719         req->last_tid = in_tid;
1720
1721         return NT_STATUS_OK;
1722 }
1723
1724 /*************************************************************
1725  Ensure an incoming session_id is a valid one for us to access.
1726 *************************************************************/
1727
1728 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1729 {
1730         const uint8_t *inhdr;
1731         uint32_t in_flags;
1732         uint16_t in_opcode;
1733         uint64_t in_session_id;
1734         struct smbXsrv_session *session = NULL;
1735         struct auth_session_info *session_info;
1736         NTSTATUS status;
1737         NTTIME now = timeval_to_nttime(&req->request_time);
1738
1739         req->session = NULL;
1740         req->tcon = NULL;
1741
1742         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1743
1744         in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1745         in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1746         in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1747
1748         if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1749                 in_session_id = req->last_session_id;
1750         }
1751
1752         req->last_session_id = 0;
1753
1754         /* lookup an existing session */
1755         status = smb2srv_session_lookup(req->sconn->conn,
1756                                         in_session_id, now,
1757                                         &session);
1758         if (session) {
1759                 req->session = session;
1760                 req->last_session_id = in_session_id;
1761         }
1762         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1763                 switch (in_opcode) {
1764                 case SMB2_OP_SESSSETUP:
1765                         status = NT_STATUS_OK;
1766                         break;
1767                 default:
1768                         break;
1769                 }
1770         }
1771         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1772                 switch (in_opcode) {
1773                 case SMB2_OP_TCON:
1774                 case SMB2_OP_CREATE:
1775                 case SMB2_OP_GETINFO:
1776                 case SMB2_OP_SETINFO:
1777                         return NT_STATUS_INVALID_HANDLE;
1778                 default:
1779                         /*
1780                          * Notice the check for
1781                          * (session_info == NULL)
1782                          * below.
1783                          */
1784                         status = NT_STATUS_OK;
1785                         break;
1786                 }
1787         }
1788         if (!NT_STATUS_IS_OK(status)) {
1789                 return status;
1790         }
1791
1792         session_info = session->global->auth_session_info;
1793         if (session_info == NULL) {
1794                 return NT_STATUS_INVALID_HANDLE;
1795         }
1796
1797         if (in_session_id != req->sconn->conn->last_session_id) {
1798                 req->sconn->conn->last_session_id = in_session_id;
1799                 set_current_user_info(session_info->unix_info->sanitized_username,
1800                                       session_info->unix_info->unix_name,
1801                                       session_info->info->domain_name);
1802         }
1803
1804         return NT_STATUS_OK;
1805 }
1806
1807 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1808                                                 uint32_t data_length)
1809 {
1810         uint16_t needed_charge;
1811         uint16_t credit_charge = 1;
1812         const uint8_t *inhdr;
1813
1814         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1815
1816         if (req->sconn->smb2.supports_multicredit) {
1817                 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1818                 credit_charge = MAX(credit_charge, 1);
1819         }
1820
1821         needed_charge = (data_length - 1)/ 65536 + 1;
1822
1823         DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1824                    (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1825                    credit_charge, needed_charge));
1826
1827         if (needed_charge > credit_charge) {
1828                 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1829                           credit_charge, needed_charge));
1830                 return NT_STATUS_INVALID_PARAMETER;
1831         }
1832
1833         return NT_STATUS_OK;
1834 }
1835
1836 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1837                                         size_t expected_body_size)
1838 {
1839         struct iovec *inhdr_v;
1840         const uint8_t *inhdr;
1841         uint16_t opcode;
1842         const uint8_t *inbody;
1843         size_t body_size;
1844         size_t min_dyn_size = expected_body_size & 0x00000001;
1845         int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1846
1847         /*
1848          * The following should be checked already.
1849          */
1850         if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1851                 return NT_STATUS_INTERNAL_ERROR;
1852         }
1853         if (req->current_idx > max_idx) {
1854                 return NT_STATUS_INTERNAL_ERROR;
1855         }
1856
1857         inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1858         if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1859                 return NT_STATUS_INTERNAL_ERROR;
1860         }
1861         if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1862                 return NT_STATUS_INTERNAL_ERROR;
1863         }
1864
1865         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1866         opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1867
1868         switch (opcode) {
1869         case SMB2_OP_IOCTL:
1870         case SMB2_OP_GETINFO:
1871                 min_dyn_size = 0;
1872                 break;
1873         case SMB2_OP_WRITE:
1874                 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
1875                         if (req->smb1req->unread_bytes < min_dyn_size) {
1876                                 return NT_STATUS_INVALID_PARAMETER;
1877                         }
1878
1879                         min_dyn_size = 0;
1880                 }
1881                 break;
1882         }
1883
1884         /*
1885          * Now check the expected body size,
1886          * where the last byte might be in the
1887          * dynamic section..
1888          */
1889         if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1890                 return NT_STATUS_INVALID_PARAMETER;
1891         }
1892         if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1893                 return NT_STATUS_INVALID_PARAMETER;
1894         }
1895
1896         inbody = SMBD_SMB2_IN_BODY_PTR(req);
1897
1898         body_size = SVAL(inbody, 0x00);
1899         if (body_size != expected_body_size) {
1900                 return NT_STATUS_INVALID_PARAMETER;
1901         }
1902
1903         return NT_STATUS_OK;
1904 }
1905
1906 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1907 {
1908         struct smbXsrv_connection *conn = req->sconn->conn;
1909         const struct smbd_smb2_dispatch_table *call = NULL;
1910         const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1911         const uint8_t *inhdr;
1912         uint16_t opcode;
1913         uint32_t flags;
1914         uint64_t mid;
1915         NTSTATUS status;
1916         NTSTATUS session_status;
1917         uint32_t allowed_flags;
1918         NTSTATUS return_value;
1919         struct smbXsrv_session *x = NULL;
1920         bool signing_required = false;
1921         bool encryption_required = false;
1922
1923         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1924
1925         /* TODO: verify more things */
1926
1927         flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1928         opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1929         mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1930         DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1931                 smb2_opcode_name(opcode),
1932                 (unsigned long long)mid));
1933
1934         if (conn->protocol >= PROTOCOL_SMB2_02) {
1935                 /*
1936                  * once the protocol is negotiated
1937                  * SMB2_OP_NEGPROT is not allowed anymore
1938                  */
1939                 if (opcode == SMB2_OP_NEGPROT) {
1940                         /* drop the connection */
1941                         return NT_STATUS_INVALID_PARAMETER;
1942                 }
1943         } else {
1944                 /*
1945                  * if the protocol is not negotiated yet
1946                  * only SMB2_OP_NEGPROT is allowed.
1947                  */
1948                 if (opcode != SMB2_OP_NEGPROT) {
1949                         /* drop the connection */
1950                         return NT_STATUS_INVALID_PARAMETER;
1951                 }
1952         }
1953
1954         /*
1955          * Check if the client provided a valid session id,
1956          * if so smbd_smb2_request_check_session() calls
1957          * set_current_user_info().
1958          *
1959          * As some command don't require a valid session id
1960          * we defer the check of the session_status
1961          */
1962         session_status = smbd_smb2_request_check_session(req);
1963         x = req->session;
1964         if (x != NULL) {
1965                 signing_required = x->global->signing_required;
1966                 encryption_required = x->global->encryption_required;
1967
1968                 if (opcode == SMB2_OP_SESSSETUP &&
1969                     x->global->channels[0].signing_key.length) {
1970                         signing_required = true;
1971                 }
1972         }
1973
1974         req->do_signing = false;
1975         req->do_encryption = false;
1976         if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
1977                 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
1978                 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
1979
1980                 if (x != NULL && x->global->session_wire_id != tf_session_id) {
1981                         DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1982                                  "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1983                                  (unsigned long long)x->global->session_wire_id,
1984                                  (unsigned long long)tf_session_id));
1985                         /*
1986                          * TODO: windows allows this...
1987                          * should we drop the connection?
1988                          *
1989                          * For now we just return ACCESS_DENIED
1990                          * (Windows clients never trigger this)
1991                          * and wait for an update of [MS-SMB2].
1992                          */
1993                         return smbd_smb2_request_error(req,
1994                                         NT_STATUS_ACCESS_DENIED);
1995                 }
1996
1997                 req->do_encryption = true;
1998         }
1999
2000         if (encryption_required && !req->do_encryption) {
2001                 return smbd_smb2_request_error(req,
2002                                 NT_STATUS_ACCESS_DENIED);
2003         }
2004
2005         call = smbd_smb2_call(opcode);
2006         if (call == NULL) {
2007                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2008         }
2009
2010         allowed_flags = SMB2_HDR_FLAG_CHAINED |
2011                         SMB2_HDR_FLAG_SIGNED |
2012                         SMB2_HDR_FLAG_DFS;
2013         if (opcode == SMB2_OP_CANCEL) {
2014                 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2015         }
2016         if ((flags & ~allowed_flags) != 0) {
2017                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2018         }
2019
2020         if (flags & SMB2_HDR_FLAG_CHAINED) {
2021                 /*
2022                  * This check is mostly for giving the correct error code
2023                  * for compounded requests.
2024                  */
2025                 if (!NT_STATUS_IS_OK(session_status)) {
2026                         return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2027                 }
2028         } else {
2029                 req->compat_chain_fsp = NULL;
2030         }
2031
2032         if (req->do_encryption) {
2033                 signing_required = false;
2034         } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2035                 DATA_BLOB signing_key;
2036
2037                 if (x == NULL) {
2038                         return smbd_smb2_request_error(
2039                                 req, NT_STATUS_USER_SESSION_DELETED);
2040                 }
2041
2042                 signing_key = x->global->channels[0].signing_key;
2043
2044                 /*
2045                  * If we have a signing key, we should
2046                  * sign the response
2047                  */
2048                 if (signing_key.length > 0) {
2049                         req->do_signing = true;
2050                 }
2051
2052                 status = smb2_signing_check_pdu(signing_key,
2053                                                 conn->protocol,
2054                                                 SMBD_SMB2_IN_HDR_IOV(req),
2055                                                 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2056                 if (!NT_STATUS_IS_OK(status)) {
2057                         return smbd_smb2_request_error(req, status);
2058                 }
2059
2060                 /*
2061                  * Now that we know the request was correctly signed
2062                  * we have to sign the response too.
2063                  */
2064                 req->do_signing = true;
2065
2066                 if (!NT_STATUS_IS_OK(session_status)) {
2067                         return smbd_smb2_request_error(req, session_status);
2068                 }
2069         } else if (opcode == SMB2_OP_CANCEL) {
2070                 /* Cancel requests are allowed to skip the signing */
2071         } else if (signing_required) {
2072                 /*
2073                  * If signing is required we try to sign
2074                  * a possible error response
2075                  */
2076                 req->do_signing = true;
2077                 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2078         }
2079
2080         if (flags & SMB2_HDR_FLAG_CHAINED) {
2081                 req->compound_related = true;
2082         }
2083
2084         if (call->need_session) {
2085                 if (!NT_STATUS_IS_OK(session_status)) {
2086                         return smbd_smb2_request_error(req, session_status);
2087                 }
2088         }
2089
2090         if (call->need_tcon) {
2091                 SMB_ASSERT(call->need_session);
2092
2093                 /*
2094                  * This call needs to be run as user.
2095                  *
2096                  * smbd_smb2_request_check_tcon()
2097                  * calls change_to_user() on success.
2098                  */
2099                 status = smbd_smb2_request_check_tcon(req);
2100                 if (!NT_STATUS_IS_OK(status)) {
2101                         return smbd_smb2_request_error(req, status);
2102                 }
2103                 if (req->tcon->global->encryption_required) {
2104                         encryption_required = true;
2105                 }
2106                 if (encryption_required && !req->do_encryption) {
2107                         return smbd_smb2_request_error(req,
2108                                 NT_STATUS_ACCESS_DENIED);
2109                 }
2110         }
2111
2112         if (call->fileid_ofs != 0) {
2113                 size_t needed = call->fileid_ofs + 16;
2114                 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2115                 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2116                 uint64_t file_id_persistent;
2117                 uint64_t file_id_volatile;
2118                 struct files_struct *fsp;
2119
2120                 SMB_ASSERT(call->need_tcon);
2121
2122                 if (needed > body_size) {
2123                         return smbd_smb2_request_error(req,
2124                                         NT_STATUS_INVALID_PARAMETER);
2125                 }
2126
2127                 file_id_persistent      = BVAL(body, call->fileid_ofs + 0);
2128                 file_id_volatile        = BVAL(body, call->fileid_ofs + 8);
2129
2130                 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2131                 if (fsp == NULL) {
2132                         if (!call->allow_invalid_fileid) {
2133                                 return smbd_smb2_request_error(req,
2134                                                 NT_STATUS_FILE_CLOSED);
2135                         }
2136
2137                         if (file_id_persistent != UINT64_MAX) {
2138                                 return smbd_smb2_request_error(req,
2139                                                 NT_STATUS_FILE_CLOSED);
2140                         }
2141                         if (file_id_volatile != UINT64_MAX) {
2142                                 return smbd_smb2_request_error(req,
2143                                                 NT_STATUS_FILE_CLOSED);
2144                         }
2145                 }
2146         }
2147
2148         if (call->as_root) {
2149                 SMB_ASSERT(call->fileid_ofs == 0);
2150                 /* This call needs to be run as root */
2151                 change_to_root_user();
2152         } else {
2153                 SMB_ASSERT(call->need_tcon);
2154         }
2155
2156         switch (opcode) {
2157         case SMB2_OP_NEGPROT:
2158                 {
2159                         START_PROFILE(smb2_negprot);
2160                         return_value = smbd_smb2_request_process_negprot(req);
2161                         END_PROFILE(smb2_negprot);
2162                 }
2163                 break;
2164
2165         case SMB2_OP_SESSSETUP:
2166                 {
2167                         START_PROFILE(smb2_sesssetup);
2168                         return_value = smbd_smb2_request_process_sesssetup(req);
2169                         END_PROFILE(smb2_sesssetup);
2170                 }
2171                 break;
2172
2173         case SMB2_OP_LOGOFF:
2174                 {
2175                         START_PROFILE(smb2_logoff);
2176                         return_value = smbd_smb2_request_process_logoff(req);
2177                         END_PROFILE(smb2_logoff);
2178                 }
2179                 break;
2180
2181         case SMB2_OP_TCON:
2182                 {
2183                         START_PROFILE(smb2_tcon);
2184                         return_value = smbd_smb2_request_process_tcon(req);
2185                         END_PROFILE(smb2_tcon);
2186                 }
2187                 break;
2188
2189         case SMB2_OP_TDIS:
2190                 {
2191                         START_PROFILE(smb2_tdis);
2192                         return_value = smbd_smb2_request_process_tdis(req);
2193                         END_PROFILE(smb2_tdis);
2194                 }
2195                 break;
2196
2197         case SMB2_OP_CREATE:
2198                 {
2199                         START_PROFILE(smb2_create);
2200                         return_value = smbd_smb2_request_process_create(req);
2201                         END_PROFILE(smb2_create);
2202                 }
2203                 break;
2204
2205         case SMB2_OP_CLOSE:
2206                 {
2207                         START_PROFILE(smb2_close);
2208                         return_value = smbd_smb2_request_process_close(req);
2209                         END_PROFILE(smb2_close);
2210                 }
2211                 break;
2212
2213         case SMB2_OP_FLUSH:
2214                 {
2215                         START_PROFILE(smb2_flush);
2216                         return_value = smbd_smb2_request_process_flush(req);
2217                         END_PROFILE(smb2_flush);
2218                 }
2219                 break;
2220
2221         case SMB2_OP_READ:
2222                 {
2223                         START_PROFILE(smb2_read);
2224                         return_value = smbd_smb2_request_process_read(req);
2225                         END_PROFILE(smb2_read);
2226                 }
2227                 break;
2228
2229         case SMB2_OP_WRITE:
2230                 {
2231                         START_PROFILE(smb2_write);
2232                         return_value = smbd_smb2_request_process_write(req);
2233                         END_PROFILE(smb2_write);
2234                 }
2235                 break;
2236
2237         case SMB2_OP_LOCK:
2238                 {
2239                         START_PROFILE(smb2_lock);
2240                         return_value = smbd_smb2_request_process_lock(req);
2241                         END_PROFILE(smb2_lock);
2242                 }
2243                 break;
2244
2245         case SMB2_OP_IOCTL:
2246                 {
2247                         START_PROFILE(smb2_ioctl);
2248                         return_value = smbd_smb2_request_process_ioctl(req);
2249                         END_PROFILE(smb2_ioctl);
2250                 }
2251                 break;
2252
2253         case SMB2_OP_CANCEL:
2254                 {
2255                         START_PROFILE(smb2_cancel);
2256                         return_value = smbd_smb2_request_process_cancel(req);
2257                         END_PROFILE(smb2_cancel);
2258                 }
2259                 break;
2260
2261         case SMB2_OP_KEEPALIVE:
2262                 {
2263                         START_PROFILE(smb2_keepalive);
2264                         return_value = smbd_smb2_request_process_keepalive(req);
2265                         END_PROFILE(smb2_keepalive);
2266                 }
2267                 break;
2268
2269         case SMB2_OP_FIND:
2270                 {
2271                         START_PROFILE(smb2_find);
2272                         return_value = smbd_smb2_request_process_find(req);
2273                         END_PROFILE(smb2_find);
2274                 }
2275                 break;
2276
2277         case SMB2_OP_NOTIFY:
2278                 {
2279                         START_PROFILE(smb2_notify);
2280                         return_value = smbd_smb2_request_process_notify(req);
2281                         END_PROFILE(smb2_notify);
2282                 }
2283                 break;
2284
2285         case SMB2_OP_GETINFO:
2286                 {
2287                         START_PROFILE(smb2_getinfo);
2288                         return_value = smbd_smb2_request_process_getinfo(req);
2289                         END_PROFILE(smb2_getinfo);
2290                 }
2291                 break;
2292
2293         case SMB2_OP_SETINFO:
2294                 {
2295                         START_PROFILE(smb2_setinfo);
2296                         return_value = smbd_smb2_request_process_setinfo(req);
2297                         END_PROFILE(smb2_setinfo);
2298                 }
2299                 break;
2300
2301         case SMB2_OP_BREAK:
2302                 {
2303                         START_PROFILE(smb2_break);
2304                         return_value = smbd_smb2_request_process_break(req);
2305                         END_PROFILE(smb2_break);
2306                 }
2307                 break;
2308
2309         default:
2310                 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2311                 break;
2312         }
2313         return return_value;
2314 }
2315
2316 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2317 {
2318         struct smbd_server_connection *sconn = req->sconn;
2319         struct smbXsrv_connection *conn = req->sconn->conn;
2320         int first_idx = 1;
2321         struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2322         struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2323         struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2324         NTSTATUS status;
2325
2326         req->subreq = NULL;
2327         TALLOC_FREE(req->async_te);
2328
2329         if (req->do_encryption &&
2330             (firsttf->iov_len == 0) &&
2331             (req->first_key.length == 0) &&
2332             (req->session != NULL) &&
2333             (req->session->global->encryption_key.length != 0))
2334         {
2335                 DATA_BLOB encryption_key = req->session->global->encryption_key;
2336                 uint8_t *tf;
2337                 uint64_t session_id = req->session->global->session_wire_id;
2338                 struct smbXsrv_session *x = req->session;
2339                 uint64_t nonce_high;
2340                 uint64_t nonce_low;
2341
2342                 nonce_high = x->nonce_high;
2343                 nonce_low = x->nonce_low;
2344
2345                 x->nonce_low += 1;
2346                 if (x->nonce_low == 0) {
2347                         x->nonce_low += 1;
2348                         x->nonce_high += 1;
2349                 }
2350
2351                 /*
2352                  * We need to place the SMB2_TRANSFORM header before the
2353                  * first SMB2 header
2354                  */
2355
2356                 /*
2357                  * we need to remember the encryption key
2358                  * and defer the signing/encryption until
2359                  * we are sure that we do not change
2360                  * the header again.
2361                  */
2362                 req->first_key = data_blob_dup_talloc(req, encryption_key);
2363                 if (req->first_key.data == NULL) {
2364                         return NT_STATUS_NO_MEMORY;
2365                 }
2366
2367                 tf = talloc_zero_array(req, uint8_t,
2368                                        SMB2_TF_HDR_SIZE);
2369                 if (tf == NULL) {
2370                         return NT_STATUS_NO_MEMORY;
2371                 }
2372
2373                 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2374                 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2375                 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2376                 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2377
2378                 firsttf->iov_base = (void *)tf;
2379                 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2380         }
2381
2382         if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2383             (req->last_key.length > 0) &&
2384             (firsttf->iov_len == 0))
2385         {
2386                 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2387                 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2388
2389                 /*
2390                  * As we are sure the header of the last request in the
2391                  * compound chain will not change, we can to sign here
2392                  * with the last signing key we remembered.
2393                  */
2394                 status = smb2_signing_sign_pdu(req->last_key,
2395                                                conn->protocol,
2396                                                lasthdr,
2397                                                SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2398                 if (!NT_STATUS_IS_OK(status)) {
2399                         return status;
2400                 }
2401         }
2402         if (req->last_key.length > 0) {
2403                 data_blob_clear_free(&req->last_key);
2404         }
2405
2406         req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2407
2408         if (req->current_idx < req->out.vector_count) {
2409                 /*
2410                  * We must process the remaining compound
2411                  * SMB2 requests before any new incoming SMB2
2412                  * requests. This is because incoming SMB2
2413                  * requests may include a cancel for a
2414                  * compound request we haven't processed
2415                  * yet.
2416                  */
2417                 struct tevent_immediate *im = tevent_create_immediate(req);
2418                 if (!im) {
2419                         return NT_STATUS_NO_MEMORY;
2420                 }
2421
2422                 if (req->do_signing && firsttf->iov_len == 0) {
2423                         struct smbXsrv_session *x = req->session;
2424                         DATA_BLOB signing_key = x->global->channels[0].signing_key;
2425
2426                         /*
2427                          * we need to remember the signing key
2428                          * and defer the signing until
2429                          * we are sure that we do not change
2430                          * the header again.
2431                          */
2432                         req->last_key = data_blob_dup_talloc(req, signing_key);
2433                         if (req->last_key.data == NULL) {
2434                                 return NT_STATUS_NO_MEMORY;
2435                         }
2436                 }
2437
2438                 tevent_schedule_immediate(im,
2439                                         req->sconn->ev_ctx,
2440                                         smbd_smb2_request_dispatch_immediate,
2441                                         req);
2442                 return NT_STATUS_OK;
2443         }
2444
2445         if (req->compound_related) {
2446                 req->compound_related = false;
2447         }
2448
2449         smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2450
2451         /* Set credit for these operations (zero credits if this
2452            is a final reply for an async operation). */
2453         smb2_calculate_credits(req, req);
2454
2455         /*
2456          * now check if we need to sign the current response
2457          */
2458         if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2459                 status = smb2_signing_encrypt_pdu(req->first_key,
2460                                         conn->protocol,
2461                                         firsttf,
2462                                         req->out.vector_count - first_idx);
2463                 if (!NT_STATUS_IS_OK(status)) {
2464                         return status;
2465                 }
2466         } else if (req->do_signing) {
2467                 struct smbXsrv_session *x = req->session;
2468                 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2469
2470                 status = smb2_signing_sign_pdu(signing_key,
2471                                                conn->protocol,
2472                                                outhdr,
2473                                                SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2474                 if (!NT_STATUS_IS_OK(status)) {
2475                         return status;
2476                 }
2477         }
2478         if (req->first_key.length > 0) {
2479                 data_blob_clear_free(&req->first_key);
2480         }
2481
2482         /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2483         if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2484             outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2485                 /* Dynamic part is NULL. Chop it off,
2486                    We're going to send it via sendfile. */
2487                 req->out.vector_count -= 1;
2488         }
2489
2490         /*
2491          * We're done with this request -
2492          * move it off the "being processed" queue.
2493          */
2494         DLIST_REMOVE(req->sconn->smb2.requests, req);
2495
2496         req->queue_entry.mem_ctx = req;
2497         req->queue_entry.vector = req->out.vector;
2498         req->queue_entry.count = req->out.vector_count;
2499         DLIST_ADD_END(req->sconn->smb2.send_queue, &req->queue_entry, NULL);
2500         req->sconn->smb2.send_queue_len++;
2501
2502         status = smbd_smb2_io_handler(sconn, TEVENT_FD_WRITE);
2503         if (!NT_STATUS_IS_OK(status)) {
2504                 return status;
2505         }
2506
2507         return NT_STATUS_OK;
2508 }
2509
2510 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2511
2512 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2513                                         struct tevent_immediate *im,
2514                                         void *private_data)
2515 {
2516         struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2517                                         struct smbd_smb2_request);
2518         struct smbd_server_connection *sconn = req->sconn;
2519         NTSTATUS status;
2520
2521         TALLOC_FREE(im);
2522
2523         if (DEBUGLEVEL >= 10) {
2524                 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2525                         req->current_idx, req->in.vector_count));
2526                 print_req_vectors(req);
2527         }
2528
2529         status = smbd_smb2_request_dispatch(req);
2530         if (!NT_STATUS_IS_OK(status)) {
2531                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2532                 return;
2533         }
2534
2535         status = smbd_smb2_request_next_incoming(sconn);
2536         if (!NT_STATUS_IS_OK(status)) {
2537                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2538                 return;
2539         }
2540 }
2541
2542 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2543                                    NTSTATUS status,
2544                                    DATA_BLOB body, DATA_BLOB *dyn,
2545                                    const char *location)
2546 {
2547         uint8_t *outhdr;
2548         struct iovec *outbody_v;
2549         struct iovec *outdyn_v;
2550         uint32_t next_command_ofs;
2551
2552         DEBUG(10,("smbd_smb2_request_done_ex: "
2553                   "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2554                   req->current_idx, nt_errstr(status), (unsigned int)body.length,
2555                   dyn ? "yes": "no",
2556                   (unsigned int)(dyn ? dyn->length : 0),
2557                   location));
2558
2559         if (body.length < 2) {
2560                 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2561         }
2562
2563         if ((body.length % 2) != 0) {
2564                 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2565         }
2566
2567         outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2568         outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2569         outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2570
2571         next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2572         SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2573
2574         outbody_v->iov_base = (void *)body.data;
2575         outbody_v->iov_len = body.length;
2576
2577         if (dyn) {
2578                 outdyn_v->iov_base = (void *)dyn->data;
2579                 outdyn_v->iov_len = dyn->length;
2580         } else {
2581                 outdyn_v->iov_base = NULL;
2582                 outdyn_v->iov_len = 0;
2583         }
2584
2585         /* see if we need to recalculate the offset to the next response */
2586         if (next_command_ofs > 0) {
2587                 next_command_ofs  = SMB2_HDR_BODY;
2588                 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2589                 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2590         }
2591
2592         if ((next_command_ofs % 8) != 0) {
2593                 size_t pad_size = 8 - (next_command_ofs % 8);
2594                 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2595                         /*
2596                          * if the dyn buffer is empty
2597                          * we can use it to add padding
2598                          */
2599                         uint8_t *pad;
2600
2601                         pad = talloc_zero_array(req,
2602                                                 uint8_t, pad_size);
2603                         if (pad == NULL) {
2604                                 return smbd_smb2_request_error(req,
2605                                                 NT_STATUS_NO_MEMORY);
2606                         }
2607
2608                         outdyn_v->iov_base = (void *)pad;
2609                         outdyn_v->iov_len = pad_size;
2610                 } else {
2611                         /*
2612                          * For now we copy the dynamic buffer
2613                          * and add the padding to the new buffer
2614                          */
2615                         size_t old_size;
2616                         uint8_t *old_dyn;
2617                         size_t new_size;
2618                         uint8_t *new_dyn;
2619
2620                         old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2621                         old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2622
2623                         new_size = old_size + pad_size;
2624                         new_dyn = talloc_zero_array(req,
2625                                                uint8_t, new_size);
2626                         if (new_dyn == NULL) {
2627                                 return smbd_smb2_request_error(req,
2628                                                 NT_STATUS_NO_MEMORY);
2629                         }
2630
2631                         memcpy(new_dyn, old_dyn, old_size);
2632                         memset(new_dyn + old_size, 0, pad_size);
2633
2634                         outdyn_v->iov_base = (void *)new_dyn;
2635                         outdyn_v->iov_len = new_size;
2636                 }
2637                 next_command_ofs += pad_size;
2638         }
2639
2640         SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2641
2642         return smbd_smb2_request_reply(req);
2643 }
2644
2645 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2646                                     NTSTATUS status,
2647                                     DATA_BLOB *info,
2648                                     const char *location)
2649 {
2650         DATA_BLOB body;
2651         DATA_BLOB _dyn;
2652         uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2653         size_t unread_bytes = smbd_smb2_unread_bytes(req);
2654
2655         DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2656                   req->current_idx, nt_errstr(status), info ? " +info" : "",
2657                   location));
2658
2659         if (unread_bytes) {
2660                 /* Recvfile error. Drain incoming socket. */
2661                 size_t ret;
2662
2663                 errno = 0;
2664                 ret = drain_socket(req->sconn->sock, unread_bytes);
2665                 if (ret != unread_bytes) {
2666                         NTSTATUS error;
2667
2668                         if (errno == 0) {
2669                                 error = NT_STATUS_IO_DEVICE_ERROR;
2670                         } else {
2671                                 error = map_nt_error_from_unix_common(errno);
2672                         }
2673
2674                         DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2675                                   "ret[%u] errno[%d] => %s\n",
2676                                   (unsigned)unread_bytes,
2677                                   (unsigned)ret, errno, nt_errstr(error)));
2678                         return error;
2679                 }
2680         }
2681
2682         body.data = outhdr + SMB2_HDR_BODY;
2683         body.length = 8;
2684         SSVAL(body.data, 0, 9);
2685
2686         if (info) {
2687                 SIVAL(body.data, 0x04, info->length);
2688         } else {
2689                 /* Allocated size of req->out.vector[i].iov_base
2690                  * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2691                  * 1 byte without having to do an alloc.
2692                  */
2693                 info = &_dyn;
2694                 info->data = ((uint8_t *)outhdr) +
2695                         OUTVEC_ALLOC_SIZE - 1;
2696                 info->length = 1;
2697                 SCVAL(info->data, 0, 0);
2698         }
2699
2700         /*
2701          * Note: Even if there is an error, continue to process the request.
2702          * per MS-SMB2.
2703          */
2704
2705         return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2706 }
2707
2708
2709 struct smbd_smb2_send_oplock_break_state {
2710         struct smbd_server_connection *sconn;
2711         struct smbd_smb2_send_queue queue_entry;
2712         uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x18];
2713         struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2714 };
2715
2716 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2717                                      struct smbXsrv_session *session,
2718                                      struct smbXsrv_tcon *tcon,
2719                                      struct smbXsrv_open *op,
2720                                      uint8_t oplock_level)
2721 {
2722         struct smbd_smb2_send_oplock_break_state *state;
2723         struct smbXsrv_connection *conn = sconn->conn;
2724         uint8_t *tf;
2725         size_t tf_len;
2726         uint8_t *hdr;
2727         uint8_t *body;
2728         size_t body_len;
2729         uint8_t *dyn;
2730         size_t dyn_len;
2731         bool do_encryption = session->global->encryption_required;
2732         uint64_t nonce_high = 0;
2733         uint64_t nonce_low = 0;
2734         NTSTATUS status;
2735
2736         if (tcon->global->encryption_required) {
2737                 do_encryption = true;
2738         }
2739
2740         state = talloc_zero(sconn, struct smbd_smb2_send_oplock_break_state);
2741         if (state == NULL) {
2742                 return NT_STATUS_NO_MEMORY;
2743         }
2744         state->sconn = sconn;
2745
2746         tf = state->buf + NBT_HDR_SIZE;
2747         tf_len = SMB2_TF_HDR_SIZE;
2748         hdr = tf + tf_len;
2749         body = hdr + SMB2_HDR_BODY;
2750         body_len = 0x18;
2751         dyn = body + body_len;
2752         dyn_len = 0;
2753
2754         if (do_encryption) {
2755                 nonce_high = session->nonce_high;
2756                 nonce_low = session->nonce_low;
2757
2758                 session->nonce_low += 1;
2759                 if (session->nonce_low == 0) {
2760                         session->nonce_low += 1;
2761                         session->nonce_high += 1;
2762                 }
2763         }
2764
2765         SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2766         SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2767         SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2768         SBVAL(tf, SMB2_TF_SESSION_ID, session->global->session_wire_id);
2769
2770         SIVAL(hdr, 0,                           SMB2_MAGIC);
2771         SSVAL(hdr, SMB2_HDR_LENGTH,             SMB2_HDR_BODY);
2772         SSVAL(hdr, SMB2_HDR_EPOCH,              0);
2773         SIVAL(hdr, SMB2_HDR_STATUS,             0);
2774         SSVAL(hdr, SMB2_HDR_OPCODE,             SMB2_OP_BREAK);
2775         SSVAL(hdr, SMB2_HDR_CREDIT,             0);
2776         SIVAL(hdr, SMB2_HDR_FLAGS,              SMB2_HDR_FLAG_REDIRECT);
2777         SIVAL(hdr, SMB2_HDR_NEXT_COMMAND,       0);
2778         SBVAL(hdr, SMB2_HDR_MESSAGE_ID,         UINT64_MAX);
2779         SIVAL(hdr, SMB2_HDR_PID,                0);
2780         SIVAL(hdr, SMB2_HDR_TID,                0);
2781         SBVAL(hdr, SMB2_HDR_SESSION_ID,         0);
2782         memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2783
2784         SSVAL(body, 0x00, body_len);
2785
2786         SCVAL(body, 0x02, oplock_level);
2787         SCVAL(body, 0x03, 0);           /* reserved */
2788         SIVAL(body, 0x04, 0);           /* reserved */
2789         SBVAL(body, 0x08, op->global->open_persistent_id);
2790         SBVAL(body, 0x10, op->global->open_volatile_id);
2791
2792         state->vector[0].iov_base = (void *)state->buf;
2793         state->vector[0].iov_len = NBT_HDR_SIZE;
2794
2795         if (do_encryption) {
2796                 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base   = tf;
2797                 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len    = tf_len;
2798         } else {
2799                 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base   = NULL;
2800                 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len    = 0;
2801         }
2802
2803         state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base  = hdr;
2804         state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len   = SMB2_HDR_BODY;
2805
2806         state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
2807         state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len  = body_len;
2808
2809         state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base  = dyn;
2810         state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len   = dyn_len;
2811
2812         smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2813
2814         if (do_encryption) {
2815                 DATA_BLOB encryption_key = session->global->encryption_key;
2816
2817                 status = smb2_signing_encrypt_pdu(encryption_key,
2818                                         conn->protocol,
2819                                         &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2820                                         SMBD_SMB2_NUM_IOV_PER_REQ);
2821                 if (!NT_STATUS_IS_OK(status)) {
2822                         return status;
2823                 }
2824         }
2825
2826         state->queue_entry.mem_ctx = state;
2827         state->queue_entry.vector = state->vector;
2828         state->queue_entry.count = ARRAY_SIZE(state->vector);
2829         DLIST_ADD_END(state->sconn->smb2.send_queue, &state->queue_entry, NULL);
2830         state->sconn->smb2.send_queue_len++;
2831
2832         status = smbd_smb2_io_handler(sconn, TEVENT_FD_WRITE);
2833         if (!NT_STATUS_IS_OK(status)) {
2834                 return status;
2835         }
2836
2837         return NT_STATUS_OK;
2838 }
2839
2840 static size_t get_min_receive_file_size(struct smbd_smb2_request *smb2_req)
2841 {
2842         if (smb2_req->do_signing) {
2843                 return 0;
2844         }
2845         if (smb2_req->do_encryption) {
2846                 return 0;
2847         }
2848         return (size_t)lp_min_receive_file_size();
2849 }
2850
2851 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2852 {
2853         NTSTATUS status;
2854         uint32_t flags;
2855         uint64_t file_id_persistent;
2856         uint64_t file_id_volatile;
2857         struct smbXsrv_open *op = NULL;
2858         struct files_struct *fsp = NULL;
2859         const uint8_t *body = NULL;
2860
2861         /*
2862          * This is only called with a pktbuf
2863          * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
2864          * bytes
2865          */
2866
2867         if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
2868                 /* Transform header. Cannot recvfile. */
2869                 return false;
2870         }
2871         if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
2872                 /* Not SMB2. Normal error path will cope. */
2873                 return false;
2874         }
2875         if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
2876                 /* Not SMB2. Normal error path will cope. */
2877                 return false;
2878         }
2879         if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
2880                 /* Needs to be a WRITE. */
2881                 return false;
2882         }
2883         if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
2884                 /* Chained. Cannot recvfile. */
2885                 return false;
2886         }
2887         flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
2888         if (flags & SMB2_HDR_FLAG_CHAINED) {
2889                 /* Chained. Cannot recvfile. */
2890                 return false;
2891         }
2892         if (flags & SMB2_HDR_FLAG_SIGNED) {
2893                 /* Signed. Cannot recvfile. */
2894                 return false;
2895         }
2896
2897         body = &state->pktbuf[SMB2_HDR_BODY];
2898
2899         file_id_persistent      = BVAL(body, 0x10);
2900         file_id_volatile        = BVAL(body, 0x18);
2901
2902         status = smb2srv_open_lookup(state->req->sconn->conn,
2903                                      file_id_persistent,
2904                                      file_id_volatile,
2905                                      0, /* now */
2906                                      &op);
2907         if (!NT_STATUS_IS_OK(status)) {
2908                 return false;
2909         }
2910
2911         fsp = op->compat;
2912         if (fsp == NULL) {
2913                 return false;
2914         }
2915         if (fsp->conn == NULL) {
2916                 return false;
2917         }
2918
2919         if (IS_IPC(fsp->conn)) {
2920                 return false;
2921         }
2922         if (IS_PRINT(fsp->conn)) {
2923                 return false;
2924         }
2925
2926         DEBUG(10,("Doing recvfile write len = %u\n",
2927                 (unsigned int)(state->pktfull - state->pktlen)));
2928
2929         return true;
2930 }
2931
2932 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2933 {
2934         struct smbd_smb2_request_read_state *state = &sconn->smb2.request_read_state;
2935         size_t max_send_queue_len;
2936         size_t cur_send_queue_len;
2937
2938         if (!NT_STATUS_IS_OK(sconn->status)) {
2939                 /*
2940                  * we're not supposed to do any io
2941                  */
2942                 return NT_STATUS_OK;
2943         }
2944
2945         if (state->req != NULL) {
2946                 /*
2947                  * if there is already a tstream_readv_pdu
2948                  * pending, we are done.
2949                  */
2950                 return NT_STATUS_OK;
2951         }
2952
2953         max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2954         cur_send_queue_len = sconn->smb2.send_queue_len;
2955
2956         if (cur_send_queue_len > max_send_queue_len) {
2957                 /*
2958                  * if we have a lot of requests to send,
2959                  * we wait until they are on the wire until we
2960                  * ask for the next request.
2961                  */
2962                 return NT_STATUS_OK;
2963         }
2964
2965         /* ask for the next request */
2966         ZERO_STRUCTP(state);
2967         state->req = smbd_smb2_request_allocate(sconn);
2968         if (state->req == NULL) {
2969                 return NT_STATUS_NO_MEMORY;
2970         }
2971         state->req->sconn = sconn;
2972         state->min_recv_size = get_min_receive_file_size(state->req);
2973
2974         TEVENT_FD_READABLE(sconn->smb2.fde);
2975
2976         return NT_STATUS_OK;
2977 }
2978
2979 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2980                              uint8_t *inbuf, size_t size)
2981 {
2982         NTSTATUS status;
2983         struct smbd_smb2_request *req = NULL;
2984
2985         DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2986                  (unsigned int)size));
2987
2988         status = smbd_initialize_smb2(sconn);
2989         if (!NT_STATUS_IS_OK(status)) {
2990                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2991                 return;
2992         }
2993
2994         status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2995         if (!NT_STATUS_IS_OK(status)) {
2996                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2997                 return;
2998         }
2999
3000         status = smbd_smb2_request_validate(req);
3001         if (!NT_STATUS_IS_OK(status)) {
3002                 smbd_server_connection_terminate(sconn, nt_errstr(status));
3003                 return;
3004         }
3005
3006         status = smbd_smb2_request_setup_out(req);
3007         if (!NT_STATUS_IS_OK(status)) {
3008                 smbd_server_connection_terminate(sconn, nt_errstr(status));
3009                 return;
3010         }
3011
3012         status = smbd_smb2_request_dispatch(req);
3013         if (!NT_STATUS_IS_OK(status)) {
3014                 smbd_server_connection_terminate(sconn, nt_errstr(status));
3015                 return;
3016         }
3017
3018         status = smbd_smb2_request_next_incoming(sconn);
3019         if (!NT_STATUS_IS_OK(status)) {
3020                 smbd_server_connection_terminate(sconn, nt_errstr(status));
3021                 return;
3022         }
3023
3024         sconn->num_requests++;
3025 }
3026
3027 static int socket_error_from_errno(int ret,
3028                                    int sys_errno,
3029                                    bool *retry)
3030 {
3031         *retry = false;
3032
3033         if (ret >= 0) {
3034                 return 0;
3035         }
3036
3037         if (ret != -1) {
3038                 return EIO;
3039         }
3040
3041         if (sys_errno == 0) {
3042                 return EIO;
3043         }
3044
3045         if (sys_errno == EINTR) {
3046                 *retry = true;
3047                 return sys_errno;
3048         }
3049
3050         if (sys_errno == EINPROGRESS) {
3051                 *retry = true;
3052                 return sys_errno;
3053         }
3054
3055         if (sys_errno == EAGAIN) {
3056                 *retry = true;
3057                 return sys_errno;
3058         }
3059
3060         /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3061         if (sys_errno == ENOMEM) {
3062                 *retry = true;
3063                 return sys_errno;
3064         }
3065
3066 #ifdef EWOULDBLOCK
3067 #if EWOULDBLOCK != EAGAIN
3068         if (sys_errno == EWOULDBLOCK) {
3069                 *retry = true;
3070                 return sys_errno;
3071         }
3072 #endif
3073 #endif
3074
3075         return sys_errno;
3076 }
3077
3078 static NTSTATUS smbd_smb2_flush_send_queue(struct smbd_server_connection *sconn)
3079 {
3080         int ret;
3081         int err;
3082         bool retry;
3083
3084         if (sconn->smb2.send_queue == NULL) {
3085                 TEVENT_FD_NOT_WRITEABLE(sconn->smb2.fde);
3086                 return NT_STATUS_OK;
3087         }
3088
3089         while (sconn->smb2.send_queue != NULL) {
3090                 struct smbd_smb2_send_queue *e = sconn->smb2.send_queue;
3091
3092                 if (e->sendfile_header != NULL) {
3093                         size_t size = 0;
3094                         size_t i = 0;
3095                         uint8_t *buf;
3096
3097                         for (i=0; i < e->count; i++) {
3098                                 size += e->vector[i].iov_len;
3099                         }
3100
3101                         if (size <= e->sendfile_header->length) {
3102                                 buf = e->sendfile_header->data;
3103                         } else {
3104                                 buf = talloc_array(e->mem_ctx, uint8_t, size);
3105                                 if (buf == NULL) {
3106                                         return NT_STATUS_NO_MEMORY;
3107                                 }
3108                         }
3109
3110                         size = 0;
3111                         for (i=0; i < e->count; i++) {
3112                                 memcpy(buf+size,
3113                                        e->vector[i].iov_base,
3114                                        e->vector[i].iov_len);
3115                                 size += e->vector[i].iov_len;
3116                         }
3117
3118                         e->sendfile_header->data = buf;
3119                         e->sendfile_header->length = size;
3120                         e->count = 0;
3121
3122                         sconn->smb2.send_queue_len--;
3123                         DLIST_REMOVE(sconn->smb2.send_queue, e);
3124                         /*
3125                          * This triggers the sendfile path via
3126                          * the destructor.
3127                          */
3128                         talloc_free(e->mem_ctx);
3129                         continue;
3130                 }
3131
3132                 ret = writev(sconn->sock, e->vector, e->count);
3133                 if (ret == 0) {
3134                         /* propagate end of file */
3135                         return NT_STATUS_INTERNAL_ERROR;
3136                 }
3137                 err = socket_error_from_errno(ret, errno, &retry);
3138                 if (retry) {
3139                         /* retry later */
3140                         TEVENT_FD_WRITEABLE(sconn->smb2.fde);
3141                         return NT_STATUS_OK;
3142                 }
3143                 if (err != 0) {
3144                         return map_nt_error_from_unix_common(err);
3145                 }
3146                 while (ret > 0) {
3147                         if (ret < e->vector[0].iov_len) {
3148                                 uint8_t *base;
3149                                 base = (uint8_t *)e->vector[0].iov_base;
3150                                 base += ret;
3151                                 e->vector[0].iov_base = (void *)base;
3152                                 e->vector[0].iov_len -= ret;
3153                                 break;
3154                         }
3155                         ret -= e->vector[0].iov_len;
3156                         e->vector += 1;
3157                         e->count -= 1;
3158                 }
3159
3160                 /*
3161                  * there're maybe some empty vectors at the end
3162                  * which we need to skip, otherwise we would get
3163                  * ret == 0 from the readv() call and return EPIPE
3164                  */
3165                 while (e->count > 0) {
3166                         if (e->vector[0].iov_len > 0) {
3167                                 break;
3168                         }
3169                         e->vector += 1;
3170                         e->count -= 1;
3171                 }
3172
3173                 if (e->count > 0) {
3174                         /* we have more to write */
3175                         TEVENT_FD_WRITEABLE(sconn->smb2.fde);
3176                         return NT_STATUS_OK;
3177                 }
3178
3179                 sconn->smb2.send_queue_len--;
3180                 DLIST_REMOVE(sconn->smb2.send_queue, e);
3181                 talloc_free(e->mem_ctx);
3182         }
3183
3184         return NT_STATUS_OK;
3185 }
3186
3187 static NTSTATUS smbd_smb2_io_handler(struct smbd_server_connection *sconn,
3188                                      uint16_t fde_flags)
3189 {
3190         struct smbd_smb2_request_read_state *state = &sconn->smb2.request_read_state;
3191         struct smbd_smb2_request *req = NULL;
3192         size_t min_recvfile_size = UINT32_MAX;
3193         int ret;
3194         int err;
3195         bool retry;
3196         NTSTATUS status;
3197         NTTIME now;
3198
3199         if (!NT_STATUS_IS_OK(sconn->status)) {
3200                 /*
3201                  * we're not supposed to do any io
3202                  */
3203                 TEVENT_FD_NOT_READABLE(sconn->smb2.fde);
3204                 TEVENT_FD_NOT_WRITEABLE(sconn->smb2.fde);
3205                 return NT_STATUS_OK;
3206         }
3207
3208         if (fde_flags & TEVENT_FD_WRITE) {
3209                 status = smbd_smb2_flush_send_queue(sconn);
3210                 if (!NT_STATUS_IS_OK(status)) {
3211                         return status;
3212                 }
3213         }
3214
3215         if (!(fde_flags & TEVENT_FD_READ)) {
3216                 return NT_STATUS_OK;
3217         }
3218
3219         if (state->req == NULL) {
3220                 TEVENT_FD_NOT_READABLE(sconn->smb2.fde);
3221                 return NT_STATUS_OK;
3222         }
3223
3224 again:
3225         if (!state->hdr.done) {
3226                 state->hdr.done = true;
3227
3228                 state->vector.iov_base = (void *)state->hdr.nbt;
3229                 state->vector.iov_len = NBT_HDR_SIZE;
3230         }
3231
3232         ret = readv(sconn->sock, &state->vector, 1);
3233         if (ret == 0) {
3234                 /* propagate end of file */
3235                 return NT_STATUS_END_OF_FILE;
3236         }
3237         err = socket_error_from_errno(ret, errno, &retry);
3238         if (retry) {
3239                 /* retry later */
3240                 TEVENT_FD_READABLE(sconn->smb2.fde);
3241                 return NT_STATUS_OK;
3242         }
3243         if (err != 0) {
3244                 return map_nt_error_from_unix_common(err);
3245         }
3246
3247         if (ret < state->vector.iov_len) {
3248                 uint8_t *base;
3249                 base = (uint8_t *)state->vector.iov_base;
3250                 base += ret;
3251                 state->vector.iov_base = (void *)base;
3252                 state->vector.iov_len -= ret;
3253                 /* we have more to read */
3254                 TEVENT_FD_READABLE(sconn->smb2.fde);
3255                 return NT_STATUS_OK;
3256         }
3257
3258         if (state->pktlen > 0) {
3259                 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3260                         /*
3261                          * Not a possible receivefile write.
3262                          * Read the rest of the data.
3263                          */
3264                         state->doing_receivefile = false;
3265
3266                         state->pktbuf = talloc_realloc(state->req,
3267                                                        state->pktbuf,
3268                                                        uint8_t,
3269                                                        state->pktfull);
3270                         if (state->pktbuf == NULL) {
3271                                 return NT_STATUS_NO_MEMORY;
3272                         }
3273
3274                         state->vector.iov_base = (void *)(state->pktbuf +
3275                                 state->pktlen);
3276                         state->vector.iov_len = (state->pktfull -
3277                                 state->pktlen);
3278
3279                         state->pktlen = state->pktfull;
3280                         goto again;
3281                 }
3282
3283                 /*
3284                  * Either this is a receivefile write so we've
3285                  * done a short read, or if not we have all the data.
3286                  */
3287                 goto got_full;
3288         }
3289
3290         /*
3291          * Now we analyze the NBT header
3292          */
3293         if (state->hdr.nbt[0] != 0x00) {
3294                 state->min_recv_size = 0;
3295         }
3296         state->pktfull = smb2_len(state->hdr.nbt);
3297         if (state->pktfull == 0) {
3298                 goto got_full;
3299         }
3300
3301         if (state->min_recv_size != 0) {
3302                 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3303                 min_recvfile_size += state->min_recv_size;
3304         }
3305
3306         if (state->pktfull > min_recvfile_size) {
3307                 /*
3308                  * Might be a receivefile write. Read the SMB2 HEADER +
3309                  * SMB2_WRITE header first. Set 'doing_receivefile'
3310                  * as we're *attempting* receivefile write. If this
3311                  * turns out not to be a SMB2_WRITE request or otherwise
3312                  * not suitable then we'll just read the rest of the data
3313                  * the next time this function is called.
3314                  */
3315                 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3316                 state->doing_receivefile = true;
3317         } else {
3318                 state->pktlen = state->pktfull;
3319         }
3320
3321         state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3322         if (state->pktbuf == NULL) {
3323                 return NT_STATUS_NO_MEMORY;
3324         }
3325
3326         state->vector.iov_base = (void *)state->pktbuf;
3327         state->vector.iov_len = state->pktlen;
3328
3329         goto again;
3330
3331 got_full:
3332
3333         if (state->hdr.nbt[0] != 0x00) {
3334                 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3335                          state->hdr.nbt[0]));
3336
3337                 req = state->req;
3338                 ZERO_STRUCTP(state);
3339                 state->req = req;
3340                 state->min_recv_size = get_min_receive_file_size(state->req);
3341                 req = NULL;
3342                 goto again;
3343         }
3344
3345         req = state->req;
3346         state->req = NULL;
3347
3348         req->request_time = timeval_current();
3349         now = timeval_to_nttime(&req->request_time);
3350
3351         status = smbd_smb2_inbuf_parse_compound(req->sconn->conn,
3352                                                 now,
3353                                                 state->pktbuf,
3354                                                 state->pktlen,
3355                                                 req,
3356                                                 &req->in.vector,
3357                                                 &req->in.vector_count);
3358         if (!NT_STATUS_IS_OK(status)) {
3359                 return status;
3360         }
3361
3362         if (state->doing_receivefile) {
3363                 req->smb1req = talloc_zero(req, struct smb_request);
3364                 if (req->smb1req == NULL) {
3365                         return NT_STATUS_NO_MEMORY;
3366                 }
3367                 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3368         }
3369
3370         ZERO_STRUCTP(state);
3371
3372         req->current_idx = 1;
3373
3374         DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3375                  req->current_idx, req->in.vector_count));
3376
3377         status = smbd_smb2_request_validate(req);
3378         if (!NT_STATUS_IS_OK(status)) {
3379                 return status;
3380         }
3381
3382         status = smbd_smb2_request_setup_out(req);
3383         if (!NT_STATUS_IS_OK(status)) {
3384                 return status;
3385         }
3386
3387         status = smbd_smb2_request_dispatch(req);
3388         if (!NT_STATUS_IS_OK(status)) {
3389                 return status;
3390         }
3391
3392         sconn->num_requests++;
3393
3394         /* The timeout_processing function isn't run nearly
3395            often enough to implement 'max log size' without
3396            overrunning the size of the file by many megabytes.
3397            This is especially true if we are running at debug
3398            level 10.  Checking every 50 SMB2s is a nice
3399            tradeoff of performance vs log file size overrun. */
3400
3401         if ((sconn->num_requests % 50) == 0 &&
3402             need_to_check_log_size()) {
3403                 change_to_root_user();
3404                 check_log_size();
3405         }
3406
3407         status = smbd_smb2_request_next_incoming(sconn);
3408         if (!NT_STATUS_IS_OK(status)) {
3409                 return status;
3410         }
3411
3412         return NT_STATUS_OK;
3413 }
3414
3415 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3416                                          struct tevent_fd *fde,
3417                                          uint16_t flags,
3418                                          void *private_data)
3419 {
3420         struct smbd_server_connection *sconn =
3421                 talloc_get_type_abort(private_data,
3422                 struct smbd_server_connection);
3423         NTSTATUS status;
3424
3425         status = smbd_smb2_io_handler(sconn, flags);
3426         if (!NT_STATUS_IS_OK(status)) {
3427                 smbd_server_connection_terminate(sconn, nt_errstr(status));
3428                 return;
3429         }
3430 }