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