ldb: add tests for ldb_wildcard_compare
[Samba.git] / source3 / smbd / smb2_server.c
blobbd0eab00606634231d689d5393b0ff665c7b357c
1 /*
2 Unix SMB/CIFS implementation.
3 Core SMB2 server
5 Copyright (C) Stefan Metzmacher 2009
6 Copyright (C) Jeremy Allison 2010
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.
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.
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/>.
22 #include "includes.h"
23 #include "system/network.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "../libcli/smb/smb_common.h"
27 #include "../lib/tsocket/tsocket.h"
28 #include "../lib/util/tevent_ntstatus.h"
29 #include "smbprofile.h"
30 #include "../lib/util/bitmap.h"
31 #include "../librpc/gen_ndr/krb5pac.h"
32 #include "lib/util/iov_buf.h"
33 #include "auth.h"
34 #include "libcli/smb/smbXcli_base.h"
36 #if defined(LINUX)
37 /* SIOCOUTQ TIOCOUTQ are the same */
38 #define __IOCTL_SEND_QUEUE_SIZE_OPCODE TIOCOUTQ
39 #define __HAVE_TCP_INFO_RTO 1
40 #define __ALLOW_MULTI_CHANNEL_SUPPORT 1
41 #elif defined(FREEBSD)
42 #define __IOCTL_SEND_QUEUE_SIZE_OPCODE FIONWRITE
43 #define __HAVE_TCP_INFO_RTO 1
44 #define __ALLOW_MULTI_CHANNEL_SUPPORT 1
45 #endif
47 #include "lib/crypto/gnutls_helpers.h"
48 #include <gnutls/gnutls.h>
49 #include <gnutls/crypto.h>
51 #undef DBGC_CLASS
52 #define DBGC_CLASS DBGC_SMB2
54 static void smbd_smb2_connection_handler(struct tevent_context *ev,
55 struct tevent_fd *fde,
56 uint16_t flags,
57 void *private_data);
58 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn);
60 static const struct smbd_smb2_dispatch_table {
61 uint16_t opcode;
62 const char *name;
63 bool need_session;
64 bool need_tcon;
65 bool as_root;
66 uint16_t fileid_ofs;
67 bool allow_invalid_fileid;
68 bool modify;
69 } smbd_smb2_table[] = {
70 #define _OP(o) .opcode = o, .name = #o
72 _OP(SMB2_OP_NEGPROT),
73 .as_root = true,
74 },{
75 _OP(SMB2_OP_SESSSETUP),
76 .as_root = true,
77 },{
78 _OP(SMB2_OP_LOGOFF),
79 .need_session = true,
80 .as_root = true,
81 },{
82 _OP(SMB2_OP_TCON),
83 .need_session = true,
85 * This call needs to be run as root.
87 * smbd_smb2_request_process_tcon()
88 * calls make_connection_snum(), which will call
89 * change_to_user(), when needed.
91 .as_root = true,
92 },{
93 _OP(SMB2_OP_TDIS),
94 .need_session = true,
95 .need_tcon = true,
96 .as_root = true,
97 },{
98 _OP(SMB2_OP_CREATE),
99 .need_session = true,
100 .need_tcon = true,
102 _OP(SMB2_OP_CLOSE),
103 .need_session = true,
104 .need_tcon = true,
105 .fileid_ofs = 0x08,
107 _OP(SMB2_OP_FLUSH),
108 .need_session = true,
109 .need_tcon = true,
110 .fileid_ofs = 0x08,
112 _OP(SMB2_OP_READ),
113 .need_session = true,
114 .need_tcon = true,
115 .fileid_ofs = 0x10,
117 _OP(SMB2_OP_WRITE),
118 .need_session = true,
119 .need_tcon = true,
120 .fileid_ofs = 0x10,
121 .modify = true,
123 _OP(SMB2_OP_LOCK),
124 .need_session = true,
125 .need_tcon = true,
126 .fileid_ofs = 0x08,
128 _OP(SMB2_OP_IOCTL),
129 .need_session = true,
130 .need_tcon = true,
131 .fileid_ofs = 0x08,
132 .allow_invalid_fileid = true,
133 .modify = true,
135 _OP(SMB2_OP_CANCEL),
136 .as_root = true,
138 _OP(SMB2_OP_KEEPALIVE),
139 .as_root = true,
141 _OP(SMB2_OP_QUERY_DIRECTORY),
142 .need_session = true,
143 .need_tcon = true,
144 .fileid_ofs = 0x08,
146 _OP(SMB2_OP_NOTIFY),
147 .need_session = true,
148 .need_tcon = true,
149 .fileid_ofs = 0x08,
151 _OP(SMB2_OP_GETINFO),
152 .need_session = true,
153 .need_tcon = true,
154 .fileid_ofs = 0x18,
156 _OP(SMB2_OP_SETINFO),
157 .need_session = true,
158 .need_tcon = true,
159 .fileid_ofs = 0x10,
160 .modify = true,
162 _OP(SMB2_OP_BREAK),
163 .need_session = true,
164 .need_tcon = true,
166 * we do not set
167 * .fileid_ofs here
168 * as LEASE breaks does not
169 * have a file id
174 const char *smb2_opcode_name(uint16_t opcode)
176 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
177 return "Bad SMB2 opcode";
179 return smbd_smb2_table[opcode].name;
182 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
184 const struct smbd_smb2_dispatch_table *ret = NULL;
186 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
187 return NULL;
190 ret = &smbd_smb2_table[opcode];
192 SMB_ASSERT(ret->opcode == opcode);
194 return ret;
197 static void print_req_vectors(const struct smbd_smb2_request *req)
199 int i;
201 for (i = 0; i < req->in.vector_count; i++) {
202 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
203 (unsigned int)i,
204 (unsigned int)req->in.vector[i].iov_len);
206 for (i = 0; i < req->out.vector_count; i++) {
207 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
208 (unsigned int)i,
209 (unsigned int)req->out.vector[i].iov_len);
213 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
215 if (size < (4 + SMB2_HDR_BODY)) {
216 return false;
219 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
220 return false;
223 return true;
226 bool smbd_smb2_is_compound(const struct smbd_smb2_request *req)
228 return req->in.vector_count >= (2*SMBD_SMB2_NUM_IOV_PER_REQ);
231 static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn,
232 uint64_t expected_seq_low)
234 int rc;
236 xconn->smb2.credits.seq_low = expected_seq_low;
237 xconn->smb2.credits.seq_range = 1;
238 xconn->smb2.credits.granted = 1;
239 xconn->smb2.credits.max = lp_smb2_max_credits();
240 xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
241 xconn->smb2.credits.max);
242 if (xconn->smb2.credits.bitmap == NULL) {
243 return NT_STATUS_NO_MEMORY;
246 tevent_fd_set_close_fn(xconn->transport.fde, NULL);
247 TALLOC_FREE(xconn->transport.fde);
249 xconn->transport.fde = tevent_add_fd(
250 xconn->client->raw_ev_ctx,
251 xconn,
252 xconn->transport.sock,
253 TEVENT_FD_READ,
254 smbd_smb2_connection_handler,
255 xconn);
256 if (xconn->transport.fde == NULL) {
257 close(xconn->transport.sock);
258 xconn->transport.sock = -1;
259 return NT_STATUS_NO_MEMORY;
261 tevent_fd_set_auto_close(xconn->transport.fde);
263 /* Ensure child is set to non-blocking mode */
264 rc = set_blocking(xconn->transport.sock, false);
265 if (rc < 0) {
266 return NT_STATUS_INTERNAL_ERROR;
269 return NT_STATUS_OK;
272 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
273 #define _smb2_setlen(_buf,len) do { \
274 uint8_t *buf = (uint8_t *)_buf; \
275 buf[0] = 0; \
276 buf[1] = ((len)&0xFF0000)>>16; \
277 buf[2] = ((len)&0xFF00)>>8; \
278 buf[3] = (len)&0xFF; \
279 } while (0)
281 static bool smb2_setup_nbt_length(struct iovec *vector, int count)
283 ssize_t len;
285 if (count == 0) {
286 return false;
289 len = iov_buflen(vector+1, count-1);
291 if ((len == -1) || (len > 0xFFFFFF)) {
292 return false;
295 _smb2_setlen(vector[0].iov_base, len);
296 return true;
299 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
301 if (req->first_key.length > 0) {
302 data_blob_clear_free(&req->first_key);
304 if (req->last_key.length > 0) {
305 data_blob_clear_free(&req->last_key);
307 return 0;
310 void smb2_request_set_async_internal(struct smbd_smb2_request *req,
311 bool async_internal)
313 req->async_internal = async_internal;
316 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
318 TALLOC_CTX *mem_pool;
319 struct smbd_smb2_request *req;
321 #if 0
322 /* Enable this to find subtle valgrind errors. */
323 mem_pool = talloc_init("smbd_smb2_request_allocate");
324 #else
325 mem_pool = talloc_tos();
326 #endif
327 if (mem_pool == NULL) {
328 return NULL;
331 req = talloc_zero(mem_pool, struct smbd_smb2_request);
332 if (req == NULL) {
333 talloc_free(mem_pool);
334 return NULL;
336 talloc_reparent(mem_pool, mem_ctx, req);
337 #if 0
338 TALLOC_FREE(mem_pool);
339 #endif
341 req->last_session_id = UINT64_MAX;
342 req->last_tid = UINT32_MAX;
344 talloc_set_destructor(req, smbd_smb2_request_destructor);
346 return req;
349 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
350 NTTIME now,
351 uint8_t *buf,
352 size_t buflen,
353 struct smbd_smb2_request *req,
354 struct iovec **piov,
355 int *pnum_iov)
357 TALLOC_CTX *mem_ctx = req;
358 struct iovec *iov;
359 int num_iov = 1;
360 size_t taken = 0;
361 uint8_t *first_hdr = buf;
362 size_t verified_buflen = 0;
363 uint8_t *tf = NULL;
364 size_t tf_len = 0;
367 * Note: index '0' is reserved for the transport protocol
369 iov = req->in._vector;
371 while (taken < buflen) {
372 size_t len = buflen - taken;
373 uint8_t *hdr = first_hdr + taken;
374 struct iovec *cur;
375 size_t full_size;
376 size_t next_command_ofs;
377 uint16_t body_size;
378 uint8_t *body = NULL;
379 uint32_t dyn_size;
380 uint8_t *dyn = NULL;
381 struct iovec *iov_alloc = NULL;
383 if (iov != req->in._vector) {
384 iov_alloc = iov;
387 if (verified_buflen > taken) {
388 len = verified_buflen - taken;
389 } else {
390 tf = NULL;
391 tf_len = 0;
394 if (len < 4) {
395 DEBUG(10, ("%d bytes left, expected at least %d\n",
396 (int)len, 4));
397 goto inval;
399 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
400 struct smbXsrv_session *s = NULL;
401 uint64_t uid;
402 struct iovec tf_iov[2];
403 NTSTATUS status;
404 size_t enc_len;
406 if (xconn->protocol < PROTOCOL_SMB2_24) {
407 DEBUG(10, ("Got SMB2_TRANSFORM header, "
408 "but dialect[0x%04X] is used\n",
409 xconn->smb2.server.dialect));
410 goto inval;
413 if (xconn->smb2.server.cipher == 0) {
414 DEBUG(10, ("Got SMB2_TRANSFORM header, "
415 "but not negotiated "
416 "client[0x%08X] server[0x%08X]\n",
417 xconn->smb2.client.capabilities,
418 xconn->smb2.server.capabilities));
419 goto inval;
422 if (len < SMB2_TF_HDR_SIZE) {
423 DEBUG(1, ("%d bytes left, expected at least %d\n",
424 (int)len, SMB2_TF_HDR_SIZE));
425 goto inval;
427 tf = hdr;
428 tf_len = SMB2_TF_HDR_SIZE;
429 taken += tf_len;
431 hdr = first_hdr + taken;
432 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
433 uid = BVAL(tf, SMB2_TF_SESSION_ID);
435 if (len < SMB2_TF_HDR_SIZE + enc_len) {
436 DEBUG(1, ("%d bytes left, expected at least %d\n",
437 (int)len,
438 (int)(SMB2_TF_HDR_SIZE + enc_len)));
439 goto inval;
442 status = smb2srv_session_lookup_conn(xconn, uid, now,
443 &s);
444 if (s == NULL) {
445 DEBUG(1, ("invalid session[%llu] in "
446 "SMB2_TRANSFORM header\n",
447 (unsigned long long)uid));
448 TALLOC_FREE(iov_alloc);
449 return NT_STATUS_USER_SESSION_DELETED;
452 tf_iov[0].iov_base = (void *)tf;
453 tf_iov[0].iov_len = tf_len;
454 tf_iov[1].iov_base = (void *)hdr;
455 tf_iov[1].iov_len = enc_len;
457 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
458 xconn->smb2.server.cipher,
459 tf_iov, 2);
460 if (!NT_STATUS_IS_OK(status)) {
461 TALLOC_FREE(iov_alloc);
462 return status;
465 verified_buflen = taken + enc_len;
466 len = enc_len;
470 * We need the header plus the body length field
473 if (len < SMB2_HDR_BODY + 2) {
475 if ((len == 5) &&
476 (IVAL(hdr, 0) == SMB_SUICIDE_PACKET) &&
477 lp_parm_bool(-1, "smbd", "suicide mode", false)) {
478 uint8_t exitcode = CVAL(hdr, 4);
479 DBG_WARNING("SUICIDE: Exiting immediately "
480 "with code %"PRIu8"\n",
481 exitcode);
482 exit(exitcode);
485 DEBUG(10, ("%d bytes left, expected at least %d\n",
486 (int)len, SMB2_HDR_BODY));
487 goto inval;
489 if (IVAL(hdr, 0) != SMB2_MAGIC) {
490 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
491 IVAL(hdr, 0)));
492 goto inval;
494 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
495 DEBUG(10, ("Got HDR len %d, expected %d\n",
496 SVAL(hdr, 4), SMB2_HDR_BODY));
497 goto inval;
500 full_size = len;
501 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
502 body_size = SVAL(hdr, SMB2_HDR_BODY);
504 if (next_command_ofs != 0) {
505 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
506 goto inval;
508 if (next_command_ofs > full_size) {
509 goto inval;
511 full_size = next_command_ofs;
513 if (body_size < 2) {
514 goto inval;
516 body_size &= 0xfffe;
518 if (body_size > (full_size - SMB2_HDR_BODY)) {
520 * let the caller handle the error
522 body_size = full_size - SMB2_HDR_BODY;
524 body = hdr + SMB2_HDR_BODY;
525 dyn = body + body_size;
526 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
528 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
529 struct iovec *iov_tmp = NULL;
531 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
532 struct iovec,
533 num_iov +
534 SMBD_SMB2_NUM_IOV_PER_REQ);
535 if (iov_tmp == NULL) {
536 TALLOC_FREE(iov_alloc);
537 return NT_STATUS_NO_MEMORY;
540 if (iov_alloc == NULL) {
541 memcpy(iov_tmp,
542 req->in._vector,
543 sizeof(req->in._vector));
546 iov = iov_tmp;
548 cur = &iov[num_iov];
549 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
551 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
552 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
553 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
554 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
555 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
556 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
557 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
558 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
560 taken += full_size;
563 *piov = iov;
564 *pnum_iov = num_iov;
565 return NT_STATUS_OK;
567 inval:
568 if (iov != req->in._vector) {
569 TALLOC_FREE(iov);
571 return NT_STATUS_INVALID_PARAMETER;
574 static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
575 const uint8_t *_inpdu, size_t size,
576 struct smbd_smb2_request **_req)
578 struct smbd_server_connection *sconn = xconn->client->sconn;
579 struct smbd_smb2_request *req;
580 uint32_t protocol_version;
581 uint8_t *inpdu = NULL;
582 const uint8_t *inhdr = NULL;
583 uint16_t cmd;
584 uint32_t next_command_ofs;
585 NTSTATUS status;
586 NTTIME now;
588 if (size < (SMB2_HDR_BODY + 2)) {
589 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
590 return NT_STATUS_INVALID_PARAMETER;
593 inhdr = _inpdu;
595 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
596 if (protocol_version != SMB2_MAGIC) {
597 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
598 protocol_version));
599 return NT_STATUS_INVALID_PARAMETER;
602 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
603 if (cmd != SMB2_OP_NEGPROT) {
604 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
605 cmd));
606 return NT_STATUS_INVALID_PARAMETER;
609 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
610 if (next_command_ofs != 0) {
611 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
612 next_command_ofs));
613 return NT_STATUS_INVALID_PARAMETER;
616 req = smbd_smb2_request_allocate(xconn);
617 if (req == NULL) {
618 return NT_STATUS_NO_MEMORY;
620 req->sconn = sconn;
621 req->xconn = xconn;
623 inpdu = talloc_memdup(req, _inpdu, size);
624 if (inpdu == NULL) {
625 return NT_STATUS_NO_MEMORY;
628 req->request_time = timeval_current();
629 now = timeval_to_nttime(&req->request_time);
631 status = smbd_smb2_inbuf_parse_compound(xconn,
632 now,
633 inpdu,
634 size,
635 req, &req->in.vector,
636 &req->in.vector_count);
637 if (!NT_STATUS_IS_OK(status)) {
638 TALLOC_FREE(req);
639 return status;
642 req->current_idx = 1;
644 *_req = req;
645 return NT_STATUS_OK;
648 static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
649 uint64_t message_id, uint64_t seq_id)
651 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
652 unsigned int offset;
653 uint64_t seq_tmp;
655 seq_tmp = xconn->smb2.credits.seq_low;
656 if (seq_id < seq_tmp) {
657 DBGC_ERR(DBGC_SMB2_CREDITS,
658 "smb2_validate_sequence_number: bad message_id "
659 "%llu (sequence id %llu) "
660 "(granted = %u, low = %llu, range = %u)\n",
661 (unsigned long long)message_id,
662 (unsigned long long)seq_id,
663 (unsigned int)xconn->smb2.credits.granted,
664 (unsigned long long)xconn->smb2.credits.seq_low,
665 (unsigned int)xconn->smb2.credits.seq_range);
666 return false;
669 seq_tmp += xconn->smb2.credits.seq_range;
670 if (seq_id >= seq_tmp) {
671 DBGC_ERR(DBGC_SMB2_CREDITS,
672 "smb2_validate_sequence_number: bad message_id "
673 "%llu (sequence id %llu) "
674 "(granted = %u, low = %llu, range = %u)\n",
675 (unsigned long long)message_id,
676 (unsigned long long)seq_id,
677 (unsigned int)xconn->smb2.credits.granted,
678 (unsigned long long)xconn->smb2.credits.seq_low,
679 (unsigned int)xconn->smb2.credits.seq_range);
680 return false;
683 offset = seq_id % xconn->smb2.credits.max;
685 if (bitmap_query(credits_bm, offset)) {
686 DBGC_ERR(DBGC_SMB2_CREDITS,
687 "smb2_validate_sequence_number: duplicate message_id "
688 "%llu (sequence id %llu) "
689 "(granted = %u, low = %llu, range = %u) "
690 "(bm offset %u)\n",
691 (unsigned long long)message_id,
692 (unsigned long long)seq_id,
693 (unsigned int)xconn->smb2.credits.granted,
694 (unsigned long long)xconn->smb2.credits.seq_low,
695 (unsigned int)xconn->smb2.credits.seq_range,
696 offset);
697 return false;
700 /* Mark the message_ids as seen in the bitmap. */
701 bitmap_set(credits_bm, offset);
703 if (seq_id != xconn->smb2.credits.seq_low) {
704 return true;
708 * Move the window forward by all the message_id's
709 * already seen.
711 while (bitmap_query(credits_bm, offset)) {
712 DBGC_DEBUG(DBGC_SMB2_CREDITS,
713 "smb2_validate_sequence_number: clearing "
714 "id %llu (position %u) from bitmap\n",
715 (unsigned long long)(xconn->smb2.credits.seq_low),
716 offset);
717 bitmap_clear(credits_bm, offset);
719 xconn->smb2.credits.seq_low += 1;
720 xconn->smb2.credits.seq_range -= 1;
721 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
724 return true;
727 static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
728 const uint8_t *inhdr)
730 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
731 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
732 uint16_t credit_charge = 1;
733 uint64_t i;
735 if (opcode == SMB2_OP_CANCEL) {
736 /* SMB2_CANCEL requests by definition resend messageids. */
737 return true;
740 if (xconn->smb2.credits.multicredit) {
741 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
742 credit_charge = MAX(credit_charge, 1);
745 DEBUGC(11,
746 DBGC_SMB2_CREDITS,
747 ("smb2_validate_message_id: mid %llu (charge %llu), "
748 "credits_granted %llu, "
749 "seqnum low/range: %llu/%llu\n",
750 (unsigned long long) message_id,
751 (unsigned long long) credit_charge,
752 (unsigned long long) xconn->smb2.credits.granted,
753 (unsigned long long) xconn->smb2.credits.seq_low,
754 (unsigned long long) xconn->smb2.credits.seq_range));
756 if (xconn->smb2.credits.granted < credit_charge) {
757 DBGC_ERR(DBGC_SMB2_CREDITS,
758 "smb2_validate_message_id: client used more "
759 "credits than granted, mid %llu, charge %llu, "
760 "credits_granted %llu, "
761 "seqnum low/range: %llu/%llu\n",
762 (unsigned long long) message_id,
763 (unsigned long long) credit_charge,
764 (unsigned long long) xconn->smb2.credits.granted,
765 (unsigned long long) xconn->smb2.credits.seq_low,
766 (unsigned long long) xconn->smb2.credits.seq_range);
767 return false;
771 * now check the message ids
773 * for multi-credit requests we need to check all current mid plus
774 * the implicit mids caused by the credit charge
775 * e.g. current mid = 15, charge 5 => mark 15-19 as used
778 for (i = 0; i <= (credit_charge-1); i++) {
779 uint64_t id = message_id + i;
780 bool ok;
782 DEBUGC(11,
783 DBGC_SMB2_CREDITS,
784 ("Iterating mid %llu charge %u (sequence %llu)\n",
785 (unsigned long long)message_id,
786 credit_charge,
787 (unsigned long long)id));
789 ok = smb2_validate_sequence_number(xconn, message_id, id);
790 if (!ok) {
791 return false;
795 /* substract used credits */
796 xconn->smb2.credits.granted -= credit_charge;
798 return true;
801 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
803 int count;
804 int idx;
806 count = req->in.vector_count;
808 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
809 /* It's not a SMB2 request */
810 return NT_STATUS_INVALID_PARAMETER;
813 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
814 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
815 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
816 const uint8_t *inhdr = NULL;
818 if (hdr->iov_len != SMB2_HDR_BODY) {
819 return NT_STATUS_INVALID_PARAMETER;
822 if (body->iov_len < 2) {
823 return NT_STATUS_INVALID_PARAMETER;
826 inhdr = (const uint8_t *)hdr->iov_base;
828 /* Check the SMB2 header */
829 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
830 return NT_STATUS_INVALID_PARAMETER;
833 if (!smb2_validate_message_id(req->xconn, inhdr)) {
834 return NT_STATUS_INVALID_PARAMETER;
838 return NT_STATUS_OK;
841 static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
842 const struct iovec *in_vector,
843 struct iovec *out_vector)
845 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
846 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
847 uint16_t credit_charge = 1;
848 uint16_t credits_requested;
849 uint32_t out_flags;
850 uint16_t cmd;
851 NTSTATUS out_status;
852 uint16_t credits_granted = 0;
853 uint64_t credits_possible;
854 uint16_t current_max_credits;
857 * first we grant only 1/16th of the max range.
859 * Windows also starts with the 1/16th and then grants
860 * more later. I was only able to trigger higher
861 * values, when using a very high credit charge.
863 * TODO: scale up depending on load, free memory
864 * or other stuff.
865 * Maybe also on the relationship between number
866 * of requests and the used sequence number.
867 * Which means we would grant more credits
868 * for client which use multi credit requests.
870 * The above is what Windows Server < 2016 is doing,
871 * but new servers use all credits (8192 by default).
873 current_max_credits = xconn->smb2.credits.max;
874 current_max_credits = MAX(current_max_credits, 1);
876 if (xconn->smb2.credits.multicredit) {
877 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
878 credit_charge = MAX(credit_charge, 1);
881 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
882 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
883 credits_requested = MAX(credits_requested, 1);
884 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
885 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
887 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
889 if (xconn->smb2.credits.max < credit_charge) {
890 smbd_server_connection_terminate(xconn,
891 "client error: credit charge > max credits\n");
892 return;
895 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
897 * In case we already send an async interim
898 * response, we should not grant
899 * credits on the final response.
901 credits_granted = 0;
902 } else {
903 uint16_t additional_possible =
904 xconn->smb2.credits.max - credit_charge;
905 uint16_t additional_max = 0;
906 uint16_t additional_credits = credits_requested - 1;
908 switch (cmd) {
909 case SMB2_OP_NEGPROT:
910 break;
911 case SMB2_OP_SESSSETUP:
913 * Windows 2012 RC1 starts to grant
914 * additional credits
915 * with a successful session setup
917 if (NT_STATUS_IS_OK(out_status)) {
918 additional_max = xconn->smb2.credits.max;
920 break;
921 default:
923 * Windows Server < 2016 and older Samba versions
924 * used to only grant additional credits in
925 * chunks of 32 credits.
927 * But we match Windows Server 2016 and grant
928 * all credits as requested.
930 additional_max = xconn->smb2.credits.max;
931 break;
934 additional_max = MIN(additional_max, additional_possible);
935 additional_credits = MIN(additional_credits, additional_max);
937 credits_granted = credit_charge + additional_credits;
941 * sequence numbers should not wrap
943 * 1. calculate the possible credits until
944 * the sequence numbers start to wrap on 64-bit.
946 * 2. UINT64_MAX is used for Break Notifications.
948 * 2. truncate the possible credits to the maximum
949 * credits we want to grant to the client in total.
951 * 3. remove the range we'll already granted to the client
952 * this makes sure the client consumes the lowest sequence
953 * number, before we can grant additional credits.
955 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
956 if (credits_possible > 0) {
957 /* remove UINT64_MAX */
958 credits_possible -= 1;
960 credits_possible = MIN(credits_possible, current_max_credits);
961 credits_possible -= xconn->smb2.credits.seq_range;
963 credits_granted = MIN(credits_granted, credits_possible);
965 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
966 xconn->smb2.credits.granted += credits_granted;
967 xconn->smb2.credits.seq_range += credits_granted;
969 DBGC_DEBUG(DBGC_SMB2_CREDITS,
970 "smb2_set_operation_credit: requested %u, charge %u, "
971 "granted %u, current possible/max %u/%u, "
972 "total granted/max/low/range %u/%u/%llu/%u\n",
973 (unsigned int)credits_requested,
974 (unsigned int)credit_charge,
975 (unsigned int)credits_granted,
976 (unsigned int)credits_possible,
977 (unsigned int)current_max_credits,
978 (unsigned int)xconn->smb2.credits.granted,
979 (unsigned int)xconn->smb2.credits.max,
980 (unsigned long long)xconn->smb2.credits.seq_low,
981 (unsigned int)xconn->smb2.credits.seq_range);
984 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
985 struct smbd_smb2_request *outreq)
987 int count, idx;
988 uint16_t total_credits = 0;
990 count = outreq->out.vector_count;
992 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
993 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
994 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
995 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
997 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
999 /* To match Windows, count up what we
1000 just granted. */
1001 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
1002 /* Set to zero in all but the last reply. */
1003 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
1004 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
1005 } else {
1006 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
1011 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
1013 if (req->current_idx <= 1) {
1014 if (size <= sizeof(req->out._body)) {
1015 return data_blob_const(req->out._body, size);
1019 return data_blob_talloc(req, NULL, size);
1022 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
1024 struct smbXsrv_connection *xconn = req->xconn;
1025 TALLOC_CTX *mem_ctx;
1026 struct iovec *vector;
1027 int count;
1028 int idx;
1029 bool ok;
1031 count = req->in.vector_count;
1032 if (count <= ARRAY_SIZE(req->out._vector)) {
1033 mem_ctx = req;
1034 vector = req->out._vector;
1035 } else {
1036 vector = talloc_zero_array(req, struct iovec, count);
1037 if (vector == NULL) {
1038 return NT_STATUS_NO_MEMORY;
1040 mem_ctx = vector;
1043 vector[0].iov_base = req->out.nbt_hdr;
1044 vector[0].iov_len = 4;
1045 SIVAL(req->out.nbt_hdr, 0, 0);
1047 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
1048 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
1049 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
1050 uint8_t *outhdr = NULL;
1051 uint8_t *outbody = NULL;
1052 uint32_t next_command_ofs = 0;
1053 struct iovec *current = &vector[idx];
1055 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
1056 /* we have a next command -
1057 * setup for the error case. */
1058 next_command_ofs = SMB2_HDR_BODY + 9;
1061 if (idx == 1) {
1062 outhdr = req->out._hdr;
1063 } else {
1064 outhdr = talloc_zero_array(mem_ctx, uint8_t,
1065 OUTVEC_ALLOC_SIZE);
1066 if (outhdr == NULL) {
1067 return NT_STATUS_NO_MEMORY;
1071 outbody = outhdr + SMB2_HDR_BODY;
1074 * SMBD_SMB2_TF_IOV_OFS might be used later
1076 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1077 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1079 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
1080 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1082 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1083 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1085 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1086 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1088 /* setup the SMB2 header */
1089 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1090 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1091 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1092 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1093 SIVAL(outhdr, SMB2_HDR_STATUS,
1094 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1095 SSVAL(outhdr, SMB2_HDR_OPCODE,
1096 SVAL(inhdr, SMB2_HDR_OPCODE));
1097 SIVAL(outhdr, SMB2_HDR_FLAGS,
1098 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1099 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1100 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1101 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1102 SIVAL(outhdr, SMB2_HDR_PID,
1103 IVAL(inhdr, SMB2_HDR_PID));
1104 SIVAL(outhdr, SMB2_HDR_TID,
1105 IVAL(inhdr, SMB2_HDR_TID));
1106 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1107 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1108 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1109 inhdr + SMB2_HDR_SIGNATURE, 16);
1111 /* setup error body header */
1112 SSVAL(outbody, 0x00, 0x08 + 1);
1113 SSVAL(outbody, 0x02, 0);
1114 SIVAL(outbody, 0x04, 0);
1117 req->out.vector = vector;
1118 req->out.vector_count = count;
1120 /* setup the length of the NBT packet */
1121 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1122 if (!ok) {
1123 return NT_STATUS_INVALID_PARAMETER_MIX;
1126 DLIST_ADD_END(xconn->smb2.requests, req);
1128 return NT_STATUS_OK;
1131 bool smbXsrv_server_multi_channel_enabled(void)
1133 bool enabled = lp_server_multi_channel_support();
1134 #ifndef __ALLOW_MULTI_CHANNEL_SUPPORT
1135 bool forced = false;
1137 * If we don't have support from the kernel
1138 * to ask for the un-acked number of bytes
1139 * in the socket send queue, we better
1140 * don't support multi-channel.
1142 forced = lp_parm_bool(-1, "force", "server multi channel support", false);
1143 if (enabled && !forced) {
1144 D_NOTICE("'server multi channel support' enabled "
1145 "but not supported on %s (%s)\n",
1146 SYSTEM_UNAME_SYSNAME, SYSTEM_UNAME_RELEASE);
1147 DEBUGADD(DBGLVL_NOTICE, ("Please report this on "
1148 "https://bugzilla.samba.org/show_bug.cgi?id=11897\n"));
1149 enabled = false;
1151 #endif /* ! __ALLOW_MULTI_CHANNEL_SUPPORT */
1152 return enabled;
1155 static NTSTATUS smbXsrv_connection_get_rto_usecs(struct smbXsrv_connection *xconn,
1156 uint32_t *_rto_usecs)
1159 * Define an Retransmission Timeout
1160 * of 1 second, if there's no way for the
1161 * kernel to tell us the current value.
1163 uint32_t rto_usecs = 1000000;
1165 #ifdef __HAVE_TCP_INFO_RTO
1167 struct tcp_info info;
1168 socklen_t ilen = sizeof(info);
1169 int ret;
1171 ZERO_STRUCT(info);
1172 ret = getsockopt(xconn->transport.sock,
1173 IPPROTO_TCP, TCP_INFO,
1174 (void *)&info, &ilen);
1175 if (ret != 0) {
1176 int saved_errno = errno;
1177 NTSTATUS status = map_nt_error_from_unix(errno);
1178 DBG_ERR("getsockopt(TCP_INFO) errno[%d/%s] -s %s\n",
1179 saved_errno, strerror(saved_errno),
1180 nt_errstr(status));
1181 return status;
1184 DBG_DEBUG("tcpi_rto[%u] tcpi_rtt[%u] tcpi_rttvar[%u]\n",
1185 (unsigned)info.tcpi_rto,
1186 (unsigned)info.tcpi_rtt,
1187 (unsigned)info.tcpi_rttvar);
1188 rto_usecs = info.tcpi_rto;
1190 #endif /* __HAVE_TCP_INFO_RTO */
1192 rto_usecs = MAX(rto_usecs, 200000); /* at least 0.2s */
1193 rto_usecs = MIN(rto_usecs, 1000000); /* at max 1.0s */
1194 *_rto_usecs = rto_usecs;
1195 return NT_STATUS_OK;
1198 static NTSTATUS smbXsrv_connection_get_acked_bytes(struct smbXsrv_connection *xconn,
1199 uint64_t *_acked_bytes)
1202 * Unless the kernel has an interface
1203 * to reveal the number of un-acked bytes
1204 * in the socket send queue, we'll assume
1205 * everything is already acked.
1207 * But that would mean that we better don't
1208 * pretent to support multi-channel.
1210 uint64_t unacked_bytes = 0;
1212 *_acked_bytes = 0;
1214 if (xconn->ack.force_unacked_timeout) {
1216 * Smbtorture tries to test channel failures...
1217 * Just pretend nothing was acked...
1219 DBG_INFO("Simulating channel failure: "
1220 "xconn->ack.unacked_bytes[%llu]\n",
1221 (unsigned long long)xconn->ack.unacked_bytes);
1222 return NT_STATUS_OK;
1225 #ifdef __IOCTL_SEND_QUEUE_SIZE_OPCODE
1227 int value = 0;
1228 int ret;
1231 * If we have kernel support to get
1232 * the number of bytes waiting in
1233 * the socket's send queue, we
1234 * use that in order to find out
1235 * the number of unacked bytes.
1237 ret = ioctl(xconn->transport.sock,
1238 __IOCTL_SEND_QUEUE_SIZE_OPCODE,
1239 &value);
1240 if (ret != 0) {
1241 int saved_errno = errno;
1242 NTSTATUS status = map_nt_error_from_unix(saved_errno);
1243 DBG_ERR("Failed to get the SEND_QUEUE_SIZE - "
1244 "errno %d (%s) - %s\n",
1245 saved_errno, strerror(saved_errno),
1246 nt_errstr(status));
1247 return status;
1250 if (value < 0) {
1251 DBG_ERR("xconn->ack.unacked_bytes[%llu] value[%d]\n",
1252 (unsigned long long)xconn->ack.unacked_bytes,
1253 value);
1254 return NT_STATUS_INTERNAL_ERROR;
1256 unacked_bytes = value;
1258 #endif
1259 if (xconn->ack.unacked_bytes == 0) {
1260 xconn->ack.unacked_bytes = unacked_bytes;
1261 return NT_STATUS_OK;
1264 if (xconn->ack.unacked_bytes < unacked_bytes) {
1265 DBG_ERR("xconn->ack.unacked_bytes[%llu] unacked_bytes[%llu]\n",
1266 (unsigned long long)xconn->ack.unacked_bytes,
1267 (unsigned long long)unacked_bytes);
1268 return NT_STATUS_INTERNAL_ERROR;
1271 *_acked_bytes = xconn->ack.unacked_bytes - unacked_bytes;
1272 xconn->ack.unacked_bytes = unacked_bytes;
1273 return NT_STATUS_OK;
1276 static void smbd_smb2_send_queue_ack_fail(struct smbd_smb2_send_queue **queue,
1277 NTSTATUS status)
1279 struct smbd_smb2_send_queue *e = NULL;
1280 struct smbd_smb2_send_queue *n = NULL;
1282 for (e = *queue; e != NULL; e = n) {
1283 n = e->next;
1285 DLIST_REMOVE(*queue, e);
1286 if (e->ack.req != NULL) {
1287 tevent_req_nterror(e->ack.req, status);
1292 static NTSTATUS smbd_smb2_send_queue_ack_bytes(struct smbd_smb2_send_queue **queue,
1293 uint64_t acked_bytes)
1295 struct smbd_smb2_send_queue *e = NULL;
1296 struct smbd_smb2_send_queue *n = NULL;
1298 for (e = *queue; e != NULL; e = n) {
1299 bool expired;
1301 n = e->next;
1303 if (e->ack.req == NULL) {
1304 continue;
1307 if (e->ack.required_acked_bytes <= acked_bytes) {
1308 e->ack.required_acked_bytes = 0;
1309 DLIST_REMOVE(*queue, e);
1310 tevent_req_done(e->ack.req);
1311 continue;
1313 e->ack.required_acked_bytes -= acked_bytes;
1315 expired = timeval_expired(&e->ack.timeout);
1316 if (expired) {
1317 return NT_STATUS_IO_TIMEOUT;
1321 return NT_STATUS_OK;
1324 static NTSTATUS smbd_smb2_check_ack_queue(struct smbXsrv_connection *xconn)
1326 uint64_t acked_bytes = 0;
1327 NTSTATUS status;
1329 status = smbXsrv_connection_get_acked_bytes(xconn, &acked_bytes);
1330 if (!NT_STATUS_IS_OK(status)) {
1331 return status;
1334 status = smbd_smb2_send_queue_ack_bytes(&xconn->ack.queue, acked_bytes);
1335 if (!NT_STATUS_IS_OK(status)) {
1336 return status;
1339 status = smbd_smb2_send_queue_ack_bytes(&xconn->smb2.send_queue, 0);
1340 if (!NT_STATUS_IS_OK(status)) {
1341 return status;
1344 return NT_STATUS_OK;
1347 static void smbXsrv_connection_ack_checker(struct tevent_req *subreq)
1349 struct smbXsrv_connection *xconn =
1350 tevent_req_callback_data(subreq,
1351 struct smbXsrv_connection);
1352 struct smbXsrv_client *client = xconn->client;
1353 struct timeval next_check;
1354 NTSTATUS status;
1355 bool ok;
1357 xconn->ack.checker_subreq = NULL;
1359 ok = tevent_wakeup_recv(subreq);
1360 TALLOC_FREE(subreq);
1361 if (!ok) {
1362 smbd_server_connection_terminate(xconn,
1363 "tevent_wakeup_recv() failed");
1364 return;
1367 status = smbd_smb2_check_ack_queue(xconn);
1368 if (!NT_STATUS_IS_OK(status)) {
1369 smbd_server_connection_terminate(xconn, nt_errstr(status));
1370 return;
1373 next_check = timeval_current_ofs_usec(xconn->ack.rto_usecs);
1374 xconn->ack.checker_subreq = tevent_wakeup_send(xconn,
1375 client->raw_ev_ctx,
1376 next_check);
1377 if (xconn->ack.checker_subreq == NULL) {
1378 smbd_server_connection_terminate(xconn,
1379 "tevent_wakeup_send() failed");
1380 return;
1382 tevent_req_set_callback(xconn->ack.checker_subreq,
1383 smbXsrv_connection_ack_checker,
1384 xconn);
1387 static NTSTATUS smbXsrv_client_pending_breaks_updated(struct smbXsrv_client *client)
1389 struct smbXsrv_connection *xconn = NULL;
1391 for (xconn = client->connections; xconn != NULL; xconn = xconn->next) {
1392 struct timeval next_check;
1393 uint64_t acked_bytes = 0;
1394 NTSTATUS status;
1397 * A new 'pending break cycle' starts
1398 * with a first pending break and lasts until
1399 * all pending breaks are finished.
1401 * This is typically a very short time,
1402 * the value of one retransmission timeout.
1405 if (client->pending_breaks == NULL) {
1407 * No more pending breaks, remove a pending
1408 * checker timer
1410 TALLOC_FREE(xconn->ack.checker_subreq);
1411 continue;
1414 if (xconn->ack.checker_subreq != NULL) {
1416 * The cycle already started =>
1417 * nothing todo
1419 continue;
1423 * Get the current retransmission timeout value.
1425 * It may change over time, but fetching it once
1426 * per 'pending break' cycled should be enough.
1428 status = smbXsrv_connection_get_rto_usecs(xconn,
1429 &xconn->ack.rto_usecs);
1430 if (!NT_STATUS_IS_OK(status)) {
1431 return status;
1435 * At the start of the cycle we reset the
1436 * unacked_bytes counter (first to 0 and
1437 * within smbXsrv_connection_get_acked_bytes()
1438 * to the current value in the kernel
1439 * send queue.
1441 xconn->ack.unacked_bytes = 0;
1442 status = smbXsrv_connection_get_acked_bytes(xconn, &acked_bytes);
1443 if (!NT_STATUS_IS_OK(status)) {
1444 return status;
1448 * We setup a timer in order to check for
1449 * acked bytes after one retransmission timeout.
1451 * The code that sets up the send_queue.ack.timeout
1452 * uses a multiple of the retransmission timeout.
1454 next_check = timeval_current_ofs_usec(xconn->ack.rto_usecs);
1455 xconn->ack.checker_subreq = tevent_wakeup_send(xconn,
1456 client->raw_ev_ctx,
1457 next_check);
1458 if (xconn->ack.checker_subreq == NULL) {
1459 return NT_STATUS_NO_MEMORY;
1461 tevent_req_set_callback(xconn->ack.checker_subreq,
1462 smbXsrv_connection_ack_checker,
1463 xconn);
1466 return NT_STATUS_OK;
1469 void smbXsrv_connection_disconnect_transport(struct smbXsrv_connection *xconn,
1470 NTSTATUS status)
1472 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
1473 return;
1476 xconn->transport.status = status;
1477 TALLOC_FREE(xconn->transport.fde);
1478 if (xconn->transport.sock != -1) {
1479 xconn->transport.sock = -1;
1481 smbd_smb2_send_queue_ack_fail(&xconn->ack.queue, status);
1482 smbd_smb2_send_queue_ack_fail(&xconn->smb2.send_queue, status);
1483 xconn->smb2.send_queue_len = 0;
1484 DO_PROFILE_INC(disconnect);
1487 size_t smbXsrv_client_valid_connections(struct smbXsrv_client *client)
1489 struct smbXsrv_connection *xconn = NULL;
1490 size_t num_ok = 0;
1492 for (xconn = client->connections; xconn != NULL; xconn = xconn->next) {
1493 if (NT_STATUS_IS_OK(xconn->transport.status)) {
1494 num_ok++;
1498 return num_ok;
1501 struct smbXsrv_connection_shutdown_state {
1502 struct tevent_queue *wait_queue;
1503 struct smbXsrv_connection *xconn;
1506 static void smbXsrv_connection_shutdown_wait_done(struct tevent_req *subreq);
1508 static struct tevent_req *smbXsrv_connection_shutdown_send(TALLOC_CTX *mem_ctx,
1509 struct tevent_context *ev,
1510 struct smbXsrv_connection *xconn)
1512 struct tevent_req *req = NULL;
1513 struct smbXsrv_connection_shutdown_state *state = NULL;
1514 struct tevent_req *subreq = NULL;
1515 size_t len = 0;
1516 struct smbd_smb2_request *preq = NULL;
1517 NTSTATUS status;
1520 * The caller should have called
1521 * smbXsrv_connection_disconnect_transport() before.
1523 SMB_ASSERT(!NT_STATUS_IS_OK(xconn->transport.status));
1524 SMB_ASSERT(xconn->transport.terminating);
1526 req = tevent_req_create(mem_ctx, &state,
1527 struct smbXsrv_connection_shutdown_state);
1528 if (req == NULL) {
1529 return NULL;
1532 state->xconn = xconn;
1533 tevent_req_defer_callback(req, ev);
1535 status = smbXsrv_session_disconnect_xconn(xconn);
1536 if (tevent_req_nterror(req, status)) {
1537 return tevent_req_post(req, ev);
1540 state->wait_queue = tevent_queue_create(state, "smbXsrv_connection_shutdown_queue");
1541 if (tevent_req_nomem(state->wait_queue, req)) {
1542 return tevent_req_post(req, ev);
1545 for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
1547 * The connection is gone so we
1548 * don't need to take care of
1549 * any crypto
1551 preq->session = NULL;
1552 preq->do_signing = false;
1553 preq->do_encryption = false;
1554 preq->preauth = NULL;
1556 if (preq->subreq != NULL) {
1557 tevent_req_cancel(preq->subreq);
1561 * Now wait until the request is finished.
1563 * We don't set a callback, as we just want to block the
1564 * wait queue and the talloc_free() of the request will
1565 * remove the item from the wait queue.
1567 subreq = tevent_queue_wait_send(preq, ev, state->wait_queue);
1568 if (tevent_req_nomem(subreq, req)) {
1569 return tevent_req_post(req, ev);
1573 len = tevent_queue_length(state->wait_queue);
1574 if (len == 0) {
1575 tevent_req_done(req);
1576 return tevent_req_post(req, ev);
1580 * Now we add our own waiter to the end of the queue,
1581 * this way we get notified when all pending requests are finished
1582 * and send to the socket.
1584 subreq = tevent_queue_wait_send(state, ev, state->wait_queue);
1585 if (tevent_req_nomem(subreq, req)) {
1586 return tevent_req_post(req, ev);
1588 tevent_req_set_callback(subreq, smbXsrv_connection_shutdown_wait_done, req);
1590 return req;
1593 static void smbXsrv_connection_shutdown_wait_done(struct tevent_req *subreq)
1595 struct tevent_req *req =
1596 tevent_req_callback_data(subreq,
1597 struct tevent_req);
1598 struct smbXsrv_connection_shutdown_state *state =
1599 tevent_req_data(req,
1600 struct smbXsrv_connection_shutdown_state);
1601 struct smbXsrv_connection *xconn = state->xconn;
1603 tevent_queue_wait_recv(subreq);
1604 TALLOC_FREE(subreq);
1606 tevent_req_done(req);
1608 * make sure the xconn pointer is still valid,
1609 * it should as we used tevent_req_defer_callback()
1611 SMB_ASSERT(xconn->transport.terminating);
1614 static NTSTATUS smbXsrv_connection_shutdown_recv(struct tevent_req *req)
1616 struct smbXsrv_connection_shutdown_state *state =
1617 tevent_req_data(req,
1618 struct smbXsrv_connection_shutdown_state);
1619 struct smbXsrv_connection *xconn = state->xconn;
1621 * make sure the xconn pointer is still valid,
1622 * it should as we used tevent_req_defer_callback()
1624 SMB_ASSERT(xconn->transport.terminating);
1625 return tevent_req_simple_recv_ntstatus(req);
1628 static void smbd_server_connection_terminate_done(struct tevent_req *subreq)
1630 struct smbXsrv_connection *xconn =
1631 tevent_req_callback_data(subreq,
1632 struct smbXsrv_connection);
1633 struct smbXsrv_client *client = xconn->client;
1634 NTSTATUS status;
1636 status = smbXsrv_connection_shutdown_recv(subreq);
1637 if (!NT_STATUS_IS_OK(status)) {
1638 exit_server("smbXsrv_connection_shutdown_recv failed");
1641 DLIST_REMOVE(client->connections, xconn);
1642 TALLOC_FREE(xconn);
1645 void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
1646 const char *reason,
1647 const char *location)
1649 struct smbXsrv_client *client = xconn->client;
1650 size_t num_ok = 0;
1653 * Make sure that no new request will be able to use this session.
1655 * smbXsrv_connection_disconnect_transport() might be called already,
1656 * but calling it again is a no-op.
1658 smbXsrv_connection_disconnect_transport(xconn,
1659 NT_STATUS_CONNECTION_DISCONNECTED);
1661 num_ok = smbXsrv_client_valid_connections(client);
1663 if (xconn->transport.terminating) {
1664 DBG_DEBUG("skip recursion conn[%s] num_ok[%zu] reason[%s] at %s\n",
1665 smbXsrv_connection_dbg(xconn), num_ok,
1666 reason, location);
1667 return;
1669 xconn->transport.terminating = true;
1671 DBG_DEBUG("conn[%s] num_ok[%zu] reason[%s] at %s\n",
1672 smbXsrv_connection_dbg(xconn), num_ok,
1673 reason, location);
1675 if (xconn->has_cluster_movable_ip) {
1677 * If the connection has a movable cluster public address
1678 * we disconnect all client connections,
1679 * as the public address might be moved to
1680 * a different node.
1682 * In future we may recheck which node currently
1683 * holds this address, but for now we keep it simple.
1685 smbd_server_disconnect_client_ex(xconn->client,
1686 reason,
1687 location);
1688 return;
1691 if (num_ok != 0) {
1692 struct tevent_req *subreq = NULL;
1694 subreq = smbXsrv_connection_shutdown_send(client,
1695 client->raw_ev_ctx,
1696 xconn);
1697 if (subreq == NULL) {
1698 exit_server("smbXsrv_connection_shutdown_send failed");
1700 tevent_req_set_callback(subreq,
1701 smbd_server_connection_terminate_done,
1702 xconn);
1703 return;
1707 * The last connection was disconnected
1709 exit_server_cleanly(reason);
1712 void smbd_server_disconnect_client_ex(struct smbXsrv_client *client,
1713 const char *reason,
1714 const char *location)
1716 size_t num_ok = 0;
1718 num_ok = smbXsrv_client_valid_connections(client);
1720 DBG_WARNING("client[%s] num_ok[%zu] reason[%s] at %s\n",
1721 client->global->remote_address, num_ok,
1722 reason, location);
1725 * Something bad happened we need to disconnect all connections.
1727 exit_server_cleanly(reason);
1730 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1731 struct iovec *outvec,
1732 const struct iovec *srcvec)
1734 const uint8_t *srctf;
1735 size_t srctf_len;
1736 const uint8_t *srchdr;
1737 size_t srchdr_len;
1738 const uint8_t *srcbody;
1739 size_t srcbody_len;
1740 const uint8_t *expected_srcbody;
1741 const uint8_t *srcdyn;
1742 size_t srcdyn_len;
1743 const uint8_t *expected_srcdyn;
1744 uint8_t *dsttf;
1745 uint8_t *dsthdr;
1746 uint8_t *dstbody;
1747 uint8_t *dstdyn;
1749 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1750 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1751 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1752 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1753 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1754 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1755 expected_srcbody = srchdr + SMB2_HDR_BODY;
1756 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1757 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1758 expected_srcdyn = srcbody + 8;
1760 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1761 return false;
1764 if (srchdr_len != SMB2_HDR_BODY) {
1765 return false;
1768 if (srctf_len == SMB2_TF_HDR_SIZE) {
1769 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1770 if (dsttf == NULL) {
1771 return false;
1773 } else {
1774 dsttf = NULL;
1776 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1777 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1779 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1780 * be allocated with size OUTVEC_ALLOC_SIZE. */
1782 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1783 if (dsthdr == NULL) {
1784 return false;
1786 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1787 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1790 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1791 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1792 * then duplicate this. Else use talloc_memdup().
1795 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1796 dstbody = dsthdr + SMB2_HDR_BODY;
1797 } else {
1798 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1799 if (dstbody == NULL) {
1800 return false;
1803 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1804 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1807 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1808 * pointing to
1809 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1810 * then duplicate this. Else use talloc_memdup().
1813 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1814 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1815 } else if (srcdyn == NULL) {
1816 dstdyn = NULL;
1817 } else {
1818 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1819 if (dstdyn == NULL) {
1820 return false;
1823 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1824 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1826 return true;
1829 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1831 struct smbd_smb2_request *newreq = NULL;
1832 struct iovec *outvec = NULL;
1833 int count = req->out.vector_count;
1834 int i;
1835 bool ok;
1837 newreq = smbd_smb2_request_allocate(req->xconn);
1838 if (!newreq) {
1839 return NULL;
1842 newreq->sconn = req->sconn;
1843 newreq->xconn = req->xconn;
1844 newreq->session = req->session;
1845 newreq->do_encryption = req->do_encryption;
1846 newreq->do_signing = req->do_signing;
1847 newreq->current_idx = req->current_idx;
1849 outvec = talloc_zero_array(newreq, struct iovec, count);
1850 if (!outvec) {
1851 TALLOC_FREE(newreq);
1852 return NULL;
1854 newreq->out.vector = outvec;
1855 newreq->out.vector_count = count;
1857 /* Setup the outvec's identically to req. */
1858 outvec[0].iov_base = newreq->out.nbt_hdr;
1859 outvec[0].iov_len = 4;
1860 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1862 /* Setup the vectors identically to the ones in req. */
1863 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1864 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1865 break;
1869 if (i < count) {
1870 /* Alloc failed. */
1871 TALLOC_FREE(newreq);
1872 return NULL;
1875 ok = smb2_setup_nbt_length(newreq->out.vector,
1876 newreq->out.vector_count);
1877 if (!ok) {
1878 TALLOC_FREE(newreq);
1879 return NULL;
1882 return newreq;
1885 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1887 struct smbXsrv_connection *xconn = req->xconn;
1888 int first_idx = 1;
1889 struct iovec *firsttf = NULL;
1890 struct iovec *outhdr_v = NULL;
1891 uint8_t *outhdr = NULL;
1892 struct smbd_smb2_request *nreq = NULL;
1893 NTSTATUS status;
1894 bool ok;
1896 /* Create a new smb2 request we'll use
1897 for the interim return. */
1898 nreq = dup_smb2_req(req);
1899 if (!nreq) {
1900 return NT_STATUS_NO_MEMORY;
1903 /* Lose the last X out vectors. They're the
1904 ones we'll be using for the async reply. */
1905 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1907 ok = smb2_setup_nbt_length(nreq->out.vector,
1908 nreq->out.vector_count);
1909 if (!ok) {
1910 return NT_STATUS_INVALID_PARAMETER_MIX;
1913 /* Step back to the previous reply. */
1914 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1915 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1916 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1917 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1918 /* And end the chain. */
1919 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1921 /* Calculate outgoing credits */
1922 smb2_calculate_credits(req, nreq);
1924 if (DEBUGLEVEL >= 10) {
1925 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1926 (unsigned int)nreq->current_idx );
1927 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1928 (unsigned int)nreq->out.vector_count );
1929 print_req_vectors(nreq);
1933 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1934 * we need to sign/encrypt here with the last/first key we remembered
1936 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1937 struct smb2_signing_key key = {
1938 .blob = req->first_key,
1940 status = smb2_signing_encrypt_pdu(&key,
1941 xconn->smb2.server.cipher,
1942 firsttf,
1943 nreq->out.vector_count - first_idx);
1944 smb2_signing_key_destructor(&key);
1945 if (!NT_STATUS_IS_OK(status)) {
1946 return status;
1948 } else if (req->last_key.length > 0) {
1949 struct smb2_signing_key key = {
1950 .blob = req->last_key,
1953 status = smb2_signing_sign_pdu(&key,
1954 xconn->protocol,
1955 outhdr_v,
1956 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1957 smb2_signing_key_destructor(&key);
1958 if (!NT_STATUS_IS_OK(status)) {
1959 return status;
1963 nreq->queue_entry.mem_ctx = nreq;
1964 nreq->queue_entry.vector = nreq->out.vector;
1965 nreq->queue_entry.count = nreq->out.vector_count;
1966 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry);
1967 xconn->smb2.send_queue_len++;
1969 status = smbd_smb2_flush_send_queue(xconn);
1970 if (!NT_STATUS_IS_OK(status)) {
1971 return status;
1974 return NT_STATUS_OK;
1977 struct smbd_smb2_request_pending_state {
1978 struct smbd_smb2_send_queue queue_entry;
1979 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1980 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1983 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1984 struct tevent_timer *te,
1985 struct timeval current_time,
1986 void *private_data);
1988 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1989 struct tevent_req *subreq,
1990 uint32_t defer_time)
1992 NTSTATUS status;
1993 struct timeval defer_endtime;
1994 uint8_t *outhdr = NULL;
1995 uint32_t flags;
1997 if (!tevent_req_is_in_progress(subreq)) {
1999 * This is a performance optimization,
2000 * it avoids one tevent_loop iteration,
2001 * which means we avoid one
2002 * talloc_stackframe_pool/talloc_free pair.
2004 tevent_req_notify_callback(subreq);
2005 return NT_STATUS_OK;
2008 req->subreq = subreq;
2009 subreq = NULL;
2011 if (req->async_te) {
2012 /* We're already async. */
2013 return NT_STATUS_OK;
2016 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2017 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
2018 if (flags & SMB2_HDR_FLAG_ASYNC) {
2019 /* We're already async. */
2020 return NT_STATUS_OK;
2023 if (req->async_internal || defer_time == 0) {
2025 * An SMB2 request implementation wants to handle the request
2026 * asynchronously "internally" while keeping synchronous
2027 * behaviour for the SMB2 request. This means we don't send an
2028 * interim response and we can allow processing of compound SMB2
2029 * requests (cf the subsequent check) for all cases.
2031 return NT_STATUS_OK;
2034 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
2036 * We're trying to go async in a compound request
2037 * chain. This is only allowed for opens that cause an
2038 * oplock break or for the last operation in the
2039 * chain, otherwise it is not allowed. See
2040 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
2042 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2044 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
2046 * Cancel the outstanding request.
2048 bool ok = tevent_req_cancel(req->subreq);
2049 if (ok) {
2050 return NT_STATUS_OK;
2052 TALLOC_FREE(req->subreq);
2053 return smbd_smb2_request_error(req,
2054 NT_STATUS_INTERNAL_ERROR);
2058 if (DEBUGLEVEL >= 10) {
2059 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
2060 (unsigned int)req->current_idx );
2061 print_req_vectors(req);
2064 if (req->current_idx > 1) {
2066 * We're going async in a compound
2067 * chain after the first request has
2068 * already been processed. Send an
2069 * interim response containing the
2070 * set of replies already generated.
2072 int idx = req->current_idx;
2074 status = smb2_send_async_interim_response(req);
2075 if (!NT_STATUS_IS_OK(status)) {
2076 return status;
2078 if (req->first_key.length > 0) {
2079 data_blob_clear_free(&req->first_key);
2082 req->current_idx = 1;
2085 * Re-arrange the in.vectors to remove what
2086 * we just sent.
2088 memmove(&req->in.vector[1],
2089 &req->in.vector[idx],
2090 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
2091 req->in.vector_count = 1 + (req->in.vector_count - idx);
2093 /* Re-arrange the out.vectors to match. */
2094 memmove(&req->out.vector[1],
2095 &req->out.vector[idx],
2096 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
2097 req->out.vector_count = 1 + (req->out.vector_count - idx);
2099 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
2101 * We only have one remaining request as
2102 * we've processed everything else.
2103 * This is no longer a compound request.
2105 req->compound_related = false;
2106 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2107 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
2108 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
2111 if (req->last_key.length > 0) {
2112 data_blob_clear_free(&req->last_key);
2116 * smbd_smb2_request_pending_timer() just send a packet
2117 * to the client and doesn't need any impersonation.
2118 * So we use req->xconn->client->raw_ev_ctx instead
2119 * of req->ev_ctx here.
2121 defer_endtime = timeval_current_ofs_usec(defer_time);
2122 req->async_te = tevent_add_timer(req->xconn->client->raw_ev_ctx,
2123 req, defer_endtime,
2124 smbd_smb2_request_pending_timer,
2125 req);
2126 if (req->async_te == NULL) {
2127 return NT_STATUS_NO_MEMORY;
2130 return NT_STATUS_OK;
2133 static
2134 struct smb2_signing_key *smbd_smb2_signing_key(struct smbXsrv_session *session,
2135 struct smbXsrv_connection *xconn)
2137 struct smbXsrv_channel_global0 *c = NULL;
2138 NTSTATUS status;
2139 struct smb2_signing_key *key = NULL;
2141 status = smbXsrv_session_find_channel(session, xconn, &c);
2142 if (NT_STATUS_IS_OK(status)) {
2143 key = c->signing_key;
2146 if (!smb2_signing_key_valid(key)) {
2147 key = session->global->signing_key;
2150 return key;
2153 static NTSTATUS smb2_get_new_nonce(struct smbXsrv_session *session,
2154 uint64_t *new_nonce_high,
2155 uint64_t *new_nonce_low)
2157 uint64_t nonce_high;
2158 uint64_t nonce_low;
2160 session->nonce_low += 1;
2161 if (session->nonce_low == 0) {
2162 session->nonce_low += 1;
2163 session->nonce_high += 1;
2167 * CCM and GCM algorithms must never have their
2168 * nonce wrap, or the security of the whole
2169 * communication and the keys is destroyed.
2170 * We must drop the connection once we have
2171 * transfered too much data.
2173 * NOTE: We assume nonces greater than 8 bytes.
2175 if (session->nonce_high >= session->nonce_high_max) {
2176 return NT_STATUS_ENCRYPTION_FAILED;
2179 nonce_high = session->nonce_high_random;
2180 nonce_high += session->nonce_high;
2181 nonce_low = session->nonce_low;
2183 *new_nonce_high = nonce_high;
2184 *new_nonce_low = nonce_low;
2185 return NT_STATUS_OK;
2188 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
2189 struct tevent_timer *te,
2190 struct timeval current_time,
2191 void *private_data)
2193 struct smbd_smb2_request *req =
2194 talloc_get_type_abort(private_data,
2195 struct smbd_smb2_request);
2196 struct smbXsrv_connection *xconn = req->xconn;
2197 struct smbd_smb2_request_pending_state *state = NULL;
2198 uint8_t *outhdr = NULL;
2199 const uint8_t *inhdr = NULL;
2200 uint8_t *tf = NULL;
2201 uint8_t *hdr = NULL;
2202 uint8_t *body = NULL;
2203 uint8_t *dyn = NULL;
2204 uint32_t flags = 0;
2205 uint64_t message_id = 0;
2206 uint64_t async_id = 0;
2207 NTSTATUS status;
2208 bool ok;
2210 TALLOC_FREE(req->async_te);
2212 /* Ensure our final reply matches the interim one. */
2213 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2214 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2215 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
2216 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
2218 async_id = message_id; /* keep it simple for now... */
2220 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
2221 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
2223 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
2224 "going async\n",
2225 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
2226 (unsigned long long)async_id ));
2229 * What we send is identical to a smbd_smb2_request_error
2230 * packet with an error status of STATUS_PENDING. Make use
2231 * of this fact sometime when refactoring. JRA.
2234 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
2235 if (state == NULL) {
2236 smbd_server_connection_terminate(xconn,
2237 nt_errstr(NT_STATUS_NO_MEMORY));
2238 return;
2241 tf = state->buf + NBT_HDR_SIZE;
2243 hdr = tf + SMB2_TF_HDR_SIZE;
2244 body = hdr + SMB2_HDR_BODY;
2245 dyn = body + 8;
2247 if (req->do_encryption) {
2248 uint64_t nonce_high = 0;
2249 uint64_t nonce_low = 0;
2250 uint64_t session_id = req->session->global->session_wire_id;
2252 status = smb2_get_new_nonce(req->session,
2253 &nonce_high,
2254 &nonce_low);
2255 if (!NT_STATUS_IS_OK(status)) {
2256 smbd_server_connection_terminate(xconn,
2257 nt_errstr(status));
2258 return;
2261 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2262 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2263 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2264 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2267 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
2268 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2269 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2270 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(NT_STATUS_PENDING));
2271 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
2273 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
2274 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2275 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
2276 SBVAL(hdr, SMB2_HDR_PID, async_id);
2277 SBVAL(hdr, SMB2_HDR_SESSION_ID,
2278 BVAL(outhdr, SMB2_HDR_SESSION_ID));
2279 memcpy(hdr+SMB2_HDR_SIGNATURE,
2280 outhdr+SMB2_HDR_SIGNATURE, 16);
2282 SSVAL(body, 0x00, 0x08 + 1);
2284 SCVAL(body, 0x02, 0);
2285 SCVAL(body, 0x03, 0);
2286 SIVAL(body, 0x04, 0);
2287 /* Match W2K8R2... */
2288 SCVAL(dyn, 0x00, 0x21);
2290 state->vector[0].iov_base = (void *)state->buf;
2291 state->vector[0].iov_len = NBT_HDR_SIZE;
2293 if (req->do_encryption) {
2294 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
2295 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len =
2296 SMB2_TF_HDR_SIZE;
2297 } else {
2298 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
2299 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
2302 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
2303 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
2305 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
2306 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
2308 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
2309 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
2311 ok = smb2_setup_nbt_length(state->vector,
2312 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2313 if (!ok) {
2314 smbd_server_connection_terminate(
2315 xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
2316 return;
2319 /* Ensure we correctly go through crediting. Grant
2320 the credits now, and zero credits on the final
2321 response. */
2322 smb2_set_operation_credit(req->xconn,
2323 SMBD_SMB2_IN_HDR_IOV(req),
2324 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
2326 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
2328 if (DEBUGLVL(10)) {
2329 int i;
2331 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
2332 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
2333 (unsigned int)i,
2334 (unsigned int)ARRAY_SIZE(state->vector),
2335 (unsigned int)state->vector[i].iov_len);
2339 if (req->do_encryption) {
2340 struct smbXsrv_session *x = req->session;
2341 struct smb2_signing_key *encryption_key = x->global->encryption_key;
2343 status = smb2_signing_encrypt_pdu(encryption_key,
2344 xconn->smb2.server.cipher,
2345 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2346 SMBD_SMB2_NUM_IOV_PER_REQ);
2347 if (!NT_STATUS_IS_OK(status)) {
2348 smbd_server_connection_terminate(xconn,
2349 nt_errstr(status));
2350 return;
2352 } else if (req->do_signing) {
2353 struct smbXsrv_session *x = req->session;
2354 struct smb2_signing_key *signing_key =
2355 smbd_smb2_signing_key(x, xconn);
2357 status = smb2_signing_sign_pdu(signing_key,
2358 xconn->protocol,
2359 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
2360 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2361 if (!NT_STATUS_IS_OK(status)) {
2362 smbd_server_connection_terminate(xconn,
2363 nt_errstr(status));
2364 return;
2368 state->queue_entry.mem_ctx = state;
2369 state->queue_entry.vector = state->vector;
2370 state->queue_entry.count = ARRAY_SIZE(state->vector);
2371 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
2372 xconn->smb2.send_queue_len++;
2374 status = smbd_smb2_flush_send_queue(xconn);
2375 if (!NT_STATUS_IS_OK(status)) {
2376 smbd_server_connection_terminate(xconn,
2377 nt_errstr(status));
2378 return;
2382 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
2384 struct smbXsrv_connection *xconn = req->xconn;
2385 struct smbd_smb2_request *cur;
2386 const uint8_t *inhdr;
2387 uint32_t flags;
2388 uint64_t search_message_id;
2389 uint64_t search_async_id;
2390 uint64_t found_id;
2392 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2394 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2395 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2396 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
2399 * We don't need the request anymore cancel requests never
2400 * have a response.
2402 * We defer the TALLOC_FREE(req) to the caller.
2404 DLIST_REMOVE(xconn->smb2.requests, req);
2406 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
2407 const uint8_t *outhdr;
2408 uint64_t message_id;
2409 uint64_t async_id;
2411 if (cur->compound_related) {
2413 * Never cancel anything in a compound request.
2414 * Way too hard to deal with the result.
2416 continue;
2419 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
2421 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
2422 async_id = BVAL(outhdr, SMB2_HDR_PID);
2424 if (flags & SMB2_HDR_FLAG_ASYNC) {
2425 if (search_async_id == async_id) {
2426 found_id = async_id;
2427 break;
2429 } else {
2430 if (search_message_id == message_id) {
2431 found_id = message_id;
2432 break;
2437 if (cur && cur->subreq) {
2438 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
2439 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
2440 "cancel opcode[%s] mid %llu\n",
2441 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
2442 (unsigned long long)found_id ));
2443 tevent_req_cancel(cur->subreq);
2446 return NT_STATUS_OK;
2449 /*************************************************************
2450 Ensure an incoming tid is a valid one for us to access.
2451 Change to the associated uid credentials and chdir to the
2452 valid tid directory.
2453 *************************************************************/
2455 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
2457 const uint8_t *inhdr;
2458 uint32_t in_flags;
2459 uint32_t in_tid;
2460 struct smbXsrv_tcon *tcon;
2461 NTSTATUS status;
2462 NTTIME now = timeval_to_nttime(&req->request_time);
2464 req->tcon = NULL;
2466 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2468 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2469 in_tid = IVAL(inhdr, SMB2_HDR_TID);
2471 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
2472 in_tid = req->last_tid;
2475 req->last_tid = 0;
2477 status = smb2srv_tcon_lookup(req->session,
2478 in_tid, now, &tcon);
2479 if (!NT_STATUS_IS_OK(status)) {
2480 return status;
2483 if (!change_to_user_and_service(
2484 tcon->compat,
2485 req->session->global->session_wire_id))
2487 return NT_STATUS_ACCESS_DENIED;
2490 req->tcon = tcon;
2491 req->last_tid = in_tid;
2493 return NT_STATUS_OK;
2496 /*************************************************************
2497 Ensure an incoming session_id is a valid one for us to access.
2498 *************************************************************/
2500 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
2502 const uint8_t *inhdr;
2503 uint32_t in_flags;
2504 uint16_t in_opcode;
2505 uint64_t in_session_id;
2506 struct smbXsrv_session *session = NULL;
2507 struct auth_session_info *session_info;
2508 NTSTATUS status;
2509 NTTIME now = timeval_to_nttime(&req->request_time);
2511 req->session = NULL;
2512 req->tcon = NULL;
2514 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2516 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2517 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2518 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
2520 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
2521 in_session_id = req->last_session_id;
2524 req->last_session_id = 0;
2526 /* look an existing session up */
2527 switch (in_opcode) {
2528 case SMB2_OP_SESSSETUP:
2530 * For a session bind request, we don't have the
2531 * channel set up at this point yet, so we defer
2532 * the verification that the connection belongs
2533 * to the session to the session setup code, which
2534 * can look at the session binding flags.
2536 status = smb2srv_session_lookup_client(req->xconn->client,
2537 in_session_id, now,
2538 &session);
2539 break;
2540 default:
2541 status = smb2srv_session_lookup_conn(req->xconn,
2542 in_session_id, now,
2543 &session);
2544 break;
2546 if (session) {
2547 req->session = session;
2548 req->last_session_id = in_session_id;
2550 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
2551 switch (in_opcode) {
2552 case SMB2_OP_SESSSETUP:
2553 status = NT_STATUS_OK;
2554 break;
2555 case SMB2_OP_LOGOFF:
2556 case SMB2_OP_CLOSE:
2557 case SMB2_OP_LOCK:
2558 case SMB2_OP_CANCEL:
2559 case SMB2_OP_KEEPALIVE:
2561 * [MS-SMB2] 3.3.5.2.9 Verifying the Session
2562 * specifies that LOGOFF, CLOSE and (UN)LOCK
2563 * should always be processed even on expired sessions.
2565 * Also see the logic in
2566 * smbd_smb2_request_process_lock().
2568 * The smb2.session.expire2 test shows that
2569 * CANCEL and KEEPALIVE/ECHO should also
2570 * be processed.
2572 status = NT_STATUS_OK;
2573 break;
2574 default:
2575 break;
2578 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2579 switch (in_opcode) {
2580 case SMB2_OP_TCON:
2581 case SMB2_OP_CREATE:
2582 case SMB2_OP_GETINFO:
2583 case SMB2_OP_SETINFO:
2584 return NT_STATUS_INVALID_HANDLE;
2585 default:
2587 * Notice the check for
2588 * (session_info == NULL)
2589 * below.
2591 status = NT_STATUS_OK;
2592 break;
2595 if (!NT_STATUS_IS_OK(status)) {
2596 return status;
2599 session_info = session->global->auth_session_info;
2600 if (session_info == NULL) {
2601 return NT_STATUS_INVALID_HANDLE;
2604 return NT_STATUS_OK;
2607 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
2608 uint32_t data_length)
2610 struct smbXsrv_connection *xconn = req->xconn;
2611 uint16_t needed_charge;
2612 uint16_t credit_charge = 1;
2613 const uint8_t *inhdr;
2615 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2617 if (xconn->smb2.credits.multicredit) {
2618 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
2619 credit_charge = MAX(credit_charge, 1);
2622 needed_charge = (data_length - 1)/ 65536 + 1;
2624 DBGC_DEBUG(DBGC_SMB2_CREDITS,
2625 "mid %llu, CreditCharge: %d, NeededCharge: %d\n",
2626 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
2627 credit_charge, needed_charge);
2629 if (needed_charge > credit_charge) {
2630 DBGC_WARNING(DBGC_SMB2_CREDITS,
2631 "CreditCharge too low, given %d, needed %d\n",
2632 credit_charge, needed_charge);
2633 return NT_STATUS_INVALID_PARAMETER;
2636 return NT_STATUS_OK;
2639 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
2640 size_t expected_body_size)
2642 struct iovec *inhdr_v;
2643 const uint8_t *inhdr;
2644 uint16_t opcode;
2645 const uint8_t *inbody;
2646 size_t body_size;
2647 size_t min_dyn_size = expected_body_size & 0x00000001;
2648 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
2651 * The following should be checked already.
2653 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
2654 return NT_STATUS_INTERNAL_ERROR;
2656 if (req->current_idx > max_idx) {
2657 return NT_STATUS_INTERNAL_ERROR;
2660 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
2661 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
2662 return NT_STATUS_INTERNAL_ERROR;
2664 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
2665 return NT_STATUS_INTERNAL_ERROR;
2668 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2669 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2671 switch (opcode) {
2672 case SMB2_OP_IOCTL:
2673 case SMB2_OP_GETINFO:
2674 case SMB2_OP_WRITE:
2675 min_dyn_size = 0;
2676 break;
2680 * Now check the expected body size,
2681 * where the last byte might be in the
2682 * dynamic section..
2684 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
2685 return NT_STATUS_INVALID_PARAMETER;
2687 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
2688 return NT_STATUS_INVALID_PARAMETER;
2691 inbody = SMBD_SMB2_IN_BODY_PTR(req);
2693 body_size = SVAL(inbody, 0x00);
2694 if (body_size != expected_body_size) {
2695 return NT_STATUS_INVALID_PARAMETER;
2698 return NT_STATUS_OK;
2701 bool smbXsrv_is_encrypted(uint8_t encryption_flags)
2703 return (!(encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)
2705 (encryption_flags & (SMBXSRV_PROCESSED_ENCRYPTED_PACKET |
2706 SMBXSRV_ENCRYPTION_DESIRED |
2707 SMBXSRV_ENCRYPTION_REQUIRED)));
2710 bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags)
2712 return ((encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET) &&
2713 (encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET));
2716 /* Set a flag if not already set, return true if set */
2717 bool smbXsrv_set_crypto_flag(uint8_t *flags, uint8_t flag)
2719 if ((flag == 0) || (*flags & flag)) {
2720 return false;
2723 *flags |= flag;
2724 return true;
2728 * Update encryption state tracking flags, this can be used to
2729 * determine whether whether the session or tcon is "encrypted".
2731 static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
2732 uint16_t opcode,
2733 bool *update_session_globalp,
2734 bool *update_tcon_globalp)
2736 /* Default: assume unecrypted and unsigned */
2737 struct smbXsrv_session *session = req->session;
2738 struct smbXsrv_tcon *tcon = req->tcon;
2739 uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
2740 uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2741 bool update_session = false;
2742 bool update_tcon = false;
2744 if (req->was_encrypted && req->do_encryption) {
2745 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
2746 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2747 } else {
2748 /* Unencrypted packet, can be signed */
2749 if (req->do_signing) {
2750 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2751 } else if (opcode == SMB2_OP_CANCEL) {
2752 /* Cancel requests are allowed to skip signing */
2753 sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2757 update_session |= smbXsrv_set_crypto_flag(
2758 &session->global->encryption_flags, encrypt_flag);
2759 update_session |= smbXsrv_set_crypto_flag(
2760 &session->global->signing_flags, sign_flag);
2762 if (tcon) {
2763 update_tcon |= smbXsrv_set_crypto_flag(
2764 &tcon->global->encryption_flags, encrypt_flag);
2765 update_tcon |= smbXsrv_set_crypto_flag(
2766 &tcon->global->signing_flags, sign_flag);
2769 *update_session_globalp = update_session;
2770 *update_tcon_globalp = update_tcon;
2771 return;
2774 bool smbXsrv_is_signed(uint8_t signing_flags)
2777 * Signing is always enabled, so unless we got an unsigned
2778 * packet and at least one signed packet that was not
2779 * encrypted, the session or tcon is "signed".
2781 return (!(signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2782 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2785 bool smbXsrv_is_partially_signed(uint8_t signing_flags)
2787 return ((signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2788 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2791 static NTSTATUS smbd_smb2_request_dispatch_update_counts(
2792 struct smbd_smb2_request *req,
2793 bool modify_call)
2795 struct smbXsrv_connection *xconn = req->xconn;
2796 const uint8_t *inhdr;
2797 uint16_t channel_sequence;
2798 uint8_t generation_wrap = 0;
2799 uint32_t flags;
2800 int cmp;
2801 struct smbXsrv_open *op;
2802 bool update_open = false;
2803 NTSTATUS status = NT_STATUS_OK;
2805 SMB_ASSERT(!req->request_counters_updated);
2807 if (xconn->protocol < PROTOCOL_SMB2_22) {
2808 return NT_STATUS_OK;
2811 if (req->compat_chain_fsp == NULL) {
2812 return NT_STATUS_OK;
2815 op = req->compat_chain_fsp->op;
2816 if (op == NULL) {
2817 return NT_STATUS_OK;
2820 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2821 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2822 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2824 cmp = channel_sequence - op->global->channel_sequence;
2825 if (cmp < 0) {
2827 * csn wrap. We need to watch out for long-running
2828 * requests that are still sitting on a previously
2829 * used csn. SMB2_OP_NOTIFY can take VERY long.
2831 generation_wrap += 1;
2834 if (abs(cmp) > INT16_MAX) {
2836 * [MS-SMB2] 3.3.5.2.10 - Verifying the Channel Sequence Number:
2838 * If the channel sequence number of the request and the one
2839 * known to the server are not equal, the channel sequence
2840 * number and outstanding request counts are only updated
2841 * "... if the unsigned difference using 16-bit arithmetic
2842 * between ChannelSequence and Open.ChannelSequence is less than
2843 * or equal to 0x7FFF ...".
2844 * Otherwise, an error is returned for the modifying
2845 * calls write, set_info, and ioctl.
2847 * There are currently two issues with the description:
2849 * * For the other calls, the document seems to imply
2850 * that processing continues without adapting the
2851 * counters (if the sequence numbers are not equal).
2853 * TODO: This needs clarification!
2855 * * Also, the behaviour if the difference is larger
2856 * than 0x7FFF is not clear. The document seems to
2857 * imply that if such a difference is reached,
2858 * the server starts to ignore the counters or
2859 * in the case of the modifying calls, return errors.
2861 * TODO: This needs clarification!
2863 * At this point Samba tries to be a little more
2864 * clever than the description in the MS-SMB2 document
2865 * by heuristically detecting and properly treating
2866 * a 16 bit overflow of the client-submitted sequence
2867 * number:
2869 * If the stored channel sequence number is more than
2870 * 0x7FFF larger than the one from the request, then
2871 * the client-provided sequence number has likely
2872 * overflown. We treat this case as valid instead
2873 * of as failure.
2875 * The MS-SMB2 behaviour would be setting cmp = -1.
2877 cmp *= -1;
2880 if (flags & SMB2_HDR_FLAG_REPLAY_OPERATION) {
2881 if (cmp == 0 && op->pre_request_count == 0) {
2882 op->request_count += 1;
2883 req->request_counters_updated = true;
2884 } else if (cmp > 0 && op->pre_request_count == 0) {
2885 op->pre_request_count += op->request_count;
2886 op->request_count = 1;
2887 op->global->channel_sequence = channel_sequence;
2888 op->global->channel_generation += generation_wrap;
2889 update_open = true;
2890 req->request_counters_updated = true;
2891 } else if (modify_call) {
2892 return NT_STATUS_FILE_NOT_AVAILABLE;
2894 } else {
2895 if (cmp == 0) {
2896 op->request_count += 1;
2897 req->request_counters_updated = true;
2898 } else if (cmp > 0) {
2899 op->pre_request_count += op->request_count;
2900 op->request_count = 1;
2901 op->global->channel_sequence = channel_sequence;
2902 op->global->channel_generation += generation_wrap;
2903 update_open = true;
2904 req->request_counters_updated = true;
2905 } else if (modify_call) {
2906 return NT_STATUS_FILE_NOT_AVAILABLE;
2909 req->channel_generation = op->global->channel_generation;
2911 if (update_open) {
2912 status = smbXsrv_open_update(op);
2915 return status;
2918 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
2920 struct smbXsrv_connection *xconn = req->xconn;
2921 const struct smbd_smb2_dispatch_table *call = NULL;
2922 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
2923 const uint8_t *inhdr;
2924 uint16_t opcode;
2925 uint32_t flags;
2926 uint64_t mid;
2927 NTSTATUS status;
2928 NTSTATUS session_status;
2929 uint32_t allowed_flags;
2930 NTSTATUS return_value;
2931 struct smbXsrv_session *x = NULL;
2932 bool signing_required = false;
2933 bool encryption_desired = false;
2934 bool encryption_required = false;
2936 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2938 DO_PROFILE_INC(request);
2940 SMB_ASSERT(!req->request_counters_updated);
2942 /* TODO: verify more things */
2944 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2945 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2946 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2947 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
2948 smb2_opcode_name(opcode),
2949 (unsigned long long)mid));
2951 if (xconn->protocol >= PROTOCOL_SMB2_02) {
2953 * once the protocol is negotiated
2954 * SMB2_OP_NEGPROT is not allowed anymore
2956 if (opcode == SMB2_OP_NEGPROT) {
2957 /* drop the connection */
2958 return NT_STATUS_INVALID_PARAMETER;
2960 } else {
2962 * if the protocol is not negotiated yet
2963 * only SMB2_OP_NEGPROT is allowed.
2965 if (opcode != SMB2_OP_NEGPROT) {
2966 /* drop the connection */
2967 return NT_STATUS_INVALID_PARAMETER;
2972 * Check if the client provided a valid session id.
2974 * As some command don't require a valid session id
2975 * we defer the check of the session_status
2977 session_status = smbd_smb2_request_check_session(req);
2978 x = req->session;
2979 if (x != NULL) {
2980 signing_required = x->global->signing_flags & SMBXSRV_SIGNING_REQUIRED;
2981 encryption_desired = x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
2982 encryption_required = x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
2985 req->async_internal = false;
2986 req->do_signing = false;
2987 if (opcode != SMB2_OP_SESSSETUP) {
2988 req->do_encryption = encryption_desired;
2989 } else {
2990 req->do_encryption = false;
2992 req->was_encrypted = false;
2993 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
2994 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
2995 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
2997 if (x != NULL && x->global->session_wire_id != tf_session_id) {
2998 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2999 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
3000 (unsigned long long)x->global->session_wire_id,
3001 (unsigned long long)tf_session_id));
3003 * TODO: windows allows this...
3004 * should we drop the connection?
3006 * For now we just return ACCESS_DENIED
3007 * (Windows clients never trigger this)
3008 * and wait for an update of [MS-SMB2].
3010 return smbd_smb2_request_error(req,
3011 NT_STATUS_ACCESS_DENIED);
3014 req->was_encrypted = true;
3015 req->do_encryption = true;
3018 if (encryption_required && !req->was_encrypted) {
3019 req->do_encryption = true;
3020 return smbd_smb2_request_error(req,
3021 NT_STATUS_ACCESS_DENIED);
3024 call = smbd_smb2_call(opcode);
3025 if (call == NULL) {
3026 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
3029 allowed_flags = SMB2_HDR_FLAG_CHAINED |
3030 SMB2_HDR_FLAG_SIGNED |
3031 SMB2_HDR_FLAG_DFS;
3032 if (xconn->protocol >= PROTOCOL_SMB3_11) {
3033 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
3035 if (opcode == SMB2_OP_NEGPROT) {
3036 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11) {
3037 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
3040 if (opcode == SMB2_OP_CANCEL) {
3041 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
3043 if (xconn->protocol >= PROTOCOL_SMB2_22) {
3044 allowed_flags |= SMB2_HDR_FLAG_REPLAY_OPERATION;
3046 if ((flags & ~allowed_flags) != 0) {
3047 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
3050 if (flags & SMB2_HDR_FLAG_CHAINED) {
3052 * This check is mostly for giving the correct error code
3053 * for compounded requests.
3055 if (!NT_STATUS_IS_OK(session_status)) {
3056 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
3058 } else {
3059 req->compat_chain_fsp = NULL;
3062 if (req->was_encrypted) {
3063 signing_required = false;
3064 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
3065 struct smb2_signing_key *signing_key = NULL;
3067 if (x == NULL) {
3069 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
3070 * If the SMB2 header of the SMB2 NEGOTIATE
3071 * request has the SMB2_FLAGS_SIGNED bit set in the
3072 * Flags field, the server MUST fail the request
3073 * with STATUS_INVALID_PARAMETER.
3075 * Microsoft test tool checks this.
3078 if ((opcode == SMB2_OP_NEGPROT) &&
3079 (flags & SMB2_HDR_FLAG_SIGNED)) {
3080 status = NT_STATUS_INVALID_PARAMETER;
3081 } else {
3082 status = NT_STATUS_USER_SESSION_DELETED;
3084 return smbd_smb2_request_error(req, status);
3087 signing_key = smbd_smb2_signing_key(x, xconn);
3090 * If we have a signing key, we should
3091 * sign the response
3093 if (smb2_signing_key_valid(signing_key)) {
3094 req->do_signing = true;
3097 status = smb2_signing_check_pdu(signing_key,
3098 xconn->protocol,
3099 SMBD_SMB2_IN_HDR_IOV(req),
3100 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
3101 if (!NT_STATUS_IS_OK(status)) {
3102 return smbd_smb2_request_error(req, status);
3106 * Now that we know the request was correctly signed
3107 * we have to sign the response too.
3109 req->do_signing = true;
3111 if (!NT_STATUS_IS_OK(session_status)) {
3112 return smbd_smb2_request_error(req, session_status);
3114 } else if (opcode == SMB2_OP_CANCEL) {
3115 /* Cancel requests are allowed to skip the signing */
3116 } else if (opcode == SMB2_OP_IOCTL) {
3118 * Some special IOCTL calls don't require
3119 * file, tcon nor session.
3121 * They typically don't do any real action
3122 * on behalf of the client.
3124 * They are mainly used to alter the behavior
3125 * of the connection for testing. So we can
3126 * run as root and skip all file, tcon and session
3127 * checks below.
3129 static const struct smbd_smb2_dispatch_table _root_ioctl_call = {
3130 _OP(SMB2_OP_IOCTL),
3131 .as_root = true,
3133 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
3134 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
3135 uint32_t in_ctl_code;
3136 size_t needed = 4;
3138 if (needed > body_size) {
3139 return smbd_smb2_request_error(req,
3140 NT_STATUS_INVALID_PARAMETER);
3143 in_ctl_code = IVAL(body, 0x04);
3145 * Only add trusted IOCTL codes here!
3147 switch (in_ctl_code) {
3148 case FSCTL_SMBTORTURE_FORCE_UNACKED_TIMEOUT:
3149 call = &_root_ioctl_call;
3150 break;
3152 } else if (signing_required) {
3154 * If signing is required we try to sign
3155 * a possible error response
3157 req->do_signing = true;
3158 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
3161 if (flags & SMB2_HDR_FLAG_CHAINED) {
3162 req->compound_related = true;
3165 if (call->need_session) {
3166 if (!NT_STATUS_IS_OK(session_status)) {
3167 return smbd_smb2_request_error(req, session_status);
3171 if (call->need_tcon) {
3172 SMB_ASSERT(call->need_session);
3175 * This call needs to be run as user.
3177 * smbd_smb2_request_check_tcon()
3178 * calls change_to_user() on success.
3179 * Which implies set_current_user_info()
3180 * and chdir_current_service().
3182 status = smbd_smb2_request_check_tcon(req);
3183 if (!NT_STATUS_IS_OK(status)) {
3184 return smbd_smb2_request_error(req, status);
3186 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
3187 encryption_desired = true;
3189 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
3190 encryption_required = true;
3192 if (encryption_required && !req->was_encrypted) {
3193 req->do_encryption = true;
3194 return smbd_smb2_request_error(req,
3195 NT_STATUS_ACCESS_DENIED);
3196 } else if (encryption_desired) {
3197 req->do_encryption = true;
3199 } else if (call->need_session) {
3200 struct auth_session_info *session_info = NULL;
3203 * Unless we also have need_tcon (see above),
3204 * we still need to call set_current_user_info().
3207 session_info = req->session->global->auth_session_info;
3208 if (session_info == NULL) {
3209 return NT_STATUS_INVALID_HANDLE;
3212 set_current_user_info(session_info->unix_info->sanitized_username,
3213 session_info->unix_info->unix_name,
3214 session_info->info->domain_name);
3217 if (req->session) {
3218 bool update_session_global = false;
3219 bool update_tcon_global = false;
3221 smb2srv_update_crypto_flags(req, opcode,
3222 &update_session_global,
3223 &update_tcon_global);
3225 if (update_session_global) {
3226 status = smbXsrv_session_update(x);
3227 if (!NT_STATUS_IS_OK(status)) {
3228 return smbd_smb2_request_error(req, status);
3231 if (update_tcon_global) {
3232 status = smbXsrv_tcon_update(req->tcon);
3233 if (!NT_STATUS_IS_OK(status)) {
3234 return smbd_smb2_request_error(req, status);
3239 if (call->fileid_ofs != 0) {
3240 size_t needed = call->fileid_ofs + 16;
3241 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
3242 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
3243 uint64_t file_id_persistent;
3244 uint64_t file_id_volatile;
3245 struct files_struct *fsp;
3247 SMB_ASSERT(call->need_tcon);
3249 if (needed > body_size) {
3250 return smbd_smb2_request_error(req,
3251 NT_STATUS_INVALID_PARAMETER);
3254 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
3255 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
3257 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
3258 if (fsp == NULL) {
3259 if (!call->allow_invalid_fileid) {
3260 return smbd_smb2_request_error(req,
3261 NT_STATUS_FILE_CLOSED);
3264 if (file_id_persistent != UINT64_MAX) {
3265 return smbd_smb2_request_error(req,
3266 NT_STATUS_FILE_CLOSED);
3268 if (file_id_volatile != UINT64_MAX) {
3269 return smbd_smb2_request_error(req,
3270 NT_STATUS_FILE_CLOSED);
3272 } else {
3273 if (fsp->fsp_flags.encryption_required && !req->was_encrypted) {
3274 return smbd_smb2_request_error(req,
3275 NT_STATUS_ACCESS_DENIED);
3280 status = smbd_smb2_request_dispatch_update_counts(req, call->modify);
3281 if (!NT_STATUS_IS_OK(status)) {
3282 return smbd_smb2_request_error(req, status);
3285 if (call->as_root) {
3286 SMB_ASSERT(call->fileid_ofs == 0);
3287 /* This call needs to be run as root */
3288 change_to_root_user();
3289 } else {
3290 SMB_ASSERT(call->need_tcon);
3293 #define _INBYTES(_r) \
3294 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
3296 switch (opcode) {
3297 case SMB2_OP_NEGPROT:
3298 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
3299 req->profile, _INBYTES(req));
3300 return_value = smbd_smb2_request_process_negprot(req);
3301 break;
3303 case SMB2_OP_SESSSETUP:
3304 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
3305 req->profile, _INBYTES(req));
3306 return_value = smbd_smb2_request_process_sesssetup(req);
3307 break;
3309 case SMB2_OP_LOGOFF:
3310 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
3311 req->profile, _INBYTES(req));
3312 return_value = smbd_smb2_request_process_logoff(req);
3313 break;
3315 case SMB2_OP_TCON:
3316 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
3317 req->profile, _INBYTES(req));
3318 return_value = smbd_smb2_request_process_tcon(req);
3319 break;
3321 case SMB2_OP_TDIS:
3322 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
3323 req->profile, _INBYTES(req));
3324 return_value = smbd_smb2_request_process_tdis(req);
3325 break;
3327 case SMB2_OP_CREATE:
3328 if (req->subreq == NULL) {
3329 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
3330 req->profile, _INBYTES(req));
3331 } else {
3332 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
3334 return_value = smbd_smb2_request_process_create(req);
3335 break;
3337 case SMB2_OP_CLOSE:
3338 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
3339 req->profile, _INBYTES(req));
3340 return_value = smbd_smb2_request_process_close(req);
3341 break;
3343 case SMB2_OP_FLUSH:
3344 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
3345 req->profile, _INBYTES(req));
3346 return_value = smbd_smb2_request_process_flush(req);
3347 break;
3349 case SMB2_OP_READ:
3350 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
3351 req->profile, _INBYTES(req));
3352 return_value = smbd_smb2_request_process_read(req);
3353 break;
3355 case SMB2_OP_WRITE:
3356 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
3357 req->profile, _INBYTES(req));
3358 return_value = smbd_smb2_request_process_write(req);
3359 break;
3361 case SMB2_OP_LOCK:
3362 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
3363 req->profile, _INBYTES(req));
3364 return_value = smbd_smb2_request_process_lock(req);
3365 break;
3367 case SMB2_OP_IOCTL:
3368 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
3369 req->profile, _INBYTES(req));
3370 return_value = smbd_smb2_request_process_ioctl(req);
3371 break;
3373 case SMB2_OP_CANCEL:
3374 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
3375 req->profile, _INBYTES(req));
3376 return_value = smbd_smb2_request_process_cancel(req);
3377 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
3380 * We don't need the request anymore cancel requests never
3381 * have a response.
3383 * smbd_smb2_request_process_cancel() already called
3384 * DLIST_REMOVE(xconn->smb2.requests, req);
3386 TALLOC_FREE(req);
3388 break;
3390 case SMB2_OP_KEEPALIVE:
3391 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
3392 req->profile, _INBYTES(req));
3393 return_value = smbd_smb2_request_process_keepalive(req);
3394 break;
3396 case SMB2_OP_QUERY_DIRECTORY:
3397 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
3398 req->profile, _INBYTES(req));
3399 return_value = smbd_smb2_request_process_query_directory(req);
3400 break;
3402 case SMB2_OP_NOTIFY:
3403 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
3404 req->profile, _INBYTES(req));
3405 return_value = smbd_smb2_request_process_notify(req);
3406 break;
3408 case SMB2_OP_GETINFO:
3409 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
3410 req->profile, _INBYTES(req));
3411 return_value = smbd_smb2_request_process_getinfo(req);
3412 break;
3414 case SMB2_OP_SETINFO:
3415 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
3416 req->profile, _INBYTES(req));
3417 return_value = smbd_smb2_request_process_setinfo(req);
3418 break;
3420 case SMB2_OP_BREAK:
3421 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
3422 req->profile, _INBYTES(req));
3423 return_value = smbd_smb2_request_process_break(req);
3424 break;
3426 default:
3427 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
3428 break;
3430 return return_value;
3433 static void smbd_smb2_request_reply_update_counts(struct smbd_smb2_request *req)
3435 struct smbXsrv_connection *xconn = req->xconn;
3436 const uint8_t *inhdr;
3437 uint16_t channel_sequence;
3438 struct smbXsrv_open *op;
3440 if (!req->request_counters_updated) {
3441 return;
3444 req->request_counters_updated = false;
3446 if (xconn->protocol < PROTOCOL_SMB2_22) {
3447 return;
3450 if (req->compat_chain_fsp == NULL) {
3451 return;
3454 op = req->compat_chain_fsp->op;
3455 if (op == NULL) {
3456 return;
3459 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
3460 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
3462 if ((op->global->channel_sequence == channel_sequence) &&
3463 (op->global->channel_generation == req->channel_generation)) {
3464 SMB_ASSERT(op->request_count > 0);
3465 op->request_count -= 1;
3466 } else {
3467 SMB_ASSERT(op->pre_request_count > 0);
3468 op->pre_request_count -= 1;
3472 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
3474 struct smbXsrv_connection *xconn = req->xconn;
3475 int first_idx = 1;
3476 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
3477 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
3478 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
3479 NTSTATUS status;
3480 bool ok;
3482 req->subreq = NULL;
3483 TALLOC_FREE(req->async_te);
3485 /* MS-SMB2: 3.3.4.1 Sending Any Outgoing Message */
3486 smbd_smb2_request_reply_update_counts(req);
3488 if (req->do_encryption &&
3489 (firsttf->iov_len == 0) &&
3490 (req->first_key.length == 0) &&
3491 (req->session != NULL) &&
3492 smb2_signing_key_valid(req->session->global->encryption_key))
3494 struct smb2_signing_key *encryption_key =
3495 req->session->global->encryption_key;
3496 uint8_t *tf;
3497 uint64_t session_id = req->session->global->session_wire_id;
3498 uint64_t nonce_high;
3499 uint64_t nonce_low;
3501 status = smb2_get_new_nonce(req->session,
3502 &nonce_high,
3503 &nonce_low);
3504 if (!NT_STATUS_IS_OK(status)) {
3505 return status;
3509 * We need to place the SMB2_TRANSFORM header before the
3510 * first SMB2 header
3514 * we need to remember the encryption key
3515 * and defer the signing/encryption until
3516 * we are sure that we do not change
3517 * the header again.
3519 req->first_key = data_blob_dup_talloc(req,
3520 encryption_key->blob);
3521 if (req->first_key.data == NULL) {
3522 return NT_STATUS_NO_MEMORY;
3525 tf = talloc_zero_array(req, uint8_t,
3526 SMB2_TF_HDR_SIZE);
3527 if (tf == NULL) {
3528 return NT_STATUS_NO_MEMORY;
3531 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
3532 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
3533 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
3534 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
3536 firsttf->iov_base = (void *)tf;
3537 firsttf->iov_len = SMB2_TF_HDR_SIZE;
3540 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
3541 (req->last_key.length > 0) &&
3542 (firsttf->iov_len == 0))
3544 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
3545 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
3546 struct smb2_signing_key key = {
3547 .blob = req->last_key,
3551 * As we are sure the header of the last request in the
3552 * compound chain will not change, we can to sign here
3553 * with the last signing key we remembered.
3555 status = smb2_signing_sign_pdu(&key,
3556 xconn->protocol,
3557 lasthdr,
3558 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
3559 smb2_signing_key_destructor(&key);
3560 if (!NT_STATUS_IS_OK(status)) {
3561 return status;
3564 if (req->last_key.length > 0) {
3565 data_blob_clear_free(&req->last_key);
3568 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
3569 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
3571 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
3573 if (req->current_idx < req->out.vector_count) {
3575 * We must process the remaining compound
3576 * SMB2 requests before any new incoming SMB2
3577 * requests. This is because incoming SMB2
3578 * requests may include a cancel for a
3579 * compound request we haven't processed
3580 * yet.
3582 struct tevent_immediate *im = tevent_create_immediate(req);
3583 if (!im) {
3584 return NT_STATUS_NO_MEMORY;
3587 if (req->do_signing && firsttf->iov_len == 0) {
3588 struct smbXsrv_session *x = req->session;
3589 struct smb2_signing_key *signing_key =
3590 smbd_smb2_signing_key(x, xconn);
3593 * we need to remember the signing key
3594 * and defer the signing until
3595 * we are sure that we do not change
3596 * the header again.
3598 req->last_key = data_blob_dup_talloc(req,
3599 signing_key->blob);
3600 if (req->last_key.data == NULL) {
3601 return NT_STATUS_NO_MEMORY;
3606 * smbd_smb2_request_dispatch() will redo the impersonation.
3607 * So we use req->xconn->client->raw_ev_ctx instead
3608 * of req->ev_ctx here.
3610 tevent_schedule_immediate(im,
3611 req->xconn->client->raw_ev_ctx,
3612 smbd_smb2_request_dispatch_immediate,
3613 req);
3614 return NT_STATUS_OK;
3617 if (req->compound_related) {
3618 req->compound_related = false;
3621 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
3622 if (!ok) {
3623 return NT_STATUS_INVALID_PARAMETER_MIX;
3626 /* Set credit for these operations (zero credits if this
3627 is a final reply for an async operation). */
3628 smb2_calculate_credits(req, req);
3631 * now check if we need to sign the current response
3633 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
3634 struct smb2_signing_key key = {
3635 .blob = req->first_key,
3637 status = smb2_signing_encrypt_pdu(&key,
3638 xconn->smb2.server.cipher,
3639 firsttf,
3640 req->out.vector_count - first_idx);
3641 smb2_signing_key_destructor(&key);
3642 if (!NT_STATUS_IS_OK(status)) {
3643 return status;
3645 } else if (req->do_signing) {
3646 struct smbXsrv_session *x = req->session;
3647 struct smb2_signing_key *signing_key =
3648 smbd_smb2_signing_key(x, xconn);
3650 status = smb2_signing_sign_pdu(signing_key,
3651 xconn->protocol,
3652 outhdr,
3653 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
3654 if (!NT_STATUS_IS_OK(status)) {
3655 return status;
3658 if (req->first_key.length > 0) {
3659 data_blob_clear_free(&req->first_key);
3662 if (req->preauth != NULL) {
3663 gnutls_hash_hd_t hash_hnd = NULL;
3664 size_t i;
3665 int rc;
3667 rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_SHA512);
3668 if (rc < 0) {
3669 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3671 rc = gnutls_hash(hash_hnd,
3672 req->preauth->sha512_value,
3673 sizeof(req->preauth->sha512_value));
3674 if (rc < 0) {
3675 gnutls_hash_deinit(hash_hnd, NULL);
3676 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3678 for (i = 1; i < req->in.vector_count; i++) {
3679 rc = gnutls_hash(hash_hnd,
3680 req->in.vector[i].iov_base,
3681 req->in.vector[i].iov_len);
3682 if (rc < 0) {
3683 gnutls_hash_deinit(hash_hnd, NULL);
3684 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3687 if (rc < 0) {
3688 gnutls_hash_deinit(hash_hnd, NULL);
3689 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3691 gnutls_hash_output(hash_hnd, req->preauth->sha512_value);
3693 rc = gnutls_hash(hash_hnd,
3694 req->preauth->sha512_value,
3695 sizeof(req->preauth->sha512_value));
3696 if (rc < 0) {
3697 gnutls_hash_deinit(hash_hnd, NULL);
3698 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3700 for (i = 1; i < req->out.vector_count; i++) {
3701 rc = gnutls_hash(hash_hnd,
3702 req->out.vector[i].iov_base,
3703 req->out.vector[i].iov_len);
3704 if (rc < 0) {
3705 gnutls_hash_deinit(hash_hnd, NULL);
3706 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3710 gnutls_hash_deinit(hash_hnd, req->preauth->sha512_value);
3712 req->preauth = NULL;
3715 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
3716 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
3717 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
3718 /* Dynamic part is NULL. Chop it off,
3719 We're going to send it via sendfile. */
3720 req->out.vector_count -= 1;
3724 * We're done with this request -
3725 * move it off the "being processed" queue.
3727 DLIST_REMOVE(xconn->smb2.requests, req);
3729 req->queue_entry.mem_ctx = req;
3730 req->queue_entry.vector = req->out.vector;
3731 req->queue_entry.count = req->out.vector_count;
3732 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry);
3733 xconn->smb2.send_queue_len++;
3735 status = smbd_smb2_flush_send_queue(xconn);
3736 if (!NT_STATUS_IS_OK(status)) {
3737 return status;
3740 return NT_STATUS_OK;
3743 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
3745 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
3746 struct tevent_immediate *im,
3747 void *private_data)
3749 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
3750 struct smbd_smb2_request);
3751 struct smbXsrv_connection *xconn = req->xconn;
3752 NTSTATUS status;
3754 TALLOC_FREE(im);
3756 if (DEBUGLEVEL >= 10) {
3757 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
3758 req->current_idx, req->in.vector_count));
3759 print_req_vectors(req);
3762 status = smbd_smb2_request_dispatch(req);
3763 if (!NT_STATUS_IS_OK(status)) {
3764 smbd_server_connection_terminate(xconn, nt_errstr(status));
3765 return;
3768 status = smbd_smb2_request_next_incoming(xconn);
3769 if (!NT_STATUS_IS_OK(status)) {
3770 smbd_server_connection_terminate(xconn, nt_errstr(status));
3771 return;
3775 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
3776 NTSTATUS status,
3777 DATA_BLOB body, DATA_BLOB *dyn,
3778 const char *location)
3780 uint8_t *outhdr;
3781 struct iovec *outbody_v;
3782 struct iovec *outdyn_v;
3783 uint32_t next_command_ofs;
3784 uint64_t mid;
3786 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3787 mid = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
3789 DBG_DEBUG("mid [%"PRIu64"] idx[%d] status[%s] "
3790 "body[%u] dyn[%s:%u] at %s\n",
3791 mid,
3792 req->current_idx,
3793 nt_errstr(status),
3794 (unsigned int)body.length,
3795 dyn ? "yes" : "no",
3796 (unsigned int)(dyn ? dyn->length : 0),
3797 location);
3799 if (body.length < 2) {
3800 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3803 if ((body.length % 2) != 0) {
3804 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3807 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
3808 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
3810 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
3811 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
3813 outbody_v->iov_base = (void *)body.data;
3814 outbody_v->iov_len = body.length;
3816 if (dyn) {
3817 outdyn_v->iov_base = (void *)dyn->data;
3818 outdyn_v->iov_len = dyn->length;
3819 } else {
3820 outdyn_v->iov_base = NULL;
3821 outdyn_v->iov_len = 0;
3825 * See if we need to recalculate the offset to the next response
3827 * Note that all responses may require padding (including the very last
3828 * one).
3830 if (req->out.vector_count >= (2 * SMBD_SMB2_NUM_IOV_PER_REQ)) {
3831 next_command_ofs = SMB2_HDR_BODY;
3832 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
3833 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
3836 if ((next_command_ofs % 8) != 0) {
3837 size_t pad_size = 8 - (next_command_ofs % 8);
3838 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
3840 * if the dyn buffer is empty
3841 * we can use it to add padding
3843 uint8_t *pad;
3845 pad = talloc_zero_array(req,
3846 uint8_t, pad_size);
3847 if (pad == NULL) {
3848 return smbd_smb2_request_error(req,
3849 NT_STATUS_NO_MEMORY);
3852 outdyn_v->iov_base = (void *)pad;
3853 outdyn_v->iov_len = pad_size;
3854 } else {
3856 * For now we copy the dynamic buffer
3857 * and add the padding to the new buffer
3859 size_t old_size;
3860 uint8_t *old_dyn;
3861 size_t new_size;
3862 uint8_t *new_dyn;
3864 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
3865 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
3867 new_size = old_size + pad_size;
3868 new_dyn = talloc_zero_array(req,
3869 uint8_t, new_size);
3870 if (new_dyn == NULL) {
3871 return smbd_smb2_request_error(req,
3872 NT_STATUS_NO_MEMORY);
3875 memcpy(new_dyn, old_dyn, old_size);
3876 memset(new_dyn + old_size, 0, pad_size);
3878 outdyn_v->iov_base = (void *)new_dyn;
3879 outdyn_v->iov_len = new_size;
3881 next_command_ofs += pad_size;
3884 if ((req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) >= req->out.vector_count) {
3885 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
3886 } else {
3887 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
3889 return smbd_smb2_request_reply(req);
3892 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
3893 NTSTATUS status,
3894 DATA_BLOB *info,
3895 const char *location)
3897 struct smbXsrv_connection *xconn = req->xconn;
3898 DATA_BLOB body;
3899 DATA_BLOB _dyn;
3900 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3901 size_t unread_bytes = smbd_smb2_unread_bytes(req);
3903 DBG_NOTICE("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| "
3904 "at %s\n", req->current_idx, nt_errstr(status),
3905 info ? " +info" : "", location);
3907 if (unread_bytes) {
3908 /* Recvfile error. Drain incoming socket. */
3909 size_t ret;
3911 errno = 0;
3912 ret = drain_socket(xconn->transport.sock, unread_bytes);
3913 if (ret != unread_bytes) {
3914 NTSTATUS error;
3916 if (errno == 0) {
3917 error = NT_STATUS_IO_DEVICE_ERROR;
3918 } else {
3919 error = map_nt_error_from_unix_common(errno);
3922 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
3923 "ret[%u] errno[%d] => %s\n",
3924 (unsigned)unread_bytes,
3925 (unsigned)ret, errno, nt_errstr(error)));
3926 return error;
3930 body.data = outhdr + SMB2_HDR_BODY;
3931 body.length = 8;
3932 SSVAL(body.data, 0, 9);
3934 if (info) {
3935 SIVAL(body.data, 0x04, info->length);
3936 } else {
3937 /* Allocated size of req->out.vector[i].iov_base
3938 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
3939 * 1 byte without having to do an alloc.
3941 info = &_dyn;
3942 info->data = ((uint8_t *)outhdr) +
3943 OUTVEC_ALLOC_SIZE - 1;
3944 info->length = 1;
3945 SCVAL(info->data, 0, 0);
3949 * Note: Even if there is an error, continue to process the request.
3950 * per MS-SMB2.
3953 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
3956 struct smbd_smb2_break_state {
3957 struct tevent_req *req;
3958 struct smbd_smb2_send_queue queue_entry;
3959 uint8_t nbt_hdr[NBT_HDR_SIZE];
3960 uint8_t hdr[SMB2_HDR_BODY];
3961 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
3964 static struct tevent_req *smbd_smb2_break_send(TALLOC_CTX *mem_ctx,
3965 struct tevent_context *ev,
3966 struct smbXsrv_connection *xconn,
3967 uint64_t session_id,
3968 const uint8_t *body,
3969 size_t body_len)
3971 struct tevent_req *req = NULL;
3972 struct smbd_smb2_break_state *state = NULL;
3973 NTSTATUS status;
3974 bool ok;
3976 req = tevent_req_create(mem_ctx, &state,
3977 struct smbd_smb2_break_state);
3978 if (req == NULL) {
3979 return NULL;
3982 state->req = req;
3983 tevent_req_defer_callback(req, ev);
3985 SIVAL(state->hdr, 0, SMB2_MAGIC);
3986 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
3987 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
3988 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
3989 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
3990 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
3991 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
3992 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
3993 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
3994 SIVAL(state->hdr, SMB2_HDR_PID, 0);
3995 SIVAL(state->hdr, SMB2_HDR_TID, 0);
3996 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, session_id);
3997 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
3999 state->vector[0] = (struct iovec) {
4000 .iov_base = state->nbt_hdr,
4001 .iov_len = sizeof(state->nbt_hdr)
4004 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
4005 .iov_base = NULL,
4006 .iov_len = 0
4009 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
4010 .iov_base = state->hdr,
4011 .iov_len = sizeof(state->hdr)
4014 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
4015 .iov_base = discard_const_p(uint8_t, body),
4016 .iov_len = body_len,
4020 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
4023 ok = smb2_setup_nbt_length(state->vector,
4024 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
4025 if (!ok) {
4026 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
4027 return tevent_req_post(req, ev);
4031 * We require TCP acks for this PDU to the client!
4032 * We want 5 retransmissions and timeout when the
4033 * retransmission timeout (rto) passed 6 times.
4035 * required_acked_bytes gets a dummy value of
4036 * UINT64_MAX, as long it's in xconn->smb2.send_queue,
4037 * it'll get the real value when it's moved to
4038 * xconn->ack.queue.
4040 * state->queue_entry.ack.req gets completed with
4041 * 1. tevent_req_done(), when all bytes are acked.
4042 * 2a. tevent_req_nterror(NT_STATUS_IO_TIMEOUT), when
4043 * the timeout expired before all bytes were acked.
4044 * 2b. tevent_req_nterror(transport_error), when the
4045 * connection got a disconnect from the kernel.
4047 state->queue_entry.ack.timeout =
4048 timeval_current_ofs_usec(xconn->ack.rto_usecs * 6);
4049 state->queue_entry.ack.required_acked_bytes = UINT64_MAX;
4050 state->queue_entry.ack.req = req;
4051 state->queue_entry.mem_ctx = state;
4052 state->queue_entry.vector = state->vector;
4053 state->queue_entry.count = ARRAY_SIZE(state->vector);
4054 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
4055 xconn->smb2.send_queue_len++;
4057 status = smbd_smb2_flush_send_queue(xconn);
4058 if (tevent_req_nterror(req, status)) {
4059 return tevent_req_post(req, ev);
4062 return req;
4065 static NTSTATUS smbd_smb2_break_recv(struct tevent_req *req)
4067 return tevent_req_simple_recv_ntstatus(req);
4070 struct smbXsrv_pending_break {
4071 struct smbXsrv_pending_break *prev, *next;
4072 struct smbXsrv_client *client;
4073 bool disable_oplock_break_retries;
4074 uint64_t session_id;
4075 uint64_t last_channel_id;
4076 union {
4077 uint8_t generic[1];
4078 uint8_t oplock[0x18];
4079 uint8_t lease[0x2c];
4080 } body;
4081 size_t body_len;
4084 static void smbXsrv_pending_break_done(struct tevent_req *subreq);
4086 static struct smbXsrv_pending_break *smbXsrv_pending_break_create(
4087 struct smbXsrv_client *client,
4088 uint64_t session_id)
4090 struct smbXsrv_pending_break *pb = NULL;
4092 pb = talloc_zero(client, struct smbXsrv_pending_break);
4093 if (pb == NULL) {
4094 return NULL;
4096 pb->client = client;
4097 pb->session_id = session_id;
4098 pb->disable_oplock_break_retries = lp_smb2_disable_oplock_break_retry();
4100 return pb;
4103 static NTSTATUS smbXsrv_pending_break_submit(struct smbXsrv_pending_break *pb);
4105 static NTSTATUS smbXsrv_pending_break_schedule(struct smbXsrv_pending_break *pb)
4107 struct smbXsrv_client *client = pb->client;
4108 NTSTATUS status;
4110 DLIST_ADD_END(client->pending_breaks, pb);
4111 status = smbXsrv_client_pending_breaks_updated(client);
4112 if (!NT_STATUS_IS_OK(status)) {
4113 return status;
4116 status = smbXsrv_pending_break_submit(pb);
4117 if (!NT_STATUS_IS_OK(status)) {
4118 return status;
4121 return NT_STATUS_OK;
4124 static NTSTATUS smbXsrv_pending_break_submit(struct smbXsrv_pending_break *pb)
4126 struct smbXsrv_client *client = pb->client;
4127 struct smbXsrv_session *session = NULL;
4128 struct smbXsrv_connection *xconn = NULL;
4129 struct smbXsrv_connection *oplock_xconn = NULL;
4130 struct tevent_req *subreq = NULL;
4131 NTSTATUS status;
4133 if (pb->session_id != 0) {
4134 status = get_valid_smbXsrv_session(client,
4135 pb->session_id,
4136 &session);
4137 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
4138 return NT_STATUS_ABANDONED;
4140 if (!NT_STATUS_IS_OK(status)) {
4141 return status;
4144 if (pb->last_channel_id != 0) {
4146 * This is what current Windows servers
4147 * do, they don't retry on all available
4148 * channels. They only use the last channel.
4150 * But it doesn't match the specification in
4151 * [MS-SMB2] "3.3.4.6 Object Store Indicates an
4152 * Oplock Break"
4154 * Per default disable_oplock_break_retries is false
4155 * and we behave like the specification.
4157 if (pb->disable_oplock_break_retries) {
4158 return NT_STATUS_ABANDONED;
4163 for (xconn = client->connections; xconn != NULL; xconn = xconn->next) {
4164 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
4165 continue;
4168 if (xconn->channel_id == 0) {
4170 * non-multichannel case
4172 break;
4175 if (session != NULL) {
4176 struct smbXsrv_channel_global0 *c = NULL;
4179 * Having a session means we're handling
4180 * an oplock break and we only need to
4181 * use channels available on the
4182 * session.
4184 status = smbXsrv_session_find_channel(session, xconn, &c);
4185 if (!NT_STATUS_IS_OK(status)) {
4186 continue;
4190 * This is what current Windows servers
4191 * do, they don't retry on all available
4192 * channels. They only use the last channel.
4194 * But it doesn't match the specification
4195 * in [MS-SMB2] "3.3.4.6 Object Store Indicates an
4196 * Oplock Break"
4198 * Per default disable_oplock_break_retries is false
4199 * and we behave like the specification.
4201 if (pb->disable_oplock_break_retries) {
4202 oplock_xconn = xconn;
4203 continue;
4207 if (xconn->channel_id > pb->last_channel_id) {
4209 * multichannel case
4211 break;
4215 if (xconn == NULL) {
4216 xconn = oplock_xconn;
4219 if (xconn == NULL) {
4221 * If there's no remaining connection available
4222 * tell the caller to stop...
4224 return NT_STATUS_ABANDONED;
4227 pb->last_channel_id = xconn->channel_id;
4229 subreq = smbd_smb2_break_send(pb,
4230 client->raw_ev_ctx,
4231 xconn,
4232 pb->session_id,
4233 pb->body.generic,
4234 pb->body_len);
4235 if (subreq == NULL) {
4236 return NT_STATUS_NO_MEMORY;
4238 tevent_req_set_callback(subreq,
4239 smbXsrv_pending_break_done,
4240 pb);
4242 return NT_STATUS_OK;
4245 static void smbXsrv_pending_break_done(struct tevent_req *subreq)
4247 struct smbXsrv_pending_break *pb =
4248 tevent_req_callback_data(subreq,
4249 struct smbXsrv_pending_break);
4250 struct smbXsrv_client *client = pb->client;
4251 NTSTATUS status;
4253 status = smbd_smb2_break_recv(subreq);
4254 TALLOC_FREE(subreq);
4255 if (!NT_STATUS_IS_OK(status)) {
4256 status = smbXsrv_pending_break_submit(pb);
4257 if (NT_STATUS_EQUAL(status, NT_STATUS_ABANDONED)) {
4259 * If there's no remaing connection
4260 * there's no need to send a break again.
4262 goto remove;
4264 if (!NT_STATUS_IS_OK(status)) {
4265 smbd_server_disconnect_client(client, nt_errstr(status));
4266 return;
4268 return;
4271 remove:
4272 DLIST_REMOVE(client->pending_breaks, pb);
4273 TALLOC_FREE(pb);
4275 status = smbXsrv_client_pending_breaks_updated(client);
4276 if (!NT_STATUS_IS_OK(status)) {
4277 smbd_server_disconnect_client(client, nt_errstr(status));
4278 return;
4282 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_client *client,
4283 struct smbXsrv_open *op,
4284 uint8_t oplock_level)
4286 struct smbXsrv_pending_break *pb = NULL;
4287 uint8_t *body = NULL;
4289 pb = smbXsrv_pending_break_create(client,
4290 op->compat->vuid);
4291 if (pb == NULL) {
4292 return NT_STATUS_NO_MEMORY;
4294 pb->body_len = sizeof(pb->body.oplock);
4295 body = pb->body.oplock;
4297 SSVAL(body, 0x00, pb->body_len);
4298 SCVAL(body, 0x02, oplock_level);
4299 SCVAL(body, 0x03, 0); /* reserved */
4300 SIVAL(body, 0x04, 0); /* reserved */
4301 SBVAL(body, 0x08, op->global->open_persistent_id);
4302 SBVAL(body, 0x10, op->global->open_volatile_id);
4304 return smbXsrv_pending_break_schedule(pb);
4307 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_client *client,
4308 uint16_t new_epoch,
4309 uint32_t lease_flags,
4310 struct smb2_lease_key *lease_key,
4311 uint32_t current_lease_state,
4312 uint32_t new_lease_state)
4314 struct smbXsrv_pending_break *pb = NULL;
4315 uint8_t *body = NULL;
4317 pb = smbXsrv_pending_break_create(client,
4318 0); /* no session_id */
4319 if (pb == NULL) {
4320 return NT_STATUS_NO_MEMORY;
4322 pb->body_len = sizeof(pb->body.lease);
4323 body = pb->body.lease;
4325 SSVAL(body, 0x00, pb->body_len);
4326 SSVAL(body, 0x02, new_epoch);
4327 SIVAL(body, 0x04, lease_flags);
4328 SBVAL(body, 0x08, lease_key->data[0]);
4329 SBVAL(body, 0x10, lease_key->data[1]);
4330 SIVAL(body, 0x18, current_lease_state);
4331 SIVAL(body, 0x1c, new_lease_state);
4332 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
4333 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
4334 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
4336 return smbXsrv_pending_break_schedule(pb);
4339 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
4341 NTSTATUS status;
4342 uint32_t flags;
4343 uint64_t file_id_persistent;
4344 uint64_t file_id_volatile;
4345 struct smbXsrv_open *op = NULL;
4346 struct files_struct *fsp = NULL;
4347 const uint8_t *body = NULL;
4350 * This is only called with a pktbuf
4351 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
4352 * bytes
4355 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
4356 /* Transform header. Cannot recvfile. */
4357 return false;
4359 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
4360 /* Not SMB2. Normal error path will cope. */
4361 return false;
4363 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
4364 /* Not SMB2. Normal error path will cope. */
4365 return false;
4367 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
4368 /* Needs to be a WRITE. */
4369 return false;
4371 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
4372 /* Chained. Cannot recvfile. */
4373 return false;
4375 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
4376 if (flags & SMB2_HDR_FLAG_CHAINED) {
4377 /* Chained. Cannot recvfile. */
4378 return false;
4380 if (flags & SMB2_HDR_FLAG_SIGNED) {
4381 /* Signed. Cannot recvfile. */
4382 return false;
4385 body = &state->pktbuf[SMB2_HDR_BODY];
4387 file_id_persistent = BVAL(body, 0x10);
4388 file_id_volatile = BVAL(body, 0x18);
4390 status = smb2srv_open_lookup(state->req->xconn,
4391 file_id_persistent,
4392 file_id_volatile,
4393 0, /* now */
4394 &op);
4395 if (!NT_STATUS_IS_OK(status)) {
4396 return false;
4399 fsp = op->compat;
4400 if (fsp == NULL) {
4401 return false;
4403 if (fsp->conn == NULL) {
4404 return false;
4407 if (IS_IPC(fsp->conn)) {
4408 return false;
4410 if (IS_PRINT(fsp->conn)) {
4411 return false;
4413 if (fsp->base_fsp != NULL) {
4414 return false;
4417 DEBUG(10,("Doing recvfile write len = %u\n",
4418 (unsigned int)(state->pktfull - state->pktlen)));
4420 return true;
4423 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
4425 struct smbd_server_connection *sconn = xconn->client->sconn;
4426 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
4427 size_t max_send_queue_len;
4428 size_t cur_send_queue_len;
4430 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
4432 * we're not supposed to do any io
4434 return NT_STATUS_OK;
4437 if (state->req != NULL) {
4439 * if there is already a tstream_readv_pdu
4440 * pending, we are done.
4442 return NT_STATUS_OK;
4445 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
4446 cur_send_queue_len = xconn->smb2.send_queue_len;
4448 if (cur_send_queue_len > max_send_queue_len) {
4450 * if we have a lot of requests to send,
4451 * we wait until they are on the wire until we
4452 * ask for the next request.
4454 return NT_STATUS_OK;
4457 /* ask for the next request */
4458 ZERO_STRUCTP(state);
4459 state->req = smbd_smb2_request_allocate(xconn);
4460 if (state->req == NULL) {
4461 return NT_STATUS_NO_MEMORY;
4463 state->req->sconn = sconn;
4464 state->req->xconn = xconn;
4465 state->min_recv_size = lp_min_receive_file_size();
4467 TEVENT_FD_READABLE(xconn->transport.fde);
4469 return NT_STATUS_OK;
4472 NTSTATUS smbd_smb2_process_negprot(struct smbXsrv_connection *xconn,
4473 uint64_t expected_seq_low,
4474 const uint8_t *inpdu, size_t size)
4476 struct smbd_server_connection *sconn = xconn->client->sconn;
4477 NTSTATUS status;
4478 struct smbd_smb2_request *req = NULL;
4480 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
4481 (unsigned int)size));
4483 status = smbd_initialize_smb2(xconn, expected_seq_low);
4484 if (!NT_STATUS_IS_OK(status)) {
4485 smbd_server_connection_terminate(xconn, nt_errstr(status));
4486 return status;
4490 * If a new connection joins the process, when we're
4491 * already in a "pending break cycle", we need to
4492 * turn on the ack checker on the new connection.
4494 status = smbXsrv_client_pending_breaks_updated(xconn->client);
4495 if (!NT_STATUS_IS_OK(status)) {
4497 * If there's a problem, we disconnect the whole
4498 * client with all connections here!
4500 * Instead of just the new connection.
4502 smbd_server_disconnect_client(xconn->client, nt_errstr(status));
4503 return status;
4506 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
4507 if (!NT_STATUS_IS_OK(status)) {
4508 smbd_server_connection_terminate(xconn, nt_errstr(status));
4509 return status;
4512 status = smbd_smb2_request_validate(req);
4513 if (!NT_STATUS_IS_OK(status)) {
4514 smbd_server_connection_terminate(xconn, nt_errstr(status));
4515 return status;
4518 status = smbd_smb2_request_setup_out(req);
4519 if (!NT_STATUS_IS_OK(status)) {
4520 smbd_server_connection_terminate(xconn, nt_errstr(status));
4521 return status;
4524 #ifdef WITH_PROFILE
4526 * this was already counted at the SMB1 layer =>
4527 * smbd_smb2_request_dispatch() should not count it twice.
4529 if (profile_p->values.request_stats.count > 0) {
4530 profile_p->values.request_stats.count--;
4532 #endif
4533 status = smbd_smb2_request_dispatch(req);
4534 if (!NT_STATUS_IS_OK(status)) {
4535 smbd_server_connection_terminate(xconn, nt_errstr(status));
4536 return status;
4539 status = smbd_smb2_request_next_incoming(xconn);
4540 if (!NT_STATUS_IS_OK(status)) {
4541 smbd_server_connection_terminate(xconn, nt_errstr(status));
4542 return status;
4545 sconn->num_requests++;
4546 return NT_STATUS_OK;
4549 static int socket_error_from_errno(int ret,
4550 int sys_errno,
4551 bool *retry)
4553 *retry = false;
4555 if (ret >= 0) {
4556 return 0;
4559 if (ret != -1) {
4560 return EIO;
4563 if (sys_errno == 0) {
4564 return EIO;
4567 if (sys_errno == EINTR) {
4568 *retry = true;
4569 return sys_errno;
4572 if (sys_errno == EINPROGRESS) {
4573 *retry = true;
4574 return sys_errno;
4577 if (sys_errno == EAGAIN) {
4578 *retry = true;
4579 return sys_errno;
4582 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
4583 if (sys_errno == ENOMEM) {
4584 *retry = true;
4585 return sys_errno;
4588 #ifdef EWOULDBLOCK
4589 #if EWOULDBLOCK != EAGAIN
4590 if (sys_errno == EWOULDBLOCK) {
4591 *retry = true;
4592 return sys_errno;
4594 #endif
4595 #endif
4597 return sys_errno;
4600 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
4602 int ret;
4603 int err;
4604 bool retry;
4605 NTSTATUS status;
4607 if (xconn->smb2.send_queue == NULL) {
4608 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
4609 return NT_STATUS_OK;
4612 while (xconn->smb2.send_queue != NULL) {
4613 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
4614 bool ok;
4615 struct msghdr msg;
4617 if (e->sendfile_header != NULL) {
4618 size_t size = 0;
4619 size_t i = 0;
4620 uint8_t *buf;
4622 status = NT_STATUS_INTERNAL_ERROR;
4624 for (i=0; i < e->count; i++) {
4625 size += e->vector[i].iov_len;
4628 if (size <= e->sendfile_header->length) {
4629 buf = e->sendfile_header->data;
4630 } else {
4631 buf = talloc_array(e->mem_ctx, uint8_t, size);
4632 if (buf == NULL) {
4633 return NT_STATUS_NO_MEMORY;
4637 size = 0;
4638 for (i=0; i < e->count; i++) {
4639 memcpy(buf+size,
4640 e->vector[i].iov_base,
4641 e->vector[i].iov_len);
4642 size += e->vector[i].iov_len;
4645 e->sendfile_header->data = buf;
4646 e->sendfile_header->length = size;
4647 e->sendfile_status = &status;
4648 e->count = 0;
4650 xconn->smb2.send_queue_len--;
4651 DLIST_REMOVE(xconn->smb2.send_queue, e);
4653 size += e->sendfile_body_size;
4656 * This triggers the sendfile path via
4657 * the destructor.
4659 talloc_free(e->mem_ctx);
4661 if (!NT_STATUS_IS_OK(status)) {
4662 smbXsrv_connection_disconnect_transport(xconn,
4663 status);
4664 return status;
4666 xconn->ack.unacked_bytes += size;
4667 continue;
4670 msg = (struct msghdr) {
4671 .msg_iov = e->vector,
4672 .msg_iovlen = e->count,
4675 ret = sendmsg(xconn->transport.sock, &msg, 0);
4676 if (ret == 0) {
4677 /* propagate end of file */
4678 return NT_STATUS_INTERNAL_ERROR;
4680 err = socket_error_from_errno(ret, errno, &retry);
4681 if (retry) {
4682 /* retry later */
4683 TEVENT_FD_WRITEABLE(xconn->transport.fde);
4684 return NT_STATUS_OK;
4686 if (err != 0) {
4687 status = map_nt_error_from_unix_common(err);
4688 smbXsrv_connection_disconnect_transport(xconn,
4689 status);
4690 return status;
4693 xconn->ack.unacked_bytes += ret;
4695 ok = iov_advance(&e->vector, &e->count, ret);
4696 if (!ok) {
4697 return NT_STATUS_INTERNAL_ERROR;
4700 if (e->count > 0) {
4701 /* we have more to write */
4702 TEVENT_FD_WRITEABLE(xconn->transport.fde);
4703 return NT_STATUS_OK;
4706 xconn->smb2.send_queue_len--;
4707 DLIST_REMOVE(xconn->smb2.send_queue, e);
4709 if (e->ack.req == NULL) {
4710 talloc_free(e->mem_ctx);
4711 continue;
4714 e->ack.required_acked_bytes = xconn->ack.unacked_bytes;
4715 DLIST_ADD_END(xconn->ack.queue, e);
4719 * Restart reads if we were blocked on
4720 * draining the send queue.
4723 status = smbd_smb2_request_next_incoming(xconn);
4724 if (!NT_STATUS_IS_OK(status)) {
4725 return status;
4728 return NT_STATUS_OK;
4731 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
4732 uint16_t fde_flags)
4734 struct smbd_server_connection *sconn = xconn->client->sconn;
4735 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
4736 struct smbd_smb2_request *req = NULL;
4737 size_t min_recvfile_size = UINT32_MAX;
4738 int ret;
4739 int err;
4740 bool retry;
4741 NTSTATUS status;
4742 NTTIME now;
4743 struct msghdr msg;
4745 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
4747 * we're not supposed to do any io
4749 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
4750 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
4751 return NT_STATUS_OK;
4754 if (fde_flags & TEVENT_FD_WRITE) {
4755 status = smbd_smb2_flush_send_queue(xconn);
4756 if (!NT_STATUS_IS_OK(status)) {
4757 return status;
4761 if (!(fde_flags & TEVENT_FD_READ)) {
4762 return NT_STATUS_OK;
4765 if (state->req == NULL) {
4766 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
4767 return NT_STATUS_OK;
4770 again:
4771 if (!state->hdr.done) {
4772 state->hdr.done = true;
4774 state->vector.iov_base = (void *)state->hdr.nbt;
4775 state->vector.iov_len = NBT_HDR_SIZE;
4778 msg = (struct msghdr) {
4779 .msg_iov = &state->vector,
4780 .msg_iovlen = 1,
4783 ret = recvmsg(xconn->transport.sock, &msg, 0);
4784 if (ret == 0) {
4785 /* propagate end of file */
4786 status = NT_STATUS_END_OF_FILE;
4787 smbXsrv_connection_disconnect_transport(xconn,
4788 status);
4789 return status;
4791 err = socket_error_from_errno(ret, errno, &retry);
4792 if (retry) {
4793 /* retry later */
4794 TEVENT_FD_READABLE(xconn->transport.fde);
4795 return NT_STATUS_OK;
4797 if (err != 0) {
4798 status = map_nt_error_from_unix_common(err);
4799 smbXsrv_connection_disconnect_transport(xconn,
4800 status);
4801 return status;
4804 if (ret < state->vector.iov_len) {
4805 uint8_t *base;
4806 base = (uint8_t *)state->vector.iov_base;
4807 base += ret;
4808 state->vector.iov_base = (void *)base;
4809 state->vector.iov_len -= ret;
4810 /* we have more to read */
4811 TEVENT_FD_READABLE(xconn->transport.fde);
4812 return NT_STATUS_OK;
4815 if (state->pktlen > 0) {
4816 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
4818 * Not a possible receivefile write.
4819 * Read the rest of the data.
4821 state->doing_receivefile = false;
4823 state->pktbuf = talloc_realloc(state->req,
4824 state->pktbuf,
4825 uint8_t,
4826 state->pktfull);
4827 if (state->pktbuf == NULL) {
4828 return NT_STATUS_NO_MEMORY;
4831 state->vector.iov_base = (void *)(state->pktbuf +
4832 state->pktlen);
4833 state->vector.iov_len = (state->pktfull -
4834 state->pktlen);
4836 state->pktlen = state->pktfull;
4837 goto again;
4841 * Either this is a receivefile write so we've
4842 * done a short read, or if not we have all the data.
4844 goto got_full;
4848 * Now we analyze the NBT header
4850 if (state->hdr.nbt[0] != 0x00) {
4851 state->min_recv_size = 0;
4853 state->pktfull = smb2_len(state->hdr.nbt);
4854 if (state->pktfull == 0) {
4855 goto got_full;
4858 if (state->min_recv_size != 0) {
4859 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
4860 min_recvfile_size += state->min_recv_size;
4863 if (state->pktfull > min_recvfile_size) {
4865 * Might be a receivefile write. Read the SMB2 HEADER +
4866 * SMB2_WRITE header first. Set 'doing_receivefile'
4867 * as we're *attempting* receivefile write. If this
4868 * turns out not to be a SMB2_WRITE request or otherwise
4869 * not suitable then we'll just read the rest of the data
4870 * the next time this function is called.
4872 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
4873 state->doing_receivefile = true;
4874 } else {
4875 state->pktlen = state->pktfull;
4878 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
4879 if (state->pktbuf == NULL) {
4880 return NT_STATUS_NO_MEMORY;
4883 state->vector.iov_base = (void *)state->pktbuf;
4884 state->vector.iov_len = state->pktlen;
4886 goto again;
4888 got_full:
4890 if (state->hdr.nbt[0] != 0x00) {
4891 DEBUG(1,("ignore NBT[0x%02X] msg\n",
4892 state->hdr.nbt[0]));
4894 req = state->req;
4895 ZERO_STRUCTP(state);
4896 state->req = req;
4897 state->min_recv_size = lp_min_receive_file_size();
4898 req = NULL;
4899 goto again;
4902 req = state->req;
4903 state->req = NULL;
4905 req->request_time = timeval_current();
4906 now = timeval_to_nttime(&req->request_time);
4908 status = smbd_smb2_inbuf_parse_compound(xconn,
4909 now,
4910 state->pktbuf,
4911 state->pktlen,
4912 req,
4913 &req->in.vector,
4914 &req->in.vector_count);
4915 if (!NT_STATUS_IS_OK(status)) {
4916 return status;
4919 if (state->doing_receivefile) {
4920 req->smb1req = talloc_zero(req, struct smb_request);
4921 if (req->smb1req == NULL) {
4922 return NT_STATUS_NO_MEMORY;
4924 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
4927 ZERO_STRUCTP(state);
4929 req->current_idx = 1;
4931 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
4932 req->current_idx, req->in.vector_count));
4934 status = smbd_smb2_request_validate(req);
4935 if (!NT_STATUS_IS_OK(status)) {
4936 return status;
4939 status = smbd_smb2_request_setup_out(req);
4940 if (!NT_STATUS_IS_OK(status)) {
4941 return status;
4944 status = smbd_smb2_request_dispatch(req);
4945 if (!NT_STATUS_IS_OK(status)) {
4946 return status;
4949 sconn->num_requests++;
4951 /* The timeout_processing function isn't run nearly
4952 often enough to implement 'max log size' without
4953 overrunning the size of the file by many megabytes.
4954 This is especially true if we are running at debug
4955 level 10. Checking every 50 SMB2s is a nice
4956 tradeoff of performance vs log file size overrun. */
4958 if ((sconn->num_requests % 50) == 0 &&
4959 need_to_check_log_size()) {
4960 change_to_root_user();
4961 check_log_size();
4964 status = smbd_smb2_request_next_incoming(xconn);
4965 if (!NT_STATUS_IS_OK(status)) {
4966 return status;
4969 return NT_STATUS_OK;
4972 static void smbd_smb2_connection_handler(struct tevent_context *ev,
4973 struct tevent_fd *fde,
4974 uint16_t flags,
4975 void *private_data)
4977 struct smbXsrv_connection *xconn =
4978 talloc_get_type_abort(private_data,
4979 struct smbXsrv_connection);
4980 NTSTATUS status;
4982 status = smbd_smb2_io_handler(xconn, flags);
4983 if (!NT_STATUS_IS_OK(status)) {
4984 smbd_server_connection_terminate(xconn, nt_errstr(status));
4985 return;