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