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