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