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