source: vendor/current/source3/smbd/smb2_server.c

Last change on this file was 989, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.7

File size: 99.6 KB
Line 
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 "lib/util/iov_buf.h"
32#include "auth.h"
33#include "lib/crypto/sha512.h"
34
35static void smbd_smb2_connection_handler(struct tevent_context *ev,
36 struct tevent_fd *fde,
37 uint16_t flags,
38 void *private_data);
39static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn);
40
41static const struct smbd_smb2_dispatch_table {
42 uint16_t opcode;
43 const char *name;
44 bool need_session;
45 bool need_tcon;
46 bool as_root;
47 uint16_t fileid_ofs;
48 bool allow_invalid_fileid;
49 bool modify;
50} smbd_smb2_table[] = {
51#define _OP(o) .opcode = o, .name = #o
52 {
53 _OP(SMB2_OP_NEGPROT),
54 .as_root = true,
55 },{
56 _OP(SMB2_OP_SESSSETUP),
57 .as_root = true,
58 },{
59 _OP(SMB2_OP_LOGOFF),
60 .need_session = true,
61 .as_root = true,
62 },{
63 _OP(SMB2_OP_TCON),
64 .need_session = true,
65 /*
66 * This call needs to be run as root.
67 *
68 * smbd_smb2_request_process_tcon()
69 * calls make_connection_snum(), which will call
70 * change_to_user(), when needed.
71 */
72 .as_root = true,
73 },{
74 _OP(SMB2_OP_TDIS),
75 .need_session = true,
76 .need_tcon = true,
77 .as_root = true,
78 },{
79 _OP(SMB2_OP_CREATE),
80 .need_session = true,
81 .need_tcon = true,
82 },{
83 _OP(SMB2_OP_CLOSE),
84 .need_session = true,
85 .need_tcon = true,
86 .fileid_ofs = 0x08,
87 },{
88 _OP(SMB2_OP_FLUSH),
89 .need_session = true,
90 .need_tcon = true,
91 .fileid_ofs = 0x08,
92 },{
93 _OP(SMB2_OP_READ),
94 .need_session = true,
95 .need_tcon = true,
96 .fileid_ofs = 0x10,
97 },{
98 _OP(SMB2_OP_WRITE),
99 .need_session = true,
100 .need_tcon = true,
101 .fileid_ofs = 0x10,
102 .modify = true,
103 },{
104 _OP(SMB2_OP_LOCK),
105 .need_session = true,
106 .need_tcon = true,
107 .fileid_ofs = 0x08,
108 },{
109 _OP(SMB2_OP_IOCTL),
110 .need_session = true,
111 .need_tcon = true,
112 .fileid_ofs = 0x08,
113 .allow_invalid_fileid = true,
114 .modify = true,
115 },{
116 _OP(SMB2_OP_CANCEL),
117 .as_root = true,
118 },{
119 _OP(SMB2_OP_KEEPALIVE),
120 .as_root = true,
121 },{
122 _OP(SMB2_OP_QUERY_DIRECTORY),
123 .need_session = true,
124 .need_tcon = true,
125 .fileid_ofs = 0x08,
126 },{
127 _OP(SMB2_OP_NOTIFY),
128 .need_session = true,
129 .need_tcon = true,
130 .fileid_ofs = 0x08,
131 },{
132 _OP(SMB2_OP_GETINFO),
133 .need_session = true,
134 .need_tcon = true,
135 .fileid_ofs = 0x18,
136 },{
137 _OP(SMB2_OP_SETINFO),
138 .need_session = true,
139 .need_tcon = true,
140 .fileid_ofs = 0x10,
141 .modify = true,
142 },{
143 _OP(SMB2_OP_BREAK),
144 .need_session = true,
145 .need_tcon = true,
146 /*
147 * we do not set
148 * .fileid_ofs here
149 * as LEASE breaks does not
150 * have a file id
151 */
152 }
153};
154
155const char *smb2_opcode_name(uint16_t opcode)
156{
157 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
158 return "Bad SMB2 opcode";
159 }
160 return smbd_smb2_table[opcode].name;
161}
162
163static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
164{
165 const struct smbd_smb2_dispatch_table *ret = NULL;
166
167 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
168 return NULL;
169 }
170
171 ret = &smbd_smb2_table[opcode];
172
173 SMB_ASSERT(ret->opcode == opcode);
174
175 return ret;
176}
177
178static void print_req_vectors(const struct smbd_smb2_request *req)
179{
180 int i;
181
182 for (i = 0; i < req->in.vector_count; i++) {
183 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
184 (unsigned int)i,
185 (unsigned int)req->in.vector[i].iov_len);
186 }
187 for (i = 0; i < req->out.vector_count; i++) {
188 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
189 (unsigned int)i,
190 (unsigned int)req->out.vector[i].iov_len);
191 }
192}
193
194bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
195{
196 if (size < (4 + SMB2_HDR_BODY)) {
197 return false;
198 }
199
200 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
201 return false;
202 }
203
204 return true;
205}
206
207static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn,
208 uint64_t expected_seq_low)
209{
210 TALLOC_FREE(xconn->transport.fde);
211
212 xconn->smb2.credits.seq_low = expected_seq_low;
213 xconn->smb2.credits.seq_range = 1;
214 xconn->smb2.credits.granted = 1;
215 xconn->smb2.credits.max = lp_smb2_max_credits();
216 xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
217 xconn->smb2.credits.max);
218 if (xconn->smb2.credits.bitmap == NULL) {
219 return NT_STATUS_NO_MEMORY;
220 }
221
222 xconn->transport.fde = tevent_add_fd(xconn->ev_ctx,
223 xconn,
224 xconn->transport.sock,
225 TEVENT_FD_READ,
226 smbd_smb2_connection_handler,
227 xconn);
228 if (xconn->transport.fde == NULL) {
229 return NT_STATUS_NO_MEMORY;
230 }
231
232 /* Ensure child is set to non-blocking mode */
233 set_blocking(xconn->transport.sock, false);
234 return NT_STATUS_OK;
235}
236
237#define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
238#define _smb2_setlen(_buf,len) do { \
239 uint8_t *buf = (uint8_t *)_buf; \
240 buf[0] = 0; \
241 buf[1] = ((len)&0xFF0000)>>16; \
242 buf[2] = ((len)&0xFF00)>>8; \
243 buf[3] = (len)&0xFF; \
244} while (0)
245
246static bool smb2_setup_nbt_length(struct iovec *vector, int count)
247{
248 ssize_t len;
249
250 if (count == 0) {
251 return false;
252 }
253
254 len = iov_buflen(vector+1, count-1);
255
256 if ((len == -1) || (len > 0xFFFFFF)) {
257 return false;
258 }
259
260 _smb2_setlen(vector[0].iov_base, len);
261 return true;
262}
263
264static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
265{
266 if (req->first_key.length > 0) {
267 data_blob_clear_free(&req->first_key);
268 }
269 if (req->last_key.length > 0) {
270 data_blob_clear_free(&req->last_key);
271 }
272 return 0;
273}
274
275static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
276{
277 TALLOC_CTX *mem_pool;
278 struct smbd_smb2_request *req;
279
280#if 0
281 /* Enable this to find subtle valgrind errors. */
282 mem_pool = talloc_init("smbd_smb2_request_allocate");
283#else
284 mem_pool = talloc_tos();
285#endif
286 if (mem_pool == NULL) {
287 return NULL;
288 }
289
290 req = talloc_zero(mem_pool, struct smbd_smb2_request);
291 if (req == NULL) {
292 talloc_free(mem_pool);
293 return NULL;
294 }
295 talloc_reparent(mem_pool, mem_ctx, req);
296#if 0
297 TALLOC_FREE(mem_pool);
298#endif
299
300 req->last_session_id = UINT64_MAX;
301 req->last_tid = UINT32_MAX;
302
303 talloc_set_destructor(req, smbd_smb2_request_destructor);
304
305 return req;
306}
307
308static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
309 NTTIME now,
310 uint8_t *buf,
311 size_t buflen,
312 struct smbd_smb2_request *req,
313 struct iovec **piov,
314 int *pnum_iov)
315{
316 TALLOC_CTX *mem_ctx = req;
317 struct iovec *iov;
318 int num_iov = 1;
319 size_t taken = 0;
320 uint8_t *first_hdr = buf;
321 size_t verified_buflen = 0;
322 uint8_t *tf = NULL;
323 size_t tf_len = 0;
324
325 /*
326 * Note: index '0' is reserved for the transport protocol
327 */
328 iov = req->in._vector;
329
330 while (taken < buflen) {
331 size_t len = buflen - taken;
332 uint8_t *hdr = first_hdr + taken;
333 struct iovec *cur;
334 size_t full_size;
335 size_t next_command_ofs;
336 uint16_t body_size;
337 uint8_t *body = NULL;
338 uint32_t dyn_size;
339 uint8_t *dyn = NULL;
340 struct iovec *iov_alloc = NULL;
341
342 if (iov != req->in._vector) {
343 iov_alloc = iov;
344 }
345
346 if (verified_buflen > taken) {
347 len = verified_buflen - taken;
348 } else {
349 tf = NULL;
350 tf_len = 0;
351 }
352
353 if (len < 4) {
354 DEBUG(10, ("%d bytes left, expected at least %d\n",
355 (int)len, 4));
356 goto inval;
357 }
358 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
359 struct smbXsrv_session *s = NULL;
360 uint64_t uid;
361 struct iovec tf_iov[2];
362 NTSTATUS status;
363 size_t enc_len;
364
365 if (xconn->protocol < PROTOCOL_SMB2_24) {
366 DEBUG(10, ("Got SMB2_TRANSFORM header, "
367 "but dialect[0x%04X] is used\n",
368 xconn->smb2.server.dialect));
369 goto inval;
370 }
371
372 if (xconn->smb2.server.cipher == 0) {
373 DEBUG(10, ("Got SMB2_TRANSFORM header, "
374 "but not negotiated "
375 "client[0x%08X] server[0x%08X]\n",
376 xconn->smb2.client.capabilities,
377 xconn->smb2.server.capabilities));
378 goto inval;
379 }
380
381 if (len < SMB2_TF_HDR_SIZE) {
382 DEBUG(1, ("%d bytes left, expected at least %d\n",
383 (int)len, SMB2_TF_HDR_SIZE));
384 goto inval;
385 }
386 tf = hdr;
387 tf_len = SMB2_TF_HDR_SIZE;
388 taken += tf_len;
389
390 hdr = first_hdr + taken;
391 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
392 uid = BVAL(tf, SMB2_TF_SESSION_ID);
393
394 if (len < SMB2_TF_HDR_SIZE + enc_len) {
395 DEBUG(1, ("%d bytes left, expected at least %d\n",
396 (int)len,
397 (int)(SMB2_TF_HDR_SIZE + enc_len)));
398 goto inval;
399 }
400
401 status = smb2srv_session_lookup_conn(xconn, uid, now,
402 &s);
403 if (s == NULL) {
404 DEBUG(1, ("invalid session[%llu] in "
405 "SMB2_TRANSFORM header\n",
406 (unsigned long long)uid));
407 TALLOC_FREE(iov_alloc);
408 return NT_STATUS_USER_SESSION_DELETED;
409 }
410
411 tf_iov[0].iov_base = (void *)tf;
412 tf_iov[0].iov_len = tf_len;
413 tf_iov[1].iov_base = (void *)hdr;
414 tf_iov[1].iov_len = enc_len;
415
416 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
417 xconn->smb2.server.cipher,
418 tf_iov, 2);
419 if (!NT_STATUS_IS_OK(status)) {
420 TALLOC_FREE(iov_alloc);
421 return status;
422 }
423
424 verified_buflen = taken + enc_len;
425 len = enc_len;
426 }
427
428 /*
429 * We need the header plus the body length field
430 */
431
432 if (len < SMB2_HDR_BODY + 2) {
433 DEBUG(10, ("%d bytes left, expected at least %d\n",
434 (int)len, SMB2_HDR_BODY));
435 goto inval;
436 }
437 if (IVAL(hdr, 0) != SMB2_MAGIC) {
438 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
439 IVAL(hdr, 0)));
440 goto inval;
441 }
442 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
443 DEBUG(10, ("Got HDR len %d, expected %d\n",
444 SVAL(hdr, 4), SMB2_HDR_BODY));
445 goto inval;
446 }
447
448 full_size = len;
449 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
450 body_size = SVAL(hdr, SMB2_HDR_BODY);
451
452 if (next_command_ofs != 0) {
453 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
454 goto inval;
455 }
456 if (next_command_ofs > full_size) {
457 goto inval;
458 }
459 full_size = next_command_ofs;
460 }
461 if (body_size < 2) {
462 goto inval;
463 }
464 body_size &= 0xfffe;
465
466 if (body_size > (full_size - SMB2_HDR_BODY)) {
467 /*
468 * let the caller handle the error
469 */
470 body_size = full_size - SMB2_HDR_BODY;
471 }
472 body = hdr + SMB2_HDR_BODY;
473 dyn = body + body_size;
474 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
475
476 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
477 struct iovec *iov_tmp = NULL;
478
479 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
480 struct iovec,
481 num_iov +
482 SMBD_SMB2_NUM_IOV_PER_REQ);
483 if (iov_tmp == NULL) {
484 TALLOC_FREE(iov_alloc);
485 return NT_STATUS_NO_MEMORY;
486 }
487
488 if (iov_alloc == NULL) {
489 memcpy(iov_tmp,
490 req->in._vector,
491 sizeof(req->in._vector));
492 }
493
494 iov = iov_tmp;
495 }
496 cur = &iov[num_iov];
497 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
498
499 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
500 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
501 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
502 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
503 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
504 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
505 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
506 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
507
508 taken += full_size;
509 }
510
511 *piov = iov;
512 *pnum_iov = num_iov;
513 return NT_STATUS_OK;
514
515inval:
516 if (iov != req->in._vector) {
517 TALLOC_FREE(iov);
518 }
519 return NT_STATUS_INVALID_PARAMETER;
520}
521
522static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
523 const uint8_t *_inpdu, size_t size,
524 struct smbd_smb2_request **_req)
525{
526 struct smbd_server_connection *sconn = xconn->client->sconn;
527 struct smbd_smb2_request *req;
528 uint32_t protocol_version;
529 uint8_t *inpdu = NULL;
530 const uint8_t *inhdr = NULL;
531 uint16_t cmd;
532 uint32_t next_command_ofs;
533 NTSTATUS status;
534 NTTIME now;
535
536 if (size < (SMB2_HDR_BODY + 2)) {
537 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
538 return NT_STATUS_INVALID_PARAMETER;
539 }
540
541 inhdr = _inpdu;
542
543 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
544 if (protocol_version != SMB2_MAGIC) {
545 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
546 protocol_version));
547 return NT_STATUS_INVALID_PARAMETER;
548 }
549
550 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
551 if (cmd != SMB2_OP_NEGPROT) {
552 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
553 cmd));
554 return NT_STATUS_INVALID_PARAMETER;
555 }
556
557 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
558 if (next_command_ofs != 0) {
559 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
560 next_command_ofs));
561 return NT_STATUS_INVALID_PARAMETER;
562 }
563
564 req = smbd_smb2_request_allocate(xconn);
565 if (req == NULL) {
566 return NT_STATUS_NO_MEMORY;
567 }
568 req->sconn = sconn;
569 req->xconn = xconn;
570
571 inpdu = talloc_memdup(req, _inpdu, size);
572 if (inpdu == NULL) {
573 return NT_STATUS_NO_MEMORY;
574 }
575
576 req->request_time = timeval_current();
577 now = timeval_to_nttime(&req->request_time);
578
579 status = smbd_smb2_inbuf_parse_compound(xconn,
580 now,
581 inpdu,
582 size,
583 req, &req->in.vector,
584 &req->in.vector_count);
585 if (!NT_STATUS_IS_OK(status)) {
586 TALLOC_FREE(req);
587 return status;
588 }
589
590 req->current_idx = 1;
591
592 *_req = req;
593 return NT_STATUS_OK;
594}
595
596static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
597 uint64_t message_id, uint64_t seq_id)
598{
599 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
600 unsigned int offset;
601 uint64_t seq_tmp;
602
603 seq_tmp = xconn->smb2.credits.seq_low;
604 if (seq_id < seq_tmp) {
605 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
606 "%llu (sequence id %llu) "
607 "(granted = %u, low = %llu, range = %u)\n",
608 (unsigned long long)message_id,
609 (unsigned long long)seq_id,
610 (unsigned int)xconn->smb2.credits.granted,
611 (unsigned long long)xconn->smb2.credits.seq_low,
612 (unsigned int)xconn->smb2.credits.seq_range));
613 return false;
614 }
615
616 seq_tmp += xconn->smb2.credits.seq_range;
617 if (seq_id >= seq_tmp) {
618 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
619 "%llu (sequence id %llu) "
620 "(granted = %u, low = %llu, range = %u)\n",
621 (unsigned long long)message_id,
622 (unsigned long long)seq_id,
623 (unsigned int)xconn->smb2.credits.granted,
624 (unsigned long long)xconn->smb2.credits.seq_low,
625 (unsigned int)xconn->smb2.credits.seq_range));
626 return false;
627 }
628
629 offset = seq_id % xconn->smb2.credits.max;
630
631 if (bitmap_query(credits_bm, offset)) {
632 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
633 "%llu (sequence id %llu) "
634 "(granted = %u, low = %llu, range = %u) "
635 "(bm offset %u)\n",
636 (unsigned long long)message_id,
637 (unsigned long long)seq_id,
638 (unsigned int)xconn->smb2.credits.granted,
639 (unsigned long long)xconn->smb2.credits.seq_low,
640 (unsigned int)xconn->smb2.credits.seq_range,
641 offset));
642 return false;
643 }
644
645 /* Mark the message_ids as seen in the bitmap. */
646 bitmap_set(credits_bm, offset);
647
648 if (seq_id != xconn->smb2.credits.seq_low) {
649 return true;
650 }
651
652 /*
653 * Move the window forward by all the message_id's
654 * already seen.
655 */
656 while (bitmap_query(credits_bm, offset)) {
657 DEBUG(10,("smb2_validate_sequence_number: clearing "
658 "id %llu (position %u) from bitmap\n",
659 (unsigned long long)(xconn->smb2.credits.seq_low),
660 offset));
661 bitmap_clear(credits_bm, offset);
662
663 xconn->smb2.credits.seq_low += 1;
664 xconn->smb2.credits.seq_range -= 1;
665 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
666 }
667
668 return true;
669}
670
671static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
672 const uint8_t *inhdr)
673{
674 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
675 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
676 uint16_t credit_charge = 1;
677 uint64_t i;
678
679 if (opcode == SMB2_OP_CANCEL) {
680 /* SMB2_CANCEL requests by definition resend messageids. */
681 return true;
682 }
683
684 if (xconn->smb2.credits.multicredit) {
685 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
686 credit_charge = MAX(credit_charge, 1);
687 }
688
689 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
690 "credits_granted %llu, "
691 "seqnum low/range: %llu/%llu\n",
692 (unsigned long long) message_id,
693 (unsigned long long) credit_charge,
694 (unsigned long long) xconn->smb2.credits.granted,
695 (unsigned long long) xconn->smb2.credits.seq_low,
696 (unsigned long long) xconn->smb2.credits.seq_range));
697
698 if (xconn->smb2.credits.granted < credit_charge) {
699 DEBUG(0, ("smb2_validate_message_id: client used more "
700 "credits than granted, mid %llu, charge %llu, "
701 "credits_granted %llu, "
702 "seqnum low/range: %llu/%llu\n",
703 (unsigned long long) message_id,
704 (unsigned long long) credit_charge,
705 (unsigned long long) xconn->smb2.credits.granted,
706 (unsigned long long) xconn->smb2.credits.seq_low,
707 (unsigned long long) xconn->smb2.credits.seq_range));
708 return false;
709 }
710
711 /*
712 * now check the message ids
713 *
714 * for multi-credit requests we need to check all current mid plus
715 * the implicit mids caused by the credit charge
716 * e.g. current mid = 15, charge 5 => mark 15-19 as used
717 */
718
719 for (i = 0; i <= (credit_charge-1); i++) {
720 uint64_t id = message_id + i;
721 bool ok;
722
723 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
724 (unsigned long long)message_id,
725 credit_charge,
726 (unsigned long long)id));
727
728 ok = smb2_validate_sequence_number(xconn, message_id, id);
729 if (!ok) {
730 return false;
731 }
732 }
733
734 /* substract used credits */
735 xconn->smb2.credits.granted -= credit_charge;
736
737 return true;
738}
739
740static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
741{
742 int count;
743 int idx;
744
745 count = req->in.vector_count;
746
747 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
748 /* It's not a SMB2 request */
749 return NT_STATUS_INVALID_PARAMETER;
750 }
751
752 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
753 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
754 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
755 const uint8_t *inhdr = NULL;
756
757 if (hdr->iov_len != SMB2_HDR_BODY) {
758 return NT_STATUS_INVALID_PARAMETER;
759 }
760
761 if (body->iov_len < 2) {
762 return NT_STATUS_INVALID_PARAMETER;
763 }
764
765 inhdr = (const uint8_t *)hdr->iov_base;
766
767 /* Check the SMB2 header */
768 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
769 return NT_STATUS_INVALID_PARAMETER;
770 }
771
772 if (!smb2_validate_message_id(req->xconn, inhdr)) {
773 return NT_STATUS_INVALID_PARAMETER;
774 }
775 }
776
777 return NT_STATUS_OK;
778}
779
780static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
781 const struct iovec *in_vector,
782 struct iovec *out_vector)
783{
784 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
785 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
786 uint16_t credit_charge = 1;
787 uint16_t credits_requested;
788 uint32_t out_flags;
789 uint16_t cmd;
790 NTSTATUS out_status;
791 uint16_t credits_granted = 0;
792 uint64_t credits_possible;
793 uint16_t current_max_credits;
794
795 /*
796 * first we grant only 1/16th of the max range.
797 *
798 * Windows also starts with the 1/16th and then grants
799 * more later. I was only able to trigger higher
800 * values, when using a very high credit charge.
801 *
802 * TODO: scale up depending on load, free memory
803 * or other stuff.
804 * Maybe also on the relationship between number
805 * of requests and the used sequence number.
806 * Which means we would grant more credits
807 * for client which use multi credit requests.
808 */
809 current_max_credits = xconn->smb2.credits.max / 16;
810 current_max_credits = MAX(current_max_credits, 1);
811
812 if (xconn->smb2.credits.multicredit) {
813 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
814 credit_charge = MAX(credit_charge, 1);
815 }
816
817 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
818 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
819 credits_requested = MAX(credits_requested, 1);
820 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
821 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
822
823 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
824
825 if (xconn->smb2.credits.max < credit_charge) {
826 smbd_server_connection_terminate(xconn,
827 "client error: credit charge > max credits\n");
828 return;
829 }
830
831 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
832 /*
833 * In case we already send an async interim
834 * response, we should not grant
835 * credits on the final response.
836 */
837 credits_granted = 0;
838 } else {
839 uint16_t additional_possible =
840 xconn->smb2.credits.max - credit_charge;
841 uint16_t additional_max = 0;
842 uint16_t additional_credits = credits_requested - 1;
843
844 switch (cmd) {
845 case SMB2_OP_NEGPROT:
846 break;
847 case SMB2_OP_SESSSETUP:
848 /*
849 * Windows 2012 RC1 starts to grant
850 * additional credits
851 * with a successful session setup
852 */
853 if (NT_STATUS_IS_OK(out_status)) {
854 additional_max = 32;
855 }
856 break;
857 default:
858 /*
859 * We match windows and only grant additional credits
860 * in chunks of 32.
861 */
862 additional_max = 32;
863 break;
864 }
865
866 additional_max = MIN(additional_max, additional_possible);
867 additional_credits = MIN(additional_credits, additional_max);
868
869 credits_granted = credit_charge + additional_credits;
870 }
871
872 /*
873 * sequence numbers should not wrap
874 *
875 * 1. calculate the possible credits until
876 * the sequence numbers start to wrap on 64-bit.
877 *
878 * 2. UINT64_MAX is used for Break Notifications.
879 *
880 * 2. truncate the possible credits to the maximum
881 * credits we want to grant to the client in total.
882 *
883 * 3. remove the range we'll already granted to the client
884 * this makes sure the client consumes the lowest sequence
885 * number, before we can grant additional credits.
886 */
887 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
888 if (credits_possible > 0) {
889 /* remove UINT64_MAX */
890 credits_possible -= 1;
891 }
892 credits_possible = MIN(credits_possible, current_max_credits);
893 credits_possible -= xconn->smb2.credits.seq_range;
894
895 credits_granted = MIN(credits_granted, credits_possible);
896
897 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
898 xconn->smb2.credits.granted += credits_granted;
899 xconn->smb2.credits.seq_range += credits_granted;
900
901 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
902 "granted %u, current possible/max %u/%u, "
903 "total granted/max/low/range %u/%u/%llu/%u\n",
904 (unsigned int)credits_requested,
905 (unsigned int)credit_charge,
906 (unsigned int)credits_granted,
907 (unsigned int)credits_possible,
908 (unsigned int)current_max_credits,
909 (unsigned int)xconn->smb2.credits.granted,
910 (unsigned int)xconn->smb2.credits.max,
911 (unsigned long long)xconn->smb2.credits.seq_low,
912 (unsigned int)xconn->smb2.credits.seq_range));
913}
914
915static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
916 struct smbd_smb2_request *outreq)
917{
918 int count, idx;
919 uint16_t total_credits = 0;
920
921 count = outreq->out.vector_count;
922
923 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
924 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
925 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
926 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
927
928 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
929
930 /* To match Windows, count up what we
931 just granted. */
932 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
933 /* Set to zero in all but the last reply. */
934 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
935 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
936 } else {
937 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
938 }
939 }
940}
941
942DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
943{
944 if (req->current_idx <= 1) {
945 if (size <= sizeof(req->out._body)) {
946 return data_blob_const(req->out._body, size);
947 }
948 }
949
950 return data_blob_talloc(req, NULL, size);
951}
952
953static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
954{
955 struct smbXsrv_connection *xconn = req->xconn;
956 TALLOC_CTX *mem_ctx;
957 struct iovec *vector;
958 int count;
959 int idx;
960 bool ok;
961
962 count = req->in.vector_count;
963 if (count <= ARRAY_SIZE(req->out._vector)) {
964 mem_ctx = req;
965 vector = req->out._vector;
966 } else {
967 vector = talloc_zero_array(req, struct iovec, count);
968 if (vector == NULL) {
969 return NT_STATUS_NO_MEMORY;
970 }
971 mem_ctx = vector;
972 }
973
974 vector[0].iov_base = req->out.nbt_hdr;
975 vector[0].iov_len = 4;
976 SIVAL(req->out.nbt_hdr, 0, 0);
977
978 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
979 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
980 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
981 uint8_t *outhdr = NULL;
982 uint8_t *outbody = NULL;
983 uint32_t next_command_ofs = 0;
984 struct iovec *current = &vector[idx];
985
986 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
987 /* we have a next command -
988 * setup for the error case. */
989 next_command_ofs = SMB2_HDR_BODY + 9;
990 }
991
992 if (idx == 1) {
993 outhdr = req->out._hdr;
994 } else {
995 outhdr = talloc_zero_array(mem_ctx, uint8_t,
996 OUTVEC_ALLOC_SIZE);
997 if (outhdr == NULL) {
998 return NT_STATUS_NO_MEMORY;
999 }
1000 }
1001
1002 outbody = outhdr + SMB2_HDR_BODY;
1003
1004 /*
1005 * SMBD_SMB2_TF_IOV_OFS might be used later
1006 */
1007 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1008 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1009
1010 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
1011 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1012
1013 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1014 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1015
1016 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1017 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1018
1019 /* setup the SMB2 header */
1020 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1021 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1022 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1023 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1024 SIVAL(outhdr, SMB2_HDR_STATUS,
1025 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1026 SSVAL(outhdr, SMB2_HDR_OPCODE,
1027 SVAL(inhdr, SMB2_HDR_OPCODE));
1028 SIVAL(outhdr, SMB2_HDR_FLAGS,
1029 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1030 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1031 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1032 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1033 SIVAL(outhdr, SMB2_HDR_PID,
1034 IVAL(inhdr, SMB2_HDR_PID));
1035 SIVAL(outhdr, SMB2_HDR_TID,
1036 IVAL(inhdr, SMB2_HDR_TID));
1037 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1038 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1039 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1040 inhdr + SMB2_HDR_SIGNATURE, 16);
1041
1042 /* setup error body header */
1043 SSVAL(outbody, 0x00, 0x08 + 1);
1044 SSVAL(outbody, 0x02, 0);
1045 SIVAL(outbody, 0x04, 0);
1046 }
1047
1048 req->out.vector = vector;
1049 req->out.vector_count = count;
1050
1051 /* setup the length of the NBT packet */
1052 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1053 if (!ok) {
1054 return NT_STATUS_INVALID_PARAMETER_MIX;
1055 }
1056
1057 DLIST_ADD_END(xconn->smb2.requests, req);
1058
1059 return NT_STATUS_OK;
1060}
1061
1062void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
1063 const char *reason,
1064 const char *location)
1065{
1066 struct smbXsrv_client *client = xconn->client;
1067
1068 DEBUG(10,("smbd_server_connection_terminate_ex: conn[%s] reason[%s] at %s\n",
1069 smbXsrv_connection_dbg(xconn), reason, location));
1070
1071 if (client->connections->next != NULL) {
1072 /* TODO: cancel pending requests */
1073 DLIST_REMOVE(client->connections, xconn);
1074 TALLOC_FREE(xconn);
1075 return;
1076 }
1077
1078 /*
1079 * The last connection was disconnected
1080 */
1081 exit_server_cleanly(reason);
1082}
1083
1084static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1085 struct iovec *outvec,
1086 const struct iovec *srcvec)
1087{
1088 const uint8_t *srctf;
1089 size_t srctf_len;
1090 const uint8_t *srchdr;
1091 size_t srchdr_len;
1092 const uint8_t *srcbody;
1093 size_t srcbody_len;
1094 const uint8_t *expected_srcbody;
1095 const uint8_t *srcdyn;
1096 size_t srcdyn_len;
1097 const uint8_t *expected_srcdyn;
1098 uint8_t *dsttf;
1099 uint8_t *dsthdr;
1100 uint8_t *dstbody;
1101 uint8_t *dstdyn;
1102
1103 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1104 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1105 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1106 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1107 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1108 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1109 expected_srcbody = srchdr + SMB2_HDR_BODY;
1110 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1111 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1112 expected_srcdyn = srcbody + 8;
1113
1114 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1115 return false;
1116 }
1117
1118 if (srchdr_len != SMB2_HDR_BODY) {
1119 return false;
1120 }
1121
1122 if (srctf_len == SMB2_TF_HDR_SIZE) {
1123 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1124 if (dsttf == NULL) {
1125 return false;
1126 }
1127 } else {
1128 dsttf = NULL;
1129 }
1130 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1131 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1132
1133 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1134 * be allocated with size OUTVEC_ALLOC_SIZE. */
1135
1136 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1137 if (dsthdr == NULL) {
1138 return false;
1139 }
1140 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1141 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1142
1143 /*
1144 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1145 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1146 * then duplicate this. Else use talloc_memdup().
1147 */
1148
1149 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1150 dstbody = dsthdr + SMB2_HDR_BODY;
1151 } else {
1152 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1153 if (dstbody == NULL) {
1154 return false;
1155 }
1156 }
1157 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1158 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1159
1160 /*
1161 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1162 * pointing to
1163 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1164 * then duplicate this. Else use talloc_memdup().
1165 */
1166
1167 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1168 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1169 } else if (srcdyn == NULL) {
1170 dstdyn = NULL;
1171 } else {
1172 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1173 if (dstdyn == NULL) {
1174 return false;
1175 }
1176 }
1177 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1178 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1179
1180 return true;
1181}
1182
1183static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1184{
1185 struct smbd_smb2_request *newreq = NULL;
1186 struct iovec *outvec = NULL;
1187 int count = req->out.vector_count;
1188 int i;
1189 bool ok;
1190
1191 newreq = smbd_smb2_request_allocate(req->xconn);
1192 if (!newreq) {
1193 return NULL;
1194 }
1195
1196 newreq->sconn = req->sconn;
1197 newreq->xconn = req->xconn;
1198 newreq->session = req->session;
1199 newreq->do_encryption = req->do_encryption;
1200 newreq->do_signing = req->do_signing;
1201 newreq->current_idx = req->current_idx;
1202
1203 outvec = talloc_zero_array(newreq, struct iovec, count);
1204 if (!outvec) {
1205 TALLOC_FREE(newreq);
1206 return NULL;
1207 }
1208 newreq->out.vector = outvec;
1209 newreq->out.vector_count = count;
1210
1211 /* Setup the outvec's identically to req. */
1212 outvec[0].iov_base = newreq->out.nbt_hdr;
1213 outvec[0].iov_len = 4;
1214 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1215
1216 /* Setup the vectors identically to the ones in req. */
1217 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1218 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1219 break;
1220 }
1221 }
1222
1223 if (i < count) {
1224 /* Alloc failed. */
1225 TALLOC_FREE(newreq);
1226 return NULL;
1227 }
1228
1229 ok = smb2_setup_nbt_length(newreq->out.vector,
1230 newreq->out.vector_count);
1231 if (!ok) {
1232 TALLOC_FREE(newreq);
1233 return NULL;
1234 }
1235
1236 return newreq;
1237}
1238
1239static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1240{
1241 struct smbXsrv_connection *xconn = req->xconn;
1242 int first_idx = 1;
1243 struct iovec *firsttf = NULL;
1244 struct iovec *outhdr_v = NULL;
1245 uint8_t *outhdr = NULL;
1246 struct smbd_smb2_request *nreq = NULL;
1247 NTSTATUS status;
1248 bool ok;
1249
1250 /* Create a new smb2 request we'll use
1251 for the interim return. */
1252 nreq = dup_smb2_req(req);
1253 if (!nreq) {
1254 return NT_STATUS_NO_MEMORY;
1255 }
1256
1257 /* Lose the last X out vectors. They're the
1258 ones we'll be using for the async reply. */
1259 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1260
1261 ok = smb2_setup_nbt_length(nreq->out.vector,
1262 nreq->out.vector_count);
1263 if (!ok) {
1264 return NT_STATUS_INVALID_PARAMETER_MIX;
1265 }
1266
1267 /* Step back to the previous reply. */
1268 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1269 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1270 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1271 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1272 /* And end the chain. */
1273 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1274
1275 /* Calculate outgoing credits */
1276 smb2_calculate_credits(req, nreq);
1277
1278 if (DEBUGLEVEL >= 10) {
1279 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1280 (unsigned int)nreq->current_idx );
1281 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1282 (unsigned int)nreq->out.vector_count );
1283 print_req_vectors(nreq);
1284 }
1285
1286 /*
1287 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1288 * we need to sign/encrypt here with the last/first key we remembered
1289 */
1290 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1291 status = smb2_signing_encrypt_pdu(req->first_key,
1292 xconn->smb2.server.cipher,
1293 firsttf,
1294 nreq->out.vector_count - first_idx);
1295 if (!NT_STATUS_IS_OK(status)) {
1296 return status;
1297 }
1298 } else if (req->last_key.length > 0) {
1299 status = smb2_signing_sign_pdu(req->last_key,
1300 xconn->protocol,
1301 outhdr_v,
1302 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1303 if (!NT_STATUS_IS_OK(status)) {
1304 return status;
1305 }
1306 }
1307
1308 nreq->queue_entry.mem_ctx = nreq;
1309 nreq->queue_entry.vector = nreq->out.vector;
1310 nreq->queue_entry.count = nreq->out.vector_count;
1311 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry);
1312 xconn->smb2.send_queue_len++;
1313
1314 status = smbd_smb2_flush_send_queue(xconn);
1315 if (!NT_STATUS_IS_OK(status)) {
1316 return status;
1317 }
1318
1319 return NT_STATUS_OK;
1320}
1321
1322struct smbd_smb2_request_pending_state {
1323 struct smbd_smb2_send_queue queue_entry;
1324 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1325 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1326};
1327
1328static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1329 struct tevent_timer *te,
1330 struct timeval current_time,
1331 void *private_data);
1332
1333NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1334 struct tevent_req *subreq,
1335 uint32_t defer_time)
1336{
1337 NTSTATUS status;
1338 struct timeval defer_endtime;
1339 uint8_t *outhdr = NULL;
1340 uint32_t flags;
1341
1342 if (!tevent_req_is_in_progress(subreq)) {
1343 /*
1344 * This is a performance optimization,
1345 * it avoids one tevent_loop iteration,
1346 * which means we avoid one
1347 * talloc_stackframe_pool/talloc_free pair.
1348 */
1349 tevent_req_notify_callback(subreq);
1350 return NT_STATUS_OK;
1351 }
1352
1353 req->subreq = subreq;
1354 subreq = NULL;
1355
1356 if (req->async_te) {
1357 /* We're already async. */
1358 return NT_STATUS_OK;
1359 }
1360
1361 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1362 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1363 if (flags & SMB2_HDR_FLAG_ASYNC) {
1364 /* We're already async. */
1365 return NT_STATUS_OK;
1366 }
1367
1368 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1369 /*
1370 * We're trying to go async in a compound request
1371 * chain. This is only allowed for opens that cause an
1372 * oplock break or for the last operation in the
1373 * chain, otherwise it is not allowed. See
1374 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
1375 */
1376 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1377
1378 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1379 /*
1380 * Cancel the outstanding request.
1381 */
1382 bool ok = tevent_req_cancel(req->subreq);
1383 if (ok) {
1384 return NT_STATUS_OK;
1385 }
1386 TALLOC_FREE(req->subreq);
1387 return smbd_smb2_request_error(req,
1388 NT_STATUS_INTERNAL_ERROR);
1389 }
1390 }
1391
1392 if (DEBUGLEVEL >= 10) {
1393 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1394 (unsigned int)req->current_idx );
1395 print_req_vectors(req);
1396 }
1397
1398 if (req->current_idx > 1) {
1399 /*
1400 * We're going async in a compound
1401 * chain after the first request has
1402 * already been processed. Send an
1403 * interim response containing the
1404 * set of replies already generated.
1405 */
1406 int idx = req->current_idx;
1407
1408 status = smb2_send_async_interim_response(req);
1409 if (!NT_STATUS_IS_OK(status)) {
1410 return status;
1411 }
1412 if (req->first_key.length > 0) {
1413 data_blob_clear_free(&req->first_key);
1414 }
1415
1416 req->current_idx = 1;
1417
1418 /*
1419 * Re-arrange the in.vectors to remove what
1420 * we just sent.
1421 */
1422 memmove(&req->in.vector[1],
1423 &req->in.vector[idx],
1424 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1425 req->in.vector_count = 1 + (req->in.vector_count - idx);
1426
1427 /* Re-arrange the out.vectors to match. */
1428 memmove(&req->out.vector[1],
1429 &req->out.vector[idx],
1430 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1431 req->out.vector_count = 1 + (req->out.vector_count - idx);
1432
1433 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1434 /*
1435 * We only have one remaining request as
1436 * we've processed everything else.
1437 * This is no longer a compound request.
1438 */
1439 req->compound_related = false;
1440 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1441 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1442 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1443 }
1444 }
1445 if (req->last_key.length > 0) {
1446 data_blob_clear_free(&req->last_key);
1447 }
1448
1449 defer_endtime = timeval_current_ofs_usec(defer_time);
1450 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1451 req, defer_endtime,
1452 smbd_smb2_request_pending_timer,
1453 req);
1454 if (req->async_te == NULL) {
1455 return NT_STATUS_NO_MEMORY;
1456 }
1457
1458 return NT_STATUS_OK;
1459}
1460
1461static DATA_BLOB smbd_smb2_signing_key(struct smbXsrv_session *session,
1462 struct smbXsrv_connection *xconn)
1463{
1464 struct smbXsrv_channel_global0 *c = NULL;
1465 NTSTATUS status;
1466 DATA_BLOB key = data_blob_null;
1467
1468 status = smbXsrv_session_find_channel(session, xconn, &c);
1469 if (NT_STATUS_IS_OK(status)) {
1470 key = c->signing_key;
1471 }
1472
1473 if (key.length == 0) {
1474 key = session->global->signing_key;
1475 }
1476
1477 return key;
1478}
1479
1480static NTSTATUS smb2_get_new_nonce(struct smbXsrv_session *session,
1481 uint64_t *new_nonce_high,
1482 uint64_t *new_nonce_low)
1483{
1484 uint64_t nonce_high;
1485 uint64_t nonce_low;
1486
1487 session->nonce_low += 1;
1488 if (session->nonce_low == 0) {
1489 session->nonce_low += 1;
1490 session->nonce_high += 1;
1491 }
1492
1493 /*
1494 * CCM and GCM algorithms must never have their
1495 * nonce wrap, or the security of the whole
1496 * communication and the keys is destroyed.
1497 * We must drop the connection once we have
1498 * transfered too much data.
1499 *
1500 * NOTE: We assume nonces greater than 8 bytes.
1501 */
1502 if (session->nonce_high >= session->nonce_high_max) {
1503 return NT_STATUS_ENCRYPTION_FAILED;
1504 }
1505
1506 nonce_high = session->nonce_high_random;
1507 nonce_high += session->nonce_high;
1508 nonce_low = session->nonce_low;
1509
1510 *new_nonce_high = nonce_high;
1511 *new_nonce_low = nonce_low;
1512 return NT_STATUS_OK;
1513}
1514
1515static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1516 struct tevent_timer *te,
1517 struct timeval current_time,
1518 void *private_data)
1519{
1520 struct smbd_smb2_request *req =
1521 talloc_get_type_abort(private_data,
1522 struct smbd_smb2_request);
1523 struct smbXsrv_connection *xconn = req->xconn;
1524 struct smbd_smb2_request_pending_state *state = NULL;
1525 uint8_t *outhdr = NULL;
1526 const uint8_t *inhdr = NULL;
1527 uint8_t *tf = NULL;
1528 size_t tf_len = 0;
1529 uint8_t *hdr = NULL;
1530 uint8_t *body = NULL;
1531 uint8_t *dyn = NULL;
1532 uint32_t flags = 0;
1533 uint64_t session_id = 0;
1534 uint64_t message_id = 0;
1535 uint64_t nonce_high = 0;
1536 uint64_t nonce_low = 0;
1537 uint64_t async_id = 0;
1538 NTSTATUS status;
1539 bool ok;
1540
1541 TALLOC_FREE(req->async_te);
1542
1543 /* Ensure our final reply matches the interim one. */
1544 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1545 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1546 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1547 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1548 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1549
1550 async_id = message_id; /* keep it simple for now... */
1551
1552 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1553 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1554
1555 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1556 "going async\n",
1557 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1558 (unsigned long long)async_id ));
1559
1560 /*
1561 * What we send is identical to a smbd_smb2_request_error
1562 * packet with an error status of STATUS_PENDING. Make use
1563 * of this fact sometime when refactoring. JRA.
1564 */
1565
1566 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
1567 if (state == NULL) {
1568 smbd_server_connection_terminate(xconn,
1569 nt_errstr(NT_STATUS_NO_MEMORY));
1570 return;
1571 }
1572
1573 tf = state->buf + NBT_HDR_SIZE;
1574 tf_len = SMB2_TF_HDR_SIZE;
1575
1576 hdr = tf + SMB2_TF_HDR_SIZE;
1577 body = hdr + SMB2_HDR_BODY;
1578 dyn = body + 8;
1579
1580 if (req->do_encryption) {
1581 status = smb2_get_new_nonce(req->session,
1582 &nonce_high,
1583 &nonce_low);
1584 if (!NT_STATUS_IS_OK(status)) {
1585 smbd_server_connection_terminate(xconn,
1586 nt_errstr(status));
1587 return;
1588 }
1589 }
1590
1591 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1592 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1593 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1594 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1595
1596 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1597 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1598 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1599 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1600 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1601
1602 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1603 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1604 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1605 SBVAL(hdr, SMB2_HDR_PID, async_id);
1606 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1607 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1608 memcpy(hdr+SMB2_HDR_SIGNATURE,
1609 outhdr+SMB2_HDR_SIGNATURE, 16);
1610
1611 SSVAL(body, 0x00, 0x08 + 1);
1612
1613 SCVAL(body, 0x02, 0);
1614 SCVAL(body, 0x03, 0);
1615 SIVAL(body, 0x04, 0);
1616 /* Match W2K8R2... */
1617 SCVAL(dyn, 0x00, 0x21);
1618
1619 state->vector[0].iov_base = (void *)state->buf;
1620 state->vector[0].iov_len = NBT_HDR_SIZE;
1621
1622 if (req->do_encryption) {
1623 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1624 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1625 } else {
1626 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1627 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1628 }
1629
1630 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1631 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1632
1633 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1634 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1635
1636 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1637 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1638
1639 ok = smb2_setup_nbt_length(state->vector,
1640 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1641 if (!ok) {
1642 smbd_server_connection_terminate(
1643 xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
1644 return;
1645 }
1646
1647 /* Ensure we correctly go through crediting. Grant
1648 the credits now, and zero credits on the final
1649 response. */
1650 smb2_set_operation_credit(req->xconn,
1651 SMBD_SMB2_IN_HDR_IOV(req),
1652 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1653
1654 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1655
1656 if (DEBUGLVL(10)) {
1657 int i;
1658
1659 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1660 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1661 (unsigned int)i,
1662 (unsigned int)ARRAY_SIZE(state->vector),
1663 (unsigned int)state->vector[i].iov_len);
1664 }
1665 }
1666
1667 if (req->do_encryption) {
1668 struct smbXsrv_session *x = req->session;
1669 DATA_BLOB encryption_key = x->global->encryption_key;
1670
1671 status = smb2_signing_encrypt_pdu(encryption_key,
1672 xconn->smb2.server.cipher,
1673 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1674 SMBD_SMB2_NUM_IOV_PER_REQ);
1675 if (!NT_STATUS_IS_OK(status)) {
1676 smbd_server_connection_terminate(xconn,
1677 nt_errstr(status));
1678 return;
1679 }
1680 } else if (req->do_signing) {
1681 struct smbXsrv_session *x = req->session;
1682 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
1683
1684 status = smb2_signing_sign_pdu(signing_key,
1685 xconn->protocol,
1686 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1687 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1688 if (!NT_STATUS_IS_OK(status)) {
1689 smbd_server_connection_terminate(xconn,
1690 nt_errstr(status));
1691 return;
1692 }
1693 }
1694
1695 state->queue_entry.mem_ctx = state;
1696 state->queue_entry.vector = state->vector;
1697 state->queue_entry.count = ARRAY_SIZE(state->vector);
1698 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
1699 xconn->smb2.send_queue_len++;
1700
1701 status = smbd_smb2_flush_send_queue(xconn);
1702 if (!NT_STATUS_IS_OK(status)) {
1703 smbd_server_connection_terminate(xconn,
1704 nt_errstr(status));
1705 return;
1706 }
1707}
1708
1709static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1710{
1711 struct smbXsrv_connection *xconn = req->xconn;
1712 struct smbd_smb2_request *cur;
1713 const uint8_t *inhdr;
1714 uint32_t flags;
1715 uint64_t search_message_id;
1716 uint64_t search_async_id;
1717 uint64_t found_id;
1718
1719 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1720
1721 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1722 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1723 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1724
1725 /*
1726 * We don't need the request anymore cancel requests never
1727 * have a response.
1728 *
1729 * We defer the TALLOC_FREE(req) to the caller.
1730 */
1731 DLIST_REMOVE(xconn->smb2.requests, req);
1732
1733 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1734 const uint8_t *outhdr;
1735 uint64_t message_id;
1736 uint64_t async_id;
1737
1738 if (cur->compound_related) {
1739 /*
1740 * Never cancel anything in a compound request.
1741 * Way too hard to deal with the result.
1742 */
1743 continue;
1744 }
1745
1746 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1747
1748 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1749 async_id = BVAL(outhdr, SMB2_HDR_PID);
1750
1751 if (flags & SMB2_HDR_FLAG_ASYNC) {
1752 if (search_async_id == async_id) {
1753 found_id = async_id;
1754 break;
1755 }
1756 } else {
1757 if (search_message_id == message_id) {
1758 found_id = message_id;
1759 break;
1760 }
1761 }
1762 }
1763
1764 if (cur && cur->subreq) {
1765 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1766 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1767 "cancel opcode[%s] mid %llu\n",
1768 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1769 (unsigned long long)found_id ));
1770 tevent_req_cancel(cur->subreq);
1771 }
1772
1773 return NT_STATUS_OK;
1774}
1775
1776/*************************************************************
1777 Ensure an incoming tid is a valid one for us to access.
1778 Change to the associated uid credentials and chdir to the
1779 valid tid directory.
1780*************************************************************/
1781
1782static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1783{
1784 const uint8_t *inhdr;
1785 uint32_t in_flags;
1786 uint32_t in_tid;
1787 struct smbXsrv_tcon *tcon;
1788 NTSTATUS status;
1789 NTTIME now = timeval_to_nttime(&req->request_time);
1790
1791 req->tcon = NULL;
1792
1793 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1794
1795 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1796 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1797
1798 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1799 in_tid = req->last_tid;
1800 }
1801
1802 req->last_tid = 0;
1803
1804 status = smb2srv_tcon_lookup(req->session,
1805 in_tid, now, &tcon);
1806 if (!NT_STATUS_IS_OK(status)) {
1807 return status;
1808 }
1809
1810 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1811 return NT_STATUS_ACCESS_DENIED;
1812 }
1813
1814 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1815 if (!set_current_service(tcon->compat, 0, true)) {
1816 return NT_STATUS_ACCESS_DENIED;
1817 }
1818
1819 req->tcon = tcon;
1820 req->last_tid = in_tid;
1821
1822 return NT_STATUS_OK;
1823}
1824
1825/*************************************************************
1826 Ensure an incoming session_id is a valid one for us to access.
1827*************************************************************/
1828
1829static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1830{
1831 const uint8_t *inhdr;
1832 uint32_t in_flags;
1833 uint16_t in_opcode;
1834 uint64_t in_session_id;
1835 struct smbXsrv_session *session = NULL;
1836 struct auth_session_info *session_info;
1837 NTSTATUS status;
1838 NTTIME now = timeval_to_nttime(&req->request_time);
1839
1840 req->session = NULL;
1841 req->tcon = NULL;
1842
1843 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1844
1845 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1846 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1847 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1848
1849 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1850 in_session_id = req->last_session_id;
1851 }
1852
1853 req->last_session_id = 0;
1854
1855 /* look an existing session up */
1856 switch (in_opcode) {
1857 case SMB2_OP_SESSSETUP:
1858 /*
1859 * For a session bind request, we don't have the
1860 * channel set up at this point yet, so we defer
1861 * the verification that the connection belongs
1862 * to the session to the session setup code, which
1863 * can look at the session binding flags.
1864 */
1865 status = smb2srv_session_lookup_client(req->xconn->client,
1866 in_session_id, now,
1867 &session);
1868 break;
1869 default:
1870 status = smb2srv_session_lookup_conn(req->xconn,
1871 in_session_id, now,
1872 &session);
1873 break;
1874 }
1875 if (session) {
1876 req->session = session;
1877 req->last_session_id = in_session_id;
1878 }
1879 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1880 switch (in_opcode) {
1881 case SMB2_OP_SESSSETUP:
1882 status = NT_STATUS_OK;
1883 break;
1884 default:
1885 break;
1886 }
1887 }
1888 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1889 switch (in_opcode) {
1890 case SMB2_OP_TCON:
1891 case SMB2_OP_CREATE:
1892 case SMB2_OP_GETINFO:
1893 case SMB2_OP_SETINFO:
1894 return NT_STATUS_INVALID_HANDLE;
1895 default:
1896 /*
1897 * Notice the check for
1898 * (session_info == NULL)
1899 * below.
1900 */
1901 status = NT_STATUS_OK;
1902 break;
1903 }
1904 }
1905 if (!NT_STATUS_IS_OK(status)) {
1906 return status;
1907 }
1908
1909 session_info = session->global->auth_session_info;
1910 if (session_info == NULL) {
1911 return NT_STATUS_INVALID_HANDLE;
1912 }
1913
1914 if (in_session_id != req->xconn->client->last_session_id) {
1915 req->xconn->client->last_session_id = in_session_id;
1916 set_current_user_info(session_info->unix_info->sanitized_username,
1917 session_info->unix_info->unix_name,
1918 session_info->info->domain_name);
1919 }
1920
1921 return NT_STATUS_OK;
1922}
1923
1924NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1925 uint32_t data_length)
1926{
1927 struct smbXsrv_connection *xconn = req->xconn;
1928 uint16_t needed_charge;
1929 uint16_t credit_charge = 1;
1930 const uint8_t *inhdr;
1931
1932 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1933
1934 if (xconn->smb2.credits.multicredit) {
1935 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1936 credit_charge = MAX(credit_charge, 1);
1937 }
1938
1939 needed_charge = (data_length - 1)/ 65536 + 1;
1940
1941 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1942 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1943 credit_charge, needed_charge));
1944
1945 if (needed_charge > credit_charge) {
1946 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1947 credit_charge, needed_charge));
1948 return NT_STATUS_INVALID_PARAMETER;
1949 }
1950
1951 return NT_STATUS_OK;
1952}
1953
1954NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1955 size_t expected_body_size)
1956{
1957 struct iovec *inhdr_v;
1958 const uint8_t *inhdr;
1959 uint16_t opcode;
1960 const uint8_t *inbody;
1961 size_t body_size;
1962 size_t min_dyn_size = expected_body_size & 0x00000001;
1963 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1964
1965 /*
1966 * The following should be checked already.
1967 */
1968 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1969 return NT_STATUS_INTERNAL_ERROR;
1970 }
1971 if (req->current_idx > max_idx) {
1972 return NT_STATUS_INTERNAL_ERROR;
1973 }
1974
1975 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1976 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1977 return NT_STATUS_INTERNAL_ERROR;
1978 }
1979 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1980 return NT_STATUS_INTERNAL_ERROR;
1981 }
1982
1983 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1984 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1985
1986 switch (opcode) {
1987 case SMB2_OP_IOCTL:
1988 case SMB2_OP_GETINFO:
1989 min_dyn_size = 0;
1990 break;
1991 case SMB2_OP_WRITE:
1992 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
1993 if (req->smb1req->unread_bytes < min_dyn_size) {
1994 return NT_STATUS_INVALID_PARAMETER;
1995 }
1996
1997 min_dyn_size = 0;
1998 }
1999 break;
2000 }
2001
2002 /*
2003 * Now check the expected body size,
2004 * where the last byte might be in the
2005 * dynamic section..
2006 */
2007 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
2008 return NT_STATUS_INVALID_PARAMETER;
2009 }
2010 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
2011 return NT_STATUS_INVALID_PARAMETER;
2012 }
2013
2014 inbody = SMBD_SMB2_IN_BODY_PTR(req);
2015
2016 body_size = SVAL(inbody, 0x00);
2017 if (body_size != expected_body_size) {
2018 return NT_STATUS_INVALID_PARAMETER;
2019 }
2020
2021 return NT_STATUS_OK;
2022}
2023
2024bool smbXsrv_is_encrypted(uint8_t encryption_flags)
2025{
2026 return (!(encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)
2027 &&
2028 (encryption_flags & (SMBXSRV_PROCESSED_ENCRYPTED_PACKET |
2029 SMBXSRV_ENCRYPTION_DESIRED |
2030 SMBXSRV_ENCRYPTION_REQUIRED)));
2031}
2032
2033bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags)
2034{
2035 return ((encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET) &&
2036 (encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET));
2037}
2038
2039/* Set a flag if not already set, return true if set */
2040bool smbXsrv_set_crypto_flag(uint8_t *flags, uint8_t flag)
2041{
2042 if ((flag == 0) || (*flags & flag)) {
2043 return false;
2044 }
2045
2046 *flags |= flag;
2047 return true;
2048}
2049
2050/*
2051 * Update encryption state tracking flags, this can be used to
2052 * determine whether whether the session or tcon is "encrypted".
2053 */
2054static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
2055 uint16_t opcode,
2056 bool *update_session_globalp,
2057 bool *update_tcon_globalp)
2058{
2059 /* Default: assume unecrypted and unsigned */
2060 struct smbXsrv_session *session = req->session;
2061 struct smbXsrv_tcon *tcon = req->tcon;
2062 uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
2063 uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2064 bool update_session = false;
2065 bool update_tcon = false;
2066
2067 if (req->was_encrypted && req->do_encryption) {
2068 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
2069 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2070 } else {
2071 /* Unencrypted packet, can be signed */
2072 if (req->do_signing) {
2073 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2074 } else if (opcode == SMB2_OP_CANCEL) {
2075 /* Cancel requests are allowed to skip signing */
2076 sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2077 }
2078 }
2079
2080 update_session |= smbXsrv_set_crypto_flag(
2081 &session->global->encryption_flags, encrypt_flag);
2082 update_session |= smbXsrv_set_crypto_flag(
2083 &session->global->signing_flags, sign_flag);
2084
2085 if (tcon) {
2086 update_tcon |= smbXsrv_set_crypto_flag(
2087 &tcon->global->encryption_flags, encrypt_flag);
2088 update_tcon |= smbXsrv_set_crypto_flag(
2089 &tcon->global->signing_flags, sign_flag);
2090 }
2091
2092 *update_session_globalp = update_session;
2093 *update_tcon_globalp = update_tcon;
2094 return;
2095}
2096
2097bool smbXsrv_is_signed(uint8_t signing_flags)
2098{
2099 /*
2100 * Signing is always enabled, so unless we got an unsigned
2101 * packet and at least one signed packet that was not
2102 * encrypted, the session or tcon is "signed".
2103 */
2104 return (!(signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2105 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2106}
2107
2108bool smbXsrv_is_partially_signed(uint8_t signing_flags)
2109{
2110 return ((signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2111 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2112}
2113
2114static NTSTATUS smbd_smb2_request_dispatch_update_counts(
2115 struct smbd_smb2_request *req,
2116 bool modify_call)
2117{
2118 struct smbXsrv_connection *xconn = req->xconn;
2119 const uint8_t *inhdr;
2120 uint16_t channel_sequence;
2121 uint32_t flags;
2122 int cmp;
2123 struct smbXsrv_open *op;
2124 bool update_open = false;
2125 NTSTATUS status = NT_STATUS_OK;
2126
2127 req->request_counters_updated = false;
2128
2129 if (xconn->protocol < PROTOCOL_SMB2_22) {
2130 return NT_STATUS_OK;
2131 }
2132
2133 if (req->compat_chain_fsp == NULL) {
2134 return NT_STATUS_OK;
2135 }
2136
2137 op = req->compat_chain_fsp->op;
2138 if (op == NULL) {
2139 return NT_STATUS_OK;
2140 }
2141
2142 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2143 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2144 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2145
2146 cmp = channel_sequence - op->global->channel_sequence;
2147
2148 if (abs(cmp) > INT16_MAX) {
2149 /*
2150 * [MS-SMB2] 3.3.5.2.10 - Verifying the Channel Sequence Number:
2151 *
2152 * If the channel sequence number of the request and the one
2153 * known to the server are not equal, the channel sequence
2154 * number and outstanding request counts are only updated
2155 * "... if the unsigned difference using 16-bit arithmetic
2156 * between ChannelSequence and Open.ChannelSequence is less than
2157 * or equal to 0x7FFF ...".
2158 * Otherwise, an error is returned for the modifying
2159 * calls write, set_info, and ioctl.
2160 *
2161 * There are currently two issues with the description:
2162 *
2163 * * For the other calls, the document seems to imply
2164 * that processing continues without adapting the
2165 * counters (if the sequence numbers are not equal).
2166 *
2167 * TODO: This needs clarification!
2168 *
2169 * * Also, the behaviour if the difference is larger
2170 * than 0x7FFF is not clear. The document seems to
2171 * imply that if such a difference is reached,
2172 * the server starts to ignore the counters or
2173 * in the case of the modifying calls, return errors.
2174 *
2175 * TODO: This needs clarification!
2176 *
2177 * At this point Samba tries to be a little more
2178 * clever than the description in the MS-SMB2 document
2179 * by heuristically detecting and properly treating
2180 * a 16 bit overflow of the client-submitted sequence
2181 * number:
2182 *
2183 * If the stored channel squence number is more than
2184 * 0x7FFF larger than the one from the request, then
2185 * the client-provided sequence number has likely
2186 * overflown. We treat this case as valid instead
2187 * of as failure.
2188 *
2189 * The MS-SMB2 behaviour would be setting cmp = -1.
2190 */
2191 cmp *= -1;
2192 }
2193
2194 if (!(flags & SMB2_HDR_FLAG_REPLAY_OPERATION)) {
2195 if (cmp == 0) {
2196 op->request_count += 1;
2197 req->request_counters_updated = true;
2198 } else if (cmp > 0) {
2199 op->pre_request_count += op->request_count;
2200 op->request_count = 1;
2201 op->global->channel_sequence = channel_sequence;
2202 update_open = true;
2203 req->request_counters_updated = true;
2204 } else if (modify_call) {
2205 return NT_STATUS_FILE_NOT_AVAILABLE;
2206 }
2207 } else {
2208 if (cmp == 0 && op->pre_request_count == 0) {
2209 op->request_count += 1;
2210 req->request_counters_updated = true;
2211 } else if (cmp > 0 && op->pre_request_count == 0) {
2212 op->pre_request_count += op->request_count;
2213 op->request_count = 1;
2214 op->global->channel_sequence = channel_sequence;
2215 update_open = true;
2216 req->request_counters_updated = true;
2217 } else if (modify_call) {
2218 return NT_STATUS_FILE_NOT_AVAILABLE;
2219 }
2220 }
2221
2222 if (update_open) {
2223 status = smbXsrv_open_update(op);
2224 }
2225
2226 return status;
2227}
2228
2229NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
2230{
2231 struct smbXsrv_connection *xconn = req->xconn;
2232 const struct smbd_smb2_dispatch_table *call = NULL;
2233 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
2234 const uint8_t *inhdr;
2235 uint16_t opcode;
2236 uint32_t flags;
2237 uint64_t mid;
2238 NTSTATUS status;
2239 NTSTATUS session_status;
2240 uint32_t allowed_flags;
2241 NTSTATUS return_value;
2242 struct smbXsrv_session *x = NULL;
2243 bool signing_required = false;
2244 bool encryption_desired = false;
2245 bool encryption_required = false;
2246
2247 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2248
2249 DO_PROFILE_INC(request);
2250
2251 /* TODO: verify more things */
2252
2253 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2254 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2255 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2256 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
2257 smb2_opcode_name(opcode),
2258 (unsigned long long)mid));
2259
2260 if (xconn->protocol >= PROTOCOL_SMB2_02) {
2261 /*
2262 * once the protocol is negotiated
2263 * SMB2_OP_NEGPROT is not allowed anymore
2264 */
2265 if (opcode == SMB2_OP_NEGPROT) {
2266 /* drop the connection */
2267 return NT_STATUS_INVALID_PARAMETER;
2268 }
2269 } else {
2270 /*
2271 * if the protocol is not negotiated yet
2272 * only SMB2_OP_NEGPROT is allowed.
2273 */
2274 if (opcode != SMB2_OP_NEGPROT) {
2275 /* drop the connection */
2276 return NT_STATUS_INVALID_PARAMETER;
2277 }
2278 }
2279
2280 /*
2281 * Check if the client provided a valid session id,
2282 * if so smbd_smb2_request_check_session() calls
2283 * set_current_user_info().
2284 *
2285 * As some command don't require a valid session id
2286 * we defer the check of the session_status
2287 */
2288 session_status = smbd_smb2_request_check_session(req);
2289 x = req->session;
2290 if (x != NULL) {
2291 signing_required = x->global->signing_flags & SMBXSRV_SIGNING_REQUIRED;
2292 encryption_desired = x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
2293 encryption_required = x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
2294 }
2295
2296 req->do_signing = false;
2297 req->do_encryption = false;
2298 req->was_encrypted = false;
2299 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
2300 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
2301 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
2302
2303 if (x != NULL && x->global->session_wire_id != tf_session_id) {
2304 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2305 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
2306 (unsigned long long)x->global->session_wire_id,
2307 (unsigned long long)tf_session_id));
2308 /*
2309 * TODO: windows allows this...
2310 * should we drop the connection?
2311 *
2312 * For now we just return ACCESS_DENIED
2313 * (Windows clients never trigger this)
2314 * and wait for an update of [MS-SMB2].
2315 */
2316 return smbd_smb2_request_error(req,
2317 NT_STATUS_ACCESS_DENIED);
2318 }
2319
2320 req->was_encrypted = true;
2321 }
2322
2323 if (encryption_required && !req->was_encrypted) {
2324 return smbd_smb2_request_error(req,
2325 NT_STATUS_ACCESS_DENIED);
2326 }
2327
2328 call = smbd_smb2_call(opcode);
2329 if (call == NULL) {
2330 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2331 }
2332
2333 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2334 SMB2_HDR_FLAG_SIGNED |
2335 SMB2_HDR_FLAG_DFS;
2336 if (xconn->protocol >= PROTOCOL_SMB3_11) {
2337 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2338 }
2339 if (opcode == SMB2_OP_NEGPROT) {
2340 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11) {
2341 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2342 }
2343 }
2344 if (opcode == SMB2_OP_CANCEL) {
2345 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2346 }
2347 if (xconn->protocol >= PROTOCOL_SMB2_22) {
2348 allowed_flags |= SMB2_HDR_FLAG_REPLAY_OPERATION;
2349 }
2350 if ((flags & ~allowed_flags) != 0) {
2351 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2352 }
2353
2354 if (flags & SMB2_HDR_FLAG_CHAINED) {
2355 /*
2356 * This check is mostly for giving the correct error code
2357 * for compounded requests.
2358 */
2359 if (!NT_STATUS_IS_OK(session_status)) {
2360 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2361 }
2362 } else {
2363 req->compat_chain_fsp = NULL;
2364 }
2365
2366 if (req->was_encrypted) {
2367 signing_required = false;
2368 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2369 DATA_BLOB signing_key = data_blob_null;
2370
2371 if (x == NULL) {
2372 /*
2373 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2374 * If the SMB2 header of the SMB2 NEGOTIATE
2375 * request has the SMB2_FLAGS_SIGNED bit set in the
2376 * Flags field, the server MUST fail the request
2377 * with STATUS_INVALID_PARAMETER.
2378 *
2379 * Microsoft test tool checks this.
2380 */
2381
2382 if ((opcode == SMB2_OP_NEGPROT) &&
2383 (flags & SMB2_HDR_FLAG_SIGNED)) {
2384 status = NT_STATUS_INVALID_PARAMETER;
2385 } else {
2386 status = NT_STATUS_USER_SESSION_DELETED;
2387 }
2388 return smbd_smb2_request_error(req, status);
2389 }
2390
2391 signing_key = smbd_smb2_signing_key(x, xconn);
2392
2393 /*
2394 * If we have a signing key, we should
2395 * sign the response
2396 */
2397 if (signing_key.length > 0) {
2398 req->do_signing = true;
2399 }
2400
2401 status = smb2_signing_check_pdu(signing_key,
2402 xconn->protocol,
2403 SMBD_SMB2_IN_HDR_IOV(req),
2404 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2405 if (!NT_STATUS_IS_OK(status)) {
2406 return smbd_smb2_request_error(req, status);
2407 }
2408
2409 /*
2410 * Now that we know the request was correctly signed
2411 * we have to sign the response too.
2412 */
2413 req->do_signing = true;
2414
2415 if (!NT_STATUS_IS_OK(session_status)) {
2416 return smbd_smb2_request_error(req, session_status);
2417 }
2418 } else if (opcode == SMB2_OP_CANCEL) {
2419 /* Cancel requests are allowed to skip the signing */
2420 } else if (signing_required) {
2421 /*
2422 * If signing is required we try to sign
2423 * a possible error response
2424 */
2425 req->do_signing = true;
2426 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2427 }
2428
2429 if (flags & SMB2_HDR_FLAG_CHAINED) {
2430 req->compound_related = true;
2431 }
2432
2433 if (call->need_session) {
2434 if (!NT_STATUS_IS_OK(session_status)) {
2435 return smbd_smb2_request_error(req, session_status);
2436 }
2437 }
2438
2439 if (call->need_tcon) {
2440 SMB_ASSERT(call->need_session);
2441
2442 /*
2443 * This call needs to be run as user.
2444 *
2445 * smbd_smb2_request_check_tcon()
2446 * calls change_to_user() on success.
2447 */
2448 status = smbd_smb2_request_check_tcon(req);
2449 if (!NT_STATUS_IS_OK(status)) {
2450 return smbd_smb2_request_error(req, status);
2451 }
2452 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
2453 encryption_desired = true;
2454 }
2455 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
2456 encryption_required = true;
2457 }
2458 if (encryption_required && !req->was_encrypted) {
2459 return smbd_smb2_request_error(req,
2460 NT_STATUS_ACCESS_DENIED);
2461 }
2462 }
2463
2464 if (req->was_encrypted || encryption_desired) {
2465 req->do_encryption = true;
2466 }
2467
2468 if (req->session) {
2469 bool update_session_global = false;
2470 bool update_tcon_global = false;
2471
2472 smb2srv_update_crypto_flags(req, opcode,
2473 &update_session_global,
2474 &update_tcon_global);
2475
2476 if (update_session_global) {
2477 status = smbXsrv_session_update(x);
2478 if (!NT_STATUS_IS_OK(status)) {
2479 return smbd_smb2_request_error(req, status);
2480 }
2481 }
2482 if (update_tcon_global) {
2483 status = smbXsrv_tcon_update(req->tcon);
2484 if (!NT_STATUS_IS_OK(status)) {
2485 return smbd_smb2_request_error(req, status);
2486 }
2487 }
2488 }
2489
2490 if (call->fileid_ofs != 0) {
2491 size_t needed = call->fileid_ofs + 16;
2492 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2493 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2494 uint64_t file_id_persistent;
2495 uint64_t file_id_volatile;
2496 struct files_struct *fsp;
2497
2498 SMB_ASSERT(call->need_tcon);
2499
2500 if (needed > body_size) {
2501 return smbd_smb2_request_error(req,
2502 NT_STATUS_INVALID_PARAMETER);
2503 }
2504
2505 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2506 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2507
2508 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2509 if (fsp == NULL) {
2510 if (!call->allow_invalid_fileid) {
2511 return smbd_smb2_request_error(req,
2512 NT_STATUS_FILE_CLOSED);
2513 }
2514
2515 if (file_id_persistent != UINT64_MAX) {
2516 return smbd_smb2_request_error(req,
2517 NT_STATUS_FILE_CLOSED);
2518 }
2519 if (file_id_volatile != UINT64_MAX) {
2520 return smbd_smb2_request_error(req,
2521 NT_STATUS_FILE_CLOSED);
2522 }
2523 }
2524 }
2525
2526 status = smbd_smb2_request_dispatch_update_counts(req, call->modify);
2527 if (!NT_STATUS_IS_OK(status)) {
2528 return smbd_smb2_request_error(req, status);
2529 }
2530
2531 if (call->as_root) {
2532 SMB_ASSERT(call->fileid_ofs == 0);
2533 /* This call needs to be run as root */
2534 change_to_root_user();
2535 } else {
2536 SMB_ASSERT(call->need_tcon);
2537 }
2538
2539#define _INBYTES(_r) \
2540 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
2541
2542 switch (opcode) {
2543 case SMB2_OP_NEGPROT:
2544 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
2545 req->profile, _INBYTES(req));
2546 return_value = smbd_smb2_request_process_negprot(req);
2547 break;
2548
2549 case SMB2_OP_SESSSETUP:
2550 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
2551 req->profile, _INBYTES(req));
2552 return_value = smbd_smb2_request_process_sesssetup(req);
2553 break;
2554
2555 case SMB2_OP_LOGOFF:
2556 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
2557 req->profile, _INBYTES(req));
2558 return_value = smbd_smb2_request_process_logoff(req);
2559 break;
2560
2561 case SMB2_OP_TCON:
2562 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
2563 req->profile, _INBYTES(req));
2564 return_value = smbd_smb2_request_process_tcon(req);
2565 break;
2566
2567 case SMB2_OP_TDIS:
2568 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
2569 req->profile, _INBYTES(req));
2570 return_value = smbd_smb2_request_process_tdis(req);
2571 break;
2572
2573 case SMB2_OP_CREATE:
2574 if (req->subreq == NULL) {
2575 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
2576 req->profile, _INBYTES(req));
2577 } else {
2578 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
2579 }
2580 return_value = smbd_smb2_request_process_create(req);
2581 break;
2582
2583 case SMB2_OP_CLOSE:
2584 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
2585 req->profile, _INBYTES(req));
2586 return_value = smbd_smb2_request_process_close(req);
2587 break;
2588
2589 case SMB2_OP_FLUSH:
2590 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
2591 req->profile, _INBYTES(req));
2592 return_value = smbd_smb2_request_process_flush(req);
2593 break;
2594
2595 case SMB2_OP_READ:
2596 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
2597 req->profile, _INBYTES(req));
2598 return_value = smbd_smb2_request_process_read(req);
2599 break;
2600
2601 case SMB2_OP_WRITE:
2602 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
2603 req->profile, _INBYTES(req));
2604 return_value = smbd_smb2_request_process_write(req);
2605 break;
2606
2607 case SMB2_OP_LOCK:
2608 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
2609 req->profile, _INBYTES(req));
2610 return_value = smbd_smb2_request_process_lock(req);
2611 break;
2612
2613 case SMB2_OP_IOCTL:
2614 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
2615 req->profile, _INBYTES(req));
2616 return_value = smbd_smb2_request_process_ioctl(req);
2617 break;
2618
2619 case SMB2_OP_CANCEL:
2620 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
2621 req->profile, _INBYTES(req));
2622 return_value = smbd_smb2_request_process_cancel(req);
2623 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
2624
2625 /*
2626 * We don't need the request anymore cancel requests never
2627 * have a response.
2628 *
2629 * smbd_smb2_request_process_cancel() already called
2630 * DLIST_REMOVE(xconn->smb2.requests, req);
2631 */
2632 TALLOC_FREE(req);
2633
2634 break;
2635
2636 case SMB2_OP_KEEPALIVE:
2637 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
2638 req->profile, _INBYTES(req));
2639 return_value = smbd_smb2_request_process_keepalive(req);
2640 break;
2641
2642 case SMB2_OP_QUERY_DIRECTORY:
2643 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
2644 req->profile, _INBYTES(req));
2645 return_value = smbd_smb2_request_process_query_directory(req);
2646 break;
2647
2648 case SMB2_OP_NOTIFY:
2649 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
2650 req->profile, _INBYTES(req));
2651 return_value = smbd_smb2_request_process_notify(req);
2652 break;
2653
2654 case SMB2_OP_GETINFO:
2655 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
2656 req->profile, _INBYTES(req));
2657 return_value = smbd_smb2_request_process_getinfo(req);
2658 break;
2659
2660 case SMB2_OP_SETINFO:
2661 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
2662 req->profile, _INBYTES(req));
2663 return_value = smbd_smb2_request_process_setinfo(req);
2664 break;
2665
2666 case SMB2_OP_BREAK:
2667 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
2668 req->profile, _INBYTES(req));
2669 return_value = smbd_smb2_request_process_break(req);
2670 break;
2671
2672 default:
2673 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2674 break;
2675 }
2676 return return_value;
2677}
2678
2679static void smbd_smb2_request_reply_update_counts(struct smbd_smb2_request *req)
2680{
2681 struct smbXsrv_connection *xconn = req->xconn;
2682 const uint8_t *inhdr;
2683 uint16_t channel_sequence;
2684 struct smbXsrv_open *op;
2685
2686 if (!req->request_counters_updated) {
2687 return;
2688 }
2689
2690 if (xconn->protocol < PROTOCOL_SMB2_22) {
2691 return;
2692 }
2693
2694 if (req->compat_chain_fsp == NULL) {
2695 return;
2696 }
2697
2698 op = req->compat_chain_fsp->op;
2699 if (op == NULL) {
2700 return;
2701 }
2702
2703 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2704 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2705
2706 if (op->global->channel_sequence == channel_sequence) {
2707 SMB_ASSERT(op->request_count > 0);
2708 op->request_count -= 1;
2709 } else {
2710 SMB_ASSERT(op->pre_request_count > 0);
2711 op->pre_request_count -= 1;
2712 }
2713}
2714
2715static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2716{
2717 struct smbXsrv_connection *xconn = req->xconn;
2718 int first_idx = 1;
2719 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2720 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2721 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2722 NTSTATUS status;
2723 bool ok;
2724
2725 req->subreq = NULL;
2726 TALLOC_FREE(req->async_te);
2727
2728 /* MS-SMB2: 3.3.4.1 Sending Any Outgoing Message */
2729 smbd_smb2_request_reply_update_counts(req);
2730
2731 if (req->do_encryption &&
2732 (firsttf->iov_len == 0) &&
2733 (req->first_key.length == 0) &&
2734 (req->session != NULL) &&
2735 (req->session->global->encryption_key.length != 0))
2736 {
2737 DATA_BLOB encryption_key = req->session->global->encryption_key;
2738 uint8_t *tf;
2739 uint64_t session_id = req->session->global->session_wire_id;
2740 uint64_t nonce_high;
2741 uint64_t nonce_low;
2742
2743 status = smb2_get_new_nonce(req->session,
2744 &nonce_high,
2745 &nonce_low);
2746 if (!NT_STATUS_IS_OK(status)) {
2747 return status;
2748 }
2749
2750 /*
2751 * We need to place the SMB2_TRANSFORM header before the
2752 * first SMB2 header
2753 */
2754
2755 /*
2756 * we need to remember the encryption key
2757 * and defer the signing/encryption until
2758 * we are sure that we do not change
2759 * the header again.
2760 */
2761 req->first_key = data_blob_dup_talloc(req, encryption_key);
2762 if (req->first_key.data == NULL) {
2763 return NT_STATUS_NO_MEMORY;
2764 }
2765
2766 tf = talloc_zero_array(req, uint8_t,
2767 SMB2_TF_HDR_SIZE);
2768 if (tf == NULL) {
2769 return NT_STATUS_NO_MEMORY;
2770 }
2771
2772 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2773 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2774 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2775 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2776
2777 firsttf->iov_base = (void *)tf;
2778 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2779 }
2780
2781 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2782 (req->last_key.length > 0) &&
2783 (firsttf->iov_len == 0))
2784 {
2785 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2786 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2787
2788 /*
2789 * As we are sure the header of the last request in the
2790 * compound chain will not change, we can to sign here
2791 * with the last signing key we remembered.
2792 */
2793 status = smb2_signing_sign_pdu(req->last_key,
2794 xconn->protocol,
2795 lasthdr,
2796 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2797 if (!NT_STATUS_IS_OK(status)) {
2798 return status;
2799 }
2800 }
2801 if (req->last_key.length > 0) {
2802 data_blob_clear_free(&req->last_key);
2803 }
2804
2805 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
2806 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
2807
2808 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2809
2810 if (req->current_idx < req->out.vector_count) {
2811 /*
2812 * We must process the remaining compound
2813 * SMB2 requests before any new incoming SMB2
2814 * requests. This is because incoming SMB2
2815 * requests may include a cancel for a
2816 * compound request we haven't processed
2817 * yet.
2818 */
2819 struct tevent_immediate *im = tevent_create_immediate(req);
2820 if (!im) {
2821 return NT_STATUS_NO_MEMORY;
2822 }
2823
2824 if (req->do_signing && firsttf->iov_len == 0) {
2825 struct smbXsrv_session *x = req->session;
2826 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2827
2828 /*
2829 * we need to remember the signing key
2830 * and defer the signing until
2831 * we are sure that we do not change
2832 * the header again.
2833 */
2834 req->last_key = data_blob_dup_talloc(req, signing_key);
2835 if (req->last_key.data == NULL) {
2836 return NT_STATUS_NO_MEMORY;
2837 }
2838 }
2839
2840 tevent_schedule_immediate(im,
2841 req->sconn->ev_ctx,
2842 smbd_smb2_request_dispatch_immediate,
2843 req);
2844 return NT_STATUS_OK;
2845 }
2846
2847 if (req->compound_related) {
2848 req->compound_related = false;
2849 }
2850
2851 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2852 if (!ok) {
2853 return NT_STATUS_INVALID_PARAMETER_MIX;
2854 }
2855
2856 /* Set credit for these operations (zero credits if this
2857 is a final reply for an async operation). */
2858 smb2_calculate_credits(req, req);
2859
2860 /*
2861 * now check if we need to sign the current response
2862 */
2863 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2864 status = smb2_signing_encrypt_pdu(req->first_key,
2865 xconn->smb2.server.cipher,
2866 firsttf,
2867 req->out.vector_count - first_idx);
2868 if (!NT_STATUS_IS_OK(status)) {
2869 return status;
2870 }
2871 } else if (req->do_signing) {
2872 struct smbXsrv_session *x = req->session;
2873 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2874
2875 status = smb2_signing_sign_pdu(signing_key,
2876 xconn->protocol,
2877 outhdr,
2878 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2879 if (!NT_STATUS_IS_OK(status)) {
2880 return status;
2881 }
2882 }
2883 if (req->first_key.length > 0) {
2884 data_blob_clear_free(&req->first_key);
2885 }
2886
2887 if (req->preauth != NULL) {
2888 struct hc_sha512state sctx;
2889 int i;
2890
2891 samba_SHA512_Init(&sctx);
2892 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2893 sizeof(req->preauth->sha512_value));
2894 for (i = 1; i < req->in.vector_count; i++) {
2895 samba_SHA512_Update(&sctx,
2896 req->in.vector[i].iov_base,
2897 req->in.vector[i].iov_len);
2898 }
2899 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2900
2901 samba_SHA512_Init(&sctx);
2902 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2903 sizeof(req->preauth->sha512_value));
2904 for (i = 1; i < req->out.vector_count; i++) {
2905 samba_SHA512_Update(&sctx,
2906 req->out.vector[i].iov_base,
2907 req->out.vector[i].iov_len);
2908 }
2909 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2910
2911 req->preauth = NULL;
2912 }
2913
2914 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2915 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2916 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2917 /* Dynamic part is NULL. Chop it off,
2918 We're going to send it via sendfile. */
2919 req->out.vector_count -= 1;
2920 }
2921
2922 /*
2923 * We're done with this request -
2924 * move it off the "being processed" queue.
2925 */
2926 DLIST_REMOVE(xconn->smb2.requests, req);
2927
2928 req->queue_entry.mem_ctx = req;
2929 req->queue_entry.vector = req->out.vector;
2930 req->queue_entry.count = req->out.vector_count;
2931 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry);
2932 xconn->smb2.send_queue_len++;
2933
2934 status = smbd_smb2_flush_send_queue(xconn);
2935 if (!NT_STATUS_IS_OK(status)) {
2936 return status;
2937 }
2938
2939 return NT_STATUS_OK;
2940}
2941
2942static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
2943
2944void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2945 struct tevent_immediate *im,
2946 void *private_data)
2947{
2948 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2949 struct smbd_smb2_request);
2950 struct smbXsrv_connection *xconn = req->xconn;
2951 NTSTATUS status;
2952
2953 TALLOC_FREE(im);
2954
2955 if (DEBUGLEVEL >= 10) {
2956 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2957 req->current_idx, req->in.vector_count));
2958 print_req_vectors(req);
2959 }
2960
2961 status = smbd_smb2_request_dispatch(req);
2962 if (!NT_STATUS_IS_OK(status)) {
2963 smbd_server_connection_terminate(xconn, nt_errstr(status));
2964 return;
2965 }
2966
2967 status = smbd_smb2_request_next_incoming(xconn);
2968 if (!NT_STATUS_IS_OK(status)) {
2969 smbd_server_connection_terminate(xconn, nt_errstr(status));
2970 return;
2971 }
2972}
2973
2974NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2975 NTSTATUS status,
2976 DATA_BLOB body, DATA_BLOB *dyn,
2977 const char *location)
2978{
2979 uint8_t *outhdr;
2980 struct iovec *outbody_v;
2981 struct iovec *outdyn_v;
2982 uint32_t next_command_ofs;
2983
2984 DEBUG(10,("smbd_smb2_request_done_ex: "
2985 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2986 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2987 dyn ? "yes": "no",
2988 (unsigned int)(dyn ? dyn->length : 0),
2989 location));
2990
2991 if (body.length < 2) {
2992 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2993 }
2994
2995 if ((body.length % 2) != 0) {
2996 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2997 }
2998
2999 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3000 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
3001 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
3002
3003 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
3004 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
3005
3006 outbody_v->iov_base = (void *)body.data;
3007 outbody_v->iov_len = body.length;
3008
3009 if (dyn) {
3010 outdyn_v->iov_base = (void *)dyn->data;
3011 outdyn_v->iov_len = dyn->length;
3012 } else {
3013 outdyn_v->iov_base = NULL;
3014 outdyn_v->iov_len = 0;
3015 }
3016
3017 /*
3018 * See if we need to recalculate the offset to the next response
3019 *
3020 * Note that all responses may require padding (including the very last
3021 * one).
3022 */
3023 if (req->out.vector_count >= (2 * SMBD_SMB2_NUM_IOV_PER_REQ)) {
3024 next_command_ofs = SMB2_HDR_BODY;
3025 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
3026 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
3027 }
3028
3029 if ((next_command_ofs % 8) != 0) {
3030 size_t pad_size = 8 - (next_command_ofs % 8);
3031 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
3032 /*
3033 * if the dyn buffer is empty
3034 * we can use it to add padding
3035 */
3036 uint8_t *pad;
3037
3038 pad = talloc_zero_array(req,
3039 uint8_t, pad_size);
3040 if (pad == NULL) {
3041 return smbd_smb2_request_error(req,
3042 NT_STATUS_NO_MEMORY);
3043 }
3044
3045 outdyn_v->iov_base = (void *)pad;
3046 outdyn_v->iov_len = pad_size;
3047 } else {
3048 /*
3049 * For now we copy the dynamic buffer
3050 * and add the padding to the new buffer
3051 */
3052 size_t old_size;
3053 uint8_t *old_dyn;
3054 size_t new_size;
3055 uint8_t *new_dyn;
3056
3057 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
3058 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
3059
3060 new_size = old_size + pad_size;
3061 new_dyn = talloc_zero_array(req,
3062 uint8_t, new_size);
3063 if (new_dyn == NULL) {
3064 return smbd_smb2_request_error(req,
3065 NT_STATUS_NO_MEMORY);
3066 }
3067
3068 memcpy(new_dyn, old_dyn, old_size);
3069 memset(new_dyn + old_size, 0, pad_size);
3070
3071 outdyn_v->iov_base = (void *)new_dyn;
3072 outdyn_v->iov_len = new_size;
3073 }
3074 next_command_ofs += pad_size;
3075 }
3076
3077 if ((req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) >= req->out.vector_count) {
3078 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
3079 } else {
3080 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
3081 }
3082 return smbd_smb2_request_reply(req);
3083}
3084
3085NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
3086 NTSTATUS status,
3087 DATA_BLOB *info,
3088 const char *location)
3089{
3090 struct smbXsrv_connection *xconn = req->xconn;
3091 DATA_BLOB body;
3092 DATA_BLOB _dyn;
3093 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3094 size_t unread_bytes = smbd_smb2_unread_bytes(req);
3095
3096 DBG_NOTICE("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| "
3097 "at %s\n", req->current_idx, nt_errstr(status),
3098 info ? " +info" : "", location);
3099
3100 if (unread_bytes) {
3101 /* Recvfile error. Drain incoming socket. */
3102 size_t ret;
3103
3104 errno = 0;
3105 ret = drain_socket(xconn->transport.sock, unread_bytes);
3106 if (ret != unread_bytes) {
3107 NTSTATUS error;
3108
3109 if (errno == 0) {
3110 error = NT_STATUS_IO_DEVICE_ERROR;
3111 } else {
3112 error = map_nt_error_from_unix_common(errno);
3113 }
3114
3115 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
3116 "ret[%u] errno[%d] => %s\n",
3117 (unsigned)unread_bytes,
3118 (unsigned)ret, errno, nt_errstr(error)));
3119 return error;
3120 }
3121 }
3122
3123 body.data = outhdr + SMB2_HDR_BODY;
3124 body.length = 8;
3125 SSVAL(body.data, 0, 9);
3126
3127 if (info) {
3128 SIVAL(body.data, 0x04, info->length);
3129 } else {
3130 /* Allocated size of req->out.vector[i].iov_base
3131 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
3132 * 1 byte without having to do an alloc.
3133 */
3134 info = &_dyn;
3135 info->data = ((uint8_t *)outhdr) +
3136 OUTVEC_ALLOC_SIZE - 1;
3137 info->length = 1;
3138 SCVAL(info->data, 0, 0);
3139 }
3140
3141 /*
3142 * Note: Even if there is an error, continue to process the request.
3143 * per MS-SMB2.
3144 */
3145
3146 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
3147}
3148
3149
3150struct smbd_smb2_send_break_state {
3151 struct smbd_smb2_send_queue queue_entry;
3152 uint8_t nbt_hdr[NBT_HDR_SIZE];
3153 uint8_t tf[SMB2_TF_HDR_SIZE];
3154 uint8_t hdr[SMB2_HDR_BODY];
3155 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
3156 uint8_t body[1];
3157};
3158
3159static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
3160 struct smbXsrv_session *session,
3161 struct smbXsrv_tcon *tcon,
3162 const uint8_t *body,
3163 size_t body_len)
3164{
3165 struct smbd_smb2_send_break_state *state;
3166 bool do_encryption = false;
3167 uint64_t session_wire_id = 0;
3168 uint64_t nonce_high = 0;
3169 uint64_t nonce_low = 0;
3170 NTSTATUS status;
3171 size_t statelen;
3172 bool ok;
3173
3174 if (session != NULL) {
3175 session_wire_id = session->global->session_wire_id;
3176 do_encryption = session->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
3177 if (tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
3178 do_encryption = true;
3179 }
3180 }
3181
3182 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
3183 body_len;
3184
3185 state = talloc_zero_size(xconn, statelen);
3186 if (state == NULL) {
3187 return NT_STATUS_NO_MEMORY;
3188 }
3189 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
3190
3191 if (do_encryption) {
3192 status = smb2_get_new_nonce(session,
3193 &nonce_high,
3194 &nonce_low);
3195 if (!NT_STATUS_IS_OK(status)) {
3196 return status;
3197 }
3198 }
3199
3200 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
3201 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
3202 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
3203 SBVAL(state->tf, SMB2_TF_SESSION_ID, session_wire_id);
3204
3205 SIVAL(state->hdr, 0, SMB2_MAGIC);
3206 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
3207 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
3208 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
3209 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
3210 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
3211 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
3212 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
3213 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
3214 SIVAL(state->hdr, SMB2_HDR_PID, 0);
3215 SIVAL(state->hdr, SMB2_HDR_TID, 0);
3216 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
3217 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
3218
3219 state->vector[0] = (struct iovec) {
3220 .iov_base = state->nbt_hdr,
3221 .iov_len = sizeof(state->nbt_hdr)
3222 };
3223
3224 if (do_encryption) {
3225 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3226 .iov_base = state->tf,
3227 .iov_len = sizeof(state->tf)
3228 };
3229 } else {
3230 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3231 .iov_base = NULL,
3232 .iov_len = 0
3233 };
3234 }
3235
3236 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
3237 .iov_base = state->hdr,
3238 .iov_len = sizeof(state->hdr)
3239 };
3240
3241 memcpy(state->body, body, body_len);
3242
3243 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
3244 .iov_base = state->body,
3245 .iov_len = body_len /* no sizeof(state->body) .. :-) */
3246 };
3247
3248 /*
3249 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
3250 */
3251
3252 ok = smb2_setup_nbt_length(state->vector,
3253 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
3254 if (!ok) {
3255 return NT_STATUS_INVALID_PARAMETER_MIX;
3256 }
3257
3258 if (do_encryption) {
3259 DATA_BLOB encryption_key = session->global->encryption_key;
3260
3261 status = smb2_signing_encrypt_pdu(encryption_key,
3262 xconn->smb2.server.cipher,
3263 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
3264 SMBD_SMB2_NUM_IOV_PER_REQ);
3265 if (!NT_STATUS_IS_OK(status)) {
3266 return status;
3267 }
3268 }
3269
3270 state->queue_entry.mem_ctx = state;
3271 state->queue_entry.vector = state->vector;
3272 state->queue_entry.count = ARRAY_SIZE(state->vector);
3273 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
3274 xconn->smb2.send_queue_len++;
3275
3276 status = smbd_smb2_flush_send_queue(xconn);
3277 if (!NT_STATUS_IS_OK(status)) {
3278 return status;
3279 }
3280
3281 return NT_STATUS_OK;
3282}
3283
3284NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_connection *xconn,
3285 struct smbXsrv_session *session,
3286 struct smbXsrv_tcon *tcon,
3287 struct smbXsrv_open *op,
3288 uint8_t oplock_level)
3289{
3290 uint8_t body[0x18];
3291
3292 SSVAL(body, 0x00, sizeof(body));
3293 SCVAL(body, 0x02, oplock_level);
3294 SCVAL(body, 0x03, 0); /* reserved */
3295 SIVAL(body, 0x04, 0); /* reserved */
3296 SBVAL(body, 0x08, op->global->open_persistent_id);
3297 SBVAL(body, 0x10, op->global->open_volatile_id);
3298
3299 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3300}
3301
3302NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_connection *xconn,
3303 uint16_t new_epoch,
3304 uint32_t lease_flags,
3305 struct smb2_lease_key *lease_key,
3306 uint32_t current_lease_state,
3307 uint32_t new_lease_state)
3308{
3309 uint8_t body[0x2c];
3310
3311 SSVAL(body, 0x00, sizeof(body));
3312 SSVAL(body, 0x02, new_epoch);
3313 SIVAL(body, 0x04, lease_flags);
3314 SBVAL(body, 0x08, lease_key->data[0]);
3315 SBVAL(body, 0x10, lease_key->data[1]);
3316 SIVAL(body, 0x18, current_lease_state);
3317 SIVAL(body, 0x1c, new_lease_state);
3318 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
3319 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
3320 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
3321
3322 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3323}
3324
3325static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
3326{
3327 NTSTATUS status;
3328 uint32_t flags;
3329 uint64_t file_id_persistent;
3330 uint64_t file_id_volatile;
3331 struct smbXsrv_open *op = NULL;
3332 struct files_struct *fsp = NULL;
3333 const uint8_t *body = NULL;
3334
3335 /*
3336 * This is only called with a pktbuf
3337 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
3338 * bytes
3339 */
3340
3341 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
3342 /* Transform header. Cannot recvfile. */
3343 return false;
3344 }
3345 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
3346 /* Not SMB2. Normal error path will cope. */
3347 return false;
3348 }
3349 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
3350 /* Not SMB2. Normal error path will cope. */
3351 return false;
3352 }
3353 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
3354 /* Needs to be a WRITE. */
3355 return false;
3356 }
3357 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
3358 /* Chained. Cannot recvfile. */
3359 return false;
3360 }
3361 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
3362 if (flags & SMB2_HDR_FLAG_CHAINED) {
3363 /* Chained. Cannot recvfile. */
3364 return false;
3365 }
3366 if (flags & SMB2_HDR_FLAG_SIGNED) {
3367 /* Signed. Cannot recvfile. */
3368 return false;
3369 }
3370
3371 body = &state->pktbuf[SMB2_HDR_BODY];
3372
3373 file_id_persistent = BVAL(body, 0x10);
3374 file_id_volatile = BVAL(body, 0x18);
3375
3376 status = smb2srv_open_lookup(state->req->xconn,
3377 file_id_persistent,
3378 file_id_volatile,
3379 0, /* now */
3380 &op);
3381 if (!NT_STATUS_IS_OK(status)) {
3382 return false;
3383 }
3384
3385 fsp = op->compat;
3386 if (fsp == NULL) {
3387 return false;
3388 }
3389 if (fsp->conn == NULL) {
3390 return false;
3391 }
3392
3393 if (IS_IPC(fsp->conn)) {
3394 return false;
3395 }
3396 if (IS_PRINT(fsp->conn)) {
3397 return false;
3398 }
3399
3400 DEBUG(10,("Doing recvfile write len = %u\n",
3401 (unsigned int)(state->pktfull - state->pktlen)));
3402
3403 return true;
3404}
3405
3406static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
3407{
3408 struct smbd_server_connection *sconn = xconn->client->sconn;
3409 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3410 size_t max_send_queue_len;
3411 size_t cur_send_queue_len;
3412
3413 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3414 /*
3415 * we're not supposed to do any io
3416 */
3417 return NT_STATUS_OK;
3418 }
3419
3420 if (state->req != NULL) {
3421 /*
3422 * if there is already a tstream_readv_pdu
3423 * pending, we are done.
3424 */
3425 return NT_STATUS_OK;
3426 }
3427
3428 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
3429 cur_send_queue_len = xconn->smb2.send_queue_len;
3430
3431 if (cur_send_queue_len > max_send_queue_len) {
3432 /*
3433 * if we have a lot of requests to send,
3434 * we wait until they are on the wire until we
3435 * ask for the next request.
3436 */
3437 return NT_STATUS_OK;
3438 }
3439
3440 /* ask for the next request */
3441 ZERO_STRUCTP(state);
3442 state->req = smbd_smb2_request_allocate(xconn);
3443 if (state->req == NULL) {
3444 return NT_STATUS_NO_MEMORY;
3445 }
3446 state->req->sconn = sconn;
3447 state->req->xconn = xconn;
3448 state->min_recv_size = lp_min_receive_file_size();
3449
3450 TEVENT_FD_READABLE(xconn->transport.fde);
3451
3452 return NT_STATUS_OK;
3453}
3454
3455void smbd_smb2_process_negprot(struct smbXsrv_connection *xconn,
3456 uint64_t expected_seq_low,
3457 const uint8_t *inpdu, size_t size)
3458{
3459 struct smbd_server_connection *sconn = xconn->client->sconn;
3460 NTSTATUS status;
3461 struct smbd_smb2_request *req = NULL;
3462
3463 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3464 (unsigned int)size));
3465
3466 status = smbd_initialize_smb2(xconn, expected_seq_low);
3467 if (!NT_STATUS_IS_OK(status)) {
3468 smbd_server_connection_terminate(xconn, nt_errstr(status));
3469 return;
3470 }
3471
3472 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
3473 if (!NT_STATUS_IS_OK(status)) {
3474 smbd_server_connection_terminate(xconn, nt_errstr(status));
3475 return;
3476 }
3477
3478 status = smbd_smb2_request_validate(req);
3479 if (!NT_STATUS_IS_OK(status)) {
3480 smbd_server_connection_terminate(xconn, nt_errstr(status));
3481 return;
3482 }
3483
3484 status = smbd_smb2_request_setup_out(req);
3485 if (!NT_STATUS_IS_OK(status)) {
3486 smbd_server_connection_terminate(xconn, nt_errstr(status));
3487 return;
3488 }
3489
3490#ifdef WITH_PROFILE
3491 /*
3492 * this was already counted at the SMB1 layer =>
3493 * smbd_smb2_request_dispatch() should not count it twice.
3494 */
3495 if (profile_p->values.request_stats.count > 0) {
3496 profile_p->values.request_stats.count--;
3497 }
3498#endif
3499 status = smbd_smb2_request_dispatch(req);
3500 if (!NT_STATUS_IS_OK(status)) {
3501 smbd_server_connection_terminate(xconn, nt_errstr(status));
3502 return;
3503 }
3504
3505 status = smbd_smb2_request_next_incoming(xconn);
3506 if (!NT_STATUS_IS_OK(status)) {
3507 smbd_server_connection_terminate(xconn, nt_errstr(status));
3508 return;
3509 }
3510
3511 sconn->num_requests++;
3512}
3513
3514static int socket_error_from_errno(int ret,
3515 int sys_errno,
3516 bool *retry)
3517{
3518 *retry = false;
3519
3520 if (ret >= 0) {
3521 return 0;
3522 }
3523
3524 if (ret != -1) {
3525 return EIO;
3526 }
3527
3528 if (sys_errno == 0) {
3529 return EIO;
3530 }
3531
3532 if (sys_errno == EINTR) {
3533 *retry = true;
3534 return sys_errno;
3535 }
3536
3537 if (sys_errno == EINPROGRESS) {
3538 *retry = true;
3539 return sys_errno;
3540 }
3541
3542 if (sys_errno == EAGAIN) {
3543 *retry = true;
3544 return sys_errno;
3545 }
3546
3547 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3548 if (sys_errno == ENOMEM) {
3549 *retry = true;
3550 return sys_errno;
3551 }
3552
3553#ifdef EWOULDBLOCK
3554#if EWOULDBLOCK != EAGAIN
3555 if (sys_errno == EWOULDBLOCK) {
3556 *retry = true;
3557 return sys_errno;
3558 }
3559#endif
3560#endif
3561
3562 return sys_errno;
3563}
3564
3565static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3566{
3567 int ret;
3568 int err;
3569 bool retry;
3570
3571 if (xconn->smb2.send_queue == NULL) {
3572 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3573 return NT_STATUS_OK;
3574 }
3575
3576 while (xconn->smb2.send_queue != NULL) {
3577 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3578 bool ok;
3579
3580 if (e->sendfile_header != NULL) {
3581 NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
3582 size_t size = 0;
3583 size_t i = 0;
3584 uint8_t *buf;
3585
3586 for (i=0; i < e->count; i++) {
3587 size += e->vector[i].iov_len;
3588 }
3589
3590 if (size <= e->sendfile_header->length) {
3591 buf = e->sendfile_header->data;
3592 } else {
3593 buf = talloc_array(e->mem_ctx, uint8_t, size);
3594 if (buf == NULL) {
3595 return NT_STATUS_NO_MEMORY;
3596 }
3597 }
3598
3599 size = 0;
3600 for (i=0; i < e->count; i++) {
3601 memcpy(buf+size,
3602 e->vector[i].iov_base,
3603 e->vector[i].iov_len);
3604 size += e->vector[i].iov_len;
3605 }
3606
3607 e->sendfile_header->data = buf;
3608 e->sendfile_header->length = size;
3609 e->sendfile_status = &status;
3610 e->count = 0;
3611
3612 xconn->smb2.send_queue_len--;
3613 DLIST_REMOVE(xconn->smb2.send_queue, e);
3614 /*
3615 * This triggers the sendfile path via
3616 * the destructor.
3617 */
3618 talloc_free(e->mem_ctx);
3619
3620 if (!NT_STATUS_IS_OK(status)) {
3621 return status;
3622 }
3623 continue;
3624 }
3625
3626 ret = writev(xconn->transport.sock, e->vector, e->count);
3627 if (ret == 0) {
3628 /* propagate end of file */
3629 return NT_STATUS_INTERNAL_ERROR;
3630 }
3631 err = socket_error_from_errno(ret, errno, &retry);
3632 if (retry) {
3633 /* retry later */
3634 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3635 return NT_STATUS_OK;
3636 }
3637 if (err != 0) {
3638 return map_nt_error_from_unix_common(err);
3639 }
3640
3641 ok = iov_advance(&e->vector, &e->count, ret);
3642 if (!ok) {
3643 return NT_STATUS_INTERNAL_ERROR;
3644 }
3645
3646 if (e->count > 0) {
3647 /* we have more to write */
3648 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3649 return NT_STATUS_OK;
3650 }
3651
3652 xconn->smb2.send_queue_len--;
3653 DLIST_REMOVE(xconn->smb2.send_queue, e);
3654 talloc_free(e->mem_ctx);
3655 }
3656
3657 return NT_STATUS_OK;
3658}
3659
3660static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3661 uint16_t fde_flags)
3662{
3663 struct smbd_server_connection *sconn = xconn->client->sconn;
3664 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3665 struct smbd_smb2_request *req = NULL;
3666 size_t min_recvfile_size = UINT32_MAX;
3667 int ret;
3668 int err;
3669 bool retry;
3670 NTSTATUS status;
3671 NTTIME now;
3672
3673 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3674 /*
3675 * we're not supposed to do any io
3676 */
3677 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3678 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3679 return NT_STATUS_OK;
3680 }
3681
3682 if (fde_flags & TEVENT_FD_WRITE) {
3683 status = smbd_smb2_flush_send_queue(xconn);
3684 if (!NT_STATUS_IS_OK(status)) {
3685 return status;
3686 }
3687 }
3688
3689 if (!(fde_flags & TEVENT_FD_READ)) {
3690 return NT_STATUS_OK;
3691 }
3692
3693 if (state->req == NULL) {
3694 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3695 return NT_STATUS_OK;
3696 }
3697
3698again:
3699 if (!state->hdr.done) {
3700 state->hdr.done = true;
3701
3702 state->vector.iov_base = (void *)state->hdr.nbt;
3703 state->vector.iov_len = NBT_HDR_SIZE;
3704 }
3705
3706 ret = readv(xconn->transport.sock, &state->vector, 1);
3707 if (ret == 0) {
3708 /* propagate end of file */
3709 return NT_STATUS_END_OF_FILE;
3710 }
3711 err = socket_error_from_errno(ret, errno, &retry);
3712 if (retry) {
3713 /* retry later */
3714 TEVENT_FD_READABLE(xconn->transport.fde);
3715 return NT_STATUS_OK;
3716 }
3717 if (err != 0) {
3718 return map_nt_error_from_unix_common(err);
3719 }
3720
3721 if (ret < state->vector.iov_len) {
3722 uint8_t *base;
3723 base = (uint8_t *)state->vector.iov_base;
3724 base += ret;
3725 state->vector.iov_base = (void *)base;
3726 state->vector.iov_len -= ret;
3727 /* we have more to read */
3728 TEVENT_FD_READABLE(xconn->transport.fde);
3729 return NT_STATUS_OK;
3730 }
3731
3732 if (state->pktlen > 0) {
3733 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3734 /*
3735 * Not a possible receivefile write.
3736 * Read the rest of the data.
3737 */
3738 state->doing_receivefile = false;
3739
3740 state->pktbuf = talloc_realloc(state->req,
3741 state->pktbuf,
3742 uint8_t,
3743 state->pktfull);
3744 if (state->pktbuf == NULL) {
3745 return NT_STATUS_NO_MEMORY;
3746 }
3747
3748 state->vector.iov_base = (void *)(state->pktbuf +
3749 state->pktlen);
3750 state->vector.iov_len = (state->pktfull -
3751 state->pktlen);
3752
3753 state->pktlen = state->pktfull;
3754 goto again;
3755 }
3756
3757 /*
3758 * Either this is a receivefile write so we've
3759 * done a short read, or if not we have all the data.
3760 */
3761 goto got_full;
3762 }
3763
3764 /*
3765 * Now we analyze the NBT header
3766 */
3767 if (state->hdr.nbt[0] != 0x00) {
3768 state->min_recv_size = 0;
3769 }
3770 state->pktfull = smb2_len(state->hdr.nbt);
3771 if (state->pktfull == 0) {
3772 goto got_full;
3773 }
3774
3775 if (state->min_recv_size != 0) {
3776 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3777 min_recvfile_size += state->min_recv_size;
3778 }
3779
3780 if (state->pktfull > min_recvfile_size) {
3781 /*
3782 * Might be a receivefile write. Read the SMB2 HEADER +
3783 * SMB2_WRITE header first. Set 'doing_receivefile'
3784 * as we're *attempting* receivefile write. If this
3785 * turns out not to be a SMB2_WRITE request or otherwise
3786 * not suitable then we'll just read the rest of the data
3787 * the next time this function is called.
3788 */
3789 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3790 state->doing_receivefile = true;
3791 } else {
3792 state->pktlen = state->pktfull;
3793 }
3794
3795 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3796 if (state->pktbuf == NULL) {
3797 return NT_STATUS_NO_MEMORY;
3798 }
3799
3800 state->vector.iov_base = (void *)state->pktbuf;
3801 state->vector.iov_len = state->pktlen;
3802
3803 goto again;
3804
3805got_full:
3806
3807 if (state->hdr.nbt[0] != 0x00) {
3808 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3809 state->hdr.nbt[0]));
3810
3811 req = state->req;
3812 ZERO_STRUCTP(state);
3813 state->req = req;
3814 state->min_recv_size = lp_min_receive_file_size();
3815 req = NULL;
3816 goto again;
3817 }
3818
3819 req = state->req;
3820 state->req = NULL;
3821
3822 req->request_time = timeval_current();
3823 now = timeval_to_nttime(&req->request_time);
3824
3825 status = smbd_smb2_inbuf_parse_compound(xconn,
3826 now,
3827 state->pktbuf,
3828 state->pktlen,
3829 req,
3830 &req->in.vector,
3831 &req->in.vector_count);
3832 if (!NT_STATUS_IS_OK(status)) {
3833 return status;
3834 }
3835
3836 if (state->doing_receivefile) {
3837 req->smb1req = talloc_zero(req, struct smb_request);
3838 if (req->smb1req == NULL) {
3839 return NT_STATUS_NO_MEMORY;
3840 }
3841 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3842 }
3843
3844 ZERO_STRUCTP(state);
3845
3846 req->current_idx = 1;
3847
3848 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3849 req->current_idx, req->in.vector_count));
3850
3851 status = smbd_smb2_request_validate(req);
3852 if (!NT_STATUS_IS_OK(status)) {
3853 return status;
3854 }
3855
3856 status = smbd_smb2_request_setup_out(req);
3857 if (!NT_STATUS_IS_OK(status)) {
3858 return status;
3859 }
3860
3861 status = smbd_smb2_request_dispatch(req);
3862 if (!NT_STATUS_IS_OK(status)) {
3863 return status;
3864 }
3865
3866 sconn->num_requests++;
3867
3868 /* The timeout_processing function isn't run nearly
3869 often enough to implement 'max log size' without
3870 overrunning the size of the file by many megabytes.
3871 This is especially true if we are running at debug
3872 level 10. Checking every 50 SMB2s is a nice
3873 tradeoff of performance vs log file size overrun. */
3874
3875 if ((sconn->num_requests % 50) == 0 &&
3876 need_to_check_log_size()) {
3877 change_to_root_user();
3878 check_log_size();
3879 }
3880
3881 status = smbd_smb2_request_next_incoming(xconn);
3882 if (!NT_STATUS_IS_OK(status)) {
3883 return status;
3884 }
3885
3886 return NT_STATUS_OK;
3887}
3888
3889static void smbd_smb2_connection_handler(struct tevent_context *ev,
3890 struct tevent_fd *fde,
3891 uint16_t flags,
3892 void *private_data)
3893{
3894 struct smbXsrv_connection *xconn =
3895 talloc_get_type_abort(private_data,
3896 struct smbXsrv_connection);
3897 NTSTATUS status;
3898
3899 status = smbd_smb2_io_handler(xconn, flags);
3900 if (!NT_STATUS_IS_OK(status)) {
3901 smbd_server_connection_terminate(xconn, nt_errstr(status));
3902 return;
3903 }
3904}
Note: See TracBrowser for help on using the repository browser.