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