libsmb: Add reparse_data_buffer_marshall()
[Samba.git] / source3 / smbd / smb2_server.c
blob55b383072e6a3cf1bca466127fed71c978578e3b
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 "smbd/smbXsrv_open.h"
27 #include "lib/param/param.h"
28 #include "../libcli/smb/smb_common.h"
29 #include "../lib/tsocket/tsocket.h"
30 #include "../lib/util/tevent_ntstatus.h"
31 #include "smbprofile.h"
32 #include "../lib/util/bitmap.h"
33 #include "../librpc/gen_ndr/krb5pac.h"
34 #include "lib/util/iov_buf.h"
35 #include "auth.h"
36 #include "libcli/smb/smbXcli_base.h"
37 #include "source3/lib/substitute.h"
39 #if defined(LINUX)
40 /* SIOCOUTQ TIOCOUTQ are the same */
41 #define __IOCTL_SEND_QUEUE_SIZE_OPCODE TIOCOUTQ
42 #define __HAVE_TCP_INFO_RTO 1
43 #define __ALLOW_MULTI_CHANNEL_SUPPORT 1
44 #elif defined(FREEBSD)
45 #define __IOCTL_SEND_QUEUE_SIZE_OPCODE FIONWRITE
46 #define __HAVE_TCP_INFO_RTO 1
47 #define __ALLOW_MULTI_CHANNEL_SUPPORT 1
48 #endif
50 #include "lib/crypto/gnutls_helpers.h"
51 #include <gnutls/gnutls.h>
52 #include <gnutls/crypto.h>
54 #undef DBGC_CLASS
55 #define DBGC_CLASS DBGC_SMB2
57 static void smbd_smb2_connection_handler(struct tevent_context *ev,
58 struct tevent_fd *fde,
59 uint16_t flags,
60 void *private_data);
61 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn);
63 static const struct smbd_smb2_dispatch_table {
64 uint16_t opcode;
65 uint16_t fileid_ofs;
66 bool need_session : 1;
67 bool need_tcon : 1;
68 bool as_root : 1;
69 bool modify : 1;
70 } smbd_smb2_table[] = {
72 .opcode = SMB2_OP_NEGPROT,
73 .as_root = true,
74 },{
75 .opcode = SMB2_OP_SESSSETUP,
76 .as_root = true,
77 },{
78 .opcode = SMB2_OP_LOGOFF,
79 .need_session = true,
80 .as_root = true,
81 },{
82 .opcode = SMB2_OP_TCON,
83 .need_session = true,
85 * This call needs to be run as root.
87 * smbd_smb2_request_process_tcon()
88 * calls make_connection_snum(), which will call
89 * change_to_user(), when needed.
91 .as_root = true,
92 },{
93 .opcode = SMB2_OP_TDIS,
94 .need_session = true,
95 .need_tcon = true,
96 .as_root = true,
97 },{
98 .opcode = SMB2_OP_CREATE,
99 .need_session = true,
100 .need_tcon = true,
102 .opcode = SMB2_OP_CLOSE,
103 .need_session = true,
104 .need_tcon = true,
105 .fileid_ofs = 0x08,
107 .opcode = SMB2_OP_FLUSH,
108 .need_session = true,
109 .need_tcon = true,
110 .fileid_ofs = 0x08,
112 .opcode = SMB2_OP_READ,
113 .need_session = true,
114 .need_tcon = true,
115 .fileid_ofs = 0x10,
117 .opcode = SMB2_OP_WRITE,
118 .need_session = true,
119 .need_tcon = true,
120 .fileid_ofs = 0x10,
121 .modify = true,
123 .opcode = SMB2_OP_LOCK,
124 .need_session = true,
125 .need_tcon = true,
126 .fileid_ofs = 0x08,
128 .opcode = SMB2_OP_IOCTL,
129 .need_session = true,
130 .need_tcon = true,
131 .fileid_ofs = 0x08,
132 .modify = true,
134 .opcode = SMB2_OP_CANCEL,
135 .as_root = true,
137 .opcode = SMB2_OP_KEEPALIVE,
139 .opcode = SMB2_OP_QUERY_DIRECTORY,
140 .need_session = true,
141 .need_tcon = true,
142 .fileid_ofs = 0x08,
144 .opcode = SMB2_OP_NOTIFY,
145 .need_session = true,
146 .need_tcon = true,
147 .fileid_ofs = 0x08,
149 .opcode = SMB2_OP_GETINFO,
150 .need_session = true,
151 .need_tcon = true,
152 .fileid_ofs = 0x18,
154 .opcode = SMB2_OP_SETINFO,
155 .need_session = true,
156 .need_tcon = true,
157 .fileid_ofs = 0x10,
158 .modify = true,
160 .opcode = SMB2_OP_BREAK,
161 .need_session = true,
162 .need_tcon = true,
164 * we do not set
165 * .fileid_ofs here
166 * as LEASE breaks does not
167 * have a file id
172 const char *smb2_opcode_name(uint16_t opcode)
174 const char *result = "Bad SMB2 opcode";
176 switch (opcode) {
177 case SMB2_OP_NEGPROT:
178 result = "SMB2_OP_NEGPROT";
179 break;
180 case SMB2_OP_SESSSETUP:
181 result = "SMB2_OP_SESSSETUP";
182 break;
183 case SMB2_OP_LOGOFF:
184 result = "SMB2_OP_LOGOFF";
185 break;
186 case SMB2_OP_TCON:
187 result = "SMB2_OP_TCON";
188 break;
189 case SMB2_OP_TDIS:
190 result = "SMB2_OP_TDIS";
191 break;
192 case SMB2_OP_CREATE:
193 result = "SMB2_OP_CREATE";
194 break;
195 case SMB2_OP_CLOSE:
196 result = "SMB2_OP_CLOSE";
197 break;
198 case SMB2_OP_FLUSH:
199 result = "SMB2_OP_FLUSH";
200 break;
201 case SMB2_OP_READ:
202 result = "SMB2_OP_READ";
203 break;
204 case SMB2_OP_WRITE:
205 result = "SMB2_OP_WRITE";
206 break;
207 case SMB2_OP_LOCK:
208 result = "SMB2_OP_LOCK";
209 break;
210 case SMB2_OP_IOCTL:
211 result = "SMB2_OP_IOCTL";
212 break;
213 case SMB2_OP_CANCEL:
214 result = "SMB2_OP_CANCEL";
215 break;
216 case SMB2_OP_KEEPALIVE:
217 result = "SMB2_OP_KEEPALIVE";
218 break;
219 case SMB2_OP_QUERY_DIRECTORY:
220 result = "SMB2_OP_QUERY_DIRECTORY";
221 break;
222 case SMB2_OP_NOTIFY:
223 result = "SMB2_OP_NOTIFY";
224 break;
225 case SMB2_OP_GETINFO:
226 result = "SMB2_OP_GETINFO";
227 break;
228 case SMB2_OP_SETINFO:
229 result = "SMB2_OP_SETINFO";
230 break;
231 case SMB2_OP_BREAK:
232 result = "SMB2_OP_BREAK";
233 break;
234 default:
235 break;
237 return result;
240 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
242 const struct smbd_smb2_dispatch_table *ret = NULL;
244 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
245 return NULL;
248 ret = &smbd_smb2_table[opcode];
250 SMB_ASSERT(ret->opcode == opcode);
252 return ret;
255 static void print_req_vectors(const struct smbd_smb2_request *req)
257 int i;
259 for (i = 0; i < req->in.vector_count; i++) {
260 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
261 (unsigned int)i,
262 (unsigned int)req->in.vector[i].iov_len);
264 for (i = 0; i < req->out.vector_count; i++) {
265 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
266 (unsigned int)i,
267 (unsigned int)req->out.vector[i].iov_len);
271 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
273 if (size < (4 + SMB2_HDR_BODY)) {
274 return false;
277 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
278 return false;
281 return true;
284 bool smbd_smb2_is_compound(const struct smbd_smb2_request *req)
286 return req->in.vector_count >= (2*SMBD_SMB2_NUM_IOV_PER_REQ);
289 bool smbd_smb2_is_last_in_compound(const struct smbd_smb2_request *req)
291 return (req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ ==
292 req->in.vector_count);
295 static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn,
296 uint64_t expected_seq_low)
298 int rc;
300 xconn->smb2.credits.seq_low = expected_seq_low;
301 xconn->smb2.credits.seq_range = 1;
302 xconn->smb2.credits.granted = 1;
303 xconn->smb2.credits.max = lp_smb2_max_credits();
304 xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
305 xconn->smb2.credits.max);
306 if (xconn->smb2.credits.bitmap == NULL) {
307 return NT_STATUS_NO_MEMORY;
310 tevent_fd_set_close_fn(xconn->transport.fde, NULL);
311 TALLOC_FREE(xconn->transport.fde);
313 xconn->transport.fde = tevent_add_fd(
314 xconn->client->raw_ev_ctx,
315 xconn,
316 xconn->transport.sock,
317 TEVENT_FD_READ,
318 smbd_smb2_connection_handler,
319 xconn);
320 if (xconn->transport.fde == NULL) {
321 close(xconn->transport.sock);
322 xconn->transport.sock = -1;
323 return NT_STATUS_NO_MEMORY;
325 tevent_fd_set_auto_close(xconn->transport.fde);
328 * Ensure child is set to non-blocking mode,
329 * unless the system supports MSG_DONTWAIT,
330 * if MSG_DONTWAIT is available we should force
331 * blocking mode.
333 #ifdef MSG_DONTWAIT
334 rc = set_blocking(xconn->transport.sock, true);
335 if (rc < 0) {
336 return NT_STATUS_INTERNAL_ERROR;
338 #else
339 rc = set_blocking(xconn->transport.sock, false);
340 if (rc < 0) {
341 return NT_STATUS_INTERNAL_ERROR;
343 #endif
345 return NT_STATUS_OK;
348 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
349 #define _smb2_setlen(_buf,len) do { \
350 uint8_t *buf = (uint8_t *)_buf; \
351 buf[0] = 0; \
352 buf[1] = ((len)&0xFF0000)>>16; \
353 buf[2] = ((len)&0xFF00)>>8; \
354 buf[3] = (len)&0xFF; \
355 } while (0)
357 static bool smb2_setup_nbt_length(struct iovec *vector, int count)
359 ssize_t len;
361 if (count == 0) {
362 return false;
365 len = iov_buflen(vector+1, count-1);
367 if ((len == -1) || (len > 0xFFFFFF)) {
368 return false;
371 _smb2_setlen(vector[0].iov_base, len);
372 return true;
375 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
377 TALLOC_FREE(req->first_enc_key);
378 TALLOC_FREE(req->last_sign_key);
379 return 0;
382 void smb2_request_set_async_internal(struct smbd_smb2_request *req,
383 bool async_internal)
385 req->async_internal = async_internal;
388 static struct smbd_smb2_request *smbd_smb2_request_allocate(struct smbXsrv_connection *xconn)
390 TALLOC_CTX *mem_pool;
391 struct smbd_smb2_request *req;
393 #if 0
394 /* Enable this to find subtle valgrind errors. */
395 mem_pool = talloc_init("smbd_smb2_request_allocate");
396 #else
397 mem_pool = talloc_tos();
398 #endif
399 if (mem_pool == NULL) {
400 return NULL;
403 req = talloc(mem_pool, struct smbd_smb2_request);
404 if (req == NULL) {
405 talloc_free(mem_pool);
406 return NULL;
408 talloc_reparent(mem_pool, xconn, req);
409 #if 0
410 TALLOC_FREE(mem_pool);
411 #endif
412 *req = (struct smbd_smb2_request) {
413 .sconn = xconn->client->sconn,
414 .xconn = xconn,
415 .last_session_id = UINT64_MAX,
416 .last_tid = UINT32_MAX,
419 talloc_set_destructor(req, smbd_smb2_request_destructor);
421 return req;
424 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
425 NTTIME now,
426 uint8_t *buf,
427 size_t buflen,
428 struct smbd_smb2_request *req,
429 struct iovec **piov,
430 int *pnum_iov)
432 TALLOC_CTX *mem_ctx = req;
433 struct iovec *iov;
434 int num_iov = 1;
435 size_t taken = 0;
436 uint8_t *first_hdr = buf;
437 size_t verified_buflen = 0;
438 uint8_t *tf = NULL;
439 size_t tf_len = 0;
442 * Note: index '0' is reserved for the transport protocol
444 iov = req->in._vector;
446 while (taken < buflen) {
447 size_t len = buflen - taken;
448 uint8_t *hdr = first_hdr + taken;
449 struct iovec *cur;
450 size_t full_size;
451 size_t next_command_ofs;
452 uint16_t body_size;
453 uint8_t *body = NULL;
454 uint32_t dyn_size;
455 uint8_t *dyn = NULL;
456 struct iovec *iov_alloc = NULL;
458 if (iov != req->in._vector) {
459 iov_alloc = iov;
462 if (verified_buflen > taken) {
463 len = verified_buflen - taken;
464 } else {
465 tf = NULL;
466 tf_len = 0;
469 if (len < 4) {
470 DEBUG(10, ("%d bytes left, expected at least %d\n",
471 (int)len, 4));
472 goto inval;
474 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
475 struct smbXsrv_session *s = NULL;
476 uint64_t uid;
477 struct iovec tf_iov[2];
478 NTSTATUS status;
479 size_t enc_len;
481 if (xconn->protocol < PROTOCOL_SMB3_00) {
482 DEBUG(10, ("Got SMB2_TRANSFORM header, "
483 "but dialect[0x%04X] is used\n",
484 xconn->smb2.server.dialect));
485 goto inval;
488 if (xconn->smb2.server.cipher == 0) {
489 DEBUG(10, ("Got SMB2_TRANSFORM header, "
490 "but not negotiated "
491 "client[0x%08X] server[0x%08X]\n",
492 xconn->smb2.client.capabilities,
493 xconn->smb2.server.capabilities));
494 goto inval;
497 if (len < SMB2_TF_HDR_SIZE) {
498 DEBUG(1, ("%d bytes left, expected at least %d\n",
499 (int)len, SMB2_TF_HDR_SIZE));
500 goto inval;
502 tf = hdr;
503 tf_len = SMB2_TF_HDR_SIZE;
504 taken += tf_len;
506 hdr = first_hdr + taken;
507 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
508 uid = BVAL(tf, SMB2_TF_SESSION_ID);
510 if (len < SMB2_TF_HDR_SIZE + enc_len) {
511 DEBUG(1, ("%d bytes left, expected at least %d\n",
512 (int)len,
513 (int)(SMB2_TF_HDR_SIZE + enc_len)));
514 goto inval;
517 status = smb2srv_session_lookup_conn(xconn, uid, now,
518 &s);
519 if (s == NULL) {
520 status = smb2srv_session_lookup_global(xconn->client,
521 uid, req, &s);
523 if (s == NULL) {
524 DEBUG(1, ("invalid session[%llu] in "
525 "SMB2_TRANSFORM header\n",
526 (unsigned long long)uid));
527 TALLOC_FREE(iov_alloc);
528 return NT_STATUS_USER_SESSION_DELETED;
531 tf_iov[0].iov_base = (void *)tf;
532 tf_iov[0].iov_len = tf_len;
533 tf_iov[1].iov_base = (void *)hdr;
534 tf_iov[1].iov_len = enc_len;
536 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
537 tf_iov, 2);
538 if (!NT_STATUS_IS_OK(status)) {
539 TALLOC_FREE(iov_alloc);
540 return status;
543 verified_buflen = taken + enc_len;
544 len = enc_len;
548 * We need the header plus the body length field
551 if (len < SMB2_HDR_BODY + 2) {
553 if ((len == 5) &&
554 (IVAL(hdr, 0) == SMB_SUICIDE_PACKET) &&
555 lp_parm_bool(-1, "smbd", "suicide mode", false)) {
556 uint8_t exitcode = CVAL(hdr, 4);
557 DBG_WARNING("SUICIDE: Exiting immediately "
558 "with code %"PRIu8"\n",
559 exitcode);
560 exit(exitcode);
563 DEBUG(10, ("%d bytes left, expected at least %d\n",
564 (int)len, SMB2_HDR_BODY));
565 goto inval;
567 if (IVAL(hdr, 0) != SMB2_MAGIC) {
568 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
569 IVAL(hdr, 0)));
570 goto inval;
572 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
573 DEBUG(10, ("Got HDR len %d, expected %d\n",
574 SVAL(hdr, 4), SMB2_HDR_BODY));
575 goto inval;
578 full_size = len;
579 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
580 body_size = SVAL(hdr, SMB2_HDR_BODY);
582 if (next_command_ofs != 0) {
583 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
584 goto inval;
586 if (next_command_ofs > full_size) {
587 goto inval;
589 full_size = next_command_ofs;
591 if (body_size < 2) {
592 goto inval;
594 body_size &= 0xfffe;
596 if (body_size > (full_size - SMB2_HDR_BODY)) {
598 * let the caller handle the error
600 body_size = full_size - SMB2_HDR_BODY;
602 body = hdr + SMB2_HDR_BODY;
603 dyn = body + body_size;
604 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
606 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
607 struct iovec *iov_tmp = NULL;
609 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
610 struct iovec,
611 num_iov +
612 SMBD_SMB2_NUM_IOV_PER_REQ);
613 if (iov_tmp == NULL) {
614 TALLOC_FREE(iov_alloc);
615 return NT_STATUS_NO_MEMORY;
618 if (iov_alloc == NULL) {
619 memcpy(iov_tmp,
620 req->in._vector,
621 sizeof(req->in._vector));
624 iov = iov_tmp;
626 cur = &iov[num_iov];
627 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
629 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
630 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
631 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
632 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
633 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
634 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
635 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
636 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
638 taken += full_size;
641 *piov = iov;
642 *pnum_iov = num_iov;
643 return NT_STATUS_OK;
645 inval:
646 if (iov != req->in._vector) {
647 TALLOC_FREE(iov);
649 return NT_STATUS_INVALID_PARAMETER;
652 static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
653 const uint8_t *_inpdu, size_t size,
654 struct smbd_smb2_request **_req)
656 struct smbd_smb2_request *req;
657 uint32_t protocol_version;
658 uint8_t *inpdu = NULL;
659 const uint8_t *inhdr = NULL;
660 uint16_t cmd;
661 uint32_t next_command_ofs;
662 NTSTATUS status;
663 NTTIME now;
665 if (size < (SMB2_HDR_BODY + 2)) {
666 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
667 return NT_STATUS_INVALID_PARAMETER;
670 inhdr = _inpdu;
672 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
673 if (protocol_version != SMB2_MAGIC) {
674 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
675 protocol_version));
676 return NT_STATUS_INVALID_PARAMETER;
679 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
680 if (cmd != SMB2_OP_NEGPROT) {
681 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
682 cmd));
683 return NT_STATUS_INVALID_PARAMETER;
686 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
687 if (next_command_ofs != 0) {
688 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
689 next_command_ofs));
690 return NT_STATUS_INVALID_PARAMETER;
693 req = smbd_smb2_request_allocate(xconn);
694 if (req == NULL) {
695 return NT_STATUS_NO_MEMORY;
698 inpdu = talloc_memdup(req, _inpdu, size);
699 if (inpdu == NULL) {
700 return NT_STATUS_NO_MEMORY;
703 req->request_time = timeval_current();
704 now = timeval_to_nttime(&req->request_time);
706 status = smbd_smb2_inbuf_parse_compound(xconn,
707 now,
708 inpdu,
709 size,
710 req, &req->in.vector,
711 &req->in.vector_count);
712 if (!NT_STATUS_IS_OK(status)) {
713 TALLOC_FREE(req);
714 return status;
717 req->current_idx = 1;
719 *_req = req;
720 return NT_STATUS_OK;
723 static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
724 uint64_t message_id, uint64_t seq_id)
726 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
727 unsigned int offset;
728 uint64_t seq_tmp;
730 seq_tmp = xconn->smb2.credits.seq_low;
731 if (seq_id < seq_tmp) {
732 DBGC_ERR(DBGC_SMB2_CREDITS,
733 "smb2_validate_sequence_number: bad message_id "
734 "%llu (sequence id %llu) "
735 "(granted = %u, low = %llu, range = %u)\n",
736 (unsigned long long)message_id,
737 (unsigned long long)seq_id,
738 (unsigned int)xconn->smb2.credits.granted,
739 (unsigned long long)xconn->smb2.credits.seq_low,
740 (unsigned int)xconn->smb2.credits.seq_range);
741 return false;
744 seq_tmp += xconn->smb2.credits.seq_range;
745 if (seq_id >= seq_tmp) {
746 DBGC_ERR(DBGC_SMB2_CREDITS,
747 "smb2_validate_sequence_number: bad message_id "
748 "%llu (sequence id %llu) "
749 "(granted = %u, low = %llu, range = %u)\n",
750 (unsigned long long)message_id,
751 (unsigned long long)seq_id,
752 (unsigned int)xconn->smb2.credits.granted,
753 (unsigned long long)xconn->smb2.credits.seq_low,
754 (unsigned int)xconn->smb2.credits.seq_range);
755 return false;
758 offset = seq_id % xconn->smb2.credits.max;
760 if (bitmap_query(credits_bm, offset)) {
761 DBGC_ERR(DBGC_SMB2_CREDITS,
762 "smb2_validate_sequence_number: duplicate message_id "
763 "%llu (sequence id %llu) "
764 "(granted = %u, low = %llu, range = %u) "
765 "(bm offset %u)\n",
766 (unsigned long long)message_id,
767 (unsigned long long)seq_id,
768 (unsigned int)xconn->smb2.credits.granted,
769 (unsigned long long)xconn->smb2.credits.seq_low,
770 (unsigned int)xconn->smb2.credits.seq_range,
771 offset);
772 return false;
775 /* Mark the message_ids as seen in the bitmap. */
776 bitmap_set(credits_bm, offset);
778 if (seq_id != xconn->smb2.credits.seq_low) {
779 return true;
783 * Move the window forward by all the message_id's
784 * already seen.
786 while (bitmap_query(credits_bm, offset)) {
787 DBGC_DEBUG(DBGC_SMB2_CREDITS,
788 "smb2_validate_sequence_number: clearing "
789 "id %llu (position %u) from bitmap\n",
790 (unsigned long long)(xconn->smb2.credits.seq_low),
791 offset);
792 bitmap_clear(credits_bm, offset);
794 xconn->smb2.credits.seq_low += 1;
795 xconn->smb2.credits.seq_range -= 1;
796 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
799 return true;
802 static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
803 const uint8_t *inhdr)
805 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
806 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
807 uint16_t credit_charge = 1;
808 uint64_t i;
810 if (opcode == SMB2_OP_CANCEL) {
811 /* SMB2_CANCEL requests by definition resend messageids. */
812 return true;
815 if (xconn->smb2.credits.multicredit) {
816 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
817 credit_charge = MAX(credit_charge, 1);
820 DEBUGC(11,
821 DBGC_SMB2_CREDITS,
822 ("smb2_validate_message_id: mid %llu (charge %llu), "
823 "credits_granted %llu, "
824 "seqnum low/range: %llu/%llu\n",
825 (unsigned long long) message_id,
826 (unsigned long long) credit_charge,
827 (unsigned long long) xconn->smb2.credits.granted,
828 (unsigned long long) xconn->smb2.credits.seq_low,
829 (unsigned long long) xconn->smb2.credits.seq_range));
831 if (xconn->smb2.credits.granted < credit_charge) {
832 DBGC_ERR(DBGC_SMB2_CREDITS,
833 "smb2_validate_message_id: client used more "
834 "credits than granted, 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);
842 return false;
846 * now check the message ids
848 * for multi-credit requests we need to check all current mid plus
849 * the implicit mids caused by the credit charge
850 * e.g. current mid = 15, charge 5 => mark 15-19 as used
853 for (i = 0; i <= (credit_charge-1); i++) {
854 uint64_t id = message_id + i;
855 bool ok;
857 DEBUGC(11,
858 DBGC_SMB2_CREDITS,
859 ("Iterating mid %llu charge %u (sequence %llu)\n",
860 (unsigned long long)message_id,
861 credit_charge,
862 (unsigned long long)id));
864 ok = smb2_validate_sequence_number(xconn, message_id, id);
865 if (!ok) {
866 return false;
870 /* subtract used credits */
871 xconn->smb2.credits.granted -= credit_charge;
873 return true;
876 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
878 int count;
879 int idx;
881 count = req->in.vector_count;
883 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
884 /* It's not a SMB2 request */
885 return NT_STATUS_INVALID_PARAMETER;
888 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
889 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
890 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
891 const uint8_t *inhdr = NULL;
893 if (hdr->iov_len != SMB2_HDR_BODY) {
894 return NT_STATUS_INVALID_PARAMETER;
897 if (body->iov_len < 2) {
898 return NT_STATUS_INVALID_PARAMETER;
901 inhdr = (const uint8_t *)hdr->iov_base;
903 /* Check the SMB2 header */
904 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
905 return NT_STATUS_INVALID_PARAMETER;
908 if (!smb2_validate_message_id(req->xconn, inhdr)) {
909 return NT_STATUS_INVALID_PARAMETER;
913 return NT_STATUS_OK;
916 static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
917 const struct iovec *in_vector,
918 struct iovec *out_vector)
920 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
921 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
922 uint16_t credit_charge = 1;
923 uint16_t credits_requested;
924 uint32_t out_flags;
925 uint16_t cmd;
926 NTSTATUS out_status;
927 uint16_t credits_granted = 0;
928 uint64_t credits_possible;
929 uint16_t current_max_credits;
932 * first we grant only 1/16th of the max range.
934 * Windows also starts with the 1/16th and then grants
935 * more later. I was only able to trigger higher
936 * values, when using a very high credit charge.
938 * TODO: scale up depending on load, free memory
939 * or other stuff.
940 * Maybe also on the relationship between number
941 * of requests and the used sequence number.
942 * Which means we would grant more credits
943 * for client which use multi credit requests.
945 * The above is what Windows Server < 2016 is doing,
946 * but new servers use all credits (8192 by default).
948 current_max_credits = xconn->smb2.credits.max;
949 current_max_credits = MAX(current_max_credits, 1);
951 if (xconn->smb2.credits.multicredit) {
952 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
953 credit_charge = MAX(credit_charge, 1);
956 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
957 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
958 credits_requested = MAX(credits_requested, 1);
959 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
960 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
962 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
964 if (xconn->smb2.credits.max < credit_charge) {
965 smbd_server_connection_terminate(xconn,
966 "client error: credit charge > max credits\n");
967 return;
970 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
972 * In case we already send an async interim
973 * response, we should not grant
974 * credits on the final response.
976 credits_granted = 0;
977 } else {
978 uint16_t additional_possible =
979 xconn->smb2.credits.max - credit_charge;
980 uint16_t additional_max = 0;
981 uint16_t additional_credits = credits_requested - 1;
983 switch (cmd) {
984 case SMB2_OP_NEGPROT:
985 break;
986 case SMB2_OP_SESSSETUP:
988 * Windows 2012 RC1 starts to grant
989 * additional credits
990 * with a successful session setup
992 if (NT_STATUS_IS_OK(out_status)) {
993 additional_max = xconn->smb2.credits.max;
995 break;
996 default:
998 * Windows Server < 2016 and older Samba versions
999 * used to only grant additional credits in
1000 * chunks of 32 credits.
1002 * But we match Windows Server 2016 and grant
1003 * all credits as requested.
1005 additional_max = xconn->smb2.credits.max;
1006 break;
1009 additional_max = MIN(additional_max, additional_possible);
1010 additional_credits = MIN(additional_credits, additional_max);
1012 credits_granted = credit_charge + additional_credits;
1016 * sequence numbers should not wrap
1018 * 1. calculate the possible credits until
1019 * the sequence numbers start to wrap on 64-bit.
1021 * 2. UINT64_MAX is used for Break Notifications.
1023 * 2. truncate the possible credits to the maximum
1024 * credits we want to grant to the client in total.
1026 * 3. remove the range we'll already granted to the client
1027 * this makes sure the client consumes the lowest sequence
1028 * number, before we can grant additional credits.
1030 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
1031 if (credits_possible > 0) {
1032 /* remove UINT64_MAX */
1033 credits_possible -= 1;
1035 credits_possible = MIN(credits_possible, current_max_credits);
1036 credits_possible -= xconn->smb2.credits.seq_range;
1038 credits_granted = MIN(credits_granted, credits_possible);
1040 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
1041 xconn->smb2.credits.granted += credits_granted;
1042 xconn->smb2.credits.seq_range += credits_granted;
1044 DBGC_DEBUG(DBGC_SMB2_CREDITS,
1045 "smb2_set_operation_credit: requested %u, charge %u, "
1046 "granted %u, current possible/max %u/%u, "
1047 "total granted/max/low/range %u/%u/%llu/%u\n",
1048 (unsigned int)credits_requested,
1049 (unsigned int)credit_charge,
1050 (unsigned int)credits_granted,
1051 (unsigned int)credits_possible,
1052 (unsigned int)current_max_credits,
1053 (unsigned int)xconn->smb2.credits.granted,
1054 (unsigned int)xconn->smb2.credits.max,
1055 (unsigned long long)xconn->smb2.credits.seq_low,
1056 (unsigned int)xconn->smb2.credits.seq_range);
1059 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
1060 struct smbd_smb2_request *outreq)
1062 int count, idx;
1063 uint16_t total_credits = 0;
1065 count = outreq->out.vector_count;
1067 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
1068 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
1069 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
1070 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
1072 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
1074 /* To match Windows, count up what we
1075 just granted. */
1076 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
1077 /* Set to zero in all but the last reply. */
1078 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
1079 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
1080 } else {
1081 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
1086 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
1088 if (req->current_idx <= 1) {
1089 if (size <= sizeof(req->out._body)) {
1090 return data_blob_const(req->out._body, size);
1094 return data_blob_talloc(req, NULL, size);
1097 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
1099 struct smbXsrv_connection *xconn = req->xconn;
1100 TALLOC_CTX *mem_ctx;
1101 struct iovec *vector;
1102 int count;
1103 int idx;
1104 bool ok;
1106 count = req->in.vector_count;
1107 if (count <= ARRAY_SIZE(req->out._vector)) {
1108 mem_ctx = req;
1109 vector = req->out._vector;
1110 } else {
1111 vector = talloc_zero_array(req, struct iovec, count);
1112 if (vector == NULL) {
1113 return NT_STATUS_NO_MEMORY;
1115 mem_ctx = vector;
1118 vector[0].iov_base = req->out.nbt_hdr;
1119 vector[0].iov_len = 4;
1120 SIVAL(req->out.nbt_hdr, 0, 0);
1122 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
1123 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
1124 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
1125 uint8_t *outhdr = NULL;
1126 uint8_t *outbody = NULL;
1127 uint32_t next_command_ofs = 0;
1128 struct iovec *current = &vector[idx];
1130 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
1131 /* we have a next command -
1132 * setup for the error case. */
1133 next_command_ofs = SMB2_HDR_BODY + 9;
1136 if (idx == 1) {
1137 outhdr = req->out._hdr;
1138 } else {
1139 outhdr = talloc_zero_array(mem_ctx, uint8_t,
1140 OUTVEC_ALLOC_SIZE);
1141 if (outhdr == NULL) {
1142 return NT_STATUS_NO_MEMORY;
1146 outbody = outhdr + SMB2_HDR_BODY;
1149 * SMBD_SMB2_TF_IOV_OFS might be used later
1151 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1152 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1154 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
1155 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1157 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1158 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1160 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1161 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1163 /* setup the SMB2 header */
1164 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1165 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1166 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1167 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1168 SIVAL(outhdr, SMB2_HDR_STATUS,
1169 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1170 SSVAL(outhdr, SMB2_HDR_OPCODE,
1171 SVAL(inhdr, SMB2_HDR_OPCODE));
1172 SIVAL(outhdr, SMB2_HDR_FLAGS,
1173 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1174 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1175 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1176 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1177 SIVAL(outhdr, SMB2_HDR_PID,
1178 IVAL(inhdr, SMB2_HDR_PID));
1179 SIVAL(outhdr, SMB2_HDR_TID,
1180 IVAL(inhdr, SMB2_HDR_TID));
1181 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1182 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1183 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1184 inhdr + SMB2_HDR_SIGNATURE, 16);
1186 /* setup error body header */
1187 SSVAL(outbody, 0x00, 0x08 + 1);
1188 SSVAL(outbody, 0x02, 0);
1189 SIVAL(outbody, 0x04, 0);
1192 req->out.vector = vector;
1193 req->out.vector_count = count;
1195 /* setup the length of the NBT packet */
1196 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1197 if (!ok) {
1198 return NT_STATUS_INVALID_PARAMETER_MIX;
1201 DLIST_ADD_END(xconn->smb2.requests, req);
1203 return NT_STATUS_OK;
1206 bool smbXsrv_server_multi_channel_enabled(void)
1208 bool enabled = lp_server_multi_channel_support();
1209 #ifndef __ALLOW_MULTI_CHANNEL_SUPPORT
1210 bool forced = false;
1211 struct loadparm_context *lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
1212 bool unspecified = lpcfg_parm_is_unspecified(lp_ctx, "server multi channel support");
1213 if (unspecified) {
1214 enabled = false;
1217 * If we don't have support from the kernel
1218 * to ask for the un-acked number of bytes
1219 * in the socket send queue, we better
1220 * don't support multi-channel.
1222 forced = lp_parm_bool(-1, "force", "server multi channel support", false);
1223 if (enabled && !forced) {
1224 D_NOTICE("'server multi channel support' enabled "
1225 "but not supported on %s (%s)\n",
1226 SYSTEM_UNAME_SYSNAME, SYSTEM_UNAME_RELEASE);
1227 DEBUGADD(DBGLVL_NOTICE, ("Please report this on "
1228 "https://bugzilla.samba.org/show_bug.cgi?id=11897\n"));
1229 enabled = false;
1231 TALLOC_FREE(lp_ctx);
1232 #endif /* ! __ALLOW_MULTI_CHANNEL_SUPPORT */
1233 return enabled;
1236 static NTSTATUS smbXsrv_connection_get_rto_usecs(struct smbXsrv_connection *xconn,
1237 uint32_t *_rto_usecs)
1240 * Define an Retransmission Timeout
1241 * of 1 second, if there's no way for the
1242 * kernel to tell us the current value.
1244 uint32_t rto_usecs = 1000000;
1246 #ifdef __HAVE_TCP_INFO_RTO
1248 struct tcp_info info;
1249 socklen_t ilen = sizeof(info);
1250 int ret;
1252 ZERO_STRUCT(info);
1253 ret = getsockopt(xconn->transport.sock,
1254 IPPROTO_TCP, TCP_INFO,
1255 (void *)&info, &ilen);
1256 if (ret != 0) {
1257 int saved_errno = errno;
1258 NTSTATUS status = map_nt_error_from_unix(errno);
1259 DBG_ERR("getsockopt(TCP_INFO) errno[%d/%s] -s %s\n",
1260 saved_errno, strerror(saved_errno),
1261 nt_errstr(status));
1262 return status;
1265 DBG_DEBUG("tcpi_rto[%u] tcpi_rtt[%u] tcpi_rttvar[%u]\n",
1266 (unsigned)info.tcpi_rto,
1267 (unsigned)info.tcpi_rtt,
1268 (unsigned)info.tcpi_rttvar);
1269 rto_usecs = info.tcpi_rto;
1271 #endif /* __HAVE_TCP_INFO_RTO */
1273 rto_usecs = MAX(rto_usecs, 200000); /* at least 0.2s */
1274 rto_usecs = MIN(rto_usecs, 1000000); /* at max 1.0s */
1275 *_rto_usecs = rto_usecs;
1276 return NT_STATUS_OK;
1279 static NTSTATUS smbXsrv_connection_get_acked_bytes(struct smbXsrv_connection *xconn,
1280 uint64_t *_acked_bytes)
1283 * Unless the kernel has an interface
1284 * to reveal the number of un-acked bytes
1285 * in the socket send queue, we'll assume
1286 * everything is already acked.
1288 * But that would mean that we better don't
1289 * pretent to support multi-channel.
1291 uint64_t unacked_bytes = 0;
1293 *_acked_bytes = 0;
1295 if (xconn->ack.force_unacked_timeout) {
1297 * Smbtorture tries to test channel failures...
1298 * Just pretend nothing was acked...
1300 DBG_INFO("Simulating channel failure: "
1301 "xconn->ack.unacked_bytes[%llu]\n",
1302 (unsigned long long)xconn->ack.unacked_bytes);
1303 return NT_STATUS_OK;
1306 #ifdef __IOCTL_SEND_QUEUE_SIZE_OPCODE
1308 int value = 0;
1309 int ret;
1312 * If we have kernel support to get
1313 * the number of bytes waiting in
1314 * the socket's send queue, we
1315 * use that in order to find out
1316 * the number of unacked bytes.
1318 ret = ioctl(xconn->transport.sock,
1319 __IOCTL_SEND_QUEUE_SIZE_OPCODE,
1320 &value);
1321 if (ret != 0) {
1322 int saved_errno = errno;
1323 NTSTATUS status = map_nt_error_from_unix(saved_errno);
1324 DBG_ERR("Failed to get the SEND_QUEUE_SIZE - "
1325 "errno %d (%s) - %s\n",
1326 saved_errno, strerror(saved_errno),
1327 nt_errstr(status));
1328 return status;
1331 if (value < 0) {
1332 DBG_ERR("xconn->ack.unacked_bytes[%llu] value[%d]\n",
1333 (unsigned long long)xconn->ack.unacked_bytes,
1334 value);
1335 return NT_STATUS_INTERNAL_ERROR;
1337 unacked_bytes = value;
1339 #endif
1340 if (xconn->ack.unacked_bytes == 0) {
1341 xconn->ack.unacked_bytes = unacked_bytes;
1342 return NT_STATUS_OK;
1345 if (xconn->ack.unacked_bytes < unacked_bytes) {
1346 DBG_ERR("xconn->ack.unacked_bytes[%llu] unacked_bytes[%llu]\n",
1347 (unsigned long long)xconn->ack.unacked_bytes,
1348 (unsigned long long)unacked_bytes);
1349 return NT_STATUS_INTERNAL_ERROR;
1352 *_acked_bytes = xconn->ack.unacked_bytes - unacked_bytes;
1353 xconn->ack.unacked_bytes = unacked_bytes;
1354 return NT_STATUS_OK;
1357 static void smbd_smb2_send_queue_ack_fail(struct smbd_smb2_send_queue **queue,
1358 NTSTATUS status)
1360 struct smbd_smb2_send_queue *e = NULL;
1361 struct smbd_smb2_send_queue *n = NULL;
1363 for (e = *queue; e != NULL; e = n) {
1364 n = e->next;
1366 DLIST_REMOVE(*queue, e);
1367 if (e->ack.req != NULL) {
1368 tevent_req_nterror(e->ack.req, status);
1373 static NTSTATUS smbd_smb2_send_queue_ack_bytes(struct smbd_smb2_send_queue **queue,
1374 uint64_t acked_bytes)
1376 struct smbd_smb2_send_queue *e = NULL;
1377 struct smbd_smb2_send_queue *n = NULL;
1379 for (e = *queue; e != NULL; e = n) {
1380 bool expired;
1382 n = e->next;
1384 if (e->ack.req == NULL) {
1385 continue;
1388 if (e->ack.required_acked_bytes <= acked_bytes) {
1389 e->ack.required_acked_bytes = 0;
1390 DLIST_REMOVE(*queue, e);
1391 tevent_req_done(e->ack.req);
1392 continue;
1394 e->ack.required_acked_bytes -= acked_bytes;
1396 expired = timeval_expired(&e->ack.timeout);
1397 if (expired) {
1398 return NT_STATUS_IO_TIMEOUT;
1402 return NT_STATUS_OK;
1405 static NTSTATUS smbd_smb2_check_ack_queue(struct smbXsrv_connection *xconn)
1407 uint64_t acked_bytes = 0;
1408 NTSTATUS status;
1410 status = smbXsrv_connection_get_acked_bytes(xconn, &acked_bytes);
1411 if (!NT_STATUS_IS_OK(status)) {
1412 return status;
1415 status = smbd_smb2_send_queue_ack_bytes(&xconn->ack.queue, acked_bytes);
1416 if (!NT_STATUS_IS_OK(status)) {
1417 return status;
1420 status = smbd_smb2_send_queue_ack_bytes(&xconn->smb2.send_queue, 0);
1421 if (!NT_STATUS_IS_OK(status)) {
1422 return status;
1425 return NT_STATUS_OK;
1428 static void smbXsrv_connection_ack_checker(struct tevent_req *subreq)
1430 struct smbXsrv_connection *xconn =
1431 tevent_req_callback_data(subreq,
1432 struct smbXsrv_connection);
1433 struct smbXsrv_client *client = xconn->client;
1434 struct timeval next_check;
1435 NTSTATUS status;
1436 bool ok;
1438 xconn->ack.checker_subreq = NULL;
1440 ok = tevent_wakeup_recv(subreq);
1441 TALLOC_FREE(subreq);
1442 if (!ok) {
1443 smbd_server_connection_terminate(xconn,
1444 "tevent_wakeup_recv() failed");
1445 return;
1448 status = smbd_smb2_check_ack_queue(xconn);
1449 if (!NT_STATUS_IS_OK(status)) {
1450 smbd_server_connection_terminate(xconn, nt_errstr(status));
1451 return;
1454 next_check = timeval_current_ofs_usec(xconn->ack.rto_usecs);
1455 xconn->ack.checker_subreq = tevent_wakeup_send(xconn,
1456 client->raw_ev_ctx,
1457 next_check);
1458 if (xconn->ack.checker_subreq == NULL) {
1459 smbd_server_connection_terminate(xconn,
1460 "tevent_wakeup_send() failed");
1461 return;
1463 tevent_req_set_callback(xconn->ack.checker_subreq,
1464 smbXsrv_connection_ack_checker,
1465 xconn);
1468 static NTSTATUS smbXsrv_client_pending_breaks_updated(struct smbXsrv_client *client)
1470 struct smbXsrv_connection *xconn = NULL;
1472 for (xconn = client->connections; xconn != NULL; xconn = xconn->next) {
1473 struct timeval next_check;
1474 uint64_t acked_bytes = 0;
1475 NTSTATUS status;
1478 * A new 'pending break cycle' starts
1479 * with a first pending break and lasts until
1480 * all pending breaks are finished.
1482 * This is typically a very short time,
1483 * the value of one retransmission timeout.
1486 if (client->pending_breaks == NULL) {
1488 * No more pending breaks, remove a pending
1489 * checker timer
1491 TALLOC_FREE(xconn->ack.checker_subreq);
1492 continue;
1495 if (xconn->ack.checker_subreq != NULL) {
1497 * The cycle already started =>
1498 * nothing todo
1500 continue;
1504 * Get the current retransmission timeout value.
1506 * It may change over time, but fetching it once
1507 * per 'pending break' cycled should be enough.
1509 status = smbXsrv_connection_get_rto_usecs(xconn,
1510 &xconn->ack.rto_usecs);
1511 if (!NT_STATUS_IS_OK(status)) {
1512 return status;
1516 * At the start of the cycle we reset the
1517 * unacked_bytes counter (first to 0 and
1518 * within smbXsrv_connection_get_acked_bytes()
1519 * to the current value in the kernel
1520 * send queue.
1522 xconn->ack.unacked_bytes = 0;
1523 status = smbXsrv_connection_get_acked_bytes(xconn, &acked_bytes);
1524 if (!NT_STATUS_IS_OK(status)) {
1525 return status;
1529 * We setup a timer in order to check for
1530 * acked bytes after one retransmission timeout.
1532 * The code that sets up the send_queue.ack.timeout
1533 * uses a multiple of the retransmission timeout.
1535 next_check = timeval_current_ofs_usec(xconn->ack.rto_usecs);
1536 xconn->ack.checker_subreq = tevent_wakeup_send(xconn,
1537 client->raw_ev_ctx,
1538 next_check);
1539 if (xconn->ack.checker_subreq == NULL) {
1540 return NT_STATUS_NO_MEMORY;
1542 tevent_req_set_callback(xconn->ack.checker_subreq,
1543 smbXsrv_connection_ack_checker,
1544 xconn);
1547 return NT_STATUS_OK;
1550 void smbXsrv_connection_disconnect_transport(struct smbXsrv_connection *xconn,
1551 NTSTATUS status)
1553 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
1554 return;
1557 xconn->transport.status = status;
1558 TALLOC_FREE(xconn->transport.fde);
1559 if (xconn->transport.sock != -1) {
1560 xconn->transport.sock = -1;
1562 smbd_smb2_send_queue_ack_fail(&xconn->ack.queue, status);
1563 smbd_smb2_send_queue_ack_fail(&xconn->smb2.send_queue, status);
1564 xconn->smb2.send_queue_len = 0;
1565 DO_PROFILE_INC(disconnect);
1568 size_t smbXsrv_client_valid_connections(struct smbXsrv_client *client)
1570 struct smbXsrv_connection *xconn = NULL;
1571 size_t num_ok = 0;
1573 for (xconn = client->connections; xconn != NULL; xconn = xconn->next) {
1574 if (NT_STATUS_IS_OK(xconn->transport.status)) {
1575 num_ok++;
1579 return num_ok;
1582 struct smbXsrv_connection_shutdown_state {
1583 struct smbXsrv_connection *xconn;
1586 static void smbXsrv_connection_shutdown_wait_done(struct tevent_req *subreq);
1588 static struct tevent_req *smbXsrv_connection_shutdown_send(TALLOC_CTX *mem_ctx,
1589 struct tevent_context *ev,
1590 struct smbXsrv_connection *xconn)
1592 struct tevent_req *req = NULL;
1593 struct smbXsrv_connection_shutdown_state *state = NULL;
1594 struct tevent_req *subreq = NULL;
1595 size_t len = 0;
1596 struct smbd_smb2_request *preq = NULL;
1597 NTSTATUS status;
1600 * The caller should have called
1601 * smbXsrv_connection_disconnect_transport() before.
1603 SMB_ASSERT(!NT_STATUS_IS_OK(xconn->transport.status));
1604 SMB_ASSERT(xconn->transport.terminating);
1605 SMB_ASSERT(xconn->transport.shutdown_wait_queue == NULL);
1607 req = tevent_req_create(mem_ctx, &state,
1608 struct smbXsrv_connection_shutdown_state);
1609 if (req == NULL) {
1610 return NULL;
1613 state->xconn = xconn;
1614 tevent_req_defer_callback(req, ev);
1616 xconn->transport.shutdown_wait_queue =
1617 tevent_queue_create(state, "smbXsrv_connection_shutdown_queue");
1618 if (tevent_req_nomem(xconn->transport.shutdown_wait_queue, req)) {
1619 return tevent_req_post(req, ev);
1622 for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
1624 * Now wait until the request is finished.
1626 * We don't set a callback, as we just want to block the
1627 * wait queue and the talloc_free() of the request will
1628 * remove the item from the wait queue.
1630 * Note that we don't cancel the requests here
1631 * in order to keep the replay detection logic correct.
1633 * However if we teardown the last channel of
1634 * a connection, we'll call some logic via
1635 * smbXsrv_session_disconnect_xconn()
1636 * -> smbXsrv_session_disconnect_xconn_callback()
1637 * -> smbXsrv_session_remove_channel()
1638 * -> smb2srv_session_shutdown_send()
1639 * will indeed cancel the request.
1641 subreq = tevent_queue_wait_send(preq, ev,
1642 xconn->transport.shutdown_wait_queue);
1643 if (tevent_req_nomem(subreq, req)) {
1644 return tevent_req_post(req, ev);
1649 * This may attach sessions with num_channels == 0
1650 * to xconn->transport.shutdown_wait_queue.
1652 status = smbXsrv_session_disconnect_xconn(xconn);
1653 if (tevent_req_nterror(req, status)) {
1654 return tevent_req_post(req, ev);
1657 len = tevent_queue_length(xconn->transport.shutdown_wait_queue);
1658 if (len == 0) {
1659 tevent_req_done(req);
1660 return tevent_req_post(req, ev);
1664 * Now we add our own waiter to the end of the queue,
1665 * this way we get notified when all pending requests are finished
1666 * and send to the socket.
1668 subreq = tevent_queue_wait_send(state, ev, xconn->transport.shutdown_wait_queue);
1669 if (tevent_req_nomem(subreq, req)) {
1670 return tevent_req_post(req, ev);
1672 tevent_req_set_callback(subreq, smbXsrv_connection_shutdown_wait_done, req);
1674 return req;
1677 static void smbXsrv_connection_shutdown_wait_done(struct tevent_req *subreq)
1679 struct tevent_req *req =
1680 tevent_req_callback_data(subreq,
1681 struct tevent_req);
1682 struct smbXsrv_connection_shutdown_state *state =
1683 tevent_req_data(req,
1684 struct smbXsrv_connection_shutdown_state);
1685 struct smbXsrv_connection *xconn = state->xconn;
1687 tevent_queue_wait_recv(subreq);
1688 TALLOC_FREE(subreq);
1690 tevent_req_done(req);
1692 * make sure the xconn pointer is still valid,
1693 * it should as we used tevent_req_defer_callback()
1695 SMB_ASSERT(xconn->transport.terminating);
1698 static NTSTATUS smbXsrv_connection_shutdown_recv(struct tevent_req *req)
1700 struct smbXsrv_connection_shutdown_state *state =
1701 tevent_req_data(req,
1702 struct smbXsrv_connection_shutdown_state);
1703 struct smbXsrv_connection *xconn = state->xconn;
1705 * make sure the xconn pointer is still valid,
1706 * it should as we used tevent_req_defer_callback()
1708 SMB_ASSERT(xconn->transport.terminating);
1709 return tevent_req_simple_recv_ntstatus(req);
1712 static void smbd_server_connection_terminate_done(struct tevent_req *subreq)
1714 struct smbXsrv_connection *xconn =
1715 tevent_req_callback_data(subreq,
1716 struct smbXsrv_connection);
1717 struct smbXsrv_client *client = xconn->client;
1718 NTSTATUS status;
1720 status = smbXsrv_connection_shutdown_recv(subreq);
1721 TALLOC_FREE(subreq);
1722 if (!NT_STATUS_IS_OK(status)) {
1723 exit_server("smbXsrv_connection_shutdown_recv failed");
1726 DLIST_REMOVE(client->connections, xconn);
1727 TALLOC_FREE(xconn);
1730 void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
1731 const char *reason,
1732 const char *location)
1734 struct smbXsrv_client *client = xconn->client;
1735 size_t num_ok = 0;
1738 * Make sure that no new request will be able to use this session.
1740 * smbXsrv_connection_disconnect_transport() might be called already,
1741 * but calling it again is a no-op.
1743 smbXsrv_connection_disconnect_transport(xconn,
1744 NT_STATUS_CONNECTION_DISCONNECTED);
1746 num_ok = smbXsrv_client_valid_connections(client);
1748 if (xconn->transport.terminating) {
1749 DBG_DEBUG("skip recursion conn[%s] num_ok[%zu] reason[%s] at %s\n",
1750 smbXsrv_connection_dbg(xconn), num_ok,
1751 reason, location);
1752 return;
1754 xconn->transport.terminating = true;
1756 DBG_DEBUG("conn[%s] num_ok[%zu] reason[%s] at %s\n",
1757 smbXsrv_connection_dbg(xconn), num_ok,
1758 reason, location);
1760 if (xconn->has_cluster_movable_ip) {
1762 * If the connection has a movable cluster public address
1763 * we disconnect all client connections,
1764 * as the public address might be moved to
1765 * a different node.
1767 * In future we may recheck which node currently
1768 * holds this address, but for now we keep it simple.
1770 smbd_server_disconnect_client_ex(xconn->client,
1771 reason,
1772 location);
1773 return;
1776 if (num_ok != 0) {
1777 struct tevent_req *subreq = NULL;
1779 subreq = smbXsrv_connection_shutdown_send(client,
1780 client->raw_ev_ctx,
1781 xconn);
1782 if (subreq == NULL) {
1783 exit_server("smbXsrv_connection_shutdown_send failed");
1785 tevent_req_set_callback(subreq,
1786 smbd_server_connection_terminate_done,
1787 xconn);
1788 return;
1792 * The last connection was disconnected
1794 exit_server_cleanly(reason);
1797 void smbd_server_disconnect_client_ex(struct smbXsrv_client *client,
1798 const char *reason,
1799 const char *location)
1801 size_t num_ok = 0;
1803 num_ok = smbXsrv_client_valid_connections(client);
1805 DBG_WARNING("client[%s] num_ok[%zu] reason[%s] at %s\n",
1806 client->global->remote_address, num_ok,
1807 reason, location);
1810 * Something bad happened we need to disconnect all connections.
1812 exit_server_cleanly(reason);
1815 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1816 struct iovec *outvec,
1817 const struct iovec *srcvec)
1819 const uint8_t *srctf;
1820 size_t srctf_len;
1821 const uint8_t *srchdr;
1822 size_t srchdr_len;
1823 const uint8_t *srcbody;
1824 size_t srcbody_len;
1825 const uint8_t *expected_srcbody;
1826 const uint8_t *srcdyn;
1827 size_t srcdyn_len;
1828 const uint8_t *expected_srcdyn;
1829 uint8_t *dsttf;
1830 uint8_t *dsthdr;
1831 uint8_t *dstbody;
1832 uint8_t *dstdyn;
1834 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1835 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1836 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1837 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1838 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1839 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1840 expected_srcbody = srchdr + SMB2_HDR_BODY;
1841 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1842 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1843 expected_srcdyn = srcbody + 8;
1845 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1846 return false;
1849 if (srchdr_len != SMB2_HDR_BODY) {
1850 return false;
1853 if (srctf_len == SMB2_TF_HDR_SIZE) {
1854 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1855 if (dsttf == NULL) {
1856 return false;
1858 } else {
1859 dsttf = NULL;
1861 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1862 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1864 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1865 * be allocated with size OUTVEC_ALLOC_SIZE. */
1867 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1868 if (dsthdr == NULL) {
1869 return false;
1871 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1872 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1875 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1876 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1877 * then duplicate this. Else use talloc_memdup().
1880 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1881 dstbody = dsthdr + SMB2_HDR_BODY;
1882 } else {
1883 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1884 if (dstbody == NULL) {
1885 return false;
1888 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1889 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1892 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1893 * pointing to
1894 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1895 * then duplicate this. Else use talloc_memdup().
1898 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1899 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1900 } else if (srcdyn == NULL) {
1901 dstdyn = NULL;
1902 } else {
1903 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1904 if (dstdyn == NULL) {
1905 return false;
1908 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1909 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1911 return true;
1914 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1916 struct smbd_smb2_request *newreq = NULL;
1917 struct iovec *outvec = NULL;
1918 int count = req->out.vector_count;
1919 int i;
1920 bool ok;
1922 newreq = smbd_smb2_request_allocate(req->xconn);
1923 if (!newreq) {
1924 return NULL;
1927 newreq->session = req->session;
1928 newreq->do_encryption = req->do_encryption;
1929 newreq->do_signing = req->do_signing;
1930 newreq->current_idx = req->current_idx;
1932 outvec = talloc_zero_array(newreq, struct iovec, count);
1933 if (!outvec) {
1934 TALLOC_FREE(newreq);
1935 return NULL;
1937 newreq->out.vector = outvec;
1938 newreq->out.vector_count = count;
1940 /* Setup the outvec's identically to req. */
1941 outvec[0].iov_base = newreq->out.nbt_hdr;
1942 outvec[0].iov_len = 4;
1943 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1945 /* Setup the vectors identically to the ones in req. */
1946 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1947 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1948 break;
1952 if (i < count) {
1953 /* Alloc failed. */
1954 TALLOC_FREE(newreq);
1955 return NULL;
1958 ok = smb2_setup_nbt_length(newreq->out.vector,
1959 newreq->out.vector_count);
1960 if (!ok) {
1961 TALLOC_FREE(newreq);
1962 return NULL;
1965 return newreq;
1968 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1970 struct smbXsrv_connection *xconn = req->xconn;
1971 int first_idx = 1;
1972 struct iovec *firsttf = NULL;
1973 struct iovec *outhdr_v = NULL;
1974 uint8_t *outhdr = NULL;
1975 struct smbd_smb2_request *nreq = NULL;
1976 NTSTATUS status;
1977 bool ok;
1979 /* Create a new smb2 request we'll use
1980 for the interim return. */
1981 nreq = dup_smb2_req(req);
1982 if (!nreq) {
1983 return NT_STATUS_NO_MEMORY;
1986 /* Lose the last X out vectors. They're the
1987 ones we'll be using for the async reply. */
1988 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1990 ok = smb2_setup_nbt_length(nreq->out.vector,
1991 nreq->out.vector_count);
1992 if (!ok) {
1993 return NT_STATUS_INVALID_PARAMETER_MIX;
1996 /* Step back to the previous reply. */
1997 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1998 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1999 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
2000 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
2001 /* And end the chain. */
2002 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
2004 /* Calculate outgoing credits */
2005 smb2_calculate_credits(req, nreq);
2007 if (DEBUGLEVEL >= 10) {
2008 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
2009 (unsigned int)nreq->current_idx );
2010 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
2011 (unsigned int)nreq->out.vector_count );
2012 print_req_vectors(nreq);
2016 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
2017 * we need to sign/encrypt here with the last/first key we remembered
2019 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2020 status = smb2_signing_encrypt_pdu(req->first_enc_key,
2021 firsttf,
2022 nreq->out.vector_count - first_idx);
2023 if (!NT_STATUS_IS_OK(status)) {
2024 return status;
2026 } else if (smb2_signing_key_valid(req->last_sign_key)) {
2027 status = smb2_signing_sign_pdu(req->last_sign_key,
2028 outhdr_v,
2029 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2030 if (!NT_STATUS_IS_OK(status)) {
2031 return status;
2035 nreq->queue_entry.mem_ctx = nreq;
2036 nreq->queue_entry.vector = nreq->out.vector;
2037 nreq->queue_entry.count = nreq->out.vector_count;
2038 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry);
2039 xconn->smb2.send_queue_len++;
2041 status = smbd_smb2_flush_send_queue(xconn);
2042 if (!NT_STATUS_IS_OK(status)) {
2043 return status;
2046 return NT_STATUS_OK;
2049 struct smbd_smb2_request_pending_state {
2050 struct smbd_smb2_send_queue queue_entry;
2051 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
2052 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
2055 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
2056 struct tevent_timer *te,
2057 struct timeval current_time,
2058 void *private_data);
2060 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
2061 struct tevent_req *subreq,
2062 uint32_t defer_time)
2064 NTSTATUS status;
2065 struct timeval defer_endtime;
2066 uint8_t *outhdr = NULL;
2067 uint32_t flags;
2069 if (!tevent_req_is_in_progress(subreq)) {
2071 * This is a performance optimization,
2072 * it avoids one tevent_loop iteration,
2073 * which means we avoid one
2074 * talloc_stackframe_pool/talloc_free pair.
2076 tevent_req_notify_callback(subreq);
2077 return NT_STATUS_OK;
2080 req->subreq = subreq;
2081 subreq = NULL;
2083 if (req->async_te) {
2084 /* We're already async. */
2085 return NT_STATUS_OK;
2088 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2089 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
2090 if (flags & SMB2_HDR_FLAG_ASYNC) {
2091 /* We're already async. */
2092 return NT_STATUS_OK;
2095 if (req->async_internal || defer_time == 0) {
2097 * An SMB2 request implementation wants to handle the request
2098 * asynchronously "internally" while keeping synchronous
2099 * behaviour for the SMB2 request. This means we don't send an
2100 * interim response and we can allow processing of compound SMB2
2101 * requests (cf the subsequent check) for all cases.
2103 return NT_STATUS_OK;
2106 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
2108 * We're trying to go async in a compound request
2109 * chain. This is only allowed for opens that cause an
2110 * oplock break or for the last operation in the
2111 * chain, otherwise it is not allowed. See
2112 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
2114 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2116 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
2118 * Cancel the outstanding request.
2120 bool ok = tevent_req_cancel(req->subreq);
2121 if (ok) {
2122 return NT_STATUS_OK;
2124 TALLOC_FREE(req->subreq);
2125 return smbd_smb2_request_error(req,
2126 NT_STATUS_INTERNAL_ERROR);
2130 if (DEBUGLEVEL >= 10) {
2131 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
2132 (unsigned int)req->current_idx );
2133 print_req_vectors(req);
2136 if (req->current_idx > 1) {
2138 * We're going async in a compound
2139 * chain after the first request has
2140 * already been processed. Send an
2141 * interim response containing the
2142 * set of replies already generated.
2144 int idx = req->current_idx;
2146 status = smb2_send_async_interim_response(req);
2147 if (!NT_STATUS_IS_OK(status)) {
2148 return status;
2150 TALLOC_FREE(req->first_enc_key);
2152 req->current_idx = 1;
2155 * Re-arrange the in.vectors to remove what
2156 * we just sent.
2158 memmove(&req->in.vector[1],
2159 &req->in.vector[idx],
2160 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
2161 req->in.vector_count = 1 + (req->in.vector_count - idx);
2163 /* Re-arrange the out.vectors to match. */
2164 memmove(&req->out.vector[1],
2165 &req->out.vector[idx],
2166 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
2167 req->out.vector_count = 1 + (req->out.vector_count - idx);
2169 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
2171 * We only have one remaining request as
2172 * we've processed everything else.
2173 * This is no longer a compound request.
2175 req->compound_related = false;
2176 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2177 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
2178 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
2181 TALLOC_FREE(req->last_sign_key);
2184 * smbd_smb2_request_pending_timer() just send a packet
2185 * to the client and doesn't need any impersonation.
2186 * So we use req->xconn->client->raw_ev_ctx instead
2187 * of req->ev_ctx here.
2189 defer_endtime = timeval_current_ofs_usec(defer_time);
2190 req->async_te = tevent_add_timer(req->xconn->client->raw_ev_ctx,
2191 req, defer_endtime,
2192 smbd_smb2_request_pending_timer,
2193 req);
2194 if (req->async_te == NULL) {
2195 return NT_STATUS_NO_MEMORY;
2198 return NT_STATUS_OK;
2201 static
2202 struct smb2_signing_key *smbd_smb2_signing_key(struct smbXsrv_session *session,
2203 struct smbXsrv_connection *xconn,
2204 bool *_has_channel)
2206 struct smbXsrv_channel_global0 *c = NULL;
2207 NTSTATUS status;
2208 struct smb2_signing_key *key = NULL;
2209 bool has_channel = false;
2211 status = smbXsrv_session_find_channel(session, xconn, &c);
2212 if (NT_STATUS_IS_OK(status)) {
2213 key = c->signing_key;
2214 has_channel = true;
2217 if (!smb2_signing_key_valid(key)) {
2218 key = session->global->signing_key;
2219 has_channel = false;
2222 if (_has_channel != NULL) {
2223 *_has_channel = has_channel;
2226 return key;
2229 static NTSTATUS smb2_get_new_nonce(struct smbXsrv_session *session,
2230 uint64_t *new_nonce_high,
2231 uint64_t *new_nonce_low)
2233 uint64_t nonce_high;
2234 uint64_t nonce_low;
2236 session->nonce_low += 1;
2237 if (session->nonce_low == 0) {
2238 session->nonce_low += 1;
2239 session->nonce_high += 1;
2243 * CCM and GCM algorithms must never have their
2244 * nonce wrap, or the security of the whole
2245 * communication and the keys is destroyed.
2246 * We must drop the connection once we have
2247 * transferred too much data.
2249 * NOTE: We assume nonces greater than 8 bytes.
2251 if (session->nonce_high >= session->nonce_high_max) {
2252 return NT_STATUS_ENCRYPTION_FAILED;
2255 nonce_high = session->nonce_high_random;
2256 nonce_high += session->nonce_high;
2257 nonce_low = session->nonce_low;
2259 *new_nonce_high = nonce_high;
2260 *new_nonce_low = nonce_low;
2261 return NT_STATUS_OK;
2264 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
2265 struct tevent_timer *te,
2266 struct timeval current_time,
2267 void *private_data)
2269 struct smbd_smb2_request *req =
2270 talloc_get_type_abort(private_data,
2271 struct smbd_smb2_request);
2272 struct smbXsrv_connection *xconn = req->xconn;
2273 struct smbd_smb2_request_pending_state *state = NULL;
2274 uint8_t *outhdr = NULL;
2275 const uint8_t *inhdr = NULL;
2276 uint8_t *tf = NULL;
2277 uint8_t *hdr = NULL;
2278 uint8_t *body = NULL;
2279 uint8_t *dyn = NULL;
2280 uint32_t flags = 0;
2281 uint64_t message_id = 0;
2282 uint64_t async_id = 0;
2283 NTSTATUS status;
2284 bool ok;
2286 TALLOC_FREE(req->async_te);
2288 /* Ensure our final reply matches the interim one. */
2289 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2290 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2291 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
2292 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
2294 async_id = message_id; /* keep it simple for now... */
2296 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
2297 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
2299 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
2300 "going async\n",
2301 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
2302 (unsigned long long)async_id ));
2305 * What we send is identical to a smbd_smb2_request_error
2306 * packet with an error status of STATUS_PENDING. Make use
2307 * of this fact sometime when refactoring. JRA.
2310 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
2311 if (state == NULL) {
2312 smbd_server_connection_terminate(xconn,
2313 nt_errstr(NT_STATUS_NO_MEMORY));
2314 return;
2317 tf = state->buf + NBT_HDR_SIZE;
2319 hdr = tf + SMB2_TF_HDR_SIZE;
2320 body = hdr + SMB2_HDR_BODY;
2321 dyn = body + 8;
2323 if (req->do_encryption) {
2324 uint64_t nonce_high = 0;
2325 uint64_t nonce_low = 0;
2326 uint64_t session_id = req->session->global->session_wire_id;
2328 status = smb2_get_new_nonce(req->session,
2329 &nonce_high,
2330 &nonce_low);
2331 if (!NT_STATUS_IS_OK(status)) {
2332 smbd_server_connection_terminate(xconn,
2333 nt_errstr(status));
2334 return;
2337 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2338 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2339 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2340 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2343 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
2344 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2345 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2346 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(NT_STATUS_PENDING));
2347 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
2350 * The STATUS_PENDING response has SMB2_HDR_FLAG_SIGNED
2351 * clearedm, but echoes the signature field.
2353 flags &= ~SMB2_HDR_FLAG_SIGNED;
2354 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
2355 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2356 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
2357 SBVAL(hdr, SMB2_HDR_PID, async_id);
2358 SBVAL(hdr, SMB2_HDR_SESSION_ID,
2359 BVAL(outhdr, SMB2_HDR_SESSION_ID));
2360 memcpy(hdr+SMB2_HDR_SIGNATURE,
2361 outhdr+SMB2_HDR_SIGNATURE, 16);
2363 SSVAL(body, 0x00, 0x08 + 1);
2365 SCVAL(body, 0x02, 0);
2366 SCVAL(body, 0x03, 0);
2367 SIVAL(body, 0x04, 0);
2368 /* Match W2K8R2... */
2369 SCVAL(dyn, 0x00, 0x21);
2371 state->vector[0].iov_base = (void *)state->buf;
2372 state->vector[0].iov_len = NBT_HDR_SIZE;
2374 if (req->do_encryption) {
2375 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
2376 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len =
2377 SMB2_TF_HDR_SIZE;
2378 } else {
2379 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
2380 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
2383 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
2384 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
2386 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
2387 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
2389 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
2390 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
2392 ok = smb2_setup_nbt_length(state->vector,
2393 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2394 if (!ok) {
2395 smbd_server_connection_terminate(
2396 xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
2397 return;
2400 /* Ensure we correctly go through crediting. Grant
2401 the credits now, and zero credits on the final
2402 response. */
2403 smb2_set_operation_credit(req->xconn,
2404 SMBD_SMB2_IN_HDR_IOV(req),
2405 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
2408 * We add SMB2_HDR_FLAG_ASYNC after smb2_set_operation_credit()
2409 * as it reacts on it
2411 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
2413 if (DEBUGLVL(10)) {
2414 int i;
2416 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
2417 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
2418 (unsigned int)i,
2419 (unsigned int)ARRAY_SIZE(state->vector),
2420 (unsigned int)state->vector[i].iov_len);
2424 if (req->do_encryption) {
2425 struct smbXsrv_session *x = req->session;
2426 struct smb2_signing_key *encryption_key = x->global->encryption_key;
2428 status = smb2_signing_encrypt_pdu(encryption_key,
2429 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2430 SMBD_SMB2_NUM_IOV_PER_REQ);
2431 if (!NT_STATUS_IS_OK(status)) {
2432 smbd_server_connection_terminate(xconn,
2433 nt_errstr(status));
2434 return;
2438 state->queue_entry.mem_ctx = state;
2439 state->queue_entry.vector = state->vector;
2440 state->queue_entry.count = ARRAY_SIZE(state->vector);
2441 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
2442 xconn->smb2.send_queue_len++;
2444 status = smbd_smb2_flush_send_queue(xconn);
2445 if (!NT_STATUS_IS_OK(status)) {
2446 smbd_server_connection_terminate(xconn,
2447 nt_errstr(status));
2448 return;
2452 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
2454 struct smbXsrv_connection *xconn = req->xconn;
2455 struct smbd_smb2_request *cur;
2456 const uint8_t *inhdr;
2457 uint32_t flags;
2458 uint64_t search_message_id;
2459 uint64_t search_async_id;
2460 uint64_t found_id;
2462 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2464 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2465 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2466 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
2469 * We don't need the request anymore cancel requests never
2470 * have a response.
2472 * We defer the TALLOC_FREE(req) to the caller.
2474 DLIST_REMOVE(xconn->smb2.requests, req);
2476 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
2477 const uint8_t *outhdr;
2478 uint64_t message_id;
2479 uint64_t async_id;
2481 if (cur->session != req->session) {
2482 continue;
2485 if (cur->compound_related) {
2487 * Never cancel anything in a compound request.
2488 * Way too hard to deal with the result.
2490 continue;
2493 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
2495 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
2496 async_id = BVAL(outhdr, SMB2_HDR_PID);
2498 if (flags & SMB2_HDR_FLAG_ASYNC) {
2499 if (search_async_id == async_id) {
2500 found_id = async_id;
2501 break;
2503 } else {
2504 if (search_message_id == message_id) {
2505 found_id = message_id;
2506 break;
2511 if (cur && cur->subreq) {
2512 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
2513 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
2514 "cancel opcode[%s] mid %llu\n",
2515 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
2516 (unsigned long long)found_id ));
2517 tevent_req_cancel(cur->subreq);
2520 return NT_STATUS_OK;
2523 /*************************************************************
2524 Ensure an incoming tid is a valid one for us to access.
2525 Change to the associated uid credentials and chdir to the
2526 valid tid directory.
2527 *************************************************************/
2529 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
2531 const uint8_t *inhdr;
2532 uint32_t in_flags;
2533 uint32_t in_tid;
2534 struct smbXsrv_tcon *tcon;
2535 NTSTATUS status;
2536 NTTIME now = timeval_to_nttime(&req->request_time);
2538 req->tcon = NULL;
2540 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2542 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2543 in_tid = IVAL(inhdr, SMB2_HDR_TID);
2545 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
2546 in_tid = req->last_tid;
2549 req->last_tid = 0;
2551 status = smb2srv_tcon_lookup(req->session,
2552 in_tid, now, &tcon);
2553 if (!NT_STATUS_IS_OK(status)) {
2554 return status;
2557 if (!change_to_user_and_service(
2558 tcon->compat,
2559 req->session->global->session_wire_id))
2561 return NT_STATUS_ACCESS_DENIED;
2564 req->tcon = tcon;
2565 req->last_tid = in_tid;
2567 return NT_STATUS_OK;
2570 /*************************************************************
2571 Ensure an incoming session_id is a valid one for us to access.
2572 *************************************************************/
2574 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
2576 const uint8_t *inhdr;
2577 uint32_t in_flags;
2578 uint16_t in_opcode;
2579 uint64_t in_session_id;
2580 struct smbXsrv_session *session = NULL;
2581 struct auth_session_info *session_info;
2582 NTSTATUS status;
2583 NTTIME now = timeval_to_nttime(&req->request_time);
2585 req->session = NULL;
2586 req->tcon = NULL;
2588 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2590 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2591 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2592 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
2594 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
2595 in_session_id = req->last_session_id;
2598 req->last_session_id = 0;
2600 /* look an existing session up */
2601 switch (in_opcode) {
2602 case SMB2_OP_SESSSETUP:
2604 * For a session bind request, we don't have the
2605 * channel set up at this point yet, so we defer
2606 * the verification that the connection belongs
2607 * to the session to the session setup code, which
2608 * can look at the session binding flags.
2610 status = smb2srv_session_lookup_client(req->xconn->client,
2611 in_session_id, now,
2612 &session);
2613 break;
2614 default:
2615 status = smb2srv_session_lookup_conn(req->xconn,
2616 in_session_id, now,
2617 &session);
2618 break;
2620 if (session) {
2621 req->session = session;
2622 req->last_session_id = in_session_id;
2624 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
2625 switch (in_opcode) {
2626 case SMB2_OP_SESSSETUP:
2627 status = smb2srv_session_lookup_global(req->xconn->client,
2628 in_session_id,
2629 req,
2630 &session);
2631 if (NT_STATUS_IS_OK(status)) {
2633 * We fallback to a session of
2634 * another process in order to
2635 * get the signing correct.
2637 * We don't set req->last_session_id here.
2639 req->session = session;
2641 break;
2642 default:
2643 break;
2646 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
2647 switch (in_opcode) {
2648 case SMB2_OP_SESSSETUP:
2649 status = NT_STATUS_OK;
2650 break;
2651 case SMB2_OP_LOGOFF:
2652 case SMB2_OP_CLOSE:
2653 case SMB2_OP_LOCK:
2654 case SMB2_OP_CANCEL:
2655 case SMB2_OP_KEEPALIVE:
2657 * [MS-SMB2] 3.3.5.2.9 Verifying the Session
2658 * specifies that LOGOFF, CLOSE and (UN)LOCK
2659 * should always be processed even on expired sessions.
2661 * Also see the logic in
2662 * smbd_smb2_request_process_lock().
2664 * The smb2.session.expire2 test shows that
2665 * CANCEL and KEEPALIVE/ECHO should also
2666 * be processed.
2668 status = NT_STATUS_OK;
2669 break;
2670 default:
2671 break;
2674 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2675 switch (in_opcode) {
2676 case SMB2_OP_TCON:
2677 case SMB2_OP_CREATE:
2678 case SMB2_OP_GETINFO:
2679 case SMB2_OP_SETINFO:
2680 return NT_STATUS_INVALID_HANDLE;
2681 default:
2683 * Notice the check for
2684 * (session_info == NULL)
2685 * below.
2687 status = NT_STATUS_OK;
2688 break;
2691 if (!NT_STATUS_IS_OK(status)) {
2692 return status;
2695 session_info = session->global->auth_session_info;
2696 if (session_info == NULL) {
2697 return NT_STATUS_INVALID_HANDLE;
2700 return NT_STATUS_OK;
2703 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
2704 uint32_t data_length)
2706 struct smbXsrv_connection *xconn = req->xconn;
2707 uint16_t needed_charge;
2708 uint16_t credit_charge = 1;
2709 const uint8_t *inhdr;
2711 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2713 if (xconn->smb2.credits.multicredit) {
2714 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
2715 credit_charge = MAX(credit_charge, 1);
2718 needed_charge = (data_length - 1)/ 65536 + 1;
2720 DBGC_DEBUG(DBGC_SMB2_CREDITS,
2721 "mid %llu, CreditCharge: %d, NeededCharge: %d\n",
2722 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
2723 credit_charge, needed_charge);
2725 if (needed_charge > credit_charge) {
2726 DBGC_WARNING(DBGC_SMB2_CREDITS,
2727 "CreditCharge too low, given %d, needed %d\n",
2728 credit_charge, needed_charge);
2729 return NT_STATUS_INVALID_PARAMETER;
2732 return NT_STATUS_OK;
2735 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
2736 size_t expected_body_size)
2738 struct iovec *inhdr_v;
2739 const uint8_t *inhdr;
2740 uint16_t opcode;
2741 const uint8_t *inbody;
2742 size_t body_size;
2743 size_t min_dyn_size = expected_body_size & 0x00000001;
2744 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
2747 * The following should be checked already.
2749 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
2750 return NT_STATUS_INTERNAL_ERROR;
2752 if (req->current_idx > max_idx) {
2753 return NT_STATUS_INTERNAL_ERROR;
2756 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
2757 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
2758 return NT_STATUS_INTERNAL_ERROR;
2760 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
2761 return NT_STATUS_INTERNAL_ERROR;
2764 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2765 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2767 switch (opcode) {
2768 case SMB2_OP_IOCTL:
2769 case SMB2_OP_GETINFO:
2770 case SMB2_OP_WRITE:
2771 min_dyn_size = 0;
2772 break;
2776 * Now check the expected body size,
2777 * where the last byte might be in the
2778 * dynamic section..
2780 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
2781 return NT_STATUS_INVALID_PARAMETER;
2783 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
2784 return NT_STATUS_INVALID_PARAMETER;
2787 inbody = SMBD_SMB2_IN_BODY_PTR(req);
2789 body_size = SVAL(inbody, 0x00);
2790 if (body_size != expected_body_size) {
2791 return NT_STATUS_INVALID_PARAMETER;
2794 return NT_STATUS_OK;
2797 bool smbXsrv_is_encrypted(uint8_t encryption_flags)
2799 return (!(encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)
2801 (encryption_flags & (SMBXSRV_PROCESSED_ENCRYPTED_PACKET |
2802 SMBXSRV_ENCRYPTION_DESIRED |
2803 SMBXSRV_ENCRYPTION_REQUIRED)));
2806 bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags)
2808 return ((encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET) &&
2809 (encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET));
2812 /* Set a flag if not already set, return true if set */
2813 bool smbXsrv_set_crypto_flag(uint8_t *flags, uint8_t flag)
2815 if ((flag == 0) || (*flags & flag)) {
2816 return false;
2819 *flags |= flag;
2820 return true;
2824 * Update encryption state tracking flags, this can be used to
2825 * determine whether whether the session or tcon is "encrypted".
2827 static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
2828 uint16_t opcode,
2829 bool *update_session_globalp,
2830 bool *update_tcon_globalp)
2832 /* Default: assume unecrypted and unsigned */
2833 struct smbXsrv_session *session = req->session;
2834 struct smbXsrv_tcon *tcon = req->tcon;
2835 uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
2836 uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2837 bool update_session = false;
2838 bool update_tcon = false;
2840 if (session->table == NULL) {
2842 * sessions from smb2srv_session_lookup_global()
2843 * have NT_STATUS_BAD_LOGON_SESSION_STATE
2844 * and session->table == NULL.
2846 * They only used to give the correct error
2847 * status, we should not update any state.
2849 goto out;
2852 if (req->was_encrypted && req->do_encryption) {
2853 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
2854 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2855 } else {
2856 /* Unencrypted packet, can be signed */
2857 if (req->do_signing) {
2858 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2862 update_session |= smbXsrv_set_crypto_flag(
2863 &session->global->encryption_flags, encrypt_flag);
2864 update_session |= smbXsrv_set_crypto_flag(
2865 &session->global->signing_flags, sign_flag);
2867 if (tcon) {
2868 update_tcon |= smbXsrv_set_crypto_flag(
2869 &tcon->global->encryption_flags, encrypt_flag);
2870 update_tcon |= smbXsrv_set_crypto_flag(
2871 &tcon->global->signing_flags, sign_flag);
2874 out:
2875 *update_session_globalp = update_session;
2876 *update_tcon_globalp = update_tcon;
2877 return;
2880 bool smbXsrv_is_signed(uint8_t signing_flags)
2883 * Signing is always enabled, so unless we got an unsigned
2884 * packet and at least one signed packet that was not
2885 * encrypted, the session or tcon is "signed".
2887 return (!(signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2888 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2891 bool smbXsrv_is_partially_signed(uint8_t signing_flags)
2893 return ((signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2894 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2897 static NTSTATUS smbd_smb2_request_dispatch_update_counts(
2898 struct smbd_smb2_request *req,
2899 bool modify_call)
2901 struct smbXsrv_connection *xconn = req->xconn;
2902 const uint8_t *inhdr;
2903 uint16_t channel_sequence;
2904 uint8_t generation_wrap = 0;
2905 uint32_t flags;
2906 int cmp;
2907 struct smbXsrv_open *op;
2908 bool update_open = false;
2909 NTSTATUS status = NT_STATUS_OK;
2911 SMB_ASSERT(!req->request_counters_updated);
2913 if (xconn->protocol < PROTOCOL_SMB3_00) {
2914 return NT_STATUS_OK;
2917 if (req->compat_chain_fsp == NULL) {
2918 return NT_STATUS_OK;
2921 op = req->compat_chain_fsp->op;
2922 if (op == NULL) {
2923 return NT_STATUS_OK;
2926 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2927 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2928 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2930 cmp = channel_sequence - op->global->channel_sequence;
2931 if (cmp < 0) {
2933 * csn wrap. We need to watch out for long-running
2934 * requests that are still sitting on a previously
2935 * used csn. SMB2_OP_NOTIFY can take VERY long.
2937 generation_wrap += 1;
2940 if (abs(cmp) > INT16_MAX) {
2942 * [MS-SMB2] 3.3.5.2.10 - Verifying the Channel Sequence Number:
2944 * If the channel sequence number of the request and the one
2945 * known to the server are not equal, the channel sequence
2946 * number and outstanding request counts are only updated
2947 * "... if the unsigned difference using 16-bit arithmetic
2948 * between ChannelSequence and Open.ChannelSequence is less than
2949 * or equal to 0x7FFF ...".
2950 * Otherwise, an error is returned for the modifying
2951 * calls write, set_info, and ioctl.
2953 * There are currently two issues with the description:
2955 * * For the other calls, the document seems to imply
2956 * that processing continues without adapting the
2957 * counters (if the sequence numbers are not equal).
2959 * TODO: This needs clarification!
2961 * * Also, the behaviour if the difference is larger
2962 * than 0x7FFF is not clear. The document seems to
2963 * imply that if such a difference is reached,
2964 * the server starts to ignore the counters or
2965 * in the case of the modifying calls, return errors.
2967 * TODO: This needs clarification!
2969 * At this point Samba tries to be a little more
2970 * clever than the description in the MS-SMB2 document
2971 * by heuristically detecting and properly treating
2972 * a 16 bit overflow of the client-submitted sequence
2973 * number:
2975 * If the stored channel sequence number is more than
2976 * 0x7FFF larger than the one from the request, then
2977 * the client-provided sequence number has likely
2978 * overflown. We treat this case as valid instead
2979 * of as failure.
2981 * The MS-SMB2 behaviour would be setting cmp = -1.
2983 cmp *= -1;
2986 if (flags & SMB2_HDR_FLAG_REPLAY_OPERATION) {
2987 if (cmp == 0 && op->pre_request_count == 0) {
2988 op->request_count += 1;
2989 req->request_counters_updated = true;
2990 } else if (cmp > 0 && op->pre_request_count == 0) {
2991 op->pre_request_count += op->request_count;
2992 op->request_count = 1;
2993 op->global->channel_sequence = channel_sequence;
2994 op->global->channel_generation += generation_wrap;
2995 update_open = true;
2996 req->request_counters_updated = true;
2997 } else if (modify_call) {
2998 return NT_STATUS_FILE_NOT_AVAILABLE;
3000 } else {
3001 if (cmp == 0) {
3002 op->request_count += 1;
3003 req->request_counters_updated = true;
3004 } else if (cmp > 0) {
3005 op->pre_request_count += op->request_count;
3006 op->request_count = 1;
3007 op->global->channel_sequence = channel_sequence;
3008 op->global->channel_generation += generation_wrap;
3009 update_open = true;
3010 req->request_counters_updated = true;
3011 } else if (modify_call) {
3012 return NT_STATUS_FILE_NOT_AVAILABLE;
3015 req->channel_generation = op->global->channel_generation;
3017 if (update_open) {
3018 status = smbXsrv_open_update(op);
3021 return status;
3024 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
3026 struct smbXsrv_connection *xconn = req->xconn;
3027 const struct smbd_smb2_dispatch_table *call = NULL;
3028 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
3029 const uint8_t *inhdr;
3030 uint16_t opcode;
3031 uint32_t flags;
3032 uint64_t mid;
3033 NTSTATUS status;
3034 NTSTATUS session_status;
3035 uint32_t allowed_flags;
3036 NTSTATUS return_value;
3037 struct smbXsrv_session *x = NULL;
3038 bool signing_required = false;
3039 bool encryption_desired = false;
3040 bool encryption_required = false;
3042 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
3044 DO_PROFILE_INC(request);
3046 SMB_ASSERT(!req->request_counters_updated);
3048 /* TODO: verify more things */
3050 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
3051 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
3052 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
3053 DBG_DEBUG("opcode[%s] mid = %"PRIu64"\n",
3054 smb2_opcode_name(opcode),
3055 mid);
3057 if (xconn->protocol >= PROTOCOL_SMB2_02) {
3059 * once the protocol is negotiated
3060 * SMB2_OP_NEGPROT is not allowed anymore
3062 if (opcode == SMB2_OP_NEGPROT) {
3063 /* drop the connection */
3064 return NT_STATUS_INVALID_PARAMETER;
3066 } else {
3068 * if the protocol is not negotiated yet
3069 * only SMB2_OP_NEGPROT is allowed.
3071 if (opcode != SMB2_OP_NEGPROT) {
3072 /* drop the connection */
3073 return NT_STATUS_INVALID_PARAMETER;
3078 * Check if the client provided a valid session id.
3080 * As some command don't require a valid session id
3081 * we defer the check of the session_status
3083 session_status = smbd_smb2_request_check_session(req);
3084 x = req->session;
3085 if (x != NULL) {
3086 signing_required = x->global->signing_flags & SMBXSRV_SIGNING_REQUIRED;
3087 encryption_desired = x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
3088 encryption_required = x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
3091 req->async_internal = false;
3092 req->do_signing = false;
3093 if (opcode != SMB2_OP_SESSSETUP) {
3094 req->do_encryption = encryption_desired;
3095 } else {
3096 req->do_encryption = false;
3098 req->was_encrypted = false;
3099 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
3100 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
3101 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
3103 if (x != NULL && x->global->session_wire_id != tf_session_id) {
3104 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
3105 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
3106 (unsigned long long)x->global->session_wire_id,
3107 (unsigned long long)tf_session_id));
3109 * TODO: windows allows this...
3110 * should we drop the connection?
3112 * For now we just return ACCESS_DENIED
3113 * (Windows clients never trigger this)
3114 * and wait for an update of [MS-SMB2].
3116 return smbd_smb2_request_error(req,
3117 NT_STATUS_ACCESS_DENIED);
3120 req->was_encrypted = true;
3121 req->do_encryption = true;
3124 if (encryption_required && !req->was_encrypted) {
3125 req->do_encryption = true;
3126 return smbd_smb2_request_error(req,
3127 NT_STATUS_ACCESS_DENIED);
3130 call = smbd_smb2_call(opcode);
3131 if (call == NULL) {
3132 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
3135 allowed_flags = SMB2_HDR_FLAG_CHAINED |
3136 SMB2_HDR_FLAG_SIGNED |
3137 SMB2_HDR_FLAG_DFS;
3138 if (xconn->protocol >= PROTOCOL_SMB3_11) {
3139 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
3141 if (opcode == SMB2_OP_NEGPROT) {
3142 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11) {
3143 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
3146 if (opcode == SMB2_OP_CANCEL) {
3147 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
3149 if (xconn->protocol >= PROTOCOL_SMB3_00) {
3150 allowed_flags |= SMB2_HDR_FLAG_REPLAY_OPERATION;
3152 if ((flags & ~allowed_flags) != 0) {
3153 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
3156 if (flags & SMB2_HDR_FLAG_CHAINED) {
3158 * This check is mostly for giving the correct error code
3159 * for compounded requests.
3161 if (!NT_STATUS_IS_OK(session_status)) {
3162 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
3164 } else {
3165 req->compat_chain_fsp = NULL;
3168 if (req->was_encrypted) {
3169 signing_required = false;
3170 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
3171 struct smb2_signing_key *signing_key = NULL;
3172 bool has_channel = false;
3174 if (x == NULL) {
3176 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
3177 * If the SMB2 header of the SMB2 NEGOTIATE
3178 * request has the SMB2_FLAGS_SIGNED bit set in the
3179 * Flags field, the server MUST fail the request
3180 * with STATUS_INVALID_PARAMETER.
3182 * Microsoft test tool checks this.
3185 if ((opcode == SMB2_OP_NEGPROT) &&
3186 (flags & SMB2_HDR_FLAG_SIGNED)) {
3187 status = NT_STATUS_INVALID_PARAMETER;
3188 } else {
3189 status = NT_STATUS_USER_SESSION_DELETED;
3191 return smbd_smb2_request_error(req, status);
3194 signing_key = smbd_smb2_signing_key(x, xconn, &has_channel);
3197 * If we have a signing key, we should
3198 * sign the response
3200 if (smb2_signing_key_valid(signing_key) && opcode != SMB2_OP_CANCEL) {
3201 req->do_signing = true;
3204 status = smb2_signing_check_pdu(signing_key,
3205 SMBD_SMB2_IN_HDR_IOV(req),
3206 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
3207 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
3208 opcode == SMB2_OP_SESSSETUP && !has_channel &&
3209 NT_STATUS_IS_OK(session_status))
3211 if (!NT_STATUS_EQUAL(x->status, NT_STATUS_BAD_LOGON_SESSION_STATE)) {
3212 struct smbXsrv_session *session = NULL;
3213 NTSTATUS error;
3215 error = smb2srv_session_lookup_global(req->xconn->client,
3216 x->global->session_wire_id,
3217 req,
3218 &session);
3219 if (!NT_STATUS_IS_OK(error)) {
3220 return smbd_smb2_request_error(req, error);
3224 * We fallback to a session of
3225 * another process in order to
3226 * get the signing correct.
3228 * We don't set req->last_session_id here.
3230 req->session = x = session;
3232 goto skipped_signing;
3234 if (!NT_STATUS_IS_OK(status)) {
3235 return smbd_smb2_request_error(req, status);
3239 * Now that we know the request was correctly signed
3240 * we have to sign the response too.
3242 if (opcode != SMB2_OP_CANCEL) {
3243 req->do_signing = true;
3246 if (!NT_STATUS_IS_OK(session_status)) {
3247 return smbd_smb2_request_error(req, session_status);
3251 if (opcode == SMB2_OP_IOCTL) {
3253 * Some special IOCTL calls don't require
3254 * file, tcon nor session.
3256 * They typically don't do any real action
3257 * on behalf of the client.
3259 * They are mainly used to alter the behavior
3260 * of the connection for testing. So we can
3261 * run as root and skip all file, tcon and session
3262 * checks below.
3264 static const struct smbd_smb2_dispatch_table _root_ioctl_call = {
3265 .opcode = SMB2_OP_IOCTL,
3266 .as_root = true,
3268 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
3269 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
3270 uint32_t in_ctl_code;
3271 size_t needed = 8;
3273 if (needed > body_size) {
3274 return smbd_smb2_request_error(req,
3275 NT_STATUS_INVALID_PARAMETER);
3278 in_ctl_code = IVAL(body, 0x04);
3280 * Only add trusted IOCTL codes here!
3282 switch (in_ctl_code) {
3283 case FSCTL_SMBTORTURE_FORCE_UNACKED_TIMEOUT:
3284 call = &_root_ioctl_call;
3285 break;
3286 case FSCTL_VALIDATE_NEGOTIATE_INFO:
3287 call = &_root_ioctl_call;
3288 break;
3289 case FSCTL_QUERY_NETWORK_INTERFACE_INFO:
3290 call = &_root_ioctl_call;
3291 break;
3295 skipped_signing:
3297 if (flags & SMB2_HDR_FLAG_CHAINED) {
3298 req->compound_related = true;
3301 if (call->need_session) {
3302 if (!NT_STATUS_IS_OK(session_status)) {
3303 return smbd_smb2_request_error(req, session_status);
3307 if (call->need_tcon) {
3308 SMB_ASSERT(call->need_session);
3311 * This call needs to be run as user.
3313 * smbd_smb2_request_check_tcon()
3314 * calls change_to_user() on success.
3315 * Which implies set_current_user_info()
3316 * and chdir_current_service().
3318 status = smbd_smb2_request_check_tcon(req);
3319 if (!NT_STATUS_IS_OK(status)) {
3320 return smbd_smb2_request_error(req, status);
3322 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
3323 encryption_desired = true;
3325 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
3326 encryption_required = true;
3328 if (encryption_required && !req->was_encrypted) {
3329 req->do_encryption = true;
3330 return smbd_smb2_request_error(req,
3331 NT_STATUS_ACCESS_DENIED);
3332 } else if (encryption_desired) {
3333 req->do_encryption = true;
3335 } else if (call->need_session) {
3336 struct auth_session_info *session_info = NULL;
3339 * Unless we also have need_tcon (see above),
3340 * we still need to call set_current_user_info().
3343 session_info = req->session->global->auth_session_info;
3344 if (session_info == NULL) {
3345 return NT_STATUS_INVALID_HANDLE;
3348 set_current_user_info(session_info->unix_info->sanitized_username,
3349 session_info->unix_info->unix_name,
3350 session_info->info->domain_name);
3353 if (req->session) {
3354 bool update_session_global = false;
3355 bool update_tcon_global = false;
3357 smb2srv_update_crypto_flags(req, opcode,
3358 &update_session_global,
3359 &update_tcon_global);
3361 if (update_session_global) {
3362 status = smbXsrv_session_update(x);
3363 if (!NT_STATUS_IS_OK(status)) {
3364 return smbd_smb2_request_error(req, status);
3367 if (update_tcon_global) {
3368 status = smbXsrv_tcon_update(req->tcon);
3369 if (!NT_STATUS_IS_OK(status)) {
3370 return smbd_smb2_request_error(req, status);
3375 if (call->fileid_ofs != 0) {
3376 size_t needed = call->fileid_ofs + 16;
3377 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
3378 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
3379 uint64_t file_id_persistent;
3380 uint64_t file_id_volatile;
3381 struct files_struct *fsp;
3383 SMB_ASSERT(call->need_tcon);
3385 if (needed > body_size) {
3386 return smbd_smb2_request_error(req,
3387 NT_STATUS_INVALID_PARAMETER);
3390 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
3391 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
3393 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
3394 if (fsp == NULL) {
3395 if (req->compound_related &&
3396 !NT_STATUS_IS_OK(req->compound_create_err))
3398 return smbd_smb2_request_error(req,
3399 req->compound_create_err);
3402 * smbd_smb2_request_process_ioctl()
3403 * has more checks in order to return more
3404 * detailed error codes...
3406 if (opcode != SMB2_OP_IOCTL) {
3407 return smbd_smb2_request_error(req,
3408 NT_STATUS_FILE_CLOSED);
3410 } else {
3411 if (fsp->fsp_flags.encryption_required && !req->was_encrypted) {
3412 return smbd_smb2_request_error(req,
3413 NT_STATUS_ACCESS_DENIED);
3418 status = smbd_smb2_request_dispatch_update_counts(req, call->modify);
3419 if (!NT_STATUS_IS_OK(status)) {
3420 return smbd_smb2_request_error(req, status);
3423 if (call->as_root) {
3424 SMB_ASSERT(call->fileid_ofs == 0);
3425 /* This call needs to be run as root */
3426 change_to_root_user();
3427 } else if (opcode != SMB2_OP_KEEPALIVE) {
3428 SMB_ASSERT(call->need_tcon);
3431 #define _INBYTES(_r) \
3432 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
3434 switch (opcode) {
3435 case SMB2_OP_NEGPROT:
3436 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
3437 req->profile, _INBYTES(req));
3438 return_value = smbd_smb2_request_process_negprot(req);
3439 break;
3441 case SMB2_OP_SESSSETUP:
3442 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
3443 req->profile, _INBYTES(req));
3444 return_value = smbd_smb2_request_process_sesssetup(req);
3445 break;
3447 case SMB2_OP_LOGOFF:
3448 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
3449 req->profile, _INBYTES(req));
3450 return_value = smbd_smb2_request_process_logoff(req);
3451 break;
3453 case SMB2_OP_TCON:
3454 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
3455 req->profile, _INBYTES(req));
3456 return_value = smbd_smb2_request_process_tcon(req);
3457 break;
3459 case SMB2_OP_TDIS:
3460 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
3461 req->profile, _INBYTES(req));
3462 return_value = smbd_smb2_request_process_tdis(req);
3463 break;
3465 case SMB2_OP_CREATE:
3466 if (req->subreq == NULL) {
3467 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
3468 req->profile, _INBYTES(req));
3469 } else {
3470 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
3472 return_value = smbd_smb2_request_process_create(req);
3473 break;
3475 case SMB2_OP_CLOSE:
3476 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
3477 req->profile, _INBYTES(req));
3478 return_value = smbd_smb2_request_process_close(req);
3479 break;
3481 case SMB2_OP_FLUSH:
3482 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
3483 req->profile, _INBYTES(req));
3484 return_value = smbd_smb2_request_process_flush(req);
3485 break;
3487 case SMB2_OP_READ:
3488 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
3489 req->profile, _INBYTES(req));
3490 return_value = smbd_smb2_request_process_read(req);
3491 break;
3493 case SMB2_OP_WRITE:
3494 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
3495 req->profile, _INBYTES(req));
3496 return_value = smbd_smb2_request_process_write(req);
3497 break;
3499 case SMB2_OP_LOCK:
3500 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
3501 req->profile, _INBYTES(req));
3502 return_value = smbd_smb2_request_process_lock(req);
3503 break;
3505 case SMB2_OP_IOCTL:
3506 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
3507 req->profile, _INBYTES(req));
3508 return_value = smbd_smb2_request_process_ioctl(req);
3509 break;
3511 case SMB2_OP_CANCEL:
3512 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
3513 req->profile, _INBYTES(req));
3514 return_value = smbd_smb2_request_process_cancel(req);
3515 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
3518 * We don't need the request anymore cancel requests never
3519 * have a response.
3521 * smbd_smb2_request_process_cancel() already called
3522 * DLIST_REMOVE(xconn->smb2.requests, req);
3524 TALLOC_FREE(req);
3526 break;
3528 case SMB2_OP_KEEPALIVE:
3529 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
3530 req->profile, _INBYTES(req));
3531 return_value = smbd_smb2_request_process_keepalive(req);
3532 break;
3534 case SMB2_OP_QUERY_DIRECTORY:
3535 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
3536 req->profile, _INBYTES(req));
3537 return_value = smbd_smb2_request_process_query_directory(req);
3538 break;
3540 case SMB2_OP_NOTIFY:
3541 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
3542 req->profile, _INBYTES(req));
3543 return_value = smbd_smb2_request_process_notify(req);
3544 break;
3546 case SMB2_OP_GETINFO:
3547 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
3548 req->profile, _INBYTES(req));
3549 return_value = smbd_smb2_request_process_getinfo(req);
3550 break;
3552 case SMB2_OP_SETINFO:
3553 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
3554 req->profile, _INBYTES(req));
3555 return_value = smbd_smb2_request_process_setinfo(req);
3556 break;
3558 case SMB2_OP_BREAK:
3559 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
3560 req->profile, _INBYTES(req));
3561 return_value = smbd_smb2_request_process_break(req);
3562 break;
3564 default:
3565 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
3566 break;
3568 return return_value;
3571 static void smbd_smb2_request_reply_update_counts(struct smbd_smb2_request *req)
3573 struct smbXsrv_connection *xconn = req->xconn;
3574 const uint8_t *inhdr;
3575 uint16_t channel_sequence;
3576 struct smbXsrv_open *op;
3578 if (!req->request_counters_updated) {
3579 return;
3582 req->request_counters_updated = false;
3584 if (xconn->protocol < PROTOCOL_SMB3_00) {
3585 return;
3588 if (req->compat_chain_fsp == NULL) {
3589 return;
3592 op = req->compat_chain_fsp->op;
3593 if (op == NULL) {
3594 return;
3597 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
3598 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
3600 if ((op->global->channel_sequence == channel_sequence) &&
3601 (op->global->channel_generation == req->channel_generation)) {
3602 SMB_ASSERT(op->request_count > 0);
3603 op->request_count -= 1;
3604 } else {
3605 SMB_ASSERT(op->pre_request_count > 0);
3606 op->pre_request_count -= 1;
3610 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
3612 struct smbXsrv_connection *xconn = req->xconn;
3613 int first_idx = 1;
3614 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
3615 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
3616 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
3617 NTSTATUS status;
3618 bool ok;
3620 req->subreq = NULL;
3621 TALLOC_FREE(req->async_te);
3623 /* MS-SMB2: 3.3.4.1 Sending Any Outgoing Message */
3624 smbd_smb2_request_reply_update_counts(req);
3626 if (req->do_encryption &&
3627 (firsttf->iov_len == 0) &&
3628 (!smb2_signing_key_valid(req->first_enc_key)) &&
3629 (req->session != NULL) &&
3630 smb2_signing_key_valid(req->session->global->encryption_key))
3632 struct smb2_signing_key *encryption_key =
3633 req->session->global->encryption_key;
3634 uint8_t *tf;
3635 uint64_t session_id = req->session->global->session_wire_id;
3636 uint64_t nonce_high;
3637 uint64_t nonce_low;
3639 status = smb2_get_new_nonce(req->session,
3640 &nonce_high,
3641 &nonce_low);
3642 if (!NT_STATUS_IS_OK(status)) {
3643 return status;
3647 * We need to place the SMB2_TRANSFORM header before the
3648 * first SMB2 header
3652 * we need to remember the encryption key
3653 * and defer the signing/encryption until
3654 * we are sure that we do not change
3655 * the header again.
3657 status = smb2_signing_key_copy(req,
3658 encryption_key,
3659 &req->first_enc_key);
3660 if (!NT_STATUS_IS_OK(status)) {
3661 return status;
3664 tf = talloc_zero_array(req, uint8_t,
3665 SMB2_TF_HDR_SIZE);
3666 if (tf == NULL) {
3667 return NT_STATUS_NO_MEMORY;
3670 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
3671 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
3672 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
3673 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
3675 firsttf->iov_base = (void *)tf;
3676 firsttf->iov_len = SMB2_TF_HDR_SIZE;
3679 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
3680 (smb2_signing_key_valid(req->last_sign_key)) &&
3681 (firsttf->iov_len == 0))
3683 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
3684 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
3687 * As we are sure the header of the last request in the
3688 * compound chain will not change, we can to sign here
3689 * with the last signing key we remembered.
3691 status = smb2_signing_sign_pdu(req->last_sign_key,
3692 lasthdr,
3693 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
3694 if (!NT_STATUS_IS_OK(status)) {
3695 return status;
3698 TALLOC_FREE(req->last_sign_key);
3700 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
3701 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
3703 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
3705 if (req->current_idx < req->out.vector_count) {
3707 * We must process the remaining compound
3708 * SMB2 requests before any new incoming SMB2
3709 * requests. This is because incoming SMB2
3710 * requests may include a cancel for a
3711 * compound request we haven't processed
3712 * yet.
3714 struct tevent_immediate *im = tevent_create_immediate(req);
3715 if (!im) {
3716 return NT_STATUS_NO_MEMORY;
3719 if (req->do_signing && firsttf->iov_len == 0) {
3720 struct smbXsrv_session *x = req->session;
3721 struct smb2_signing_key *signing_key =
3722 smbd_smb2_signing_key(x, xconn, NULL);
3725 * we need to remember the signing key
3726 * and defer the signing until
3727 * we are sure that we do not change
3728 * the header again.
3730 status = smb2_signing_key_copy(req,
3731 signing_key,
3732 &req->last_sign_key);
3733 if (!NT_STATUS_IS_OK(status)) {
3734 return status;
3739 * smbd_smb2_request_dispatch() will redo the impersonation.
3740 * So we use req->xconn->client->raw_ev_ctx instead
3741 * of req->ev_ctx here.
3743 tevent_schedule_immediate(im,
3744 req->xconn->client->raw_ev_ctx,
3745 smbd_smb2_request_dispatch_immediate,
3746 req);
3747 return NT_STATUS_OK;
3750 if (req->compound_related) {
3751 req->compound_related = false;
3754 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
3755 if (!ok) {
3756 return NT_STATUS_INVALID_PARAMETER_MIX;
3759 /* Set credit for these operations (zero credits if this
3760 is a final reply for an async operation). */
3761 smb2_calculate_credits(req, req);
3764 * now check if we need to sign the current response
3766 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
3767 status = smb2_signing_encrypt_pdu(req->first_enc_key,
3768 firsttf,
3769 req->out.vector_count - first_idx);
3770 if (!NT_STATUS_IS_OK(status)) {
3771 return status;
3773 } else if (req->do_signing) {
3774 struct smbXsrv_session *x = req->session;
3775 struct smb2_signing_key *signing_key =
3776 smbd_smb2_signing_key(x, xconn, NULL);
3778 status = smb2_signing_sign_pdu(signing_key,
3779 outhdr,
3780 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
3781 if (!NT_STATUS_IS_OK(status)) {
3782 return status;
3785 TALLOC_FREE(req->first_enc_key);
3787 if (req->preauth != NULL) {
3788 gnutls_hash_hd_t hash_hnd = NULL;
3789 size_t i;
3790 int rc;
3792 rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_SHA512);
3793 if (rc < 0) {
3794 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3796 rc = gnutls_hash(hash_hnd,
3797 req->preauth->sha512_value,
3798 sizeof(req->preauth->sha512_value));
3799 if (rc < 0) {
3800 gnutls_hash_deinit(hash_hnd, NULL);
3801 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3803 for (i = 1; i < req->in.vector_count; i++) {
3804 rc = gnutls_hash(hash_hnd,
3805 req->in.vector[i].iov_base,
3806 req->in.vector[i].iov_len);
3807 if (rc < 0) {
3808 gnutls_hash_deinit(hash_hnd, NULL);
3809 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3812 if (rc < 0) {
3813 gnutls_hash_deinit(hash_hnd, NULL);
3814 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3816 gnutls_hash_output(hash_hnd, req->preauth->sha512_value);
3818 rc = gnutls_hash(hash_hnd,
3819 req->preauth->sha512_value,
3820 sizeof(req->preauth->sha512_value));
3821 if (rc < 0) {
3822 gnutls_hash_deinit(hash_hnd, NULL);
3823 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3825 for (i = 1; i < req->out.vector_count; i++) {
3826 rc = gnutls_hash(hash_hnd,
3827 req->out.vector[i].iov_base,
3828 req->out.vector[i].iov_len);
3829 if (rc < 0) {
3830 gnutls_hash_deinit(hash_hnd, NULL);
3831 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3835 gnutls_hash_deinit(hash_hnd, req->preauth->sha512_value);
3837 req->preauth = NULL;
3840 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
3841 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
3842 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
3843 /* Dynamic part is NULL. Chop it off,
3844 We're going to send it via sendfile. */
3845 req->out.vector_count -= 1;
3849 * We're done with this request -
3850 * move it off the "being processed" queue.
3852 DLIST_REMOVE(xconn->smb2.requests, req);
3854 req->queue_entry.mem_ctx = req;
3855 req->queue_entry.vector = req->out.vector;
3856 req->queue_entry.count = req->out.vector_count;
3857 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry);
3858 xconn->smb2.send_queue_len++;
3860 status = smbd_smb2_flush_send_queue(xconn);
3861 if (!NT_STATUS_IS_OK(status)) {
3862 return status;
3865 return NT_STATUS_OK;
3868 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
3870 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
3871 struct tevent_immediate *im,
3872 void *private_data)
3874 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
3875 struct smbd_smb2_request);
3876 struct smbXsrv_connection *xconn = req->xconn;
3877 NTSTATUS status;
3879 TALLOC_FREE(im);
3881 if (DEBUGLEVEL >= 10) {
3882 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
3883 req->current_idx, req->in.vector_count));
3884 print_req_vectors(req);
3887 status = smbd_smb2_request_dispatch(req);
3888 if (!NT_STATUS_IS_OK(status)) {
3889 smbd_server_connection_terminate(xconn, nt_errstr(status));
3890 return;
3893 status = smbd_smb2_request_next_incoming(xconn);
3894 if (!NT_STATUS_IS_OK(status)) {
3895 smbd_server_connection_terminate(xconn, nt_errstr(status));
3896 return;
3900 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
3901 NTSTATUS status,
3902 DATA_BLOB body, DATA_BLOB *dyn,
3903 const char *location)
3905 uint8_t *outhdr;
3906 struct iovec *outbody_v;
3907 struct iovec *outdyn_v;
3908 uint32_t next_command_ofs;
3909 uint64_t mid;
3911 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3912 mid = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
3914 DBG_DEBUG("mid [%"PRIu64"] idx[%d] status[%s] "
3915 "body[%u] dyn[%s:%u] at %s\n",
3916 mid,
3917 req->current_idx,
3918 nt_errstr(status),
3919 (unsigned int)body.length,
3920 dyn ? "yes" : "no",
3921 (unsigned int)(dyn ? dyn->length : 0),
3922 location);
3924 if (body.length < 2) {
3925 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3928 if ((body.length % 2) != 0) {
3929 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3932 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
3933 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
3935 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
3936 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
3938 outbody_v->iov_base = (void *)body.data;
3939 outbody_v->iov_len = body.length;
3941 if (dyn) {
3942 outdyn_v->iov_base = (void *)dyn->data;
3943 outdyn_v->iov_len = dyn->length;
3944 } else {
3945 outdyn_v->iov_base = NULL;
3946 outdyn_v->iov_len = 0;
3950 * See if we need to recalculate the offset to the next response
3952 * Note that all responses may require padding (including the very last
3953 * one).
3955 if (req->out.vector_count >= (2 * SMBD_SMB2_NUM_IOV_PER_REQ)) {
3956 next_command_ofs = SMB2_HDR_BODY;
3957 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
3958 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
3961 if ((next_command_ofs % 8) != 0) {
3962 size_t pad_size = 8 - (next_command_ofs % 8);
3963 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
3965 * if the dyn buffer is empty
3966 * we can use it to add padding
3968 uint8_t *pad;
3970 pad = talloc_zero_array(req,
3971 uint8_t, pad_size);
3972 if (pad == NULL) {
3973 return smbd_smb2_request_error(req,
3974 NT_STATUS_NO_MEMORY);
3977 outdyn_v->iov_base = (void *)pad;
3978 outdyn_v->iov_len = pad_size;
3979 } else {
3981 * For now we copy the dynamic buffer
3982 * and add the padding to the new buffer
3984 size_t old_size;
3985 uint8_t *old_dyn;
3986 size_t new_size;
3987 uint8_t *new_dyn;
3989 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
3990 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
3992 new_size = old_size + pad_size;
3993 new_dyn = talloc_zero_array(req,
3994 uint8_t, new_size);
3995 if (new_dyn == NULL) {
3996 return smbd_smb2_request_error(req,
3997 NT_STATUS_NO_MEMORY);
4000 memcpy(new_dyn, old_dyn, old_size);
4001 memset(new_dyn + old_size, 0, pad_size);
4003 outdyn_v->iov_base = (void *)new_dyn;
4004 outdyn_v->iov_len = new_size;
4006 next_command_ofs += pad_size;
4009 if ((req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) >= req->out.vector_count) {
4010 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
4011 } else {
4012 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
4014 return smbd_smb2_request_reply(req);
4017 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
4018 NTSTATUS status,
4019 uint8_t error_context_count,
4020 DATA_BLOB *info,
4021 const char *location)
4023 struct smbXsrv_connection *xconn = req->xconn;
4024 DATA_BLOB body;
4025 DATA_BLOB _dyn;
4026 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
4027 size_t unread_bytes = smbd_smb2_unread_bytes(req);
4029 DBG_NOTICE("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| "
4030 "at %s\n", req->current_idx, nt_errstr(status),
4031 info ? " +info" : "", location);
4033 if (unread_bytes) {
4034 /* Recvfile error. Drain incoming socket. */
4035 size_t ret;
4037 errno = 0;
4038 ret = drain_socket(xconn->transport.sock, unread_bytes);
4039 if (ret != unread_bytes) {
4040 NTSTATUS error;
4042 if (errno == 0) {
4043 error = NT_STATUS_IO_DEVICE_ERROR;
4044 } else {
4045 error = map_nt_error_from_unix_common(errno);
4048 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
4049 "ret[%u] errno[%d] => %s\n",
4050 (unsigned)unread_bytes,
4051 (unsigned)ret, errno, nt_errstr(error)));
4052 return error;
4056 body.data = outhdr + SMB2_HDR_BODY;
4057 body.length = 8;
4058 SSVAL(body.data, 0, 9);
4059 SCVAL(body.data, 2, error_context_count);
4061 if (info) {
4062 SIVAL(body.data, 0x04, info->length);
4063 } else {
4064 /* Allocated size of req->out.vector[i].iov_base
4065 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
4066 * 1 byte without having to do an alloc.
4068 info = &_dyn;
4069 info->data = ((uint8_t *)outhdr) +
4070 OUTVEC_ALLOC_SIZE - 1;
4071 info->length = 1;
4072 SCVAL(info->data, 0, 0);
4076 * Note: Even if there is an error, continue to process the request.
4077 * per MS-SMB2.
4080 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
4083 struct smbd_smb2_break_state {
4084 struct tevent_req *req;
4085 struct smbd_smb2_send_queue queue_entry;
4086 uint8_t nbt_hdr[NBT_HDR_SIZE];
4087 uint8_t hdr[SMB2_HDR_BODY];
4088 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
4091 static struct tevent_req *smbd_smb2_break_send(TALLOC_CTX *mem_ctx,
4092 struct tevent_context *ev,
4093 struct smbXsrv_connection *xconn,
4094 uint64_t session_id,
4095 const uint8_t *body,
4096 size_t body_len)
4098 struct tevent_req *req = NULL;
4099 struct smbd_smb2_break_state *state = NULL;
4100 NTSTATUS status;
4101 bool ok;
4103 req = tevent_req_create(mem_ctx, &state,
4104 struct smbd_smb2_break_state);
4105 if (req == NULL) {
4106 return NULL;
4109 state->req = req;
4110 tevent_req_defer_callback(req, ev);
4112 SIVAL(state->hdr, 0, SMB2_MAGIC);
4113 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
4114 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
4115 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
4116 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
4117 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
4118 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
4119 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
4120 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
4121 SIVAL(state->hdr, SMB2_HDR_PID, 0);
4122 SIVAL(state->hdr, SMB2_HDR_TID, 0);
4123 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, session_id);
4124 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
4126 state->vector[0] = (struct iovec) {
4127 .iov_base = state->nbt_hdr,
4128 .iov_len = sizeof(state->nbt_hdr)
4131 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
4132 .iov_base = NULL,
4133 .iov_len = 0
4136 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
4137 .iov_base = state->hdr,
4138 .iov_len = sizeof(state->hdr)
4141 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
4142 .iov_base = discard_const_p(uint8_t, body),
4143 .iov_len = body_len,
4147 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
4150 ok = smb2_setup_nbt_length(state->vector,
4151 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
4152 if (!ok) {
4153 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
4154 return tevent_req_post(req, ev);
4158 * We require TCP acks for this PDU to the client!
4159 * We want 5 retransmissions and timeout when the
4160 * retransmission timeout (rto) passed 6 times.
4162 * required_acked_bytes gets a dummy value of
4163 * UINT64_MAX, as long it's in xconn->smb2.send_queue,
4164 * it'll get the real value when it's moved to
4165 * xconn->ack.queue.
4167 * state->queue_entry.ack.req gets completed with
4168 * 1. tevent_req_done(), when all bytes are acked.
4169 * 2a. tevent_req_nterror(NT_STATUS_IO_TIMEOUT), when
4170 * the timeout expired before all bytes were acked.
4171 * 2b. tevent_req_nterror(transport_error), when the
4172 * connection got a disconnect from the kernel.
4174 state->queue_entry.ack.timeout =
4175 timeval_current_ofs_usec(xconn->ack.rto_usecs * 6);
4176 state->queue_entry.ack.required_acked_bytes = UINT64_MAX;
4177 state->queue_entry.ack.req = req;
4178 state->queue_entry.mem_ctx = state;
4179 state->queue_entry.vector = state->vector;
4180 state->queue_entry.count = ARRAY_SIZE(state->vector);
4181 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
4182 xconn->smb2.send_queue_len++;
4184 status = smbd_smb2_flush_send_queue(xconn);
4185 if (tevent_req_nterror(req, status)) {
4186 return tevent_req_post(req, ev);
4189 return req;
4192 static NTSTATUS smbd_smb2_break_recv(struct tevent_req *req)
4194 return tevent_req_simple_recv_ntstatus(req);
4197 struct smbXsrv_pending_break {
4198 struct smbXsrv_pending_break *prev, *next;
4199 struct smbXsrv_client *client;
4200 bool disable_oplock_break_retries;
4201 uint64_t session_id;
4202 uint64_t last_channel_id;
4203 union {
4204 uint8_t generic[1];
4205 uint8_t oplock[0x18];
4206 uint8_t lease[0x2c];
4207 } body;
4208 size_t body_len;
4211 static void smbXsrv_pending_break_done(struct tevent_req *subreq);
4213 static struct smbXsrv_pending_break *smbXsrv_pending_break_create(
4214 struct smbXsrv_client *client,
4215 uint64_t session_id)
4217 struct smbXsrv_pending_break *pb = NULL;
4219 pb = talloc_zero(client, struct smbXsrv_pending_break);
4220 if (pb == NULL) {
4221 return NULL;
4223 pb->client = client;
4224 pb->session_id = session_id;
4225 pb->disable_oplock_break_retries = lp_smb2_disable_oplock_break_retry();
4227 return pb;
4230 static NTSTATUS smbXsrv_pending_break_submit(struct smbXsrv_pending_break *pb);
4232 static NTSTATUS smbXsrv_pending_break_schedule(struct smbXsrv_pending_break *pb)
4234 struct smbXsrv_client *client = pb->client;
4235 NTSTATUS status;
4237 DLIST_ADD_END(client->pending_breaks, pb);
4238 status = smbXsrv_client_pending_breaks_updated(client);
4239 if (!NT_STATUS_IS_OK(status)) {
4240 return status;
4243 status = smbXsrv_pending_break_submit(pb);
4244 if (!NT_STATUS_IS_OK(status)) {
4245 return status;
4248 return NT_STATUS_OK;
4251 static NTSTATUS smbXsrv_pending_break_submit(struct smbXsrv_pending_break *pb)
4253 struct smbXsrv_client *client = pb->client;
4254 struct smbXsrv_session *session = NULL;
4255 struct smbXsrv_connection *xconn = NULL;
4256 struct smbXsrv_connection *oplock_xconn = NULL;
4257 struct tevent_req *subreq = NULL;
4258 NTSTATUS status;
4260 if (pb->session_id != 0) {
4261 status = get_valid_smbXsrv_session(client,
4262 pb->session_id,
4263 &session);
4264 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
4265 return NT_STATUS_ABANDONED;
4267 if (!NT_STATUS_IS_OK(status)) {
4268 return status;
4271 if (pb->last_channel_id != 0) {
4273 * This is what current Windows servers
4274 * do, they don't retry on all available
4275 * channels. They only use the last channel.
4277 * But it doesn't match the specification in
4278 * [MS-SMB2] "3.3.4.6 Object Store Indicates an
4279 * Oplock Break"
4281 * Per default disable_oplock_break_retries is false
4282 * and we behave like the specification.
4284 if (pb->disable_oplock_break_retries) {
4285 return NT_STATUS_ABANDONED;
4290 for (xconn = client->connections; xconn != NULL; xconn = xconn->next) {
4291 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
4292 continue;
4295 if (xconn->channel_id == 0) {
4297 * non-multichannel case
4299 break;
4302 if (session != NULL) {
4303 struct smbXsrv_channel_global0 *c = NULL;
4306 * Having a session means we're handling
4307 * an oplock break and we only need to
4308 * use channels available on the
4309 * session.
4311 status = smbXsrv_session_find_channel(session, xconn, &c);
4312 if (!NT_STATUS_IS_OK(status)) {
4313 continue;
4317 * This is what current Windows servers
4318 * do, they don't retry on all available
4319 * channels. They only use the last channel.
4321 * But it doesn't match the specification
4322 * in [MS-SMB2] "3.3.4.6 Object Store Indicates an
4323 * Oplock Break"
4325 * Per default disable_oplock_break_retries is false
4326 * and we behave like the specification.
4328 if (pb->disable_oplock_break_retries) {
4329 oplock_xconn = xconn;
4330 continue;
4334 if (xconn->channel_id > pb->last_channel_id) {
4336 * multichannel case
4338 break;
4342 if (xconn == NULL) {
4343 xconn = oplock_xconn;
4346 if (xconn == NULL) {
4348 * If there's no remaining connection available
4349 * tell the caller to stop...
4351 return NT_STATUS_ABANDONED;
4354 pb->last_channel_id = xconn->channel_id;
4356 subreq = smbd_smb2_break_send(pb,
4357 client->raw_ev_ctx,
4358 xconn,
4359 pb->session_id,
4360 pb->body.generic,
4361 pb->body_len);
4362 if (subreq == NULL) {
4363 return NT_STATUS_NO_MEMORY;
4365 tevent_req_set_callback(subreq,
4366 smbXsrv_pending_break_done,
4367 pb);
4369 return NT_STATUS_OK;
4372 static void smbXsrv_pending_break_done(struct tevent_req *subreq)
4374 struct smbXsrv_pending_break *pb =
4375 tevent_req_callback_data(subreq,
4376 struct smbXsrv_pending_break);
4377 struct smbXsrv_client *client = pb->client;
4378 NTSTATUS status;
4380 status = smbd_smb2_break_recv(subreq);
4381 TALLOC_FREE(subreq);
4382 if (!NT_STATUS_IS_OK(status)) {
4383 status = smbXsrv_pending_break_submit(pb);
4384 if (NT_STATUS_EQUAL(status, NT_STATUS_ABANDONED)) {
4386 * If there's no remaining connection
4387 * there's no need to send a break again.
4389 goto remove;
4391 if (!NT_STATUS_IS_OK(status)) {
4392 smbd_server_disconnect_client(client, nt_errstr(status));
4393 return;
4395 return;
4398 remove:
4399 DLIST_REMOVE(client->pending_breaks, pb);
4400 TALLOC_FREE(pb);
4402 status = smbXsrv_client_pending_breaks_updated(client);
4403 if (!NT_STATUS_IS_OK(status)) {
4404 smbd_server_disconnect_client(client, nt_errstr(status));
4405 return;
4409 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_client *client,
4410 struct smbXsrv_open *op,
4411 uint8_t oplock_level)
4413 struct smbXsrv_pending_break *pb = NULL;
4414 uint8_t *body = NULL;
4416 pb = smbXsrv_pending_break_create(client,
4417 op->compat->vuid);
4418 if (pb == NULL) {
4419 return NT_STATUS_NO_MEMORY;
4421 pb->body_len = sizeof(pb->body.oplock);
4422 body = pb->body.oplock;
4424 SSVAL(body, 0x00, pb->body_len);
4425 SCVAL(body, 0x02, oplock_level);
4426 SCVAL(body, 0x03, 0); /* reserved */
4427 SIVAL(body, 0x04, 0); /* reserved */
4428 SBVAL(body, 0x08, op->global->open_persistent_id);
4429 SBVAL(body, 0x10, op->global->open_volatile_id);
4431 return smbXsrv_pending_break_schedule(pb);
4434 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_client *client,
4435 uint16_t new_epoch,
4436 uint32_t lease_flags,
4437 struct smb2_lease_key *lease_key,
4438 uint32_t current_lease_state,
4439 uint32_t new_lease_state)
4441 struct smbXsrv_pending_break *pb = NULL;
4442 uint8_t *body = NULL;
4444 pb = smbXsrv_pending_break_create(client,
4445 0); /* no session_id */
4446 if (pb == NULL) {
4447 return NT_STATUS_NO_MEMORY;
4449 pb->body_len = sizeof(pb->body.lease);
4450 body = pb->body.lease;
4452 SSVAL(body, 0x00, pb->body_len);
4453 SSVAL(body, 0x02, new_epoch);
4454 SIVAL(body, 0x04, lease_flags);
4455 SBVAL(body, 0x08, lease_key->data[0]);
4456 SBVAL(body, 0x10, lease_key->data[1]);
4457 SIVAL(body, 0x18, current_lease_state);
4458 SIVAL(body, 0x1c, new_lease_state);
4459 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
4460 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
4461 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
4463 return smbXsrv_pending_break_schedule(pb);
4466 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
4468 NTSTATUS status;
4469 uint32_t flags;
4470 uint64_t file_id_persistent;
4471 uint64_t file_id_volatile;
4472 struct smbXsrv_open *op = NULL;
4473 struct files_struct *fsp = NULL;
4474 const uint8_t *body = NULL;
4477 * This is only called with a pktbuf
4478 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
4479 * bytes
4482 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
4483 /* Transform header. Cannot recvfile. */
4484 return false;
4486 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
4487 /* Not SMB2. Normal error path will cope. */
4488 return false;
4490 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
4491 /* Not SMB2. Normal error path will cope. */
4492 return false;
4494 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
4495 /* Needs to be a WRITE. */
4496 return false;
4498 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
4499 /* Chained. Cannot recvfile. */
4500 return false;
4502 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
4503 if (flags & SMB2_HDR_FLAG_CHAINED) {
4504 /* Chained. Cannot recvfile. */
4505 return false;
4507 if (flags & SMB2_HDR_FLAG_SIGNED) {
4508 /* Signed. Cannot recvfile. */
4509 return false;
4512 body = &state->pktbuf[SMB2_HDR_BODY];
4514 file_id_persistent = BVAL(body, 0x10);
4515 file_id_volatile = BVAL(body, 0x18);
4517 status = smb2srv_open_lookup(state->req->xconn,
4518 file_id_persistent,
4519 file_id_volatile,
4520 0, /* now */
4521 &op);
4522 if (!NT_STATUS_IS_OK(status)) {
4523 return false;
4526 fsp = op->compat;
4527 if (fsp == NULL) {
4528 return false;
4530 if (fsp->conn == NULL) {
4531 return false;
4534 if (IS_IPC(fsp->conn)) {
4535 return false;
4537 if (IS_PRINT(fsp->conn)) {
4538 return false;
4540 if (fsp_is_alternate_stream(fsp)) {
4541 return false;
4544 DEBUG(10,("Doing recvfile write len = %u\n",
4545 (unsigned int)(state->pktfull - state->pktlen)));
4547 return true;
4550 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
4552 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
4553 struct smbd_smb2_request *req = NULL;
4554 size_t max_send_queue_len;
4555 size_t cur_send_queue_len;
4557 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
4559 * we're not supposed to do any io
4561 return NT_STATUS_OK;
4564 if (state->req != NULL) {
4566 * if there is already a tstream_readv_pdu
4567 * pending, we are done.
4569 return NT_STATUS_OK;
4572 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
4573 cur_send_queue_len = xconn->smb2.send_queue_len;
4575 if (cur_send_queue_len > max_send_queue_len) {
4577 * if we have a lot of requests to send,
4578 * we wait until they are on the wire until we
4579 * ask for the next request.
4581 return NT_STATUS_OK;
4584 /* ask for the next request */
4585 req = smbd_smb2_request_allocate(xconn);
4586 if (req == NULL) {
4587 return NT_STATUS_NO_MEMORY;
4589 *state = (struct smbd_smb2_request_read_state) {
4590 .req = req,
4591 .min_recv_size = lp_min_receive_file_size(),
4592 ._vector = {
4593 [0] = (struct iovec) {
4594 .iov_base = (void *)state->hdr.nbt,
4595 .iov_len = NBT_HDR_SIZE,
4598 .vector = state->_vector,
4599 .count = 1,
4602 TEVENT_FD_READABLE(xconn->transport.fde);
4604 return NT_STATUS_OK;
4607 NTSTATUS smbd_smb2_process_negprot(struct smbXsrv_connection *xconn,
4608 uint64_t expected_seq_low,
4609 const uint8_t *inpdu, size_t size)
4611 struct smbd_server_connection *sconn = xconn->client->sconn;
4612 NTSTATUS status;
4613 struct smbd_smb2_request *req = NULL;
4615 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
4616 (unsigned int)size));
4618 status = smbd_initialize_smb2(xconn, expected_seq_low);
4619 if (!NT_STATUS_IS_OK(status)) {
4620 smbd_server_connection_terminate(xconn, nt_errstr(status));
4621 return status;
4625 * If a new connection joins the process, when we're
4626 * already in a "pending break cycle", we need to
4627 * turn on the ack checker on the new connection.
4629 status = smbXsrv_client_pending_breaks_updated(xconn->client);
4630 if (!NT_STATUS_IS_OK(status)) {
4632 * If there's a problem, we disconnect the whole
4633 * client with all connections here!
4635 * Instead of just the new connection.
4637 smbd_server_disconnect_client(xconn->client, nt_errstr(status));
4638 return status;
4641 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
4642 if (!NT_STATUS_IS_OK(status)) {
4643 smbd_server_connection_terminate(xconn, nt_errstr(status));
4644 return status;
4647 status = smbd_smb2_request_validate(req);
4648 if (!NT_STATUS_IS_OK(status)) {
4649 smbd_server_connection_terminate(xconn, nt_errstr(status));
4650 return status;
4653 status = smbd_smb2_request_setup_out(req);
4654 if (!NT_STATUS_IS_OK(status)) {
4655 smbd_server_connection_terminate(xconn, nt_errstr(status));
4656 return status;
4659 #ifdef WITH_PROFILE
4661 * this was already counted at the SMB1 layer =>
4662 * smbd_smb2_request_dispatch() should not count it twice.
4664 if (profile_p->values.request_stats.count > 0) {
4665 profile_p->values.request_stats.count--;
4667 #endif
4668 status = smbd_smb2_request_dispatch(req);
4669 if (!NT_STATUS_IS_OK(status)) {
4670 smbd_server_connection_terminate(xconn, nt_errstr(status));
4671 return status;
4674 status = smbd_smb2_request_next_incoming(xconn);
4675 if (!NT_STATUS_IS_OK(status)) {
4676 smbd_server_connection_terminate(xconn, nt_errstr(status));
4677 return status;
4680 sconn->num_requests++;
4681 return NT_STATUS_OK;
4684 static int socket_error_from_errno(int ret,
4685 int sys_errno,
4686 bool *retry)
4688 *retry = false;
4690 if (ret >= 0) {
4691 return 0;
4694 if (ret != -1) {
4695 return EIO;
4698 if (sys_errno == 0) {
4699 return EIO;
4702 if (sys_errno == EINTR) {
4703 *retry = true;
4704 return sys_errno;
4707 if (sys_errno == EINPROGRESS) {
4708 *retry = true;
4709 return sys_errno;
4712 if (sys_errno == EAGAIN) {
4713 *retry = true;
4714 return sys_errno;
4717 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
4718 if (sys_errno == ENOMEM) {
4719 *retry = true;
4720 return sys_errno;
4723 #ifdef EWOULDBLOCK
4724 #if EWOULDBLOCK != EAGAIN
4725 if (sys_errno == EWOULDBLOCK) {
4726 *retry = true;
4727 return sys_errno;
4729 #endif
4730 #endif
4732 return sys_errno;
4735 static NTSTATUS smbd_smb2_advance_send_queue(struct smbXsrv_connection *xconn,
4736 struct smbd_smb2_send_queue **_e,
4737 size_t n)
4739 struct smbd_smb2_send_queue *e = *_e;
4740 bool ok;
4742 xconn->ack.unacked_bytes += n;
4744 ok = iov_advance(&e->vector, &e->count, n);
4745 if (!ok) {
4746 return NT_STATUS_INTERNAL_ERROR;
4749 if (e->count > 0) {
4750 return NT_STATUS_RETRY;
4753 xconn->smb2.send_queue_len--;
4754 DLIST_REMOVE(xconn->smb2.send_queue, e);
4756 if (e->ack.req == NULL) {
4757 *_e = NULL;
4758 talloc_free(e->mem_ctx);
4759 return NT_STATUS_OK;
4762 e->ack.required_acked_bytes = xconn->ack.unacked_bytes;
4763 DLIST_ADD_END(xconn->ack.queue, e);
4765 return NT_STATUS_OK;
4768 static NTSTATUS smbd_smb2_flush_with_sendmsg(struct smbXsrv_connection *xconn)
4770 int ret;
4771 int err;
4772 bool retry;
4773 NTSTATUS status;
4775 if (xconn->smb2.send_queue == NULL) {
4776 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
4777 return NT_STATUS_OK;
4780 while (xconn->smb2.send_queue != NULL) {
4781 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
4782 unsigned sendmsg_flags = 0;
4784 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
4786 * we're not supposed to do any io
4787 * just flush all pending stuff.
4789 xconn->smb2.send_queue_len--;
4790 DLIST_REMOVE(xconn->smb2.send_queue, e);
4792 talloc_free(e->mem_ctx);
4793 continue;
4796 if (e->sendfile_header != NULL) {
4797 size_t size = 0;
4798 size_t i = 0;
4799 uint8_t *buf;
4801 status = NT_STATUS_INTERNAL_ERROR;
4803 for (i=0; i < e->count; i++) {
4804 size += e->vector[i].iov_len;
4807 if (size <= e->sendfile_header->length) {
4808 buf = e->sendfile_header->data;
4809 } else {
4810 buf = talloc_array(e->mem_ctx, uint8_t, size);
4811 if (buf == NULL) {
4812 return NT_STATUS_NO_MEMORY;
4816 size = 0;
4817 for (i=0; i < e->count; i++) {
4818 memcpy(buf+size,
4819 e->vector[i].iov_base,
4820 e->vector[i].iov_len);
4821 size += e->vector[i].iov_len;
4824 e->sendfile_header->data = buf;
4825 e->sendfile_header->length = size;
4826 e->sendfile_status = &status;
4827 e->count = 0;
4829 xconn->smb2.send_queue_len--;
4830 DLIST_REMOVE(xconn->smb2.send_queue, e);
4832 size += e->sendfile_body_size;
4835 * This triggers the sendfile path via
4836 * the destructor.
4838 talloc_free(e->mem_ctx);
4840 if (!NT_STATUS_IS_OK(status)) {
4841 smbXsrv_connection_disconnect_transport(xconn,
4842 status);
4843 return status;
4845 xconn->ack.unacked_bytes += size;
4846 continue;
4849 e->msg = (struct msghdr) {
4850 .msg_iov = e->vector,
4851 .msg_iovlen = e->count,
4854 #ifdef MSG_NOSIGNAL
4855 sendmsg_flags |= MSG_NOSIGNAL;
4856 #endif
4857 #ifdef MSG_DONTWAIT
4858 sendmsg_flags |= MSG_DONTWAIT;
4859 #endif
4861 ret = sendmsg(xconn->transport.sock, &e->msg, sendmsg_flags);
4862 if (ret == 0) {
4863 /* propagate end of file */
4864 return NT_STATUS_INTERNAL_ERROR;
4866 err = socket_error_from_errno(ret, errno, &retry);
4867 if (retry) {
4868 /* retry later */
4869 TEVENT_FD_WRITEABLE(xconn->transport.fde);
4870 return NT_STATUS_OK;
4872 if (err != 0) {
4873 status = map_nt_error_from_unix_common(err);
4874 smbXsrv_connection_disconnect_transport(xconn,
4875 status);
4876 return status;
4879 status = smbd_smb2_advance_send_queue(xconn, &e, ret);
4880 if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4881 /* retry later */
4882 TEVENT_FD_WRITEABLE(xconn->transport.fde);
4883 return NT_STATUS_OK;
4885 if (!NT_STATUS_IS_OK(status)) {
4886 smbXsrv_connection_disconnect_transport(xconn,
4887 status);
4888 return status;
4892 return NT_STATUS_MORE_PROCESSING_REQUIRED;
4895 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
4897 NTSTATUS status;
4899 status = smbd_smb2_flush_with_sendmsg(xconn);
4900 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
4901 return status;
4905 * Restart reads if we were blocked on
4906 * draining the send queue.
4909 status = smbd_smb2_request_next_incoming(xconn);
4910 if (!NT_STATUS_IS_OK(status)) {
4911 return status;
4914 return NT_STATUS_OK;
4917 static NTSTATUS smbd_smb2_advance_incoming(struct smbXsrv_connection *xconn, size_t n)
4919 struct smbd_server_connection *sconn = xconn->client->sconn;
4920 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
4921 struct smbd_smb2_request *req = NULL;
4922 size_t min_recvfile_size = UINT32_MAX;
4923 NTSTATUS status;
4924 NTTIME now;
4925 bool ok;
4927 ok = iov_advance(&state->vector, &state->count, n);
4928 if (!ok) {
4929 return NT_STATUS_INTERNAL_ERROR;
4932 if (state->count > 0) {
4933 return NT_STATUS_PENDING;
4936 if (state->pktlen > 0) {
4937 if (!state->doing_receivefile) {
4939 * we have all the data.
4941 goto got_full;
4944 if (!is_smb2_recvfile_write(state)) {
4945 size_t ofs = state->pktlen;
4948 * Not a possible receivefile write.
4949 * Read the rest of the data.
4951 state->doing_receivefile = false;
4953 state->pktbuf = talloc_realloc(state->req,
4954 state->pktbuf,
4955 uint8_t,
4956 state->pktfull);
4957 if (state->pktbuf == NULL) {
4958 return NT_STATUS_NO_MEMORY;
4961 state->_vector[0] = (struct iovec) {
4962 .iov_base = (void *)(state->pktbuf + ofs),
4963 .iov_len = (state->pktfull - ofs),
4965 state->vector = state->_vector;
4966 state->count = 1;
4968 state->pktlen = state->pktfull;
4969 return NT_STATUS_RETRY;
4973 * This is a receivefile write so we've
4974 * done a short read.
4976 goto got_full;
4980 * Now we analyze the NBT header
4982 if (state->hdr.nbt[0] != 0x00) {
4983 state->min_recv_size = 0;
4985 state->pktfull = smb2_len(state->hdr.nbt);
4986 if (state->pktfull == 0) {
4987 goto got_full;
4990 if (state->min_recv_size != 0) {
4991 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
4992 min_recvfile_size += state->min_recv_size;
4995 if (state->pktfull > min_recvfile_size) {
4997 * Might be a receivefile write. Read the SMB2 HEADER +
4998 * SMB2_WRITE header first. Set 'doing_receivefile'
4999 * as we're *attempting* receivefile write. If this
5000 * turns out not to be a SMB2_WRITE request or otherwise
5001 * not suitable then we'll just read the rest of the data
5002 * the next time this function is called.
5004 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
5005 state->doing_receivefile = true;
5006 } else {
5007 state->pktlen = state->pktfull;
5010 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
5011 if (state->pktbuf == NULL) {
5012 return NT_STATUS_NO_MEMORY;
5015 state->_vector[0] = (struct iovec) {
5016 .iov_base = (void *)state->pktbuf,
5017 .iov_len = state->pktlen,
5019 state->vector = state->_vector;
5020 state->count = 1;
5022 return NT_STATUS_RETRY;
5024 got_full:
5026 if (state->hdr.nbt[0] != 0x00) {
5027 DEBUG(1,("ignore NBT[0x%02X] msg\n",
5028 state->hdr.nbt[0]));
5030 req = state->req;
5031 *state = (struct smbd_smb2_request_read_state) {
5032 .req = req,
5033 .min_recv_size = lp_min_receive_file_size(),
5034 ._vector = {
5035 [0] = (struct iovec) {
5036 .iov_base = (void *)state->hdr.nbt,
5037 .iov_len = NBT_HDR_SIZE,
5040 .vector = state->_vector,
5041 .count = 1,
5043 return NT_STATUS_RETRY;
5046 req = state->req;
5048 req->request_time = timeval_current();
5049 now = timeval_to_nttime(&req->request_time);
5051 status = smbd_smb2_inbuf_parse_compound(xconn,
5052 now,
5053 state->pktbuf,
5054 state->pktlen,
5055 req,
5056 &req->in.vector,
5057 &req->in.vector_count);
5058 if (!NT_STATUS_IS_OK(status)) {
5059 return status;
5062 if (state->doing_receivefile) {
5063 req->smb1req = talloc_zero(req, struct smb_request);
5064 if (req->smb1req == NULL) {
5065 return NT_STATUS_NO_MEMORY;
5067 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
5070 *state = (struct smbd_smb2_request_read_state) {
5071 .req = NULL,
5074 req->current_idx = 1;
5076 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
5077 req->current_idx, req->in.vector_count));
5079 status = smbd_smb2_request_validate(req);
5080 if (!NT_STATUS_IS_OK(status)) {
5081 return status;
5084 status = smbd_smb2_request_setup_out(req);
5085 if (!NT_STATUS_IS_OK(status)) {
5086 return status;
5089 status = smbd_smb2_request_dispatch(req);
5090 if (!NT_STATUS_IS_OK(status)) {
5091 return status;
5094 sconn->num_requests++;
5096 /* The timeout_processing function isn't run nearly
5097 often enough to implement 'max log size' without
5098 overrunning the size of the file by many megabytes.
5099 This is especially true if we are running at debug
5100 level 10. Checking every 50 SMB2s is a nice
5101 tradeoff of performance vs log file size overrun. */
5103 if ((sconn->num_requests % 50) == 0 &&
5104 need_to_check_log_size()) {
5105 change_to_root_user();
5106 check_log_size();
5109 status = smbd_smb2_request_next_incoming(xconn);
5110 if (!NT_STATUS_IS_OK(status)) {
5111 return status;
5114 return NT_STATUS_OK;
5117 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
5118 uint16_t fde_flags)
5120 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
5121 unsigned recvmsg_flags = 0;
5122 int ret;
5123 int err;
5124 bool retry;
5125 NTSTATUS status;
5127 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
5129 * we're not supposed to do any io
5131 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
5132 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
5133 return NT_STATUS_OK;
5136 if (fde_flags & TEVENT_FD_WRITE) {
5137 status = smbd_smb2_flush_send_queue(xconn);
5138 if (!NT_STATUS_IS_OK(status)) {
5139 return status;
5143 if (!(fde_flags & TEVENT_FD_READ)) {
5144 return NT_STATUS_OK;
5147 if (state->req == NULL) {
5148 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
5149 return NT_STATUS_OK;
5152 again:
5154 state->msg = (struct msghdr) {
5155 .msg_iov = state->vector,
5156 .msg_iovlen = state->count,
5159 #ifdef MSG_NOSIGNAL
5160 recvmsg_flags |= MSG_NOSIGNAL;
5161 #endif
5162 #ifdef MSG_DONTWAIT
5163 recvmsg_flags |= MSG_DONTWAIT;
5164 #endif
5166 ret = recvmsg(xconn->transport.sock, &state->msg, recvmsg_flags);
5167 if (ret == 0) {
5168 /* propagate end of file */
5169 status = NT_STATUS_END_OF_FILE;
5170 smbXsrv_connection_disconnect_transport(xconn,
5171 status);
5172 return status;
5174 err = socket_error_from_errno(ret, errno, &retry);
5175 if (retry) {
5176 /* retry later */
5177 TEVENT_FD_READABLE(xconn->transport.fde);
5178 return NT_STATUS_OK;
5180 if (err != 0) {
5181 status = map_nt_error_from_unix_common(err);
5182 smbXsrv_connection_disconnect_transport(xconn,
5183 status);
5184 return status;
5187 status = smbd_smb2_advance_incoming(xconn, ret);
5188 if (NT_STATUS_EQUAL(status, NT_STATUS_PENDING)) {
5189 /* we have more to read */
5190 TEVENT_FD_READABLE(xconn->transport.fde);
5191 return NT_STATUS_OK;
5193 if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5195 * smbd_smb2_advance_incoming setup a new vector
5196 * that we should try to read immediately.
5198 goto again;
5200 if (!NT_STATUS_IS_OK(status)) {
5201 return status;
5204 return NT_STATUS_OK;
5207 static void smbd_smb2_connection_handler(struct tevent_context *ev,
5208 struct tevent_fd *fde,
5209 uint16_t flags,
5210 void *private_data)
5212 struct smbXsrv_connection *xconn =
5213 talloc_get_type_abort(private_data,
5214 struct smbXsrv_connection);
5215 NTSTATUS status;
5217 status = smbd_smb2_io_handler(xconn, flags);
5218 if (!NT_STATUS_IS_OK(status)) {
5219 smbd_server_connection_terminate(xconn, nt_errstr(status));
5220 return;