s3:smb2_server: there's no need to copy req->out.vector when we just keep the last...
[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                 req->current_idx = 1;
1218
1219                 /* Re-arrange the in.vectors. */
1220                 memmove(&req->in.vector[req->current_idx],
1221                         &req->in.vector[i],
1222                         sizeof(req->in.vector[0])*SMBD_SMB2_NUM_IOV_PER_REQ);
1223                 req->in.vector_count = req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ;
1224
1225                 /* Reset the new in size. */
1226                 smb2_setup_nbt_length(req->in.vector, req->in.vector_count);
1227
1228                 /* Re-arrange the out.vectors. */
1229                 memmove(&req->out.vector[req->current_idx],
1230                         &req->out.vector[i],
1231                         sizeof(req->out.vector[0])*SMBD_SMB2_NUM_IOV_PER_REQ);
1232                 req->out.vector_count = req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ;
1233
1234                 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1235                 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1236                 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1237         }
1238
1239         defer_endtime = timeval_current_ofs_usec(defer_time);
1240         req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1241                                          req, defer_endtime,
1242                                          smbd_smb2_request_pending_timer,
1243                                          req);
1244         if (req->async_te == NULL) {
1245                 return NT_STATUS_NO_MEMORY;
1246         }
1247
1248         return NT_STATUS_OK;
1249 }
1250
1251 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1252                                             struct tevent_timer *te,
1253                                             struct timeval current_time,
1254                                             void *private_data)
1255 {
1256         struct smbd_smb2_request *req =
1257                 talloc_get_type_abort(private_data,
1258                 struct smbd_smb2_request);
1259         struct smbd_smb2_request_pending_state *state = NULL;
1260         uint8_t *outhdr = NULL;
1261         const uint8_t *inhdr = NULL;
1262         uint8_t *hdr = NULL;
1263         uint8_t *body = NULL;
1264         uint32_t flags = 0;
1265         uint64_t message_id = 0;
1266         uint64_t async_id = 0;
1267         struct tevent_req *subreq = NULL;
1268
1269         TALLOC_FREE(req->async_te);
1270
1271         /* Ensure our final reply matches the interim one. */
1272         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1273         outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1274         flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1275         message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1276
1277         async_id = message_id; /* keep it simple for now... */
1278
1279         SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1280         SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1281
1282         DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1283                 "going async\n",
1284                 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1285                 (unsigned long long)async_id ));
1286
1287         /*
1288          * What we send is identical to a smbd_smb2_request_error
1289          * packet with an error status of STATUS_PENDING. Make use
1290          * of this fact sometime when refactoring. JRA.
1291          */
1292
1293         state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1294         if (state == NULL) {
1295                 smbd_server_connection_terminate(req->sconn,
1296                                                  nt_errstr(NT_STATUS_NO_MEMORY));
1297                 return;
1298         }
1299         state->sconn = req->sconn;
1300
1301         state->vector[0].iov_base = (void *)state->buf;
1302         state->vector[0].iov_len = 4;
1303
1304         state->vector[1].iov_base = state->buf + 4;
1305         state->vector[1].iov_len = SMB2_HDR_BODY;
1306
1307         state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
1308         state->vector[2].iov_len = 9;
1309
1310         smb2_setup_nbt_length(state->vector, 3);
1311
1312         hdr = (uint8_t *)state->vector[1].iov_base;
1313         body = (uint8_t *)state->vector[2].iov_base;
1314
1315         SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1316         SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1317         SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1318         SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1319         SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1320
1321         SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1322         SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1323         SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1324         SBVAL(hdr, SMB2_HDR_PID, async_id);
1325         SBVAL(hdr, SMB2_HDR_SESSION_ID,
1326                 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1327         memcpy(hdr+SMB2_HDR_SIGNATURE,
1328                outhdr+SMB2_HDR_SIGNATURE, 16);
1329
1330         SSVAL(body, 0x00, 0x08 + 1);
1331
1332         SCVAL(body, 0x02, 0);
1333         SCVAL(body, 0x03, 0);
1334         SIVAL(body, 0x04, 0);
1335         /* Match W2K8R2... */
1336         SCVAL(body, 0x08, 0x21);
1337
1338         /* Ensure we correctly go through crediting. Grant
1339            the credits now, and zero credits on the final
1340            response. */
1341         smb2_set_operation_credit(req->sconn,
1342                         SMBD_SMB2_IN_HDR_IOV(req),
1343                         &state->vector[1]);
1344
1345         SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1346
1347         if (req->do_signing) {
1348                 NTSTATUS status;
1349                 struct smbXsrv_session *x = req->session;
1350                 struct smbXsrv_connection *conn = x->connection;
1351                 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1352
1353                 status = smb2_signing_sign_pdu(signing_key,
1354                                                conn->protocol,
1355                                                &state->vector[1], 2);
1356                 if (!NT_STATUS_IS_OK(status)) {
1357                         smbd_server_connection_terminate(req->sconn,
1358                                                 nt_errstr(status));
1359                         return;
1360                 }
1361         }
1362
1363         subreq = tstream_writev_queue_send(state,
1364                                         state->sconn->ev_ctx,
1365                                         state->sconn->smb2.stream,
1366                                         state->sconn->smb2.send_queue,
1367                                         state->vector,
1368                                         3);
1369         if (subreq == NULL) {
1370                 smbd_server_connection_terminate(state->sconn,
1371                                                  nt_errstr(NT_STATUS_NO_MEMORY));
1372                 return;
1373         }
1374         tevent_req_set_callback(subreq,
1375                         smbd_smb2_request_pending_writev_done,
1376                         state);
1377 }
1378
1379 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1380 {
1381         struct smbd_server_connection *sconn = req->sconn;
1382         struct smbd_smb2_request *cur;
1383         const uint8_t *inhdr;
1384         uint32_t flags;
1385         uint64_t search_message_id;
1386         uint64_t search_async_id;
1387         uint64_t found_id;
1388
1389         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1390
1391         flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1392         search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1393         search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1394
1395         /*
1396          * we don't need the request anymore
1397          * cancel requests never have a response
1398          */
1399         DLIST_REMOVE(req->sconn->smb2.requests, req);
1400         TALLOC_FREE(req);
1401
1402         for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1403                 const uint8_t *outhdr;
1404                 uint64_t message_id;
1405                 uint64_t async_id;
1406
1407                 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1408
1409                 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1410                 async_id = BVAL(outhdr, SMB2_HDR_PID);
1411
1412                 if (flags & SMB2_HDR_FLAG_ASYNC) {
1413                         if (search_async_id == async_id) {
1414                                 found_id = async_id;
1415                                 break;
1416                         }
1417                 } else {
1418                         if (search_message_id == message_id) {
1419                                 found_id = message_id;
1420                                 break;
1421                         }
1422                 }
1423         }
1424
1425         if (cur && cur->subreq) {
1426                 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1427                 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1428                         "cancel opcode[%s] mid %llu\n",
1429                         smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1430                         (unsigned long long)found_id ));
1431                 tevent_req_cancel(cur->subreq);
1432         }
1433
1434         return NT_STATUS_OK;
1435 }
1436
1437 /*************************************************************
1438  Ensure an incoming tid is a valid one for us to access.
1439  Change to the associated uid credentials and chdir to the
1440  valid tid directory.
1441 *************************************************************/
1442
1443 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1444 {
1445         const uint8_t *inhdr;
1446         uint32_t in_flags;
1447         uint32_t in_tid;
1448         struct smbXsrv_tcon *tcon;
1449         NTSTATUS status;
1450         NTTIME now = timeval_to_nttime(&req->request_time);
1451
1452         req->tcon = NULL;
1453
1454         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1455
1456         in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1457         in_tid = IVAL(inhdr, SMB2_HDR_TID);
1458
1459         if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1460                 in_tid = req->last_tid;
1461         }
1462
1463         status = smb2srv_tcon_lookup(req->session,
1464                                      in_tid, now, &tcon);
1465         if (!NT_STATUS_IS_OK(status)) {
1466                 return status;
1467         }
1468
1469         if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1470                 return NT_STATUS_ACCESS_DENIED;
1471         }
1472
1473         /* should we pass FLAG_CASELESS_PATHNAMES here? */
1474         if (!set_current_service(tcon->compat, 0, true)) {
1475                 return NT_STATUS_ACCESS_DENIED;
1476         }
1477
1478         req->tcon = tcon;
1479         req->last_tid = in_tid;
1480
1481         return NT_STATUS_OK;
1482 }
1483
1484 /*************************************************************
1485  Ensure an incoming session_id is a valid one for us to access.
1486 *************************************************************/
1487
1488 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1489 {
1490         const uint8_t *inhdr;
1491         uint32_t in_flags;
1492         uint16_t in_opcode;
1493         uint64_t in_session_id;
1494         struct smbXsrv_session *session = NULL;
1495         struct auth_session_info *session_info;
1496         NTSTATUS status;
1497         NTTIME now = timeval_to_nttime(&req->request_time);
1498
1499         req->session = NULL;
1500         req->tcon = NULL;
1501
1502         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1503
1504         in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1505         in_opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1506         in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1507
1508         if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1509                 in_session_id = req->last_session_id;
1510         }
1511
1512         /* lookup an existing session */
1513         status = smb2srv_session_lookup(req->sconn->conn,
1514                                         in_session_id, now,
1515                                         &session);
1516         if (session) {
1517                 req->session = session;
1518                 req->last_session_id = in_session_id;
1519         }
1520         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1521                 switch (in_opcode) {
1522                 case SMB2_OP_SESSSETUP:
1523                         status = NT_STATUS_OK;
1524                         break;
1525                 default:
1526                         break;
1527                 }
1528         }
1529         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1530                 switch (in_opcode) {
1531                 case SMB2_OP_TCON:
1532                 case SMB2_OP_CREATE:
1533                 case SMB2_OP_GETINFO:
1534                 case SMB2_OP_SETINFO:
1535                         return NT_STATUS_INVALID_HANDLE;
1536                 default:
1537                         /*
1538                          * Notice the check for
1539                          * (session_info == NULL)
1540                          * below.
1541                          */
1542                         status = NT_STATUS_OK;
1543                         break;
1544                 }
1545         }
1546         if (!NT_STATUS_IS_OK(status)) {
1547                 return status;
1548         }
1549
1550         session_info = session->global->auth_session_info;
1551         if (session_info == NULL) {
1552                 return NT_STATUS_INVALID_HANDLE;
1553         }
1554
1555         set_current_user_info(session_info->unix_info->sanitized_username,
1556                               session_info->unix_info->unix_name,
1557                               session_info->info->domain_name);
1558
1559         return NT_STATUS_OK;
1560 }
1561
1562 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1563                                                 uint32_t data_length)
1564 {
1565         uint16_t needed_charge;
1566         uint16_t credit_charge = 1;
1567         const uint8_t *inhdr;
1568
1569         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1570
1571         if (req->sconn->smb2.supports_multicredit) {
1572                 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1573                 credit_charge = MAX(credit_charge, 1);
1574         }
1575
1576         needed_charge = (data_length - 1)/ 65536 + 1;
1577
1578         DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1579                    (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1580                    credit_charge, needed_charge));
1581
1582         if (needed_charge > credit_charge) {
1583                 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1584                           credit_charge, needed_charge));
1585                 return NT_STATUS_INVALID_PARAMETER;
1586         }
1587
1588         return NT_STATUS_OK;
1589 }
1590
1591 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1592                                         size_t expected_body_size)
1593 {
1594         const uint8_t *inhdr;
1595         uint16_t opcode;
1596         const uint8_t *inbody;
1597         int i = req->current_idx;
1598         size_t body_size;
1599         size_t min_dyn_size = expected_body_size & 0x00000001;
1600
1601         /*
1602          * The following should be checked already.
1603          */
1604         if ((i+2) > req->in.vector_count) {
1605                 return NT_STATUS_INTERNAL_ERROR;
1606         }
1607         if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1608                 return NT_STATUS_INTERNAL_ERROR;
1609         }
1610         if (req->in.vector[i+1].iov_len < 2) {
1611                 return NT_STATUS_INTERNAL_ERROR;
1612         }
1613
1614         inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1615         opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1616
1617         switch (opcode) {
1618         case SMB2_OP_IOCTL:
1619         case SMB2_OP_GETINFO:
1620                 min_dyn_size = 0;
1621                 break;
1622         }
1623
1624         /*
1625          * Now check the expected body size,
1626          * where the last byte might be in the
1627          * dynamic section..
1628          */
1629         if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1630                 return NT_STATUS_INVALID_PARAMETER;
1631         }
1632         if (req->in.vector[i+2].iov_len < min_dyn_size) {
1633                 return NT_STATUS_INVALID_PARAMETER;
1634         }
1635
1636         inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1637
1638         body_size = SVAL(inbody, 0x00);
1639         if (body_size != expected_body_size) {
1640                 return NT_STATUS_INVALID_PARAMETER;
1641         }
1642
1643         return NT_STATUS_OK;
1644 }
1645
1646 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1647 {
1648         struct smbXsrv_connection *conn = req->sconn->conn;
1649         const struct smbd_smb2_dispatch_table *call = NULL;
1650         const uint8_t *inhdr;
1651         uint16_t opcode;
1652         uint32_t flags;
1653         uint64_t mid;
1654         NTSTATUS status;
1655         NTSTATUS session_status;
1656         uint32_t allowed_flags;
1657         NTSTATUS return_value;
1658         struct smbXsrv_session *x = NULL;
1659         bool signing_required = false;
1660
1661         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1662
1663         /* TODO: verify more things */
1664
1665         flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1666         opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1667         mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1668         DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1669                 smb2_opcode_name(opcode),
1670                 (unsigned long long)mid));
1671
1672         if (conn->protocol >= PROTOCOL_SMB2_02) {
1673                 /*
1674                  * once the protocol is negotiated
1675                  * SMB2_OP_NEGPROT is not allowed anymore
1676                  */
1677                 if (opcode == SMB2_OP_NEGPROT) {
1678                         /* drop the connection */
1679                         return NT_STATUS_INVALID_PARAMETER;
1680                 }
1681         } else {
1682                 /*
1683                  * if the protocol is not negotiated yet
1684                  * only SMB2_OP_NEGPROT is allowed.
1685                  */
1686                 if (opcode != SMB2_OP_NEGPROT) {
1687                         /* drop the connection */
1688                         return NT_STATUS_INVALID_PARAMETER;
1689                 }
1690         }
1691
1692         call = smbd_smb2_call(opcode);
1693         if (call == NULL) {
1694                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1695         }
1696
1697         allowed_flags = SMB2_HDR_FLAG_CHAINED |
1698                         SMB2_HDR_FLAG_SIGNED |
1699                         SMB2_HDR_FLAG_DFS;
1700         if (opcode == SMB2_OP_CANCEL) {
1701                 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1702         }
1703         if ((flags & ~allowed_flags) != 0) {
1704                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1705         }
1706
1707         /*
1708          * Check if the client provided a valid session id,
1709          * if so smbd_smb2_request_check_session() calls
1710          * set_current_user_info().
1711          *
1712          * As some command don't require a valid session id
1713          * we defer the check of the session_status
1714          */
1715         session_status = smbd_smb2_request_check_session(req);
1716         x = req->session;
1717
1718         if (x != NULL) {
1719                 signing_required = x->global->signing_required;
1720
1721                 if (opcode == SMB2_OP_SESSSETUP &&
1722                     x->global->channels[0].signing_key.length) {
1723                         signing_required = true;
1724                 }
1725         }
1726
1727         req->do_signing = false;
1728         if (flags & SMB2_HDR_FLAG_SIGNED) {
1729                 DATA_BLOB signing_key;
1730
1731                 if (x == NULL) {
1732                         return smbd_smb2_request_error(
1733                                 req, NT_STATUS_ACCESS_DENIED);
1734                 }
1735
1736                 signing_key = x->global->channels[0].signing_key;
1737
1738                 if (!NT_STATUS_IS_OK(session_status)) {
1739                         return smbd_smb2_request_error(req, session_status);
1740                 }
1741
1742                 req->do_signing = true;
1743                 status = smb2_signing_check_pdu(signing_key,
1744                                                 conn->protocol,
1745                                                 SMBD_SMB2_IN_HDR_IOV(req),
1746                                                 SMBD_SMB2_NUM_IOV_PER_REQ);
1747                 if (!NT_STATUS_IS_OK(status)) {
1748                         return smbd_smb2_request_error(req, status);
1749                 }
1750         } else if (opcode == SMB2_OP_CANCEL) {
1751                 /* Cancel requests are allowed to skip the signing */
1752         } else if (signing_required) {
1753                 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1754         }
1755
1756         if (flags & SMB2_HDR_FLAG_CHAINED) {
1757                 /*
1758                  * This check is mostly for giving the correct error code
1759                  * for compounded requests.
1760                  *
1761                  * TODO: we may need to move this after the session
1762                  *       and tcon checks.
1763                  */
1764                 if (!NT_STATUS_IS_OK(req->next_status)) {
1765                         return smbd_smb2_request_error(req, req->next_status);
1766                 }
1767         } else {
1768                 req->compat_chain_fsp = NULL;
1769         }
1770
1771         if (req->compound_related) {
1772                 req->sconn->smb2.compound_related_in_progress = true;
1773         }
1774
1775         if (call->need_session) {
1776                 if (!NT_STATUS_IS_OK(session_status)) {
1777                         return smbd_smb2_request_error(req, session_status);
1778                 }
1779         }
1780
1781         if (call->need_tcon) {
1782                 SMB_ASSERT(call->need_session);
1783
1784                 /*
1785                  * This call needs to be run as user.
1786                  *
1787                  * smbd_smb2_request_check_tcon()
1788                  * calls change_to_user() on success.
1789                  */
1790                 status = smbd_smb2_request_check_tcon(req);
1791                 if (!NT_STATUS_IS_OK(status)) {
1792                         return smbd_smb2_request_error(req, status);
1793                 }
1794         }
1795
1796         if (call->as_root) {
1797                 /* This call needs to be run as root */
1798                 change_to_root_user();
1799         } else {
1800                 SMB_ASSERT(call->need_tcon);
1801         }
1802
1803         switch (opcode) {
1804         case SMB2_OP_NEGPROT:
1805                 {
1806                         START_PROFILE(smb2_negprot);
1807                         return_value = smbd_smb2_request_process_negprot(req);
1808                         END_PROFILE(smb2_negprot);
1809                 }
1810                 break;
1811
1812         case SMB2_OP_SESSSETUP:
1813                 {
1814                         START_PROFILE(smb2_sesssetup);
1815                         return_value = smbd_smb2_request_process_sesssetup(req);
1816                         END_PROFILE(smb2_sesssetup);
1817                 }
1818                 break;
1819
1820         case SMB2_OP_LOGOFF:
1821                 {
1822                         START_PROFILE(smb2_logoff);
1823                         return_value = smbd_smb2_request_process_logoff(req);
1824                         END_PROFILE(smb2_logoff);
1825                 }
1826                 break;
1827
1828         case SMB2_OP_TCON:
1829                 {
1830                         START_PROFILE(smb2_tcon);
1831                         return_value = smbd_smb2_request_process_tcon(req);
1832                         END_PROFILE(smb2_tcon);
1833                 }
1834                 break;
1835
1836         case SMB2_OP_TDIS:
1837                 {
1838                         START_PROFILE(smb2_tdis);
1839                         return_value = smbd_smb2_request_process_tdis(req);
1840                         END_PROFILE(smb2_tdis);
1841                 }
1842                 break;
1843
1844         case SMB2_OP_CREATE:
1845                 {
1846                         START_PROFILE(smb2_create);
1847                         return_value = smbd_smb2_request_process_create(req);
1848                         END_PROFILE(smb2_create);
1849                 }
1850                 break;
1851
1852         case SMB2_OP_CLOSE:
1853                 {
1854                         START_PROFILE(smb2_close);
1855                         return_value = smbd_smb2_request_process_close(req);
1856                         END_PROFILE(smb2_close);
1857                 }
1858                 break;
1859
1860         case SMB2_OP_FLUSH:
1861                 {
1862                         START_PROFILE(smb2_flush);
1863                         return_value = smbd_smb2_request_process_flush(req);
1864                         END_PROFILE(smb2_flush);
1865                 }
1866                 break;
1867
1868         case SMB2_OP_READ:
1869                 {
1870                         START_PROFILE(smb2_read);
1871                         return_value = smbd_smb2_request_process_read(req);
1872                         END_PROFILE(smb2_read);
1873                 }
1874                 break;
1875
1876         case SMB2_OP_WRITE:
1877                 {
1878                         START_PROFILE(smb2_write);
1879                         return_value = smbd_smb2_request_process_write(req);
1880                         END_PROFILE(smb2_write);
1881                 }
1882                 break;
1883
1884         case SMB2_OP_LOCK:
1885                 {
1886                         START_PROFILE(smb2_lock);
1887                         return_value = smbd_smb2_request_process_lock(req);
1888                         END_PROFILE(smb2_lock);
1889                 }
1890                 break;
1891
1892         case SMB2_OP_IOCTL:
1893                 {
1894                         START_PROFILE(smb2_ioctl);
1895                         return_value = smbd_smb2_request_process_ioctl(req);
1896                         END_PROFILE(smb2_ioctl);
1897                 }
1898                 break;
1899
1900         case SMB2_OP_CANCEL:
1901                 {
1902                         START_PROFILE(smb2_cancel);
1903                         return_value = smbd_smb2_request_process_cancel(req);
1904                         END_PROFILE(smb2_cancel);
1905                 }
1906                 break;
1907
1908         case SMB2_OP_KEEPALIVE:
1909                 {
1910                         START_PROFILE(smb2_keepalive);
1911                         return_value = smbd_smb2_request_process_keepalive(req);
1912                         END_PROFILE(smb2_keepalive);
1913                 }
1914                 break;
1915
1916         case SMB2_OP_FIND:
1917                 {
1918                         START_PROFILE(smb2_find);
1919                         return_value = smbd_smb2_request_process_find(req);
1920                         END_PROFILE(smb2_find);
1921                 }
1922                 break;
1923
1924         case SMB2_OP_NOTIFY:
1925                 {
1926                         START_PROFILE(smb2_notify);
1927                         return_value = smbd_smb2_request_process_notify(req);
1928                         END_PROFILE(smb2_notify);
1929                 }
1930                 break;
1931
1932         case SMB2_OP_GETINFO:
1933                 {
1934                         START_PROFILE(smb2_getinfo);
1935                         return_value = smbd_smb2_request_process_getinfo(req);
1936                         END_PROFILE(smb2_getinfo);
1937                 }
1938                 break;
1939
1940         case SMB2_OP_SETINFO:
1941                 {
1942                         START_PROFILE(smb2_setinfo);
1943                         return_value = smbd_smb2_request_process_setinfo(req);
1944                         END_PROFILE(smb2_setinfo);
1945                 }
1946                 break;
1947
1948         case SMB2_OP_BREAK:
1949                 {
1950                         START_PROFILE(smb2_break);
1951                         return_value = smbd_smb2_request_process_break(req);
1952                         END_PROFILE(smb2_break);
1953                 }
1954                 break;
1955
1956         default:
1957                 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1958                 break;
1959         }
1960         return return_value;
1961 }
1962
1963 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1964 {
1965         struct tevent_req *subreq;
1966         struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
1967         struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
1968
1969         req->subreq = NULL;
1970         TALLOC_FREE(req->async_te);
1971
1972         req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
1973
1974         if (req->current_idx < req->out.vector_count) {
1975                 /*
1976                  * We must process the remaining compound
1977                  * SMB2 requests before any new incoming SMB2
1978                  * requests. This is because incoming SMB2
1979                  * requests may include a cancel for a
1980                  * compound request we haven't processed
1981                  * yet.
1982                  */
1983                 struct tevent_immediate *im = tevent_create_immediate(req);
1984                 if (!im) {
1985                         return NT_STATUS_NO_MEMORY;
1986                 }
1987                 tevent_schedule_immediate(im,
1988                                         req->sconn->ev_ctx,
1989                                         smbd_smb2_request_dispatch_immediate,
1990                                         req);
1991                 return NT_STATUS_OK;
1992         }
1993
1994         if (req->compound_related) {
1995                 req->sconn->smb2.compound_related_in_progress = false;
1996         }
1997
1998         smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1999
2000         /* Set credit for these operations (zero credits if this
2001            is a final reply for an async operation). */
2002         smb2_calculate_credits(req, req);
2003
2004         if (req->do_signing) {
2005                 NTSTATUS status;
2006                 struct smbXsrv_session *x = req->session;
2007                 struct smbXsrv_connection *conn = x->connection;
2008                 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2009
2010                 status = smb2_signing_sign_pdu(signing_key,
2011                                                conn->protocol,
2012                                                outhdr,
2013                                                SMBD_SMB2_NUM_IOV_PER_REQ);
2014                 if (!NT_STATUS_IS_OK(status)) {
2015                         return status;
2016                 }
2017         }
2018
2019         if (DEBUGLEVEL >= 10) {
2020                 dbgtext("smbd_smb2_request_reply: sending...\n");
2021                 print_req_vectors(req);
2022         }
2023
2024         /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2025         if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2026             outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2027                 /* Dynamic part is NULL. Chop it off,
2028                    We're going to send it via sendfile. */
2029                 req->out.vector_count -= 1;
2030         }
2031
2032         subreq = tstream_writev_queue_send(req,
2033                                            req->sconn->ev_ctx,
2034                                            req->sconn->smb2.stream,
2035                                            req->sconn->smb2.send_queue,
2036                                            req->out.vector,
2037                                            req->out.vector_count);
2038         if (subreq == NULL) {
2039                 return NT_STATUS_NO_MEMORY;
2040         }
2041         tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
2042         /*
2043          * We're done with this request -
2044          * move it off the "being processed" queue.
2045          */
2046         DLIST_REMOVE(req->sconn->smb2.requests, req);
2047
2048         return NT_STATUS_OK;
2049 }
2050
2051 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2052
2053 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2054                                         struct tevent_immediate *im,
2055                                         void *private_data)
2056 {
2057         struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2058                                         struct smbd_smb2_request);
2059         struct smbd_server_connection *sconn = req->sconn;
2060         NTSTATUS status;
2061
2062         TALLOC_FREE(im);
2063
2064         if (DEBUGLEVEL >= 10) {
2065                 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2066                         req->current_idx, req->in.vector_count));
2067                 print_req_vectors(req);
2068         }
2069
2070         status = smbd_smb2_request_dispatch(req);
2071         if (!NT_STATUS_IS_OK(status)) {
2072                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2073                 return;
2074         }
2075
2076         status = smbd_smb2_request_next_incoming(sconn);
2077         if (!NT_STATUS_IS_OK(status)) {
2078                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2079                 return;
2080         }
2081 }
2082
2083 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
2084 {
2085         struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
2086                                         struct smbd_smb2_request);
2087         struct smbd_server_connection *sconn = req->sconn;
2088         int ret;
2089         int sys_errno;
2090         NTSTATUS status;
2091
2092         ret = tstream_writev_queue_recv(subreq, &sys_errno);
2093         TALLOC_FREE(subreq);
2094         TALLOC_FREE(req);
2095         if (ret == -1) {
2096                 status = map_nt_error_from_unix(sys_errno);
2097                 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2098                         nt_errstr(status)));
2099                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2100                 return;
2101         }
2102
2103         status = smbd_smb2_request_next_incoming(sconn);
2104         if (!NT_STATUS_IS_OK(status)) {
2105                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2106                 return;
2107         }
2108 }
2109
2110 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2111                                    NTSTATUS status,
2112                                    DATA_BLOB body, DATA_BLOB *dyn,
2113                                    const char *location)
2114 {
2115         uint8_t *outhdr;
2116         int i = req->current_idx;
2117         uint32_t next_command_ofs;
2118
2119         DEBUG(10,("smbd_smb2_request_done_ex: "
2120                   "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2121                   i, nt_errstr(status), (unsigned int)body.length,
2122                   dyn ? "yes": "no",
2123                   (unsigned int)(dyn ? dyn->length : 0),
2124                   location));
2125
2126         if (body.length < 2) {
2127                 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2128         }
2129
2130         if ((body.length % 2) != 0) {
2131                 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2132         }
2133
2134         outhdr = (uint8_t *)req->out.vector[i].iov_base;
2135
2136         next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2137         SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2138
2139         req->out.vector[i+1].iov_base = (void *)body.data;
2140         req->out.vector[i+1].iov_len = body.length;
2141
2142         if (dyn) {
2143                 req->out.vector[i+2].iov_base   = (void *)dyn->data;
2144                 req->out.vector[i+2].iov_len    = dyn->length;
2145         } else {
2146                 req->out.vector[i+2].iov_base = NULL;
2147                 req->out.vector[i+2].iov_len = 0;
2148         }
2149
2150         /* see if we need to recalculate the offset to the next response */
2151         if (next_command_ofs > 0) {
2152                 next_command_ofs  = SMB2_HDR_BODY;
2153                 next_command_ofs += req->out.vector[i+1].iov_len;
2154                 next_command_ofs += req->out.vector[i+2].iov_len;
2155         }
2156
2157         if ((next_command_ofs % 8) != 0) {
2158                 size_t pad_size = 8 - (next_command_ofs % 8);
2159                 if (req->out.vector[i+2].iov_len == 0) {
2160                         /*
2161                          * if the dyn buffer is empty
2162                          * we can use it to add padding
2163                          */
2164                         uint8_t *pad;
2165
2166                         pad = talloc_zero_array(req->out.vector,
2167                                                 uint8_t, pad_size);
2168                         if (pad == NULL) {
2169                                 return smbd_smb2_request_error(req,
2170                                                 NT_STATUS_NO_MEMORY);
2171                         }
2172
2173                         req->out.vector[i+2].iov_base = (void *)pad;
2174                         req->out.vector[i+2].iov_len = pad_size;
2175                 } else {
2176                         /*
2177                          * For now we copy the dynamic buffer
2178                          * and add the padding to the new buffer
2179                          */
2180                         size_t old_size;
2181                         uint8_t *old_dyn;
2182                         size_t new_size;
2183                         uint8_t *new_dyn;
2184
2185                         old_size = req->out.vector[i+2].iov_len;
2186                         old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2187
2188                         new_size = old_size + pad_size;
2189                         new_dyn = talloc_zero_array(req->out.vector,
2190                                                uint8_t, new_size);
2191                         if (new_dyn == NULL) {
2192                                 return smbd_smb2_request_error(req,
2193                                                 NT_STATUS_NO_MEMORY);
2194                         }
2195
2196                         memcpy(new_dyn, old_dyn, old_size);
2197                         memset(new_dyn + old_size, 0, pad_size);
2198
2199                         req->out.vector[i+2].iov_base = (void *)new_dyn;
2200                         req->out.vector[i+2].iov_len = new_size;
2201                 }
2202                 next_command_ofs += pad_size;
2203         }
2204
2205         SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2206
2207         return smbd_smb2_request_reply(req);
2208 }
2209
2210 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2211                                     NTSTATUS status,
2212                                     DATA_BLOB *info,
2213                                     const char *location)
2214 {
2215         DATA_BLOB body;
2216         int i = req->current_idx;
2217         uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2218
2219         DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2220                   i, nt_errstr(status), info ? " +info" : "",
2221                   location));
2222
2223         body.data = outhdr + SMB2_HDR_BODY;
2224         body.length = 8;
2225         SSVAL(body.data, 0, 9);
2226
2227         if (info) {
2228                 SIVAL(body.data, 0x04, info->length);
2229         } else {
2230                 /* Allocated size of req->out.vector[i].iov_base
2231                  * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2232                  * 1 byte without having to do an alloc.
2233                  */
2234                 info = talloc_zero_array(req->out.vector,
2235                                         DATA_BLOB,
2236                                         1);
2237                 if (!info) {
2238                         return NT_STATUS_NO_MEMORY;
2239                 }
2240                 info->data = ((uint8_t *)outhdr) +
2241                         OUTVEC_ALLOC_SIZE - 1;
2242                 info->length = 1;
2243                 SCVAL(info->data, 0, 0);
2244         }
2245
2246         /*
2247          * if a request fails, all other remaining
2248          * compounded requests should fail too
2249          */
2250         req->next_status = NT_STATUS_INVALID_PARAMETER;
2251
2252         return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2253 }
2254
2255
2256 struct smbd_smb2_send_oplock_break_state {
2257         struct smbd_server_connection *sconn;
2258         uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2259         struct iovec vector;
2260 };
2261
2262 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2263
2264 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2265                                      uint64_t file_id_persistent,
2266                                      uint64_t file_id_volatile,
2267                                      uint8_t oplock_level)
2268 {
2269         struct smbd_smb2_send_oplock_break_state *state;
2270         struct tevent_req *subreq;
2271         uint8_t *hdr;
2272         uint8_t *body;
2273
2274         state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2275         if (state == NULL) {
2276                 return NT_STATUS_NO_MEMORY;
2277         }
2278         state->sconn = sconn;
2279
2280         state->vector.iov_base = (void *)state->buf;
2281         state->vector.iov_len = sizeof(state->buf);
2282
2283         _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2284         hdr = state->buf + 4;
2285         body = hdr + SMB2_HDR_BODY;
2286
2287         SIVAL(hdr, 0,                           SMB2_MAGIC);
2288         SSVAL(hdr, SMB2_HDR_LENGTH,             SMB2_HDR_BODY);
2289         SSVAL(hdr, SMB2_HDR_EPOCH,              0);
2290         SIVAL(hdr, SMB2_HDR_STATUS,             0);
2291         SSVAL(hdr, SMB2_HDR_OPCODE,             SMB2_OP_BREAK);
2292         SSVAL(hdr, SMB2_HDR_CREDIT,             0);
2293         SIVAL(hdr, SMB2_HDR_FLAGS,              SMB2_HDR_FLAG_REDIRECT);
2294         SIVAL(hdr, SMB2_HDR_NEXT_COMMAND,       0);
2295         SBVAL(hdr, SMB2_HDR_MESSAGE_ID,         UINT64_MAX);
2296         SIVAL(hdr, SMB2_HDR_PID,                0);
2297         SIVAL(hdr, SMB2_HDR_TID,                0);
2298         SBVAL(hdr, SMB2_HDR_SESSION_ID,         0);
2299         memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2300
2301         SSVAL(body, 0x00, 0x18);
2302
2303         SCVAL(body, 0x02, oplock_level);
2304         SCVAL(body, 0x03, 0);           /* reserved */
2305         SIVAL(body, 0x04, 0);           /* reserved */
2306         SBVAL(body, 0x08, file_id_persistent);
2307         SBVAL(body, 0x10, file_id_volatile);
2308
2309         subreq = tstream_writev_queue_send(state,
2310                                            sconn->ev_ctx,
2311                                            sconn->smb2.stream,
2312                                            sconn->smb2.send_queue,
2313                                            &state->vector, 1);
2314         if (subreq == NULL) {
2315                 return NT_STATUS_NO_MEMORY;
2316         }
2317         tevent_req_set_callback(subreq,
2318                                 smbd_smb2_oplock_break_writev_done,
2319                                 state);
2320
2321         return NT_STATUS_OK;
2322 }
2323
2324 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2325 {
2326         struct smbd_smb2_send_oplock_break_state *state =
2327                 tevent_req_callback_data(subreq,
2328                 struct smbd_smb2_send_oplock_break_state);
2329         struct smbd_server_connection *sconn = state->sconn;
2330         int ret;
2331         int sys_errno;
2332
2333         ret = tstream_writev_queue_recv(subreq, &sys_errno);
2334         TALLOC_FREE(subreq);
2335         if (ret == -1) {
2336                 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2337                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2338                 return;
2339         }
2340
2341         TALLOC_FREE(state);
2342 }
2343
2344 struct smbd_smb2_request_read_state {
2345         struct tevent_context *ev;
2346         struct smbd_server_connection *sconn;
2347         struct smbd_smb2_request *smb2_req;
2348         struct {
2349                 uint8_t nbt[NBT_HDR_SIZE];
2350                 bool done;
2351         } hdr;
2352         size_t pktlen;
2353         uint8_t *pktbuf;
2354 };
2355
2356 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2357                                          void *private_data,
2358                                          TALLOC_CTX *mem_ctx,
2359                                          struct iovec **_vector,
2360                                          size_t *_count);
2361 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2362
2363 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2364                                         struct tevent_context *ev,
2365                                         struct smbd_server_connection *sconn)
2366 {
2367         struct tevent_req *req;
2368         struct smbd_smb2_request_read_state *state;
2369         struct tevent_req *subreq;
2370
2371         req = tevent_req_create(mem_ctx, &state,
2372                                 struct smbd_smb2_request_read_state);
2373         if (req == NULL) {
2374                 return NULL;
2375         }
2376         state->ev = ev;
2377         state->sconn = sconn;
2378
2379         state->smb2_req = smbd_smb2_request_allocate(state);
2380         if (tevent_req_nomem(state->smb2_req, req)) {
2381                 return tevent_req_post(req, ev);
2382         }
2383         state->smb2_req->sconn = sconn;
2384
2385         subreq = tstream_readv_pdu_queue_send(state->smb2_req,
2386                                         state->ev,
2387                                         state->sconn->smb2.stream,
2388                                         state->sconn->smb2.recv_queue,
2389                                         smbd_smb2_request_next_vector,
2390                                         state);
2391         if (tevent_req_nomem(subreq, req)) {
2392                 return tevent_req_post(req, ev);
2393         }
2394         tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2395
2396         return req;
2397 }
2398
2399 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2400                                          void *private_data,
2401                                          TALLOC_CTX *mem_ctx,
2402                                          struct iovec **_vector,
2403                                          size_t *_count)
2404 {
2405         struct smbd_smb2_request_read_state *state =
2406                 talloc_get_type_abort(private_data,
2407                 struct smbd_smb2_request_read_state);
2408         struct iovec *vector;
2409
2410         if (state->pktlen > 0) {
2411                 /* if there're no remaining bytes, we're done */
2412                 *_vector = NULL;
2413                 *_count = 0;
2414                 return 0;
2415         }
2416
2417         if (!state->hdr.done) {
2418                 /*
2419                  * first we need to get the NBT header
2420                  */
2421                 vector = talloc_array(mem_ctx, struct iovec, 1);
2422                 if (vector == NULL) {
2423                         return -1;
2424                 }
2425
2426                 vector[0].iov_base = (void *)state->hdr.nbt;
2427                 vector[0].iov_len = NBT_HDR_SIZE;
2428
2429                 *_vector = vector;
2430                 *_count = 1;
2431
2432                 state->hdr.done = true;
2433                 return 0;
2434         }
2435
2436         /*
2437          * Now we analyze the NBT header
2438          */
2439         state->pktlen = smb2_len(state->hdr.nbt);
2440
2441         if (state->pktlen == 0) {
2442                 /* if there're no remaining bytes, we're done */
2443                 *_vector = NULL;
2444                 *_count = 0;
2445                 return 0;
2446         }
2447
2448         state->pktbuf = talloc_array(state->smb2_req, uint8_t, state->pktlen);
2449         if (state->pktbuf == NULL) {
2450                 return -1;
2451         }
2452
2453         vector = talloc_array(mem_ctx, struct iovec, 1);
2454         if (vector == NULL) {
2455                 return -1;
2456         }
2457
2458         vector[0].iov_base = (void *)state->pktbuf;
2459         vector[0].iov_len = state->pktlen;
2460
2461         *_vector = vector;
2462         *_count = 1;
2463         return 0;
2464 }
2465
2466 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2467 {
2468         struct tevent_req *req =
2469                 tevent_req_callback_data(subreq,
2470                 struct tevent_req);
2471         struct smbd_smb2_request_read_state *state =
2472                 tevent_req_data(req,
2473                 struct smbd_smb2_request_read_state);
2474         int ret;
2475         int sys_errno;
2476         NTSTATUS status;
2477         NTTIME now;
2478
2479         ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2480         TALLOC_FREE(subreq);
2481         if (ret == -1) {
2482                 status = map_nt_error_from_unix(sys_errno);
2483                 tevent_req_nterror(req, status);
2484                 return;
2485         }
2486
2487         if (state->hdr.nbt[0] != 0x00) {
2488                 DEBUG(1,("smbd_smb2_request_read_done: ignore NBT[0x%02X] msg\n",
2489                          state->hdr.nbt[0]));
2490
2491                 ZERO_STRUCT(state->hdr);
2492                 TALLOC_FREE(state->pktbuf);
2493                 state->pktlen = 0;
2494
2495                 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
2496                                                 state->ev,
2497                                                 state->sconn->smb2.stream,
2498                                                 state->sconn->smb2.recv_queue,
2499                                                 smbd_smb2_request_next_vector,
2500                                                 state);
2501                 if (tevent_req_nomem(subreq, req)) {
2502                         return;
2503                 }
2504                 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2505                 return;
2506         }
2507
2508         state->smb2_req->request_time = timeval_current();
2509         now = timeval_to_nttime(&state->smb2_req->request_time);
2510
2511         status = smbd_smb2_inbuf_parse_compound(state->smb2_req->sconn->conn,
2512                                                 now,
2513                                                 state->pktbuf,
2514                                                 state->pktlen,
2515                                                 state->smb2_req,
2516                                                 &state->smb2_req->in.vector,
2517                                                 &state->smb2_req->in.vector_count);
2518         if (tevent_req_nterror(req, status)) {
2519                 return;
2520         }
2521
2522         state->smb2_req->current_idx = 1;
2523
2524         tevent_req_done(req);
2525 }
2526
2527 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2528                                             TALLOC_CTX *mem_ctx,
2529                                             struct smbd_smb2_request **_smb2_req)
2530 {
2531         struct smbd_smb2_request_read_state *state =
2532                 tevent_req_data(req,
2533                 struct smbd_smb2_request_read_state);
2534         NTSTATUS status;
2535
2536         if (tevent_req_is_nterror(req, &status)) {
2537                 tevent_req_received(req);
2538                 return status;
2539         }
2540
2541         *_smb2_req = talloc_move(mem_ctx, &state->smb2_req);
2542         tevent_req_received(req);
2543         return NT_STATUS_OK;
2544 }
2545
2546 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2547
2548 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2549 {
2550         size_t max_send_queue_len;
2551         size_t cur_send_queue_len;
2552         struct tevent_req *subreq;
2553
2554         if (sconn->smb2.compound_related_in_progress) {
2555                 /*
2556                  * Can't read another until the related
2557                  * compound is done.
2558                  */
2559                 return NT_STATUS_OK;
2560         }
2561
2562         if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2563                 /*
2564                  * if there is already a smbd_smb2_request_read
2565                  * pending, we are done.
2566                  */
2567                 return NT_STATUS_OK;
2568         }
2569
2570         max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2571         cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2572
2573         if (cur_send_queue_len > max_send_queue_len) {
2574                 /*
2575                  * if we have a lot of requests to send,
2576                  * we wait until they are on the wire until we
2577                  * ask for the next request.
2578                  */
2579                 return NT_STATUS_OK;
2580         }
2581
2582         /* ask for the next request */
2583         subreq = smbd_smb2_request_read_send(sconn, sconn->ev_ctx, sconn);
2584         if (subreq == NULL) {
2585                 return NT_STATUS_NO_MEMORY;
2586         }
2587         tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2588
2589         return NT_STATUS_OK;
2590 }
2591
2592 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2593                              uint8_t *inbuf, size_t size)
2594 {
2595         NTSTATUS status;
2596         struct smbd_smb2_request *req = NULL;
2597
2598         DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2599                  (unsigned int)size));
2600
2601         status = smbd_initialize_smb2(sconn);
2602         if (!NT_STATUS_IS_OK(status)) {
2603                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2604                 return;
2605         }
2606
2607         status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2608         if (!NT_STATUS_IS_OK(status)) {
2609                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2610                 return;
2611         }
2612
2613         status = smbd_smb2_request_validate(req);
2614         if (!NT_STATUS_IS_OK(status)) {
2615                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2616                 return;
2617         }
2618
2619         status = smbd_smb2_request_setup_out(req);
2620         if (!NT_STATUS_IS_OK(status)) {
2621                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2622                 return;
2623         }
2624
2625         status = smbd_smb2_request_dispatch(req);
2626         if (!NT_STATUS_IS_OK(status)) {
2627                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2628                 return;
2629         }
2630
2631         status = smbd_smb2_request_next_incoming(sconn);
2632         if (!NT_STATUS_IS_OK(status)) {
2633                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2634                 return;
2635         }
2636
2637         sconn->num_requests++;
2638 }
2639
2640 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2641 {
2642         struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2643                                                struct smbd_server_connection);
2644         NTSTATUS status;
2645         struct smbd_smb2_request *req = NULL;
2646
2647         status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2648         TALLOC_FREE(subreq);
2649         if (!NT_STATUS_IS_OK(status)) {
2650                 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2651                         nt_errstr(status)));
2652                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2653                 return;
2654         }
2655
2656         DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2657                  req->current_idx, req->in.vector_count));
2658
2659         status = smbd_smb2_request_validate(req);
2660         if (!NT_STATUS_IS_OK(status)) {
2661                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2662                 return;
2663         }
2664
2665         status = smbd_smb2_request_setup_out(req);
2666         if (!NT_STATUS_IS_OK(status)) {
2667                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2668                 return;
2669         }
2670
2671         status = smbd_smb2_request_dispatch(req);
2672         if (!NT_STATUS_IS_OK(status)) {
2673                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2674                 return;
2675         }
2676
2677         status = smbd_smb2_request_next_incoming(sconn);
2678         if (!NT_STATUS_IS_OK(status)) {
2679                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2680                 return;
2681         }
2682
2683         sconn->num_requests++;
2684
2685         /* The timeout_processing function isn't run nearly
2686            often enough to implement 'max log size' without
2687            overrunning the size of the file by many megabytes.
2688            This is especially true if we are running at debug
2689            level 10.  Checking every 50 SMB2s is a nice
2690            tradeoff of performance vs log file size overrun. */
2691
2692         if ((sconn->num_requests % 50) == 0 &&
2693             need_to_check_log_size()) {
2694                 change_to_root_user();
2695                 check_log_size();
2696         }
2697 }