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