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