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