auth/credentials: a temporary MEMORY ccache needs krb5_cc_destroy()
[Samba.git] / source3 / smbd / smb2_server.c
blob642b530134b9e2334167564f52a55f8622dcd185
1 /*
2 Unix SMB/CIFS implementation.
3 Core SMB2 server
5 Copyright (C) Stefan Metzmacher 2009
6 Copyright (C) Jeremy Allison 2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "system/network.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "source3/smbd/smbXsrv_session.h"
27 #include "smbd/smbXsrv_open.h"
28 #include "lib/param/param.h"
29 #include "../libcli/smb/smb_common.h"
30 #include "../lib/tsocket/tsocket.h"
31 #include "../lib/util/tevent_ntstatus.h"
32 #include "smbprofile.h"
33 #include "../lib/util/bitmap.h"
34 #include "../librpc/gen_ndr/krb5pac.h"
35 #include "lib/util/iov_buf.h"
36 #include "auth.h"
37 #include "libcli/smb/smbXcli_base.h"
38 #include "source3/lib/substitute.h"
40 #if defined(LINUX)
41 /* SIOCOUTQ TIOCOUTQ are the same */
42 #define __IOCTL_SEND_QUEUE_SIZE_OPCODE TIOCOUTQ
43 #define __HAVE_TCP_INFO_RTO 1
44 #define __ALLOW_MULTI_CHANNEL_SUPPORT 1
45 #elif defined(FREEBSD)
46 #define __IOCTL_SEND_QUEUE_SIZE_OPCODE FIONWRITE
47 #define __HAVE_TCP_INFO_RTO 1
48 #define __ALLOW_MULTI_CHANNEL_SUPPORT 1
49 #endif
51 #include "lib/crypto/gnutls_helpers.h"
52 #include <gnutls/gnutls.h>
53 #include <gnutls/crypto.h>
55 #undef DBGC_CLASS
56 #define DBGC_CLASS DBGC_SMB2
58 static void smbd_smb2_connection_handler(struct tevent_context *ev,
59 struct tevent_fd *fde,
60 uint16_t flags,
61 void *private_data);
62 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn);
64 static const struct smbd_smb2_dispatch_table {
65 uint16_t opcode;
66 uint16_t fileid_ofs;
67 bool need_session : 1;
68 bool need_tcon : 1;
69 bool as_root : 1;
70 bool modify : 1;
71 } smbd_smb2_table[] = {
73 .opcode = SMB2_OP_NEGPROT,
74 .as_root = true,
75 },{
76 .opcode = SMB2_OP_SESSSETUP,
77 .as_root = true,
78 },{
79 .opcode = SMB2_OP_LOGOFF,
80 .need_session = true,
81 .as_root = true,
82 },{
83 .opcode = SMB2_OP_TCON,
84 .need_session = true,
86 * This call needs to be run as root.
88 * smbd_smb2_request_process_tcon()
89 * calls make_connection_snum(), which will call
90 * change_to_user(), when needed.
92 .as_root = true,
93 },{
94 .opcode = SMB2_OP_TDIS,
95 .need_session = true,
96 .need_tcon = true,
97 .as_root = true,
98 },{
99 .opcode = SMB2_OP_CREATE,
100 .need_session = true,
101 .need_tcon = true,
103 .opcode = SMB2_OP_CLOSE,
104 .need_session = true,
105 .need_tcon = true,
106 .fileid_ofs = 0x08,
108 .opcode = SMB2_OP_FLUSH,
109 .need_session = true,
110 .need_tcon = true,
111 .fileid_ofs = 0x08,
113 .opcode = SMB2_OP_READ,
114 .need_session = true,
115 .need_tcon = true,
116 .fileid_ofs = 0x10,
118 .opcode = SMB2_OP_WRITE,
119 .need_session = true,
120 .need_tcon = true,
121 .fileid_ofs = 0x10,
122 .modify = true,
124 .opcode = SMB2_OP_LOCK,
125 .need_session = true,
126 .need_tcon = true,
127 .fileid_ofs = 0x08,
129 .opcode = SMB2_OP_IOCTL,
130 .need_session = true,
131 .need_tcon = true,
132 .fileid_ofs = 0x08,
133 .modify = true,
135 .opcode = SMB2_OP_CANCEL,
136 .as_root = true,
138 .opcode = SMB2_OP_KEEPALIVE,
140 .opcode = SMB2_OP_QUERY_DIRECTORY,
141 .need_session = true,
142 .need_tcon = true,
143 .fileid_ofs = 0x08,
145 .opcode = SMB2_OP_NOTIFY,
146 .need_session = true,
147 .need_tcon = true,
148 .fileid_ofs = 0x08,
150 .opcode = SMB2_OP_GETINFO,
151 .need_session = true,
152 .need_tcon = true,
153 .fileid_ofs = 0x18,
155 .opcode = SMB2_OP_SETINFO,
156 .need_session = true,
157 .need_tcon = true,
158 .fileid_ofs = 0x10,
159 .modify = true,
161 .opcode = SMB2_OP_BREAK,
162 .need_session = true,
163 .need_tcon = true,
165 * we do not set
166 * .fileid_ofs here
167 * as LEASE breaks does not
168 * have a file id
173 const char *smb2_opcode_name(uint16_t opcode)
175 const char *result = "Bad SMB2 opcode";
177 switch (opcode) {
178 case SMB2_OP_NEGPROT:
179 result = "SMB2_OP_NEGPROT";
180 break;
181 case SMB2_OP_SESSSETUP:
182 result = "SMB2_OP_SESSSETUP";
183 break;
184 case SMB2_OP_LOGOFF:
185 result = "SMB2_OP_LOGOFF";
186 break;
187 case SMB2_OP_TCON:
188 result = "SMB2_OP_TCON";
189 break;
190 case SMB2_OP_TDIS:
191 result = "SMB2_OP_TDIS";
192 break;
193 case SMB2_OP_CREATE:
194 result = "SMB2_OP_CREATE";
195 break;
196 case SMB2_OP_CLOSE:
197 result = "SMB2_OP_CLOSE";
198 break;
199 case SMB2_OP_FLUSH:
200 result = "SMB2_OP_FLUSH";
201 break;
202 case SMB2_OP_READ:
203 result = "SMB2_OP_READ";
204 break;
205 case SMB2_OP_WRITE:
206 result = "SMB2_OP_WRITE";
207 break;
208 case SMB2_OP_LOCK:
209 result = "SMB2_OP_LOCK";
210 break;
211 case SMB2_OP_IOCTL:
212 result = "SMB2_OP_IOCTL";
213 break;
214 case SMB2_OP_CANCEL:
215 result = "SMB2_OP_CANCEL";
216 break;
217 case SMB2_OP_KEEPALIVE:
218 result = "SMB2_OP_KEEPALIVE";
219 break;
220 case SMB2_OP_QUERY_DIRECTORY:
221 result = "SMB2_OP_QUERY_DIRECTORY";
222 break;
223 case SMB2_OP_NOTIFY:
224 result = "SMB2_OP_NOTIFY";
225 break;
226 case SMB2_OP_GETINFO:
227 result = "SMB2_OP_GETINFO";
228 break;
229 case SMB2_OP_SETINFO:
230 result = "SMB2_OP_SETINFO";
231 break;
232 case SMB2_OP_BREAK:
233 result = "SMB2_OP_BREAK";
234 break;
235 default:
236 break;
238 return result;
241 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
243 const struct smbd_smb2_dispatch_table *ret = NULL;
245 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
246 return NULL;
249 ret = &smbd_smb2_table[opcode];
251 SMB_ASSERT(ret->opcode == opcode);
253 return ret;
256 static void print_req_vectors(const struct smbd_smb2_request *req)
258 int i;
260 for (i = 0; i < req->in.vector_count; i++) {
261 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
262 (unsigned int)i,
263 (unsigned int)req->in.vector[i].iov_len);
265 for (i = 0; i < req->out.vector_count; i++) {
266 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
267 (unsigned int)i,
268 (unsigned int)req->out.vector[i].iov_len);
272 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
274 if (size < (4 + SMB2_HDR_BODY)) {
275 return false;
278 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
279 return false;
282 return true;
285 bool smbd_smb2_is_compound(const struct smbd_smb2_request *req)
287 return req->in.vector_count >= (2*SMBD_SMB2_NUM_IOV_PER_REQ);
290 bool smbd_smb2_is_last_in_compound(const struct smbd_smb2_request *req)
292 return (req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ ==
293 req->in.vector_count);
296 static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn,
297 uint64_t expected_seq_low)
299 int rc;
301 xconn->smb2.credits.seq_low = expected_seq_low;
302 xconn->smb2.credits.seq_range = 1;
303 xconn->smb2.credits.granted = 1;
304 xconn->smb2.credits.max = lp_smb2_max_credits();
305 xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
306 xconn->smb2.credits.max);
307 if (xconn->smb2.credits.bitmap == NULL) {
308 return NT_STATUS_NO_MEMORY;
311 tevent_fd_set_close_fn(xconn->transport.fde, NULL);
312 TALLOC_FREE(xconn->transport.fde);
314 xconn->transport.fde = tevent_add_fd(
315 xconn->client->raw_ev_ctx,
316 xconn,
317 xconn->transport.sock,
318 TEVENT_FD_ERROR | TEVENT_FD_READ,
319 smbd_smb2_connection_handler,
320 xconn);
321 if (xconn->transport.fde == NULL) {
322 close(xconn->transport.sock);
323 xconn->transport.sock = -1;
324 return NT_STATUS_NO_MEMORY;
326 tevent_fd_set_auto_close(xconn->transport.fde);
329 * Ensure child is set to non-blocking mode,
330 * unless the system supports MSG_DONTWAIT,
331 * if MSG_DONTWAIT is available we should force
332 * blocking mode.
334 #ifdef MSG_DONTWAIT
335 rc = set_blocking(xconn->transport.sock, true);
336 if (rc < 0) {
337 return NT_STATUS_INTERNAL_ERROR;
339 #else
340 rc = set_blocking(xconn->transport.sock, false);
341 if (rc < 0) {
342 return NT_STATUS_INTERNAL_ERROR;
344 #endif
346 return NT_STATUS_OK;
349 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
350 #define _smb2_setlen(_buf,len) do { \
351 uint8_t *buf = (uint8_t *)_buf; \
352 buf[0] = 0; \
353 buf[1] = ((len)&0xFF0000)>>16; \
354 buf[2] = ((len)&0xFF00)>>8; \
355 buf[3] = (len)&0xFF; \
356 } while (0)
358 static bool smb2_setup_nbt_length(struct iovec *vector, int count)
360 ssize_t len;
362 if (count == 0) {
363 return false;
366 len = iov_buflen(vector+1, count-1);
368 if ((len == -1) || (len > 0xFFFFFF)) {
369 return false;
372 _smb2_setlen(vector[0].iov_base, len);
373 return true;
376 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
378 TALLOC_FREE(req->first_enc_key);
379 TALLOC_FREE(req->last_sign_key);
380 return 0;
383 void smb2_request_set_async_internal(struct smbd_smb2_request *req,
384 bool async_internal)
386 req->async_internal = async_internal;
389 static struct smbd_smb2_request *smbd_smb2_request_allocate(struct smbXsrv_connection *xconn)
391 TALLOC_CTX *mem_pool;
392 struct smbd_smb2_request *req;
394 #if 0
395 /* Enable this to find subtle valgrind errors. */
396 mem_pool = talloc_init("smbd_smb2_request_allocate");
397 #else
398 mem_pool = talloc_tos();
399 #endif
400 if (mem_pool == NULL) {
401 return NULL;
404 req = talloc(mem_pool, struct smbd_smb2_request);
405 if (req == NULL) {
406 talloc_free(mem_pool);
407 return NULL;
409 talloc_reparent(mem_pool, xconn, req);
410 #if 0
411 TALLOC_FREE(mem_pool);
412 #endif
413 *req = (struct smbd_smb2_request) {
414 .sconn = xconn->client->sconn,
415 .xconn = xconn,
416 .last_session_id = UINT64_MAX,
417 .last_tid = UINT32_MAX,
420 talloc_set_destructor(req, smbd_smb2_request_destructor);
422 return req;
425 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
426 NTTIME now,
427 uint8_t *buf,
428 size_t buflen,
429 struct smbd_smb2_request *req,
430 struct iovec **piov,
431 int *pnum_iov)
433 TALLOC_CTX *mem_ctx = req;
434 struct iovec *iov;
435 int num_iov = 1;
436 size_t taken = 0;
437 uint8_t *first_hdr = buf;
438 size_t verified_buflen = 0;
439 uint8_t *tf = NULL;
440 size_t tf_len = 0;
443 * Note: index '0' is reserved for the transport protocol
445 iov = req->in._vector;
447 while (taken < buflen) {
448 size_t len = buflen - taken;
449 uint8_t *hdr = first_hdr + taken;
450 struct iovec *cur;
451 size_t full_size;
452 size_t next_command_ofs;
453 uint16_t body_size;
454 uint8_t *body = NULL;
455 uint32_t dyn_size;
456 uint8_t *dyn = NULL;
457 struct iovec *iov_alloc = NULL;
459 if (iov != req->in._vector) {
460 iov_alloc = iov;
463 if (verified_buflen > taken) {
464 len = verified_buflen - taken;
465 } else {
466 tf = NULL;
467 tf_len = 0;
470 if (len < 4) {
471 DEBUG(10, ("%d bytes left, expected at least %d\n",
472 (int)len, 4));
473 goto inval;
475 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
476 struct smbXsrv_session *s = NULL;
477 uint64_t uid;
478 struct iovec tf_iov[2];
479 NTSTATUS status;
480 size_t enc_len;
482 if (xconn->protocol < PROTOCOL_SMB3_00) {
483 DEBUG(10, ("Got SMB2_TRANSFORM header, "
484 "but dialect[0x%04X] is used\n",
485 xconn->smb2.server.dialect));
486 goto inval;
489 if (xconn->smb2.server.cipher == 0) {
490 DEBUG(10, ("Got SMB2_TRANSFORM header, "
491 "but not negotiated "
492 "client[0x%08X] server[0x%08X]\n",
493 xconn->smb2.client.capabilities,
494 xconn->smb2.server.capabilities));
495 goto inval;
498 if (len < SMB2_TF_HDR_SIZE) {
499 DEBUG(1, ("%d bytes left, expected at least %d\n",
500 (int)len, SMB2_TF_HDR_SIZE));
501 goto inval;
503 tf = hdr;
504 tf_len = SMB2_TF_HDR_SIZE;
505 taken += tf_len;
507 hdr = first_hdr + taken;
508 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
509 uid = BVAL(tf, SMB2_TF_SESSION_ID);
511 if (len < SMB2_TF_HDR_SIZE + enc_len) {
512 DEBUG(1, ("%d bytes left, expected at least %d\n",
513 (int)len,
514 (int)(SMB2_TF_HDR_SIZE + enc_len)));
515 goto inval;
518 status = smb2srv_session_lookup_conn(xconn, uid, now,
519 &s);
520 if (!NT_STATUS_IS_OK(status)) {
521 status = smb2srv_session_lookup_global(xconn->client,
522 uid, req, &s);
524 if (!NT_STATUS_IS_OK(status)) {
525 DBG_WARNING("invalid session[%" PRIu64 "] in "
526 "SMB2_TRANSFORM header\n",
527 uid);
528 TALLOC_FREE(iov_alloc);
529 return NT_STATUS_USER_SESSION_DELETED;
532 tf_iov[0].iov_base = (void *)tf;
533 tf_iov[0].iov_len = tf_len;
534 tf_iov[1].iov_base = (void *)hdr;
535 tf_iov[1].iov_len = enc_len;
537 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
538 tf_iov, 2);
539 if (!NT_STATUS_IS_OK(status)) {
540 TALLOC_FREE(iov_alloc);
541 return status;
544 verified_buflen = taken + enc_len;
545 len = enc_len;
549 * We need the header plus the body length field
552 if (len < SMB2_HDR_BODY + 2) {
554 if ((len == 5) &&
555 (IVAL(hdr, 0) == SMB_SUICIDE_PACKET) &&
556 lp_parm_bool(-1, "smbd", "suicide mode", false)) {
557 uint8_t exitcode = CVAL(hdr, 4);
558 DBG_WARNING("SUICIDE: Exiting immediately "
559 "with code %"PRIu8"\n",
560 exitcode);
561 exit(exitcode);
564 DEBUG(10, ("%d bytes left, expected at least %d\n",
565 (int)len, SMB2_HDR_BODY));
566 goto inval;
568 if (IVAL(hdr, 0) != SMB2_MAGIC) {
569 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
570 IVAL(hdr, 0)));
571 goto inval;
573 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
574 DEBUG(10, ("Got HDR len %d, expected %d\n",
575 SVAL(hdr, 4), SMB2_HDR_BODY));
576 goto inval;
579 full_size = len;
580 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
581 body_size = SVAL(hdr, SMB2_HDR_BODY);
583 if (next_command_ofs != 0) {
584 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
585 goto inval;
587 if (next_command_ofs > full_size) {
588 goto inval;
590 full_size = next_command_ofs;
592 if (body_size < 2) {
593 goto inval;
595 body_size &= 0xfffe;
597 if (body_size > (full_size - SMB2_HDR_BODY)) {
599 * let the caller handle the error
601 body_size = full_size - SMB2_HDR_BODY;
603 body = hdr + SMB2_HDR_BODY;
604 dyn = body + body_size;
605 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
607 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
608 struct iovec *iov_tmp = NULL;
610 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
611 struct iovec,
612 num_iov +
613 SMBD_SMB2_NUM_IOV_PER_REQ);
614 if (iov_tmp == NULL) {
615 TALLOC_FREE(iov_alloc);
616 return NT_STATUS_NO_MEMORY;
619 if (iov_alloc == NULL) {
620 memcpy(iov_tmp,
621 req->in._vector,
622 sizeof(req->in._vector));
625 iov = iov_tmp;
627 cur = &iov[num_iov];
628 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
630 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
631 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
632 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
633 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
634 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
635 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
636 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
637 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
639 taken += full_size;
642 *piov = iov;
643 *pnum_iov = num_iov;
644 return NT_STATUS_OK;
646 inval:
647 if (iov != req->in._vector) {
648 TALLOC_FREE(iov);
650 return NT_STATUS_INVALID_PARAMETER;
653 static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
654 const uint8_t *_inpdu, size_t size,
655 struct smbd_smb2_request **_req)
657 struct smbd_smb2_request *req;
658 uint32_t protocol_version;
659 uint8_t *inpdu = NULL;
660 const uint8_t *inhdr = NULL;
661 uint16_t cmd;
662 uint32_t next_command_ofs;
663 NTSTATUS status;
664 NTTIME now;
666 if (size < (SMB2_HDR_BODY + 2)) {
667 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
668 return NT_STATUS_INVALID_PARAMETER;
671 inhdr = _inpdu;
673 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
674 if (protocol_version != SMB2_MAGIC) {
675 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
676 protocol_version));
677 return NT_STATUS_INVALID_PARAMETER;
680 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
681 if (cmd != SMB2_OP_NEGPROT) {
682 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
683 cmd));
684 return NT_STATUS_INVALID_PARAMETER;
687 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
688 if (next_command_ofs != 0) {
689 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
690 next_command_ofs));
691 return NT_STATUS_INVALID_PARAMETER;
694 req = smbd_smb2_request_allocate(xconn);
695 if (req == NULL) {
696 return NT_STATUS_NO_MEMORY;
699 inpdu = talloc_memdup(req, _inpdu, size);
700 if (inpdu == NULL) {
701 return NT_STATUS_NO_MEMORY;
704 req->request_time = timeval_current();
705 now = timeval_to_nttime(&req->request_time);
707 status = smbd_smb2_inbuf_parse_compound(xconn,
708 now,
709 inpdu,
710 size,
711 req, &req->in.vector,
712 &req->in.vector_count);
713 if (!NT_STATUS_IS_OK(status)) {
714 TALLOC_FREE(req);
715 return status;
718 req->current_idx = 1;
720 *_req = req;
721 return NT_STATUS_OK;
724 static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
725 uint64_t message_id, uint64_t seq_id)
727 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
728 unsigned int offset;
729 uint64_t seq_tmp;
731 seq_tmp = xconn->smb2.credits.seq_low;
732 if (seq_id < seq_tmp) {
733 DBGC_ERR(DBGC_SMB2_CREDITS,
734 "smb2_validate_sequence_number: bad message_id "
735 "%llu (sequence id %llu) "
736 "(granted = %u, low = %llu, range = %u)\n",
737 (unsigned long long)message_id,
738 (unsigned long long)seq_id,
739 (unsigned int)xconn->smb2.credits.granted,
740 (unsigned long long)xconn->smb2.credits.seq_low,
741 (unsigned int)xconn->smb2.credits.seq_range);
742 return false;
745 seq_tmp += xconn->smb2.credits.seq_range;
746 if (seq_id >= seq_tmp) {
747 DBGC_ERR(DBGC_SMB2_CREDITS,
748 "smb2_validate_sequence_number: bad message_id "
749 "%llu (sequence id %llu) "
750 "(granted = %u, low = %llu, range = %u)\n",
751 (unsigned long long)message_id,
752 (unsigned long long)seq_id,
753 (unsigned int)xconn->smb2.credits.granted,
754 (unsigned long long)xconn->smb2.credits.seq_low,
755 (unsigned int)xconn->smb2.credits.seq_range);
756 return false;
759 offset = seq_id % xconn->smb2.credits.max;
761 if (bitmap_query(credits_bm, offset)) {
762 DBGC_ERR(DBGC_SMB2_CREDITS,
763 "smb2_validate_sequence_number: duplicate message_id "
764 "%llu (sequence id %llu) "
765 "(granted = %u, low = %llu, range = %u) "
766 "(bm offset %u)\n",
767 (unsigned long long)message_id,
768 (unsigned long long)seq_id,
769 (unsigned int)xconn->smb2.credits.granted,
770 (unsigned long long)xconn->smb2.credits.seq_low,
771 (unsigned int)xconn->smb2.credits.seq_range,
772 offset);
773 return false;
776 /* Mark the message_ids as seen in the bitmap. */
777 bitmap_set(credits_bm, offset);
779 if (seq_id != xconn->smb2.credits.seq_low) {
780 return true;
784 * Move the window forward by all the message_id's
785 * already seen.
787 while (bitmap_query(credits_bm, offset)) {
788 DBGC_DEBUG(DBGC_SMB2_CREDITS,
789 "smb2_validate_sequence_number: clearing "
790 "id %llu (position %u) from bitmap\n",
791 (unsigned long long)(xconn->smb2.credits.seq_low),
792 offset);
793 bitmap_clear(credits_bm, offset);
795 xconn->smb2.credits.seq_low += 1;
796 xconn->smb2.credits.seq_range -= 1;
797 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
800 return true;
803 static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
804 const uint8_t *inhdr)
806 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
807 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
808 uint16_t credit_charge = 1;
809 uint64_t i;
811 if (opcode == SMB2_OP_CANCEL) {
812 /* SMB2_CANCEL requests by definition resend messageids. */
813 return true;
816 if (xconn->smb2.credits.multicredit) {
817 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
818 credit_charge = MAX(credit_charge, 1);
821 DEBUGC(11,
822 DBGC_SMB2_CREDITS,
823 ("smb2_validate_message_id: mid %llu (charge %llu), "
824 "credits_granted %llu, "
825 "seqnum low/range: %llu/%llu\n",
826 (unsigned long long) message_id,
827 (unsigned long long) credit_charge,
828 (unsigned long long) xconn->smb2.credits.granted,
829 (unsigned long long) xconn->smb2.credits.seq_low,
830 (unsigned long long) xconn->smb2.credits.seq_range));
832 if (xconn->smb2.credits.granted < credit_charge) {
833 DBGC_ERR(DBGC_SMB2_CREDITS,
834 "smb2_validate_message_id: client used more "
835 "credits than granted, mid %llu, charge %llu, "
836 "credits_granted %llu, "
837 "seqnum low/range: %llu/%llu\n",
838 (unsigned long long) message_id,
839 (unsigned long long) credit_charge,
840 (unsigned long long) xconn->smb2.credits.granted,
841 (unsigned long long) xconn->smb2.credits.seq_low,
842 (unsigned long long) xconn->smb2.credits.seq_range);
843 return false;
847 * now check the message ids
849 * for multi-credit requests we need to check all current mid plus
850 * the implicit mids caused by the credit charge
851 * e.g. current mid = 15, charge 5 => mark 15-19 as used
854 for (i = 0; i <= (credit_charge-1); i++) {
855 uint64_t id = message_id + i;
856 bool ok;
858 DEBUGC(11,
859 DBGC_SMB2_CREDITS,
860 ("Iterating mid %llu charge %u (sequence %llu)\n",
861 (unsigned long long)message_id,
862 credit_charge,
863 (unsigned long long)id));
865 ok = smb2_validate_sequence_number(xconn, message_id, id);
866 if (!ok) {
867 return false;
871 /* subtract used credits */
872 xconn->smb2.credits.granted -= credit_charge;
874 return true;
877 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
879 int count;
880 int idx;
882 count = req->in.vector_count;
884 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
885 /* It's not a SMB2 request */
886 return NT_STATUS_INVALID_PARAMETER;
889 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
890 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
891 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
892 const uint8_t *inhdr = NULL;
894 if (hdr->iov_len != SMB2_HDR_BODY) {
895 return NT_STATUS_INVALID_PARAMETER;
898 if (body->iov_len < 2) {
899 return NT_STATUS_INVALID_PARAMETER;
902 inhdr = (const uint8_t *)hdr->iov_base;
904 /* Check the SMB2 header */
905 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
906 return NT_STATUS_INVALID_PARAMETER;
909 if (!smb2_validate_message_id(req->xconn, inhdr)) {
910 return NT_STATUS_INVALID_PARAMETER;
914 return NT_STATUS_OK;
917 static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
918 const struct iovec *in_vector,
919 struct iovec *out_vector)
921 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
922 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
923 uint16_t credit_charge = 1;
924 uint16_t credits_requested;
925 uint32_t out_flags;
926 uint16_t cmd;
927 NTSTATUS out_status;
928 uint16_t credits_granted = 0;
929 uint64_t credits_possible;
930 uint16_t current_max_credits;
933 * first we grant only 1/16th of the max range.
935 * Windows also starts with the 1/16th and then grants
936 * more later. I was only able to trigger higher
937 * values, when using a very high credit charge.
939 * TODO: scale up depending on load, free memory
940 * or other stuff.
941 * Maybe also on the relationship between number
942 * of requests and the used sequence number.
943 * Which means we would grant more credits
944 * for client which use multi credit requests.
946 * The above is what Windows Server < 2016 is doing,
947 * but new servers use all credits (8192 by default).
949 current_max_credits = xconn->smb2.credits.max;
950 current_max_credits = MAX(current_max_credits, 1);
952 if (xconn->smb2.credits.multicredit) {
953 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
954 credit_charge = MAX(credit_charge, 1);
957 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
958 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
959 credits_requested = MAX(credits_requested, 1);
960 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
961 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
963 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
965 if (xconn->smb2.credits.max < credit_charge) {
966 smbd_server_connection_terminate(xconn,
967 "client error: credit charge > max credits\n");
968 return;
971 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
973 * In case we already send an async interim
974 * response, we should not grant
975 * credits on the final response.
977 credits_granted = 0;
978 } else {
979 uint16_t additional_possible =
980 xconn->smb2.credits.max - credit_charge;
981 uint16_t additional_max = 0;
982 uint16_t additional_credits = credits_requested - 1;
984 switch (cmd) {
985 case SMB2_OP_NEGPROT:
986 break;
987 case SMB2_OP_SESSSETUP:
989 * Windows 2012 RC1 starts to grant
990 * additional credits
991 * with a successful session setup
993 if (NT_STATUS_IS_OK(out_status)) {
994 additional_max = xconn->smb2.credits.max;
996 break;
997 default:
999 * Windows Server < 2016 and older Samba versions
1000 * used to only grant additional credits in
1001 * chunks of 32 credits.
1003 * But we match Windows Server 2016 and grant
1004 * all credits as requested.
1006 additional_max = xconn->smb2.credits.max;
1007 break;
1010 additional_max = MIN(additional_max, additional_possible);
1011 additional_credits = MIN(additional_credits, additional_max);
1013 credits_granted = credit_charge + additional_credits;
1017 * sequence numbers should not wrap
1019 * 1. calculate the possible credits until
1020 * the sequence numbers start to wrap on 64-bit.
1022 * 2. UINT64_MAX is used for Break Notifications.
1024 * 2. truncate the possible credits to the maximum
1025 * credits we want to grant to the client in total.
1027 * 3. remove the range we'll already granted to the client
1028 * this makes sure the client consumes the lowest sequence
1029 * number, before we can grant additional credits.
1031 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
1032 if (credits_possible > 0) {
1033 /* remove UINT64_MAX */
1034 credits_possible -= 1;
1036 credits_possible = MIN(credits_possible, current_max_credits);
1037 credits_possible -= xconn->smb2.credits.seq_range;
1039 credits_granted = MIN(credits_granted, credits_possible);
1041 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
1042 xconn->smb2.credits.granted += credits_granted;
1043 xconn->smb2.credits.seq_range += credits_granted;
1045 DBGC_DEBUG(DBGC_SMB2_CREDITS,
1046 "smb2_set_operation_credit: requested %u, charge %u, "
1047 "granted %u, current possible/max %u/%u, "
1048 "total granted/max/low/range %u/%u/%llu/%u\n",
1049 (unsigned int)credits_requested,
1050 (unsigned int)credit_charge,
1051 (unsigned int)credits_granted,
1052 (unsigned int)credits_possible,
1053 (unsigned int)current_max_credits,
1054 (unsigned int)xconn->smb2.credits.granted,
1055 (unsigned int)xconn->smb2.credits.max,
1056 (unsigned long long)xconn->smb2.credits.seq_low,
1057 (unsigned int)xconn->smb2.credits.seq_range);
1060 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
1061 struct smbd_smb2_request *outreq)
1063 int count, idx;
1064 uint16_t total_credits = 0;
1066 count = outreq->out.vector_count;
1068 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
1069 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
1070 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
1071 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
1073 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
1075 /* To match Windows, count up what we
1076 just granted. */
1077 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
1078 /* Set to zero in all but the last reply. */
1079 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
1080 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
1081 } else {
1082 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
1087 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
1089 if (req->current_idx <= 1) {
1090 if (size <= sizeof(req->out._body)) {
1091 return data_blob_const(req->out._body, size);
1095 return data_blob_talloc(req, NULL, size);
1098 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
1100 struct smbXsrv_connection *xconn = req->xconn;
1101 TALLOC_CTX *mem_ctx;
1102 struct iovec *vector;
1103 int count;
1104 int idx;
1105 bool ok;
1107 count = req->in.vector_count;
1108 if (count <= ARRAY_SIZE(req->out._vector)) {
1109 mem_ctx = req;
1110 vector = req->out._vector;
1111 } else {
1112 vector = talloc_zero_array(req, struct iovec, count);
1113 if (vector == NULL) {
1114 return NT_STATUS_NO_MEMORY;
1116 mem_ctx = vector;
1119 vector[0].iov_base = req->out.nbt_hdr;
1120 vector[0].iov_len = 4;
1121 SIVAL(req->out.nbt_hdr, 0, 0);
1123 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
1124 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
1125 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
1126 uint8_t *outhdr = NULL;
1127 uint8_t *outbody = NULL;
1128 uint32_t next_command_ofs = 0;
1129 struct iovec *current = &vector[idx];
1131 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
1132 /* we have a next command -
1133 * setup for the error case. */
1134 next_command_ofs = SMB2_HDR_BODY + 9;
1137 if (idx == 1) {
1138 outhdr = req->out._hdr;
1139 } else {
1140 outhdr = talloc_zero_array(mem_ctx, uint8_t,
1141 OUTVEC_ALLOC_SIZE);
1142 if (outhdr == NULL) {
1143 return NT_STATUS_NO_MEMORY;
1147 outbody = outhdr + SMB2_HDR_BODY;
1150 * SMBD_SMB2_TF_IOV_OFS might be used later
1152 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1153 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1155 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
1156 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1158 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1159 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1161 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1162 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1164 /* setup the SMB2 header */
1165 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1166 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1167 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1168 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1169 SIVAL(outhdr, SMB2_HDR_STATUS,
1170 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1171 SSVAL(outhdr, SMB2_HDR_OPCODE,
1172 SVAL(inhdr, SMB2_HDR_OPCODE));
1173 SIVAL(outhdr, SMB2_HDR_FLAGS,
1174 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1175 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1176 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1177 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1178 SIVAL(outhdr, SMB2_HDR_PID,
1179 IVAL(inhdr, SMB2_HDR_PID));
1180 SIVAL(outhdr, SMB2_HDR_TID,
1181 IVAL(inhdr, SMB2_HDR_TID));
1182 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1183 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1184 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1185 inhdr + SMB2_HDR_SIGNATURE, 16);
1187 /* setup error body header */
1188 SSVAL(outbody, 0x00, 0x08 + 1);
1189 SSVAL(outbody, 0x02, 0);
1190 SIVAL(outbody, 0x04, 0);
1193 req->out.vector = vector;
1194 req->out.vector_count = count;
1196 /* setup the length of the NBT packet */
1197 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1198 if (!ok) {
1199 return NT_STATUS_INVALID_PARAMETER_MIX;
1202 DLIST_ADD_END(xconn->smb2.requests, req);
1204 return NT_STATUS_OK;
1207 bool smbXsrv_server_multi_channel_enabled(void)
1209 bool enabled = lp_server_multi_channel_support();
1210 #ifndef __ALLOW_MULTI_CHANNEL_SUPPORT
1211 bool forced = false;
1212 struct loadparm_context *lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
1213 bool unspecified = lpcfg_parm_is_unspecified(lp_ctx, "server multi channel support");
1214 if (unspecified) {
1215 enabled = false;
1218 * If we don't have support from the kernel
1219 * to ask for the un-acked number of bytes
1220 * in the socket send queue, we better
1221 * don't support multi-channel.
1223 forced = lp_parm_bool(-1, "force", "server multi channel support", false);
1224 if (enabled && !forced) {
1225 D_NOTICE("'server multi channel support' enabled "
1226 "but not supported on %s (%s)\n",
1227 SYSTEM_UNAME_SYSNAME, SYSTEM_UNAME_RELEASE);
1228 DEBUGADD(DBGLVL_NOTICE, ("Please report this on "
1229 "https://bugzilla.samba.org/show_bug.cgi?id=11897\n"));
1230 enabled = false;
1232 TALLOC_FREE(lp_ctx);
1233 #endif /* ! __ALLOW_MULTI_CHANNEL_SUPPORT */
1234 return enabled;
1237 static NTSTATUS smbXsrv_connection_get_rto_usecs(struct smbXsrv_connection *xconn,
1238 uint32_t *_rto_usecs)
1241 * Define an Retransmission Timeout
1242 * of 1 second, if there's no way for the
1243 * kernel to tell us the current value.
1245 uint32_t rto_usecs = 1000000;
1247 #ifdef __HAVE_TCP_INFO_RTO
1249 struct tcp_info info;
1250 socklen_t ilen = sizeof(info);
1251 int ret;
1253 ZERO_STRUCT(info);
1254 ret = getsockopt(xconn->transport.sock,
1255 IPPROTO_TCP, TCP_INFO,
1256 (void *)&info, &ilen);
1257 if (ret != 0) {
1258 int saved_errno = errno;
1259 NTSTATUS status = map_nt_error_from_unix(errno);
1260 DBG_ERR("getsockopt(TCP_INFO) errno[%d/%s] -s %s\n",
1261 saved_errno, strerror(saved_errno),
1262 nt_errstr(status));
1263 return status;
1266 DBG_DEBUG("tcpi_rto[%u] tcpi_rtt[%u] tcpi_rttvar[%u]\n",
1267 (unsigned)info.tcpi_rto,
1268 (unsigned)info.tcpi_rtt,
1269 (unsigned)info.tcpi_rttvar);
1270 rto_usecs = info.tcpi_rto;
1272 #endif /* __HAVE_TCP_INFO_RTO */
1274 rto_usecs = MAX(rto_usecs, 200000); /* at least 0.2s */
1275 rto_usecs = MIN(rto_usecs, 1000000); /* at max 1.0s */
1276 *_rto_usecs = rto_usecs;
1277 return NT_STATUS_OK;
1280 static NTSTATUS smbXsrv_connection_get_acked_bytes(struct smbXsrv_connection *xconn,
1281 uint64_t *_acked_bytes)
1284 * Unless the kernel has an interface
1285 * to reveal the number of un-acked bytes
1286 * in the socket send queue, we'll assume
1287 * everything is already acked.
1289 * But that would mean that we better don't
1290 * pretent to support multi-channel.
1292 uint64_t unacked_bytes = 0;
1294 *_acked_bytes = 0;
1296 if (xconn->ack.force_unacked_timeout) {
1298 * Smbtorture tries to test channel failures...
1299 * Just pretend nothing was acked...
1301 DBG_INFO("Simulating channel failure: "
1302 "xconn->ack.unacked_bytes[%llu]\n",
1303 (unsigned long long)xconn->ack.unacked_bytes);
1304 return NT_STATUS_OK;
1307 #ifdef __IOCTL_SEND_QUEUE_SIZE_OPCODE
1309 int value = 0;
1310 int ret;
1313 * If we have kernel support to get
1314 * the number of bytes waiting in
1315 * the socket's send queue, we
1316 * use that in order to find out
1317 * the number of unacked bytes.
1319 ret = ioctl(xconn->transport.sock,
1320 __IOCTL_SEND_QUEUE_SIZE_OPCODE,
1321 &value);
1322 if (ret != 0) {
1323 int saved_errno = errno;
1324 NTSTATUS status = map_nt_error_from_unix(saved_errno);
1325 DBG_ERR("Failed to get the SEND_QUEUE_SIZE - "
1326 "errno %d (%s) - %s\n",
1327 saved_errno, strerror(saved_errno),
1328 nt_errstr(status));
1329 return status;
1332 if (value < 0) {
1333 DBG_ERR("xconn->ack.unacked_bytes[%llu] value[%d]\n",
1334 (unsigned long long)xconn->ack.unacked_bytes,
1335 value);
1336 return NT_STATUS_INTERNAL_ERROR;
1338 unacked_bytes = value;
1340 #endif
1341 if (xconn->ack.unacked_bytes == 0) {
1342 xconn->ack.unacked_bytes = unacked_bytes;
1343 return NT_STATUS_OK;
1346 if (xconn->ack.unacked_bytes < unacked_bytes) {
1347 DBG_ERR("xconn->ack.unacked_bytes[%llu] unacked_bytes[%llu]\n",
1348 (unsigned long long)xconn->ack.unacked_bytes,
1349 (unsigned long long)unacked_bytes);
1350 return NT_STATUS_INTERNAL_ERROR;
1353 *_acked_bytes = xconn->ack.unacked_bytes - unacked_bytes;
1354 xconn->ack.unacked_bytes = unacked_bytes;
1355 return NT_STATUS_OK;
1358 static void smbd_smb2_send_queue_ack_fail(struct smbd_smb2_send_queue **queue,
1359 NTSTATUS status)
1361 struct smbd_smb2_send_queue *e = NULL;
1362 struct smbd_smb2_send_queue *n = NULL;
1364 for (e = *queue; e != NULL; e = n) {
1365 n = e->next;
1367 DLIST_REMOVE(*queue, e);
1368 if (e->ack.req != NULL) {
1369 tevent_req_nterror(e->ack.req, status);
1374 static NTSTATUS smbd_smb2_send_queue_ack_bytes(struct smbd_smb2_send_queue **queue,
1375 uint64_t acked_bytes)
1377 struct smbd_smb2_send_queue *e = NULL;
1378 struct smbd_smb2_send_queue *n = NULL;
1380 for (e = *queue; e != NULL; e = n) {
1381 bool expired;
1383 n = e->next;
1385 if (e->ack.req == NULL) {
1386 continue;
1389 if (e->ack.required_acked_bytes <= acked_bytes) {
1390 e->ack.required_acked_bytes = 0;
1391 DLIST_REMOVE(*queue, e);
1392 tevent_req_done(e->ack.req);
1393 continue;
1395 e->ack.required_acked_bytes -= acked_bytes;
1397 expired = timeval_expired(&e->ack.timeout);
1398 if (expired) {
1399 return NT_STATUS_IO_TIMEOUT;
1403 return NT_STATUS_OK;
1406 static NTSTATUS smbd_smb2_check_ack_queue(struct smbXsrv_connection *xconn)
1408 uint64_t acked_bytes = 0;
1409 NTSTATUS status;
1411 status = smbXsrv_connection_get_acked_bytes(xconn, &acked_bytes);
1412 if (!NT_STATUS_IS_OK(status)) {
1413 return status;
1416 status = smbd_smb2_send_queue_ack_bytes(&xconn->ack.queue, acked_bytes);
1417 if (!NT_STATUS_IS_OK(status)) {
1418 return status;
1421 status = smbd_smb2_send_queue_ack_bytes(&xconn->smb2.send_queue, 0);
1422 if (!NT_STATUS_IS_OK(status)) {
1423 return status;
1426 return NT_STATUS_OK;
1429 static void smbXsrv_connection_ack_checker(struct tevent_req *subreq)
1431 struct smbXsrv_connection *xconn =
1432 tevent_req_callback_data(subreq,
1433 struct smbXsrv_connection);
1434 struct smbXsrv_client *client = xconn->client;
1435 struct timeval next_check;
1436 NTSTATUS status;
1437 bool ok;
1439 xconn->ack.checker_subreq = NULL;
1441 ok = tevent_wakeup_recv(subreq);
1442 TALLOC_FREE(subreq);
1443 if (!ok) {
1444 smbd_server_connection_terminate(xconn,
1445 "tevent_wakeup_recv() failed");
1446 return;
1449 status = smbd_smb2_check_ack_queue(xconn);
1450 if (!NT_STATUS_IS_OK(status)) {
1451 smbd_server_connection_terminate(xconn, nt_errstr(status));
1452 return;
1455 next_check = timeval_current_ofs_usec(xconn->ack.rto_usecs);
1456 xconn->ack.checker_subreq = tevent_wakeup_send(xconn,
1457 client->raw_ev_ctx,
1458 next_check);
1459 if (xconn->ack.checker_subreq == NULL) {
1460 smbd_server_connection_terminate(xconn,
1461 "tevent_wakeup_send() failed");
1462 return;
1464 tevent_req_set_callback(xconn->ack.checker_subreq,
1465 smbXsrv_connection_ack_checker,
1466 xconn);
1469 static NTSTATUS smbXsrv_client_pending_breaks_updated(struct smbXsrv_client *client)
1471 struct smbXsrv_connection *xconn = NULL;
1473 for (xconn = client->connections; xconn != NULL; xconn = xconn->next) {
1474 struct timeval next_check;
1475 uint64_t acked_bytes = 0;
1476 NTSTATUS status;
1479 * A new 'pending break cycle' starts
1480 * with a first pending break and lasts until
1481 * all pending breaks are finished.
1483 * This is typically a very short time,
1484 * the value of one retransmission timeout.
1487 if (client->pending_breaks == NULL) {
1489 * No more pending breaks, remove a pending
1490 * checker timer
1492 TALLOC_FREE(xconn->ack.checker_subreq);
1493 continue;
1496 if (xconn->ack.checker_subreq != NULL) {
1498 * The cycle already started =>
1499 * nothing todo
1501 continue;
1505 * Get the current retransmission timeout value.
1507 * It may change over time, but fetching it once
1508 * per 'pending break' cycled should be enough.
1510 status = smbXsrv_connection_get_rto_usecs(xconn,
1511 &xconn->ack.rto_usecs);
1512 if (!NT_STATUS_IS_OK(status)) {
1513 return status;
1517 * At the start of the cycle we reset the
1518 * unacked_bytes counter (first to 0 and
1519 * within smbXsrv_connection_get_acked_bytes()
1520 * to the current value in the kernel
1521 * send queue.
1523 xconn->ack.unacked_bytes = 0;
1524 status = smbXsrv_connection_get_acked_bytes(xconn, &acked_bytes);
1525 if (!NT_STATUS_IS_OK(status)) {
1526 return status;
1530 * We setup a timer in order to check for
1531 * acked bytes after one retransmission timeout.
1533 * The code that sets up the send_queue.ack.timeout
1534 * uses a multiple of the retransmission timeout.
1536 next_check = timeval_current_ofs_usec(xconn->ack.rto_usecs);
1537 xconn->ack.checker_subreq = tevent_wakeup_send(xconn,
1538 client->raw_ev_ctx,
1539 next_check);
1540 if (xconn->ack.checker_subreq == NULL) {
1541 return NT_STATUS_NO_MEMORY;
1543 tevent_req_set_callback(xconn->ack.checker_subreq,
1544 smbXsrv_connection_ack_checker,
1545 xconn);
1548 return NT_STATUS_OK;
1551 void smbXsrv_connection_disconnect_transport(struct smbXsrv_connection *xconn,
1552 NTSTATUS status)
1554 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
1555 return;
1558 xconn->transport.status = status;
1559 TALLOC_FREE(xconn->transport.fde);
1560 if (xconn->transport.sock != -1) {
1561 xconn->transport.sock = -1;
1563 smbd_smb2_send_queue_ack_fail(&xconn->ack.queue, status);
1564 smbd_smb2_send_queue_ack_fail(&xconn->smb2.send_queue, status);
1565 xconn->smb2.send_queue_len = 0;
1566 DO_PROFILE_INC(disconnect);
1569 size_t smbXsrv_client_valid_connections(struct smbXsrv_client *client)
1571 struct smbXsrv_connection *xconn = NULL;
1572 size_t num_ok = 0;
1574 for (xconn = client->connections; xconn != NULL; xconn = xconn->next) {
1575 if (NT_STATUS_IS_OK(xconn->transport.status)) {
1576 num_ok++;
1580 return num_ok;
1583 struct smbXsrv_connection_shutdown_state {
1584 struct smbXsrv_connection *xconn;
1587 static void smbXsrv_connection_shutdown_wait_done(struct tevent_req *subreq);
1589 static struct tevent_req *smbXsrv_connection_shutdown_send(TALLOC_CTX *mem_ctx,
1590 struct tevent_context *ev,
1591 struct smbXsrv_connection *xconn)
1593 struct tevent_req *req = NULL;
1594 struct smbXsrv_connection_shutdown_state *state = NULL;
1595 struct tevent_req *subreq = NULL;
1596 size_t len = 0;
1597 struct smbd_smb2_request *preq = NULL;
1598 NTSTATUS status;
1601 * The caller should have called
1602 * smbXsrv_connection_disconnect_transport() before.
1604 SMB_ASSERT(!NT_STATUS_IS_OK(xconn->transport.status));
1605 SMB_ASSERT(xconn->transport.terminating);
1606 SMB_ASSERT(xconn->transport.shutdown_wait_queue == NULL);
1608 req = tevent_req_create(mem_ctx, &state,
1609 struct smbXsrv_connection_shutdown_state);
1610 if (req == NULL) {
1611 return NULL;
1614 state->xconn = xconn;
1615 tevent_req_defer_callback(req, ev);
1617 xconn->transport.shutdown_wait_queue =
1618 tevent_queue_create(state, "smbXsrv_connection_shutdown_queue");
1619 if (tevent_req_nomem(xconn->transport.shutdown_wait_queue, req)) {
1620 return tevent_req_post(req, ev);
1623 for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
1625 * Now wait until the request is finished.
1627 * We don't set a callback, as we just want to block the
1628 * wait queue and the talloc_free() of the request will
1629 * remove the item from the wait queue.
1631 * Note that we don't cancel the requests here
1632 * in order to keep the replay detection logic correct.
1634 * However if we teardown the last channel of
1635 * a connection, we'll call some logic via
1636 * smbXsrv_session_disconnect_xconn()
1637 * -> smbXsrv_session_disconnect_xconn_callback()
1638 * -> smbXsrv_session_remove_channel()
1639 * -> smb2srv_session_shutdown_send()
1640 * will indeed cancel the request.
1642 subreq = tevent_queue_wait_send(preq, ev,
1643 xconn->transport.shutdown_wait_queue);
1644 if (tevent_req_nomem(subreq, req)) {
1645 return tevent_req_post(req, ev);
1650 * This may attach sessions with num_channels == 0
1651 * to xconn->transport.shutdown_wait_queue.
1653 status = smbXsrv_session_disconnect_xconn(xconn);
1654 if (tevent_req_nterror(req, status)) {
1655 return tevent_req_post(req, ev);
1658 len = tevent_queue_length(xconn->transport.shutdown_wait_queue);
1659 if (len == 0) {
1660 tevent_req_done(req);
1661 return tevent_req_post(req, ev);
1665 * Now we add our own waiter to the end of the queue,
1666 * this way we get notified when all pending requests are finished
1667 * and send to the socket.
1669 subreq = tevent_queue_wait_send(state, ev, xconn->transport.shutdown_wait_queue);
1670 if (tevent_req_nomem(subreq, req)) {
1671 return tevent_req_post(req, ev);
1673 tevent_req_set_callback(subreq, smbXsrv_connection_shutdown_wait_done, req);
1675 return req;
1678 static void smbXsrv_connection_shutdown_wait_done(struct tevent_req *subreq)
1680 struct tevent_req *req =
1681 tevent_req_callback_data(subreq,
1682 struct tevent_req);
1683 struct smbXsrv_connection_shutdown_state *state =
1684 tevent_req_data(req,
1685 struct smbXsrv_connection_shutdown_state);
1686 struct smbXsrv_connection *xconn = state->xconn;
1688 tevent_queue_wait_recv(subreq);
1689 TALLOC_FREE(subreq);
1691 tevent_req_done(req);
1693 * make sure the xconn pointer is still valid,
1694 * it should as we used tevent_req_defer_callback()
1696 SMB_ASSERT(xconn->transport.terminating);
1699 static NTSTATUS smbXsrv_connection_shutdown_recv(struct tevent_req *req)
1701 struct smbXsrv_connection_shutdown_state *state =
1702 tevent_req_data(req,
1703 struct smbXsrv_connection_shutdown_state);
1704 struct smbXsrv_connection *xconn = state->xconn;
1706 * make sure the xconn pointer is still valid,
1707 * it should as we used tevent_req_defer_callback()
1709 SMB_ASSERT(xconn->transport.terminating);
1710 return tevent_req_simple_recv_ntstatus(req);
1713 static void smbd_server_connection_terminate_done(struct tevent_req *subreq)
1715 struct smbXsrv_connection *xconn =
1716 tevent_req_callback_data(subreq,
1717 struct smbXsrv_connection);
1718 struct smbXsrv_client *client = xconn->client;
1719 NTSTATUS status;
1721 status = smbXsrv_connection_shutdown_recv(subreq);
1722 TALLOC_FREE(subreq);
1723 if (!NT_STATUS_IS_OK(status)) {
1724 exit_server("smbXsrv_connection_shutdown_recv failed");
1727 DLIST_REMOVE(client->connections, xconn);
1728 TALLOC_FREE(xconn);
1731 void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
1732 const char *reason,
1733 const char *location)
1735 struct smbXsrv_client *client = xconn->client;
1736 size_t num_ok = 0;
1739 * Make sure that no new request will be able to use this session.
1741 * smbXsrv_connection_disconnect_transport() might be called already,
1742 * but calling it again is a no-op.
1744 smbXsrv_connection_disconnect_transport(xconn,
1745 NT_STATUS_CONNECTION_DISCONNECTED);
1747 num_ok = smbXsrv_client_valid_connections(client);
1749 if (xconn->transport.terminating) {
1750 DBG_DEBUG("skip recursion conn[%s] num_ok[%zu] reason[%s] at %s\n",
1751 smbXsrv_connection_dbg(xconn), num_ok,
1752 reason, location);
1753 return;
1755 xconn->transport.terminating = true;
1757 DBG_DEBUG("conn[%s] num_ok[%zu] reason[%s] at %s\n",
1758 smbXsrv_connection_dbg(xconn), num_ok,
1759 reason, location);
1761 if (xconn->has_cluster_movable_ip) {
1763 * If the connection has a movable cluster public address
1764 * we disconnect all client connections,
1765 * as the public address might be moved to
1766 * a different node.
1768 * In future we may recheck which node currently
1769 * holds this address, but for now we keep it simple.
1771 smbd_server_disconnect_client_ex(xconn->client,
1772 reason,
1773 location);
1774 return;
1777 if (num_ok != 0) {
1778 struct tevent_req *subreq = NULL;
1780 subreq = smbXsrv_connection_shutdown_send(client,
1781 client->raw_ev_ctx,
1782 xconn);
1783 if (subreq == NULL) {
1784 exit_server("smbXsrv_connection_shutdown_send failed");
1786 tevent_req_set_callback(subreq,
1787 smbd_server_connection_terminate_done,
1788 xconn);
1789 return;
1793 * The last connection was disconnected
1795 exit_server_cleanly(reason);
1798 void smbd_server_disconnect_client_ex(struct smbXsrv_client *client,
1799 const char *reason,
1800 const char *location)
1802 size_t num_ok = 0;
1804 num_ok = smbXsrv_client_valid_connections(client);
1806 DBG_WARNING("client[%s] num_ok[%zu] reason[%s] at %s\n",
1807 client->global->remote_address, num_ok,
1808 reason, location);
1811 * Something bad happened we need to disconnect all connections.
1813 exit_server_cleanly(reason);
1816 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1817 struct iovec *outvec,
1818 const struct iovec *srcvec)
1820 const uint8_t *srctf;
1821 size_t srctf_len;
1822 const uint8_t *srchdr;
1823 size_t srchdr_len;
1824 const uint8_t *srcbody;
1825 size_t srcbody_len;
1826 const uint8_t *expected_srcbody;
1827 const uint8_t *srcdyn;
1828 size_t srcdyn_len;
1829 const uint8_t *expected_srcdyn;
1830 uint8_t *dsttf;
1831 uint8_t *dsthdr;
1832 uint8_t *dstbody;
1833 uint8_t *dstdyn;
1835 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1836 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1837 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1838 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1839 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1840 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1841 expected_srcbody = srchdr + SMB2_HDR_BODY;
1842 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1843 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1844 expected_srcdyn = srcbody + 8;
1846 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1847 return false;
1850 if (srchdr_len != SMB2_HDR_BODY) {
1851 return false;
1854 if (srctf_len == SMB2_TF_HDR_SIZE) {
1855 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1856 if (dsttf == NULL) {
1857 return false;
1859 } else {
1860 dsttf = NULL;
1862 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1863 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1865 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1866 * be allocated with size OUTVEC_ALLOC_SIZE. */
1868 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1869 if (dsthdr == NULL) {
1870 return false;
1872 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1873 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1876 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1877 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1878 * then duplicate this. Else use talloc_memdup().
1881 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1882 dstbody = dsthdr + SMB2_HDR_BODY;
1883 } else {
1884 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1885 if (dstbody == NULL) {
1886 return false;
1889 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1890 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1893 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1894 * pointing to
1895 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1896 * then duplicate this. Else use talloc_memdup().
1899 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1900 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1901 } else if (srcdyn == NULL) {
1902 dstdyn = NULL;
1903 } else {
1904 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1905 if (dstdyn == NULL) {
1906 return false;
1909 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1910 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1912 return true;
1915 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1917 struct smbd_smb2_request *newreq = NULL;
1918 struct iovec *outvec = NULL;
1919 int count = req->out.vector_count;
1920 int i;
1921 bool ok;
1923 newreq = smbd_smb2_request_allocate(req->xconn);
1924 if (!newreq) {
1925 return NULL;
1928 newreq->session = req->session;
1929 newreq->do_encryption = req->do_encryption;
1930 newreq->do_signing = req->do_signing;
1931 newreq->current_idx = req->current_idx;
1933 outvec = talloc_zero_array(newreq, struct iovec, count);
1934 if (!outvec) {
1935 TALLOC_FREE(newreq);
1936 return NULL;
1938 newreq->out.vector = outvec;
1939 newreq->out.vector_count = count;
1941 /* Setup the outvec's identically to req. */
1942 outvec[0].iov_base = newreq->out.nbt_hdr;
1943 outvec[0].iov_len = 4;
1944 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1946 /* Setup the vectors identically to the ones in req. */
1947 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1948 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1949 break;
1953 if (i < count) {
1954 /* Alloc failed. */
1955 TALLOC_FREE(newreq);
1956 return NULL;
1959 ok = smb2_setup_nbt_length(newreq->out.vector,
1960 newreq->out.vector_count);
1961 if (!ok) {
1962 TALLOC_FREE(newreq);
1963 return NULL;
1966 return newreq;
1969 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1971 struct smbXsrv_connection *xconn = req->xconn;
1972 int first_idx = 1;
1973 struct iovec *firsttf = NULL;
1974 struct iovec *outhdr_v = NULL;
1975 uint8_t *outhdr = NULL;
1976 struct smbd_smb2_request *nreq = NULL;
1977 NTSTATUS status;
1978 bool ok;
1980 /* Create a new smb2 request we'll use
1981 for the interim return. */
1982 nreq = dup_smb2_req(req);
1983 if (!nreq) {
1984 return NT_STATUS_NO_MEMORY;
1987 /* Lose the last X out vectors. They're the
1988 ones we'll be using for the async reply. */
1989 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1991 ok = smb2_setup_nbt_length(nreq->out.vector,
1992 nreq->out.vector_count);
1993 if (!ok) {
1994 return NT_STATUS_INVALID_PARAMETER_MIX;
1997 /* Step back to the previous reply. */
1998 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1999 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
2000 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
2001 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
2002 /* And end the chain. */
2003 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
2005 /* Calculate outgoing credits */
2006 smb2_calculate_credits(req, nreq);
2008 if (DEBUGLEVEL >= 10) {
2009 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
2010 (unsigned int)nreq->current_idx );
2011 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
2012 (unsigned int)nreq->out.vector_count );
2013 print_req_vectors(nreq);
2017 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
2018 * we need to sign/encrypt here with the last/first key we remembered
2020 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2021 status = smb2_signing_encrypt_pdu(req->first_enc_key,
2022 firsttf,
2023 nreq->out.vector_count - first_idx);
2024 if (!NT_STATUS_IS_OK(status)) {
2025 return status;
2027 } else if (smb2_signing_key_valid(req->last_sign_key)) {
2028 status = smb2_signing_sign_pdu(req->last_sign_key,
2029 outhdr_v,
2030 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2031 if (!NT_STATUS_IS_OK(status)) {
2032 return status;
2036 nreq->queue_entry.mem_ctx = nreq;
2037 nreq->queue_entry.vector = nreq->out.vector;
2038 nreq->queue_entry.count = nreq->out.vector_count;
2039 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry);
2040 xconn->smb2.send_queue_len++;
2042 status = smbd_smb2_flush_send_queue(xconn);
2043 if (!NT_STATUS_IS_OK(status)) {
2044 return status;
2047 return NT_STATUS_OK;
2050 struct smbd_smb2_request_pending_state {
2051 struct smbd_smb2_send_queue queue_entry;
2052 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
2053 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
2056 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
2057 struct tevent_timer *te,
2058 struct timeval current_time,
2059 void *private_data);
2061 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
2062 struct tevent_req *subreq,
2063 uint32_t defer_time)
2065 NTSTATUS status;
2066 struct timeval defer_endtime;
2067 uint8_t *outhdr = NULL;
2068 uint32_t flags;
2070 if (!tevent_req_is_in_progress(subreq)) {
2072 * This is a performance optimization,
2073 * it avoids one tevent_loop iteration,
2074 * which means we avoid one
2075 * talloc_stackframe_pool/talloc_free pair.
2077 tevent_req_notify_callback(subreq);
2078 return NT_STATUS_OK;
2081 req->subreq = subreq;
2082 subreq = NULL;
2084 if (req->async_te) {
2085 /* We're already async. */
2086 return NT_STATUS_OK;
2089 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2090 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
2091 if (flags & SMB2_HDR_FLAG_ASYNC) {
2092 /* We're already async. */
2093 return NT_STATUS_OK;
2096 if (req->async_internal || defer_time == 0) {
2098 * An SMB2 request implementation wants to handle the request
2099 * asynchronously "internally" while keeping synchronous
2100 * behaviour for the SMB2 request. This means we don't send an
2101 * interim response and we can allow processing of compound SMB2
2102 * requests (cf the subsequent check) for all cases.
2104 return NT_STATUS_OK;
2107 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
2109 * We're trying to go async in a compound request
2110 * chain. This is only allowed for opens that cause an
2111 * oplock break or for the last operation in the
2112 * chain, otherwise it is not allowed. See
2113 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
2115 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2117 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
2119 * Cancel the outstanding request.
2121 bool ok = tevent_req_cancel(req->subreq);
2122 if (ok) {
2123 return NT_STATUS_OK;
2125 TALLOC_FREE(req->subreq);
2126 return smbd_smb2_request_error(req,
2127 NT_STATUS_INTERNAL_ERROR);
2131 if (DEBUGLEVEL >= 10) {
2132 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
2133 (unsigned int)req->current_idx );
2134 print_req_vectors(req);
2137 if (req->current_idx > 1) {
2139 * We're going async in a compound
2140 * chain after the first request has
2141 * already been processed. Send an
2142 * interim response containing the
2143 * set of replies already generated.
2145 int idx = req->current_idx;
2147 status = smb2_send_async_interim_response(req);
2148 if (!NT_STATUS_IS_OK(status)) {
2149 return status;
2151 TALLOC_FREE(req->first_enc_key);
2153 req->current_idx = 1;
2156 * Re-arrange the in.vectors to remove what
2157 * we just sent.
2159 memmove(&req->in.vector[1],
2160 &req->in.vector[idx],
2161 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
2162 req->in.vector_count = 1 + (req->in.vector_count - idx);
2164 /* Re-arrange the out.vectors to match. */
2165 memmove(&req->out.vector[1],
2166 &req->out.vector[idx],
2167 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
2168 req->out.vector_count = 1 + (req->out.vector_count - idx);
2170 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
2172 * We only have one remaining request as
2173 * we've processed everything else.
2174 * This is no longer a compound request.
2176 req->compound_related = false;
2177 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2178 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
2179 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
2182 TALLOC_FREE(req->last_sign_key);
2185 * smbd_smb2_request_pending_timer() just send a packet
2186 * to the client and doesn't need any impersonation.
2187 * So we use req->xconn->client->raw_ev_ctx instead
2188 * of req->ev_ctx here.
2190 defer_endtime = timeval_current_ofs_usec(defer_time);
2191 req->async_te = tevent_add_timer(req->xconn->client->raw_ev_ctx,
2192 req, defer_endtime,
2193 smbd_smb2_request_pending_timer,
2194 req);
2195 if (req->async_te == NULL) {
2196 return NT_STATUS_NO_MEMORY;
2199 return NT_STATUS_OK;
2202 static
2203 struct smb2_signing_key *smbd_smb2_signing_key(struct smbXsrv_session *session,
2204 struct smbXsrv_connection *xconn,
2205 bool *_has_channel)
2207 struct smbXsrv_channel_global0 *c = NULL;
2208 NTSTATUS status;
2209 struct smb2_signing_key *key = NULL;
2210 bool has_channel = false;
2212 status = smbXsrv_session_find_channel(session, xconn, &c);
2213 if (NT_STATUS_IS_OK(status)) {
2214 key = c->signing_key;
2215 has_channel = true;
2218 if (!smb2_signing_key_valid(key)) {
2219 key = session->global->signing_key;
2220 has_channel = false;
2223 if (_has_channel != NULL) {
2224 *_has_channel = has_channel;
2227 return key;
2230 static NTSTATUS smb2_get_new_nonce(struct smbXsrv_session *session,
2231 uint64_t *new_nonce_high,
2232 uint64_t *new_nonce_low)
2234 uint64_t nonce_high;
2235 uint64_t nonce_low;
2237 session->nonce_low += 1;
2238 if (session->nonce_low == 0) {
2239 session->nonce_low += 1;
2240 session->nonce_high += 1;
2244 * CCM and GCM algorithms must never have their
2245 * nonce wrap, or the security of the whole
2246 * communication and the keys is destroyed.
2247 * We must drop the connection once we have
2248 * transferred too much data.
2250 * NOTE: We assume nonces greater than 8 bytes.
2252 if (session->nonce_high >= session->nonce_high_max) {
2253 return NT_STATUS_ENCRYPTION_FAILED;
2256 nonce_high = session->nonce_high_random;
2257 nonce_high += session->nonce_high;
2258 nonce_low = session->nonce_low;
2260 *new_nonce_high = nonce_high;
2261 *new_nonce_low = nonce_low;
2262 return NT_STATUS_OK;
2265 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
2266 struct tevent_timer *te,
2267 struct timeval current_time,
2268 void *private_data)
2270 struct smbd_smb2_request *req =
2271 talloc_get_type_abort(private_data,
2272 struct smbd_smb2_request);
2273 struct smbXsrv_connection *xconn = req->xconn;
2274 struct smbd_smb2_request_pending_state *state = NULL;
2275 uint8_t *outhdr = NULL;
2276 const uint8_t *inhdr = NULL;
2277 uint8_t *tf = NULL;
2278 uint8_t *hdr = NULL;
2279 uint8_t *body = NULL;
2280 uint8_t *dyn = NULL;
2281 uint32_t flags = 0;
2282 uint64_t message_id = 0;
2283 uint64_t async_id = 0;
2284 NTSTATUS status;
2285 bool ok;
2287 TALLOC_FREE(req->async_te);
2289 /* Ensure our final reply matches the interim one. */
2290 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2291 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2292 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
2293 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
2295 async_id = message_id; /* keep it simple for now... */
2297 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
2298 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
2300 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
2301 "going async\n",
2302 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
2303 (unsigned long long)async_id ));
2306 * What we send is identical to a smbd_smb2_request_error
2307 * packet with an error status of STATUS_PENDING. Make use
2308 * of this fact sometime when refactoring. JRA.
2311 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
2312 if (state == NULL) {
2313 smbd_server_connection_terminate(xconn,
2314 nt_errstr(NT_STATUS_NO_MEMORY));
2315 return;
2318 tf = state->buf + NBT_HDR_SIZE;
2320 hdr = tf + SMB2_TF_HDR_SIZE;
2321 body = hdr + SMB2_HDR_BODY;
2322 dyn = body + 8;
2324 if (req->do_encryption) {
2325 uint64_t nonce_high = 0;
2326 uint64_t nonce_low = 0;
2327 uint64_t session_id = req->session->global->session_wire_id;
2329 status = smb2_get_new_nonce(req->session,
2330 &nonce_high,
2331 &nonce_low);
2332 if (!NT_STATUS_IS_OK(status)) {
2333 smbd_server_connection_terminate(xconn,
2334 nt_errstr(status));
2335 return;
2338 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2339 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2340 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2341 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2344 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
2345 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2346 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2347 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(NT_STATUS_PENDING));
2348 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
2351 * The STATUS_PENDING response has SMB2_HDR_FLAG_SIGNED
2352 * clearedm, but echoes the signature field.
2354 flags &= ~SMB2_HDR_FLAG_SIGNED;
2355 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
2356 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2357 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
2358 SBVAL(hdr, SMB2_HDR_PID, async_id);
2359 SBVAL(hdr, SMB2_HDR_SESSION_ID,
2360 BVAL(outhdr, SMB2_HDR_SESSION_ID));
2361 memcpy(hdr+SMB2_HDR_SIGNATURE,
2362 outhdr+SMB2_HDR_SIGNATURE, 16);
2364 SSVAL(body, 0x00, 0x08 + 1);
2366 SCVAL(body, 0x02, 0);
2367 SCVAL(body, 0x03, 0);
2368 SIVAL(body, 0x04, 0);
2369 /* Match W2K8R2... */
2370 SCVAL(dyn, 0x00, 0x21);
2372 state->vector[0].iov_base = (void *)state->buf;
2373 state->vector[0].iov_len = NBT_HDR_SIZE;
2375 if (req->do_encryption) {
2376 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
2377 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len =
2378 SMB2_TF_HDR_SIZE;
2379 } else {
2380 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
2381 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
2384 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
2385 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
2387 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
2388 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
2390 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
2391 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
2393 ok = smb2_setup_nbt_length(state->vector,
2394 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2395 if (!ok) {
2396 smbd_server_connection_terminate(
2397 xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
2398 return;
2401 /* Ensure we correctly go through crediting. Grant
2402 the credits now, and zero credits on the final
2403 response. */
2404 smb2_set_operation_credit(req->xconn,
2405 SMBD_SMB2_IN_HDR_IOV(req),
2406 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
2409 * We add SMB2_HDR_FLAG_ASYNC after smb2_set_operation_credit()
2410 * as it reacts on it
2412 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
2414 if (DEBUGLVL(10)) {
2415 int i;
2417 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
2418 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
2419 (unsigned int)i,
2420 (unsigned int)ARRAY_SIZE(state->vector),
2421 (unsigned int)state->vector[i].iov_len);
2425 if (req->do_encryption) {
2426 struct smbXsrv_session *x = req->session;
2427 struct smb2_signing_key *encryption_key = x->global->encryption_key;
2429 status = smb2_signing_encrypt_pdu(encryption_key,
2430 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2431 SMBD_SMB2_NUM_IOV_PER_REQ);
2432 if (!NT_STATUS_IS_OK(status)) {
2433 smbd_server_connection_terminate(xconn,
2434 nt_errstr(status));
2435 return;
2439 state->queue_entry.mem_ctx = state;
2440 state->queue_entry.vector = state->vector;
2441 state->queue_entry.count = ARRAY_SIZE(state->vector);
2442 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
2443 xconn->smb2.send_queue_len++;
2445 status = smbd_smb2_flush_send_queue(xconn);
2446 if (!NT_STATUS_IS_OK(status)) {
2447 smbd_server_connection_terminate(xconn,
2448 nt_errstr(status));
2449 return;
2453 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
2455 struct smbXsrv_connection *xconn = req->xconn;
2456 struct smbd_smb2_request *cur;
2457 const uint8_t *inhdr;
2458 uint32_t flags;
2459 uint64_t search_message_id;
2460 uint64_t search_async_id;
2461 uint64_t found_id = 0;
2463 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2465 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2466 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2467 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
2470 * We don't need the request anymore cancel requests never
2471 * have a response.
2473 * We defer the TALLOC_FREE(req) to the caller.
2475 DLIST_REMOVE(xconn->smb2.requests, req);
2477 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
2478 const uint8_t *outhdr;
2479 uint64_t message_id;
2480 uint64_t async_id;
2482 if (cur->session != req->session) {
2483 continue;
2486 if (cur->compound_related) {
2488 * Never cancel anything in a compound request.
2489 * Way too hard to deal with the result.
2491 continue;
2494 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
2496 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
2497 async_id = BVAL(outhdr, SMB2_HDR_PID);
2499 if (flags & SMB2_HDR_FLAG_ASYNC) {
2500 if (search_async_id == async_id) {
2501 found_id = async_id;
2502 break;
2504 } else {
2505 if (search_message_id == message_id) {
2506 found_id = message_id;
2507 break;
2512 if (cur && cur->subreq) {
2513 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
2514 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
2515 "cancel opcode[%s] mid %llu\n",
2516 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
2517 (unsigned long long)found_id ));
2518 tevent_req_cancel(cur->subreq);
2521 return NT_STATUS_OK;
2524 /*************************************************************
2525 Ensure an incoming tid is a valid one for us to access.
2526 Change to the associated uid credentials and chdir to the
2527 valid tid directory.
2528 *************************************************************/
2530 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
2532 const uint8_t *inhdr;
2533 uint32_t in_flags;
2534 uint32_t in_tid;
2535 struct smbXsrv_tcon *tcon;
2536 NTSTATUS status;
2537 NTTIME now = timeval_to_nttime(&req->request_time);
2539 req->tcon = NULL;
2541 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2543 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2544 in_tid = IVAL(inhdr, SMB2_HDR_TID);
2546 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
2547 in_tid = req->last_tid;
2550 req->last_tid = 0;
2552 status = smb2srv_tcon_lookup(req->session,
2553 in_tid, now, &tcon);
2554 if (!NT_STATUS_IS_OK(status)) {
2555 return status;
2558 if (!change_to_user_and_service(
2559 tcon->compat,
2560 req->session->global->session_wire_id))
2562 return NT_STATUS_ACCESS_DENIED;
2565 req->tcon = tcon;
2566 req->last_tid = in_tid;
2568 return NT_STATUS_OK;
2571 /*************************************************************
2572 Ensure an incoming session_id is a valid one for us to access.
2573 *************************************************************/
2575 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
2577 const uint8_t *inhdr;
2578 uint32_t in_flags;
2579 uint16_t in_opcode;
2580 uint64_t in_session_id;
2581 struct smbXsrv_session *session = NULL;
2582 struct auth_session_info *session_info;
2583 NTSTATUS status;
2584 NTTIME now = timeval_to_nttime(&req->request_time);
2586 req->session = NULL;
2587 req->tcon = NULL;
2589 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2591 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2592 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2593 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
2595 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
2596 in_session_id = req->last_session_id;
2599 req->last_session_id = 0;
2601 /* look an existing session up */
2602 switch (in_opcode) {
2603 case SMB2_OP_SESSSETUP:
2605 * For a session bind request, we don't have the
2606 * channel set up at this point yet, so we defer
2607 * the verification that the connection belongs
2608 * to the session to the session setup code, which
2609 * can look at the session binding flags.
2611 status = smb2srv_session_lookup_client(req->xconn->client,
2612 in_session_id, now,
2613 &session);
2614 break;
2615 default:
2616 status = smb2srv_session_lookup_conn(req->xconn,
2617 in_session_id, now,
2618 &session);
2619 break;
2621 if (session) {
2622 req->session = session;
2623 req->last_session_id = in_session_id;
2625 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
2626 switch (in_opcode) {
2627 case SMB2_OP_SESSSETUP:
2628 status = smb2srv_session_lookup_global(req->xconn->client,
2629 in_session_id,
2630 req,
2631 &session);
2632 if (NT_STATUS_IS_OK(status)) {
2634 * We fallback to a session of
2635 * another process in order to
2636 * get the signing correct.
2638 * We don't set req->last_session_id here.
2640 req->session = session;
2642 break;
2643 default:
2644 break;
2647 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
2648 switch (in_opcode) {
2649 case SMB2_OP_SESSSETUP:
2650 status = NT_STATUS_OK;
2651 break;
2652 case SMB2_OP_LOGOFF:
2653 case SMB2_OP_CLOSE:
2654 case SMB2_OP_LOCK:
2655 case SMB2_OP_CANCEL:
2656 case SMB2_OP_KEEPALIVE:
2658 * [MS-SMB2] 3.3.5.2.9 Verifying the Session
2659 * specifies that LOGOFF, CLOSE and (UN)LOCK
2660 * should always be processed even on expired sessions.
2662 * Also see the logic in
2663 * smbd_smb2_request_process_lock().
2665 * The smb2.session.expire2 test shows that
2666 * CANCEL and KEEPALIVE/ECHO should also
2667 * be processed.
2669 status = NT_STATUS_OK;
2670 break;
2671 default:
2672 break;
2675 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2676 switch (in_opcode) {
2677 case SMB2_OP_TCON:
2678 case SMB2_OP_CREATE:
2679 case SMB2_OP_GETINFO:
2680 case SMB2_OP_SETINFO:
2681 return NT_STATUS_INVALID_HANDLE;
2682 default:
2684 * Notice the check for
2685 * (session_info == NULL)
2686 * below.
2688 status = NT_STATUS_OK;
2689 break;
2692 if (!NT_STATUS_IS_OK(status)) {
2693 return status;
2696 session_info = session->global->auth_session_info;
2697 if (session_info == NULL) {
2698 return NT_STATUS_INVALID_HANDLE;
2701 return NT_STATUS_OK;
2704 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
2705 uint32_t data_length)
2707 struct smbXsrv_connection *xconn = req->xconn;
2708 uint16_t needed_charge;
2709 uint16_t credit_charge = 1;
2710 const uint8_t *inhdr;
2712 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2714 if (xconn->smb2.credits.multicredit) {
2715 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
2716 credit_charge = MAX(credit_charge, 1);
2719 needed_charge = (data_length - 1)/ 65536 + 1;
2721 DBGC_DEBUG(DBGC_SMB2_CREDITS,
2722 "mid %llu, CreditCharge: %d, NeededCharge: %d\n",
2723 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
2724 credit_charge, needed_charge);
2726 if (needed_charge > credit_charge) {
2727 DBGC_WARNING(DBGC_SMB2_CREDITS,
2728 "CreditCharge too low, given %d, needed %d\n",
2729 credit_charge, needed_charge);
2730 return NT_STATUS_INVALID_PARAMETER;
2733 return NT_STATUS_OK;
2736 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
2737 size_t expected_body_size)
2739 struct iovec *inhdr_v;
2740 const uint8_t *inhdr;
2741 uint16_t opcode;
2742 const uint8_t *inbody;
2743 size_t body_size;
2744 size_t min_dyn_size = expected_body_size & 0x00000001;
2745 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
2748 * The following should be checked already.
2750 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
2751 return NT_STATUS_INTERNAL_ERROR;
2753 if (req->current_idx > max_idx) {
2754 return NT_STATUS_INTERNAL_ERROR;
2757 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
2758 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
2759 return NT_STATUS_INTERNAL_ERROR;
2761 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
2762 return NT_STATUS_INTERNAL_ERROR;
2765 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2766 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2768 switch (opcode) {
2769 case SMB2_OP_IOCTL:
2770 case SMB2_OP_GETINFO:
2771 case SMB2_OP_WRITE:
2772 min_dyn_size = 0;
2773 break;
2777 * Now check the expected body size,
2778 * where the last byte might be in the
2779 * dynamic section..
2781 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
2782 return NT_STATUS_INVALID_PARAMETER;
2784 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
2785 return NT_STATUS_INVALID_PARAMETER;
2788 inbody = SMBD_SMB2_IN_BODY_PTR(req);
2790 body_size = SVAL(inbody, 0x00);
2791 if (body_size != expected_body_size) {
2792 return NT_STATUS_INVALID_PARAMETER;
2795 return NT_STATUS_OK;
2798 bool smbXsrv_is_encrypted(uint8_t encryption_flags)
2800 return (!(encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)
2802 (encryption_flags & (SMBXSRV_PROCESSED_ENCRYPTED_PACKET |
2803 SMBXSRV_ENCRYPTION_DESIRED |
2804 SMBXSRV_ENCRYPTION_REQUIRED)));
2807 bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags)
2809 return ((encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET) &&
2810 (encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET));
2813 /* Set a flag if not already set, return true if set */
2814 bool smbXsrv_set_crypto_flag(uint8_t *flags, uint8_t flag)
2816 if ((flag == 0) || (*flags & flag)) {
2817 return false;
2820 *flags |= flag;
2821 return true;
2825 * Update encryption state tracking flags, this can be used to
2826 * determine whether whether the session or tcon is "encrypted".
2828 static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
2829 uint16_t opcode,
2830 bool *update_session_globalp,
2831 bool *update_tcon_globalp)
2833 /* Default: assume unecrypted and unsigned */
2834 struct smbXsrv_session *session = req->session;
2835 struct smbXsrv_tcon *tcon = req->tcon;
2836 uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
2837 uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2838 bool update_session = false;
2839 bool update_tcon = false;
2841 if (session->table == NULL) {
2843 * sessions from smb2srv_session_lookup_global()
2844 * have NT_STATUS_BAD_LOGON_SESSION_STATE
2845 * and session->table == NULL.
2847 * They only used to give the correct error
2848 * status, we should not update any state.
2850 goto out;
2853 if (req->was_encrypted && req->do_encryption) {
2854 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
2855 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2856 } else {
2857 /* Unencrypted packet, can be signed */
2858 if (req->do_signing) {
2859 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2863 update_session |= smbXsrv_set_crypto_flag(
2864 &session->global->encryption_flags, encrypt_flag);
2865 update_session |= smbXsrv_set_crypto_flag(
2866 &session->global->signing_flags, sign_flag);
2868 if (tcon) {
2869 update_tcon |= smbXsrv_set_crypto_flag(
2870 &tcon->global->encryption_flags, encrypt_flag);
2871 update_tcon |= smbXsrv_set_crypto_flag(
2872 &tcon->global->signing_flags, sign_flag);
2875 out:
2876 *update_session_globalp = update_session;
2877 *update_tcon_globalp = update_tcon;
2878 return;
2881 bool smbXsrv_is_signed(uint8_t signing_flags)
2884 * Signing is always enabled, so unless we got an unsigned
2885 * packet and at least one signed packet that was not
2886 * encrypted, the session or tcon is "signed".
2888 return (!(signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2889 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2892 bool smbXsrv_is_partially_signed(uint8_t signing_flags)
2894 return ((signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2895 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2898 static NTSTATUS smbd_smb2_request_dispatch_update_counts(
2899 struct smbd_smb2_request *req,
2900 bool modify_call)
2902 struct smbXsrv_connection *xconn = req->xconn;
2903 const uint8_t *inhdr;
2904 uint16_t channel_sequence;
2905 uint8_t generation_wrap = 0;
2906 uint32_t flags;
2907 int cmp;
2908 struct smbXsrv_open *op;
2909 bool update_open = false;
2910 NTSTATUS status = NT_STATUS_OK;
2912 SMB_ASSERT(!req->request_counters_updated);
2914 if (xconn->protocol < PROTOCOL_SMB3_00) {
2915 return NT_STATUS_OK;
2918 if (req->compat_chain_fsp == NULL) {
2919 return NT_STATUS_OK;
2922 op = req->compat_chain_fsp->op;
2923 if (op == NULL) {
2924 return NT_STATUS_OK;
2927 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2928 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2929 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2931 cmp = channel_sequence - op->global->channel_sequence;
2932 if (cmp < 0) {
2934 * csn wrap. We need to watch out for long-running
2935 * requests that are still sitting on a previously
2936 * used csn. SMB2_OP_NOTIFY can take VERY long.
2938 generation_wrap += 1;
2941 if (abs(cmp) > INT16_MAX) {
2943 * [MS-SMB2] 3.3.5.2.10 - Verifying the Channel Sequence Number:
2945 * If the channel sequence number of the request and the one
2946 * known to the server are not equal, the channel sequence
2947 * number and outstanding request counts are only updated
2948 * "... if the unsigned difference using 16-bit arithmetic
2949 * between ChannelSequence and Open.ChannelSequence is less than
2950 * or equal to 0x7FFF ...".
2951 * Otherwise, an error is returned for the modifying
2952 * calls write, set_info, and ioctl.
2954 * There are currently two issues with the description:
2956 * * For the other calls, the document seems to imply
2957 * that processing continues without adapting the
2958 * counters (if the sequence numbers are not equal).
2960 * TODO: This needs clarification!
2962 * * Also, the behaviour if the difference is larger
2963 * than 0x7FFF is not clear. The document seems to
2964 * imply that if such a difference is reached,
2965 * the server starts to ignore the counters or
2966 * in the case of the modifying calls, return errors.
2968 * TODO: This needs clarification!
2970 * At this point Samba tries to be a little more
2971 * clever than the description in the MS-SMB2 document
2972 * by heuristically detecting and properly treating
2973 * a 16 bit overflow of the client-submitted sequence
2974 * number:
2976 * If the stored channel sequence number is more than
2977 * 0x7FFF larger than the one from the request, then
2978 * the client-provided sequence number has likely
2979 * overflown. We treat this case as valid instead
2980 * of as failure.
2982 * The MS-SMB2 behaviour would be setting cmp = -1.
2984 cmp *= -1;
2987 if (flags & SMB2_HDR_FLAG_REPLAY_OPERATION) {
2988 if (cmp == 0 && op->pre_request_count == 0) {
2989 op->request_count += 1;
2990 req->request_counters_updated = true;
2991 } else if (cmp > 0 && op->pre_request_count == 0) {
2992 op->pre_request_count += op->request_count;
2993 op->request_count = 1;
2994 op->global->channel_sequence = channel_sequence;
2995 op->global->channel_generation += generation_wrap;
2996 update_open = true;
2997 req->request_counters_updated = true;
2998 } else if (modify_call) {
2999 return NT_STATUS_FILE_NOT_AVAILABLE;
3001 } else {
3002 if (cmp == 0) {
3003 op->request_count += 1;
3004 req->request_counters_updated = true;
3005 } else if (cmp > 0) {
3006 op->pre_request_count += op->request_count;
3007 op->request_count = 1;
3008 op->global->channel_sequence = channel_sequence;
3009 op->global->channel_generation += generation_wrap;
3010 update_open = true;
3011 req->request_counters_updated = true;
3012 } else if (modify_call) {
3013 return NT_STATUS_FILE_NOT_AVAILABLE;
3016 req->channel_generation = op->global->channel_generation;
3018 if (update_open) {
3019 status = smbXsrv_open_update(op);
3022 return status;
3025 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
3027 struct smbXsrv_connection *xconn = req->xconn;
3028 const struct smbd_smb2_dispatch_table *call = NULL;
3029 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
3030 const uint8_t *inhdr;
3031 uint16_t opcode;
3032 uint32_t flags;
3033 uint64_t mid;
3034 NTSTATUS status;
3035 NTSTATUS session_status;
3036 uint32_t allowed_flags;
3037 NTSTATUS return_value;
3038 struct smbXsrv_session *x = NULL;
3039 bool signing_required = false;
3040 bool encryption_desired = false;
3041 bool encryption_required = false;
3043 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
3045 DO_PROFILE_INC(request);
3047 SMB_ASSERT(!req->request_counters_updated);
3049 /* TODO: verify more things */
3051 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
3052 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
3053 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
3054 DBG_DEBUG("opcode[%s] mid = %"PRIu64"\n",
3055 smb2_opcode_name(opcode),
3056 mid);
3058 if (xconn->protocol >= PROTOCOL_SMB2_02) {
3060 * once the protocol is negotiated
3061 * SMB2_OP_NEGPROT is not allowed anymore
3063 if (opcode == SMB2_OP_NEGPROT) {
3064 /* drop the connection */
3065 return NT_STATUS_INVALID_PARAMETER;
3067 } else {
3069 * if the protocol is not negotiated yet
3070 * only SMB2_OP_NEGPROT is allowed.
3072 if (opcode != SMB2_OP_NEGPROT) {
3073 /* drop the connection */
3074 return NT_STATUS_INVALID_PARAMETER;
3079 * Check if the client provided a valid session id.
3081 * As some command don't require a valid session id
3082 * we defer the check of the session_status
3084 session_status = smbd_smb2_request_check_session(req);
3085 x = req->session;
3086 if (x != NULL) {
3087 signing_required = x->global->signing_flags & SMBXSRV_SIGNING_REQUIRED;
3088 encryption_desired = x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
3089 encryption_required = x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
3092 req->async_internal = false;
3093 req->do_signing = false;
3094 if (opcode != SMB2_OP_SESSSETUP) {
3095 req->do_encryption = encryption_desired;
3096 } else {
3097 req->do_encryption = false;
3099 req->was_encrypted = false;
3100 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
3101 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
3102 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
3104 if (x != NULL && x->global->session_wire_id != tf_session_id) {
3105 DBG_ERR("invalid session_id "
3106 "in SMB2_HDR[%" PRIu64 "], SMB2_TF[%" PRIu64
3107 "]\n",
3108 x->global->session_wire_id,
3109 tf_session_id);
3111 * TODO: windows allows this...
3112 * should we drop the connection?
3114 * For now we just return ACCESS_DENIED
3115 * (Windows clients never trigger this)
3116 * and wait for an update of [MS-SMB2].
3118 return smbd_smb2_request_error(req,
3119 NT_STATUS_ACCESS_DENIED);
3122 req->was_encrypted = true;
3123 req->do_encryption = true;
3126 if (encryption_required && !req->was_encrypted) {
3127 req->do_encryption = true;
3128 return smbd_smb2_request_error(req,
3129 NT_STATUS_ACCESS_DENIED);
3132 call = smbd_smb2_call(opcode);
3133 if (call == NULL) {
3134 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
3137 allowed_flags = SMB2_HDR_FLAG_CHAINED |
3138 SMB2_HDR_FLAG_SIGNED |
3139 SMB2_HDR_FLAG_DFS;
3140 if (xconn->protocol >= PROTOCOL_SMB3_11) {
3141 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
3143 if (opcode == SMB2_OP_NEGPROT) {
3144 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11) {
3145 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
3148 if (opcode == SMB2_OP_CANCEL) {
3149 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
3151 if (xconn->protocol >= PROTOCOL_SMB3_00) {
3152 allowed_flags |= SMB2_HDR_FLAG_REPLAY_OPERATION;
3154 if ((flags & ~allowed_flags) != 0) {
3155 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
3158 if (flags & SMB2_HDR_FLAG_CHAINED) {
3160 * This check is mostly for giving the correct error code
3161 * for compounded requests.
3163 if (!NT_STATUS_IS_OK(session_status)) {
3164 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
3166 } else {
3167 req->compat_chain_fsp = NULL;
3170 if (req->was_encrypted) {
3171 signing_required = false;
3172 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
3173 struct smb2_signing_key *signing_key = NULL;
3174 bool has_channel = false;
3176 if (x == NULL) {
3178 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
3179 * If the SMB2 header of the SMB2 NEGOTIATE
3180 * request has the SMB2_FLAGS_SIGNED bit set in the
3181 * Flags field, the server MUST fail the request
3182 * with STATUS_INVALID_PARAMETER.
3184 * Microsoft test tool checks this.
3187 if ((opcode == SMB2_OP_NEGPROT) &&
3188 (flags & SMB2_HDR_FLAG_SIGNED)) {
3189 status = NT_STATUS_INVALID_PARAMETER;
3190 } else {
3191 status = NT_STATUS_USER_SESSION_DELETED;
3193 return smbd_smb2_request_error(req, status);
3196 signing_key = smbd_smb2_signing_key(x, xconn, &has_channel);
3199 * If we have a signing key, we should
3200 * sign the response
3202 if (smb2_signing_key_valid(signing_key) && opcode != SMB2_OP_CANCEL) {
3203 req->do_signing = true;
3206 status = smb2_signing_check_pdu(signing_key,
3207 SMBD_SMB2_IN_HDR_IOV(req),
3208 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
3209 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
3210 opcode == SMB2_OP_SESSSETUP && !has_channel &&
3211 NT_STATUS_IS_OK(session_status))
3213 if (!NT_STATUS_EQUAL(x->status, NT_STATUS_BAD_LOGON_SESSION_STATE)) {
3214 struct smbXsrv_session *session = NULL;
3215 NTSTATUS error;
3217 error = smb2srv_session_lookup_global(req->xconn->client,
3218 x->global->session_wire_id,
3219 req,
3220 &session);
3221 if (!NT_STATUS_IS_OK(error)) {
3222 return smbd_smb2_request_error(req, error);
3226 * We fallback to a session of
3227 * another process in order to
3228 * get the signing correct.
3230 * We don't set req->last_session_id here.
3232 req->session = x = session;
3234 goto skipped_signing;
3236 if (!NT_STATUS_IS_OK(status)) {
3237 return smbd_smb2_request_error(req, status);
3241 * Now that we know the request was correctly signed
3242 * we have to sign the response too.
3244 if (opcode != SMB2_OP_CANCEL) {
3245 req->do_signing = true;
3248 if (!NT_STATUS_IS_OK(session_status)) {
3249 return smbd_smb2_request_error(req, session_status);
3253 if (opcode == SMB2_OP_IOCTL) {
3255 * Some special IOCTL calls don't require
3256 * file, tcon nor session.
3258 * They typically don't do any real action
3259 * on behalf of the client.
3261 * They are mainly used to alter the behavior
3262 * of the connection for testing. So we can
3263 * run as root and skip all file, tcon and session
3264 * checks below.
3266 static const struct smbd_smb2_dispatch_table _root_ioctl_call = {
3267 .opcode = SMB2_OP_IOCTL,
3268 .as_root = true,
3270 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
3271 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
3272 uint32_t in_ctl_code;
3273 size_t needed = 8;
3275 if (needed > body_size) {
3276 return smbd_smb2_request_error(req,
3277 NT_STATUS_INVALID_PARAMETER);
3280 in_ctl_code = IVAL(body, 0x04);
3282 * Only add trusted IOCTL codes here!
3284 switch (in_ctl_code) {
3285 case FSCTL_SMBTORTURE_FORCE_UNACKED_TIMEOUT:
3286 call = &_root_ioctl_call;
3287 break;
3288 case FSCTL_VALIDATE_NEGOTIATE_INFO:
3289 call = &_root_ioctl_call;
3290 break;
3291 case FSCTL_QUERY_NETWORK_INTERFACE_INFO:
3292 call = &_root_ioctl_call;
3293 break;
3297 skipped_signing:
3299 if (flags & SMB2_HDR_FLAG_CHAINED) {
3300 req->compound_related = true;
3303 if (call->need_session) {
3304 if (!NT_STATUS_IS_OK(session_status)) {
3305 return smbd_smb2_request_error(req, session_status);
3309 if (call->need_tcon) {
3310 SMB_ASSERT(call->need_session);
3313 * This call needs to be run as user.
3315 * smbd_smb2_request_check_tcon()
3316 * calls change_to_user() on success.
3317 * Which implies set_current_user_info()
3318 * and chdir_current_service().
3320 status = smbd_smb2_request_check_tcon(req);
3321 if (!NT_STATUS_IS_OK(status)) {
3322 return smbd_smb2_request_error(req, status);
3324 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
3325 encryption_desired = true;
3327 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
3328 encryption_required = true;
3330 if (encryption_required && !req->was_encrypted) {
3331 req->do_encryption = true;
3332 return smbd_smb2_request_error(req,
3333 NT_STATUS_ACCESS_DENIED);
3334 } else if (encryption_desired) {
3335 req->do_encryption = true;
3337 } else if (call->need_session) {
3338 struct auth_session_info *session_info = NULL;
3341 * Unless we also have need_tcon (see above),
3342 * we still need to call set_current_user_info().
3345 session_info = req->session->global->auth_session_info;
3346 if (session_info == NULL) {
3347 return NT_STATUS_INVALID_HANDLE;
3350 set_current_user_info(session_info->unix_info->sanitized_username,
3351 session_info->unix_info->unix_name,
3352 session_info->info->domain_name);
3355 if (req->session) {
3356 bool update_session_global = false;
3357 bool update_tcon_global = false;
3359 smb2srv_update_crypto_flags(req, opcode,
3360 &update_session_global,
3361 &update_tcon_global);
3363 if (update_session_global) {
3364 status = smbXsrv_session_update(x);
3365 if (!NT_STATUS_IS_OK(status)) {
3366 return smbd_smb2_request_error(req, status);
3369 if (update_tcon_global) {
3370 status = smbXsrv_tcon_update(req->tcon);
3371 if (!NT_STATUS_IS_OK(status)) {
3372 return smbd_smb2_request_error(req, status);
3377 if (call->fileid_ofs != 0) {
3378 size_t needed = call->fileid_ofs + 16;
3379 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
3380 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
3381 uint64_t file_id_persistent;
3382 uint64_t file_id_volatile;
3383 struct files_struct *fsp;
3385 SMB_ASSERT(call->need_tcon);
3387 if (needed > body_size) {
3388 return smbd_smb2_request_error(req,
3389 NT_STATUS_INVALID_PARAMETER);
3392 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
3393 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
3395 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
3396 if (fsp == NULL) {
3397 if (req->compound_related &&
3398 !NT_STATUS_IS_OK(req->compound_create_err))
3400 return smbd_smb2_request_error(req,
3401 req->compound_create_err);
3404 * smbd_smb2_request_process_ioctl()
3405 * has more checks in order to return more
3406 * detailed error codes...
3408 if (opcode != SMB2_OP_IOCTL) {
3409 return smbd_smb2_request_error(req,
3410 NT_STATUS_FILE_CLOSED);
3412 } else {
3413 if (fsp->fsp_flags.encryption_required && !req->was_encrypted) {
3414 return smbd_smb2_request_error(req,
3415 NT_STATUS_ACCESS_DENIED);
3420 status = smbd_smb2_request_dispatch_update_counts(req, call->modify);
3421 if (!NT_STATUS_IS_OK(status)) {
3422 return smbd_smb2_request_error(req, status);
3425 if (call->as_root) {
3426 SMB_ASSERT(call->fileid_ofs == 0);
3427 /* This call needs to be run as root */
3428 change_to_root_user();
3429 } else if (opcode != SMB2_OP_KEEPALIVE) {
3430 SMB_ASSERT(call->need_tcon);
3433 #define _INBYTES(_r) \
3434 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
3436 switch (opcode) {
3437 case SMB2_OP_NEGPROT:
3438 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
3439 req->profile, _INBYTES(req));
3440 return_value = smbd_smb2_request_process_negprot(req);
3441 break;
3443 case SMB2_OP_SESSSETUP:
3444 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
3445 req->profile, _INBYTES(req));
3446 return_value = smbd_smb2_request_process_sesssetup(req);
3447 break;
3449 case SMB2_OP_LOGOFF:
3450 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
3451 req->profile, _INBYTES(req));
3452 return_value = smbd_smb2_request_process_logoff(req);
3453 break;
3455 case SMB2_OP_TCON:
3456 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
3457 req->profile, _INBYTES(req));
3458 return_value = smbd_smb2_request_process_tcon(req);
3459 break;
3461 case SMB2_OP_TDIS:
3462 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
3463 req->profile, _INBYTES(req));
3464 return_value = smbd_smb2_request_process_tdis(req);
3465 break;
3467 case SMB2_OP_CREATE:
3468 if (req->subreq == NULL) {
3469 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
3470 req->profile, _INBYTES(req));
3471 } else {
3472 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
3474 return_value = smbd_smb2_request_process_create(req);
3475 break;
3477 case SMB2_OP_CLOSE:
3478 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
3479 req->profile, _INBYTES(req));
3480 return_value = smbd_smb2_request_process_close(req);
3481 break;
3483 case SMB2_OP_FLUSH:
3484 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
3485 req->profile, _INBYTES(req));
3486 return_value = smbd_smb2_request_process_flush(req);
3487 break;
3489 case SMB2_OP_READ:
3490 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
3491 req->profile, _INBYTES(req));
3492 return_value = smbd_smb2_request_process_read(req);
3493 break;
3495 case SMB2_OP_WRITE:
3496 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
3497 req->profile, _INBYTES(req));
3498 return_value = smbd_smb2_request_process_write(req);
3499 break;
3501 case SMB2_OP_LOCK:
3502 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
3503 req->profile, _INBYTES(req));
3504 return_value = smbd_smb2_request_process_lock(req);
3505 break;
3507 case SMB2_OP_IOCTL:
3508 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
3509 req->profile, _INBYTES(req));
3510 return_value = smbd_smb2_request_process_ioctl(req);
3511 break;
3513 case SMB2_OP_CANCEL:
3514 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
3515 req->profile, _INBYTES(req));
3516 return_value = smbd_smb2_request_process_cancel(req);
3517 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
3520 * We don't need the request anymore cancel requests never
3521 * have a response.
3523 * smbd_smb2_request_process_cancel() already called
3524 * DLIST_REMOVE(xconn->smb2.requests, req);
3526 TALLOC_FREE(req);
3528 break;
3530 case SMB2_OP_KEEPALIVE:
3531 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
3532 req->profile, _INBYTES(req));
3533 return_value = smbd_smb2_request_process_keepalive(req);
3534 break;
3536 case SMB2_OP_QUERY_DIRECTORY:
3537 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
3538 req->profile, _INBYTES(req));
3539 return_value = smbd_smb2_request_process_query_directory(req);
3540 break;
3542 case SMB2_OP_NOTIFY:
3543 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
3544 req->profile, _INBYTES(req));
3545 return_value = smbd_smb2_request_process_notify(req);
3546 break;
3548 case SMB2_OP_GETINFO:
3549 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
3550 req->profile, _INBYTES(req));
3551 return_value = smbd_smb2_request_process_getinfo(req);
3552 break;
3554 case SMB2_OP_SETINFO:
3555 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
3556 req->profile, _INBYTES(req));
3557 return_value = smbd_smb2_request_process_setinfo(req);
3558 break;
3560 case SMB2_OP_BREAK:
3561 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
3562 req->profile, _INBYTES(req));
3563 return_value = smbd_smb2_request_process_break(req);
3564 break;
3566 default:
3567 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
3568 break;
3570 return return_value;
3573 static void smbd_smb2_request_reply_update_counts(struct smbd_smb2_request *req)
3575 struct smbXsrv_connection *xconn = req->xconn;
3576 const uint8_t *inhdr;
3577 uint16_t channel_sequence;
3578 struct smbXsrv_open *op;
3580 if (!req->request_counters_updated) {
3581 return;
3584 req->request_counters_updated = false;
3586 if (xconn->protocol < PROTOCOL_SMB3_00) {
3587 return;
3590 if (req->compat_chain_fsp == NULL) {
3591 return;
3594 op = req->compat_chain_fsp->op;
3595 if (op == NULL) {
3596 return;
3599 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
3600 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
3602 if ((op->global->channel_sequence == channel_sequence) &&
3603 (op->global->channel_generation == req->channel_generation)) {
3604 SMB_ASSERT(op->request_count > 0);
3605 op->request_count -= 1;
3606 } else {
3607 SMB_ASSERT(op->pre_request_count > 0);
3608 op->pre_request_count -= 1;
3612 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
3614 struct smbXsrv_connection *xconn = req->xconn;
3615 int first_idx = 1;
3616 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
3617 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
3618 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
3619 NTSTATUS status;
3620 bool ok;
3622 req->subreq = NULL;
3623 TALLOC_FREE(req->async_te);
3625 /* MS-SMB2: 3.3.4.1 Sending Any Outgoing Message */
3626 smbd_smb2_request_reply_update_counts(req);
3628 if (req->do_encryption &&
3629 (firsttf->iov_len == 0) &&
3630 (!smb2_signing_key_valid(req->first_enc_key)) &&
3631 (req->session != NULL) &&
3632 smb2_signing_key_valid(req->session->global->encryption_key))
3634 struct smb2_signing_key *encryption_key =
3635 req->session->global->encryption_key;
3636 uint8_t *tf;
3637 uint64_t session_id = req->session->global->session_wire_id;
3638 uint64_t nonce_high;
3639 uint64_t nonce_low;
3641 status = smb2_get_new_nonce(req->session,
3642 &nonce_high,
3643 &nonce_low);
3644 if (!NT_STATUS_IS_OK(status)) {
3645 return status;
3649 * We need to place the SMB2_TRANSFORM header before the
3650 * first SMB2 header
3654 * we need to remember the encryption key
3655 * and defer the signing/encryption until
3656 * we are sure that we do not change
3657 * the header again.
3659 status = smb2_signing_key_copy(req,
3660 encryption_key,
3661 &req->first_enc_key);
3662 if (!NT_STATUS_IS_OK(status)) {
3663 return status;
3666 tf = talloc_zero_array(req, uint8_t,
3667 SMB2_TF_HDR_SIZE);
3668 if (tf == NULL) {
3669 return NT_STATUS_NO_MEMORY;
3672 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
3673 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
3674 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
3675 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
3677 firsttf->iov_base = (void *)tf;
3678 firsttf->iov_len = SMB2_TF_HDR_SIZE;
3681 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
3682 (smb2_signing_key_valid(req->last_sign_key)) &&
3683 (firsttf->iov_len == 0))
3685 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
3686 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
3689 * As we are sure the header of the last request in the
3690 * compound chain will not change, we can to sign here
3691 * with the last signing key we remembered.
3693 status = smb2_signing_sign_pdu(req->last_sign_key,
3694 lasthdr,
3695 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
3696 if (!NT_STATUS_IS_OK(status)) {
3697 return status;
3700 TALLOC_FREE(req->last_sign_key);
3702 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
3703 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
3705 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
3707 if (req->current_idx < req->out.vector_count) {
3709 * We must process the remaining compound
3710 * SMB2 requests before any new incoming SMB2
3711 * requests. This is because incoming SMB2
3712 * requests may include a cancel for a
3713 * compound request we haven't processed
3714 * yet.
3716 struct tevent_immediate *im = tevent_create_immediate(req);
3717 if (!im) {
3718 return NT_STATUS_NO_MEMORY;
3721 if (req->do_signing && firsttf->iov_len == 0) {
3722 struct smbXsrv_session *x = req->session;
3723 struct smb2_signing_key *signing_key =
3724 smbd_smb2_signing_key(x, xconn, NULL);
3727 * we need to remember the signing key
3728 * and defer the signing until
3729 * we are sure that we do not change
3730 * the header again.
3732 status = smb2_signing_key_copy(req,
3733 signing_key,
3734 &req->last_sign_key);
3735 if (!NT_STATUS_IS_OK(status)) {
3736 return status;
3741 * smbd_smb2_request_dispatch() will redo the impersonation.
3742 * So we use req->xconn->client->raw_ev_ctx instead
3743 * of req->ev_ctx here.
3745 tevent_schedule_immediate(im,
3746 req->xconn->client->raw_ev_ctx,
3747 smbd_smb2_request_dispatch_immediate,
3748 req);
3749 return NT_STATUS_OK;
3752 if (req->compound_related) {
3753 req->compound_related = false;
3756 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
3757 if (!ok) {
3758 return NT_STATUS_INVALID_PARAMETER_MIX;
3761 /* Set credit for these operations (zero credits if this
3762 is a final reply for an async operation). */
3763 smb2_calculate_credits(req, req);
3766 * now check if we need to sign the current response
3768 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
3769 status = smb2_signing_encrypt_pdu(req->first_enc_key,
3770 firsttf,
3771 req->out.vector_count - first_idx);
3772 if (!NT_STATUS_IS_OK(status)) {
3773 return status;
3775 } else if (req->do_signing) {
3776 struct smbXsrv_session *x = req->session;
3777 struct smb2_signing_key *signing_key =
3778 smbd_smb2_signing_key(x, xconn, NULL);
3780 status = smb2_signing_sign_pdu(signing_key,
3781 outhdr,
3782 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
3783 if (!NT_STATUS_IS_OK(status)) {
3784 return status;
3787 TALLOC_FREE(req->first_enc_key);
3789 if (req->preauth != NULL) {
3790 gnutls_hash_hd_t hash_hnd = NULL;
3791 size_t i;
3792 int rc;
3794 rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_SHA512);
3795 if (rc < 0) {
3796 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3798 rc = gnutls_hash(hash_hnd,
3799 req->preauth->sha512_value,
3800 sizeof(req->preauth->sha512_value));
3801 if (rc < 0) {
3802 gnutls_hash_deinit(hash_hnd, NULL);
3803 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3805 for (i = 1; i < req->in.vector_count; i++) {
3806 rc = gnutls_hash(hash_hnd,
3807 req->in.vector[i].iov_base,
3808 req->in.vector[i].iov_len);
3809 if (rc < 0) {
3810 gnutls_hash_deinit(hash_hnd, NULL);
3811 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3814 gnutls_hash_output(hash_hnd, req->preauth->sha512_value);
3816 rc = gnutls_hash(hash_hnd,
3817 req->preauth->sha512_value,
3818 sizeof(req->preauth->sha512_value));
3819 if (rc < 0) {
3820 gnutls_hash_deinit(hash_hnd, NULL);
3821 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3823 for (i = 1; i < req->out.vector_count; i++) {
3824 rc = gnutls_hash(hash_hnd,
3825 req->out.vector[i].iov_base,
3826 req->out.vector[i].iov_len);
3827 if (rc < 0) {
3828 gnutls_hash_deinit(hash_hnd, NULL);
3829 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3833 gnutls_hash_deinit(hash_hnd, req->preauth->sha512_value);
3835 req->preauth = NULL;
3838 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
3839 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
3840 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
3841 /* Dynamic part is NULL. Chop it off,
3842 We're going to send it via sendfile. */
3843 req->out.vector_count -= 1;
3847 * We're done with this request -
3848 * move it off the "being processed" queue.
3850 DLIST_REMOVE(xconn->smb2.requests, req);
3852 req->queue_entry.mem_ctx = req;
3853 req->queue_entry.vector = req->out.vector;
3854 req->queue_entry.count = req->out.vector_count;
3855 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry);
3856 xconn->smb2.send_queue_len++;
3858 status = smbd_smb2_flush_send_queue(xconn);
3859 if (!NT_STATUS_IS_OK(status)) {
3860 return status;
3863 return NT_STATUS_OK;
3866 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
3868 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
3869 struct tevent_immediate *im,
3870 void *private_data)
3872 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
3873 struct smbd_smb2_request);
3874 struct smbXsrv_connection *xconn = req->xconn;
3875 NTSTATUS status;
3877 TALLOC_FREE(im);
3879 if (DEBUGLEVEL >= 10) {
3880 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
3881 req->current_idx, req->in.vector_count));
3882 print_req_vectors(req);
3885 status = smbd_smb2_request_dispatch(req);
3886 if (!NT_STATUS_IS_OK(status)) {
3887 smbd_server_connection_terminate(xconn, nt_errstr(status));
3888 return;
3891 status = smbd_smb2_request_next_incoming(xconn);
3892 if (!NT_STATUS_IS_OK(status)) {
3893 smbd_server_connection_terminate(xconn, nt_errstr(status));
3894 return;
3898 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
3899 NTSTATUS status,
3900 DATA_BLOB body, DATA_BLOB *dyn,
3901 const char *location)
3903 uint8_t *outhdr;
3904 struct iovec *outbody_v;
3905 struct iovec *outdyn_v;
3906 uint32_t next_command_ofs;
3907 uint64_t mid;
3909 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3910 mid = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
3912 DBG_DEBUG("mid [%"PRIu64"] idx[%d] status[%s] "
3913 "body[%u] dyn[%s:%u] at %s\n",
3914 mid,
3915 req->current_idx,
3916 nt_errstr(status),
3917 (unsigned int)body.length,
3918 dyn ? "yes" : "no",
3919 (unsigned int)(dyn ? dyn->length : 0),
3920 location);
3922 if (body.length < 2) {
3923 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3926 if ((body.length % 2) != 0) {
3927 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3930 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
3931 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
3933 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
3934 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
3936 outbody_v->iov_base = (void *)body.data;
3937 outbody_v->iov_len = body.length;
3939 if (dyn) {
3940 outdyn_v->iov_base = (void *)dyn->data;
3941 outdyn_v->iov_len = dyn->length;
3942 } else {
3943 outdyn_v->iov_base = NULL;
3944 outdyn_v->iov_len = 0;
3948 * See if we need to recalculate the offset to the next response
3950 * Note that all responses may require padding (including the very last
3951 * one).
3953 if (req->out.vector_count >= (2 * SMBD_SMB2_NUM_IOV_PER_REQ)) {
3954 next_command_ofs = SMB2_HDR_BODY;
3955 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
3956 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
3959 if ((next_command_ofs % 8) != 0) {
3960 size_t pad_size = 8 - (next_command_ofs % 8);
3961 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
3963 * if the dyn buffer is empty
3964 * we can use it to add padding
3966 uint8_t *pad;
3968 pad = talloc_zero_array(req,
3969 uint8_t, pad_size);
3970 if (pad == NULL) {
3971 return smbd_smb2_request_error(req,
3972 NT_STATUS_NO_MEMORY);
3975 outdyn_v->iov_base = (void *)pad;
3976 outdyn_v->iov_len = pad_size;
3977 } else {
3979 * For now we copy the dynamic buffer
3980 * and add the padding to the new buffer
3982 size_t old_size;
3983 uint8_t *old_dyn;
3984 size_t new_size;
3985 uint8_t *new_dyn;
3987 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
3988 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
3990 new_size = old_size + pad_size;
3991 new_dyn = talloc_zero_array(req,
3992 uint8_t, new_size);
3993 if (new_dyn == NULL) {
3994 return smbd_smb2_request_error(req,
3995 NT_STATUS_NO_MEMORY);
3998 memcpy(new_dyn, old_dyn, old_size);
3999 memset(new_dyn + old_size, 0, pad_size);
4001 outdyn_v->iov_base = (void *)new_dyn;
4002 outdyn_v->iov_len = new_size;
4004 next_command_ofs += pad_size;
4007 if ((req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) >= req->out.vector_count) {
4008 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
4009 } else {
4010 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
4012 return smbd_smb2_request_reply(req);
4015 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
4016 NTSTATUS status,
4017 uint8_t error_context_count,
4018 DATA_BLOB *info,
4019 const char *location)
4021 struct smbXsrv_connection *xconn = req->xconn;
4022 DATA_BLOB body;
4023 DATA_BLOB _dyn;
4024 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
4025 size_t unread_bytes = smbd_smb2_unread_bytes(req);
4027 DBG_NOTICE("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| "
4028 "at %s\n", req->current_idx, nt_errstr(status),
4029 info ? " +info" : "", location);
4031 if (unread_bytes) {
4032 /* Recvfile error. Drain incoming socket. */
4033 size_t ret;
4035 errno = 0;
4036 ret = drain_socket(xconn->transport.sock, unread_bytes);
4037 if (ret != unread_bytes) {
4038 NTSTATUS error;
4040 if (errno == 0) {
4041 error = NT_STATUS_IO_DEVICE_ERROR;
4042 } else {
4043 error = map_nt_error_from_unix_common(errno);
4046 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
4047 "ret[%u] errno[%d] => %s\n",
4048 (unsigned)unread_bytes,
4049 (unsigned)ret, errno, nt_errstr(error)));
4050 return error;
4054 body.data = outhdr + SMB2_HDR_BODY;
4055 body.length = 8;
4056 SSVAL(body.data, 0, 9);
4057 SCVAL(body.data, 2, error_context_count);
4059 if (info) {
4060 SIVAL(body.data, 0x04, info->length);
4061 } else {
4062 /* Allocated size of req->out.vector[i].iov_base
4063 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
4064 * 1 byte without having to do an alloc.
4066 info = &_dyn;
4067 info->data = ((uint8_t *)outhdr) +
4068 OUTVEC_ALLOC_SIZE - 1;
4069 info->length = 1;
4070 SCVAL(info->data, 0, 0);
4074 * Note: Even if there is an error, continue to process the request.
4075 * per MS-SMB2.
4078 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
4081 struct smbd_smb2_break_state {
4082 struct tevent_req *req;
4083 struct smbd_smb2_send_queue queue_entry;
4084 uint8_t nbt_hdr[NBT_HDR_SIZE];
4085 uint8_t hdr[SMB2_HDR_BODY];
4086 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
4089 static struct tevent_req *smbd_smb2_break_send(TALLOC_CTX *mem_ctx,
4090 struct tevent_context *ev,
4091 struct smbXsrv_connection *xconn,
4092 uint64_t session_id,
4093 const uint8_t *body,
4094 size_t body_len)
4096 struct tevent_req *req = NULL;
4097 struct smbd_smb2_break_state *state = NULL;
4098 NTSTATUS status;
4099 bool ok;
4101 req = tevent_req_create(mem_ctx, &state,
4102 struct smbd_smb2_break_state);
4103 if (req == NULL) {
4104 return NULL;
4107 state->req = req;
4108 tevent_req_defer_callback(req, ev);
4110 SIVAL(state->hdr, 0, SMB2_MAGIC);
4111 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
4112 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
4113 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
4114 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
4115 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
4116 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
4117 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
4118 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
4119 SIVAL(state->hdr, SMB2_HDR_PID, 0);
4120 SIVAL(state->hdr, SMB2_HDR_TID, 0);
4121 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, session_id);
4122 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
4124 state->vector[0] = (struct iovec) {
4125 .iov_base = state->nbt_hdr,
4126 .iov_len = sizeof(state->nbt_hdr)
4129 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
4130 .iov_base = NULL,
4131 .iov_len = 0
4134 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
4135 .iov_base = state->hdr,
4136 .iov_len = sizeof(state->hdr)
4139 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
4140 .iov_base = discard_const_p(uint8_t, body),
4141 .iov_len = body_len,
4145 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
4148 ok = smb2_setup_nbt_length(state->vector,
4149 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
4150 if (!ok) {
4151 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
4152 return tevent_req_post(req, ev);
4156 * We require TCP acks for this PDU to the client!
4157 * We want 5 retransmissions and timeout when the
4158 * retransmission timeout (rto) passed 6 times.
4160 * required_acked_bytes gets a dummy value of
4161 * UINT64_MAX, as long it's in xconn->smb2.send_queue,
4162 * it'll get the real value when it's moved to
4163 * xconn->ack.queue.
4165 * state->queue_entry.ack.req gets completed with
4166 * 1. tevent_req_done(), when all bytes are acked.
4167 * 2a. tevent_req_nterror(NT_STATUS_IO_TIMEOUT), when
4168 * the timeout expired before all bytes were acked.
4169 * 2b. tevent_req_nterror(transport_error), when the
4170 * connection got a disconnect from the kernel.
4172 state->queue_entry.ack.timeout =
4173 timeval_current_ofs_usec(xconn->ack.rto_usecs * 6);
4174 state->queue_entry.ack.required_acked_bytes = UINT64_MAX;
4175 state->queue_entry.ack.req = req;
4176 state->queue_entry.mem_ctx = state;
4177 state->queue_entry.vector = state->vector;
4178 state->queue_entry.count = ARRAY_SIZE(state->vector);
4179 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
4180 xconn->smb2.send_queue_len++;
4182 status = smbd_smb2_flush_send_queue(xconn);
4183 if (tevent_req_nterror(req, status)) {
4184 return tevent_req_post(req, ev);
4187 return req;
4190 static NTSTATUS smbd_smb2_break_recv(struct tevent_req *req)
4192 return tevent_req_simple_recv_ntstatus(req);
4195 struct smbXsrv_pending_break {
4196 struct smbXsrv_pending_break *prev, *next;
4197 struct smbXsrv_client *client;
4198 bool disable_oplock_break_retries;
4199 uint64_t session_id;
4200 uint64_t last_channel_id;
4201 union {
4202 uint8_t generic[1];
4203 uint8_t oplock[0x18];
4204 uint8_t lease[0x2c];
4205 } body;
4206 size_t body_len;
4209 static void smbXsrv_pending_break_done(struct tevent_req *subreq);
4211 static struct smbXsrv_pending_break *smbXsrv_pending_break_create(
4212 struct smbXsrv_client *client,
4213 uint64_t session_id)
4215 struct smbXsrv_pending_break *pb = NULL;
4217 pb = talloc_zero(client, struct smbXsrv_pending_break);
4218 if (pb == NULL) {
4219 return NULL;
4221 pb->client = client;
4222 pb->session_id = session_id;
4223 pb->disable_oplock_break_retries = lp_smb2_disable_oplock_break_retry();
4225 return pb;
4228 static NTSTATUS smbXsrv_pending_break_submit(struct smbXsrv_pending_break *pb);
4230 static NTSTATUS smbXsrv_pending_break_schedule(struct smbXsrv_pending_break *pb)
4232 struct smbXsrv_client *client = pb->client;
4233 NTSTATUS status;
4235 DLIST_ADD_END(client->pending_breaks, pb);
4236 status = smbXsrv_client_pending_breaks_updated(client);
4237 if (!NT_STATUS_IS_OK(status)) {
4238 return status;
4241 status = smbXsrv_pending_break_submit(pb);
4242 if (!NT_STATUS_IS_OK(status)) {
4243 return status;
4246 return NT_STATUS_OK;
4249 static NTSTATUS smbXsrv_pending_break_submit(struct smbXsrv_pending_break *pb)
4251 struct smbXsrv_client *client = pb->client;
4252 struct smbXsrv_session *session = NULL;
4253 struct smbXsrv_connection *xconn = NULL;
4254 struct smbXsrv_connection *oplock_xconn = NULL;
4255 struct tevent_req *subreq = NULL;
4256 NTSTATUS status;
4258 if (pb->session_id != 0) {
4259 status = get_valid_smbXsrv_session(client,
4260 pb->session_id,
4261 &session);
4262 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
4263 return NT_STATUS_ABANDONED;
4265 if (!NT_STATUS_IS_OK(status)) {
4266 return status;
4269 if (pb->last_channel_id != 0) {
4271 * This is what current Windows servers
4272 * do, they don't retry on all available
4273 * channels. They only use the last channel.
4275 * But it doesn't match the specification in
4276 * [MS-SMB2] "3.3.4.6 Object Store Indicates an
4277 * Oplock Break"
4279 * Per default disable_oplock_break_retries is false
4280 * and we behave like the specification.
4282 if (pb->disable_oplock_break_retries) {
4283 return NT_STATUS_ABANDONED;
4288 for (xconn = client->connections; xconn != NULL; xconn = xconn->next) {
4289 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
4290 continue;
4293 if (xconn->channel_id == 0) {
4295 * non-multichannel case
4297 break;
4300 if (session != NULL) {
4301 struct smbXsrv_channel_global0 *c = NULL;
4304 * Having a session means we're handling
4305 * an oplock break and we only need to
4306 * use channels available on the
4307 * session.
4309 status = smbXsrv_session_find_channel(session, xconn, &c);
4310 if (!NT_STATUS_IS_OK(status)) {
4311 continue;
4315 * This is what current Windows servers
4316 * do, they don't retry on all available
4317 * channels. They only use the last channel.
4319 * But it doesn't match the specification
4320 * in [MS-SMB2] "3.3.4.6 Object Store Indicates an
4321 * Oplock Break"
4323 * Per default disable_oplock_break_retries is false
4324 * and we behave like the specification.
4326 if (pb->disable_oplock_break_retries) {
4327 oplock_xconn = xconn;
4328 continue;
4332 if (xconn->channel_id > pb->last_channel_id) {
4334 * multichannel case
4336 break;
4340 if (xconn == NULL) {
4341 xconn = oplock_xconn;
4344 if (xconn == NULL) {
4346 * If there's no remaining connection available
4347 * tell the caller to stop...
4349 return NT_STATUS_ABANDONED;
4352 pb->last_channel_id = xconn->channel_id;
4354 subreq = smbd_smb2_break_send(pb,
4355 client->raw_ev_ctx,
4356 xconn,
4357 pb->session_id,
4358 pb->body.generic,
4359 pb->body_len);
4360 if (subreq == NULL) {
4361 return NT_STATUS_NO_MEMORY;
4363 tevent_req_set_callback(subreq,
4364 smbXsrv_pending_break_done,
4365 pb);
4367 return NT_STATUS_OK;
4370 static void smbXsrv_pending_break_done(struct tevent_req *subreq)
4372 struct smbXsrv_pending_break *pb =
4373 tevent_req_callback_data(subreq,
4374 struct smbXsrv_pending_break);
4375 struct smbXsrv_client *client = pb->client;
4376 NTSTATUS status;
4378 status = smbd_smb2_break_recv(subreq);
4379 TALLOC_FREE(subreq);
4380 if (!NT_STATUS_IS_OK(status)) {
4381 status = smbXsrv_pending_break_submit(pb);
4382 if (NT_STATUS_EQUAL(status, NT_STATUS_ABANDONED)) {
4384 * If there's no remaining connection
4385 * there's no need to send a break again.
4387 goto remove;
4389 if (!NT_STATUS_IS_OK(status)) {
4390 smbd_server_disconnect_client(client, nt_errstr(status));
4391 return;
4393 return;
4396 remove:
4397 DLIST_REMOVE(client->pending_breaks, pb);
4398 TALLOC_FREE(pb);
4400 status = smbXsrv_client_pending_breaks_updated(client);
4401 if (!NT_STATUS_IS_OK(status)) {
4402 smbd_server_disconnect_client(client, nt_errstr(status));
4403 return;
4407 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_client *client,
4408 struct smbXsrv_open *op,
4409 uint8_t oplock_level)
4411 struct smbXsrv_pending_break *pb = NULL;
4412 uint8_t *body = NULL;
4414 pb = smbXsrv_pending_break_create(client,
4415 op->compat->vuid);
4416 if (pb == NULL) {
4417 return NT_STATUS_NO_MEMORY;
4419 pb->body_len = sizeof(pb->body.oplock);
4420 body = pb->body.oplock;
4422 SSVAL(body, 0x00, pb->body_len);
4423 SCVAL(body, 0x02, oplock_level);
4424 SCVAL(body, 0x03, 0); /* reserved */
4425 SIVAL(body, 0x04, 0); /* reserved */
4426 SBVAL(body, 0x08, op->global->open_persistent_id);
4427 SBVAL(body, 0x10, op->global->open_volatile_id);
4429 return smbXsrv_pending_break_schedule(pb);
4432 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_client *client,
4433 uint16_t new_epoch,
4434 uint32_t lease_flags,
4435 struct smb2_lease_key *lease_key,
4436 uint32_t current_lease_state,
4437 uint32_t new_lease_state)
4439 struct smbXsrv_pending_break *pb = NULL;
4440 uint8_t *body = NULL;
4442 pb = smbXsrv_pending_break_create(client,
4443 0); /* no session_id */
4444 if (pb == NULL) {
4445 return NT_STATUS_NO_MEMORY;
4447 pb->body_len = sizeof(pb->body.lease);
4448 body = pb->body.lease;
4450 SSVAL(body, 0x00, pb->body_len);
4451 SSVAL(body, 0x02, new_epoch);
4452 SIVAL(body, 0x04, lease_flags);
4453 SBVAL(body, 0x08, lease_key->data[0]);
4454 SBVAL(body, 0x10, lease_key->data[1]);
4455 SIVAL(body, 0x18, current_lease_state);
4456 SIVAL(body, 0x1c, new_lease_state);
4457 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
4458 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
4459 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
4461 return smbXsrv_pending_break_schedule(pb);
4464 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
4466 NTSTATUS status;
4467 uint32_t flags;
4468 uint64_t file_id_persistent;
4469 uint64_t file_id_volatile;
4470 struct smbXsrv_open *op = NULL;
4471 struct files_struct *fsp = NULL;
4472 const uint8_t *body = NULL;
4475 * This is only called with a pktbuf
4476 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
4477 * bytes
4480 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
4481 /* Transform header. Cannot recvfile. */
4482 return false;
4484 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
4485 /* Not SMB2. Normal error path will cope. */
4486 return false;
4488 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
4489 /* Not SMB2. Normal error path will cope. */
4490 return false;
4492 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
4493 /* Needs to be a WRITE. */
4494 return false;
4496 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
4497 /* Chained. Cannot recvfile. */
4498 return false;
4500 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
4501 if (flags & SMB2_HDR_FLAG_CHAINED) {
4502 /* Chained. Cannot recvfile. */
4503 return false;
4505 if (flags & SMB2_HDR_FLAG_SIGNED) {
4506 /* Signed. Cannot recvfile. */
4507 return false;
4510 body = &state->pktbuf[SMB2_HDR_BODY];
4512 file_id_persistent = BVAL(body, 0x10);
4513 file_id_volatile = BVAL(body, 0x18);
4515 status = smb2srv_open_lookup(state->req->xconn,
4516 file_id_persistent,
4517 file_id_volatile,
4518 0, /* now */
4519 &op);
4520 if (!NT_STATUS_IS_OK(status)) {
4521 return false;
4524 fsp = op->compat;
4525 if (fsp == NULL) {
4526 return false;
4528 if (fsp->conn == NULL) {
4529 return false;
4532 if (IS_IPC(fsp->conn)) {
4533 return false;
4535 if (IS_PRINT(fsp->conn)) {
4536 return false;
4538 if (fsp_is_alternate_stream(fsp)) {
4539 return false;
4542 DEBUG(10,("Doing recvfile write len = %u\n",
4543 (unsigned int)(state->pktfull - state->pktlen)));
4545 return true;
4548 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
4550 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
4551 struct smbd_smb2_request *req = NULL;
4552 size_t max_send_queue_len;
4553 size_t cur_send_queue_len;
4555 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
4557 * we're not supposed to do any io
4559 return NT_STATUS_OK;
4562 if (state->req != NULL) {
4564 * if there is already a tstream_readv_pdu
4565 * pending, we are done.
4567 return NT_STATUS_OK;
4570 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
4571 cur_send_queue_len = xconn->smb2.send_queue_len;
4573 if (cur_send_queue_len > max_send_queue_len) {
4575 * if we have a lot of requests to send,
4576 * we wait until they are on the wire until we
4577 * ask for the next request.
4579 return NT_STATUS_OK;
4582 /* ask for the next request */
4583 req = smbd_smb2_request_allocate(xconn);
4584 if (req == NULL) {
4585 return NT_STATUS_NO_MEMORY;
4587 *state = (struct smbd_smb2_request_read_state) {
4588 .req = req,
4589 .min_recv_size = lp_min_receive_file_size(),
4590 ._vector = {
4591 [0] = (struct iovec) {
4592 .iov_base = (void *)state->hdr.nbt,
4593 .iov_len = NBT_HDR_SIZE,
4596 .vector = state->_vector,
4597 .count = 1,
4600 TEVENT_FD_READABLE(xconn->transport.fde);
4602 return NT_STATUS_OK;
4605 NTSTATUS smbd_smb2_process_negprot(struct smbXsrv_connection *xconn,
4606 uint64_t expected_seq_low,
4607 const uint8_t *inpdu, size_t size)
4609 struct smbd_server_connection *sconn = xconn->client->sconn;
4610 NTSTATUS status;
4611 struct smbd_smb2_request *req = NULL;
4613 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
4614 (unsigned int)size));
4616 status = smbd_initialize_smb2(xconn, expected_seq_low);
4617 if (!NT_STATUS_IS_OK(status)) {
4618 smbd_server_connection_terminate(xconn, nt_errstr(status));
4619 return status;
4623 * If a new connection joins the process, when we're
4624 * already in a "pending break cycle", we need to
4625 * turn on the ack checker on the new connection.
4627 status = smbXsrv_client_pending_breaks_updated(xconn->client);
4628 if (!NT_STATUS_IS_OK(status)) {
4630 * If there's a problem, we disconnect the whole
4631 * client with all connections here!
4633 * Instead of just the new connection.
4635 smbd_server_disconnect_client(xconn->client, nt_errstr(status));
4636 return status;
4639 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
4640 if (!NT_STATUS_IS_OK(status)) {
4641 smbd_server_connection_terminate(xconn, nt_errstr(status));
4642 return status;
4645 status = smbd_smb2_request_validate(req);
4646 if (!NT_STATUS_IS_OK(status)) {
4647 smbd_server_connection_terminate(xconn, nt_errstr(status));
4648 return status;
4651 status = smbd_smb2_request_setup_out(req);
4652 if (!NT_STATUS_IS_OK(status)) {
4653 smbd_server_connection_terminate(xconn, nt_errstr(status));
4654 return status;
4657 #ifdef WITH_PROFILE
4659 * this was already counted at the SMB1 layer =>
4660 * smbd_smb2_request_dispatch() should not count it twice.
4662 if (profile_p->values.request_stats.count > 0) {
4663 profile_p->values.request_stats.count--;
4665 #endif
4666 status = smbd_smb2_request_dispatch(req);
4667 if (!NT_STATUS_IS_OK(status)) {
4668 smbd_server_connection_terminate(xconn, nt_errstr(status));
4669 return status;
4672 status = smbd_smb2_request_next_incoming(xconn);
4673 if (!NT_STATUS_IS_OK(status)) {
4674 smbd_server_connection_terminate(xconn, nt_errstr(status));
4675 return status;
4678 sconn->num_requests++;
4679 return NT_STATUS_OK;
4682 static int socket_error_from_errno(int ret,
4683 int sys_errno,
4684 bool *retry)
4686 *retry = false;
4688 if (ret >= 0) {
4689 return 0;
4692 if (ret != -1) {
4693 return EIO;
4696 if (sys_errno == 0) {
4697 return EIO;
4700 if (sys_errno == EINTR) {
4701 *retry = true;
4702 return sys_errno;
4705 if (sys_errno == EINPROGRESS) {
4706 *retry = true;
4707 return sys_errno;
4710 if (sys_errno == EAGAIN) {
4711 *retry = true;
4712 return sys_errno;
4715 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
4716 if (sys_errno == ENOMEM) {
4717 *retry = true;
4718 return sys_errno;
4721 #ifdef EWOULDBLOCK
4722 #if EWOULDBLOCK != EAGAIN
4723 if (sys_errno == EWOULDBLOCK) {
4724 *retry = true;
4725 return sys_errno;
4727 #endif
4728 #endif
4730 return sys_errno;
4733 static NTSTATUS smbd_smb2_advance_send_queue(struct smbXsrv_connection *xconn,
4734 struct smbd_smb2_send_queue **_e,
4735 size_t n)
4737 struct smbd_smb2_send_queue *e = *_e;
4738 bool ok;
4740 xconn->ack.unacked_bytes += n;
4742 ok = iov_advance(&e->vector, &e->count, n);
4743 if (!ok) {
4744 return NT_STATUS_INTERNAL_ERROR;
4747 if (e->count > 0) {
4748 return NT_STATUS_RETRY;
4751 xconn->smb2.send_queue_len--;
4752 DLIST_REMOVE(xconn->smb2.send_queue, e);
4754 if (e->ack.req == NULL) {
4755 *_e = NULL;
4756 talloc_free(e->mem_ctx);
4757 return NT_STATUS_OK;
4760 e->ack.required_acked_bytes = xconn->ack.unacked_bytes;
4761 DLIST_ADD_END(xconn->ack.queue, e);
4763 return NT_STATUS_OK;
4766 static NTSTATUS smbd_smb2_flush_with_sendmsg(struct smbXsrv_connection *xconn)
4768 int ret;
4769 int err;
4770 bool retry;
4771 NTSTATUS status;
4773 if (xconn->smb2.send_queue == NULL) {
4774 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
4775 return NT_STATUS_OK;
4778 while (xconn->smb2.send_queue != NULL) {
4779 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
4780 unsigned sendmsg_flags = 0;
4782 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
4784 * we're not supposed to do any io
4785 * just flush all pending stuff.
4787 xconn->smb2.send_queue_len--;
4788 DLIST_REMOVE(xconn->smb2.send_queue, e);
4790 talloc_free(e->mem_ctx);
4791 continue;
4794 if (e->sendfile_header != NULL) {
4795 size_t size = 0;
4796 size_t i = 0;
4797 uint8_t *buf;
4799 status = NT_STATUS_INTERNAL_ERROR;
4801 for (i=0; i < e->count; i++) {
4802 size += e->vector[i].iov_len;
4805 if (size <= e->sendfile_header->length) {
4806 buf = e->sendfile_header->data;
4807 } else {
4808 buf = talloc_array(e->mem_ctx, uint8_t, size);
4809 if (buf == NULL) {
4810 return NT_STATUS_NO_MEMORY;
4814 size = 0;
4815 for (i=0; i < e->count; i++) {
4816 memcpy(buf+size,
4817 e->vector[i].iov_base,
4818 e->vector[i].iov_len);
4819 size += e->vector[i].iov_len;
4822 e->sendfile_header->data = buf;
4823 e->sendfile_header->length = size;
4824 e->sendfile_status = &status;
4825 e->count = 0;
4827 xconn->smb2.send_queue_len--;
4828 DLIST_REMOVE(xconn->smb2.send_queue, e);
4830 size += e->sendfile_body_size;
4833 * This triggers the sendfile path via
4834 * the destructor.
4836 talloc_free(e->mem_ctx);
4838 if (!NT_STATUS_IS_OK(status)) {
4839 smbXsrv_connection_disconnect_transport(xconn,
4840 status);
4841 return status;
4843 xconn->ack.unacked_bytes += size;
4844 continue;
4847 e->msg = (struct msghdr) {
4848 .msg_iov = e->vector,
4849 .msg_iovlen = e->count,
4852 #ifdef MSG_NOSIGNAL
4853 sendmsg_flags |= MSG_NOSIGNAL;
4854 #endif
4855 #ifdef MSG_DONTWAIT
4856 sendmsg_flags |= MSG_DONTWAIT;
4857 #endif
4859 ret = sendmsg(xconn->transport.sock, &e->msg, sendmsg_flags);
4860 if (ret == 0) {
4861 /* propagate end of file */
4862 return NT_STATUS_INTERNAL_ERROR;
4864 err = socket_error_from_errno(ret, errno, &retry);
4865 if (retry) {
4866 /* retry later */
4867 TEVENT_FD_WRITEABLE(xconn->transport.fde);
4868 return NT_STATUS_OK;
4870 if (err != 0) {
4871 status = map_nt_error_from_unix_common(err);
4872 smbXsrv_connection_disconnect_transport(xconn,
4873 status);
4874 return status;
4877 status = smbd_smb2_advance_send_queue(xconn, &e, ret);
4878 if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4879 /* retry later */
4880 TEVENT_FD_WRITEABLE(xconn->transport.fde);
4881 return NT_STATUS_OK;
4883 if (!NT_STATUS_IS_OK(status)) {
4884 smbXsrv_connection_disconnect_transport(xconn,
4885 status);
4886 return status;
4890 return NT_STATUS_MORE_PROCESSING_REQUIRED;
4893 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
4895 NTSTATUS status;
4897 status = smbd_smb2_flush_with_sendmsg(xconn);
4898 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
4899 return status;
4903 * Restart reads if we were blocked on
4904 * draining the send queue.
4907 status = smbd_smb2_request_next_incoming(xconn);
4908 if (!NT_STATUS_IS_OK(status)) {
4909 return status;
4912 return NT_STATUS_OK;
4915 static NTSTATUS smbd_smb2_advance_incoming(struct smbXsrv_connection *xconn, size_t n)
4917 struct smbd_server_connection *sconn = xconn->client->sconn;
4918 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
4919 struct smbd_smb2_request *req = NULL;
4920 size_t min_recvfile_size = UINT32_MAX;
4921 NTSTATUS status;
4922 NTTIME now;
4923 bool ok;
4925 ok = iov_advance(&state->vector, &state->count, n);
4926 if (!ok) {
4927 return NT_STATUS_INTERNAL_ERROR;
4930 if (state->count > 0) {
4931 return NT_STATUS_PENDING;
4934 if (state->pktlen > 0) {
4935 if (!state->doing_receivefile) {
4937 * we have all the data.
4939 goto got_full;
4942 if (!is_smb2_recvfile_write(state)) {
4943 size_t ofs = state->pktlen;
4946 * Not a possible receivefile write.
4947 * Read the rest of the data.
4949 state->doing_receivefile = false;
4951 state->pktbuf = talloc_realloc(state->req,
4952 state->pktbuf,
4953 uint8_t,
4954 state->pktfull);
4955 if (state->pktbuf == NULL) {
4956 return NT_STATUS_NO_MEMORY;
4959 state->_vector[0] = (struct iovec) {
4960 .iov_base = (void *)(state->pktbuf + ofs),
4961 .iov_len = (state->pktfull - ofs),
4963 state->vector = state->_vector;
4964 state->count = 1;
4966 state->pktlen = state->pktfull;
4967 return NT_STATUS_RETRY;
4971 * This is a receivefile write so we've
4972 * done a short read.
4974 goto got_full;
4978 * Now we analyze the NBT header
4980 if (state->hdr.nbt[0] != 0x00) {
4981 state->min_recv_size = 0;
4983 state->pktfull = smb2_len(state->hdr.nbt);
4984 if (state->pktfull == 0) {
4985 goto got_full;
4988 if (state->min_recv_size != 0) {
4989 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
4990 min_recvfile_size += state->min_recv_size;
4993 if (state->pktfull > min_recvfile_size) {
4995 * Might be a receivefile write. Read the SMB2 HEADER +
4996 * SMB2_WRITE header first. Set 'doing_receivefile'
4997 * as we're *attempting* receivefile write. If this
4998 * turns out not to be a SMB2_WRITE request or otherwise
4999 * not suitable then we'll just read the rest of the data
5000 * the next time this function is called.
5002 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
5003 state->doing_receivefile = true;
5004 } else {
5005 state->pktlen = state->pktfull;
5008 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
5009 if (state->pktbuf == NULL) {
5010 return NT_STATUS_NO_MEMORY;
5013 state->_vector[0] = (struct iovec) {
5014 .iov_base = (void *)state->pktbuf,
5015 .iov_len = state->pktlen,
5017 state->vector = state->_vector;
5018 state->count = 1;
5020 return NT_STATUS_RETRY;
5022 got_full:
5024 if (state->hdr.nbt[0] != 0x00) {
5025 DEBUG(1,("ignore NBT[0x%02X] msg\n",
5026 state->hdr.nbt[0]));
5028 req = state->req;
5029 *state = (struct smbd_smb2_request_read_state) {
5030 .req = req,
5031 .min_recv_size = lp_min_receive_file_size(),
5032 ._vector = {
5033 [0] = (struct iovec) {
5034 .iov_base = (void *)state->hdr.nbt,
5035 .iov_len = NBT_HDR_SIZE,
5038 .vector = state->_vector,
5039 .count = 1,
5041 return NT_STATUS_RETRY;
5044 req = state->req;
5046 req->request_time = timeval_current();
5047 now = timeval_to_nttime(&req->request_time);
5049 status = smbd_smb2_inbuf_parse_compound(xconn,
5050 now,
5051 state->pktbuf,
5052 state->pktlen,
5053 req,
5054 &req->in.vector,
5055 &req->in.vector_count);
5056 if (!NT_STATUS_IS_OK(status)) {
5057 return status;
5060 if (state->doing_receivefile) {
5061 req->smb1req = talloc_zero(req, struct smb_request);
5062 if (req->smb1req == NULL) {
5063 return NT_STATUS_NO_MEMORY;
5065 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
5068 *state = (struct smbd_smb2_request_read_state) {
5069 .req = NULL,
5072 req->current_idx = 1;
5074 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
5075 req->current_idx, req->in.vector_count));
5077 status = smbd_smb2_request_validate(req);
5078 if (!NT_STATUS_IS_OK(status)) {
5079 return status;
5082 status = smbd_smb2_request_setup_out(req);
5083 if (!NT_STATUS_IS_OK(status)) {
5084 return status;
5087 status = smbd_smb2_request_dispatch(req);
5088 if (!NT_STATUS_IS_OK(status)) {
5089 return status;
5092 sconn->num_requests++;
5094 /* The timeout_processing function isn't run nearly
5095 often enough to implement 'max log size' without
5096 overrunning the size of the file by many megabytes.
5097 This is especially true if we are running at debug
5098 level 10. Checking every 50 SMB2s is a nice
5099 tradeoff of performance vs log file size overrun. */
5101 if ((sconn->num_requests % 50) == 0 &&
5102 need_to_check_log_size()) {
5103 change_to_root_user();
5104 check_log_size();
5107 status = smbd_smb2_request_next_incoming(xconn);
5108 if (!NT_STATUS_IS_OK(status)) {
5109 return status;
5112 return NT_STATUS_OK;
5115 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
5116 uint16_t fde_flags)
5118 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
5119 unsigned recvmsg_flags = 0;
5120 int ret;
5121 int err;
5122 bool retry;
5123 NTSTATUS status;
5125 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
5127 * we're not supposed to do any io
5129 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
5130 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
5131 TEVENT_FD_NOT_WANTERROR(xconn->transport.fde);
5132 return NT_STATUS_OK;
5135 if (fde_flags & TEVENT_FD_ERROR) {
5136 ret = samba_socket_poll_or_sock_error(xconn->transport.sock);
5137 if (ret == -1) {
5138 err = errno;
5139 status = map_nt_error_from_unix_common(err);
5140 smbXsrv_connection_disconnect_transport(xconn,
5141 status);
5142 return status;
5144 /* This should not happen */
5145 status = NT_STATUS_REMOTE_DISCONNECT;
5146 smbXsrv_connection_disconnect_transport(xconn,
5147 status);
5148 return status;
5151 if (fde_flags & TEVENT_FD_WRITE) {
5152 status = smbd_smb2_flush_send_queue(xconn);
5153 if (!NT_STATUS_IS_OK(status)) {
5154 return status;
5158 if (!(fde_flags & TEVENT_FD_READ)) {
5159 return NT_STATUS_OK;
5162 if (state->req == NULL) {
5163 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
5164 return NT_STATUS_OK;
5167 again:
5169 state->msg = (struct msghdr) {
5170 .msg_iov = state->vector,
5171 .msg_iovlen = state->count,
5174 #ifdef MSG_NOSIGNAL
5175 recvmsg_flags |= MSG_NOSIGNAL;
5176 #endif
5177 #ifdef MSG_DONTWAIT
5178 recvmsg_flags |= MSG_DONTWAIT;
5179 #endif
5181 ret = recvmsg(xconn->transport.sock, &state->msg, recvmsg_flags);
5182 if (ret == 0) {
5183 /* propagate end of file */
5184 status = NT_STATUS_END_OF_FILE;
5185 smbXsrv_connection_disconnect_transport(xconn,
5186 status);
5187 return status;
5189 err = socket_error_from_errno(ret, errno, &retry);
5190 if (retry) {
5191 /* retry later */
5192 TEVENT_FD_READABLE(xconn->transport.fde);
5193 return NT_STATUS_OK;
5195 if (err != 0) {
5196 status = map_nt_error_from_unix_common(err);
5197 smbXsrv_connection_disconnect_transport(xconn,
5198 status);
5199 return status;
5202 status = smbd_smb2_advance_incoming(xconn, ret);
5203 if (NT_STATUS_EQUAL(status, NT_STATUS_PENDING)) {
5204 /* we have more to read */
5205 TEVENT_FD_READABLE(xconn->transport.fde);
5206 return NT_STATUS_OK;
5208 if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5210 * smbd_smb2_advance_incoming setup a new vector
5211 * that we should try to read immediately.
5213 goto again;
5215 if (!NT_STATUS_IS_OK(status)) {
5216 return status;
5219 return NT_STATUS_OK;
5222 static void smbd_smb2_connection_handler(struct tevent_context *ev,
5223 struct tevent_fd *fde,
5224 uint16_t flags,
5225 void *private_data)
5227 struct smbXsrv_connection *xconn =
5228 talloc_get_type_abort(private_data,
5229 struct smbXsrv_connection);
5230 NTSTATUS status;
5232 status = smbd_smb2_io_handler(xconn, flags);
5233 if (!NT_STATUS_IS_OK(status)) {
5234 smbd_server_connection_terminate(xconn, nt_errstr(status));
5235 return;