ctdb-server: Remove duplicate logic
[samba4-gss.git] / source3 / smbd / smb2_server.c
blob610d79e5760dda44f321e224fd39efa071e90f12
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 "source3/smbd/smbXsrv_session.h"
27 #include "smbd/smbXsrv_open.h"
28 #include "lib/param/param.h"
29 #include "../libcli/smb/smb_common.h"
30 #include "../lib/tsocket/tsocket.h"
31 #include "../lib/util/tevent_ntstatus.h"
32 #include "smbprofile.h"
33 #include "../lib/util/bitmap.h"
34 #include "../librpc/gen_ndr/krb5pac.h"
35 #include "lib/util/iov_buf.h"
36 #include "auth.h"
37 #include "libcli/smb/smbXcli_base.h"
38 #include "source3/lib/substitute.h"
40 #if defined(LINUX)
41 /* SIOCOUTQ TIOCOUTQ are the same */
42 #define __IOCTL_SEND_QUEUE_SIZE_OPCODE TIOCOUTQ
43 #define __HAVE_TCP_INFO_RTO 1
44 #define __ALLOW_MULTI_CHANNEL_SUPPORT 1
45 #elif defined(FREEBSD)
46 #define __IOCTL_SEND_QUEUE_SIZE_OPCODE FIONWRITE
47 #define __HAVE_TCP_INFO_RTO 1
48 #define __ALLOW_MULTI_CHANNEL_SUPPORT 1
49 #endif
51 #include "lib/crypto/gnutls_helpers.h"
52 #include <gnutls/gnutls.h>
53 #include <gnutls/crypto.h>
55 #undef DBGC_CLASS
56 #define DBGC_CLASS DBGC_SMB2
58 static void smbd_smb2_connection_handler(struct tevent_context *ev,
59 struct tevent_fd *fde,
60 uint16_t flags,
61 void *private_data);
62 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn);
64 static const struct smbd_smb2_dispatch_table {
65 uint16_t opcode;
66 uint16_t fileid_ofs;
67 bool need_session : 1;
68 bool need_tcon : 1;
69 bool as_root : 1;
70 bool modify : 1;
71 } smbd_smb2_table[] = {
73 .opcode = SMB2_OP_NEGPROT,
74 .as_root = true,
75 },{
76 .opcode = SMB2_OP_SESSSETUP,
77 .as_root = true,
78 },{
79 .opcode = SMB2_OP_LOGOFF,
80 .need_session = true,
81 .as_root = true,
82 },{
83 .opcode = SMB2_OP_TCON,
84 .need_session = true,
86 * This call needs to be run as root.
88 * smbd_smb2_request_process_tcon()
89 * calls make_connection_snum(), which will call
90 * change_to_user(), when needed.
92 .as_root = true,
93 },{
94 .opcode = SMB2_OP_TDIS,
95 .need_session = true,
96 .need_tcon = true,
97 .as_root = true,
98 },{
99 .opcode = SMB2_OP_CREATE,
100 .need_session = true,
101 .need_tcon = true,
103 .opcode = SMB2_OP_CLOSE,
104 .need_session = true,
105 .need_tcon = true,
106 .fileid_ofs = 0x08,
108 .opcode = SMB2_OP_FLUSH,
109 .need_session = true,
110 .need_tcon = true,
111 .fileid_ofs = 0x08,
113 .opcode = SMB2_OP_READ,
114 .need_session = true,
115 .need_tcon = true,
116 .fileid_ofs = 0x10,
118 .opcode = SMB2_OP_WRITE,
119 .need_session = true,
120 .need_tcon = true,
121 .fileid_ofs = 0x10,
122 .modify = true,
124 .opcode = SMB2_OP_LOCK,
125 .need_session = true,
126 .need_tcon = true,
127 .fileid_ofs = 0x08,
129 .opcode = SMB2_OP_IOCTL,
130 .need_session = true,
131 .need_tcon = true,
132 .fileid_ofs = 0x08,
133 .modify = true,
135 .opcode = SMB2_OP_CANCEL,
136 .as_root = true,
138 .opcode = SMB2_OP_KEEPALIVE,
140 .opcode = SMB2_OP_QUERY_DIRECTORY,
141 .need_session = true,
142 .need_tcon = true,
143 .fileid_ofs = 0x08,
145 .opcode = SMB2_OP_NOTIFY,
146 .need_session = true,
147 .need_tcon = true,
148 .fileid_ofs = 0x08,
150 .opcode = SMB2_OP_GETINFO,
151 .need_session = true,
152 .need_tcon = true,
153 .fileid_ofs = 0x18,
155 .opcode = SMB2_OP_SETINFO,
156 .need_session = true,
157 .need_tcon = true,
158 .fileid_ofs = 0x10,
159 .modify = true,
161 .opcode = SMB2_OP_BREAK,
162 .need_session = true,
163 .need_tcon = true,
165 * we do not set
166 * .fileid_ofs here
167 * as LEASE breaks does not
168 * have a file id
173 const char *smb2_opcode_name(uint16_t opcode)
175 const char *result = "Bad SMB2 opcode";
177 switch (opcode) {
178 case SMB2_OP_NEGPROT:
179 result = "SMB2_OP_NEGPROT";
180 break;
181 case SMB2_OP_SESSSETUP:
182 result = "SMB2_OP_SESSSETUP";
183 break;
184 case SMB2_OP_LOGOFF:
185 result = "SMB2_OP_LOGOFF";
186 break;
187 case SMB2_OP_TCON:
188 result = "SMB2_OP_TCON";
189 break;
190 case SMB2_OP_TDIS:
191 result = "SMB2_OP_TDIS";
192 break;
193 case SMB2_OP_CREATE:
194 result = "SMB2_OP_CREATE";
195 break;
196 case SMB2_OP_CLOSE:
197 result = "SMB2_OP_CLOSE";
198 break;
199 case SMB2_OP_FLUSH:
200 result = "SMB2_OP_FLUSH";
201 break;
202 case SMB2_OP_READ:
203 result = "SMB2_OP_READ";
204 break;
205 case SMB2_OP_WRITE:
206 result = "SMB2_OP_WRITE";
207 break;
208 case SMB2_OP_LOCK:
209 result = "SMB2_OP_LOCK";
210 break;
211 case SMB2_OP_IOCTL:
212 result = "SMB2_OP_IOCTL";
213 break;
214 case SMB2_OP_CANCEL:
215 result = "SMB2_OP_CANCEL";
216 break;
217 case SMB2_OP_KEEPALIVE:
218 result = "SMB2_OP_KEEPALIVE";
219 break;
220 case SMB2_OP_QUERY_DIRECTORY:
221 result = "SMB2_OP_QUERY_DIRECTORY";
222 break;
223 case SMB2_OP_NOTIFY:
224 result = "SMB2_OP_NOTIFY";
225 break;
226 case SMB2_OP_GETINFO:
227 result = "SMB2_OP_GETINFO";
228 break;
229 case SMB2_OP_SETINFO:
230 result = "SMB2_OP_SETINFO";
231 break;
232 case SMB2_OP_BREAK:
233 result = "SMB2_OP_BREAK";
234 break;
235 default:
236 break;
238 return result;
241 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
243 const struct smbd_smb2_dispatch_table *ret = NULL;
245 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
246 return NULL;
249 ret = &smbd_smb2_table[opcode];
251 SMB_ASSERT(ret->opcode == opcode);
253 return ret;
256 static void print_req_vectors(const struct smbd_smb2_request *req)
258 int i;
260 for (i = 0; i < req->in.vector_count; i++) {
261 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
262 (unsigned int)i,
263 (unsigned int)req->in.vector[i].iov_len);
265 for (i = 0; i < req->out.vector_count; i++) {
266 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
267 (unsigned int)i,
268 (unsigned int)req->out.vector[i].iov_len);
272 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
274 if (size < (4 + SMB2_HDR_BODY)) {
275 return false;
278 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
279 return false;
282 return true;
285 bool smbd_smb2_is_compound(const struct smbd_smb2_request *req)
287 return req->in.vector_count >= (2*SMBD_SMB2_NUM_IOV_PER_REQ);
290 bool smbd_smb2_is_last_in_compound(const struct smbd_smb2_request *req)
292 return (req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ ==
293 req->in.vector_count);
296 static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn,
297 uint64_t expected_seq_low)
299 int rc;
301 xconn->smb2.credits.seq_low = expected_seq_low;
302 xconn->smb2.credits.seq_range = 1;
303 xconn->smb2.credits.granted = 1;
304 xconn->smb2.credits.max = lp_smb2_max_credits();
305 xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
306 xconn->smb2.credits.max);
307 if (xconn->smb2.credits.bitmap == NULL) {
308 return NT_STATUS_NO_MEMORY;
311 tevent_fd_set_close_fn(xconn->transport.fde, NULL);
312 TALLOC_FREE(xconn->transport.fde);
314 xconn->transport.fde = tevent_add_fd(
315 xconn->client->raw_ev_ctx,
316 xconn,
317 xconn->transport.sock,
318 TEVENT_FD_ERROR | TEVENT_FD_READ,
319 smbd_smb2_connection_handler,
320 xconn);
321 if (xconn->transport.fde == NULL) {
322 close(xconn->transport.sock);
323 xconn->transport.sock = -1;
324 return NT_STATUS_NO_MEMORY;
326 tevent_fd_set_auto_close(xconn->transport.fde);
329 * Ensure child is set to non-blocking mode,
330 * unless the system supports MSG_DONTWAIT,
331 * if MSG_DONTWAIT is available we should force
332 * blocking mode.
334 #ifdef MSG_DONTWAIT
335 rc = set_blocking(xconn->transport.sock, true);
336 if (rc < 0) {
337 return NT_STATUS_INTERNAL_ERROR;
339 #else
340 rc = set_blocking(xconn->transport.sock, false);
341 if (rc < 0) {
342 return NT_STATUS_INTERNAL_ERROR;
344 #endif
346 return NT_STATUS_OK;
349 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
350 #define _smb2_setlen(_buf,len) do { \
351 uint8_t *buf = (uint8_t *)_buf; \
352 buf[0] = 0; \
353 buf[1] = ((len)&0xFF0000)>>16; \
354 buf[2] = ((len)&0xFF00)>>8; \
355 buf[3] = (len)&0xFF; \
356 } while (0)
358 static bool smb2_setup_nbt_length(struct iovec *vector, int count)
360 ssize_t len;
362 if (count == 0) {
363 return false;
366 len = iov_buflen(vector+1, count-1);
368 if ((len == -1) || (len > 0xFFFFFF)) {
369 return false;
372 _smb2_setlen(vector[0].iov_base, len);
373 return true;
376 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
378 TALLOC_FREE(req->first_enc_key);
379 TALLOC_FREE(req->last_sign_key);
380 return 0;
383 void smb2_request_set_async_internal(struct smbd_smb2_request *req,
384 bool async_internal)
386 req->async_internal = async_internal;
389 static struct smbd_smb2_request *smbd_smb2_request_allocate(struct smbXsrv_connection *xconn)
391 TALLOC_CTX *mem_pool;
392 struct smbd_smb2_request *req;
394 #if 0
395 /* Enable this to find subtle valgrind errors. */
396 mem_pool = talloc_init("smbd_smb2_request_allocate");
397 #else
398 mem_pool = talloc_tos();
399 #endif
400 if (mem_pool == NULL) {
401 return NULL;
404 req = talloc(mem_pool, struct smbd_smb2_request);
405 if (req == NULL) {
406 talloc_free(mem_pool);
407 return NULL;
409 talloc_reparent(mem_pool, xconn, req);
410 #if 0
411 TALLOC_FREE(mem_pool);
412 #endif
413 *req = (struct smbd_smb2_request) {
414 .sconn = xconn->client->sconn,
415 .xconn = xconn,
416 .last_session_id = UINT64_MAX,
417 .last_tid = UINT32_MAX,
420 talloc_set_destructor(req, smbd_smb2_request_destructor);
422 return req;
425 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
426 NTTIME now,
427 uint8_t *buf,
428 size_t buflen,
429 struct smbd_smb2_request *req,
430 struct iovec **piov,
431 int *pnum_iov)
433 TALLOC_CTX *mem_ctx = req;
434 struct iovec *iov;
435 int num_iov = 1;
436 size_t taken = 0;
437 uint8_t *first_hdr = buf;
438 size_t verified_buflen = 0;
439 uint8_t *tf = NULL;
440 size_t tf_len = 0;
443 * Note: index '0' is reserved for the transport protocol
445 iov = req->in._vector;
447 while (taken < buflen) {
448 size_t len = buflen - taken;
449 uint8_t *hdr = first_hdr + taken;
450 struct iovec *cur;
451 size_t full_size;
452 size_t next_command_ofs;
453 uint16_t body_size;
454 uint8_t *body = NULL;
455 uint32_t dyn_size;
456 uint8_t *dyn = NULL;
457 struct iovec *iov_alloc = NULL;
459 if (iov != req->in._vector) {
460 iov_alloc = iov;
463 if (verified_buflen > taken) {
464 len = verified_buflen - taken;
465 } else {
466 tf = NULL;
467 tf_len = 0;
470 if (len < 4) {
471 DEBUG(10, ("%d bytes left, expected at least %d\n",
472 (int)len, 4));
473 goto inval;
475 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
476 struct smbXsrv_session *s = NULL;
477 uint64_t uid;
478 struct iovec tf_iov[2];
479 NTSTATUS status;
480 size_t enc_len;
482 if (xconn->protocol < PROTOCOL_SMB3_00) {
483 DEBUG(10, ("Got SMB2_TRANSFORM header, "
484 "but dialect[0x%04X] is used\n",
485 xconn->smb2.server.dialect));
486 goto inval;
489 if (xconn->smb2.server.cipher == 0) {
490 DEBUG(10, ("Got SMB2_TRANSFORM header, "
491 "but not negotiated "
492 "client[0x%08X] server[0x%08X]\n",
493 xconn->smb2.client.capabilities,
494 xconn->smb2.server.capabilities));
495 goto inval;
498 if (!xconn->smb2.got_authenticated_session) {
499 D_INFO("Got SMB2_TRANSFORM header, "
500 "but not no authenticated session yet "
501 "client[%s] server[%s]\n",
502 tsocket_address_string(
503 xconn->remote_address, talloc_tos()),
504 tsocket_address_string(
505 xconn->local_address, talloc_tos()));
506 goto inval;
509 if (len < SMB2_TF_HDR_SIZE) {
510 DEBUG(1, ("%d bytes left, expected at least %d\n",
511 (int)len, SMB2_TF_HDR_SIZE));
512 goto inval;
514 tf = hdr;
515 tf_len = SMB2_TF_HDR_SIZE;
516 taken += tf_len;
518 hdr = first_hdr + taken;
519 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
520 uid = BVAL(tf, SMB2_TF_SESSION_ID);
522 if (len < SMB2_TF_HDR_SIZE + enc_len) {
523 DEBUG(1, ("%d bytes left, expected at least %d\n",
524 (int)len,
525 (int)(SMB2_TF_HDR_SIZE + enc_len)));
526 goto inval;
529 status = smb2srv_session_lookup_conn(xconn, uid, now,
530 &s);
531 if (!NT_STATUS_IS_OK(status)) {
532 status = smb2srv_session_lookup_global(xconn->client,
533 uid, req, &s);
535 if (!NT_STATUS_IS_OK(status)) {
536 DBG_WARNING("invalid session[%" PRIu64 "] in "
537 "SMB2_TRANSFORM header\n",
538 uid);
539 TALLOC_FREE(iov_alloc);
540 return NT_STATUS_USER_SESSION_DELETED;
543 tf_iov[0].iov_base = (void *)tf;
544 tf_iov[0].iov_len = tf_len;
545 tf_iov[1].iov_base = (void *)hdr;
546 tf_iov[1].iov_len = enc_len;
548 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
549 tf_iov, 2);
550 if (!NT_STATUS_IS_OK(status)) {
551 TALLOC_FREE(iov_alloc);
552 return status;
555 verified_buflen = taken + enc_len;
556 len = enc_len;
560 * We need the header plus the body length field
563 if (len < SMB2_HDR_BODY + 2) {
565 if ((len == 5) &&
566 (IVAL(hdr, 0) == SMB_SUICIDE_PACKET) &&
567 lp_parm_bool(-1, "smbd", "suicide mode", false)) {
568 uint8_t exitcode = CVAL(hdr, 4);
569 DBG_WARNING("SUICIDE: Exiting immediately "
570 "with code %"PRIu8"\n",
571 exitcode);
572 exit(exitcode);
575 DEBUG(10, ("%d bytes left, expected at least %d\n",
576 (int)len, SMB2_HDR_BODY));
577 goto inval;
579 if (IVAL(hdr, 0) != SMB2_MAGIC) {
580 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
581 IVAL(hdr, 0)));
582 goto inval;
584 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
585 DEBUG(10, ("Got HDR len %d, expected %d\n",
586 SVAL(hdr, 4), SMB2_HDR_BODY));
587 goto inval;
590 full_size = len;
591 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
592 body_size = SVAL(hdr, SMB2_HDR_BODY);
594 if (next_command_ofs != 0) {
595 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
596 goto inval;
598 if (next_command_ofs > full_size) {
599 goto inval;
601 full_size = next_command_ofs;
603 if (body_size < 2) {
604 goto inval;
606 body_size &= 0xfffe;
608 if (body_size > (full_size - SMB2_HDR_BODY)) {
610 * let the caller handle the error
612 body_size = full_size - SMB2_HDR_BODY;
614 body = hdr + SMB2_HDR_BODY;
615 dyn = body + body_size;
616 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
618 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
619 struct iovec *iov_tmp = NULL;
621 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
622 struct iovec,
623 num_iov +
624 SMBD_SMB2_NUM_IOV_PER_REQ);
625 if (iov_tmp == NULL) {
626 TALLOC_FREE(iov_alloc);
627 return NT_STATUS_NO_MEMORY;
630 if (iov_alloc == NULL) {
631 memcpy(iov_tmp,
632 req->in._vector,
633 sizeof(req->in._vector));
636 iov = iov_tmp;
638 cur = &iov[num_iov];
639 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
641 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
642 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
643 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
644 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
645 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
646 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
647 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
648 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
650 taken += full_size;
653 *piov = iov;
654 *pnum_iov = num_iov;
655 return NT_STATUS_OK;
657 inval:
658 if (iov != req->in._vector) {
659 TALLOC_FREE(iov);
661 return NT_STATUS_INVALID_PARAMETER;
664 static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
665 const uint8_t *_inpdu, size_t size,
666 struct smbd_smb2_request **_req)
668 struct smbd_smb2_request *req;
669 uint32_t protocol_version;
670 uint8_t *inpdu = NULL;
671 const uint8_t *inhdr = NULL;
672 uint16_t cmd;
673 uint32_t next_command_ofs;
674 NTSTATUS status;
675 NTTIME now;
677 if (size < (SMB2_HDR_BODY + 2)) {
678 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
679 return NT_STATUS_INVALID_PARAMETER;
682 inhdr = _inpdu;
684 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
685 if (protocol_version != SMB2_MAGIC) {
686 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
687 protocol_version));
688 return NT_STATUS_INVALID_PARAMETER;
691 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
692 if (cmd != SMB2_OP_NEGPROT) {
693 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
694 cmd));
695 return NT_STATUS_INVALID_PARAMETER;
698 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
699 if (next_command_ofs != 0) {
700 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
701 next_command_ofs));
702 return NT_STATUS_INVALID_PARAMETER;
705 req = smbd_smb2_request_allocate(xconn);
706 if (req == NULL) {
707 return NT_STATUS_NO_MEMORY;
710 inpdu = talloc_memdup(req, _inpdu, size);
711 if (inpdu == NULL) {
712 return NT_STATUS_NO_MEMORY;
715 req->request_time = timeval_current();
716 now = timeval_to_nttime(&req->request_time);
718 status = smbd_smb2_inbuf_parse_compound(xconn,
719 now,
720 inpdu,
721 size,
722 req, &req->in.vector,
723 &req->in.vector_count);
724 if (!NT_STATUS_IS_OK(status)) {
725 TALLOC_FREE(req);
726 return status;
729 req->current_idx = 1;
731 *_req = req;
732 return NT_STATUS_OK;
735 static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
736 uint64_t message_id, uint64_t seq_id)
738 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
739 unsigned int offset;
740 uint64_t seq_tmp;
742 seq_tmp = xconn->smb2.credits.seq_low;
743 if (seq_id < seq_tmp) {
744 DBGC_ERR(DBGC_SMB2_CREDITS,
745 "smb2_validate_sequence_number: bad message_id "
746 "%llu (sequence id %llu) "
747 "(granted = %u, low = %llu, range = %u)\n",
748 (unsigned long long)message_id,
749 (unsigned long long)seq_id,
750 (unsigned int)xconn->smb2.credits.granted,
751 (unsigned long long)xconn->smb2.credits.seq_low,
752 (unsigned int)xconn->smb2.credits.seq_range);
753 return false;
756 seq_tmp += xconn->smb2.credits.seq_range;
757 if (seq_id >= seq_tmp) {
758 DBGC_ERR(DBGC_SMB2_CREDITS,
759 "smb2_validate_sequence_number: bad message_id "
760 "%llu (sequence id %llu) "
761 "(granted = %u, low = %llu, range = %u)\n",
762 (unsigned long long)message_id,
763 (unsigned long long)seq_id,
764 (unsigned int)xconn->smb2.credits.granted,
765 (unsigned long long)xconn->smb2.credits.seq_low,
766 (unsigned int)xconn->smb2.credits.seq_range);
767 return false;
770 offset = seq_id % xconn->smb2.credits.max;
772 if (bitmap_query(credits_bm, offset)) {
773 DBGC_ERR(DBGC_SMB2_CREDITS,
774 "smb2_validate_sequence_number: duplicate message_id "
775 "%llu (sequence id %llu) "
776 "(granted = %u, low = %llu, range = %u) "
777 "(bm offset %u)\n",
778 (unsigned long long)message_id,
779 (unsigned long long)seq_id,
780 (unsigned int)xconn->smb2.credits.granted,
781 (unsigned long long)xconn->smb2.credits.seq_low,
782 (unsigned int)xconn->smb2.credits.seq_range,
783 offset);
784 return false;
787 /* Mark the message_ids as seen in the bitmap. */
788 bitmap_set(credits_bm, offset);
790 if (seq_id != xconn->smb2.credits.seq_low) {
791 return true;
795 * Move the window forward by all the message_id's
796 * already seen.
798 while (bitmap_query(credits_bm, offset)) {
799 DBGC_DEBUG(DBGC_SMB2_CREDITS,
800 "smb2_validate_sequence_number: clearing "
801 "id %llu (position %u) from bitmap\n",
802 (unsigned long long)(xconn->smb2.credits.seq_low),
803 offset);
804 bitmap_clear(credits_bm, offset);
806 xconn->smb2.credits.seq_low += 1;
807 xconn->smb2.credits.seq_range -= 1;
808 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
811 return true;
814 static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
815 const uint8_t *inhdr)
817 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
818 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
819 uint16_t credit_charge = 1;
820 uint64_t i;
822 if (opcode == SMB2_OP_CANCEL) {
823 /* SMB2_CANCEL requests by definition resend messageids. */
824 return true;
827 if (xconn->smb2.credits.multicredit) {
828 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
829 credit_charge = MAX(credit_charge, 1);
832 DEBUGC(11,
833 DBGC_SMB2_CREDITS,
834 ("smb2_validate_message_id: mid %llu (charge %llu), "
835 "credits_granted %llu, "
836 "seqnum low/range: %llu/%llu\n",
837 (unsigned long long) message_id,
838 (unsigned long long) credit_charge,
839 (unsigned long long) xconn->smb2.credits.granted,
840 (unsigned long long) xconn->smb2.credits.seq_low,
841 (unsigned long long) xconn->smb2.credits.seq_range));
843 if (xconn->smb2.credits.granted < credit_charge) {
844 DBGC_ERR(DBGC_SMB2_CREDITS,
845 "smb2_validate_message_id: client used more "
846 "credits than granted, mid %llu, charge %llu, "
847 "credits_granted %llu, "
848 "seqnum low/range: %llu/%llu\n",
849 (unsigned long long) message_id,
850 (unsigned long long) credit_charge,
851 (unsigned long long) xconn->smb2.credits.granted,
852 (unsigned long long) xconn->smb2.credits.seq_low,
853 (unsigned long long) xconn->smb2.credits.seq_range);
854 return false;
858 * now check the message ids
860 * for multi-credit requests we need to check all current mid plus
861 * the implicit mids caused by the credit charge
862 * e.g. current mid = 15, charge 5 => mark 15-19 as used
865 for (i = 0; i <= (credit_charge-1); i++) {
866 uint64_t id = message_id + i;
867 bool ok;
869 DEBUGC(11,
870 DBGC_SMB2_CREDITS,
871 ("Iterating mid %llu charge %u (sequence %llu)\n",
872 (unsigned long long)message_id,
873 credit_charge,
874 (unsigned long long)id));
876 ok = smb2_validate_sequence_number(xconn, message_id, id);
877 if (!ok) {
878 return false;
882 /* subtract used credits */
883 xconn->smb2.credits.granted -= credit_charge;
885 return true;
888 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
890 int count;
891 int idx;
893 count = req->in.vector_count;
895 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
896 /* It's not a SMB2 request */
897 return NT_STATUS_INVALID_PARAMETER;
900 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
901 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
902 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
903 const uint8_t *inhdr = NULL;
905 if (hdr->iov_len != SMB2_HDR_BODY) {
906 return NT_STATUS_INVALID_PARAMETER;
909 if (body->iov_len < 2) {
910 return NT_STATUS_INVALID_PARAMETER;
913 inhdr = (const uint8_t *)hdr->iov_base;
915 /* Check the SMB2 header */
916 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
917 return NT_STATUS_INVALID_PARAMETER;
920 if (!smb2_validate_message_id(req->xconn, inhdr)) {
921 return NT_STATUS_INVALID_PARAMETER;
925 return NT_STATUS_OK;
928 static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
929 const struct iovec *in_vector,
930 struct iovec *out_vector)
932 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
933 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
934 uint16_t credit_charge = 1;
935 uint16_t credits_requested;
936 uint32_t out_flags;
937 uint16_t cmd;
938 NTSTATUS out_status;
939 uint16_t credits_granted = 0;
940 uint64_t credits_possible;
941 uint16_t current_max_credits;
944 * first we grant only 1/16th of the max range.
946 * Windows also starts with the 1/16th and then grants
947 * more later. I was only able to trigger higher
948 * values, when using a very high credit charge.
950 * TODO: scale up depending on load, free memory
951 * or other stuff.
952 * Maybe also on the relationship between number
953 * of requests and the used sequence number.
954 * Which means we would grant more credits
955 * for client which use multi credit requests.
957 * The above is what Windows Server < 2016 is doing,
958 * but new servers use all credits (8192 by default).
960 current_max_credits = xconn->smb2.credits.max;
961 current_max_credits = MAX(current_max_credits, 1);
963 if (xconn->smb2.credits.multicredit) {
964 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
965 credit_charge = MAX(credit_charge, 1);
968 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
969 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
970 credits_requested = MAX(credits_requested, 1);
971 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
972 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
974 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
976 if (xconn->smb2.credits.max < credit_charge) {
977 smbd_server_connection_terminate(xconn,
978 "client error: credit charge > max credits\n");
979 return;
982 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
984 * In case we already send an async interim
985 * response, we should not grant
986 * credits on the final response.
988 credits_granted = 0;
989 } else {
990 uint16_t additional_possible =
991 xconn->smb2.credits.max - credit_charge;
992 uint16_t additional_max = 0;
993 uint16_t additional_credits = credits_requested - 1;
995 switch (cmd) {
996 case SMB2_OP_NEGPROT:
997 break;
998 case SMB2_OP_SESSSETUP:
1000 * Windows 2012 RC1 starts to grant
1001 * additional credits
1002 * with a successful session setup
1004 if (NT_STATUS_IS_OK(out_status)) {
1005 additional_max = xconn->smb2.credits.max;
1007 break;
1008 default:
1010 * Windows Server < 2016 and older Samba versions
1011 * used to only grant additional credits in
1012 * chunks of 32 credits.
1014 * But we match Windows Server 2016 and grant
1015 * all credits as requested.
1017 additional_max = xconn->smb2.credits.max;
1018 break;
1021 additional_max = MIN(additional_max, additional_possible);
1022 additional_credits = MIN(additional_credits, additional_max);
1024 credits_granted = credit_charge + additional_credits;
1028 * sequence numbers should not wrap
1030 * 1. calculate the possible credits until
1031 * the sequence numbers start to wrap on 64-bit.
1033 * 2. UINT64_MAX is used for Break Notifications.
1035 * 2. truncate the possible credits to the maximum
1036 * credits we want to grant to the client in total.
1038 * 3. remove the range we'll already granted to the client
1039 * this makes sure the client consumes the lowest sequence
1040 * number, before we can grant additional credits.
1042 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
1043 if (credits_possible > 0) {
1044 /* remove UINT64_MAX */
1045 credits_possible -= 1;
1047 credits_possible = MIN(credits_possible, current_max_credits);
1048 credits_possible -= xconn->smb2.credits.seq_range;
1050 credits_granted = MIN(credits_granted, credits_possible);
1052 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
1053 xconn->smb2.credits.granted += credits_granted;
1054 xconn->smb2.credits.seq_range += credits_granted;
1056 DBGC_DEBUG(DBGC_SMB2_CREDITS,
1057 "smb2_set_operation_credit: requested %u, charge %u, "
1058 "granted %u, current possible/max %u/%u, "
1059 "total granted/max/low/range %u/%u/%llu/%u\n",
1060 (unsigned int)credits_requested,
1061 (unsigned int)credit_charge,
1062 (unsigned int)credits_granted,
1063 (unsigned int)credits_possible,
1064 (unsigned int)current_max_credits,
1065 (unsigned int)xconn->smb2.credits.granted,
1066 (unsigned int)xconn->smb2.credits.max,
1067 (unsigned long long)xconn->smb2.credits.seq_low,
1068 (unsigned int)xconn->smb2.credits.seq_range);
1071 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
1072 struct smbd_smb2_request *outreq)
1074 int count, idx;
1075 uint16_t total_credits = 0;
1077 count = outreq->out.vector_count;
1079 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
1080 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
1081 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
1082 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
1084 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
1086 /* To match Windows, count up what we
1087 just granted. */
1088 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
1089 /* Set to zero in all but the last reply. */
1090 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
1091 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
1092 } else {
1093 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
1098 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
1100 if (req->current_idx <= 1) {
1101 if (size <= sizeof(req->out._body)) {
1102 return data_blob_const(req->out._body, size);
1106 return data_blob_talloc(req, NULL, size);
1109 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
1111 struct smbXsrv_connection *xconn = req->xconn;
1112 TALLOC_CTX *mem_ctx;
1113 struct iovec *vector;
1114 int count;
1115 int idx;
1116 bool ok;
1118 count = req->in.vector_count;
1119 if (count <= ARRAY_SIZE(req->out._vector)) {
1120 mem_ctx = req;
1121 vector = req->out._vector;
1122 } else {
1123 vector = talloc_zero_array(req, struct iovec, count);
1124 if (vector == NULL) {
1125 return NT_STATUS_NO_MEMORY;
1127 mem_ctx = vector;
1130 vector[0].iov_base = req->out.nbt_hdr;
1131 vector[0].iov_len = 4;
1132 SIVAL(req->out.nbt_hdr, 0, 0);
1134 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
1135 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
1136 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
1137 uint8_t *outhdr = NULL;
1138 uint8_t *outbody = NULL;
1139 uint32_t next_command_ofs = 0;
1140 struct iovec *current = &vector[idx];
1142 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
1143 /* we have a next command -
1144 * setup for the error case. */
1145 next_command_ofs = SMB2_HDR_BODY + 9;
1148 if (idx == 1) {
1149 outhdr = req->out._hdr;
1150 } else {
1151 outhdr = talloc_zero_array(mem_ctx, uint8_t,
1152 OUTVEC_ALLOC_SIZE);
1153 if (outhdr == NULL) {
1154 return NT_STATUS_NO_MEMORY;
1158 outbody = outhdr + SMB2_HDR_BODY;
1161 * SMBD_SMB2_TF_IOV_OFS might be used later
1163 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1164 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1166 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
1167 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1169 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1170 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1172 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1173 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1175 /* setup the SMB2 header */
1176 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1177 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1178 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1179 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1180 SIVAL(outhdr, SMB2_HDR_STATUS,
1181 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1182 SSVAL(outhdr, SMB2_HDR_OPCODE,
1183 SVAL(inhdr, SMB2_HDR_OPCODE));
1184 SIVAL(outhdr, SMB2_HDR_FLAGS,
1185 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1186 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1187 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1188 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1189 SIVAL(outhdr, SMB2_HDR_PID,
1190 IVAL(inhdr, SMB2_HDR_PID));
1191 SIVAL(outhdr, SMB2_HDR_TID,
1192 IVAL(inhdr, SMB2_HDR_TID));
1193 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1194 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1195 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1196 inhdr + SMB2_HDR_SIGNATURE, 16);
1198 /* setup error body header */
1199 SSVAL(outbody, 0x00, 0x08 + 1);
1200 SSVAL(outbody, 0x02, 0);
1201 SIVAL(outbody, 0x04, 0);
1204 req->out.vector = vector;
1205 req->out.vector_count = count;
1207 /* setup the length of the NBT packet */
1208 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1209 if (!ok) {
1210 return NT_STATUS_INVALID_PARAMETER_MIX;
1213 DLIST_ADD_END(xconn->smb2.requests, req);
1215 return NT_STATUS_OK;
1218 bool smbXsrv_server_multi_channel_enabled(void)
1220 bool enabled = lp_server_multi_channel_support();
1221 #ifndef __ALLOW_MULTI_CHANNEL_SUPPORT
1222 bool forced = false;
1223 struct loadparm_context *lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
1224 bool unspecified = lpcfg_parm_is_unspecified(lp_ctx, "server multi channel support");
1225 if (unspecified) {
1226 enabled = false;
1229 * If we don't have support from the kernel
1230 * to ask for the un-acked number of bytes
1231 * in the socket send queue, we better
1232 * don't support multi-channel.
1234 forced = lp_parm_bool(-1, "force", "server multi channel support", false);
1235 if (enabled && !forced) {
1236 D_NOTICE("'server multi channel support' enabled "
1237 "but not supported on %s (%s)\n",
1238 SYSTEM_UNAME_SYSNAME, SYSTEM_UNAME_RELEASE);
1239 DEBUGADD(DBGLVL_NOTICE, ("Please report this on "
1240 "https://bugzilla.samba.org/show_bug.cgi?id=11897\n"));
1241 enabled = false;
1243 TALLOC_FREE(lp_ctx);
1244 #endif /* ! __ALLOW_MULTI_CHANNEL_SUPPORT */
1245 return enabled;
1248 static NTSTATUS smbXsrv_connection_get_rto_usecs(struct smbXsrv_connection *xconn,
1249 uint32_t *_rto_usecs)
1252 * Define an Retransmission Timeout
1253 * of 1 second, if there's no way for the
1254 * kernel to tell us the current value.
1256 uint32_t rto_usecs = 1000000;
1258 #ifdef __HAVE_TCP_INFO_RTO
1260 struct tcp_info info;
1261 socklen_t ilen = sizeof(info);
1262 int ret;
1264 ZERO_STRUCT(info);
1265 ret = getsockopt(xconn->transport.sock,
1266 IPPROTO_TCP, TCP_INFO,
1267 (void *)&info, &ilen);
1268 if (ret != 0) {
1269 int saved_errno = errno;
1270 NTSTATUS status = map_nt_error_from_unix(errno);
1271 DBG_ERR("getsockopt(TCP_INFO) errno[%d/%s] -s %s\n",
1272 saved_errno, strerror(saved_errno),
1273 nt_errstr(status));
1274 return status;
1277 DBG_DEBUG("tcpi_rto[%u] tcpi_rtt[%u] tcpi_rttvar[%u]\n",
1278 (unsigned)info.tcpi_rto,
1279 (unsigned)info.tcpi_rtt,
1280 (unsigned)info.tcpi_rttvar);
1281 rto_usecs = info.tcpi_rto;
1283 #endif /* __HAVE_TCP_INFO_RTO */
1285 rto_usecs = MAX(rto_usecs, 200000); /* at least 0.2s */
1286 rto_usecs = MIN(rto_usecs, 1000000); /* at max 1.0s */
1287 *_rto_usecs = rto_usecs;
1288 return NT_STATUS_OK;
1291 static NTSTATUS smbXsrv_connection_get_acked_bytes(struct smbXsrv_connection *xconn,
1292 uint64_t *_acked_bytes)
1295 * Unless the kernel has an interface
1296 * to reveal the number of un-acked bytes
1297 * in the socket send queue, we'll assume
1298 * everything is already acked.
1300 * But that would mean that we better don't
1301 * pretent to support multi-channel.
1303 uint64_t unacked_bytes = 0;
1305 *_acked_bytes = 0;
1307 if (xconn->ack.force_unacked_timeout) {
1309 * Smbtorture tries to test channel failures...
1310 * Just pretend nothing was acked...
1312 DBG_INFO("Simulating channel failure: "
1313 "xconn->ack.unacked_bytes[%llu]\n",
1314 (unsigned long long)xconn->ack.unacked_bytes);
1315 return NT_STATUS_OK;
1318 #ifdef __IOCTL_SEND_QUEUE_SIZE_OPCODE
1320 int value = 0;
1321 int ret;
1324 * If we have kernel support to get
1325 * the number of bytes waiting in
1326 * the socket's send queue, we
1327 * use that in order to find out
1328 * the number of unacked bytes.
1330 ret = ioctl(xconn->transport.sock,
1331 __IOCTL_SEND_QUEUE_SIZE_OPCODE,
1332 &value);
1333 if (ret != 0) {
1334 int saved_errno = errno;
1335 NTSTATUS status = map_nt_error_from_unix(saved_errno);
1336 DBG_ERR("Failed to get the SEND_QUEUE_SIZE - "
1337 "errno %d (%s) - %s\n",
1338 saved_errno, strerror(saved_errno),
1339 nt_errstr(status));
1340 return status;
1343 if (value < 0) {
1344 DBG_ERR("xconn->ack.unacked_bytes[%llu] value[%d]\n",
1345 (unsigned long long)xconn->ack.unacked_bytes,
1346 value);
1347 return NT_STATUS_INTERNAL_ERROR;
1349 unacked_bytes = value;
1351 #endif
1352 if (xconn->ack.unacked_bytes == 0) {
1353 xconn->ack.unacked_bytes = unacked_bytes;
1354 return NT_STATUS_OK;
1357 if (xconn->ack.unacked_bytes < unacked_bytes) {
1358 DBG_ERR("xconn->ack.unacked_bytes[%llu] unacked_bytes[%llu]\n",
1359 (unsigned long long)xconn->ack.unacked_bytes,
1360 (unsigned long long)unacked_bytes);
1361 return NT_STATUS_INTERNAL_ERROR;
1364 *_acked_bytes = xconn->ack.unacked_bytes - unacked_bytes;
1365 xconn->ack.unacked_bytes = unacked_bytes;
1366 return NT_STATUS_OK;
1369 static void smbd_smb2_send_queue_ack_fail(struct smbd_smb2_send_queue **queue,
1370 NTSTATUS status)
1372 struct smbd_smb2_send_queue *e = NULL;
1373 struct smbd_smb2_send_queue *n = NULL;
1375 for (e = *queue; e != NULL; e = n) {
1376 n = e->next;
1378 DLIST_REMOVE(*queue, e);
1379 if (e->ack.req != NULL) {
1380 tevent_req_nterror(e->ack.req, status);
1385 static NTSTATUS smbd_smb2_send_queue_ack_bytes(struct smbd_smb2_send_queue **queue,
1386 uint64_t acked_bytes)
1388 struct smbd_smb2_send_queue *e = NULL;
1389 struct smbd_smb2_send_queue *n = NULL;
1391 for (e = *queue; e != NULL; e = n) {
1392 bool expired;
1394 n = e->next;
1396 if (e->ack.req == NULL) {
1397 continue;
1400 if (e->ack.required_acked_bytes <= acked_bytes) {
1401 e->ack.required_acked_bytes = 0;
1402 DLIST_REMOVE(*queue, e);
1403 tevent_req_done(e->ack.req);
1404 continue;
1406 e->ack.required_acked_bytes -= acked_bytes;
1408 expired = timeval_expired(&e->ack.timeout);
1409 if (expired) {
1410 return NT_STATUS_IO_TIMEOUT;
1414 return NT_STATUS_OK;
1417 static NTSTATUS smbd_smb2_check_ack_queue(struct smbXsrv_connection *xconn)
1419 uint64_t acked_bytes = 0;
1420 NTSTATUS status;
1422 status = smbXsrv_connection_get_acked_bytes(xconn, &acked_bytes);
1423 if (!NT_STATUS_IS_OK(status)) {
1424 return status;
1427 status = smbd_smb2_send_queue_ack_bytes(&xconn->ack.queue, acked_bytes);
1428 if (!NT_STATUS_IS_OK(status)) {
1429 return status;
1432 status = smbd_smb2_send_queue_ack_bytes(&xconn->smb2.send_queue, 0);
1433 if (!NT_STATUS_IS_OK(status)) {
1434 return status;
1437 return NT_STATUS_OK;
1440 static void smbXsrv_connection_ack_checker(struct tevent_req *subreq)
1442 struct smbXsrv_connection *xconn =
1443 tevent_req_callback_data(subreq,
1444 struct smbXsrv_connection);
1445 struct smbXsrv_client *client = xconn->client;
1446 struct timeval next_check;
1447 NTSTATUS status;
1448 bool ok;
1450 xconn->ack.checker_subreq = NULL;
1452 ok = tevent_wakeup_recv(subreq);
1453 TALLOC_FREE(subreq);
1454 if (!ok) {
1455 smbd_server_connection_terminate(xconn,
1456 "tevent_wakeup_recv() failed");
1457 return;
1460 status = smbd_smb2_check_ack_queue(xconn);
1461 if (!NT_STATUS_IS_OK(status)) {
1462 smbd_server_connection_terminate(xconn, nt_errstr(status));
1463 return;
1466 next_check = timeval_current_ofs_usec(xconn->ack.rto_usecs);
1467 xconn->ack.checker_subreq = tevent_wakeup_send(xconn,
1468 client->raw_ev_ctx,
1469 next_check);
1470 if (xconn->ack.checker_subreq == NULL) {
1471 smbd_server_connection_terminate(xconn,
1472 "tevent_wakeup_send() failed");
1473 return;
1475 tevent_req_set_callback(xconn->ack.checker_subreq,
1476 smbXsrv_connection_ack_checker,
1477 xconn);
1480 static NTSTATUS smbXsrv_client_pending_breaks_updated(struct smbXsrv_client *client)
1482 struct smbXsrv_connection *xconn = NULL;
1484 for (xconn = client->connections; xconn != NULL; xconn = xconn->next) {
1485 struct timeval next_check;
1486 uint64_t acked_bytes = 0;
1487 NTSTATUS status;
1490 * A new 'pending break cycle' starts
1491 * with a first pending break and lasts until
1492 * all pending breaks are finished.
1494 * This is typically a very short time,
1495 * the value of one retransmission timeout.
1498 if (client->pending_breaks == NULL) {
1500 * No more pending breaks, remove a pending
1501 * checker timer
1503 TALLOC_FREE(xconn->ack.checker_subreq);
1504 continue;
1507 if (xconn->ack.checker_subreq != NULL) {
1509 * The cycle already started =>
1510 * nothing todo
1512 continue;
1516 * Get the current retransmission timeout value.
1518 * It may change over time, but fetching it once
1519 * per 'pending break' cycled should be enough.
1521 status = smbXsrv_connection_get_rto_usecs(xconn,
1522 &xconn->ack.rto_usecs);
1523 if (!NT_STATUS_IS_OK(status)) {
1524 return status;
1528 * At the start of the cycle we reset the
1529 * unacked_bytes counter (first to 0 and
1530 * within smbXsrv_connection_get_acked_bytes()
1531 * to the current value in the kernel
1532 * send queue.
1534 xconn->ack.unacked_bytes = 0;
1535 status = smbXsrv_connection_get_acked_bytes(xconn, &acked_bytes);
1536 if (!NT_STATUS_IS_OK(status)) {
1537 return status;
1541 * We setup a timer in order to check for
1542 * acked bytes after one retransmission timeout.
1544 * The code that sets up the send_queue.ack.timeout
1545 * uses a multiple of the retransmission timeout.
1547 next_check = timeval_current_ofs_usec(xconn->ack.rto_usecs);
1548 xconn->ack.checker_subreq = tevent_wakeup_send(xconn,
1549 client->raw_ev_ctx,
1550 next_check);
1551 if (xconn->ack.checker_subreq == NULL) {
1552 return NT_STATUS_NO_MEMORY;
1554 tevent_req_set_callback(xconn->ack.checker_subreq,
1555 smbXsrv_connection_ack_checker,
1556 xconn);
1559 return NT_STATUS_OK;
1562 void smbXsrv_connection_disconnect_transport(struct smbXsrv_connection *xconn,
1563 NTSTATUS status)
1565 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
1566 return;
1569 xconn->transport.status = status;
1570 TALLOC_FREE(xconn->transport.fde);
1571 if (xconn->transport.sock != -1) {
1572 xconn->transport.sock = -1;
1574 smbd_smb2_send_queue_ack_fail(&xconn->ack.queue, status);
1575 smbd_smb2_send_queue_ack_fail(&xconn->smb2.send_queue, status);
1576 xconn->smb2.send_queue_len = 0;
1577 DO_PROFILE_INC(disconnect);
1580 size_t smbXsrv_client_valid_connections(struct smbXsrv_client *client)
1582 struct smbXsrv_connection *xconn = NULL;
1583 size_t num_ok = 0;
1585 for (xconn = client->connections; xconn != NULL; xconn = xconn->next) {
1586 if (NT_STATUS_IS_OK(xconn->transport.status)) {
1587 num_ok++;
1591 return num_ok;
1594 struct smbXsrv_connection_shutdown_state {
1595 struct smbXsrv_connection *xconn;
1598 static void smbXsrv_connection_shutdown_wait_done(struct tevent_req *subreq);
1600 static struct tevent_req *smbXsrv_connection_shutdown_send(TALLOC_CTX *mem_ctx,
1601 struct tevent_context *ev,
1602 struct smbXsrv_connection *xconn)
1604 struct tevent_req *req = NULL;
1605 struct smbXsrv_connection_shutdown_state *state = NULL;
1606 struct tevent_req *subreq = NULL;
1607 size_t len = 0;
1608 struct smbd_smb2_request *preq = NULL;
1609 NTSTATUS status;
1612 * The caller should have called
1613 * smbXsrv_connection_disconnect_transport() before.
1615 SMB_ASSERT(!NT_STATUS_IS_OK(xconn->transport.status));
1616 SMB_ASSERT(xconn->transport.terminating);
1617 SMB_ASSERT(xconn->transport.shutdown_wait_queue == NULL);
1619 req = tevent_req_create(mem_ctx, &state,
1620 struct smbXsrv_connection_shutdown_state);
1621 if (req == NULL) {
1622 return NULL;
1625 state->xconn = xconn;
1626 tevent_req_defer_callback(req, ev);
1628 xconn->transport.shutdown_wait_queue =
1629 tevent_queue_create(state, "smbXsrv_connection_shutdown_queue");
1630 if (tevent_req_nomem(xconn->transport.shutdown_wait_queue, req)) {
1631 return tevent_req_post(req, ev);
1634 for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
1636 * Now wait until the request is finished.
1638 * We don't set a callback, as we just want to block the
1639 * wait queue and the talloc_free() of the request will
1640 * remove the item from the wait queue.
1642 * Note that we don't cancel the requests here
1643 * in order to keep the replay detection logic correct.
1645 * However if we teardown the last channel of
1646 * a connection, we'll call some logic via
1647 * smbXsrv_session_disconnect_xconn()
1648 * -> smbXsrv_session_disconnect_xconn_callback()
1649 * -> smbXsrv_session_remove_channel()
1650 * -> smb2srv_session_shutdown_send()
1651 * will indeed cancel the request.
1653 subreq = tevent_queue_wait_send(preq, ev,
1654 xconn->transport.shutdown_wait_queue);
1655 if (tevent_req_nomem(subreq, req)) {
1656 return tevent_req_post(req, ev);
1661 * This may attach sessions with num_channels == 0
1662 * to xconn->transport.shutdown_wait_queue.
1664 status = smbXsrv_session_disconnect_xconn(xconn);
1665 if (tevent_req_nterror(req, status)) {
1666 return tevent_req_post(req, ev);
1669 len = tevent_queue_length(xconn->transport.shutdown_wait_queue);
1670 if (len == 0) {
1671 tevent_req_done(req);
1672 return tevent_req_post(req, ev);
1676 * Now we add our own waiter to the end of the queue,
1677 * this way we get notified when all pending requests are finished
1678 * and send to the socket.
1680 subreq = tevent_queue_wait_send(state, ev, xconn->transport.shutdown_wait_queue);
1681 if (tevent_req_nomem(subreq, req)) {
1682 return tevent_req_post(req, ev);
1684 tevent_req_set_callback(subreq, smbXsrv_connection_shutdown_wait_done, req);
1686 return req;
1689 static void smbXsrv_connection_shutdown_wait_done(struct tevent_req *subreq)
1691 struct tevent_req *req =
1692 tevent_req_callback_data(subreq,
1693 struct tevent_req);
1694 struct smbXsrv_connection_shutdown_state *state =
1695 tevent_req_data(req,
1696 struct smbXsrv_connection_shutdown_state);
1697 struct smbXsrv_connection *xconn = state->xconn;
1699 tevent_queue_wait_recv(subreq);
1700 TALLOC_FREE(subreq);
1702 tevent_req_done(req);
1704 * make sure the xconn pointer is still valid,
1705 * it should as we used tevent_req_defer_callback()
1707 SMB_ASSERT(xconn->transport.terminating);
1710 static NTSTATUS smbXsrv_connection_shutdown_recv(struct tevent_req *req)
1712 struct smbXsrv_connection_shutdown_state *state =
1713 tevent_req_data(req,
1714 struct smbXsrv_connection_shutdown_state);
1715 struct smbXsrv_connection *xconn = state->xconn;
1717 * make sure the xconn pointer is still valid,
1718 * it should as we used tevent_req_defer_callback()
1720 SMB_ASSERT(xconn->transport.terminating);
1721 return tevent_req_simple_recv_ntstatus(req);
1724 struct smbd_server_connection_terminate_state {
1725 struct smbXsrv_connection *xconn;
1726 char *reason;
1729 static void smbd_server_connection_terminate_done(struct tevent_req *subreq)
1731 struct smbd_server_connection_terminate_state *state =
1732 tevent_req_callback_data(
1733 subreq,
1734 struct smbd_server_connection_terminate_state);
1735 struct smbXsrv_connection *xconn = state->xconn;
1736 struct smbXsrv_client *client = xconn->client;
1737 const char *reason = state->reason;
1738 size_t num_ok;
1739 NTSTATUS status;
1741 status = smbXsrv_connection_shutdown_recv(subreq);
1742 TALLOC_FREE(subreq);
1743 if (!NT_STATUS_IS_OK(status)) {
1744 exit_server("smbXsrv_connection_shutdown_recv failed");
1747 DLIST_REMOVE(client->connections, xconn);
1748 TALLOC_FREE(xconn);
1750 num_ok = smbXsrv_client_valid_connections(client);
1751 if (num_ok > 0) {
1752 return;
1756 * The last connection was disconnected
1758 exit_server_cleanly(reason);
1761 void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
1762 const char *reason,
1763 const char *location)
1765 struct smbd_server_connection_terminate_state *state = NULL;
1766 struct smbXsrv_client *client = xconn->client;
1767 struct tevent_req *subreq = NULL;
1768 size_t num_ok = 0;
1770 state = talloc_zero(xconn, struct smbd_server_connection_terminate_state);
1771 if (state == NULL) {
1772 exit_server("smbXsrv_connection_shutdown_send failed");
1774 state->xconn = xconn;
1775 state->reason = talloc_strdup(state, reason);
1776 if (state->reason == NULL) {
1777 exit_server("talloc_strdup failed");
1781 * Make sure that no new request will be able to use this session.
1783 * smbXsrv_connection_disconnect_transport() might be called already,
1784 * but calling it again is a no-op.
1786 smbXsrv_connection_disconnect_transport(xconn,
1787 NT_STATUS_CONNECTION_DISCONNECTED);
1789 num_ok = smbXsrv_client_valid_connections(client);
1791 if (xconn->transport.terminating) {
1792 DBG_DEBUG("skip recursion conn[%s] num_ok[%zu] reason[%s] at %s\n",
1793 smbXsrv_connection_dbg(xconn), num_ok,
1794 reason, location);
1795 return;
1797 xconn->transport.terminating = true;
1799 DBG_DEBUG("conn[%s] num_ok[%zu] reason[%s] at %s\n",
1800 smbXsrv_connection_dbg(xconn), num_ok,
1801 reason, location);
1803 if (xconn->has_cluster_movable_ip) {
1805 * If the connection has a movable cluster public address
1806 * we disconnect all client connections,
1807 * as the public address might be moved to
1808 * a different node.
1810 * In future we may recheck which node currently
1811 * holds this address, but for now we keep it simple.
1813 smbd_server_disconnect_client_ex(xconn->client,
1814 reason,
1815 location);
1816 return;
1819 subreq = smbXsrv_connection_shutdown_send(client,
1820 client->raw_ev_ctx,
1821 xconn);
1822 if (subreq == NULL) {
1823 exit_server("smbXsrv_connection_shutdown_send failed");
1825 tevent_req_set_callback(subreq,
1826 smbd_server_connection_terminate_done,
1827 state);
1828 return;
1831 void smbd_server_disconnect_client_ex(struct smbXsrv_client *client,
1832 const char *reason,
1833 const char *location)
1835 size_t num_ok = 0;
1837 num_ok = smbXsrv_client_valid_connections(client);
1839 DBG_WARNING("client[%s] num_ok[%zu] reason[%s] at %s\n",
1840 client->global->remote_address, num_ok,
1841 reason, location);
1844 * Something bad happened we need to disconnect all connections.
1846 exit_server_cleanly(reason);
1849 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1850 struct iovec *outvec,
1851 const struct iovec *srcvec)
1853 const uint8_t *srctf;
1854 size_t srctf_len;
1855 const uint8_t *srchdr;
1856 size_t srchdr_len;
1857 const uint8_t *srcbody;
1858 size_t srcbody_len;
1859 const uint8_t *expected_srcbody;
1860 const uint8_t *srcdyn;
1861 size_t srcdyn_len;
1862 const uint8_t *expected_srcdyn;
1863 uint8_t *dsttf;
1864 uint8_t *dsthdr;
1865 uint8_t *dstbody;
1866 uint8_t *dstdyn;
1868 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1869 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1870 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1871 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1872 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1873 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1874 expected_srcbody = srchdr + SMB2_HDR_BODY;
1875 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1876 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1877 expected_srcdyn = srcbody + 8;
1879 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1880 return false;
1883 if (srchdr_len != SMB2_HDR_BODY) {
1884 return false;
1887 if (srctf_len == SMB2_TF_HDR_SIZE) {
1888 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1889 if (dsttf == NULL) {
1890 return false;
1892 } else {
1893 dsttf = NULL;
1895 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1896 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1898 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1899 * be allocated with size OUTVEC_ALLOC_SIZE. */
1901 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1902 if (dsthdr == NULL) {
1903 return false;
1905 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1906 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1909 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1910 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1911 * then duplicate this. Else use talloc_memdup().
1914 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1915 dstbody = dsthdr + SMB2_HDR_BODY;
1916 } else {
1917 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1918 if (dstbody == NULL) {
1919 return false;
1922 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1923 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1926 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1927 * pointing to
1928 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1929 * then duplicate this. Else use talloc_memdup().
1932 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1933 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1934 } else if (srcdyn == NULL) {
1935 dstdyn = NULL;
1936 } else {
1937 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1938 if (dstdyn == NULL) {
1939 return false;
1942 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1943 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1945 return true;
1948 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1950 struct smbd_smb2_request *newreq = NULL;
1951 struct iovec *outvec = NULL;
1952 int count = req->out.vector_count;
1953 int i;
1954 bool ok;
1956 newreq = smbd_smb2_request_allocate(req->xconn);
1957 if (!newreq) {
1958 return NULL;
1961 newreq->session = req->session;
1962 newreq->do_encryption = req->do_encryption;
1963 newreq->do_signing = req->do_signing;
1964 newreq->current_idx = req->current_idx;
1966 outvec = talloc_zero_array(newreq, struct iovec, count);
1967 if (!outvec) {
1968 TALLOC_FREE(newreq);
1969 return NULL;
1971 newreq->out.vector = outvec;
1972 newreq->out.vector_count = count;
1974 /* Setup the outvec's identically to req. */
1975 outvec[0].iov_base = newreq->out.nbt_hdr;
1976 outvec[0].iov_len = 4;
1977 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1979 /* Setup the vectors identically to the ones in req. */
1980 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1981 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1982 break;
1986 if (i < count) {
1987 /* Alloc failed. */
1988 TALLOC_FREE(newreq);
1989 return NULL;
1992 ok = smb2_setup_nbt_length(newreq->out.vector,
1993 newreq->out.vector_count);
1994 if (!ok) {
1995 TALLOC_FREE(newreq);
1996 return NULL;
1999 return newreq;
2002 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
2004 struct smbXsrv_connection *xconn = req->xconn;
2005 int first_idx = 1;
2006 struct iovec *firsttf = NULL;
2007 struct iovec *outhdr_v = NULL;
2008 uint8_t *outhdr = NULL;
2009 struct smbd_smb2_request *nreq = NULL;
2010 NTSTATUS status;
2011 bool ok;
2013 /* Create a new smb2 request we'll use
2014 for the interim return. */
2015 nreq = dup_smb2_req(req);
2016 if (!nreq) {
2017 return NT_STATUS_NO_MEMORY;
2020 /* Lose the last X out vectors. They're the
2021 ones we'll be using for the async reply. */
2022 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
2024 ok = smb2_setup_nbt_length(nreq->out.vector,
2025 nreq->out.vector_count);
2026 if (!ok) {
2027 return NT_STATUS_INVALID_PARAMETER_MIX;
2030 /* Step back to the previous reply. */
2031 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
2032 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
2033 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
2034 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
2035 /* And end the chain. */
2036 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
2038 /* Calculate outgoing credits */
2039 smb2_calculate_credits(req, nreq);
2041 if (DEBUGLEVEL >= 10) {
2042 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
2043 (unsigned int)nreq->current_idx );
2044 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
2045 (unsigned int)nreq->out.vector_count );
2046 print_req_vectors(nreq);
2050 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
2051 * we need to sign/encrypt here with the last/first key we remembered
2053 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2054 status = smb2_signing_encrypt_pdu(req->first_enc_key,
2055 firsttf,
2056 nreq->out.vector_count - first_idx);
2057 if (!NT_STATUS_IS_OK(status)) {
2058 return status;
2060 } else if (smb2_signing_key_valid(req->last_sign_key)) {
2061 status = smb2_signing_sign_pdu(req->last_sign_key,
2062 outhdr_v,
2063 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2064 if (!NT_STATUS_IS_OK(status)) {
2065 return status;
2069 nreq->queue_entry.mem_ctx = nreq;
2070 nreq->queue_entry.vector = nreq->out.vector;
2071 nreq->queue_entry.count = nreq->out.vector_count;
2072 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry);
2073 xconn->smb2.send_queue_len++;
2075 status = smbd_smb2_flush_send_queue(xconn);
2076 if (!NT_STATUS_IS_OK(status)) {
2077 return status;
2080 return NT_STATUS_OK;
2083 struct smbd_smb2_request_pending_state {
2084 struct smbd_smb2_send_queue queue_entry;
2085 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
2086 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
2089 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
2090 struct tevent_timer *te,
2091 struct timeval current_time,
2092 void *private_data);
2094 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
2095 struct tevent_req *subreq,
2096 uint32_t defer_time)
2098 NTSTATUS status;
2099 struct timeval defer_endtime;
2100 uint8_t *outhdr = NULL;
2101 uint32_t flags;
2103 if (!tevent_req_is_in_progress(subreq)) {
2105 * This is a performance optimization,
2106 * it avoids one tevent_loop iteration,
2107 * which means we avoid one
2108 * talloc_stackframe_pool/talloc_free pair.
2110 tevent_req_notify_callback(subreq);
2111 return NT_STATUS_OK;
2114 req->subreq = subreq;
2115 subreq = NULL;
2117 if (req->async_te) {
2118 /* We're already async. */
2119 return NT_STATUS_OK;
2122 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2123 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
2124 if (flags & SMB2_HDR_FLAG_ASYNC) {
2125 /* We're already async. */
2126 return NT_STATUS_OK;
2129 if (req->async_internal || defer_time == 0) {
2131 * An SMB2 request implementation wants to handle the request
2132 * asynchronously "internally" while keeping synchronous
2133 * behaviour for the SMB2 request. This means we don't send an
2134 * interim response and we can allow processing of compound SMB2
2135 * requests (cf the subsequent check) for all cases.
2137 return NT_STATUS_OK;
2140 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
2142 * We're trying to go async in a compound request
2143 * chain. This is only allowed for opens that cause an
2144 * oplock break or for the last operation in the
2145 * chain, otherwise it is not allowed. See
2146 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
2148 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2150 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
2152 * Cancel the outstanding request.
2154 bool ok = tevent_req_cancel(req->subreq);
2155 if (ok) {
2156 return NT_STATUS_OK;
2158 TALLOC_FREE(req->subreq);
2159 return smbd_smb2_request_error(req,
2160 NT_STATUS_INTERNAL_ERROR);
2164 if (DEBUGLEVEL >= 10) {
2165 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
2166 (unsigned int)req->current_idx );
2167 print_req_vectors(req);
2170 if (req->current_idx > 1) {
2172 * We're going async in a compound
2173 * chain after the first request has
2174 * already been processed. Send an
2175 * interim response containing the
2176 * set of replies already generated.
2178 int idx = req->current_idx;
2180 status = smb2_send_async_interim_response(req);
2181 if (!NT_STATUS_IS_OK(status)) {
2182 return status;
2184 TALLOC_FREE(req->first_enc_key);
2186 req->current_idx = 1;
2189 * Re-arrange the in.vectors to remove what
2190 * we just sent.
2192 memmove(&req->in.vector[1],
2193 &req->in.vector[idx],
2194 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
2195 req->in.vector_count = 1 + (req->in.vector_count - idx);
2197 /* Re-arrange the out.vectors to match. */
2198 memmove(&req->out.vector[1],
2199 &req->out.vector[idx],
2200 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
2201 req->out.vector_count = 1 + (req->out.vector_count - idx);
2203 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
2205 * We only have one remaining request as
2206 * we've processed everything else.
2207 * This is no longer a compound request.
2209 req->compound_related = false;
2210 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2211 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
2212 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
2215 TALLOC_FREE(req->last_sign_key);
2218 * smbd_smb2_request_pending_timer() just send a packet
2219 * to the client and doesn't need any impersonation.
2220 * So we use req->xconn->client->raw_ev_ctx instead
2221 * of req->ev_ctx here.
2223 defer_endtime = timeval_current_ofs_usec(defer_time);
2224 req->async_te = tevent_add_timer(req->xconn->client->raw_ev_ctx,
2225 req, defer_endtime,
2226 smbd_smb2_request_pending_timer,
2227 req);
2228 if (req->async_te == NULL) {
2229 return NT_STATUS_NO_MEMORY;
2232 return NT_STATUS_OK;
2235 static
2236 struct smb2_signing_key *smbd_smb2_signing_key(struct smbXsrv_session *session,
2237 struct smbXsrv_connection *xconn,
2238 bool *_has_channel)
2240 struct smbXsrv_channel_global0 *c = NULL;
2241 NTSTATUS status;
2242 struct smb2_signing_key *key = NULL;
2243 bool has_channel = false;
2245 status = smbXsrv_session_find_channel(session, xconn, &c);
2246 if (NT_STATUS_IS_OK(status)) {
2247 key = c->signing_key;
2248 has_channel = true;
2251 if (!smb2_signing_key_valid(key)) {
2252 key = session->global->signing_key;
2253 has_channel = false;
2256 if (_has_channel != NULL) {
2257 *_has_channel = has_channel;
2260 return key;
2263 static NTSTATUS smb2_get_new_nonce(struct smbXsrv_session *session,
2264 uint64_t *new_nonce_high,
2265 uint64_t *new_nonce_low)
2267 uint64_t nonce_high;
2268 uint64_t nonce_low;
2270 session->nonce_low += 1;
2271 if (session->nonce_low == 0) {
2272 session->nonce_low += 1;
2273 session->nonce_high += 1;
2277 * CCM and GCM algorithms must never have their
2278 * nonce wrap, or the security of the whole
2279 * communication and the keys is destroyed.
2280 * We must drop the connection once we have
2281 * transferred too much data.
2283 * NOTE: We assume nonces greater than 8 bytes.
2285 if (session->nonce_high >= session->nonce_high_max) {
2286 return NT_STATUS_ENCRYPTION_FAILED;
2289 nonce_high = session->nonce_high_random;
2290 nonce_high += session->nonce_high;
2291 nonce_low = session->nonce_low;
2293 *new_nonce_high = nonce_high;
2294 *new_nonce_low = nonce_low;
2295 return NT_STATUS_OK;
2298 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
2299 struct tevent_timer *te,
2300 struct timeval current_time,
2301 void *private_data)
2303 struct smbd_smb2_request *req =
2304 talloc_get_type_abort(private_data,
2305 struct smbd_smb2_request);
2306 struct smbXsrv_connection *xconn = req->xconn;
2307 struct smbd_smb2_request_pending_state *state = NULL;
2308 uint8_t *outhdr = NULL;
2309 const uint8_t *inhdr = NULL;
2310 uint8_t *tf = NULL;
2311 uint8_t *hdr = NULL;
2312 uint8_t *body = NULL;
2313 uint8_t *dyn = NULL;
2314 uint32_t flags = 0;
2315 uint64_t message_id = 0;
2316 uint64_t async_id = 0;
2317 NTSTATUS status;
2318 bool ok;
2320 TALLOC_FREE(req->async_te);
2322 /* Ensure our final reply matches the interim one. */
2323 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2324 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2325 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
2326 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
2328 async_id = message_id; /* keep it simple for now... */
2330 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
2331 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
2333 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
2334 "going async\n",
2335 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
2336 (unsigned long long)async_id ));
2339 * What we send is identical to a smbd_smb2_request_error
2340 * packet with an error status of STATUS_PENDING. Make use
2341 * of this fact sometime when refactoring. JRA.
2344 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
2345 if (state == NULL) {
2346 smbd_server_connection_terminate(xconn,
2347 nt_errstr(NT_STATUS_NO_MEMORY));
2348 return;
2351 tf = state->buf + NBT_HDR_SIZE;
2353 hdr = tf + SMB2_TF_HDR_SIZE;
2354 body = hdr + SMB2_HDR_BODY;
2355 dyn = body + 8;
2357 if (req->do_encryption) {
2358 uint64_t nonce_high = 0;
2359 uint64_t nonce_low = 0;
2360 uint64_t session_id = req->session->global->session_wire_id;
2362 status = smb2_get_new_nonce(req->session,
2363 &nonce_high,
2364 &nonce_low);
2365 if (!NT_STATUS_IS_OK(status)) {
2366 smbd_server_connection_terminate(xconn,
2367 nt_errstr(status));
2368 return;
2371 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2372 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2373 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2374 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2377 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
2378 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2379 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2380 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(NT_STATUS_PENDING));
2381 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
2384 * The STATUS_PENDING response has SMB2_HDR_FLAG_SIGNED
2385 * clearedm, but echoes the signature field.
2387 flags &= ~SMB2_HDR_FLAG_SIGNED;
2388 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
2389 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2390 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
2391 SBVAL(hdr, SMB2_HDR_PID, async_id);
2392 SBVAL(hdr, SMB2_HDR_SESSION_ID,
2393 BVAL(outhdr, SMB2_HDR_SESSION_ID));
2394 memcpy(hdr+SMB2_HDR_SIGNATURE,
2395 outhdr+SMB2_HDR_SIGNATURE, 16);
2397 SSVAL(body, 0x00, 0x08 + 1);
2399 SCVAL(body, 0x02, 0);
2400 SCVAL(body, 0x03, 0);
2401 SIVAL(body, 0x04, 0);
2402 /* Match W2K8R2... */
2403 SCVAL(dyn, 0x00, 0x21);
2405 state->vector[0].iov_base = (void *)state->buf;
2406 state->vector[0].iov_len = NBT_HDR_SIZE;
2408 if (req->do_encryption) {
2409 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
2410 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len =
2411 SMB2_TF_HDR_SIZE;
2412 } else {
2413 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
2414 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
2417 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
2418 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
2420 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
2421 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
2423 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
2424 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
2426 ok = smb2_setup_nbt_length(state->vector,
2427 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2428 if (!ok) {
2429 smbd_server_connection_terminate(
2430 xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
2431 return;
2434 /* Ensure we correctly go through crediting. Grant
2435 the credits now, and zero credits on the final
2436 response. */
2437 smb2_set_operation_credit(req->xconn,
2438 SMBD_SMB2_IN_HDR_IOV(req),
2439 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
2442 * We add SMB2_HDR_FLAG_ASYNC after smb2_set_operation_credit()
2443 * as it reacts on it
2445 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
2447 if (DEBUGLVL(10)) {
2448 int i;
2450 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
2451 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
2452 (unsigned int)i,
2453 (unsigned int)ARRAY_SIZE(state->vector),
2454 (unsigned int)state->vector[i].iov_len);
2458 if (req->do_encryption) {
2459 struct smbXsrv_session *x = req->session;
2460 struct smb2_signing_key *encryption_key = x->global->encryption_key;
2462 status = smb2_signing_encrypt_pdu(encryption_key,
2463 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2464 SMBD_SMB2_NUM_IOV_PER_REQ);
2465 if (!NT_STATUS_IS_OK(status)) {
2466 smbd_server_connection_terminate(xconn,
2467 nt_errstr(status));
2468 return;
2472 state->queue_entry.mem_ctx = state;
2473 state->queue_entry.vector = state->vector;
2474 state->queue_entry.count = ARRAY_SIZE(state->vector);
2475 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
2476 xconn->smb2.send_queue_len++;
2478 status = smbd_smb2_flush_send_queue(xconn);
2479 if (!NT_STATUS_IS_OK(status)) {
2480 smbd_server_connection_terminate(xconn,
2481 nt_errstr(status));
2482 return;
2486 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
2488 struct smbXsrv_connection *xconn = req->xconn;
2489 struct smbd_smb2_request *cur;
2490 const uint8_t *inhdr;
2491 uint32_t flags;
2492 uint64_t search_message_id;
2493 uint64_t search_async_id;
2494 uint64_t found_id = 0;
2496 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2498 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2499 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2500 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
2503 * We don't need the request anymore cancel requests never
2504 * have a response.
2506 * We defer the TALLOC_FREE(req) to the caller.
2508 DLIST_REMOVE(xconn->smb2.requests, req);
2510 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
2511 const uint8_t *outhdr;
2512 uint64_t message_id;
2513 uint64_t async_id;
2515 if (cur->session != req->session) {
2516 continue;
2519 if (cur->compound_related) {
2521 * Never cancel anything in a compound request.
2522 * Way too hard to deal with the result.
2524 continue;
2527 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
2529 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
2530 async_id = BVAL(outhdr, SMB2_HDR_PID);
2532 if (flags & SMB2_HDR_FLAG_ASYNC) {
2533 if (search_async_id == async_id) {
2534 found_id = async_id;
2535 break;
2537 } else {
2538 if (search_message_id == message_id) {
2539 found_id = message_id;
2540 break;
2545 if (cur && cur->subreq) {
2546 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
2547 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
2548 "cancel opcode[%s] mid %llu\n",
2549 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
2550 (unsigned long long)found_id ));
2551 tevent_req_cancel(cur->subreq);
2554 return NT_STATUS_OK;
2557 /*************************************************************
2558 Ensure an incoming tid is a valid one for us to access.
2559 Change to the associated uid credentials and chdir to the
2560 valid tid directory.
2561 *************************************************************/
2563 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
2565 const uint8_t *inhdr;
2566 uint32_t in_flags;
2567 uint32_t in_tid;
2568 struct smbXsrv_tcon *tcon;
2569 NTSTATUS status;
2570 NTTIME now = timeval_to_nttime(&req->request_time);
2572 req->tcon = NULL;
2574 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2576 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2577 in_tid = IVAL(inhdr, SMB2_HDR_TID);
2579 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
2580 in_tid = req->last_tid;
2583 req->last_tid = 0;
2585 status = smb2srv_tcon_lookup(req->session,
2586 in_tid, now, &tcon);
2587 if (!NT_STATUS_IS_OK(status)) {
2588 return status;
2591 if (!change_to_user_and_service(
2592 tcon->compat,
2593 req->session->global->session_wire_id))
2595 return NT_STATUS_ACCESS_DENIED;
2598 req->tcon = tcon;
2599 req->last_tid = in_tid;
2601 return NT_STATUS_OK;
2604 /*************************************************************
2605 Ensure an incoming session_id is a valid one for us to access.
2606 *************************************************************/
2608 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
2610 const uint8_t *inhdr;
2611 uint32_t in_flags;
2612 uint16_t in_opcode;
2613 uint64_t in_session_id;
2614 struct smbXsrv_session *session = NULL;
2615 struct auth_session_info *session_info;
2616 NTSTATUS status;
2617 NTTIME now = timeval_to_nttime(&req->request_time);
2619 req->session = NULL;
2620 req->tcon = NULL;
2622 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2624 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2625 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2626 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
2628 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
2629 in_session_id = req->last_session_id;
2632 req->last_session_id = 0;
2634 /* look an existing session up */
2635 switch (in_opcode) {
2636 case SMB2_OP_SESSSETUP:
2638 * For a session bind request, we don't have the
2639 * channel set up at this point yet, so we defer
2640 * the verification that the connection belongs
2641 * to the session to the session setup code, which
2642 * can look at the session binding flags.
2644 status = smb2srv_session_lookup_client(req->xconn->client,
2645 in_session_id, now,
2646 &session);
2647 break;
2648 default:
2649 status = smb2srv_session_lookup_conn(req->xconn,
2650 in_session_id, now,
2651 &session);
2652 break;
2654 if (session) {
2655 req->session = session;
2656 req->last_session_id = in_session_id;
2658 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
2659 switch (in_opcode) {
2660 case SMB2_OP_SESSSETUP:
2661 status = smb2srv_session_lookup_global(req->xconn->client,
2662 in_session_id,
2663 req,
2664 &session);
2665 if (NT_STATUS_IS_OK(status)) {
2667 * We fallback to a session of
2668 * another process in order to
2669 * get the signing correct.
2671 * We don't set req->last_session_id here.
2673 req->session = session;
2675 break;
2676 default:
2677 break;
2680 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
2681 switch (in_opcode) {
2682 case SMB2_OP_SESSSETUP:
2683 status = NT_STATUS_OK;
2684 break;
2685 case SMB2_OP_LOGOFF:
2686 case SMB2_OP_CLOSE:
2687 case SMB2_OP_LOCK:
2688 case SMB2_OP_CANCEL:
2689 case SMB2_OP_KEEPALIVE:
2691 * [MS-SMB2] 3.3.5.2.9 Verifying the Session
2692 * specifies that LOGOFF, CLOSE and (UN)LOCK
2693 * should always be processed even on expired sessions.
2695 * Also see the logic in
2696 * smbd_smb2_request_process_lock().
2698 * The smb2.session.expire2 test shows that
2699 * CANCEL and KEEPALIVE/ECHO should also
2700 * be processed.
2702 status = NT_STATUS_OK;
2703 break;
2704 default:
2705 break;
2708 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2709 switch (in_opcode) {
2710 case SMB2_OP_TCON:
2711 case SMB2_OP_CREATE:
2712 case SMB2_OP_GETINFO:
2713 case SMB2_OP_SETINFO:
2714 return NT_STATUS_INVALID_HANDLE;
2715 default:
2717 * Notice the check for
2718 * (session_info == NULL)
2719 * below.
2721 status = NT_STATUS_OK;
2722 break;
2725 if (!NT_STATUS_IS_OK(status)) {
2726 return status;
2729 session_info = session->global->auth_session_info;
2730 if (session_info == NULL) {
2731 return NT_STATUS_INVALID_HANDLE;
2734 return NT_STATUS_OK;
2737 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
2738 uint32_t data_length)
2740 struct smbXsrv_connection *xconn = req->xconn;
2741 uint16_t needed_charge;
2742 uint16_t credit_charge = 1;
2743 const uint8_t *inhdr;
2745 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2747 if (xconn->smb2.credits.multicredit) {
2748 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
2749 credit_charge = MAX(credit_charge, 1);
2752 needed_charge = (data_length - 1)/ 65536 + 1;
2754 DBGC_DEBUG(DBGC_SMB2_CREDITS,
2755 "mid %llu, CreditCharge: %d, NeededCharge: %d\n",
2756 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
2757 credit_charge, needed_charge);
2759 if (needed_charge > credit_charge) {
2760 DBGC_WARNING(DBGC_SMB2_CREDITS,
2761 "CreditCharge too low, given %d, needed %d\n",
2762 credit_charge, needed_charge);
2763 return NT_STATUS_INVALID_PARAMETER;
2766 return NT_STATUS_OK;
2769 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
2770 size_t expected_body_size)
2772 struct iovec *inhdr_v;
2773 const uint8_t *inhdr;
2774 uint16_t opcode;
2775 const uint8_t *inbody;
2776 size_t body_size;
2777 size_t min_dyn_size = expected_body_size & 0x00000001;
2778 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
2781 * The following should be checked already.
2783 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
2784 return NT_STATUS_INTERNAL_ERROR;
2786 if (req->current_idx > max_idx) {
2787 return NT_STATUS_INTERNAL_ERROR;
2790 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
2791 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
2792 return NT_STATUS_INTERNAL_ERROR;
2794 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
2795 return NT_STATUS_INTERNAL_ERROR;
2798 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2799 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2801 switch (opcode) {
2802 case SMB2_OP_IOCTL:
2803 case SMB2_OP_GETINFO:
2804 case SMB2_OP_WRITE:
2805 min_dyn_size = 0;
2806 break;
2810 * Now check the expected body size,
2811 * where the last byte might be in the
2812 * dynamic section..
2814 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
2815 return NT_STATUS_INVALID_PARAMETER;
2817 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
2818 return NT_STATUS_INVALID_PARAMETER;
2821 inbody = SMBD_SMB2_IN_BODY_PTR(req);
2823 body_size = SVAL(inbody, 0x00);
2824 if (body_size != expected_body_size) {
2825 return NT_STATUS_INVALID_PARAMETER;
2828 return NT_STATUS_OK;
2831 bool smbXsrv_is_encrypted(uint8_t encryption_flags)
2833 return (!(encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)
2835 (encryption_flags & (SMBXSRV_PROCESSED_ENCRYPTED_PACKET |
2836 SMBXSRV_ENCRYPTION_DESIRED |
2837 SMBXSRV_ENCRYPTION_REQUIRED)));
2840 bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags)
2842 return ((encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET) &&
2843 (encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET));
2846 /* Set a flag if not already set, return true if set */
2847 bool smbXsrv_set_crypto_flag(uint8_t *flags, uint8_t flag)
2849 if ((flag == 0) || (*flags & flag)) {
2850 return false;
2853 *flags |= flag;
2854 return true;
2858 * Update encryption state tracking flags, this can be used to
2859 * determine whether whether the session or tcon is "encrypted".
2861 static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
2862 uint16_t opcode,
2863 bool *update_session_globalp,
2864 bool *update_tcon_globalp)
2866 /* Default: assume unecrypted and unsigned */
2867 struct smbXsrv_session *session = req->session;
2868 struct smbXsrv_tcon *tcon = req->tcon;
2869 uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
2870 uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2871 bool update_session = false;
2872 bool update_tcon = false;
2874 if (session->table == NULL) {
2876 * sessions from smb2srv_session_lookup_global()
2877 * have NT_STATUS_BAD_LOGON_SESSION_STATE
2878 * and session->table == NULL.
2880 * They only used to give the correct error
2881 * status, we should not update any state.
2883 goto out;
2886 if (req->was_encrypted && req->do_encryption) {
2887 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
2888 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2889 } else {
2890 /* Unencrypted packet, can be signed */
2891 if (req->do_signing) {
2892 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2896 update_session |= smbXsrv_set_crypto_flag(
2897 &session->global->encryption_flags, encrypt_flag);
2898 update_session |= smbXsrv_set_crypto_flag(
2899 &session->global->signing_flags, sign_flag);
2901 if (tcon) {
2902 update_tcon |= smbXsrv_set_crypto_flag(
2903 &tcon->global->encryption_flags, encrypt_flag);
2904 update_tcon |= smbXsrv_set_crypto_flag(
2905 &tcon->global->signing_flags, sign_flag);
2908 out:
2909 *update_session_globalp = update_session;
2910 *update_tcon_globalp = update_tcon;
2911 return;
2914 bool smbXsrv_is_signed(uint8_t signing_flags)
2917 * Signing is always enabled, so unless we got an unsigned
2918 * packet and at least one signed packet that was not
2919 * encrypted, the session or tcon is "signed".
2921 return (!(signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2922 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2925 bool smbXsrv_is_partially_signed(uint8_t signing_flags)
2927 return ((signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2928 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2931 static NTSTATUS smbd_smb2_request_dispatch_update_counts(
2932 struct smbd_smb2_request *req,
2933 bool modify_call)
2935 struct smbXsrv_connection *xconn = req->xconn;
2936 const uint8_t *inhdr;
2937 uint16_t channel_sequence;
2938 uint8_t generation_wrap = 0;
2939 uint32_t flags;
2940 int cmp;
2941 struct smbXsrv_open *op;
2942 bool update_open = false;
2943 NTSTATUS status = NT_STATUS_OK;
2945 SMB_ASSERT(!req->request_counters_updated);
2947 if (xconn->protocol < PROTOCOL_SMB3_00) {
2948 return NT_STATUS_OK;
2951 if (req->compat_chain_fsp == NULL) {
2952 return NT_STATUS_OK;
2955 op = req->compat_chain_fsp->op;
2956 if (op == NULL) {
2957 return NT_STATUS_OK;
2960 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2961 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2962 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2964 cmp = channel_sequence - op->global->channel_sequence;
2965 if (cmp < 0) {
2967 * csn wrap. We need to watch out for long-running
2968 * requests that are still sitting on a previously
2969 * used csn. SMB2_OP_NOTIFY can take VERY long.
2971 generation_wrap += 1;
2974 if (abs(cmp) > INT16_MAX) {
2976 * [MS-SMB2] 3.3.5.2.10 - Verifying the Channel Sequence Number:
2978 * If the channel sequence number of the request and the one
2979 * known to the server are not equal, the channel sequence
2980 * number and outstanding request counts are only updated
2981 * "... if the unsigned difference using 16-bit arithmetic
2982 * between ChannelSequence and Open.ChannelSequence is less than
2983 * or equal to 0x7FFF ...".
2984 * Otherwise, an error is returned for the modifying
2985 * calls write, set_info, and ioctl.
2987 * There are currently two issues with the description:
2989 * * For the other calls, the document seems to imply
2990 * that processing continues without adapting the
2991 * counters (if the sequence numbers are not equal).
2993 * TODO: This needs clarification!
2995 * * Also, the behaviour if the difference is larger
2996 * than 0x7FFF is not clear. The document seems to
2997 * imply that if such a difference is reached,
2998 * the server starts to ignore the counters or
2999 * in the case of the modifying calls, return errors.
3001 * TODO: This needs clarification!
3003 * At this point Samba tries to be a little more
3004 * clever than the description in the MS-SMB2 document
3005 * by heuristically detecting and properly treating
3006 * a 16 bit overflow of the client-submitted sequence
3007 * number:
3009 * If the stored channel sequence number is more than
3010 * 0x7FFF larger than the one from the request, then
3011 * the client-provided sequence number has likely
3012 * overflown. We treat this case as valid instead
3013 * of as failure.
3015 * The MS-SMB2 behaviour would be setting cmp = -1.
3017 cmp *= -1;
3020 if (flags & SMB2_HDR_FLAG_REPLAY_OPERATION) {
3021 if (cmp == 0 && op->pre_request_count == 0) {
3022 op->request_count += 1;
3023 req->request_counters_updated = true;
3024 } else if (cmp > 0 && op->pre_request_count == 0) {
3025 op->pre_request_count += op->request_count;
3026 op->request_count = 1;
3027 op->global->channel_sequence = channel_sequence;
3028 op->global->channel_generation += generation_wrap;
3029 update_open = true;
3030 req->request_counters_updated = true;
3031 } else if (modify_call) {
3032 return NT_STATUS_FILE_NOT_AVAILABLE;
3034 } else {
3035 if (cmp == 0) {
3036 op->request_count += 1;
3037 req->request_counters_updated = true;
3038 } else if (cmp > 0) {
3039 op->pre_request_count += op->request_count;
3040 op->request_count = 1;
3041 op->global->channel_sequence = channel_sequence;
3042 op->global->channel_generation += generation_wrap;
3043 update_open = true;
3044 req->request_counters_updated = true;
3045 } else if (modify_call) {
3046 return NT_STATUS_FILE_NOT_AVAILABLE;
3049 req->channel_generation = op->global->channel_generation;
3051 if (update_open) {
3052 status = smbXsrv_open_update(op);
3055 return status;
3058 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
3060 struct smbXsrv_connection *xconn = req->xconn;
3061 const struct smbd_smb2_dispatch_table *call = NULL;
3062 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
3063 const uint8_t *inhdr;
3064 uint16_t opcode;
3065 uint32_t flags;
3066 uint64_t mid;
3067 NTSTATUS status;
3068 NTSTATUS session_status;
3069 uint32_t allowed_flags;
3070 NTSTATUS return_value;
3071 struct smbXsrv_session *x = NULL;
3072 bool signing_required = false;
3073 bool encryption_desired = false;
3074 bool encryption_required = false;
3075 bool session_expired = false;
3077 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
3079 DO_PROFILE_INC(request);
3081 SMB_ASSERT(!req->request_counters_updated);
3083 /* TODO: verify more things */
3085 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
3086 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
3087 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
3088 DBG_DEBUG("opcode[%s] mid = %"PRIu64"\n",
3089 smb2_opcode_name(opcode),
3090 mid);
3092 if (xconn->protocol >= PROTOCOL_SMB2_02) {
3094 * once the protocol is negotiated
3095 * SMB2_OP_NEGPROT is not allowed anymore
3097 if (opcode == SMB2_OP_NEGPROT) {
3098 /* drop the connection */
3099 return NT_STATUS_INVALID_PARAMETER;
3101 } else {
3103 * if the protocol is not negotiated yet
3104 * only SMB2_OP_NEGPROT is allowed.
3106 if (opcode != SMB2_OP_NEGPROT) {
3107 /* drop the connection */
3108 return NT_STATUS_INVALID_PARAMETER;
3113 * Check if the client provided a valid session id.
3115 * As some command don't require a valid session id
3116 * we defer the check of the session_status
3118 session_status = smbd_smb2_request_check_session(req);
3119 x = req->session;
3120 if (x != NULL) {
3121 signing_required = x->global->signing_flags & SMBXSRV_SIGNING_REQUIRED;
3122 encryption_desired = x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
3123 encryption_required = x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
3124 session_expired =
3125 NT_STATUS_EQUAL(session_status,
3126 NT_STATUS_NETWORK_SESSION_EXPIRED);
3129 req->async_internal = false;
3130 req->do_signing = false;
3131 if (opcode != SMB2_OP_SESSSETUP) {
3132 req->do_encryption = encryption_desired;
3133 } else {
3134 req->do_encryption = false;
3136 req->was_encrypted = false;
3137 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
3138 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
3139 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
3141 if (x != NULL && x->global->session_wire_id != tf_session_id) {
3142 DBG_ERR("invalid session_id "
3143 "in SMB2_HDR[%" PRIu64 "], SMB2_TF[%" PRIu64
3144 "]\n",
3145 x->global->session_wire_id,
3146 tf_session_id);
3148 * TODO: windows allows this...
3149 * should we drop the connection?
3151 * For now we just return ACCESS_DENIED
3152 * (Windows clients never trigger this)
3153 * and wait for an update of [MS-SMB2].
3155 return smbd_smb2_request_error(req,
3156 NT_STATUS_ACCESS_DENIED);
3159 req->was_encrypted = true;
3160 req->do_encryption = true;
3163 if (encryption_required && !req->was_encrypted) {
3164 req->do_encryption = true;
3165 return smbd_smb2_request_error(req,
3166 NT_STATUS_ACCESS_DENIED);
3169 call = smbd_smb2_call(opcode);
3170 if (call == NULL) {
3171 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
3174 allowed_flags = SMB2_HDR_FLAG_CHAINED |
3175 SMB2_HDR_FLAG_SIGNED |
3176 SMB2_HDR_FLAG_DFS;
3177 if (xconn->protocol >= PROTOCOL_SMB3_11) {
3178 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
3180 if (opcode == SMB2_OP_NEGPROT) {
3181 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11) {
3182 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
3185 if (opcode == SMB2_OP_CANCEL) {
3186 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
3188 if (xconn->protocol >= PROTOCOL_SMB3_00) {
3189 allowed_flags |= SMB2_HDR_FLAG_REPLAY_OPERATION;
3191 if ((flags & ~allowed_flags) != 0) {
3192 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
3195 if (flags & SMB2_HDR_FLAG_CHAINED) {
3197 * This check is mostly for giving the correct error code
3198 * for compounded requests.
3200 if (!session_expired && !NT_STATUS_IS_OK(session_status)) {
3201 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
3203 } else {
3204 req->compat_chain_fsp = NULL;
3207 if (req->was_encrypted) {
3208 signing_required = false;
3209 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
3210 struct smb2_signing_key *signing_key = NULL;
3211 bool has_channel = false;
3213 if (x == NULL) {
3215 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
3216 * If the SMB2 header of the SMB2 NEGOTIATE
3217 * request has the SMB2_FLAGS_SIGNED bit set in the
3218 * Flags field, the server MUST fail the request
3219 * with STATUS_INVALID_PARAMETER.
3221 * Microsoft test tool checks this.
3224 if ((opcode == SMB2_OP_NEGPROT) &&
3225 (flags & SMB2_HDR_FLAG_SIGNED)) {
3226 status = NT_STATUS_INVALID_PARAMETER;
3227 } else {
3228 status = NT_STATUS_USER_SESSION_DELETED;
3230 return smbd_smb2_request_error(req, status);
3233 signing_key = smbd_smb2_signing_key(x, xconn, &has_channel);
3236 * If we have a signing key, we should
3237 * sign the response
3239 if (smb2_signing_key_valid(signing_key) && opcode != SMB2_OP_CANCEL) {
3240 req->do_signing = true;
3243 status = smb2_signing_check_pdu(signing_key,
3244 SMBD_SMB2_IN_HDR_IOV(req),
3245 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
3246 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
3247 opcode == SMB2_OP_SESSSETUP && !has_channel &&
3248 NT_STATUS_IS_OK(session_status))
3250 if (!NT_STATUS_EQUAL(x->status, NT_STATUS_BAD_LOGON_SESSION_STATE)) {
3251 struct smbXsrv_session *session = NULL;
3252 NTSTATUS error;
3254 error = smb2srv_session_lookup_global(req->xconn->client,
3255 x->global->session_wire_id,
3256 req,
3257 &session);
3258 if (!NT_STATUS_IS_OK(error)) {
3259 return smbd_smb2_request_error(req, error);
3263 * We fallback to a session of
3264 * another process in order to
3265 * get the signing correct.
3267 * We don't set req->last_session_id here.
3269 req->session = x = session;
3271 goto skipped_signing;
3273 if (!NT_STATUS_IS_OK(status)) {
3274 return smbd_smb2_request_error(req, status);
3278 * Now that we know the request was correctly signed
3279 * we have to sign the response too.
3281 if (opcode != SMB2_OP_CANCEL) {
3282 req->do_signing = true;
3285 if (!NT_STATUS_IS_OK(session_status)) {
3286 if (session_expired && opcode == SMB2_OP_CREATE) {
3287 req->compound_create_err = session_status;
3289 return smbd_smb2_request_error(req, session_status);
3293 if (opcode == SMB2_OP_IOCTL) {
3295 * Some special IOCTL calls don't require
3296 * file, tcon nor session.
3298 * They typically don't do any real action
3299 * on behalf of the client.
3301 * They are mainly used to alter the behavior
3302 * of the connection for testing. So we can
3303 * run as root and skip all file, tcon and session
3304 * checks below.
3306 static const struct smbd_smb2_dispatch_table _root_ioctl_call = {
3307 .opcode = SMB2_OP_IOCTL,
3308 .as_root = true,
3310 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
3311 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
3312 uint32_t in_ctl_code;
3313 size_t needed = 8;
3315 if (needed > body_size) {
3316 return smbd_smb2_request_error(req,
3317 NT_STATUS_INVALID_PARAMETER);
3320 in_ctl_code = IVAL(body, 0x04);
3322 * Only add trusted IOCTL codes here!
3324 switch (in_ctl_code) {
3325 case FSCTL_SMBTORTURE_FORCE_UNACKED_TIMEOUT:
3326 call = &_root_ioctl_call;
3327 break;
3328 case FSCTL_VALIDATE_NEGOTIATE_INFO:
3329 call = &_root_ioctl_call;
3330 break;
3331 case FSCTL_QUERY_NETWORK_INTERFACE_INFO:
3332 call = &_root_ioctl_call;
3333 break;
3337 skipped_signing:
3339 if (flags & SMB2_HDR_FLAG_CHAINED) {
3340 if (!NT_STATUS_IS_OK(req->compound_create_err)) {
3341 return smbd_smb2_request_error(req,
3342 req->compound_create_err);
3344 req->compound_related = true;
3347 if (call->need_session) {
3348 if (!NT_STATUS_IS_OK(session_status)) {
3349 if (session_expired && opcode == SMB2_OP_CREATE) {
3350 req->compound_create_err = session_status;
3352 return smbd_smb2_request_error(req, session_status);
3356 if (call->need_tcon) {
3357 SMB_ASSERT(call->need_session);
3360 * This call needs to be run as user.
3362 * smbd_smb2_request_check_tcon()
3363 * calls change_to_user() on success.
3364 * Which implies set_current_user_info()
3365 * and chdir_current_service().
3367 status = smbd_smb2_request_check_tcon(req);
3368 if (!NT_STATUS_IS_OK(status)) {
3369 return smbd_smb2_request_error(req, status);
3371 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
3372 encryption_desired = true;
3374 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
3375 encryption_required = true;
3377 if (encryption_required && !req->was_encrypted) {
3378 req->do_encryption = true;
3379 return smbd_smb2_request_error(req,
3380 NT_STATUS_ACCESS_DENIED);
3381 } else if (encryption_desired) {
3382 req->do_encryption = true;
3384 } else if (call->need_session) {
3385 struct auth_session_info *session_info = NULL;
3388 * Unless we also have need_tcon (see above),
3389 * we still need to call set_current_user_info().
3392 session_info = req->session->global->auth_session_info;
3393 if (session_info == NULL) {
3394 return NT_STATUS_INVALID_HANDLE;
3397 set_current_user_info(session_info->unix_info->sanitized_username,
3398 session_info->unix_info->unix_name,
3399 session_info->info->domain_name);
3402 if (req->session) {
3403 bool update_session_global = false;
3404 bool update_tcon_global = false;
3406 smb2srv_update_crypto_flags(req, opcode,
3407 &update_session_global,
3408 &update_tcon_global);
3410 if (update_session_global) {
3411 status = smbXsrv_session_update(x);
3412 if (!NT_STATUS_IS_OK(status)) {
3413 return smbd_smb2_request_error(req, status);
3416 if (update_tcon_global) {
3417 status = smbXsrv_tcon_update(req->tcon);
3418 if (!NT_STATUS_IS_OK(status)) {
3419 return smbd_smb2_request_error(req, status);
3424 if (call->fileid_ofs != 0) {
3425 size_t needed = call->fileid_ofs + 16;
3426 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
3427 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
3428 uint64_t file_id_persistent;
3429 uint64_t file_id_volatile;
3430 struct files_struct *fsp;
3432 SMB_ASSERT(call->need_tcon);
3434 if (needed > body_size) {
3435 return smbd_smb2_request_error(req,
3436 NT_STATUS_INVALID_PARAMETER);
3439 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
3440 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
3442 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
3443 if (fsp == NULL) {
3444 if (req->compound_related &&
3445 !NT_STATUS_IS_OK(req->compound_create_err))
3447 return smbd_smb2_request_error(req,
3448 req->compound_create_err);
3451 * smbd_smb2_request_process_ioctl()
3452 * has more checks in order to return more
3453 * detailed error codes...
3455 if (opcode != SMB2_OP_IOCTL) {
3456 return smbd_smb2_request_error(req,
3457 NT_STATUS_FILE_CLOSED);
3459 } else {
3460 if (fsp->fsp_flags.encryption_required && !req->was_encrypted) {
3461 return smbd_smb2_request_error(req,
3462 NT_STATUS_ACCESS_DENIED);
3467 status = smbd_smb2_request_dispatch_update_counts(req, call->modify);
3468 if (!NT_STATUS_IS_OK(status)) {
3469 return smbd_smb2_request_error(req, status);
3472 if (call->as_root) {
3473 SMB_ASSERT(call->fileid_ofs == 0);
3474 /* This call needs to be run as root */
3475 change_to_root_user();
3476 } else if (opcode != SMB2_OP_KEEPALIVE) {
3477 SMB_ASSERT(call->need_tcon);
3480 #define _INBYTES(_r) \
3481 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
3483 switch (opcode) {
3484 case SMB2_OP_NEGPROT:
3485 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
3486 req->profile, _INBYTES(req));
3487 return_value = smbd_smb2_request_process_negprot(req);
3488 break;
3490 case SMB2_OP_SESSSETUP:
3491 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
3492 req->profile, _INBYTES(req));
3493 return_value = smbd_smb2_request_process_sesssetup(req);
3494 break;
3496 case SMB2_OP_LOGOFF:
3497 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
3498 req->profile, _INBYTES(req));
3499 return_value = smbd_smb2_request_process_logoff(req);
3500 break;
3502 case SMB2_OP_TCON:
3503 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
3504 req->profile, _INBYTES(req));
3505 return_value = smbd_smb2_request_process_tcon(req);
3506 break;
3508 case SMB2_OP_TDIS:
3509 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
3510 req->profile, _INBYTES(req));
3511 return_value = smbd_smb2_request_process_tdis(req);
3512 break;
3514 case SMB2_OP_CREATE:
3515 if (req->subreq == NULL) {
3516 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
3517 req->profile, _INBYTES(req));
3518 } else {
3519 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
3521 return_value = smbd_smb2_request_process_create(req);
3522 break;
3524 case SMB2_OP_CLOSE:
3525 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
3526 req->profile, _INBYTES(req));
3527 return_value = smbd_smb2_request_process_close(req);
3528 break;
3530 case SMB2_OP_FLUSH:
3531 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
3532 req->profile, _INBYTES(req));
3533 return_value = smbd_smb2_request_process_flush(req);
3534 break;
3536 case SMB2_OP_READ:
3537 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
3538 req->profile, _INBYTES(req));
3539 return_value = smbd_smb2_request_process_read(req);
3540 break;
3542 case SMB2_OP_WRITE:
3543 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
3544 req->profile, _INBYTES(req));
3545 return_value = smbd_smb2_request_process_write(req);
3546 break;
3548 case SMB2_OP_LOCK:
3549 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
3550 req->profile, _INBYTES(req));
3551 return_value = smbd_smb2_request_process_lock(req);
3552 break;
3554 case SMB2_OP_IOCTL:
3555 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
3556 req->profile, _INBYTES(req));
3557 return_value = smbd_smb2_request_process_ioctl(req);
3558 break;
3560 case SMB2_OP_CANCEL:
3561 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
3562 req->profile, _INBYTES(req));
3563 return_value = smbd_smb2_request_process_cancel(req);
3564 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
3567 * We don't need the request anymore cancel requests never
3568 * have a response.
3570 * smbd_smb2_request_process_cancel() already called
3571 * DLIST_REMOVE(xconn->smb2.requests, req);
3573 TALLOC_FREE(req);
3575 break;
3577 case SMB2_OP_KEEPALIVE:
3578 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
3579 req->profile, _INBYTES(req));
3580 return_value = smbd_smb2_request_process_keepalive(req);
3581 break;
3583 case SMB2_OP_QUERY_DIRECTORY:
3584 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
3585 req->profile, _INBYTES(req));
3586 return_value = smbd_smb2_request_process_query_directory(req);
3587 break;
3589 case SMB2_OP_NOTIFY:
3590 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
3591 req->profile, _INBYTES(req));
3592 return_value = smbd_smb2_request_process_notify(req);
3593 break;
3595 case SMB2_OP_GETINFO:
3596 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
3597 req->profile, _INBYTES(req));
3598 return_value = smbd_smb2_request_process_getinfo(req);
3599 break;
3601 case SMB2_OP_SETINFO:
3602 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
3603 req->profile, _INBYTES(req));
3604 return_value = smbd_smb2_request_process_setinfo(req);
3605 break;
3607 case SMB2_OP_BREAK:
3608 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
3609 req->profile, _INBYTES(req));
3610 return_value = smbd_smb2_request_process_break(req);
3611 break;
3613 default:
3614 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
3615 break;
3617 return return_value;
3620 static void smbd_smb2_request_reply_update_counts(struct smbd_smb2_request *req)
3622 struct smbXsrv_connection *xconn = req->xconn;
3623 const uint8_t *inhdr;
3624 uint16_t channel_sequence;
3625 struct smbXsrv_open *op;
3627 if (!req->request_counters_updated) {
3628 return;
3631 req->request_counters_updated = false;
3633 if (xconn->protocol < PROTOCOL_SMB3_00) {
3634 return;
3637 if (req->compat_chain_fsp == NULL) {
3638 return;
3641 op = req->compat_chain_fsp->op;
3642 if (op == NULL) {
3643 return;
3646 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
3647 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
3649 if ((op->global->channel_sequence == channel_sequence) &&
3650 (op->global->channel_generation == req->channel_generation)) {
3651 SMB_ASSERT(op->request_count > 0);
3652 op->request_count -= 1;
3653 } else {
3654 SMB_ASSERT(op->pre_request_count > 0);
3655 op->pre_request_count -= 1;
3659 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
3661 struct smbXsrv_connection *xconn = req->xconn;
3662 int first_idx = 1;
3663 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
3664 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
3665 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
3666 NTSTATUS status;
3667 bool ok;
3669 req->subreq = NULL;
3670 TALLOC_FREE(req->async_te);
3672 /* MS-SMB2: 3.3.4.1 Sending Any Outgoing Message */
3673 smbd_smb2_request_reply_update_counts(req);
3675 if (req->do_encryption &&
3676 (firsttf->iov_len == 0) &&
3677 (!smb2_signing_key_valid(req->first_enc_key)) &&
3678 (req->session != NULL) &&
3679 smb2_signing_key_valid(req->session->global->encryption_key))
3681 struct smb2_signing_key *encryption_key =
3682 req->session->global->encryption_key;
3683 uint8_t *tf;
3684 uint64_t session_id = req->session->global->session_wire_id;
3685 uint64_t nonce_high;
3686 uint64_t nonce_low;
3688 status = smb2_get_new_nonce(req->session,
3689 &nonce_high,
3690 &nonce_low);
3691 if (!NT_STATUS_IS_OK(status)) {
3692 return status;
3696 * We need to place the SMB2_TRANSFORM header before the
3697 * first SMB2 header
3701 * we need to remember the encryption key
3702 * and defer the signing/encryption until
3703 * we are sure that we do not change
3704 * the header again.
3706 status = smb2_signing_key_copy(req,
3707 encryption_key,
3708 &req->first_enc_key);
3709 if (!NT_STATUS_IS_OK(status)) {
3710 return status;
3713 tf = talloc_zero_array(req, uint8_t,
3714 SMB2_TF_HDR_SIZE);
3715 if (tf == NULL) {
3716 return NT_STATUS_NO_MEMORY;
3719 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
3720 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
3721 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
3722 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
3724 firsttf->iov_base = (void *)tf;
3725 firsttf->iov_len = SMB2_TF_HDR_SIZE;
3728 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
3729 (smb2_signing_key_valid(req->last_sign_key)) &&
3730 (firsttf->iov_len == 0))
3732 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
3733 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
3736 * As we are sure the header of the last request in the
3737 * compound chain will not change, we can to sign here
3738 * with the last signing key we remembered.
3740 status = smb2_signing_sign_pdu(req->last_sign_key,
3741 lasthdr,
3742 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
3743 if (!NT_STATUS_IS_OK(status)) {
3744 return status;
3747 TALLOC_FREE(req->last_sign_key);
3749 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
3750 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
3752 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
3754 if (req->current_idx < req->out.vector_count) {
3756 * We must process the remaining compound
3757 * SMB2 requests before any new incoming SMB2
3758 * requests. This is because incoming SMB2
3759 * requests may include a cancel for a
3760 * compound request we haven't processed
3761 * yet.
3763 struct tevent_immediate *im = tevent_create_immediate(req);
3764 if (!im) {
3765 return NT_STATUS_NO_MEMORY;
3768 if (req->do_signing && firsttf->iov_len == 0) {
3769 struct smbXsrv_session *x = req->session;
3770 struct smb2_signing_key *signing_key =
3771 smbd_smb2_signing_key(x, xconn, NULL);
3774 * we need to remember the signing key
3775 * and defer the signing until
3776 * we are sure that we do not change
3777 * the header again.
3779 status = smb2_signing_key_copy(req,
3780 signing_key,
3781 &req->last_sign_key);
3782 if (!NT_STATUS_IS_OK(status)) {
3783 return status;
3788 * smbd_smb2_request_dispatch() will redo the impersonation.
3789 * So we use req->xconn->client->raw_ev_ctx instead
3790 * of req->ev_ctx here.
3792 tevent_schedule_immediate(im,
3793 req->xconn->client->raw_ev_ctx,
3794 smbd_smb2_request_dispatch_immediate,
3795 req);
3796 return NT_STATUS_OK;
3799 if (req->compound_related) {
3800 req->compound_related = false;
3803 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
3804 if (!ok) {
3805 return NT_STATUS_INVALID_PARAMETER_MIX;
3808 /* Set credit for these operations (zero credits if this
3809 is a final reply for an async operation). */
3810 smb2_calculate_credits(req, req);
3813 * now check if we need to sign the current response
3815 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
3816 status = smb2_signing_encrypt_pdu(req->first_enc_key,
3817 firsttf,
3818 req->out.vector_count - first_idx);
3819 if (!NT_STATUS_IS_OK(status)) {
3820 return status;
3822 } else if (req->do_signing) {
3823 struct smbXsrv_session *x = req->session;
3824 struct smb2_signing_key *signing_key =
3825 smbd_smb2_signing_key(x, xconn, NULL);
3827 status = smb2_signing_sign_pdu(signing_key,
3828 outhdr,
3829 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
3830 if (!NT_STATUS_IS_OK(status)) {
3831 return status;
3834 TALLOC_FREE(req->first_enc_key);
3836 if (req->preauth != NULL) {
3837 gnutls_hash_hd_t hash_hnd = NULL;
3838 size_t i;
3839 int rc;
3841 rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_SHA512);
3842 if (rc < 0) {
3843 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3845 rc = gnutls_hash(hash_hnd,
3846 req->preauth->sha512_value,
3847 sizeof(req->preauth->sha512_value));
3848 if (rc < 0) {
3849 gnutls_hash_deinit(hash_hnd, NULL);
3850 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3852 for (i = 1; i < req->in.vector_count; i++) {
3853 rc = gnutls_hash(hash_hnd,
3854 req->in.vector[i].iov_base,
3855 req->in.vector[i].iov_len);
3856 if (rc < 0) {
3857 gnutls_hash_deinit(hash_hnd, NULL);
3858 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3861 gnutls_hash_output(hash_hnd, req->preauth->sha512_value);
3863 rc = gnutls_hash(hash_hnd,
3864 req->preauth->sha512_value,
3865 sizeof(req->preauth->sha512_value));
3866 if (rc < 0) {
3867 gnutls_hash_deinit(hash_hnd, NULL);
3868 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3870 for (i = 1; i < req->out.vector_count; i++) {
3871 rc = gnutls_hash(hash_hnd,
3872 req->out.vector[i].iov_base,
3873 req->out.vector[i].iov_len);
3874 if (rc < 0) {
3875 gnutls_hash_deinit(hash_hnd, NULL);
3876 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3880 gnutls_hash_deinit(hash_hnd, req->preauth->sha512_value);
3882 req->preauth = NULL;
3885 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
3886 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
3887 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
3888 /* Dynamic part is NULL. Chop it off,
3889 We're going to send it via sendfile. */
3890 req->out.vector_count -= 1;
3894 * We're done with this request -
3895 * move it off the "being processed" queue.
3897 DLIST_REMOVE(xconn->smb2.requests, req);
3899 req->queue_entry.mem_ctx = req;
3900 req->queue_entry.vector = req->out.vector;
3901 req->queue_entry.count = req->out.vector_count;
3902 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry);
3903 xconn->smb2.send_queue_len++;
3905 status = smbd_smb2_flush_send_queue(xconn);
3906 if (!NT_STATUS_IS_OK(status)) {
3907 return status;
3910 return NT_STATUS_OK;
3913 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
3915 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
3916 struct tevent_immediate *im,
3917 void *private_data)
3919 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
3920 struct smbd_smb2_request);
3921 struct smbXsrv_connection *xconn = req->xconn;
3922 NTSTATUS status;
3924 TALLOC_FREE(im);
3926 if (DEBUGLEVEL >= 10) {
3927 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
3928 req->current_idx, req->in.vector_count));
3929 print_req_vectors(req);
3932 status = smbd_smb2_request_dispatch(req);
3933 if (!NT_STATUS_IS_OK(status)) {
3934 smbd_server_connection_terminate(xconn, nt_errstr(status));
3935 return;
3938 status = smbd_smb2_request_next_incoming(xconn);
3939 if (!NT_STATUS_IS_OK(status)) {
3940 smbd_server_connection_terminate(xconn, nt_errstr(status));
3941 return;
3945 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
3946 NTSTATUS status,
3947 DATA_BLOB body, DATA_BLOB *dyn,
3948 const char *location)
3950 uint8_t *outhdr;
3951 struct iovec *outbody_v;
3952 struct iovec *outdyn_v;
3953 uint32_t next_command_ofs;
3954 uint64_t mid;
3956 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3957 mid = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
3959 DBG_DEBUG("mid [%"PRIu64"] idx[%d] status[%s] "
3960 "body[%u] dyn[%s:%u] at %s\n",
3961 mid,
3962 req->current_idx,
3963 nt_errstr(status),
3964 (unsigned int)body.length,
3965 dyn ? "yes" : "no",
3966 (unsigned int)(dyn ? dyn->length : 0),
3967 location);
3969 if (body.length < 2) {
3970 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3973 if ((body.length % 2) != 0) {
3974 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3977 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
3978 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
3980 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
3981 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
3983 outbody_v->iov_base = (void *)body.data;
3984 outbody_v->iov_len = body.length;
3986 if (dyn) {
3987 outdyn_v->iov_base = (void *)dyn->data;
3988 outdyn_v->iov_len = dyn->length;
3989 } else {
3990 outdyn_v->iov_base = NULL;
3991 outdyn_v->iov_len = 0;
3995 * See if we need to recalculate the offset to the next response
3997 * Note that all responses may require padding (including the very last
3998 * one).
4000 if (req->out.vector_count >= (2 * SMBD_SMB2_NUM_IOV_PER_REQ)) {
4001 next_command_ofs = SMB2_HDR_BODY;
4002 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
4003 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
4006 if ((next_command_ofs % 8) != 0) {
4007 size_t pad_size = 8 - (next_command_ofs % 8);
4008 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
4010 * if the dyn buffer is empty
4011 * we can use it to add padding
4013 uint8_t *pad;
4015 pad = talloc_zero_array(req,
4016 uint8_t, pad_size);
4017 if (pad == NULL) {
4018 return smbd_smb2_request_error(req,
4019 NT_STATUS_NO_MEMORY);
4022 outdyn_v->iov_base = (void *)pad;
4023 outdyn_v->iov_len = pad_size;
4024 } else {
4026 * For now we copy the dynamic buffer
4027 * and add the padding to the new buffer
4029 size_t old_size;
4030 uint8_t *old_dyn;
4031 size_t new_size;
4032 uint8_t *new_dyn;
4034 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
4035 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
4037 new_size = old_size + pad_size;
4038 new_dyn = talloc_zero_array(req,
4039 uint8_t, new_size);
4040 if (new_dyn == NULL) {
4041 return smbd_smb2_request_error(req,
4042 NT_STATUS_NO_MEMORY);
4045 memcpy(new_dyn, old_dyn, old_size);
4046 memset(new_dyn + old_size, 0, pad_size);
4048 outdyn_v->iov_base = (void *)new_dyn;
4049 outdyn_v->iov_len = new_size;
4051 next_command_ofs += pad_size;
4054 if ((req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) >= req->out.vector_count) {
4055 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
4056 } else {
4057 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
4059 return smbd_smb2_request_reply(req);
4062 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
4063 NTSTATUS status,
4064 uint8_t error_context_count,
4065 DATA_BLOB *info,
4066 const char *location)
4068 struct smbXsrv_connection *xconn = req->xconn;
4069 DATA_BLOB body;
4070 DATA_BLOB _dyn;
4071 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
4072 size_t unread_bytes = smbd_smb2_unread_bytes(req);
4074 DBG_NOTICE("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| "
4075 "at %s\n", req->current_idx, nt_errstr(status),
4076 info ? " +info" : "", location);
4078 if (unread_bytes) {
4079 /* Recvfile error. Drain incoming socket. */
4080 size_t ret;
4082 errno = 0;
4083 ret = drain_socket(xconn->transport.sock, unread_bytes);
4084 if (ret != unread_bytes) {
4085 NTSTATUS error;
4087 if (errno == 0) {
4088 error = NT_STATUS_IO_DEVICE_ERROR;
4089 } else {
4090 error = map_nt_error_from_unix_common(errno);
4093 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
4094 "ret[%u] errno[%d] => %s\n",
4095 (unsigned)unread_bytes,
4096 (unsigned)ret, errno, nt_errstr(error)));
4097 return error;
4101 if (req->compound_related &&
4102 NT_STATUS_EQUAL(status, NT_STATUS_CANCELLED))
4105 * A compound request went async but was cancelled as it was not
4106 * one of the allowed async compound requests.
4108 status = NT_STATUS_INTERNAL_ERROR;
4111 body.data = outhdr + SMB2_HDR_BODY;
4112 body.length = 8;
4113 SSVAL(body.data, 0, 9);
4114 SCVAL(body.data, 2, error_context_count);
4116 if (info) {
4117 SIVAL(body.data, 0x04, info->length);
4118 } else {
4119 /* Allocated size of req->out.vector[i].iov_base
4120 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
4121 * 1 byte without having to do an alloc.
4123 info = &_dyn;
4124 info->data = ((uint8_t *)outhdr) +
4125 OUTVEC_ALLOC_SIZE - 1;
4126 info->length = 1;
4127 SCVAL(info->data, 0, 0);
4131 * Note: Even if there is an error, continue to process the request.
4132 * per MS-SMB2.
4135 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
4138 struct smbd_smb2_break_state {
4139 struct tevent_req *req;
4140 struct smbd_smb2_send_queue queue_entry;
4141 uint8_t nbt_hdr[NBT_HDR_SIZE];
4142 uint8_t hdr[SMB2_HDR_BODY];
4143 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
4146 static struct tevent_req *smbd_smb2_break_send(TALLOC_CTX *mem_ctx,
4147 struct tevent_context *ev,
4148 struct smbXsrv_connection *xconn,
4149 uint64_t session_id,
4150 const uint8_t *body,
4151 size_t body_len)
4153 struct tevent_req *req = NULL;
4154 struct smbd_smb2_break_state *state = NULL;
4155 NTSTATUS status;
4156 bool ok;
4158 req = tevent_req_create(mem_ctx, &state,
4159 struct smbd_smb2_break_state);
4160 if (req == NULL) {
4161 return NULL;
4164 state->req = req;
4165 tevent_req_defer_callback(req, ev);
4167 SIVAL(state->hdr, 0, SMB2_MAGIC);
4168 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
4169 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
4170 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
4171 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
4172 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
4173 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
4174 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
4175 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
4176 SIVAL(state->hdr, SMB2_HDR_PID, 0);
4177 SIVAL(state->hdr, SMB2_HDR_TID, 0);
4178 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, session_id);
4179 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
4181 state->vector[0] = (struct iovec) {
4182 .iov_base = state->nbt_hdr,
4183 .iov_len = sizeof(state->nbt_hdr)
4186 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
4187 .iov_base = NULL,
4188 .iov_len = 0
4191 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
4192 .iov_base = state->hdr,
4193 .iov_len = sizeof(state->hdr)
4196 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
4197 .iov_base = discard_const_p(uint8_t, body),
4198 .iov_len = body_len,
4202 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
4205 ok = smb2_setup_nbt_length(state->vector,
4206 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
4207 if (!ok) {
4208 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
4209 return tevent_req_post(req, ev);
4213 * We require TCP acks for this PDU to the client!
4214 * We want 5 retransmissions and timeout when the
4215 * retransmission timeout (rto) passed 6 times.
4217 * required_acked_bytes gets a dummy value of
4218 * UINT64_MAX, as long it's in xconn->smb2.send_queue,
4219 * it'll get the real value when it's moved to
4220 * xconn->ack.queue.
4222 * state->queue_entry.ack.req gets completed with
4223 * 1. tevent_req_done(), when all bytes are acked.
4224 * 2a. tevent_req_nterror(NT_STATUS_IO_TIMEOUT), when
4225 * the timeout expired before all bytes were acked.
4226 * 2b. tevent_req_nterror(transport_error), when the
4227 * connection got a disconnect from the kernel.
4229 state->queue_entry.ack.timeout =
4230 timeval_current_ofs_usec(xconn->ack.rto_usecs * 6);
4231 state->queue_entry.ack.required_acked_bytes = UINT64_MAX;
4232 state->queue_entry.ack.req = req;
4233 state->queue_entry.mem_ctx = state;
4234 state->queue_entry.vector = state->vector;
4235 state->queue_entry.count = ARRAY_SIZE(state->vector);
4236 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
4237 xconn->smb2.send_queue_len++;
4239 status = smbd_smb2_flush_send_queue(xconn);
4240 if (tevent_req_nterror(req, status)) {
4241 return tevent_req_post(req, ev);
4244 return req;
4247 static NTSTATUS smbd_smb2_break_recv(struct tevent_req *req)
4249 return tevent_req_simple_recv_ntstatus(req);
4252 struct smbXsrv_pending_break {
4253 struct smbXsrv_pending_break *prev, *next;
4254 struct smbXsrv_client *client;
4255 bool disable_oplock_break_retries;
4256 uint64_t session_id;
4257 uint64_t last_channel_id;
4258 union {
4259 uint8_t generic[1];
4260 uint8_t oplock[0x18];
4261 uint8_t lease[0x2c];
4262 } body;
4263 size_t body_len;
4266 static void smbXsrv_pending_break_done(struct tevent_req *subreq);
4268 static struct smbXsrv_pending_break *smbXsrv_pending_break_create(
4269 struct smbXsrv_client *client,
4270 uint64_t session_id)
4272 struct smbXsrv_pending_break *pb = NULL;
4274 pb = talloc_zero(client, struct smbXsrv_pending_break);
4275 if (pb == NULL) {
4276 return NULL;
4278 pb->client = client;
4279 pb->session_id = session_id;
4280 pb->disable_oplock_break_retries = lp_smb2_disable_oplock_break_retry();
4282 return pb;
4285 static NTSTATUS smbXsrv_pending_break_submit(struct smbXsrv_pending_break *pb);
4287 static NTSTATUS smbXsrv_pending_break_schedule(struct smbXsrv_pending_break *pb)
4289 struct smbXsrv_client *client = pb->client;
4290 NTSTATUS status;
4292 DLIST_ADD_END(client->pending_breaks, pb);
4293 status = smbXsrv_client_pending_breaks_updated(client);
4294 if (!NT_STATUS_IS_OK(status)) {
4295 return status;
4298 status = smbXsrv_pending_break_submit(pb);
4299 if (!NT_STATUS_IS_OK(status)) {
4300 return status;
4303 return NT_STATUS_OK;
4306 static NTSTATUS smbXsrv_pending_break_submit(struct smbXsrv_pending_break *pb)
4308 struct smbXsrv_client *client = pb->client;
4309 struct smbXsrv_session *session = NULL;
4310 struct smbXsrv_connection *xconn = NULL;
4311 struct smbXsrv_connection *oplock_xconn = NULL;
4312 struct tevent_req *subreq = NULL;
4313 NTSTATUS status;
4315 if (pb->session_id != 0) {
4316 status = get_valid_smbXsrv_session(client,
4317 pb->session_id,
4318 &session);
4319 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
4320 return NT_STATUS_ABANDONED;
4322 if (!NT_STATUS_IS_OK(status)) {
4323 return status;
4326 if (pb->last_channel_id != 0) {
4328 * This is what current Windows servers
4329 * do, they don't retry on all available
4330 * channels. They only use the last channel.
4332 * But it doesn't match the specification in
4333 * [MS-SMB2] "3.3.4.6 Object Store Indicates an
4334 * Oplock Break"
4336 * Per default disable_oplock_break_retries is false
4337 * and we behave like the specification.
4339 if (pb->disable_oplock_break_retries) {
4340 return NT_STATUS_ABANDONED;
4345 for (xconn = client->connections; xconn != NULL; xconn = xconn->next) {
4346 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
4347 continue;
4350 if (xconn->channel_id == 0) {
4352 * non-multichannel case
4354 break;
4357 if (session != NULL) {
4358 struct smbXsrv_channel_global0 *c = NULL;
4361 * Having a session means we're handling
4362 * an oplock break and we only need to
4363 * use channels available on the
4364 * session.
4366 status = smbXsrv_session_find_channel(session, xconn, &c);
4367 if (!NT_STATUS_IS_OK(status)) {
4368 continue;
4372 * This is what current Windows servers
4373 * do, they don't retry on all available
4374 * channels. They only use the last channel.
4376 * But it doesn't match the specification
4377 * in [MS-SMB2] "3.3.4.6 Object Store Indicates an
4378 * Oplock Break"
4380 * Per default disable_oplock_break_retries is false
4381 * and we behave like the specification.
4383 if (pb->disable_oplock_break_retries) {
4384 oplock_xconn = xconn;
4385 continue;
4389 if (xconn->channel_id > pb->last_channel_id) {
4391 * multichannel case
4393 break;
4397 if (xconn == NULL) {
4398 xconn = oplock_xconn;
4401 if (xconn == NULL) {
4403 * If there's no remaining connection available
4404 * tell the caller to stop...
4406 return NT_STATUS_ABANDONED;
4409 pb->last_channel_id = xconn->channel_id;
4411 subreq = smbd_smb2_break_send(pb,
4412 client->raw_ev_ctx,
4413 xconn,
4414 pb->session_id,
4415 pb->body.generic,
4416 pb->body_len);
4417 if (subreq == NULL) {
4418 return NT_STATUS_NO_MEMORY;
4420 tevent_req_set_callback(subreq,
4421 smbXsrv_pending_break_done,
4422 pb);
4424 return NT_STATUS_OK;
4427 static void smbXsrv_pending_break_done(struct tevent_req *subreq)
4429 struct smbXsrv_pending_break *pb =
4430 tevent_req_callback_data(subreq,
4431 struct smbXsrv_pending_break);
4432 struct smbXsrv_client *client = pb->client;
4433 NTSTATUS status;
4435 status = smbd_smb2_break_recv(subreq);
4436 TALLOC_FREE(subreq);
4437 if (!NT_STATUS_IS_OK(status)) {
4438 status = smbXsrv_pending_break_submit(pb);
4439 if (NT_STATUS_EQUAL(status, NT_STATUS_ABANDONED)) {
4441 * If there's no remaining connection
4442 * there's no need to send a break again.
4444 goto remove;
4446 if (!NT_STATUS_IS_OK(status)) {
4447 smbd_server_disconnect_client(client, nt_errstr(status));
4448 return;
4450 return;
4453 remove:
4454 DLIST_REMOVE(client->pending_breaks, pb);
4455 TALLOC_FREE(pb);
4457 status = smbXsrv_client_pending_breaks_updated(client);
4458 if (!NT_STATUS_IS_OK(status)) {
4459 smbd_server_disconnect_client(client, nt_errstr(status));
4460 return;
4464 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_client *client,
4465 struct smbXsrv_open *op,
4466 uint8_t oplock_level)
4468 struct smbXsrv_pending_break *pb = NULL;
4469 uint8_t *body = NULL;
4471 pb = smbXsrv_pending_break_create(client,
4472 op->compat->vuid);
4473 if (pb == NULL) {
4474 return NT_STATUS_NO_MEMORY;
4476 pb->body_len = sizeof(pb->body.oplock);
4477 body = pb->body.oplock;
4479 SSVAL(body, 0x00, pb->body_len);
4480 SCVAL(body, 0x02, oplock_level);
4481 SCVAL(body, 0x03, 0); /* reserved */
4482 SIVAL(body, 0x04, 0); /* reserved */
4483 SBVAL(body, 0x08, op->global->open_persistent_id);
4484 SBVAL(body, 0x10, op->global->open_volatile_id);
4486 return smbXsrv_pending_break_schedule(pb);
4489 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_client *client,
4490 uint16_t new_epoch,
4491 uint32_t lease_flags,
4492 struct smb2_lease_key *lease_key,
4493 uint32_t current_lease_state,
4494 uint32_t new_lease_state)
4496 struct smbXsrv_pending_break *pb = NULL;
4497 uint8_t *body = NULL;
4499 pb = smbXsrv_pending_break_create(client,
4500 0); /* no session_id */
4501 if (pb == NULL) {
4502 return NT_STATUS_NO_MEMORY;
4504 pb->body_len = sizeof(pb->body.lease);
4505 body = pb->body.lease;
4507 SSVAL(body, 0x00, pb->body_len);
4508 SSVAL(body, 0x02, new_epoch);
4509 SIVAL(body, 0x04, lease_flags);
4510 SBVAL(body, 0x08, lease_key->data[0]);
4511 SBVAL(body, 0x10, lease_key->data[1]);
4512 SIVAL(body, 0x18, current_lease_state);
4513 SIVAL(body, 0x1c, new_lease_state);
4514 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
4515 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
4516 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
4518 return smbXsrv_pending_break_schedule(pb);
4521 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
4523 NTSTATUS status;
4524 uint32_t flags;
4525 uint64_t file_id_persistent;
4526 uint64_t file_id_volatile;
4527 struct smbXsrv_open *op = NULL;
4528 struct files_struct *fsp = NULL;
4529 const uint8_t *body = NULL;
4532 * This is only called with a pktbuf
4533 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
4534 * bytes
4537 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
4538 /* Transform header. Cannot recvfile. */
4539 return false;
4541 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
4542 /* Not SMB2. Normal error path will cope. */
4543 return false;
4545 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
4546 /* Not SMB2. Normal error path will cope. */
4547 return false;
4549 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
4550 /* Needs to be a WRITE. */
4551 return false;
4553 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
4554 /* Chained. Cannot recvfile. */
4555 return false;
4557 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
4558 if (flags & SMB2_HDR_FLAG_CHAINED) {
4559 /* Chained. Cannot recvfile. */
4560 return false;
4562 if (flags & SMB2_HDR_FLAG_SIGNED) {
4563 /* Signed. Cannot recvfile. */
4564 return false;
4567 body = &state->pktbuf[SMB2_HDR_BODY];
4569 file_id_persistent = BVAL(body, 0x10);
4570 file_id_volatile = BVAL(body, 0x18);
4572 status = smb2srv_open_lookup(state->req->xconn,
4573 file_id_persistent,
4574 file_id_volatile,
4575 0, /* now */
4576 &op);
4577 if (!NT_STATUS_IS_OK(status)) {
4578 return false;
4581 fsp = op->compat;
4582 if (fsp == NULL) {
4583 return false;
4585 if (fsp->conn == NULL) {
4586 return false;
4589 if (IS_IPC(fsp->conn)) {
4590 return false;
4592 if (IS_PRINT(fsp->conn)) {
4593 return false;
4595 if (fsp_is_alternate_stream(fsp)) {
4596 return false;
4599 DEBUG(10,("Doing recvfile write len = %u\n",
4600 (unsigned int)(state->pktfull - state->pktlen)));
4602 return true;
4605 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
4607 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
4608 struct smbd_smb2_request *req = NULL;
4609 size_t max_send_queue_len;
4610 size_t cur_send_queue_len;
4612 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
4614 * we're not supposed to do any io
4616 return NT_STATUS_OK;
4619 if (state->req != NULL) {
4621 * if there is already a tstream_readv_pdu
4622 * pending, we are done.
4624 return NT_STATUS_OK;
4627 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
4628 cur_send_queue_len = xconn->smb2.send_queue_len;
4630 if (cur_send_queue_len > max_send_queue_len) {
4632 * if we have a lot of requests to send,
4633 * we wait until they are on the wire until we
4634 * ask for the next request.
4636 return NT_STATUS_OK;
4639 /* ask for the next request */
4640 req = smbd_smb2_request_allocate(xconn);
4641 if (req == NULL) {
4642 return NT_STATUS_NO_MEMORY;
4644 *state = (struct smbd_smb2_request_read_state) {
4645 .req = req,
4646 .min_recv_size = lp_min_receive_file_size(),
4647 ._vector = {
4648 [0] = (struct iovec) {
4649 .iov_base = (void *)state->hdr.nbt,
4650 .iov_len = NBT_HDR_SIZE,
4653 .vector = state->_vector,
4654 .count = 1,
4657 TEVENT_FD_READABLE(xconn->transport.fde);
4659 return NT_STATUS_OK;
4662 NTSTATUS smbd_smb2_process_negprot(struct smbXsrv_connection *xconn,
4663 uint64_t expected_seq_low,
4664 const uint8_t *inpdu, size_t size)
4666 struct smbd_server_connection *sconn = xconn->client->sconn;
4667 NTSTATUS status;
4668 struct smbd_smb2_request *req = NULL;
4670 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
4671 (unsigned int)size));
4673 status = smbd_initialize_smb2(xconn, expected_seq_low);
4674 if (!NT_STATUS_IS_OK(status)) {
4675 smbd_server_connection_terminate(xconn, nt_errstr(status));
4676 return status;
4680 * If a new connection joins the process, when we're
4681 * already in a "pending break cycle", we need to
4682 * turn on the ack checker on the new connection.
4684 status = smbXsrv_client_pending_breaks_updated(xconn->client);
4685 if (!NT_STATUS_IS_OK(status)) {
4687 * If there's a problem, we disconnect the whole
4688 * client with all connections here!
4690 * Instead of just the new connection.
4692 smbd_server_disconnect_client(xconn->client, nt_errstr(status));
4693 return status;
4696 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
4697 if (!NT_STATUS_IS_OK(status)) {
4698 smbd_server_connection_terminate(xconn, nt_errstr(status));
4699 return status;
4702 status = smbd_smb2_request_validate(req);
4703 if (!NT_STATUS_IS_OK(status)) {
4704 smbd_server_connection_terminate(xconn, nt_errstr(status));
4705 return status;
4708 status = smbd_smb2_request_setup_out(req);
4709 if (!NT_STATUS_IS_OK(status)) {
4710 smbd_server_connection_terminate(xconn, nt_errstr(status));
4711 return status;
4714 #ifdef WITH_PROFILE
4716 * this was already counted at the SMB1 layer =>
4717 * smbd_smb2_request_dispatch() should not count it twice.
4719 if (profile_p->values.request_stats.count > 0) {
4720 profile_p->values.request_stats.count--;
4722 #endif
4723 status = smbd_smb2_request_dispatch(req);
4724 if (!NT_STATUS_IS_OK(status)) {
4725 smbd_server_connection_terminate(xconn, nt_errstr(status));
4726 return status;
4729 status = smbd_smb2_request_next_incoming(xconn);
4730 if (!NT_STATUS_IS_OK(status)) {
4731 smbd_server_connection_terminate(xconn, nt_errstr(status));
4732 return status;
4735 sconn->num_requests++;
4736 return NT_STATUS_OK;
4739 static int socket_error_from_errno(int ret,
4740 int sys_errno,
4741 bool *retry)
4743 *retry = false;
4745 if (ret >= 0) {
4746 return 0;
4749 if (ret != -1) {
4750 return EIO;
4753 if (sys_errno == 0) {
4754 return EIO;
4757 if (sys_errno == EINTR) {
4758 *retry = true;
4759 return sys_errno;
4762 if (sys_errno == EINPROGRESS) {
4763 *retry = true;
4764 return sys_errno;
4767 if (sys_errno == EAGAIN) {
4768 *retry = true;
4769 return sys_errno;
4772 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
4773 if (sys_errno == ENOMEM) {
4774 *retry = true;
4775 return sys_errno;
4778 #ifdef EWOULDBLOCK
4779 #if EWOULDBLOCK != EAGAIN
4780 if (sys_errno == EWOULDBLOCK) {
4781 *retry = true;
4782 return sys_errno;
4784 #endif
4785 #endif
4787 return sys_errno;
4790 static NTSTATUS smbd_smb2_advance_send_queue(struct smbXsrv_connection *xconn,
4791 struct smbd_smb2_send_queue **_e,
4792 size_t n)
4794 struct smbd_smb2_send_queue *e = *_e;
4795 bool ok;
4797 xconn->ack.unacked_bytes += n;
4799 ok = iov_advance(&e->vector, &e->count, n);
4800 if (!ok) {
4801 return NT_STATUS_INTERNAL_ERROR;
4804 if (e->count > 0) {
4805 return NT_STATUS_RETRY;
4808 xconn->smb2.send_queue_len--;
4809 DLIST_REMOVE(xconn->smb2.send_queue, e);
4811 if (e->ack.req == NULL) {
4812 *_e = NULL;
4813 talloc_free(e->mem_ctx);
4814 return NT_STATUS_OK;
4817 e->ack.required_acked_bytes = xconn->ack.unacked_bytes;
4818 DLIST_ADD_END(xconn->ack.queue, e);
4820 return NT_STATUS_OK;
4823 static NTSTATUS smbd_smb2_flush_with_sendmsg(struct smbXsrv_connection *xconn)
4825 int ret;
4826 int err;
4827 bool retry;
4828 NTSTATUS status;
4830 if (xconn->smb2.send_queue == NULL) {
4831 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
4832 return NT_STATUS_OK;
4835 while (xconn->smb2.send_queue != NULL) {
4836 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
4837 unsigned sendmsg_flags = 0;
4839 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
4841 * we're not supposed to do any io
4842 * just flush all pending stuff.
4844 xconn->smb2.send_queue_len--;
4845 DLIST_REMOVE(xconn->smb2.send_queue, e);
4847 talloc_free(e->mem_ctx);
4848 continue;
4851 if (e->sendfile_header != NULL) {
4852 size_t size = 0;
4853 size_t i = 0;
4854 uint8_t *buf;
4856 status = NT_STATUS_INTERNAL_ERROR;
4858 for (i=0; i < e->count; i++) {
4859 size += e->vector[i].iov_len;
4862 if (size <= e->sendfile_header->length) {
4863 buf = e->sendfile_header->data;
4864 } else {
4865 buf = talloc_array(e->mem_ctx, uint8_t, size);
4866 if (buf == NULL) {
4867 return NT_STATUS_NO_MEMORY;
4871 size = 0;
4872 for (i=0; i < e->count; i++) {
4873 memcpy(buf+size,
4874 e->vector[i].iov_base,
4875 e->vector[i].iov_len);
4876 size += e->vector[i].iov_len;
4879 e->sendfile_header->data = buf;
4880 e->sendfile_header->length = size;
4881 e->sendfile_status = &status;
4882 e->count = 0;
4884 xconn->smb2.send_queue_len--;
4885 DLIST_REMOVE(xconn->smb2.send_queue, e);
4887 size += e->sendfile_body_size;
4890 * This triggers the sendfile path via
4891 * the destructor.
4893 talloc_free(e->mem_ctx);
4895 if (!NT_STATUS_IS_OK(status)) {
4896 smbXsrv_connection_disconnect_transport(xconn,
4897 status);
4898 return status;
4900 xconn->ack.unacked_bytes += size;
4901 continue;
4904 e->msg = (struct msghdr) {
4905 .msg_iov = e->vector,
4906 .msg_iovlen = e->count,
4909 #ifdef MSG_NOSIGNAL
4910 sendmsg_flags |= MSG_NOSIGNAL;
4911 #endif
4912 #ifdef MSG_DONTWAIT
4913 sendmsg_flags |= MSG_DONTWAIT;
4914 #endif
4916 ret = sendmsg(xconn->transport.sock, &e->msg, sendmsg_flags);
4917 if (ret == 0) {
4918 /* propagate end of file */
4919 return NT_STATUS_INTERNAL_ERROR;
4921 err = socket_error_from_errno(ret, errno, &retry);
4922 if (retry) {
4923 /* retry later */
4924 TEVENT_FD_WRITEABLE(xconn->transport.fde);
4925 return NT_STATUS_OK;
4927 if (err != 0) {
4928 status = map_nt_error_from_unix_common(err);
4929 smbXsrv_connection_disconnect_transport(xconn,
4930 status);
4931 return status;
4934 status = smbd_smb2_advance_send_queue(xconn, &e, ret);
4935 if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4936 /* retry later */
4937 TEVENT_FD_WRITEABLE(xconn->transport.fde);
4938 return NT_STATUS_OK;
4940 if (!NT_STATUS_IS_OK(status)) {
4941 smbXsrv_connection_disconnect_transport(xconn,
4942 status);
4943 return status;
4947 return NT_STATUS_MORE_PROCESSING_REQUIRED;
4950 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
4952 NTSTATUS status;
4954 status = smbd_smb2_flush_with_sendmsg(xconn);
4955 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
4956 return status;
4960 * Restart reads if we were blocked on
4961 * draining the send queue.
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 NTSTATUS smbd_smb2_advance_incoming(struct smbXsrv_connection *xconn, size_t n)
4974 struct smbd_server_connection *sconn = xconn->client->sconn;
4975 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
4976 struct smbd_smb2_request *req = NULL;
4977 size_t min_recvfile_size = UINT32_MAX;
4978 NTSTATUS status;
4979 NTTIME now;
4980 bool ok;
4982 ok = iov_advance(&state->vector, &state->count, n);
4983 if (!ok) {
4984 return NT_STATUS_INTERNAL_ERROR;
4987 if (state->count > 0) {
4988 return NT_STATUS_PENDING;
4991 if (state->pktlen > 0) {
4992 if (!state->doing_receivefile) {
4994 * we have all the data.
4996 goto got_full;
4999 if (!is_smb2_recvfile_write(state)) {
5000 size_t ofs = state->pktlen;
5003 * Not a possible receivefile write.
5004 * Read the rest of the data.
5006 state->doing_receivefile = false;
5008 state->pktbuf = talloc_realloc(state->req,
5009 state->pktbuf,
5010 uint8_t,
5011 state->pktfull);
5012 if (state->pktbuf == NULL) {
5013 return NT_STATUS_NO_MEMORY;
5016 state->_vector[0] = (struct iovec) {
5017 .iov_base = (void *)(state->pktbuf + ofs),
5018 .iov_len = (state->pktfull - ofs),
5020 state->vector = state->_vector;
5021 state->count = 1;
5023 state->pktlen = state->pktfull;
5024 return NT_STATUS_RETRY;
5028 * This is a receivefile write so we've
5029 * done a short read.
5031 goto got_full;
5035 * Now we analyze the NBT header
5037 if (state->hdr.nbt[0] != 0x00) {
5038 state->min_recv_size = 0;
5040 state->pktfull = smb2_len(state->hdr.nbt);
5041 if (state->pktfull == 0) {
5042 goto got_full;
5045 if (state->min_recv_size != 0) {
5046 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
5047 min_recvfile_size += state->min_recv_size;
5050 if (state->pktfull > min_recvfile_size) {
5052 * Might be a receivefile write. Read the SMB2 HEADER +
5053 * SMB2_WRITE header first. Set 'doing_receivefile'
5054 * as we're *attempting* receivefile write. If this
5055 * turns out not to be a SMB2_WRITE request or otherwise
5056 * not suitable then we'll just read the rest of the data
5057 * the next time this function is called.
5059 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
5060 state->doing_receivefile = true;
5061 } else {
5062 state->pktlen = state->pktfull;
5065 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
5066 if (state->pktbuf == NULL) {
5067 return NT_STATUS_NO_MEMORY;
5070 state->_vector[0] = (struct iovec) {
5071 .iov_base = (void *)state->pktbuf,
5072 .iov_len = state->pktlen,
5074 state->vector = state->_vector;
5075 state->count = 1;
5077 return NT_STATUS_RETRY;
5079 got_full:
5081 if (state->hdr.nbt[0] != 0x00) {
5082 DEBUG(1,("ignore NBT[0x%02X] msg\n",
5083 state->hdr.nbt[0]));
5085 req = state->req;
5086 *state = (struct smbd_smb2_request_read_state) {
5087 .req = req,
5088 .min_recv_size = lp_min_receive_file_size(),
5089 ._vector = {
5090 [0] = (struct iovec) {
5091 .iov_base = (void *)state->hdr.nbt,
5092 .iov_len = NBT_HDR_SIZE,
5095 .vector = state->_vector,
5096 .count = 1,
5098 return NT_STATUS_RETRY;
5101 req = state->req;
5103 req->request_time = timeval_current();
5104 now = timeval_to_nttime(&req->request_time);
5106 status = smbd_smb2_inbuf_parse_compound(xconn,
5107 now,
5108 state->pktbuf,
5109 state->pktlen,
5110 req,
5111 &req->in.vector,
5112 &req->in.vector_count);
5113 if (!NT_STATUS_IS_OK(status)) {
5114 return status;
5117 if (state->doing_receivefile) {
5118 req->smb1req = talloc_zero(req, struct smb_request);
5119 if (req->smb1req == NULL) {
5120 return NT_STATUS_NO_MEMORY;
5122 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
5125 *state = (struct smbd_smb2_request_read_state) {
5126 .req = NULL,
5129 req->current_idx = 1;
5131 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
5132 req->current_idx, req->in.vector_count));
5134 status = smbd_smb2_request_validate(req);
5135 if (!NT_STATUS_IS_OK(status)) {
5136 return status;
5139 status = smbd_smb2_request_setup_out(req);
5140 if (!NT_STATUS_IS_OK(status)) {
5141 return status;
5144 status = smbd_smb2_request_dispatch(req);
5145 if (!NT_STATUS_IS_OK(status)) {
5146 return status;
5149 sconn->num_requests++;
5151 /* The timeout_processing function isn't run nearly
5152 often enough to implement 'max log size' without
5153 overrunning the size of the file by many megabytes.
5154 This is especially true if we are running at debug
5155 level 10. Checking every 50 SMB2s is a nice
5156 tradeoff of performance vs log file size overrun. */
5158 if ((sconn->num_requests % 50) == 0 &&
5159 need_to_check_log_size()) {
5160 change_to_root_user();
5161 check_log_size();
5164 status = smbd_smb2_request_next_incoming(xconn);
5165 if (!NT_STATUS_IS_OK(status)) {
5166 return status;
5169 return NT_STATUS_OK;
5172 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
5173 uint16_t fde_flags)
5175 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
5176 unsigned recvmsg_flags = 0;
5177 int ret;
5178 int err;
5179 bool retry;
5180 NTSTATUS status;
5182 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
5184 * we're not supposed to do any io
5186 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
5187 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
5188 TEVENT_FD_NOT_WANTERROR(xconn->transport.fde);
5189 return NT_STATUS_OK;
5192 if (fde_flags & TEVENT_FD_ERROR) {
5193 ret = samba_socket_poll_or_sock_error(xconn->transport.sock);
5194 if (ret == -1) {
5195 err = errno;
5196 status = map_nt_error_from_unix_common(err);
5197 smbXsrv_connection_disconnect_transport(xconn,
5198 status);
5199 return status;
5201 /* This should not happen */
5202 status = NT_STATUS_REMOTE_DISCONNECT;
5203 smbXsrv_connection_disconnect_transport(xconn,
5204 status);
5205 return status;
5208 if (fde_flags & TEVENT_FD_WRITE) {
5209 status = smbd_smb2_flush_send_queue(xconn);
5210 if (!NT_STATUS_IS_OK(status)) {
5211 return status;
5215 if (!(fde_flags & TEVENT_FD_READ)) {
5216 return NT_STATUS_OK;
5219 if (state->req == NULL) {
5220 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
5221 return NT_STATUS_OK;
5224 again:
5226 state->msg = (struct msghdr) {
5227 .msg_iov = state->vector,
5228 .msg_iovlen = state->count,
5231 #ifdef MSG_NOSIGNAL
5232 recvmsg_flags |= MSG_NOSIGNAL;
5233 #endif
5234 #ifdef MSG_DONTWAIT
5235 recvmsg_flags |= MSG_DONTWAIT;
5236 #endif
5238 ret = recvmsg(xconn->transport.sock, &state->msg, recvmsg_flags);
5239 if (ret == 0) {
5240 /* propagate end of file */
5241 status = NT_STATUS_END_OF_FILE;
5242 smbXsrv_connection_disconnect_transport(xconn,
5243 status);
5244 return status;
5246 err = socket_error_from_errno(ret, errno, &retry);
5247 if (retry) {
5248 /* retry later */
5249 TEVENT_FD_READABLE(xconn->transport.fde);
5250 return NT_STATUS_OK;
5252 if (err != 0) {
5253 status = map_nt_error_from_unix_common(err);
5254 smbXsrv_connection_disconnect_transport(xconn,
5255 status);
5256 return status;
5259 status = smbd_smb2_advance_incoming(xconn, ret);
5260 if (NT_STATUS_EQUAL(status, NT_STATUS_PENDING)) {
5261 /* we have more to read */
5262 TEVENT_FD_READABLE(xconn->transport.fde);
5263 return NT_STATUS_OK;
5265 if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5267 * smbd_smb2_advance_incoming setup a new vector
5268 * that we should try to read immediately.
5270 goto again;
5272 if (!NT_STATUS_IS_OK(status)) {
5273 return status;
5276 return NT_STATUS_OK;
5279 static void smbd_smb2_connection_handler(struct tevent_context *ev,
5280 struct tevent_fd *fde,
5281 uint16_t flags,
5282 void *private_data)
5284 struct smbXsrv_connection *xconn =
5285 talloc_get_type_abort(private_data,
5286 struct smbXsrv_connection);
5287 NTSTATUS status;
5289 status = smbd_smb2_io_handler(xconn, flags);
5290 if (!NT_STATUS_IS_OK(status)) {
5291 smbd_server_connection_terminate(xconn, nt_errstr(status));
5292 return;