smbd: use check_any_access_fsp() for all access checks
[Samba.git] / source3 / smbd / smb2_server.c
blob5a595313cd0fc2635a751612d5909547d6e0de7e
1 /*
2 Unix SMB/CIFS implementation.
3 Core SMB2 server
5 Copyright (C) Stefan Metzmacher 2009
6 Copyright (C) Jeremy Allison 2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "system/network.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "smbd/smbXsrv_open.h"
27 #include "lib/param/param.h"
28 #include "../libcli/smb/smb_common.h"
29 #include "../lib/tsocket/tsocket.h"
30 #include "../lib/util/tevent_ntstatus.h"
31 #include "smbprofile.h"
32 #include "../lib/util/bitmap.h"
33 #include "../librpc/gen_ndr/krb5pac.h"
34 #include "lib/util/iov_buf.h"
35 #include "auth.h"
36 #include "libcli/smb/smbXcli_base.h"
37 #include "source3/lib/substitute.h"
39 #if defined(LINUX)
40 /* SIOCOUTQ TIOCOUTQ are the same */
41 #define __IOCTL_SEND_QUEUE_SIZE_OPCODE TIOCOUTQ
42 #define __HAVE_TCP_INFO_RTO 1
43 #define __ALLOW_MULTI_CHANNEL_SUPPORT 1
44 #elif defined(FREEBSD)
45 #define __IOCTL_SEND_QUEUE_SIZE_OPCODE FIONWRITE
46 #define __HAVE_TCP_INFO_RTO 1
47 #define __ALLOW_MULTI_CHANNEL_SUPPORT 1
48 #endif
50 #include "lib/crypto/gnutls_helpers.h"
51 #include <gnutls/gnutls.h>
52 #include <gnutls/crypto.h>
54 #undef DBGC_CLASS
55 #define DBGC_CLASS DBGC_SMB2
57 static void smbd_smb2_connection_handler(struct tevent_context *ev,
58 struct tevent_fd *fde,
59 uint16_t flags,
60 void *private_data);
61 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn);
63 static const struct smbd_smb2_dispatch_table {
64 uint16_t opcode;
65 uint16_t fileid_ofs;
66 bool need_session : 1;
67 bool need_tcon : 1;
68 bool as_root : 1;
69 bool modify : 1;
70 } smbd_smb2_table[] = {
72 .opcode = SMB2_OP_NEGPROT,
73 .as_root = true,
74 },{
75 .opcode = SMB2_OP_SESSSETUP,
76 .as_root = true,
77 },{
78 .opcode = SMB2_OP_LOGOFF,
79 .need_session = true,
80 .as_root = true,
81 },{
82 .opcode = SMB2_OP_TCON,
83 .need_session = true,
85 * This call needs to be run as root.
87 * smbd_smb2_request_process_tcon()
88 * calls make_connection_snum(), which will call
89 * change_to_user(), when needed.
91 .as_root = true,
92 },{
93 .opcode = SMB2_OP_TDIS,
94 .need_session = true,
95 .need_tcon = true,
96 .as_root = true,
97 },{
98 .opcode = SMB2_OP_CREATE,
99 .need_session = true,
100 .need_tcon = true,
102 .opcode = SMB2_OP_CLOSE,
103 .need_session = true,
104 .need_tcon = true,
105 .fileid_ofs = 0x08,
107 .opcode = SMB2_OP_FLUSH,
108 .need_session = true,
109 .need_tcon = true,
110 .fileid_ofs = 0x08,
112 .opcode = SMB2_OP_READ,
113 .need_session = true,
114 .need_tcon = true,
115 .fileid_ofs = 0x10,
117 .opcode = SMB2_OP_WRITE,
118 .need_session = true,
119 .need_tcon = true,
120 .fileid_ofs = 0x10,
121 .modify = true,
123 .opcode = SMB2_OP_LOCK,
124 .need_session = true,
125 .need_tcon = true,
126 .fileid_ofs = 0x08,
128 .opcode = SMB2_OP_IOCTL,
129 .need_session = true,
130 .need_tcon = true,
131 .fileid_ofs = 0x08,
132 .modify = true,
134 .opcode = SMB2_OP_CANCEL,
135 .as_root = true,
137 .opcode = SMB2_OP_KEEPALIVE,
139 .opcode = SMB2_OP_QUERY_DIRECTORY,
140 .need_session = true,
141 .need_tcon = true,
142 .fileid_ofs = 0x08,
144 .opcode = SMB2_OP_NOTIFY,
145 .need_session = true,
146 .need_tcon = true,
147 .fileid_ofs = 0x08,
149 .opcode = SMB2_OP_GETINFO,
150 .need_session = true,
151 .need_tcon = true,
152 .fileid_ofs = 0x18,
154 .opcode = SMB2_OP_SETINFO,
155 .need_session = true,
156 .need_tcon = true,
157 .fileid_ofs = 0x10,
158 .modify = true,
160 .opcode = SMB2_OP_BREAK,
161 .need_session = true,
162 .need_tcon = true,
164 * we do not set
165 * .fileid_ofs here
166 * as LEASE breaks does not
167 * have a file id
172 const char *smb2_opcode_name(uint16_t opcode)
174 const char *result = "Bad SMB2 opcode";
176 switch (opcode) {
177 case SMB2_OP_NEGPROT:
178 result = "SMB2_OP_NEGPROT";
179 break;
180 case SMB2_OP_SESSSETUP:
181 result = "SMB2_OP_SESSSETUP";
182 break;
183 case SMB2_OP_LOGOFF:
184 result = "SMB2_OP_LOGOFF";
185 break;
186 case SMB2_OP_TCON:
187 result = "SMB2_OP_TCON";
188 break;
189 case SMB2_OP_TDIS:
190 result = "SMB2_OP_TDIS";
191 break;
192 case SMB2_OP_CREATE:
193 result = "SMB2_OP_CREATE";
194 break;
195 case SMB2_OP_CLOSE:
196 result = "SMB2_OP_CLOSE";
197 break;
198 case SMB2_OP_FLUSH:
199 result = "SMB2_OP_FLUSH";
200 break;
201 case SMB2_OP_READ:
202 result = "SMB2_OP_READ";
203 break;
204 case SMB2_OP_WRITE:
205 result = "SMB2_OP_WRITE";
206 break;
207 case SMB2_OP_LOCK:
208 result = "SMB2_OP_LOCK";
209 break;
210 case SMB2_OP_IOCTL:
211 result = "SMB2_OP_IOCTL";
212 break;
213 case SMB2_OP_CANCEL:
214 result = "SMB2_OP_CANCEL";
215 break;
216 case SMB2_OP_KEEPALIVE:
217 result = "SMB2_OP_KEEPALIVE";
218 break;
219 case SMB2_OP_QUERY_DIRECTORY:
220 result = "SMB2_OP_QUERY_DIRECTORY";
221 break;
222 case SMB2_OP_NOTIFY:
223 result = "SMB2_OP_NOTIFY";
224 break;
225 case SMB2_OP_GETINFO:
226 result = "SMB2_OP_GETINFO";
227 break;
228 case SMB2_OP_SETINFO:
229 result = "SMB2_OP_SETINFO";
230 break;
231 case SMB2_OP_BREAK:
232 result = "SMB2_OP_BREAK";
233 break;
234 default:
235 break;
237 return result;
240 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
242 const struct smbd_smb2_dispatch_table *ret = NULL;
244 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
245 return NULL;
248 ret = &smbd_smb2_table[opcode];
250 SMB_ASSERT(ret->opcode == opcode);
252 return ret;
255 static void print_req_vectors(const struct smbd_smb2_request *req)
257 int i;
259 for (i = 0; i < req->in.vector_count; i++) {
260 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
261 (unsigned int)i,
262 (unsigned int)req->in.vector[i].iov_len);
264 for (i = 0; i < req->out.vector_count; i++) {
265 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
266 (unsigned int)i,
267 (unsigned int)req->out.vector[i].iov_len);
271 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
273 if (size < (4 + SMB2_HDR_BODY)) {
274 return false;
277 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
278 return false;
281 return true;
284 bool smbd_smb2_is_compound(const struct smbd_smb2_request *req)
286 return req->in.vector_count >= (2*SMBD_SMB2_NUM_IOV_PER_REQ);
289 bool smbd_smb2_is_last_in_compound(const struct smbd_smb2_request *req)
291 return (req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ ==
292 req->in.vector_count);
295 static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn,
296 uint64_t expected_seq_low)
298 int rc;
300 xconn->smb2.credits.seq_low = expected_seq_low;
301 xconn->smb2.credits.seq_range = 1;
302 xconn->smb2.credits.granted = 1;
303 xconn->smb2.credits.max = lp_smb2_max_credits();
304 xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
305 xconn->smb2.credits.max);
306 if (xconn->smb2.credits.bitmap == NULL) {
307 return NT_STATUS_NO_MEMORY;
310 tevent_fd_set_close_fn(xconn->transport.fde, NULL);
311 TALLOC_FREE(xconn->transport.fde);
313 xconn->transport.fde = tevent_add_fd(
314 xconn->client->raw_ev_ctx,
315 xconn,
316 xconn->transport.sock,
317 TEVENT_FD_READ,
318 smbd_smb2_connection_handler,
319 xconn);
320 if (xconn->transport.fde == NULL) {
321 close(xconn->transport.sock);
322 xconn->transport.sock = -1;
323 return NT_STATUS_NO_MEMORY;
325 tevent_fd_set_auto_close(xconn->transport.fde);
328 * Ensure child is set to non-blocking mode,
329 * unless the system supports MSG_DONTWAIT,
330 * if MSG_DONTWAIT is available we should force
331 * blocking mode.
333 #ifdef MSG_DONTWAIT
334 rc = set_blocking(xconn->transport.sock, true);
335 if (rc < 0) {
336 return NT_STATUS_INTERNAL_ERROR;
338 #else
339 rc = set_blocking(xconn->transport.sock, false);
340 if (rc < 0) {
341 return NT_STATUS_INTERNAL_ERROR;
343 #endif
345 return NT_STATUS_OK;
348 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
349 #define _smb2_setlen(_buf,len) do { \
350 uint8_t *buf = (uint8_t *)_buf; \
351 buf[0] = 0; \
352 buf[1] = ((len)&0xFF0000)>>16; \
353 buf[2] = ((len)&0xFF00)>>8; \
354 buf[3] = (len)&0xFF; \
355 } while (0)
357 static bool smb2_setup_nbt_length(struct iovec *vector, int count)
359 ssize_t len;
361 if (count == 0) {
362 return false;
365 len = iov_buflen(vector+1, count-1);
367 if ((len == -1) || (len > 0xFFFFFF)) {
368 return false;
371 _smb2_setlen(vector[0].iov_base, len);
372 return true;
375 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
377 TALLOC_FREE(req->first_enc_key);
378 TALLOC_FREE(req->last_sign_key);
379 return 0;
382 void smb2_request_set_async_internal(struct smbd_smb2_request *req,
383 bool async_internal)
385 req->async_internal = async_internal;
388 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
390 TALLOC_CTX *mem_pool;
391 struct smbd_smb2_request *req;
393 #if 0
394 /* Enable this to find subtle valgrind errors. */
395 mem_pool = talloc_init("smbd_smb2_request_allocate");
396 #else
397 mem_pool = talloc_tos();
398 #endif
399 if (mem_pool == NULL) {
400 return NULL;
403 req = talloc_zero(mem_pool, struct smbd_smb2_request);
404 if (req == NULL) {
405 talloc_free(mem_pool);
406 return NULL;
408 talloc_reparent(mem_pool, mem_ctx, req);
409 #if 0
410 TALLOC_FREE(mem_pool);
411 #endif
413 req->last_session_id = UINT64_MAX;
414 req->last_tid = UINT32_MAX;
416 talloc_set_destructor(req, smbd_smb2_request_destructor);
418 return req;
421 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
422 NTTIME now,
423 uint8_t *buf,
424 size_t buflen,
425 struct smbd_smb2_request *req,
426 struct iovec **piov,
427 int *pnum_iov)
429 TALLOC_CTX *mem_ctx = req;
430 struct iovec *iov;
431 int num_iov = 1;
432 size_t taken = 0;
433 uint8_t *first_hdr = buf;
434 size_t verified_buflen = 0;
435 uint8_t *tf = NULL;
436 size_t tf_len = 0;
439 * Note: index '0' is reserved for the transport protocol
441 iov = req->in._vector;
443 while (taken < buflen) {
444 size_t len = buflen - taken;
445 uint8_t *hdr = first_hdr + taken;
446 struct iovec *cur;
447 size_t full_size;
448 size_t next_command_ofs;
449 uint16_t body_size;
450 uint8_t *body = NULL;
451 uint32_t dyn_size;
452 uint8_t *dyn = NULL;
453 struct iovec *iov_alloc = NULL;
455 if (iov != req->in._vector) {
456 iov_alloc = iov;
459 if (verified_buflen > taken) {
460 len = verified_buflen - taken;
461 } else {
462 tf = NULL;
463 tf_len = 0;
466 if (len < 4) {
467 DEBUG(10, ("%d bytes left, expected at least %d\n",
468 (int)len, 4));
469 goto inval;
471 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
472 struct smbXsrv_session *s = NULL;
473 uint64_t uid;
474 struct iovec tf_iov[2];
475 NTSTATUS status;
476 size_t enc_len;
478 if (xconn->protocol < PROTOCOL_SMB3_00) {
479 DEBUG(10, ("Got SMB2_TRANSFORM header, "
480 "but dialect[0x%04X] is used\n",
481 xconn->smb2.server.dialect));
482 goto inval;
485 if (xconn->smb2.server.cipher == 0) {
486 DEBUG(10, ("Got SMB2_TRANSFORM header, "
487 "but not negotiated "
488 "client[0x%08X] server[0x%08X]\n",
489 xconn->smb2.client.capabilities,
490 xconn->smb2.server.capabilities));
491 goto inval;
494 if (len < SMB2_TF_HDR_SIZE) {
495 DEBUG(1, ("%d bytes left, expected at least %d\n",
496 (int)len, SMB2_TF_HDR_SIZE));
497 goto inval;
499 tf = hdr;
500 tf_len = SMB2_TF_HDR_SIZE;
501 taken += tf_len;
503 hdr = first_hdr + taken;
504 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
505 uid = BVAL(tf, SMB2_TF_SESSION_ID);
507 if (len < SMB2_TF_HDR_SIZE + enc_len) {
508 DEBUG(1, ("%d bytes left, expected at least %d\n",
509 (int)len,
510 (int)(SMB2_TF_HDR_SIZE + enc_len)));
511 goto inval;
514 status = smb2srv_session_lookup_conn(xconn, uid, now,
515 &s);
516 if (s == NULL) {
517 status = smb2srv_session_lookup_global(xconn->client,
518 uid, req, &s);
520 if (s == NULL) {
521 DEBUG(1, ("invalid session[%llu] in "
522 "SMB2_TRANSFORM header\n",
523 (unsigned long long)uid));
524 TALLOC_FREE(iov_alloc);
525 return NT_STATUS_USER_SESSION_DELETED;
528 tf_iov[0].iov_base = (void *)tf;
529 tf_iov[0].iov_len = tf_len;
530 tf_iov[1].iov_base = (void *)hdr;
531 tf_iov[1].iov_len = enc_len;
533 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
534 tf_iov, 2);
535 if (!NT_STATUS_IS_OK(status)) {
536 TALLOC_FREE(iov_alloc);
537 return status;
540 verified_buflen = taken + enc_len;
541 len = enc_len;
545 * We need the header plus the body length field
548 if (len < SMB2_HDR_BODY + 2) {
550 if ((len == 5) &&
551 (IVAL(hdr, 0) == SMB_SUICIDE_PACKET) &&
552 lp_parm_bool(-1, "smbd", "suicide mode", false)) {
553 uint8_t exitcode = CVAL(hdr, 4);
554 DBG_WARNING("SUICIDE: Exiting immediately "
555 "with code %"PRIu8"\n",
556 exitcode);
557 exit(exitcode);
560 DEBUG(10, ("%d bytes left, expected at least %d\n",
561 (int)len, SMB2_HDR_BODY));
562 goto inval;
564 if (IVAL(hdr, 0) != SMB2_MAGIC) {
565 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
566 IVAL(hdr, 0)));
567 goto inval;
569 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
570 DEBUG(10, ("Got HDR len %d, expected %d\n",
571 SVAL(hdr, 4), SMB2_HDR_BODY));
572 goto inval;
575 full_size = len;
576 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
577 body_size = SVAL(hdr, SMB2_HDR_BODY);
579 if (next_command_ofs != 0) {
580 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
581 goto inval;
583 if (next_command_ofs > full_size) {
584 goto inval;
586 full_size = next_command_ofs;
588 if (body_size < 2) {
589 goto inval;
591 body_size &= 0xfffe;
593 if (body_size > (full_size - SMB2_HDR_BODY)) {
595 * let the caller handle the error
597 body_size = full_size - SMB2_HDR_BODY;
599 body = hdr + SMB2_HDR_BODY;
600 dyn = body + body_size;
601 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
603 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
604 struct iovec *iov_tmp = NULL;
606 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
607 struct iovec,
608 num_iov +
609 SMBD_SMB2_NUM_IOV_PER_REQ);
610 if (iov_tmp == NULL) {
611 TALLOC_FREE(iov_alloc);
612 return NT_STATUS_NO_MEMORY;
615 if (iov_alloc == NULL) {
616 memcpy(iov_tmp,
617 req->in._vector,
618 sizeof(req->in._vector));
621 iov = iov_tmp;
623 cur = &iov[num_iov];
624 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
626 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
627 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
628 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
629 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
630 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
631 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
632 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
633 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
635 taken += full_size;
638 *piov = iov;
639 *pnum_iov = num_iov;
640 return NT_STATUS_OK;
642 inval:
643 if (iov != req->in._vector) {
644 TALLOC_FREE(iov);
646 return NT_STATUS_INVALID_PARAMETER;
649 static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
650 const uint8_t *_inpdu, size_t size,
651 struct smbd_smb2_request **_req)
653 struct smbd_server_connection *sconn = xconn->client->sconn;
654 struct smbd_smb2_request *req;
655 uint32_t protocol_version;
656 uint8_t *inpdu = NULL;
657 const uint8_t *inhdr = NULL;
658 uint16_t cmd;
659 uint32_t next_command_ofs;
660 NTSTATUS status;
661 NTTIME now;
663 if (size < (SMB2_HDR_BODY + 2)) {
664 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
665 return NT_STATUS_INVALID_PARAMETER;
668 inhdr = _inpdu;
670 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
671 if (protocol_version != SMB2_MAGIC) {
672 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
673 protocol_version));
674 return NT_STATUS_INVALID_PARAMETER;
677 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
678 if (cmd != SMB2_OP_NEGPROT) {
679 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
680 cmd));
681 return NT_STATUS_INVALID_PARAMETER;
684 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
685 if (next_command_ofs != 0) {
686 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
687 next_command_ofs));
688 return NT_STATUS_INVALID_PARAMETER;
691 req = smbd_smb2_request_allocate(xconn);
692 if (req == NULL) {
693 return NT_STATUS_NO_MEMORY;
695 req->sconn = sconn;
696 req->xconn = xconn;
698 inpdu = talloc_memdup(req, _inpdu, size);
699 if (inpdu == NULL) {
700 return NT_STATUS_NO_MEMORY;
703 req->request_time = timeval_current();
704 now = timeval_to_nttime(&req->request_time);
706 status = smbd_smb2_inbuf_parse_compound(xconn,
707 now,
708 inpdu,
709 size,
710 req, &req->in.vector,
711 &req->in.vector_count);
712 if (!NT_STATUS_IS_OK(status)) {
713 TALLOC_FREE(req);
714 return status;
717 req->current_idx = 1;
719 *_req = req;
720 return NT_STATUS_OK;
723 static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
724 uint64_t message_id, uint64_t seq_id)
726 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
727 unsigned int offset;
728 uint64_t seq_tmp;
730 seq_tmp = xconn->smb2.credits.seq_low;
731 if (seq_id < seq_tmp) {
732 DBGC_ERR(DBGC_SMB2_CREDITS,
733 "smb2_validate_sequence_number: bad message_id "
734 "%llu (sequence id %llu) "
735 "(granted = %u, low = %llu, range = %u)\n",
736 (unsigned long long)message_id,
737 (unsigned long long)seq_id,
738 (unsigned int)xconn->smb2.credits.granted,
739 (unsigned long long)xconn->smb2.credits.seq_low,
740 (unsigned int)xconn->smb2.credits.seq_range);
741 return false;
744 seq_tmp += xconn->smb2.credits.seq_range;
745 if (seq_id >= seq_tmp) {
746 DBGC_ERR(DBGC_SMB2_CREDITS,
747 "smb2_validate_sequence_number: bad message_id "
748 "%llu (sequence id %llu) "
749 "(granted = %u, low = %llu, range = %u)\n",
750 (unsigned long long)message_id,
751 (unsigned long long)seq_id,
752 (unsigned int)xconn->smb2.credits.granted,
753 (unsigned long long)xconn->smb2.credits.seq_low,
754 (unsigned int)xconn->smb2.credits.seq_range);
755 return false;
758 offset = seq_id % xconn->smb2.credits.max;
760 if (bitmap_query(credits_bm, offset)) {
761 DBGC_ERR(DBGC_SMB2_CREDITS,
762 "smb2_validate_sequence_number: duplicate message_id "
763 "%llu (sequence id %llu) "
764 "(granted = %u, low = %llu, range = %u) "
765 "(bm offset %u)\n",
766 (unsigned long long)message_id,
767 (unsigned long long)seq_id,
768 (unsigned int)xconn->smb2.credits.granted,
769 (unsigned long long)xconn->smb2.credits.seq_low,
770 (unsigned int)xconn->smb2.credits.seq_range,
771 offset);
772 return false;
775 /* Mark the message_ids as seen in the bitmap. */
776 bitmap_set(credits_bm, offset);
778 if (seq_id != xconn->smb2.credits.seq_low) {
779 return true;
783 * Move the window forward by all the message_id's
784 * already seen.
786 while (bitmap_query(credits_bm, offset)) {
787 DBGC_DEBUG(DBGC_SMB2_CREDITS,
788 "smb2_validate_sequence_number: clearing "
789 "id %llu (position %u) from bitmap\n",
790 (unsigned long long)(xconn->smb2.credits.seq_low),
791 offset);
792 bitmap_clear(credits_bm, offset);
794 xconn->smb2.credits.seq_low += 1;
795 xconn->smb2.credits.seq_range -= 1;
796 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
799 return true;
802 static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
803 const uint8_t *inhdr)
805 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
806 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
807 uint16_t credit_charge = 1;
808 uint64_t i;
810 if (opcode == SMB2_OP_CANCEL) {
811 /* SMB2_CANCEL requests by definition resend messageids. */
812 return true;
815 if (xconn->smb2.credits.multicredit) {
816 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
817 credit_charge = MAX(credit_charge, 1);
820 DEBUGC(11,
821 DBGC_SMB2_CREDITS,
822 ("smb2_validate_message_id: mid %llu (charge %llu), "
823 "credits_granted %llu, "
824 "seqnum low/range: %llu/%llu\n",
825 (unsigned long long) message_id,
826 (unsigned long long) credit_charge,
827 (unsigned long long) xconn->smb2.credits.granted,
828 (unsigned long long) xconn->smb2.credits.seq_low,
829 (unsigned long long) xconn->smb2.credits.seq_range));
831 if (xconn->smb2.credits.granted < credit_charge) {
832 DBGC_ERR(DBGC_SMB2_CREDITS,
833 "smb2_validate_message_id: client used more "
834 "credits than granted, mid %llu, charge %llu, "
835 "credits_granted %llu, "
836 "seqnum low/range: %llu/%llu\n",
837 (unsigned long long) message_id,
838 (unsigned long long) credit_charge,
839 (unsigned long long) xconn->smb2.credits.granted,
840 (unsigned long long) xconn->smb2.credits.seq_low,
841 (unsigned long long) xconn->smb2.credits.seq_range);
842 return false;
846 * now check the message ids
848 * for multi-credit requests we need to check all current mid plus
849 * the implicit mids caused by the credit charge
850 * e.g. current mid = 15, charge 5 => mark 15-19 as used
853 for (i = 0; i <= (credit_charge-1); i++) {
854 uint64_t id = message_id + i;
855 bool ok;
857 DEBUGC(11,
858 DBGC_SMB2_CREDITS,
859 ("Iterating mid %llu charge %u (sequence %llu)\n",
860 (unsigned long long)message_id,
861 credit_charge,
862 (unsigned long long)id));
864 ok = smb2_validate_sequence_number(xconn, message_id, id);
865 if (!ok) {
866 return false;
870 /* subtract used credits */
871 xconn->smb2.credits.granted -= credit_charge;
873 return true;
876 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
878 int count;
879 int idx;
881 count = req->in.vector_count;
883 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
884 /* It's not a SMB2 request */
885 return NT_STATUS_INVALID_PARAMETER;
888 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
889 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
890 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
891 const uint8_t *inhdr = NULL;
893 if (hdr->iov_len != SMB2_HDR_BODY) {
894 return NT_STATUS_INVALID_PARAMETER;
897 if (body->iov_len < 2) {
898 return NT_STATUS_INVALID_PARAMETER;
901 inhdr = (const uint8_t *)hdr->iov_base;
903 /* Check the SMB2 header */
904 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
905 return NT_STATUS_INVALID_PARAMETER;
908 if (!smb2_validate_message_id(req->xconn, inhdr)) {
909 return NT_STATUS_INVALID_PARAMETER;
913 return NT_STATUS_OK;
916 static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
917 const struct iovec *in_vector,
918 struct iovec *out_vector)
920 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
921 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
922 uint16_t credit_charge = 1;
923 uint16_t credits_requested;
924 uint32_t out_flags;
925 uint16_t cmd;
926 NTSTATUS out_status;
927 uint16_t credits_granted = 0;
928 uint64_t credits_possible;
929 uint16_t current_max_credits;
932 * first we grant only 1/16th of the max range.
934 * Windows also starts with the 1/16th and then grants
935 * more later. I was only able to trigger higher
936 * values, when using a very high credit charge.
938 * TODO: scale up depending on load, free memory
939 * or other stuff.
940 * Maybe also on the relationship between number
941 * of requests and the used sequence number.
942 * Which means we would grant more credits
943 * for client which use multi credit requests.
945 * The above is what Windows Server < 2016 is doing,
946 * but new servers use all credits (8192 by default).
948 current_max_credits = xconn->smb2.credits.max;
949 current_max_credits = MAX(current_max_credits, 1);
951 if (xconn->smb2.credits.multicredit) {
952 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
953 credit_charge = MAX(credit_charge, 1);
956 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
957 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
958 credits_requested = MAX(credits_requested, 1);
959 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
960 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
962 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
964 if (xconn->smb2.credits.max < credit_charge) {
965 smbd_server_connection_terminate(xconn,
966 "client error: credit charge > max credits\n");
967 return;
970 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
972 * In case we already send an async interim
973 * response, we should not grant
974 * credits on the final response.
976 credits_granted = 0;
977 } else {
978 uint16_t additional_possible =
979 xconn->smb2.credits.max - credit_charge;
980 uint16_t additional_max = 0;
981 uint16_t additional_credits = credits_requested - 1;
983 switch (cmd) {
984 case SMB2_OP_NEGPROT:
985 break;
986 case SMB2_OP_SESSSETUP:
988 * Windows 2012 RC1 starts to grant
989 * additional credits
990 * with a successful session setup
992 if (NT_STATUS_IS_OK(out_status)) {
993 additional_max = xconn->smb2.credits.max;
995 break;
996 default:
998 * Windows Server < 2016 and older Samba versions
999 * used to only grant additional credits in
1000 * chunks of 32 credits.
1002 * But we match Windows Server 2016 and grant
1003 * all credits as requested.
1005 additional_max = xconn->smb2.credits.max;
1006 break;
1009 additional_max = MIN(additional_max, additional_possible);
1010 additional_credits = MIN(additional_credits, additional_max);
1012 credits_granted = credit_charge + additional_credits;
1016 * sequence numbers should not wrap
1018 * 1. calculate the possible credits until
1019 * the sequence numbers start to wrap on 64-bit.
1021 * 2. UINT64_MAX is used for Break Notifications.
1023 * 2. truncate the possible credits to the maximum
1024 * credits we want to grant to the client in total.
1026 * 3. remove the range we'll already granted to the client
1027 * this makes sure the client consumes the lowest sequence
1028 * number, before we can grant additional credits.
1030 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
1031 if (credits_possible > 0) {
1032 /* remove UINT64_MAX */
1033 credits_possible -= 1;
1035 credits_possible = MIN(credits_possible, current_max_credits);
1036 credits_possible -= xconn->smb2.credits.seq_range;
1038 credits_granted = MIN(credits_granted, credits_possible);
1040 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
1041 xconn->smb2.credits.granted += credits_granted;
1042 xconn->smb2.credits.seq_range += credits_granted;
1044 DBGC_DEBUG(DBGC_SMB2_CREDITS,
1045 "smb2_set_operation_credit: requested %u, charge %u, "
1046 "granted %u, current possible/max %u/%u, "
1047 "total granted/max/low/range %u/%u/%llu/%u\n",
1048 (unsigned int)credits_requested,
1049 (unsigned int)credit_charge,
1050 (unsigned int)credits_granted,
1051 (unsigned int)credits_possible,
1052 (unsigned int)current_max_credits,
1053 (unsigned int)xconn->smb2.credits.granted,
1054 (unsigned int)xconn->smb2.credits.max,
1055 (unsigned long long)xconn->smb2.credits.seq_low,
1056 (unsigned int)xconn->smb2.credits.seq_range);
1059 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
1060 struct smbd_smb2_request *outreq)
1062 int count, idx;
1063 uint16_t total_credits = 0;
1065 count = outreq->out.vector_count;
1067 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
1068 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
1069 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
1070 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
1072 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
1074 /* To match Windows, count up what we
1075 just granted. */
1076 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
1077 /* Set to zero in all but the last reply. */
1078 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
1079 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
1080 } else {
1081 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
1086 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
1088 if (req->current_idx <= 1) {
1089 if (size <= sizeof(req->out._body)) {
1090 return data_blob_const(req->out._body, size);
1094 return data_blob_talloc(req, NULL, size);
1097 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
1099 struct smbXsrv_connection *xconn = req->xconn;
1100 TALLOC_CTX *mem_ctx;
1101 struct iovec *vector;
1102 int count;
1103 int idx;
1104 bool ok;
1106 count = req->in.vector_count;
1107 if (count <= ARRAY_SIZE(req->out._vector)) {
1108 mem_ctx = req;
1109 vector = req->out._vector;
1110 } else {
1111 vector = talloc_zero_array(req, struct iovec, count);
1112 if (vector == NULL) {
1113 return NT_STATUS_NO_MEMORY;
1115 mem_ctx = vector;
1118 vector[0].iov_base = req->out.nbt_hdr;
1119 vector[0].iov_len = 4;
1120 SIVAL(req->out.nbt_hdr, 0, 0);
1122 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
1123 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
1124 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
1125 uint8_t *outhdr = NULL;
1126 uint8_t *outbody = NULL;
1127 uint32_t next_command_ofs = 0;
1128 struct iovec *current = &vector[idx];
1130 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
1131 /* we have a next command -
1132 * setup for the error case. */
1133 next_command_ofs = SMB2_HDR_BODY + 9;
1136 if (idx == 1) {
1137 outhdr = req->out._hdr;
1138 } else {
1139 outhdr = talloc_zero_array(mem_ctx, uint8_t,
1140 OUTVEC_ALLOC_SIZE);
1141 if (outhdr == NULL) {
1142 return NT_STATUS_NO_MEMORY;
1146 outbody = outhdr + SMB2_HDR_BODY;
1149 * SMBD_SMB2_TF_IOV_OFS might be used later
1151 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1152 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1154 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
1155 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1157 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1158 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1160 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1161 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1163 /* setup the SMB2 header */
1164 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1165 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1166 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1167 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1168 SIVAL(outhdr, SMB2_HDR_STATUS,
1169 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1170 SSVAL(outhdr, SMB2_HDR_OPCODE,
1171 SVAL(inhdr, SMB2_HDR_OPCODE));
1172 SIVAL(outhdr, SMB2_HDR_FLAGS,
1173 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1174 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1175 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1176 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1177 SIVAL(outhdr, SMB2_HDR_PID,
1178 IVAL(inhdr, SMB2_HDR_PID));
1179 SIVAL(outhdr, SMB2_HDR_TID,
1180 IVAL(inhdr, SMB2_HDR_TID));
1181 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1182 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1183 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1184 inhdr + SMB2_HDR_SIGNATURE, 16);
1186 /* setup error body header */
1187 SSVAL(outbody, 0x00, 0x08 + 1);
1188 SSVAL(outbody, 0x02, 0);
1189 SIVAL(outbody, 0x04, 0);
1192 req->out.vector = vector;
1193 req->out.vector_count = count;
1195 /* setup the length of the NBT packet */
1196 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1197 if (!ok) {
1198 return NT_STATUS_INVALID_PARAMETER_MIX;
1201 DLIST_ADD_END(xconn->smb2.requests, req);
1203 return NT_STATUS_OK;
1206 bool smbXsrv_server_multi_channel_enabled(void)
1208 bool enabled = lp_server_multi_channel_support();
1209 #ifndef __ALLOW_MULTI_CHANNEL_SUPPORT
1210 bool forced = false;
1211 struct loadparm_context *lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
1212 bool unspecified = lpcfg_parm_is_unspecified(lp_ctx, "server multi channel support");
1213 if (unspecified) {
1214 enabled = false;
1217 * If we don't have support from the kernel
1218 * to ask for the un-acked number of bytes
1219 * in the socket send queue, we better
1220 * don't support multi-channel.
1222 forced = lp_parm_bool(-1, "force", "server multi channel support", false);
1223 if (enabled && !forced) {
1224 D_NOTICE("'server multi channel support' enabled "
1225 "but not supported on %s (%s)\n",
1226 SYSTEM_UNAME_SYSNAME, SYSTEM_UNAME_RELEASE);
1227 DEBUGADD(DBGLVL_NOTICE, ("Please report this on "
1228 "https://bugzilla.samba.org/show_bug.cgi?id=11897\n"));
1229 enabled = false;
1231 TALLOC_FREE(lp_ctx);
1232 #endif /* ! __ALLOW_MULTI_CHANNEL_SUPPORT */
1233 return enabled;
1236 static NTSTATUS smbXsrv_connection_get_rto_usecs(struct smbXsrv_connection *xconn,
1237 uint32_t *_rto_usecs)
1240 * Define an Retransmission Timeout
1241 * of 1 second, if there's no way for the
1242 * kernel to tell us the current value.
1244 uint32_t rto_usecs = 1000000;
1246 #ifdef __HAVE_TCP_INFO_RTO
1248 struct tcp_info info;
1249 socklen_t ilen = sizeof(info);
1250 int ret;
1252 ZERO_STRUCT(info);
1253 ret = getsockopt(xconn->transport.sock,
1254 IPPROTO_TCP, TCP_INFO,
1255 (void *)&info, &ilen);
1256 if (ret != 0) {
1257 int saved_errno = errno;
1258 NTSTATUS status = map_nt_error_from_unix(errno);
1259 DBG_ERR("getsockopt(TCP_INFO) errno[%d/%s] -s %s\n",
1260 saved_errno, strerror(saved_errno),
1261 nt_errstr(status));
1262 return status;
1265 DBG_DEBUG("tcpi_rto[%u] tcpi_rtt[%u] tcpi_rttvar[%u]\n",
1266 (unsigned)info.tcpi_rto,
1267 (unsigned)info.tcpi_rtt,
1268 (unsigned)info.tcpi_rttvar);
1269 rto_usecs = info.tcpi_rto;
1271 #endif /* __HAVE_TCP_INFO_RTO */
1273 rto_usecs = MAX(rto_usecs, 200000); /* at least 0.2s */
1274 rto_usecs = MIN(rto_usecs, 1000000); /* at max 1.0s */
1275 *_rto_usecs = rto_usecs;
1276 return NT_STATUS_OK;
1279 static NTSTATUS smbXsrv_connection_get_acked_bytes(struct smbXsrv_connection *xconn,
1280 uint64_t *_acked_bytes)
1283 * Unless the kernel has an interface
1284 * to reveal the number of un-acked bytes
1285 * in the socket send queue, we'll assume
1286 * everything is already acked.
1288 * But that would mean that we better don't
1289 * pretent to support multi-channel.
1291 uint64_t unacked_bytes = 0;
1293 *_acked_bytes = 0;
1295 if (xconn->ack.force_unacked_timeout) {
1297 * Smbtorture tries to test channel failures...
1298 * Just pretend nothing was acked...
1300 DBG_INFO("Simulating channel failure: "
1301 "xconn->ack.unacked_bytes[%llu]\n",
1302 (unsigned long long)xconn->ack.unacked_bytes);
1303 return NT_STATUS_OK;
1306 #ifdef __IOCTL_SEND_QUEUE_SIZE_OPCODE
1308 int value = 0;
1309 int ret;
1312 * If we have kernel support to get
1313 * the number of bytes waiting in
1314 * the socket's send queue, we
1315 * use that in order to find out
1316 * the number of unacked bytes.
1318 ret = ioctl(xconn->transport.sock,
1319 __IOCTL_SEND_QUEUE_SIZE_OPCODE,
1320 &value);
1321 if (ret != 0) {
1322 int saved_errno = errno;
1323 NTSTATUS status = map_nt_error_from_unix(saved_errno);
1324 DBG_ERR("Failed to get the SEND_QUEUE_SIZE - "
1325 "errno %d (%s) - %s\n",
1326 saved_errno, strerror(saved_errno),
1327 nt_errstr(status));
1328 return status;
1331 if (value < 0) {
1332 DBG_ERR("xconn->ack.unacked_bytes[%llu] value[%d]\n",
1333 (unsigned long long)xconn->ack.unacked_bytes,
1334 value);
1335 return NT_STATUS_INTERNAL_ERROR;
1337 unacked_bytes = value;
1339 #endif
1340 if (xconn->ack.unacked_bytes == 0) {
1341 xconn->ack.unacked_bytes = unacked_bytes;
1342 return NT_STATUS_OK;
1345 if (xconn->ack.unacked_bytes < unacked_bytes) {
1346 DBG_ERR("xconn->ack.unacked_bytes[%llu] unacked_bytes[%llu]\n",
1347 (unsigned long long)xconn->ack.unacked_bytes,
1348 (unsigned long long)unacked_bytes);
1349 return NT_STATUS_INTERNAL_ERROR;
1352 *_acked_bytes = xconn->ack.unacked_bytes - unacked_bytes;
1353 xconn->ack.unacked_bytes = unacked_bytes;
1354 return NT_STATUS_OK;
1357 static void smbd_smb2_send_queue_ack_fail(struct smbd_smb2_send_queue **queue,
1358 NTSTATUS status)
1360 struct smbd_smb2_send_queue *e = NULL;
1361 struct smbd_smb2_send_queue *n = NULL;
1363 for (e = *queue; e != NULL; e = n) {
1364 n = e->next;
1366 DLIST_REMOVE(*queue, e);
1367 if (e->ack.req != NULL) {
1368 tevent_req_nterror(e->ack.req, status);
1373 static NTSTATUS smbd_smb2_send_queue_ack_bytes(struct smbd_smb2_send_queue **queue,
1374 uint64_t acked_bytes)
1376 struct smbd_smb2_send_queue *e = NULL;
1377 struct smbd_smb2_send_queue *n = NULL;
1379 for (e = *queue; e != NULL; e = n) {
1380 bool expired;
1382 n = e->next;
1384 if (e->ack.req == NULL) {
1385 continue;
1388 if (e->ack.required_acked_bytes <= acked_bytes) {
1389 e->ack.required_acked_bytes = 0;
1390 DLIST_REMOVE(*queue, e);
1391 tevent_req_done(e->ack.req);
1392 continue;
1394 e->ack.required_acked_bytes -= acked_bytes;
1396 expired = timeval_expired(&e->ack.timeout);
1397 if (expired) {
1398 return NT_STATUS_IO_TIMEOUT;
1402 return NT_STATUS_OK;
1405 static NTSTATUS smbd_smb2_check_ack_queue(struct smbXsrv_connection *xconn)
1407 uint64_t acked_bytes = 0;
1408 NTSTATUS status;
1410 status = smbXsrv_connection_get_acked_bytes(xconn, &acked_bytes);
1411 if (!NT_STATUS_IS_OK(status)) {
1412 return status;
1415 status = smbd_smb2_send_queue_ack_bytes(&xconn->ack.queue, acked_bytes);
1416 if (!NT_STATUS_IS_OK(status)) {
1417 return status;
1420 status = smbd_smb2_send_queue_ack_bytes(&xconn->smb2.send_queue, 0);
1421 if (!NT_STATUS_IS_OK(status)) {
1422 return status;
1425 return NT_STATUS_OK;
1428 static void smbXsrv_connection_ack_checker(struct tevent_req *subreq)
1430 struct smbXsrv_connection *xconn =
1431 tevent_req_callback_data(subreq,
1432 struct smbXsrv_connection);
1433 struct smbXsrv_client *client = xconn->client;
1434 struct timeval next_check;
1435 NTSTATUS status;
1436 bool ok;
1438 xconn->ack.checker_subreq = NULL;
1440 ok = tevent_wakeup_recv(subreq);
1441 TALLOC_FREE(subreq);
1442 if (!ok) {
1443 smbd_server_connection_terminate(xconn,
1444 "tevent_wakeup_recv() failed");
1445 return;
1448 status = smbd_smb2_check_ack_queue(xconn);
1449 if (!NT_STATUS_IS_OK(status)) {
1450 smbd_server_connection_terminate(xconn, nt_errstr(status));
1451 return;
1454 next_check = timeval_current_ofs_usec(xconn->ack.rto_usecs);
1455 xconn->ack.checker_subreq = tevent_wakeup_send(xconn,
1456 client->raw_ev_ctx,
1457 next_check);
1458 if (xconn->ack.checker_subreq == NULL) {
1459 smbd_server_connection_terminate(xconn,
1460 "tevent_wakeup_send() failed");
1461 return;
1463 tevent_req_set_callback(xconn->ack.checker_subreq,
1464 smbXsrv_connection_ack_checker,
1465 xconn);
1468 static NTSTATUS smbXsrv_client_pending_breaks_updated(struct smbXsrv_client *client)
1470 struct smbXsrv_connection *xconn = NULL;
1472 for (xconn = client->connections; xconn != NULL; xconn = xconn->next) {
1473 struct timeval next_check;
1474 uint64_t acked_bytes = 0;
1475 NTSTATUS status;
1478 * A new 'pending break cycle' starts
1479 * with a first pending break and lasts until
1480 * all pending breaks are finished.
1482 * This is typically a very short time,
1483 * the value of one retransmission timeout.
1486 if (client->pending_breaks == NULL) {
1488 * No more pending breaks, remove a pending
1489 * checker timer
1491 TALLOC_FREE(xconn->ack.checker_subreq);
1492 continue;
1495 if (xconn->ack.checker_subreq != NULL) {
1497 * The cycle already started =>
1498 * nothing todo
1500 continue;
1504 * Get the current retransmission timeout value.
1506 * It may change over time, but fetching it once
1507 * per 'pending break' cycled should be enough.
1509 status = smbXsrv_connection_get_rto_usecs(xconn,
1510 &xconn->ack.rto_usecs);
1511 if (!NT_STATUS_IS_OK(status)) {
1512 return status;
1516 * At the start of the cycle we reset the
1517 * unacked_bytes counter (first to 0 and
1518 * within smbXsrv_connection_get_acked_bytes()
1519 * to the current value in the kernel
1520 * send queue.
1522 xconn->ack.unacked_bytes = 0;
1523 status = smbXsrv_connection_get_acked_bytes(xconn, &acked_bytes);
1524 if (!NT_STATUS_IS_OK(status)) {
1525 return status;
1529 * We setup a timer in order to check for
1530 * acked bytes after one retransmission timeout.
1532 * The code that sets up the send_queue.ack.timeout
1533 * uses a multiple of the retransmission timeout.
1535 next_check = timeval_current_ofs_usec(xconn->ack.rto_usecs);
1536 xconn->ack.checker_subreq = tevent_wakeup_send(xconn,
1537 client->raw_ev_ctx,
1538 next_check);
1539 if (xconn->ack.checker_subreq == NULL) {
1540 return NT_STATUS_NO_MEMORY;
1542 tevent_req_set_callback(xconn->ack.checker_subreq,
1543 smbXsrv_connection_ack_checker,
1544 xconn);
1547 return NT_STATUS_OK;
1550 void smbXsrv_connection_disconnect_transport(struct smbXsrv_connection *xconn,
1551 NTSTATUS status)
1553 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
1554 return;
1557 xconn->transport.status = status;
1558 TALLOC_FREE(xconn->transport.fde);
1559 if (xconn->transport.sock != -1) {
1560 xconn->transport.sock = -1;
1562 smbd_smb2_send_queue_ack_fail(&xconn->ack.queue, status);
1563 smbd_smb2_send_queue_ack_fail(&xconn->smb2.send_queue, status);
1564 xconn->smb2.send_queue_len = 0;
1565 DO_PROFILE_INC(disconnect);
1568 size_t smbXsrv_client_valid_connections(struct smbXsrv_client *client)
1570 struct smbXsrv_connection *xconn = NULL;
1571 size_t num_ok = 0;
1573 for (xconn = client->connections; xconn != NULL; xconn = xconn->next) {
1574 if (NT_STATUS_IS_OK(xconn->transport.status)) {
1575 num_ok++;
1579 return num_ok;
1582 struct smbXsrv_connection_shutdown_state {
1583 struct smbXsrv_connection *xconn;
1586 static void smbXsrv_connection_shutdown_wait_done(struct tevent_req *subreq);
1588 static struct tevent_req *smbXsrv_connection_shutdown_send(TALLOC_CTX *mem_ctx,
1589 struct tevent_context *ev,
1590 struct smbXsrv_connection *xconn)
1592 struct tevent_req *req = NULL;
1593 struct smbXsrv_connection_shutdown_state *state = NULL;
1594 struct tevent_req *subreq = NULL;
1595 size_t len = 0;
1596 struct smbd_smb2_request *preq = NULL;
1597 NTSTATUS status;
1600 * The caller should have called
1601 * smbXsrv_connection_disconnect_transport() before.
1603 SMB_ASSERT(!NT_STATUS_IS_OK(xconn->transport.status));
1604 SMB_ASSERT(xconn->transport.terminating);
1605 SMB_ASSERT(xconn->transport.shutdown_wait_queue == NULL);
1607 req = tevent_req_create(mem_ctx, &state,
1608 struct smbXsrv_connection_shutdown_state);
1609 if (req == NULL) {
1610 return NULL;
1613 state->xconn = xconn;
1614 tevent_req_defer_callback(req, ev);
1616 xconn->transport.shutdown_wait_queue =
1617 tevent_queue_create(state, "smbXsrv_connection_shutdown_queue");
1618 if (tevent_req_nomem(xconn->transport.shutdown_wait_queue, req)) {
1619 return tevent_req_post(req, ev);
1622 for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
1624 * Now wait until the request is finished.
1626 * We don't set a callback, as we just want to block the
1627 * wait queue and the talloc_free() of the request will
1628 * remove the item from the wait queue.
1630 * Note that we don't cancel the requests here
1631 * in order to keep the replay detection logic correct.
1633 * However if we teardown the last channel of
1634 * a connection, we'll call some logic via
1635 * smbXsrv_session_disconnect_xconn()
1636 * -> smbXsrv_session_disconnect_xconn_callback()
1637 * -> smbXsrv_session_remove_channel()
1638 * -> smb2srv_session_shutdown_send()
1639 * will indeed cancel the request.
1641 subreq = tevent_queue_wait_send(preq, ev,
1642 xconn->transport.shutdown_wait_queue);
1643 if (tevent_req_nomem(subreq, req)) {
1644 return tevent_req_post(req, ev);
1649 * This may attach sessions with num_channels == 0
1650 * to xconn->transport.shutdown_wait_queue.
1652 status = smbXsrv_session_disconnect_xconn(xconn);
1653 if (tevent_req_nterror(req, status)) {
1654 return tevent_req_post(req, ev);
1657 len = tevent_queue_length(xconn->transport.shutdown_wait_queue);
1658 if (len == 0) {
1659 tevent_req_done(req);
1660 return tevent_req_post(req, ev);
1664 * Now we add our own waiter to the end of the queue,
1665 * this way we get notified when all pending requests are finished
1666 * and send to the socket.
1668 subreq = tevent_queue_wait_send(state, ev, xconn->transport.shutdown_wait_queue);
1669 if (tevent_req_nomem(subreq, req)) {
1670 return tevent_req_post(req, ev);
1672 tevent_req_set_callback(subreq, smbXsrv_connection_shutdown_wait_done, req);
1674 return req;
1677 static void smbXsrv_connection_shutdown_wait_done(struct tevent_req *subreq)
1679 struct tevent_req *req =
1680 tevent_req_callback_data(subreq,
1681 struct tevent_req);
1682 struct smbXsrv_connection_shutdown_state *state =
1683 tevent_req_data(req,
1684 struct smbXsrv_connection_shutdown_state);
1685 struct smbXsrv_connection *xconn = state->xconn;
1687 tevent_queue_wait_recv(subreq);
1688 TALLOC_FREE(subreq);
1690 tevent_req_done(req);
1692 * make sure the xconn pointer is still valid,
1693 * it should as we used tevent_req_defer_callback()
1695 SMB_ASSERT(xconn->transport.terminating);
1698 static NTSTATUS smbXsrv_connection_shutdown_recv(struct tevent_req *req)
1700 struct smbXsrv_connection_shutdown_state *state =
1701 tevent_req_data(req,
1702 struct smbXsrv_connection_shutdown_state);
1703 struct smbXsrv_connection *xconn = state->xconn;
1705 * make sure the xconn pointer is still valid,
1706 * it should as we used tevent_req_defer_callback()
1708 SMB_ASSERT(xconn->transport.terminating);
1709 return tevent_req_simple_recv_ntstatus(req);
1712 static void smbd_server_connection_terminate_done(struct tevent_req *subreq)
1714 struct smbXsrv_connection *xconn =
1715 tevent_req_callback_data(subreq,
1716 struct smbXsrv_connection);
1717 struct smbXsrv_client *client = xconn->client;
1718 NTSTATUS status;
1720 status = smbXsrv_connection_shutdown_recv(subreq);
1721 TALLOC_FREE(subreq);
1722 if (!NT_STATUS_IS_OK(status)) {
1723 exit_server("smbXsrv_connection_shutdown_recv failed");
1726 DLIST_REMOVE(client->connections, xconn);
1727 TALLOC_FREE(xconn);
1730 void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
1731 const char *reason,
1732 const char *location)
1734 struct smbXsrv_client *client = xconn->client;
1735 size_t num_ok = 0;
1738 * Make sure that no new request will be able to use this session.
1740 * smbXsrv_connection_disconnect_transport() might be called already,
1741 * but calling it again is a no-op.
1743 smbXsrv_connection_disconnect_transport(xconn,
1744 NT_STATUS_CONNECTION_DISCONNECTED);
1746 num_ok = smbXsrv_client_valid_connections(client);
1748 if (xconn->transport.terminating) {
1749 DBG_DEBUG("skip recursion conn[%s] num_ok[%zu] reason[%s] at %s\n",
1750 smbXsrv_connection_dbg(xconn), num_ok,
1751 reason, location);
1752 return;
1754 xconn->transport.terminating = true;
1756 DBG_DEBUG("conn[%s] num_ok[%zu] reason[%s] at %s\n",
1757 smbXsrv_connection_dbg(xconn), num_ok,
1758 reason, location);
1760 if (xconn->has_cluster_movable_ip) {
1762 * If the connection has a movable cluster public address
1763 * we disconnect all client connections,
1764 * as the public address might be moved to
1765 * a different node.
1767 * In future we may recheck which node currently
1768 * holds this address, but for now we keep it simple.
1770 smbd_server_disconnect_client_ex(xconn->client,
1771 reason,
1772 location);
1773 return;
1776 if (num_ok != 0) {
1777 struct tevent_req *subreq = NULL;
1779 subreq = smbXsrv_connection_shutdown_send(client,
1780 client->raw_ev_ctx,
1781 xconn);
1782 if (subreq == NULL) {
1783 exit_server("smbXsrv_connection_shutdown_send failed");
1785 tevent_req_set_callback(subreq,
1786 smbd_server_connection_terminate_done,
1787 xconn);
1788 return;
1792 * The last connection was disconnected
1794 exit_server_cleanly(reason);
1797 void smbd_server_disconnect_client_ex(struct smbXsrv_client *client,
1798 const char *reason,
1799 const char *location)
1801 size_t num_ok = 0;
1803 num_ok = smbXsrv_client_valid_connections(client);
1805 DBG_WARNING("client[%s] num_ok[%zu] reason[%s] at %s\n",
1806 client->global->remote_address, num_ok,
1807 reason, location);
1810 * Something bad happened we need to disconnect all connections.
1812 exit_server_cleanly(reason);
1815 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1816 struct iovec *outvec,
1817 const struct iovec *srcvec)
1819 const uint8_t *srctf;
1820 size_t srctf_len;
1821 const uint8_t *srchdr;
1822 size_t srchdr_len;
1823 const uint8_t *srcbody;
1824 size_t srcbody_len;
1825 const uint8_t *expected_srcbody;
1826 const uint8_t *srcdyn;
1827 size_t srcdyn_len;
1828 const uint8_t *expected_srcdyn;
1829 uint8_t *dsttf;
1830 uint8_t *dsthdr;
1831 uint8_t *dstbody;
1832 uint8_t *dstdyn;
1834 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1835 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1836 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1837 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1838 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1839 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1840 expected_srcbody = srchdr + SMB2_HDR_BODY;
1841 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1842 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1843 expected_srcdyn = srcbody + 8;
1845 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1846 return false;
1849 if (srchdr_len != SMB2_HDR_BODY) {
1850 return false;
1853 if (srctf_len == SMB2_TF_HDR_SIZE) {
1854 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1855 if (dsttf == NULL) {
1856 return false;
1858 } else {
1859 dsttf = NULL;
1861 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1862 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1864 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1865 * be allocated with size OUTVEC_ALLOC_SIZE. */
1867 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1868 if (dsthdr == NULL) {
1869 return false;
1871 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1872 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1875 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1876 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1877 * then duplicate this. Else use talloc_memdup().
1880 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1881 dstbody = dsthdr + SMB2_HDR_BODY;
1882 } else {
1883 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1884 if (dstbody == NULL) {
1885 return false;
1888 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1889 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1892 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1893 * pointing to
1894 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1895 * then duplicate this. Else use talloc_memdup().
1898 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1899 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1900 } else if (srcdyn == NULL) {
1901 dstdyn = NULL;
1902 } else {
1903 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1904 if (dstdyn == NULL) {
1905 return false;
1908 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1909 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1911 return true;
1914 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1916 struct smbd_smb2_request *newreq = NULL;
1917 struct iovec *outvec = NULL;
1918 int count = req->out.vector_count;
1919 int i;
1920 bool ok;
1922 newreq = smbd_smb2_request_allocate(req->xconn);
1923 if (!newreq) {
1924 return NULL;
1927 newreq->sconn = req->sconn;
1928 newreq->xconn = req->xconn;
1929 newreq->session = req->session;
1930 newreq->do_encryption = req->do_encryption;
1931 newreq->do_signing = req->do_signing;
1932 newreq->current_idx = req->current_idx;
1934 outvec = talloc_zero_array(newreq, struct iovec, count);
1935 if (!outvec) {
1936 TALLOC_FREE(newreq);
1937 return NULL;
1939 newreq->out.vector = outvec;
1940 newreq->out.vector_count = count;
1942 /* Setup the outvec's identically to req. */
1943 outvec[0].iov_base = newreq->out.nbt_hdr;
1944 outvec[0].iov_len = 4;
1945 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1947 /* Setup the vectors identically to the ones in req. */
1948 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1949 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1950 break;
1954 if (i < count) {
1955 /* Alloc failed. */
1956 TALLOC_FREE(newreq);
1957 return NULL;
1960 ok = smb2_setup_nbt_length(newreq->out.vector,
1961 newreq->out.vector_count);
1962 if (!ok) {
1963 TALLOC_FREE(newreq);
1964 return NULL;
1967 return newreq;
1970 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1972 struct smbXsrv_connection *xconn = req->xconn;
1973 int first_idx = 1;
1974 struct iovec *firsttf = NULL;
1975 struct iovec *outhdr_v = NULL;
1976 uint8_t *outhdr = NULL;
1977 struct smbd_smb2_request *nreq = NULL;
1978 NTSTATUS status;
1979 bool ok;
1981 /* Create a new smb2 request we'll use
1982 for the interim return. */
1983 nreq = dup_smb2_req(req);
1984 if (!nreq) {
1985 return NT_STATUS_NO_MEMORY;
1988 /* Lose the last X out vectors. They're the
1989 ones we'll be using for the async reply. */
1990 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1992 ok = smb2_setup_nbt_length(nreq->out.vector,
1993 nreq->out.vector_count);
1994 if (!ok) {
1995 return NT_STATUS_INVALID_PARAMETER_MIX;
1998 /* Step back to the previous reply. */
1999 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
2000 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
2001 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
2002 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
2003 /* And end the chain. */
2004 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
2006 /* Calculate outgoing credits */
2007 smb2_calculate_credits(req, nreq);
2009 if (DEBUGLEVEL >= 10) {
2010 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
2011 (unsigned int)nreq->current_idx );
2012 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
2013 (unsigned int)nreq->out.vector_count );
2014 print_req_vectors(nreq);
2018 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
2019 * we need to sign/encrypt here with the last/first key we remembered
2021 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2022 status = smb2_signing_encrypt_pdu(req->first_enc_key,
2023 firsttf,
2024 nreq->out.vector_count - first_idx);
2025 if (!NT_STATUS_IS_OK(status)) {
2026 return status;
2028 } else if (smb2_signing_key_valid(req->last_sign_key)) {
2029 status = smb2_signing_sign_pdu(req->last_sign_key,
2030 outhdr_v,
2031 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2032 if (!NT_STATUS_IS_OK(status)) {
2033 return status;
2037 nreq->queue_entry.mem_ctx = nreq;
2038 nreq->queue_entry.vector = nreq->out.vector;
2039 nreq->queue_entry.count = nreq->out.vector_count;
2040 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry);
2041 xconn->smb2.send_queue_len++;
2043 status = smbd_smb2_flush_send_queue(xconn);
2044 if (!NT_STATUS_IS_OK(status)) {
2045 return status;
2048 return NT_STATUS_OK;
2051 struct smbd_smb2_request_pending_state {
2052 struct smbd_smb2_send_queue queue_entry;
2053 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
2054 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
2057 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
2058 struct tevent_timer *te,
2059 struct timeval current_time,
2060 void *private_data);
2062 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
2063 struct tevent_req *subreq,
2064 uint32_t defer_time)
2066 NTSTATUS status;
2067 struct timeval defer_endtime;
2068 uint8_t *outhdr = NULL;
2069 uint32_t flags;
2071 if (!tevent_req_is_in_progress(subreq)) {
2073 * This is a performance optimization,
2074 * it avoids one tevent_loop iteration,
2075 * which means we avoid one
2076 * talloc_stackframe_pool/talloc_free pair.
2078 tevent_req_notify_callback(subreq);
2079 return NT_STATUS_OK;
2082 req->subreq = subreq;
2083 subreq = NULL;
2085 if (req->async_te) {
2086 /* We're already async. */
2087 return NT_STATUS_OK;
2090 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2091 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
2092 if (flags & SMB2_HDR_FLAG_ASYNC) {
2093 /* We're already async. */
2094 return NT_STATUS_OK;
2097 if (req->async_internal || defer_time == 0) {
2099 * An SMB2 request implementation wants to handle the request
2100 * asynchronously "internally" while keeping synchronous
2101 * behaviour for the SMB2 request. This means we don't send an
2102 * interim response and we can allow processing of compound SMB2
2103 * requests (cf the subsequent check) for all cases.
2105 return NT_STATUS_OK;
2108 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
2110 * We're trying to go async in a compound request
2111 * chain. This is only allowed for opens that cause an
2112 * oplock break or for the last operation in the
2113 * chain, otherwise it is not allowed. See
2114 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
2116 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2118 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
2120 * Cancel the outstanding request.
2122 bool ok = tevent_req_cancel(req->subreq);
2123 if (ok) {
2124 return NT_STATUS_OK;
2126 TALLOC_FREE(req->subreq);
2127 return smbd_smb2_request_error(req,
2128 NT_STATUS_INTERNAL_ERROR);
2132 if (DEBUGLEVEL >= 10) {
2133 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
2134 (unsigned int)req->current_idx );
2135 print_req_vectors(req);
2138 if (req->current_idx > 1) {
2140 * We're going async in a compound
2141 * chain after the first request has
2142 * already been processed. Send an
2143 * interim response containing the
2144 * set of replies already generated.
2146 int idx = req->current_idx;
2148 status = smb2_send_async_interim_response(req);
2149 if (!NT_STATUS_IS_OK(status)) {
2150 return status;
2152 TALLOC_FREE(req->first_enc_key);
2154 req->current_idx = 1;
2157 * Re-arrange the in.vectors to remove what
2158 * we just sent.
2160 memmove(&req->in.vector[1],
2161 &req->in.vector[idx],
2162 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
2163 req->in.vector_count = 1 + (req->in.vector_count - idx);
2165 /* Re-arrange the out.vectors to match. */
2166 memmove(&req->out.vector[1],
2167 &req->out.vector[idx],
2168 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
2169 req->out.vector_count = 1 + (req->out.vector_count - idx);
2171 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
2173 * We only have one remaining request as
2174 * we've processed everything else.
2175 * This is no longer a compound request.
2177 req->compound_related = false;
2178 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2179 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
2180 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
2183 TALLOC_FREE(req->last_sign_key);
2186 * smbd_smb2_request_pending_timer() just send a packet
2187 * to the client and doesn't need any impersonation.
2188 * So we use req->xconn->client->raw_ev_ctx instead
2189 * of req->ev_ctx here.
2191 defer_endtime = timeval_current_ofs_usec(defer_time);
2192 req->async_te = tevent_add_timer(req->xconn->client->raw_ev_ctx,
2193 req, defer_endtime,
2194 smbd_smb2_request_pending_timer,
2195 req);
2196 if (req->async_te == NULL) {
2197 return NT_STATUS_NO_MEMORY;
2200 return NT_STATUS_OK;
2203 static
2204 struct smb2_signing_key *smbd_smb2_signing_key(struct smbXsrv_session *session,
2205 struct smbXsrv_connection *xconn,
2206 bool *_has_channel)
2208 struct smbXsrv_channel_global0 *c = NULL;
2209 NTSTATUS status;
2210 struct smb2_signing_key *key = NULL;
2211 bool has_channel = false;
2213 status = smbXsrv_session_find_channel(session, xconn, &c);
2214 if (NT_STATUS_IS_OK(status)) {
2215 key = c->signing_key;
2216 has_channel = true;
2219 if (!smb2_signing_key_valid(key)) {
2220 key = session->global->signing_key;
2221 has_channel = false;
2224 if (_has_channel != NULL) {
2225 *_has_channel = has_channel;
2228 return key;
2231 static NTSTATUS smb2_get_new_nonce(struct smbXsrv_session *session,
2232 uint64_t *new_nonce_high,
2233 uint64_t *new_nonce_low)
2235 uint64_t nonce_high;
2236 uint64_t nonce_low;
2238 session->nonce_low += 1;
2239 if (session->nonce_low == 0) {
2240 session->nonce_low += 1;
2241 session->nonce_high += 1;
2245 * CCM and GCM algorithms must never have their
2246 * nonce wrap, or the security of the whole
2247 * communication and the keys is destroyed.
2248 * We must drop the connection once we have
2249 * transferred too much data.
2251 * NOTE: We assume nonces greater than 8 bytes.
2253 if (session->nonce_high >= session->nonce_high_max) {
2254 return NT_STATUS_ENCRYPTION_FAILED;
2257 nonce_high = session->nonce_high_random;
2258 nonce_high += session->nonce_high;
2259 nonce_low = session->nonce_low;
2261 *new_nonce_high = nonce_high;
2262 *new_nonce_low = nonce_low;
2263 return NT_STATUS_OK;
2266 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
2267 struct tevent_timer *te,
2268 struct timeval current_time,
2269 void *private_data)
2271 struct smbd_smb2_request *req =
2272 talloc_get_type_abort(private_data,
2273 struct smbd_smb2_request);
2274 struct smbXsrv_connection *xconn = req->xconn;
2275 struct smbd_smb2_request_pending_state *state = NULL;
2276 uint8_t *outhdr = NULL;
2277 const uint8_t *inhdr = NULL;
2278 uint8_t *tf = NULL;
2279 uint8_t *hdr = NULL;
2280 uint8_t *body = NULL;
2281 uint8_t *dyn = NULL;
2282 uint32_t flags = 0;
2283 uint64_t message_id = 0;
2284 uint64_t async_id = 0;
2285 NTSTATUS status;
2286 bool ok;
2288 TALLOC_FREE(req->async_te);
2290 /* Ensure our final reply matches the interim one. */
2291 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2292 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2293 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
2294 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
2296 async_id = message_id; /* keep it simple for now... */
2298 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
2299 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
2301 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
2302 "going async\n",
2303 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
2304 (unsigned long long)async_id ));
2307 * What we send is identical to a smbd_smb2_request_error
2308 * packet with an error status of STATUS_PENDING. Make use
2309 * of this fact sometime when refactoring. JRA.
2312 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
2313 if (state == NULL) {
2314 smbd_server_connection_terminate(xconn,
2315 nt_errstr(NT_STATUS_NO_MEMORY));
2316 return;
2319 tf = state->buf + NBT_HDR_SIZE;
2321 hdr = tf + SMB2_TF_HDR_SIZE;
2322 body = hdr + SMB2_HDR_BODY;
2323 dyn = body + 8;
2325 if (req->do_encryption) {
2326 uint64_t nonce_high = 0;
2327 uint64_t nonce_low = 0;
2328 uint64_t session_id = req->session->global->session_wire_id;
2330 status = smb2_get_new_nonce(req->session,
2331 &nonce_high,
2332 &nonce_low);
2333 if (!NT_STATUS_IS_OK(status)) {
2334 smbd_server_connection_terminate(xconn,
2335 nt_errstr(status));
2336 return;
2339 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2340 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2341 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2342 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2345 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
2346 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2347 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2348 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(NT_STATUS_PENDING));
2349 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
2352 * The STATUS_PENDING response has SMB2_HDR_FLAG_SIGNED
2353 * clearedm, but echoes the signature field.
2355 flags &= ~SMB2_HDR_FLAG_SIGNED;
2356 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
2357 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2358 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
2359 SBVAL(hdr, SMB2_HDR_PID, async_id);
2360 SBVAL(hdr, SMB2_HDR_SESSION_ID,
2361 BVAL(outhdr, SMB2_HDR_SESSION_ID));
2362 memcpy(hdr+SMB2_HDR_SIGNATURE,
2363 outhdr+SMB2_HDR_SIGNATURE, 16);
2365 SSVAL(body, 0x00, 0x08 + 1);
2367 SCVAL(body, 0x02, 0);
2368 SCVAL(body, 0x03, 0);
2369 SIVAL(body, 0x04, 0);
2370 /* Match W2K8R2... */
2371 SCVAL(dyn, 0x00, 0x21);
2373 state->vector[0].iov_base = (void *)state->buf;
2374 state->vector[0].iov_len = NBT_HDR_SIZE;
2376 if (req->do_encryption) {
2377 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
2378 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len =
2379 SMB2_TF_HDR_SIZE;
2380 } else {
2381 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
2382 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
2385 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
2386 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
2388 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
2389 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
2391 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
2392 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
2394 ok = smb2_setup_nbt_length(state->vector,
2395 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2396 if (!ok) {
2397 smbd_server_connection_terminate(
2398 xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
2399 return;
2402 /* Ensure we correctly go through crediting. Grant
2403 the credits now, and zero credits on the final
2404 response. */
2405 smb2_set_operation_credit(req->xconn,
2406 SMBD_SMB2_IN_HDR_IOV(req),
2407 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
2410 * We add SMB2_HDR_FLAG_ASYNC after smb2_set_operation_credit()
2411 * as it reacts on it
2413 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
2415 if (DEBUGLVL(10)) {
2416 int i;
2418 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
2419 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
2420 (unsigned int)i,
2421 (unsigned int)ARRAY_SIZE(state->vector),
2422 (unsigned int)state->vector[i].iov_len);
2426 if (req->do_encryption) {
2427 struct smbXsrv_session *x = req->session;
2428 struct smb2_signing_key *encryption_key = x->global->encryption_key;
2430 status = smb2_signing_encrypt_pdu(encryption_key,
2431 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2432 SMBD_SMB2_NUM_IOV_PER_REQ);
2433 if (!NT_STATUS_IS_OK(status)) {
2434 smbd_server_connection_terminate(xconn,
2435 nt_errstr(status));
2436 return;
2440 state->queue_entry.mem_ctx = state;
2441 state->queue_entry.vector = state->vector;
2442 state->queue_entry.count = ARRAY_SIZE(state->vector);
2443 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
2444 xconn->smb2.send_queue_len++;
2446 status = smbd_smb2_flush_send_queue(xconn);
2447 if (!NT_STATUS_IS_OK(status)) {
2448 smbd_server_connection_terminate(xconn,
2449 nt_errstr(status));
2450 return;
2454 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
2456 struct smbXsrv_connection *xconn = req->xconn;
2457 struct smbd_smb2_request *cur;
2458 const uint8_t *inhdr;
2459 uint32_t flags;
2460 uint64_t search_message_id;
2461 uint64_t search_async_id;
2462 uint64_t found_id;
2464 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2466 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2467 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2468 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
2471 * We don't need the request anymore cancel requests never
2472 * have a response.
2474 * We defer the TALLOC_FREE(req) to the caller.
2476 DLIST_REMOVE(xconn->smb2.requests, req);
2478 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
2479 const uint8_t *outhdr;
2480 uint64_t message_id;
2481 uint64_t async_id;
2483 if (cur->session != req->session) {
2484 continue;
2487 if (cur->compound_related) {
2489 * Never cancel anything in a compound request.
2490 * Way too hard to deal with the result.
2492 continue;
2495 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
2497 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
2498 async_id = BVAL(outhdr, SMB2_HDR_PID);
2500 if (flags & SMB2_HDR_FLAG_ASYNC) {
2501 if (search_async_id == async_id) {
2502 found_id = async_id;
2503 break;
2505 } else {
2506 if (search_message_id == message_id) {
2507 found_id = message_id;
2508 break;
2513 if (cur && cur->subreq) {
2514 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
2515 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
2516 "cancel opcode[%s] mid %llu\n",
2517 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
2518 (unsigned long long)found_id ));
2519 tevent_req_cancel(cur->subreq);
2522 return NT_STATUS_OK;
2525 /*************************************************************
2526 Ensure an incoming tid is a valid one for us to access.
2527 Change to the associated uid credentials and chdir to the
2528 valid tid directory.
2529 *************************************************************/
2531 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
2533 const uint8_t *inhdr;
2534 uint32_t in_flags;
2535 uint32_t in_tid;
2536 struct smbXsrv_tcon *tcon;
2537 NTSTATUS status;
2538 NTTIME now = timeval_to_nttime(&req->request_time);
2540 req->tcon = NULL;
2542 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2544 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2545 in_tid = IVAL(inhdr, SMB2_HDR_TID);
2547 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
2548 in_tid = req->last_tid;
2551 req->last_tid = 0;
2553 status = smb2srv_tcon_lookup(req->session,
2554 in_tid, now, &tcon);
2555 if (!NT_STATUS_IS_OK(status)) {
2556 return status;
2559 if (!change_to_user_and_service(
2560 tcon->compat,
2561 req->session->global->session_wire_id))
2563 return NT_STATUS_ACCESS_DENIED;
2566 req->tcon = tcon;
2567 req->last_tid = in_tid;
2569 return NT_STATUS_OK;
2572 /*************************************************************
2573 Ensure an incoming session_id is a valid one for us to access.
2574 *************************************************************/
2576 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
2578 const uint8_t *inhdr;
2579 uint32_t in_flags;
2580 uint16_t in_opcode;
2581 uint64_t in_session_id;
2582 struct smbXsrv_session *session = NULL;
2583 struct auth_session_info *session_info;
2584 NTSTATUS status;
2585 NTTIME now = timeval_to_nttime(&req->request_time);
2587 req->session = NULL;
2588 req->tcon = NULL;
2590 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2592 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2593 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2594 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
2596 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
2597 in_session_id = req->last_session_id;
2600 req->last_session_id = 0;
2602 /* look an existing session up */
2603 switch (in_opcode) {
2604 case SMB2_OP_SESSSETUP:
2606 * For a session bind request, we don't have the
2607 * channel set up at this point yet, so we defer
2608 * the verification that the connection belongs
2609 * to the session to the session setup code, which
2610 * can look at the session binding flags.
2612 status = smb2srv_session_lookup_client(req->xconn->client,
2613 in_session_id, now,
2614 &session);
2615 break;
2616 default:
2617 status = smb2srv_session_lookup_conn(req->xconn,
2618 in_session_id, now,
2619 &session);
2620 break;
2622 if (session) {
2623 req->session = session;
2624 req->last_session_id = in_session_id;
2626 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
2627 switch (in_opcode) {
2628 case SMB2_OP_SESSSETUP:
2629 status = smb2srv_session_lookup_global(req->xconn->client,
2630 in_session_id,
2631 req,
2632 &session);
2633 if (NT_STATUS_IS_OK(status)) {
2635 * We fallback to a session of
2636 * another process in order to
2637 * get the signing correct.
2639 * We don't set req->last_session_id here.
2641 req->session = session;
2643 break;
2644 default:
2645 break;
2648 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
2649 switch (in_opcode) {
2650 case SMB2_OP_SESSSETUP:
2651 status = NT_STATUS_OK;
2652 break;
2653 case SMB2_OP_LOGOFF:
2654 case SMB2_OP_CLOSE:
2655 case SMB2_OP_LOCK:
2656 case SMB2_OP_CANCEL:
2657 case SMB2_OP_KEEPALIVE:
2659 * [MS-SMB2] 3.3.5.2.9 Verifying the Session
2660 * specifies that LOGOFF, CLOSE and (UN)LOCK
2661 * should always be processed even on expired sessions.
2663 * Also see the logic in
2664 * smbd_smb2_request_process_lock().
2666 * The smb2.session.expire2 test shows that
2667 * CANCEL and KEEPALIVE/ECHO should also
2668 * be processed.
2670 status = NT_STATUS_OK;
2671 break;
2672 default:
2673 break;
2676 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2677 switch (in_opcode) {
2678 case SMB2_OP_TCON:
2679 case SMB2_OP_CREATE:
2680 case SMB2_OP_GETINFO:
2681 case SMB2_OP_SETINFO:
2682 return NT_STATUS_INVALID_HANDLE;
2683 default:
2685 * Notice the check for
2686 * (session_info == NULL)
2687 * below.
2689 status = NT_STATUS_OK;
2690 break;
2693 if (!NT_STATUS_IS_OK(status)) {
2694 return status;
2697 session_info = session->global->auth_session_info;
2698 if (session_info == NULL) {
2699 return NT_STATUS_INVALID_HANDLE;
2702 return NT_STATUS_OK;
2705 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
2706 uint32_t data_length)
2708 struct smbXsrv_connection *xconn = req->xconn;
2709 uint16_t needed_charge;
2710 uint16_t credit_charge = 1;
2711 const uint8_t *inhdr;
2713 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2715 if (xconn->smb2.credits.multicredit) {
2716 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
2717 credit_charge = MAX(credit_charge, 1);
2720 needed_charge = (data_length - 1)/ 65536 + 1;
2722 DBGC_DEBUG(DBGC_SMB2_CREDITS,
2723 "mid %llu, CreditCharge: %d, NeededCharge: %d\n",
2724 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
2725 credit_charge, needed_charge);
2727 if (needed_charge > credit_charge) {
2728 DBGC_WARNING(DBGC_SMB2_CREDITS,
2729 "CreditCharge too low, given %d, needed %d\n",
2730 credit_charge, needed_charge);
2731 return NT_STATUS_INVALID_PARAMETER;
2734 return NT_STATUS_OK;
2737 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
2738 size_t expected_body_size)
2740 struct iovec *inhdr_v;
2741 const uint8_t *inhdr;
2742 uint16_t opcode;
2743 const uint8_t *inbody;
2744 size_t body_size;
2745 size_t min_dyn_size = expected_body_size & 0x00000001;
2746 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
2749 * The following should be checked already.
2751 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
2752 return NT_STATUS_INTERNAL_ERROR;
2754 if (req->current_idx > max_idx) {
2755 return NT_STATUS_INTERNAL_ERROR;
2758 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
2759 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
2760 return NT_STATUS_INTERNAL_ERROR;
2762 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
2763 return NT_STATUS_INTERNAL_ERROR;
2766 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2767 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2769 switch (opcode) {
2770 case SMB2_OP_IOCTL:
2771 case SMB2_OP_GETINFO:
2772 case SMB2_OP_WRITE:
2773 min_dyn_size = 0;
2774 break;
2778 * Now check the expected body size,
2779 * where the last byte might be in the
2780 * dynamic section..
2782 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
2783 return NT_STATUS_INVALID_PARAMETER;
2785 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
2786 return NT_STATUS_INVALID_PARAMETER;
2789 inbody = SMBD_SMB2_IN_BODY_PTR(req);
2791 body_size = SVAL(inbody, 0x00);
2792 if (body_size != expected_body_size) {
2793 return NT_STATUS_INVALID_PARAMETER;
2796 return NT_STATUS_OK;
2799 bool smbXsrv_is_encrypted(uint8_t encryption_flags)
2801 return (!(encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)
2803 (encryption_flags & (SMBXSRV_PROCESSED_ENCRYPTED_PACKET |
2804 SMBXSRV_ENCRYPTION_DESIRED |
2805 SMBXSRV_ENCRYPTION_REQUIRED)));
2808 bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags)
2810 return ((encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET) &&
2811 (encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET));
2814 /* Set a flag if not already set, return true if set */
2815 bool smbXsrv_set_crypto_flag(uint8_t *flags, uint8_t flag)
2817 if ((flag == 0) || (*flags & flag)) {
2818 return false;
2821 *flags |= flag;
2822 return true;
2826 * Update encryption state tracking flags, this can be used to
2827 * determine whether whether the session or tcon is "encrypted".
2829 static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
2830 uint16_t opcode,
2831 bool *update_session_globalp,
2832 bool *update_tcon_globalp)
2834 /* Default: assume unecrypted and unsigned */
2835 struct smbXsrv_session *session = req->session;
2836 struct smbXsrv_tcon *tcon = req->tcon;
2837 uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
2838 uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2839 bool update_session = false;
2840 bool update_tcon = false;
2842 if (session->table == NULL) {
2844 * sessions from smb2srv_session_lookup_global()
2845 * have NT_STATUS_BAD_LOGON_SESSION_STATE
2846 * and session->table == NULL.
2848 * They only used to give the correct error
2849 * status, we should not update any state.
2851 goto out;
2854 if (req->was_encrypted && req->do_encryption) {
2855 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
2856 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2857 } else {
2858 /* Unencrypted packet, can be signed */
2859 if (req->do_signing) {
2860 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2864 update_session |= smbXsrv_set_crypto_flag(
2865 &session->global->encryption_flags, encrypt_flag);
2866 update_session |= smbXsrv_set_crypto_flag(
2867 &session->global->signing_flags, sign_flag);
2869 if (tcon) {
2870 update_tcon |= smbXsrv_set_crypto_flag(
2871 &tcon->global->encryption_flags, encrypt_flag);
2872 update_tcon |= smbXsrv_set_crypto_flag(
2873 &tcon->global->signing_flags, sign_flag);
2876 out:
2877 *update_session_globalp = update_session;
2878 *update_tcon_globalp = update_tcon;
2879 return;
2882 bool smbXsrv_is_signed(uint8_t signing_flags)
2885 * Signing is always enabled, so unless we got an unsigned
2886 * packet and at least one signed packet that was not
2887 * encrypted, the session or tcon is "signed".
2889 return (!(signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2890 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2893 bool smbXsrv_is_partially_signed(uint8_t signing_flags)
2895 return ((signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2896 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2899 static NTSTATUS smbd_smb2_request_dispatch_update_counts(
2900 struct smbd_smb2_request *req,
2901 bool modify_call)
2903 struct smbXsrv_connection *xconn = req->xconn;
2904 const uint8_t *inhdr;
2905 uint16_t channel_sequence;
2906 uint8_t generation_wrap = 0;
2907 uint32_t flags;
2908 int cmp;
2909 struct smbXsrv_open *op;
2910 bool update_open = false;
2911 NTSTATUS status = NT_STATUS_OK;
2913 SMB_ASSERT(!req->request_counters_updated);
2915 if (xconn->protocol < PROTOCOL_SMB3_00) {
2916 return NT_STATUS_OK;
2919 if (req->compat_chain_fsp == NULL) {
2920 return NT_STATUS_OK;
2923 op = req->compat_chain_fsp->op;
2924 if (op == NULL) {
2925 return NT_STATUS_OK;
2928 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2929 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2930 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2932 cmp = channel_sequence - op->global->channel_sequence;
2933 if (cmp < 0) {
2935 * csn wrap. We need to watch out for long-running
2936 * requests that are still sitting on a previously
2937 * used csn. SMB2_OP_NOTIFY can take VERY long.
2939 generation_wrap += 1;
2942 if (abs(cmp) > INT16_MAX) {
2944 * [MS-SMB2] 3.3.5.2.10 - Verifying the Channel Sequence Number:
2946 * If the channel sequence number of the request and the one
2947 * known to the server are not equal, the channel sequence
2948 * number and outstanding request counts are only updated
2949 * "... if the unsigned difference using 16-bit arithmetic
2950 * between ChannelSequence and Open.ChannelSequence is less than
2951 * or equal to 0x7FFF ...".
2952 * Otherwise, an error is returned for the modifying
2953 * calls write, set_info, and ioctl.
2955 * There are currently two issues with the description:
2957 * * For the other calls, the document seems to imply
2958 * that processing continues without adapting the
2959 * counters (if the sequence numbers are not equal).
2961 * TODO: This needs clarification!
2963 * * Also, the behaviour if the difference is larger
2964 * than 0x7FFF is not clear. The document seems to
2965 * imply that if such a difference is reached,
2966 * the server starts to ignore the counters or
2967 * in the case of the modifying calls, return errors.
2969 * TODO: This needs clarification!
2971 * At this point Samba tries to be a little more
2972 * clever than the description in the MS-SMB2 document
2973 * by heuristically detecting and properly treating
2974 * a 16 bit overflow of the client-submitted sequence
2975 * number:
2977 * If the stored channel sequence number is more than
2978 * 0x7FFF larger than the one from the request, then
2979 * the client-provided sequence number has likely
2980 * overflown. We treat this case as valid instead
2981 * of as failure.
2983 * The MS-SMB2 behaviour would be setting cmp = -1.
2985 cmp *= -1;
2988 if (flags & SMB2_HDR_FLAG_REPLAY_OPERATION) {
2989 if (cmp == 0 && op->pre_request_count == 0) {
2990 op->request_count += 1;
2991 req->request_counters_updated = true;
2992 } else if (cmp > 0 && op->pre_request_count == 0) {
2993 op->pre_request_count += op->request_count;
2994 op->request_count = 1;
2995 op->global->channel_sequence = channel_sequence;
2996 op->global->channel_generation += generation_wrap;
2997 update_open = true;
2998 req->request_counters_updated = true;
2999 } else if (modify_call) {
3000 return NT_STATUS_FILE_NOT_AVAILABLE;
3002 } else {
3003 if (cmp == 0) {
3004 op->request_count += 1;
3005 req->request_counters_updated = true;
3006 } else if (cmp > 0) {
3007 op->pre_request_count += op->request_count;
3008 op->request_count = 1;
3009 op->global->channel_sequence = channel_sequence;
3010 op->global->channel_generation += generation_wrap;
3011 update_open = true;
3012 req->request_counters_updated = true;
3013 } else if (modify_call) {
3014 return NT_STATUS_FILE_NOT_AVAILABLE;
3017 req->channel_generation = op->global->channel_generation;
3019 if (update_open) {
3020 status = smbXsrv_open_update(op);
3023 return status;
3026 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
3028 struct smbXsrv_connection *xconn = req->xconn;
3029 const struct smbd_smb2_dispatch_table *call = NULL;
3030 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
3031 const uint8_t *inhdr;
3032 uint16_t opcode;
3033 uint32_t flags;
3034 uint64_t mid;
3035 NTSTATUS status;
3036 NTSTATUS session_status;
3037 uint32_t allowed_flags;
3038 NTSTATUS return_value;
3039 struct smbXsrv_session *x = NULL;
3040 bool signing_required = false;
3041 bool encryption_desired = false;
3042 bool encryption_required = false;
3044 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
3046 DO_PROFILE_INC(request);
3048 SMB_ASSERT(!req->request_counters_updated);
3050 /* TODO: verify more things */
3052 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
3053 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
3054 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
3055 DBG_DEBUG("opcode[%s] mid = %"PRIu64"\n",
3056 smb2_opcode_name(opcode),
3057 mid);
3059 if (xconn->protocol >= PROTOCOL_SMB2_02) {
3061 * once the protocol is negotiated
3062 * SMB2_OP_NEGPROT is not allowed anymore
3064 if (opcode == SMB2_OP_NEGPROT) {
3065 /* drop the connection */
3066 return NT_STATUS_INVALID_PARAMETER;
3068 } else {
3070 * if the protocol is not negotiated yet
3071 * only SMB2_OP_NEGPROT is allowed.
3073 if (opcode != SMB2_OP_NEGPROT) {
3074 /* drop the connection */
3075 return NT_STATUS_INVALID_PARAMETER;
3080 * Check if the client provided a valid session id.
3082 * As some command don't require a valid session id
3083 * we defer the check of the session_status
3085 session_status = smbd_smb2_request_check_session(req);
3086 x = req->session;
3087 if (x != NULL) {
3088 signing_required = x->global->signing_flags & SMBXSRV_SIGNING_REQUIRED;
3089 encryption_desired = x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
3090 encryption_required = x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
3093 req->async_internal = false;
3094 req->do_signing = false;
3095 if (opcode != SMB2_OP_SESSSETUP) {
3096 req->do_encryption = encryption_desired;
3097 } else {
3098 req->do_encryption = false;
3100 req->was_encrypted = false;
3101 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
3102 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
3103 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
3105 if (x != NULL && x->global->session_wire_id != tf_session_id) {
3106 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
3107 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
3108 (unsigned long long)x->global->session_wire_id,
3109 (unsigned long long)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 if (rc < 0) {
3815 gnutls_hash_deinit(hash_hnd, NULL);
3816 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3818 gnutls_hash_output(hash_hnd, req->preauth->sha512_value);
3820 rc = gnutls_hash(hash_hnd,
3821 req->preauth->sha512_value,
3822 sizeof(req->preauth->sha512_value));
3823 if (rc < 0) {
3824 gnutls_hash_deinit(hash_hnd, NULL);
3825 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3827 for (i = 1; i < req->out.vector_count; i++) {
3828 rc = gnutls_hash(hash_hnd,
3829 req->out.vector[i].iov_base,
3830 req->out.vector[i].iov_len);
3831 if (rc < 0) {
3832 gnutls_hash_deinit(hash_hnd, NULL);
3833 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3837 gnutls_hash_deinit(hash_hnd, req->preauth->sha512_value);
3839 req->preauth = NULL;
3842 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
3843 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
3844 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
3845 /* Dynamic part is NULL. Chop it off,
3846 We're going to send it via sendfile. */
3847 req->out.vector_count -= 1;
3851 * We're done with this request -
3852 * move it off the "being processed" queue.
3854 DLIST_REMOVE(xconn->smb2.requests, req);
3856 req->queue_entry.mem_ctx = req;
3857 req->queue_entry.vector = req->out.vector;
3858 req->queue_entry.count = req->out.vector_count;
3859 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry);
3860 xconn->smb2.send_queue_len++;
3862 status = smbd_smb2_flush_send_queue(xconn);
3863 if (!NT_STATUS_IS_OK(status)) {
3864 return status;
3867 return NT_STATUS_OK;
3870 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
3872 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
3873 struct tevent_immediate *im,
3874 void *private_data)
3876 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
3877 struct smbd_smb2_request);
3878 struct smbXsrv_connection *xconn = req->xconn;
3879 NTSTATUS status;
3881 TALLOC_FREE(im);
3883 if (DEBUGLEVEL >= 10) {
3884 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
3885 req->current_idx, req->in.vector_count));
3886 print_req_vectors(req);
3889 status = smbd_smb2_request_dispatch(req);
3890 if (!NT_STATUS_IS_OK(status)) {
3891 smbd_server_connection_terminate(xconn, nt_errstr(status));
3892 return;
3895 status = smbd_smb2_request_next_incoming(xconn);
3896 if (!NT_STATUS_IS_OK(status)) {
3897 smbd_server_connection_terminate(xconn, nt_errstr(status));
3898 return;
3902 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
3903 NTSTATUS status,
3904 DATA_BLOB body, DATA_BLOB *dyn,
3905 const char *location)
3907 uint8_t *outhdr;
3908 struct iovec *outbody_v;
3909 struct iovec *outdyn_v;
3910 uint32_t next_command_ofs;
3911 uint64_t mid;
3913 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3914 mid = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
3916 DBG_DEBUG("mid [%"PRIu64"] idx[%d] status[%s] "
3917 "body[%u] dyn[%s:%u] at %s\n",
3918 mid,
3919 req->current_idx,
3920 nt_errstr(status),
3921 (unsigned int)body.length,
3922 dyn ? "yes" : "no",
3923 (unsigned int)(dyn ? dyn->length : 0),
3924 location);
3926 if (body.length < 2) {
3927 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3930 if ((body.length % 2) != 0) {
3931 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3934 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
3935 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
3937 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
3938 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
3940 outbody_v->iov_base = (void *)body.data;
3941 outbody_v->iov_len = body.length;
3943 if (dyn) {
3944 outdyn_v->iov_base = (void *)dyn->data;
3945 outdyn_v->iov_len = dyn->length;
3946 } else {
3947 outdyn_v->iov_base = NULL;
3948 outdyn_v->iov_len = 0;
3952 * See if we need to recalculate the offset to the next response
3954 * Note that all responses may require padding (including the very last
3955 * one).
3957 if (req->out.vector_count >= (2 * SMBD_SMB2_NUM_IOV_PER_REQ)) {
3958 next_command_ofs = SMB2_HDR_BODY;
3959 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
3960 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
3963 if ((next_command_ofs % 8) != 0) {
3964 size_t pad_size = 8 - (next_command_ofs % 8);
3965 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
3967 * if the dyn buffer is empty
3968 * we can use it to add padding
3970 uint8_t *pad;
3972 pad = talloc_zero_array(req,
3973 uint8_t, pad_size);
3974 if (pad == NULL) {
3975 return smbd_smb2_request_error(req,
3976 NT_STATUS_NO_MEMORY);
3979 outdyn_v->iov_base = (void *)pad;
3980 outdyn_v->iov_len = pad_size;
3981 } else {
3983 * For now we copy the dynamic buffer
3984 * and add the padding to the new buffer
3986 size_t old_size;
3987 uint8_t *old_dyn;
3988 size_t new_size;
3989 uint8_t *new_dyn;
3991 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
3992 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
3994 new_size = old_size + pad_size;
3995 new_dyn = talloc_zero_array(req,
3996 uint8_t, new_size);
3997 if (new_dyn == NULL) {
3998 return smbd_smb2_request_error(req,
3999 NT_STATUS_NO_MEMORY);
4002 memcpy(new_dyn, old_dyn, old_size);
4003 memset(new_dyn + old_size, 0, pad_size);
4005 outdyn_v->iov_base = (void *)new_dyn;
4006 outdyn_v->iov_len = new_size;
4008 next_command_ofs += pad_size;
4011 if ((req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) >= req->out.vector_count) {
4012 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
4013 } else {
4014 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
4016 return smbd_smb2_request_reply(req);
4019 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
4020 NTSTATUS status,
4021 uint8_t error_context_count,
4022 DATA_BLOB *info,
4023 const char *location)
4025 struct smbXsrv_connection *xconn = req->xconn;
4026 DATA_BLOB body;
4027 DATA_BLOB _dyn;
4028 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
4029 size_t unread_bytes = smbd_smb2_unread_bytes(req);
4031 DBG_NOTICE("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| "
4032 "at %s\n", req->current_idx, nt_errstr(status),
4033 info ? " +info" : "", location);
4035 if (unread_bytes) {
4036 /* Recvfile error. Drain incoming socket. */
4037 size_t ret;
4039 errno = 0;
4040 ret = drain_socket(xconn->transport.sock, unread_bytes);
4041 if (ret != unread_bytes) {
4042 NTSTATUS error;
4044 if (errno == 0) {
4045 error = NT_STATUS_IO_DEVICE_ERROR;
4046 } else {
4047 error = map_nt_error_from_unix_common(errno);
4050 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
4051 "ret[%u] errno[%d] => %s\n",
4052 (unsigned)unread_bytes,
4053 (unsigned)ret, errno, nt_errstr(error)));
4054 return error;
4058 body.data = outhdr + SMB2_HDR_BODY;
4059 body.length = 8;
4060 SSVAL(body.data, 0, 9);
4061 SCVAL(body.data, 2, error_context_count);
4063 if (info) {
4064 SIVAL(body.data, 0x04, info->length);
4065 } else {
4066 /* Allocated size of req->out.vector[i].iov_base
4067 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
4068 * 1 byte without having to do an alloc.
4070 info = &_dyn;
4071 info->data = ((uint8_t *)outhdr) +
4072 OUTVEC_ALLOC_SIZE - 1;
4073 info->length = 1;
4074 SCVAL(info->data, 0, 0);
4078 * Note: Even if there is an error, continue to process the request.
4079 * per MS-SMB2.
4082 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
4085 struct smbd_smb2_break_state {
4086 struct tevent_req *req;
4087 struct smbd_smb2_send_queue queue_entry;
4088 uint8_t nbt_hdr[NBT_HDR_SIZE];
4089 uint8_t hdr[SMB2_HDR_BODY];
4090 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
4093 static struct tevent_req *smbd_smb2_break_send(TALLOC_CTX *mem_ctx,
4094 struct tevent_context *ev,
4095 struct smbXsrv_connection *xconn,
4096 uint64_t session_id,
4097 const uint8_t *body,
4098 size_t body_len)
4100 struct tevent_req *req = NULL;
4101 struct smbd_smb2_break_state *state = NULL;
4102 NTSTATUS status;
4103 bool ok;
4105 req = tevent_req_create(mem_ctx, &state,
4106 struct smbd_smb2_break_state);
4107 if (req == NULL) {
4108 return NULL;
4111 state->req = req;
4112 tevent_req_defer_callback(req, ev);
4114 SIVAL(state->hdr, 0, SMB2_MAGIC);
4115 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
4116 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
4117 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
4118 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
4119 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
4120 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
4121 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
4122 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
4123 SIVAL(state->hdr, SMB2_HDR_PID, 0);
4124 SIVAL(state->hdr, SMB2_HDR_TID, 0);
4125 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, session_id);
4126 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
4128 state->vector[0] = (struct iovec) {
4129 .iov_base = state->nbt_hdr,
4130 .iov_len = sizeof(state->nbt_hdr)
4133 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
4134 .iov_base = NULL,
4135 .iov_len = 0
4138 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
4139 .iov_base = state->hdr,
4140 .iov_len = sizeof(state->hdr)
4143 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
4144 .iov_base = discard_const_p(uint8_t, body),
4145 .iov_len = body_len,
4149 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
4152 ok = smb2_setup_nbt_length(state->vector,
4153 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
4154 if (!ok) {
4155 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
4156 return tevent_req_post(req, ev);
4160 * We require TCP acks for this PDU to the client!
4161 * We want 5 retransmissions and timeout when the
4162 * retransmission timeout (rto) passed 6 times.
4164 * required_acked_bytes gets a dummy value of
4165 * UINT64_MAX, as long it's in xconn->smb2.send_queue,
4166 * it'll get the real value when it's moved to
4167 * xconn->ack.queue.
4169 * state->queue_entry.ack.req gets completed with
4170 * 1. tevent_req_done(), when all bytes are acked.
4171 * 2a. tevent_req_nterror(NT_STATUS_IO_TIMEOUT), when
4172 * the timeout expired before all bytes were acked.
4173 * 2b. tevent_req_nterror(transport_error), when the
4174 * connection got a disconnect from the kernel.
4176 state->queue_entry.ack.timeout =
4177 timeval_current_ofs_usec(xconn->ack.rto_usecs * 6);
4178 state->queue_entry.ack.required_acked_bytes = UINT64_MAX;
4179 state->queue_entry.ack.req = req;
4180 state->queue_entry.mem_ctx = state;
4181 state->queue_entry.vector = state->vector;
4182 state->queue_entry.count = ARRAY_SIZE(state->vector);
4183 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
4184 xconn->smb2.send_queue_len++;
4186 status = smbd_smb2_flush_send_queue(xconn);
4187 if (tevent_req_nterror(req, status)) {
4188 return tevent_req_post(req, ev);
4191 return req;
4194 static NTSTATUS smbd_smb2_break_recv(struct tevent_req *req)
4196 return tevent_req_simple_recv_ntstatus(req);
4199 struct smbXsrv_pending_break {
4200 struct smbXsrv_pending_break *prev, *next;
4201 struct smbXsrv_client *client;
4202 bool disable_oplock_break_retries;
4203 uint64_t session_id;
4204 uint64_t last_channel_id;
4205 union {
4206 uint8_t generic[1];
4207 uint8_t oplock[0x18];
4208 uint8_t lease[0x2c];
4209 } body;
4210 size_t body_len;
4213 static void smbXsrv_pending_break_done(struct tevent_req *subreq);
4215 static struct smbXsrv_pending_break *smbXsrv_pending_break_create(
4216 struct smbXsrv_client *client,
4217 uint64_t session_id)
4219 struct smbXsrv_pending_break *pb = NULL;
4221 pb = talloc_zero(client, struct smbXsrv_pending_break);
4222 if (pb == NULL) {
4223 return NULL;
4225 pb->client = client;
4226 pb->session_id = session_id;
4227 pb->disable_oplock_break_retries = lp_smb2_disable_oplock_break_retry();
4229 return pb;
4232 static NTSTATUS smbXsrv_pending_break_submit(struct smbXsrv_pending_break *pb);
4234 static NTSTATUS smbXsrv_pending_break_schedule(struct smbXsrv_pending_break *pb)
4236 struct smbXsrv_client *client = pb->client;
4237 NTSTATUS status;
4239 DLIST_ADD_END(client->pending_breaks, pb);
4240 status = smbXsrv_client_pending_breaks_updated(client);
4241 if (!NT_STATUS_IS_OK(status)) {
4242 return status;
4245 status = smbXsrv_pending_break_submit(pb);
4246 if (!NT_STATUS_IS_OK(status)) {
4247 return status;
4250 return NT_STATUS_OK;
4253 static NTSTATUS smbXsrv_pending_break_submit(struct smbXsrv_pending_break *pb)
4255 struct smbXsrv_client *client = pb->client;
4256 struct smbXsrv_session *session = NULL;
4257 struct smbXsrv_connection *xconn = NULL;
4258 struct smbXsrv_connection *oplock_xconn = NULL;
4259 struct tevent_req *subreq = NULL;
4260 NTSTATUS status;
4262 if (pb->session_id != 0) {
4263 status = get_valid_smbXsrv_session(client,
4264 pb->session_id,
4265 &session);
4266 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
4267 return NT_STATUS_ABANDONED;
4269 if (!NT_STATUS_IS_OK(status)) {
4270 return status;
4273 if (pb->last_channel_id != 0) {
4275 * This is what current Windows servers
4276 * do, they don't retry on all available
4277 * channels. They only use the last channel.
4279 * But it doesn't match the specification in
4280 * [MS-SMB2] "3.3.4.6 Object Store Indicates an
4281 * Oplock Break"
4283 * Per default disable_oplock_break_retries is false
4284 * and we behave like the specification.
4286 if (pb->disable_oplock_break_retries) {
4287 return NT_STATUS_ABANDONED;
4292 for (xconn = client->connections; xconn != NULL; xconn = xconn->next) {
4293 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
4294 continue;
4297 if (xconn->channel_id == 0) {
4299 * non-multichannel case
4301 break;
4304 if (session != NULL) {
4305 struct smbXsrv_channel_global0 *c = NULL;
4308 * Having a session means we're handling
4309 * an oplock break and we only need to
4310 * use channels available on the
4311 * session.
4313 status = smbXsrv_session_find_channel(session, xconn, &c);
4314 if (!NT_STATUS_IS_OK(status)) {
4315 continue;
4319 * This is what current Windows servers
4320 * do, they don't retry on all available
4321 * channels. They only use the last channel.
4323 * But it doesn't match the specification
4324 * in [MS-SMB2] "3.3.4.6 Object Store Indicates an
4325 * Oplock Break"
4327 * Per default disable_oplock_break_retries is false
4328 * and we behave like the specification.
4330 if (pb->disable_oplock_break_retries) {
4331 oplock_xconn = xconn;
4332 continue;
4336 if (xconn->channel_id > pb->last_channel_id) {
4338 * multichannel case
4340 break;
4344 if (xconn == NULL) {
4345 xconn = oplock_xconn;
4348 if (xconn == NULL) {
4350 * If there's no remaining connection available
4351 * tell the caller to stop...
4353 return NT_STATUS_ABANDONED;
4356 pb->last_channel_id = xconn->channel_id;
4358 subreq = smbd_smb2_break_send(pb,
4359 client->raw_ev_ctx,
4360 xconn,
4361 pb->session_id,
4362 pb->body.generic,
4363 pb->body_len);
4364 if (subreq == NULL) {
4365 return NT_STATUS_NO_MEMORY;
4367 tevent_req_set_callback(subreq,
4368 smbXsrv_pending_break_done,
4369 pb);
4371 return NT_STATUS_OK;
4374 static void smbXsrv_pending_break_done(struct tevent_req *subreq)
4376 struct smbXsrv_pending_break *pb =
4377 tevent_req_callback_data(subreq,
4378 struct smbXsrv_pending_break);
4379 struct smbXsrv_client *client = pb->client;
4380 NTSTATUS status;
4382 status = smbd_smb2_break_recv(subreq);
4383 TALLOC_FREE(subreq);
4384 if (!NT_STATUS_IS_OK(status)) {
4385 status = smbXsrv_pending_break_submit(pb);
4386 if (NT_STATUS_EQUAL(status, NT_STATUS_ABANDONED)) {
4388 * If there's no remaining connection
4389 * there's no need to send a break again.
4391 goto remove;
4393 if (!NT_STATUS_IS_OK(status)) {
4394 smbd_server_disconnect_client(client, nt_errstr(status));
4395 return;
4397 return;
4400 remove:
4401 DLIST_REMOVE(client->pending_breaks, pb);
4402 TALLOC_FREE(pb);
4404 status = smbXsrv_client_pending_breaks_updated(client);
4405 if (!NT_STATUS_IS_OK(status)) {
4406 smbd_server_disconnect_client(client, nt_errstr(status));
4407 return;
4411 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_client *client,
4412 struct smbXsrv_open *op,
4413 uint8_t oplock_level)
4415 struct smbXsrv_pending_break *pb = NULL;
4416 uint8_t *body = NULL;
4418 pb = smbXsrv_pending_break_create(client,
4419 op->compat->vuid);
4420 if (pb == NULL) {
4421 return NT_STATUS_NO_MEMORY;
4423 pb->body_len = sizeof(pb->body.oplock);
4424 body = pb->body.oplock;
4426 SSVAL(body, 0x00, pb->body_len);
4427 SCVAL(body, 0x02, oplock_level);
4428 SCVAL(body, 0x03, 0); /* reserved */
4429 SIVAL(body, 0x04, 0); /* reserved */
4430 SBVAL(body, 0x08, op->global->open_persistent_id);
4431 SBVAL(body, 0x10, op->global->open_volatile_id);
4433 return smbXsrv_pending_break_schedule(pb);
4436 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_client *client,
4437 uint16_t new_epoch,
4438 uint32_t lease_flags,
4439 struct smb2_lease_key *lease_key,
4440 uint32_t current_lease_state,
4441 uint32_t new_lease_state)
4443 struct smbXsrv_pending_break *pb = NULL;
4444 uint8_t *body = NULL;
4446 pb = smbXsrv_pending_break_create(client,
4447 0); /* no session_id */
4448 if (pb == NULL) {
4449 return NT_STATUS_NO_MEMORY;
4451 pb->body_len = sizeof(pb->body.lease);
4452 body = pb->body.lease;
4454 SSVAL(body, 0x00, pb->body_len);
4455 SSVAL(body, 0x02, new_epoch);
4456 SIVAL(body, 0x04, lease_flags);
4457 SBVAL(body, 0x08, lease_key->data[0]);
4458 SBVAL(body, 0x10, lease_key->data[1]);
4459 SIVAL(body, 0x18, current_lease_state);
4460 SIVAL(body, 0x1c, new_lease_state);
4461 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
4462 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
4463 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
4465 return smbXsrv_pending_break_schedule(pb);
4468 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
4470 NTSTATUS status;
4471 uint32_t flags;
4472 uint64_t file_id_persistent;
4473 uint64_t file_id_volatile;
4474 struct smbXsrv_open *op = NULL;
4475 struct files_struct *fsp = NULL;
4476 const uint8_t *body = NULL;
4479 * This is only called with a pktbuf
4480 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
4481 * bytes
4484 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
4485 /* Transform header. Cannot recvfile. */
4486 return false;
4488 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
4489 /* Not SMB2. Normal error path will cope. */
4490 return false;
4492 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
4493 /* Not SMB2. Normal error path will cope. */
4494 return false;
4496 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
4497 /* Needs to be a WRITE. */
4498 return false;
4500 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
4501 /* Chained. Cannot recvfile. */
4502 return false;
4504 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
4505 if (flags & SMB2_HDR_FLAG_CHAINED) {
4506 /* Chained. Cannot recvfile. */
4507 return false;
4509 if (flags & SMB2_HDR_FLAG_SIGNED) {
4510 /* Signed. Cannot recvfile. */
4511 return false;
4514 body = &state->pktbuf[SMB2_HDR_BODY];
4516 file_id_persistent = BVAL(body, 0x10);
4517 file_id_volatile = BVAL(body, 0x18);
4519 status = smb2srv_open_lookup(state->req->xconn,
4520 file_id_persistent,
4521 file_id_volatile,
4522 0, /* now */
4523 &op);
4524 if (!NT_STATUS_IS_OK(status)) {
4525 return false;
4528 fsp = op->compat;
4529 if (fsp == NULL) {
4530 return false;
4532 if (fsp->conn == NULL) {
4533 return false;
4536 if (IS_IPC(fsp->conn)) {
4537 return false;
4539 if (IS_PRINT(fsp->conn)) {
4540 return false;
4542 if (fsp_is_alternate_stream(fsp)) {
4543 return false;
4546 DEBUG(10,("Doing recvfile write len = %u\n",
4547 (unsigned int)(state->pktfull - state->pktlen)));
4549 return true;
4552 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
4554 struct smbd_server_connection *sconn = xconn->client->sconn;
4555 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
4556 size_t max_send_queue_len;
4557 size_t cur_send_queue_len;
4559 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
4561 * we're not supposed to do any io
4563 return NT_STATUS_OK;
4566 if (state->req != NULL) {
4568 * if there is already a tstream_readv_pdu
4569 * pending, we are done.
4571 return NT_STATUS_OK;
4574 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
4575 cur_send_queue_len = xconn->smb2.send_queue_len;
4577 if (cur_send_queue_len > max_send_queue_len) {
4579 * if we have a lot of requests to send,
4580 * we wait until they are on the wire until we
4581 * ask for the next request.
4583 return NT_STATUS_OK;
4586 /* ask for the next request */
4587 ZERO_STRUCTP(state);
4588 state->req = smbd_smb2_request_allocate(xconn);
4589 if (state->req == NULL) {
4590 return NT_STATUS_NO_MEMORY;
4592 state->req->sconn = sconn;
4593 state->req->xconn = xconn;
4594 state->min_recv_size = lp_min_receive_file_size();
4596 TEVENT_FD_READABLE(xconn->transport.fde);
4598 return NT_STATUS_OK;
4601 NTSTATUS smbd_smb2_process_negprot(struct smbXsrv_connection *xconn,
4602 uint64_t expected_seq_low,
4603 const uint8_t *inpdu, size_t size)
4605 struct smbd_server_connection *sconn = xconn->client->sconn;
4606 NTSTATUS status;
4607 struct smbd_smb2_request *req = NULL;
4609 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
4610 (unsigned int)size));
4612 status = smbd_initialize_smb2(xconn, expected_seq_low);
4613 if (!NT_STATUS_IS_OK(status)) {
4614 smbd_server_connection_terminate(xconn, nt_errstr(status));
4615 return status;
4619 * If a new connection joins the process, when we're
4620 * already in a "pending break cycle", we need to
4621 * turn on the ack checker on the new connection.
4623 status = smbXsrv_client_pending_breaks_updated(xconn->client);
4624 if (!NT_STATUS_IS_OK(status)) {
4626 * If there's a problem, we disconnect the whole
4627 * client with all connections here!
4629 * Instead of just the new connection.
4631 smbd_server_disconnect_client(xconn->client, nt_errstr(status));
4632 return status;
4635 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
4636 if (!NT_STATUS_IS_OK(status)) {
4637 smbd_server_connection_terminate(xconn, nt_errstr(status));
4638 return status;
4641 status = smbd_smb2_request_validate(req);
4642 if (!NT_STATUS_IS_OK(status)) {
4643 smbd_server_connection_terminate(xconn, nt_errstr(status));
4644 return status;
4647 status = smbd_smb2_request_setup_out(req);
4648 if (!NT_STATUS_IS_OK(status)) {
4649 smbd_server_connection_terminate(xconn, nt_errstr(status));
4650 return status;
4653 #ifdef WITH_PROFILE
4655 * this was already counted at the SMB1 layer =>
4656 * smbd_smb2_request_dispatch() should not count it twice.
4658 if (profile_p->values.request_stats.count > 0) {
4659 profile_p->values.request_stats.count--;
4661 #endif
4662 status = smbd_smb2_request_dispatch(req);
4663 if (!NT_STATUS_IS_OK(status)) {
4664 smbd_server_connection_terminate(xconn, nt_errstr(status));
4665 return status;
4668 status = smbd_smb2_request_next_incoming(xconn);
4669 if (!NT_STATUS_IS_OK(status)) {
4670 smbd_server_connection_terminate(xconn, nt_errstr(status));
4671 return status;
4674 sconn->num_requests++;
4675 return NT_STATUS_OK;
4678 static int socket_error_from_errno(int ret,
4679 int sys_errno,
4680 bool *retry)
4682 *retry = false;
4684 if (ret >= 0) {
4685 return 0;
4688 if (ret != -1) {
4689 return EIO;
4692 if (sys_errno == 0) {
4693 return EIO;
4696 if (sys_errno == EINTR) {
4697 *retry = true;
4698 return sys_errno;
4701 if (sys_errno == EINPROGRESS) {
4702 *retry = true;
4703 return sys_errno;
4706 if (sys_errno == EAGAIN) {
4707 *retry = true;
4708 return sys_errno;
4711 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
4712 if (sys_errno == ENOMEM) {
4713 *retry = true;
4714 return sys_errno;
4717 #ifdef EWOULDBLOCK
4718 #if EWOULDBLOCK != EAGAIN
4719 if (sys_errno == EWOULDBLOCK) {
4720 *retry = true;
4721 return sys_errno;
4723 #endif
4724 #endif
4726 return sys_errno;
4729 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
4731 int ret;
4732 int err;
4733 bool retry;
4734 NTSTATUS status;
4736 if (xconn->smb2.send_queue == NULL) {
4737 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
4738 return NT_STATUS_OK;
4741 while (xconn->smb2.send_queue != NULL) {
4742 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
4743 unsigned sendmsg_flags = 0;
4744 bool ok;
4745 struct msghdr msg;
4747 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
4749 * we're not supposed to do any io
4750 * just flush all pending stuff.
4752 xconn->smb2.send_queue_len--;
4753 DLIST_REMOVE(xconn->smb2.send_queue, e);
4755 talloc_free(e->mem_ctx);
4756 continue;
4759 if (e->sendfile_header != NULL) {
4760 size_t size = 0;
4761 size_t i = 0;
4762 uint8_t *buf;
4764 status = NT_STATUS_INTERNAL_ERROR;
4766 for (i=0; i < e->count; i++) {
4767 size += e->vector[i].iov_len;
4770 if (size <= e->sendfile_header->length) {
4771 buf = e->sendfile_header->data;
4772 } else {
4773 buf = talloc_array(e->mem_ctx, uint8_t, size);
4774 if (buf == NULL) {
4775 return NT_STATUS_NO_MEMORY;
4779 size = 0;
4780 for (i=0; i < e->count; i++) {
4781 memcpy(buf+size,
4782 e->vector[i].iov_base,
4783 e->vector[i].iov_len);
4784 size += e->vector[i].iov_len;
4787 e->sendfile_header->data = buf;
4788 e->sendfile_header->length = size;
4789 e->sendfile_status = &status;
4790 e->count = 0;
4792 xconn->smb2.send_queue_len--;
4793 DLIST_REMOVE(xconn->smb2.send_queue, e);
4795 size += e->sendfile_body_size;
4798 * This triggers the sendfile path via
4799 * the destructor.
4801 talloc_free(e->mem_ctx);
4803 if (!NT_STATUS_IS_OK(status)) {
4804 smbXsrv_connection_disconnect_transport(xconn,
4805 status);
4806 return status;
4808 xconn->ack.unacked_bytes += size;
4809 continue;
4812 msg = (struct msghdr) {
4813 .msg_iov = e->vector,
4814 .msg_iovlen = e->count,
4817 #ifdef MSG_NOSIGNAL
4818 sendmsg_flags |= MSG_NOSIGNAL;
4819 #endif
4820 #ifdef MSG_DONTWAIT
4821 sendmsg_flags |= MSG_DONTWAIT;
4822 #endif
4824 ret = sendmsg(xconn->transport.sock, &msg, sendmsg_flags);
4825 if (ret == 0) {
4826 /* propagate end of file */
4827 return NT_STATUS_INTERNAL_ERROR;
4829 err = socket_error_from_errno(ret, errno, &retry);
4830 if (retry) {
4831 /* retry later */
4832 TEVENT_FD_WRITEABLE(xconn->transport.fde);
4833 return NT_STATUS_OK;
4835 if (err != 0) {
4836 status = map_nt_error_from_unix_common(err);
4837 smbXsrv_connection_disconnect_transport(xconn,
4838 status);
4839 return status;
4842 xconn->ack.unacked_bytes += ret;
4844 ok = iov_advance(&e->vector, &e->count, ret);
4845 if (!ok) {
4846 return NT_STATUS_INTERNAL_ERROR;
4849 if (e->count > 0) {
4850 /* we have more to write */
4851 TEVENT_FD_WRITEABLE(xconn->transport.fde);
4852 return NT_STATUS_OK;
4855 xconn->smb2.send_queue_len--;
4856 DLIST_REMOVE(xconn->smb2.send_queue, e);
4858 if (e->ack.req == NULL) {
4859 talloc_free(e->mem_ctx);
4860 continue;
4863 e->ack.required_acked_bytes = xconn->ack.unacked_bytes;
4864 DLIST_ADD_END(xconn->ack.queue, e);
4868 * Restart reads if we were blocked on
4869 * draining the send queue.
4872 status = smbd_smb2_request_next_incoming(xconn);
4873 if (!NT_STATUS_IS_OK(status)) {
4874 return status;
4877 return NT_STATUS_OK;
4880 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
4881 uint16_t fde_flags)
4883 struct smbd_server_connection *sconn = xconn->client->sconn;
4884 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
4885 struct smbd_smb2_request *req = NULL;
4886 size_t min_recvfile_size = UINT32_MAX;
4887 unsigned recvmsg_flags = 0;
4888 int ret;
4889 int err;
4890 bool retry;
4891 NTSTATUS status;
4892 NTTIME now;
4893 struct msghdr msg;
4895 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
4897 * we're not supposed to do any io
4899 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
4900 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
4901 return NT_STATUS_OK;
4904 if (fde_flags & TEVENT_FD_WRITE) {
4905 status = smbd_smb2_flush_send_queue(xconn);
4906 if (!NT_STATUS_IS_OK(status)) {
4907 return status;
4911 if (!(fde_flags & TEVENT_FD_READ)) {
4912 return NT_STATUS_OK;
4915 if (state->req == NULL) {
4916 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
4917 return NT_STATUS_OK;
4920 again:
4921 if (!state->hdr.done) {
4922 state->hdr.done = true;
4924 state->vector.iov_base = (void *)state->hdr.nbt;
4925 state->vector.iov_len = NBT_HDR_SIZE;
4928 msg = (struct msghdr) {
4929 .msg_iov = &state->vector,
4930 .msg_iovlen = 1,
4933 #ifdef MSG_NOSIGNAL
4934 recvmsg_flags |= MSG_NOSIGNAL;
4935 #endif
4936 #ifdef MSG_DONTWAIT
4937 recvmsg_flags |= MSG_DONTWAIT;
4938 #endif
4940 ret = recvmsg(xconn->transport.sock, &msg, recvmsg_flags);
4941 if (ret == 0) {
4942 /* propagate end of file */
4943 status = NT_STATUS_END_OF_FILE;
4944 smbXsrv_connection_disconnect_transport(xconn,
4945 status);
4946 return status;
4948 err = socket_error_from_errno(ret, errno, &retry);
4949 if (retry) {
4950 /* retry later */
4951 TEVENT_FD_READABLE(xconn->transport.fde);
4952 return NT_STATUS_OK;
4954 if (err != 0) {
4955 status = map_nt_error_from_unix_common(err);
4956 smbXsrv_connection_disconnect_transport(xconn,
4957 status);
4958 return status;
4961 if (ret < state->vector.iov_len) {
4962 uint8_t *base;
4963 base = (uint8_t *)state->vector.iov_base;
4964 base += ret;
4965 state->vector.iov_base = (void *)base;
4966 state->vector.iov_len -= ret;
4967 /* we have more to read */
4968 TEVENT_FD_READABLE(xconn->transport.fde);
4969 return NT_STATUS_OK;
4972 if (state->pktlen > 0) {
4973 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
4975 * Not a possible receivefile write.
4976 * Read the rest of the data.
4978 state->doing_receivefile = false;
4980 state->pktbuf = talloc_realloc(state->req,
4981 state->pktbuf,
4982 uint8_t,
4983 state->pktfull);
4984 if (state->pktbuf == NULL) {
4985 return NT_STATUS_NO_MEMORY;
4988 state->vector.iov_base = (void *)(state->pktbuf +
4989 state->pktlen);
4990 state->vector.iov_len = (state->pktfull -
4991 state->pktlen);
4993 state->pktlen = state->pktfull;
4994 goto again;
4998 * Either this is a receivefile write so we've
4999 * done a short read, or if not we have all the data.
5001 goto got_full;
5005 * Now we analyze the NBT header
5007 if (state->hdr.nbt[0] != 0x00) {
5008 state->min_recv_size = 0;
5010 state->pktfull = smb2_len(state->hdr.nbt);
5011 if (state->pktfull == 0) {
5012 goto got_full;
5015 if (state->min_recv_size != 0) {
5016 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
5017 min_recvfile_size += state->min_recv_size;
5020 if (state->pktfull > min_recvfile_size) {
5022 * Might be a receivefile write. Read the SMB2 HEADER +
5023 * SMB2_WRITE header first. Set 'doing_receivefile'
5024 * as we're *attempting* receivefile write. If this
5025 * turns out not to be a SMB2_WRITE request or otherwise
5026 * not suitable then we'll just read the rest of the data
5027 * the next time this function is called.
5029 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
5030 state->doing_receivefile = true;
5031 } else {
5032 state->pktlen = state->pktfull;
5035 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
5036 if (state->pktbuf == NULL) {
5037 return NT_STATUS_NO_MEMORY;
5040 state->vector.iov_base = (void *)state->pktbuf;
5041 state->vector.iov_len = state->pktlen;
5043 goto again;
5045 got_full:
5047 if (state->hdr.nbt[0] != 0x00) {
5048 DEBUG(1,("ignore NBT[0x%02X] msg\n",
5049 state->hdr.nbt[0]));
5051 req = state->req;
5052 ZERO_STRUCTP(state);
5053 state->req = req;
5054 state->min_recv_size = lp_min_receive_file_size();
5055 req = NULL;
5056 goto again;
5059 req = state->req;
5060 state->req = NULL;
5062 req->request_time = timeval_current();
5063 now = timeval_to_nttime(&req->request_time);
5065 status = smbd_smb2_inbuf_parse_compound(xconn,
5066 now,
5067 state->pktbuf,
5068 state->pktlen,
5069 req,
5070 &req->in.vector,
5071 &req->in.vector_count);
5072 if (!NT_STATUS_IS_OK(status)) {
5073 return status;
5076 if (state->doing_receivefile) {
5077 req->smb1req = talloc_zero(req, struct smb_request);
5078 if (req->smb1req == NULL) {
5079 return NT_STATUS_NO_MEMORY;
5081 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
5084 ZERO_STRUCTP(state);
5086 req->current_idx = 1;
5088 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
5089 req->current_idx, req->in.vector_count));
5091 status = smbd_smb2_request_validate(req);
5092 if (!NT_STATUS_IS_OK(status)) {
5093 return status;
5096 status = smbd_smb2_request_setup_out(req);
5097 if (!NT_STATUS_IS_OK(status)) {
5098 return status;
5101 status = smbd_smb2_request_dispatch(req);
5102 if (!NT_STATUS_IS_OK(status)) {
5103 return status;
5106 sconn->num_requests++;
5108 /* The timeout_processing function isn't run nearly
5109 often enough to implement 'max log size' without
5110 overrunning the size of the file by many megabytes.
5111 This is especially true if we are running at debug
5112 level 10. Checking every 50 SMB2s is a nice
5113 tradeoff of performance vs log file size overrun. */
5115 if ((sconn->num_requests % 50) == 0 &&
5116 need_to_check_log_size()) {
5117 change_to_root_user();
5118 check_log_size();
5121 status = smbd_smb2_request_next_incoming(xconn);
5122 if (!NT_STATUS_IS_OK(status)) {
5123 return status;
5126 return NT_STATUS_OK;
5129 static void smbd_smb2_connection_handler(struct tevent_context *ev,
5130 struct tevent_fd *fde,
5131 uint16_t flags,
5132 void *private_data)
5134 struct smbXsrv_connection *xconn =
5135 talloc_get_type_abort(private_data,
5136 struct smbXsrv_connection);
5137 NTSTATUS status;
5139 status = smbd_smb2_io_handler(xconn, flags);
5140 if (!NT_STATUS_IS_OK(status)) {
5141 smbd_server_connection_terminate(xconn, nt_errstr(status));
5142 return;