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