2 Unix SMB/CIFS implementation.
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/>.
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../libcli/smb/smb_common.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "../lib/util/tevent_ntstatus.h"
28 #include "smbprofile.h"
29 #include "../lib/util/bitmap.h"
30 #include "../librpc/gen_ndr/krb5pac.h"
31 #include "lib/util/iov_buf.h"
33 #include "libcli/smb/smbXcli_base.h"
35 #include "lib/crypto/gnutls_helpers.h"
36 #include <gnutls/gnutls.h>
37 #include <gnutls/crypto.h>
40 #define DBGC_CLASS DBGC_SMB2
42 static void smbd_smb2_connection_handler(struct tevent_context *ev,
43 struct tevent_fd *fde,
46 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn);
48 static const struct smbd_smb2_dispatch_table {
55 bool allow_invalid_fileid;
57 } smbd_smb2_table[] = {
58 #define _OP(o) .opcode = o, .name = #o
63 _OP(SMB2_OP_SESSSETUP),
73 * This call needs to be run as root.
75 * smbd_smb2_request_process_tcon()
76 * calls make_connection_snum(), which will call
77 * change_to_user(), when needed.
101 .need_session = true,
106 .need_session = true,
112 .need_session = true,
117 .need_session = true,
120 .allow_invalid_fileid = true,
126 _OP(SMB2_OP_KEEPALIVE),
129 _OP(SMB2_OP_QUERY_DIRECTORY),
130 .need_session = true,
135 .need_session = true,
139 _OP(SMB2_OP_GETINFO),
140 .need_session = true,
144 _OP(SMB2_OP_SETINFO),
145 .need_session = true,
151 .need_session = true,
156 * as LEASE breaks does not
162 const char *smb2_opcode_name(uint16_t opcode)
164 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
165 return "Bad SMB2 opcode";
167 return smbd_smb2_table[opcode].name;
170 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
172 const struct smbd_smb2_dispatch_table *ret = NULL;
174 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
178 ret = &smbd_smb2_table[opcode];
180 SMB_ASSERT(ret->opcode == opcode);
185 static void print_req_vectors(const struct smbd_smb2_request *req)
189 for (i = 0; i < req->in.vector_count; i++) {
190 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
192 (unsigned int)req->in.vector[i].iov_len);
194 for (i = 0; i < req->out.vector_count; i++) {
195 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
197 (unsigned int)req->out.vector[i].iov_len);
201 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
203 if (size < (4 + SMB2_HDR_BODY)) {
207 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
214 bool smbd_smb2_is_compound(const struct smbd_smb2_request *req)
216 return req->in.vector_count >= (2*SMBD_SMB2_NUM_IOV_PER_REQ);
219 static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn,
220 uint64_t expected_seq_low)
222 TALLOC_FREE(xconn->transport.fde);
224 xconn->smb2.credits.seq_low = expected_seq_low;
225 xconn->smb2.credits.seq_range = 1;
226 xconn->smb2.credits.granted = 1;
227 xconn->smb2.credits.max = lp_smb2_max_credits();
228 xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
229 xconn->smb2.credits.max);
230 if (xconn->smb2.credits.bitmap == NULL) {
231 return NT_STATUS_NO_MEMORY;
234 xconn->transport.fde = tevent_add_fd(
235 xconn->client->raw_ev_ctx,
237 xconn->transport.sock,
239 smbd_smb2_connection_handler,
241 if (xconn->transport.fde == NULL) {
242 return NT_STATUS_NO_MEMORY;
245 /* Ensure child is set to non-blocking mode */
246 set_blocking(xconn->transport.sock, false);
250 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
251 #define _smb2_setlen(_buf,len) do { \
252 uint8_t *buf = (uint8_t *)_buf; \
254 buf[1] = ((len)&0xFF0000)>>16; \
255 buf[2] = ((len)&0xFF00)>>8; \
256 buf[3] = (len)&0xFF; \
259 static bool smb2_setup_nbt_length(struct iovec *vector, int count)
267 len = iov_buflen(vector+1, count-1);
269 if ((len == -1) || (len > 0xFFFFFF)) {
273 _smb2_setlen(vector[0].iov_base, len);
277 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
279 if (req->first_key.length > 0) {
280 data_blob_clear_free(&req->first_key);
282 if (req->last_key.length > 0) {
283 data_blob_clear_free(&req->last_key);
288 void smb2_request_set_async_internal(struct smbd_smb2_request *req,
291 req->async_internal = async_internal;
294 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
296 TALLOC_CTX *mem_pool;
297 struct smbd_smb2_request *req;
300 /* Enable this to find subtle valgrind errors. */
301 mem_pool = talloc_init("smbd_smb2_request_allocate");
303 mem_pool = talloc_tos();
305 if (mem_pool == NULL) {
309 req = talloc_zero(mem_pool, struct smbd_smb2_request);
311 talloc_free(mem_pool);
314 talloc_reparent(mem_pool, mem_ctx, req);
316 TALLOC_FREE(mem_pool);
319 req->last_session_id = UINT64_MAX;
320 req->last_tid = UINT32_MAX;
322 talloc_set_destructor(req, smbd_smb2_request_destructor);
327 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
331 struct smbd_smb2_request *req,
335 TALLOC_CTX *mem_ctx = req;
339 uint8_t *first_hdr = buf;
340 size_t verified_buflen = 0;
345 * Note: index '0' is reserved for the transport protocol
347 iov = req->in._vector;
349 while (taken < buflen) {
350 size_t len = buflen - taken;
351 uint8_t *hdr = first_hdr + taken;
354 size_t next_command_ofs;
356 uint8_t *body = NULL;
359 struct iovec *iov_alloc = NULL;
361 if (iov != req->in._vector) {
365 if (verified_buflen > taken) {
366 len = verified_buflen - taken;
373 DEBUG(10, ("%d bytes left, expected at least %d\n",
377 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
378 struct smbXsrv_session *s = NULL;
380 struct iovec tf_iov[2];
384 if (xconn->protocol < PROTOCOL_SMB2_24) {
385 DEBUG(10, ("Got SMB2_TRANSFORM header, "
386 "but dialect[0x%04X] is used\n",
387 xconn->smb2.server.dialect));
391 if (xconn->smb2.server.cipher == 0) {
392 DEBUG(10, ("Got SMB2_TRANSFORM header, "
393 "but not negotiated "
394 "client[0x%08X] server[0x%08X]\n",
395 xconn->smb2.client.capabilities,
396 xconn->smb2.server.capabilities));
400 if (len < SMB2_TF_HDR_SIZE) {
401 DEBUG(1, ("%d bytes left, expected at least %d\n",
402 (int)len, SMB2_TF_HDR_SIZE));
406 tf_len = SMB2_TF_HDR_SIZE;
409 hdr = first_hdr + taken;
410 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
411 uid = BVAL(tf, SMB2_TF_SESSION_ID);
413 if (len < SMB2_TF_HDR_SIZE + enc_len) {
414 DEBUG(1, ("%d bytes left, expected at least %d\n",
416 (int)(SMB2_TF_HDR_SIZE + enc_len)));
420 status = smb2srv_session_lookup_conn(xconn, uid, now,
423 DEBUG(1, ("invalid session[%llu] in "
424 "SMB2_TRANSFORM header\n",
425 (unsigned long long)uid));
426 TALLOC_FREE(iov_alloc);
427 return NT_STATUS_USER_SESSION_DELETED;
430 tf_iov[0].iov_base = (void *)tf;
431 tf_iov[0].iov_len = tf_len;
432 tf_iov[1].iov_base = (void *)hdr;
433 tf_iov[1].iov_len = enc_len;
435 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
436 xconn->smb2.server.cipher,
438 if (!NT_STATUS_IS_OK(status)) {
439 TALLOC_FREE(iov_alloc);
443 verified_buflen = taken + enc_len;
448 * We need the header plus the body length field
451 if (len < SMB2_HDR_BODY + 2) {
454 (IVAL(hdr, 0) == SMB_SUICIDE_PACKET) &&
455 lp_parm_bool(-1, "smbd", "suicide mode", false)) {
456 uint8_t exitcode = CVAL(hdr, 4);
457 DBG_WARNING("SUICIDE: Exiting immediately "
458 "with code %"PRIu8"\n",
463 DEBUG(10, ("%d bytes left, expected at least %d\n",
464 (int)len, SMB2_HDR_BODY));
467 if (IVAL(hdr, 0) != SMB2_MAGIC) {
468 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
472 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
473 DEBUG(10, ("Got HDR len %d, expected %d\n",
474 SVAL(hdr, 4), SMB2_HDR_BODY));
479 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
480 body_size = SVAL(hdr, SMB2_HDR_BODY);
482 if (next_command_ofs != 0) {
483 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
486 if (next_command_ofs > full_size) {
489 full_size = next_command_ofs;
496 if (body_size > (full_size - SMB2_HDR_BODY)) {
498 * let the caller handle the error
500 body_size = full_size - SMB2_HDR_BODY;
502 body = hdr + SMB2_HDR_BODY;
503 dyn = body + body_size;
504 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
506 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
507 struct iovec *iov_tmp = NULL;
509 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
512 SMBD_SMB2_NUM_IOV_PER_REQ);
513 if (iov_tmp == NULL) {
514 TALLOC_FREE(iov_alloc);
515 return NT_STATUS_NO_MEMORY;
518 if (iov_alloc == NULL) {
521 sizeof(req->in._vector));
527 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
529 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
530 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
531 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
532 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
533 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
534 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
535 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
536 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
546 if (iov != req->in._vector) {
549 return NT_STATUS_INVALID_PARAMETER;
552 static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
553 const uint8_t *_inpdu, size_t size,
554 struct smbd_smb2_request **_req)
556 struct smbd_server_connection *sconn = xconn->client->sconn;
557 struct smbd_smb2_request *req;
558 uint32_t protocol_version;
559 uint8_t *inpdu = NULL;
560 const uint8_t *inhdr = NULL;
562 uint32_t next_command_ofs;
566 if (size < (SMB2_HDR_BODY + 2)) {
567 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
568 return NT_STATUS_INVALID_PARAMETER;
573 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
574 if (protocol_version != SMB2_MAGIC) {
575 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
577 return NT_STATUS_INVALID_PARAMETER;
580 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
581 if (cmd != SMB2_OP_NEGPROT) {
582 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
584 return NT_STATUS_INVALID_PARAMETER;
587 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
588 if (next_command_ofs != 0) {
589 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
591 return NT_STATUS_INVALID_PARAMETER;
594 req = smbd_smb2_request_allocate(xconn);
596 return NT_STATUS_NO_MEMORY;
601 inpdu = talloc_memdup(req, _inpdu, size);
603 return NT_STATUS_NO_MEMORY;
606 req->request_time = timeval_current();
607 now = timeval_to_nttime(&req->request_time);
609 status = smbd_smb2_inbuf_parse_compound(xconn,
613 req, &req->in.vector,
614 &req->in.vector_count);
615 if (!NT_STATUS_IS_OK(status)) {
620 req->current_idx = 1;
626 static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
627 uint64_t message_id, uint64_t seq_id)
629 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
633 seq_tmp = xconn->smb2.credits.seq_low;
634 if (seq_id < seq_tmp) {
635 DBGC_ERR(DBGC_SMB2_CREDITS,
636 "smb2_validate_sequence_number: bad message_id "
637 "%llu (sequence id %llu) "
638 "(granted = %u, low = %llu, range = %u)\n",
639 (unsigned long long)message_id,
640 (unsigned long long)seq_id,
641 (unsigned int)xconn->smb2.credits.granted,
642 (unsigned long long)xconn->smb2.credits.seq_low,
643 (unsigned int)xconn->smb2.credits.seq_range);
647 seq_tmp += xconn->smb2.credits.seq_range;
648 if (seq_id >= seq_tmp) {
649 DBGC_ERR(DBGC_SMB2_CREDITS,
650 "smb2_validate_sequence_number: bad message_id "
651 "%llu (sequence id %llu) "
652 "(granted = %u, low = %llu, range = %u)\n",
653 (unsigned long long)message_id,
654 (unsigned long long)seq_id,
655 (unsigned int)xconn->smb2.credits.granted,
656 (unsigned long long)xconn->smb2.credits.seq_low,
657 (unsigned int)xconn->smb2.credits.seq_range);
661 offset = seq_id % xconn->smb2.credits.max;
663 if (bitmap_query(credits_bm, offset)) {
664 DBGC_ERR(DBGC_SMB2_CREDITS,
665 "smb2_validate_sequence_number: duplicate message_id "
666 "%llu (sequence id %llu) "
667 "(granted = %u, low = %llu, range = %u) "
669 (unsigned long long)message_id,
670 (unsigned long long)seq_id,
671 (unsigned int)xconn->smb2.credits.granted,
672 (unsigned long long)xconn->smb2.credits.seq_low,
673 (unsigned int)xconn->smb2.credits.seq_range,
678 /* Mark the message_ids as seen in the bitmap. */
679 bitmap_set(credits_bm, offset);
681 if (seq_id != xconn->smb2.credits.seq_low) {
686 * Move the window forward by all the message_id's
689 while (bitmap_query(credits_bm, offset)) {
690 DBGC_DEBUG(DBGC_SMB2_CREDITS,
691 "smb2_validate_sequence_number: clearing "
692 "id %llu (position %u) from bitmap\n",
693 (unsigned long long)(xconn->smb2.credits.seq_low),
695 bitmap_clear(credits_bm, offset);
697 xconn->smb2.credits.seq_low += 1;
698 xconn->smb2.credits.seq_range -= 1;
699 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
705 static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
706 const uint8_t *inhdr)
708 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
709 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
710 uint16_t credit_charge = 1;
713 if (opcode == SMB2_OP_CANCEL) {
714 /* SMB2_CANCEL requests by definition resend messageids. */
718 if (xconn->smb2.credits.multicredit) {
719 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
720 credit_charge = MAX(credit_charge, 1);
725 ("smb2_validate_message_id: mid %llu (charge %llu), "
726 "credits_granted %llu, "
727 "seqnum low/range: %llu/%llu\n",
728 (unsigned long long) message_id,
729 (unsigned long long) credit_charge,
730 (unsigned long long) xconn->smb2.credits.granted,
731 (unsigned long long) xconn->smb2.credits.seq_low,
732 (unsigned long long) xconn->smb2.credits.seq_range));
734 if (xconn->smb2.credits.granted < credit_charge) {
735 DBGC_ERR(DBGC_SMB2_CREDITS,
736 "smb2_validate_message_id: client used more "
737 "credits than granted, mid %llu, charge %llu, "
738 "credits_granted %llu, "
739 "seqnum low/range: %llu/%llu\n",
740 (unsigned long long) message_id,
741 (unsigned long long) credit_charge,
742 (unsigned long long) xconn->smb2.credits.granted,
743 (unsigned long long) xconn->smb2.credits.seq_low,
744 (unsigned long long) xconn->smb2.credits.seq_range);
749 * now check the message ids
751 * for multi-credit requests we need to check all current mid plus
752 * the implicit mids caused by the credit charge
753 * e.g. current mid = 15, charge 5 => mark 15-19 as used
756 for (i = 0; i <= (credit_charge-1); i++) {
757 uint64_t id = message_id + i;
762 ("Iterating mid %llu charge %u (sequence %llu)\n",
763 (unsigned long long)message_id,
765 (unsigned long long)id));
767 ok = smb2_validate_sequence_number(xconn, message_id, id);
773 /* substract used credits */
774 xconn->smb2.credits.granted -= credit_charge;
779 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
784 count = req->in.vector_count;
786 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
787 /* It's not a SMB2 request */
788 return NT_STATUS_INVALID_PARAMETER;
791 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
792 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
793 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
794 const uint8_t *inhdr = NULL;
796 if (hdr->iov_len != SMB2_HDR_BODY) {
797 return NT_STATUS_INVALID_PARAMETER;
800 if (body->iov_len < 2) {
801 return NT_STATUS_INVALID_PARAMETER;
804 inhdr = (const uint8_t *)hdr->iov_base;
806 /* Check the SMB2 header */
807 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
808 return NT_STATUS_INVALID_PARAMETER;
811 if (!smb2_validate_message_id(req->xconn, inhdr)) {
812 return NT_STATUS_INVALID_PARAMETER;
819 static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
820 const struct iovec *in_vector,
821 struct iovec *out_vector)
823 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
824 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
825 uint16_t credit_charge = 1;
826 uint16_t credits_requested;
830 uint16_t credits_granted = 0;
831 uint64_t credits_possible;
832 uint16_t current_max_credits;
835 * first we grant only 1/16th of the max range.
837 * Windows also starts with the 1/16th and then grants
838 * more later. I was only able to trigger higher
839 * values, when using a very high credit charge.
841 * TODO: scale up depending on load, free memory
843 * Maybe also on the relationship between number
844 * of requests and the used sequence number.
845 * Which means we would grant more credits
846 * for client which use multi credit requests.
848 * The above is what Windows Server < 2016 is doing,
849 * but new servers use all credits (8192 by default).
851 current_max_credits = xconn->smb2.credits.max;
852 current_max_credits = MAX(current_max_credits, 1);
854 if (xconn->smb2.credits.multicredit) {
855 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
856 credit_charge = MAX(credit_charge, 1);
859 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
860 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
861 credits_requested = MAX(credits_requested, 1);
862 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
863 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
865 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
867 if (xconn->smb2.credits.max < credit_charge) {
868 smbd_server_connection_terminate(xconn,
869 "client error: credit charge > max credits\n");
873 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
875 * In case we already send an async interim
876 * response, we should not grant
877 * credits on the final response.
881 uint16_t additional_possible =
882 xconn->smb2.credits.max - credit_charge;
883 uint16_t additional_max = 0;
884 uint16_t additional_credits = credits_requested - 1;
887 case SMB2_OP_NEGPROT:
889 case SMB2_OP_SESSSETUP:
891 * Windows 2012 RC1 starts to grant
893 * with a successful session setup
895 if (NT_STATUS_IS_OK(out_status)) {
896 additional_max = xconn->smb2.credits.max;
901 * Windows Server < 2016 and older Samba versions
902 * used to only grant additional credits in
903 * chunks of 32 credits.
905 * But we match Windows Server 2016 and grant
906 * all credits as requested.
908 additional_max = xconn->smb2.credits.max;
912 additional_max = MIN(additional_max, additional_possible);
913 additional_credits = MIN(additional_credits, additional_max);
915 credits_granted = credit_charge + additional_credits;
919 * sequence numbers should not wrap
921 * 1. calculate the possible credits until
922 * the sequence numbers start to wrap on 64-bit.
924 * 2. UINT64_MAX is used for Break Notifications.
926 * 2. truncate the possible credits to the maximum
927 * credits we want to grant to the client in total.
929 * 3. remove the range we'll already granted to the client
930 * this makes sure the client consumes the lowest sequence
931 * number, before we can grant additional credits.
933 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
934 if (credits_possible > 0) {
935 /* remove UINT64_MAX */
936 credits_possible -= 1;
938 credits_possible = MIN(credits_possible, current_max_credits);
939 credits_possible -= xconn->smb2.credits.seq_range;
941 credits_granted = MIN(credits_granted, credits_possible);
943 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
944 xconn->smb2.credits.granted += credits_granted;
945 xconn->smb2.credits.seq_range += credits_granted;
947 DBGC_DEBUG(DBGC_SMB2_CREDITS,
948 "smb2_set_operation_credit: requested %u, charge %u, "
949 "granted %u, current possible/max %u/%u, "
950 "total granted/max/low/range %u/%u/%llu/%u\n",
951 (unsigned int)credits_requested,
952 (unsigned int)credit_charge,
953 (unsigned int)credits_granted,
954 (unsigned int)credits_possible,
955 (unsigned int)current_max_credits,
956 (unsigned int)xconn->smb2.credits.granted,
957 (unsigned int)xconn->smb2.credits.max,
958 (unsigned long long)xconn->smb2.credits.seq_low,
959 (unsigned int)xconn->smb2.credits.seq_range);
962 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
963 struct smbd_smb2_request *outreq)
966 uint16_t total_credits = 0;
968 count = outreq->out.vector_count;
970 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
971 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
972 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
973 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
975 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
977 /* To match Windows, count up what we
979 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
980 /* Set to zero in all but the last reply. */
981 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
982 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
984 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
989 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
991 if (req->current_idx <= 1) {
992 if (size <= sizeof(req->out._body)) {
993 return data_blob_const(req->out._body, size);
997 return data_blob_talloc(req, NULL, size);
1000 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
1002 struct smbXsrv_connection *xconn = req->xconn;
1003 TALLOC_CTX *mem_ctx;
1004 struct iovec *vector;
1009 count = req->in.vector_count;
1010 if (count <= ARRAY_SIZE(req->out._vector)) {
1012 vector = req->out._vector;
1014 vector = talloc_zero_array(req, struct iovec, count);
1015 if (vector == NULL) {
1016 return NT_STATUS_NO_MEMORY;
1021 vector[0].iov_base = req->out.nbt_hdr;
1022 vector[0].iov_len = 4;
1023 SIVAL(req->out.nbt_hdr, 0, 0);
1025 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
1026 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
1027 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
1028 uint8_t *outhdr = NULL;
1029 uint8_t *outbody = NULL;
1030 uint32_t next_command_ofs = 0;
1031 struct iovec *current = &vector[idx];
1033 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
1034 /* we have a next command -
1035 * setup for the error case. */
1036 next_command_ofs = SMB2_HDR_BODY + 9;
1040 outhdr = req->out._hdr;
1042 outhdr = talloc_zero_array(mem_ctx, uint8_t,
1044 if (outhdr == NULL) {
1045 return NT_STATUS_NO_MEMORY;
1049 outbody = outhdr + SMB2_HDR_BODY;
1052 * SMBD_SMB2_TF_IOV_OFS might be used later
1054 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1055 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1057 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
1058 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1060 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1061 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1063 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1064 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1066 /* setup the SMB2 header */
1067 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1068 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1069 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1070 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1071 SIVAL(outhdr, SMB2_HDR_STATUS,
1072 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1073 SSVAL(outhdr, SMB2_HDR_OPCODE,
1074 SVAL(inhdr, SMB2_HDR_OPCODE));
1075 SIVAL(outhdr, SMB2_HDR_FLAGS,
1076 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1077 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1078 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1079 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1080 SIVAL(outhdr, SMB2_HDR_PID,
1081 IVAL(inhdr, SMB2_HDR_PID));
1082 SIVAL(outhdr, SMB2_HDR_TID,
1083 IVAL(inhdr, SMB2_HDR_TID));
1084 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1085 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1086 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1087 inhdr + SMB2_HDR_SIGNATURE, 16);
1089 /* setup error body header */
1090 SSVAL(outbody, 0x00, 0x08 + 1);
1091 SSVAL(outbody, 0x02, 0);
1092 SIVAL(outbody, 0x04, 0);
1095 req->out.vector = vector;
1096 req->out.vector_count = count;
1098 /* setup the length of the NBT packet */
1099 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1101 return NT_STATUS_INVALID_PARAMETER_MIX;
1104 DLIST_ADD_END(xconn->smb2.requests, req);
1106 return NT_STATUS_OK;
1109 void smbXsrv_connection_disconnect_transport(struct smbXsrv_connection *xconn,
1112 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
1116 xconn->transport.status = status;
1117 TALLOC_FREE(xconn->transport.fde);
1118 if (xconn->transport.sock != -1) {
1119 xconn->transport.sock = -1;
1121 DO_PROFILE_INC(disconnect);
1124 static size_t smbXsrv_client_valid_connections(struct smbXsrv_client *client)
1126 struct smbXsrv_connection *xconn = NULL;
1129 for (xconn = client->connections; xconn != NULL; xconn = xconn->next) {
1130 if (NT_STATUS_IS_OK(xconn->transport.status)) {
1138 struct smbXsrv_connection_shutdown_state {
1139 struct tevent_queue *wait_queue;
1142 static void smbXsrv_connection_shutdown_wait_done(struct tevent_req *subreq);
1144 static struct tevent_req *smbXsrv_connection_shutdown_send(TALLOC_CTX *mem_ctx,
1145 struct tevent_context *ev,
1146 struct smbXsrv_connection *xconn)
1148 struct tevent_req *req = NULL;
1149 struct smbXsrv_connection_shutdown_state *state = NULL;
1150 struct tevent_req *subreq = NULL;
1152 struct smbd_smb2_request *preq = NULL;
1156 * The caller should have called
1157 * smbXsrv_connection_disconnect_transport() before.
1159 SMB_ASSERT(!NT_STATUS_IS_OK(xconn->transport.status));
1161 req = tevent_req_create(mem_ctx, &state,
1162 struct smbXsrv_connection_shutdown_state);
1167 status = smbXsrv_session_disconnect_xconn(xconn);
1168 if (tevent_req_nterror(req, status)) {
1169 return tevent_req_post(req, ev);
1172 state->wait_queue = tevent_queue_create(state, "smbXsrv_connection_shutdown_queue");
1173 if (tevent_req_nomem(state->wait_queue, req)) {
1174 return tevent_req_post(req, ev);
1177 for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
1179 * The connection is gone so we
1180 * don't need to take care of
1183 preq->session = NULL;
1184 preq->do_signing = false;
1185 preq->do_encryption = false;
1186 preq->preauth = NULL;
1188 if (preq->subreq != NULL) {
1189 tevent_req_cancel(preq->subreq);
1193 * Now wait until the request is finished.
1195 * We don't set a callback, as we just want to block the
1196 * wait queue and the talloc_free() of the request will
1197 * remove the item from the wait queue.
1199 subreq = tevent_queue_wait_send(preq, ev, state->wait_queue);
1200 if (tevent_req_nomem(subreq, req)) {
1201 return tevent_req_post(req, ev);
1205 len = tevent_queue_length(state->wait_queue);
1207 tevent_req_done(req);
1208 return tevent_req_post(req, ev);
1212 * Now we add our own waiter to the end of the queue,
1213 * this way we get notified when all pending requests are finished
1214 * and send to the socket.
1216 subreq = tevent_queue_wait_send(state, ev, state->wait_queue);
1217 if (tevent_req_nomem(subreq, req)) {
1218 return tevent_req_post(req, ev);
1220 tevent_req_set_callback(subreq, smbXsrv_connection_shutdown_wait_done, req);
1225 static void smbXsrv_connection_shutdown_wait_done(struct tevent_req *subreq)
1227 struct tevent_req *req =
1228 tevent_req_callback_data(subreq,
1231 tevent_queue_wait_recv(subreq);
1232 TALLOC_FREE(subreq);
1234 tevent_req_done(req);
1237 static NTSTATUS smbXsrv_connection_shutdown_recv(struct tevent_req *req)
1239 return tevent_req_simple_recv_ntstatus(req);
1242 static void smbd_server_connection_terminate_done(struct tevent_req *subreq)
1244 struct smbXsrv_connection *xconn =
1245 tevent_req_callback_data(subreq,
1246 struct smbXsrv_connection);
1247 struct smbXsrv_client *client = xconn->client;
1250 status = smbXsrv_connection_shutdown_recv(subreq);
1251 if (!NT_STATUS_IS_OK(status)) {
1252 exit_server("smbXsrv_connection_shutdown_recv failed");
1255 DLIST_REMOVE(client->connections, xconn);
1259 void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
1261 const char *location)
1263 struct smbXsrv_client *client = xconn->client;
1267 * Make sure that no new request will be able to use this session.
1269 * smbXsrv_connection_disconnect_transport() might be called already,
1270 * but calling it again is a no-op.
1272 smbXsrv_connection_disconnect_transport(xconn,
1273 NT_STATUS_CONNECTION_DISCONNECTED);
1275 num_ok = smbXsrv_client_valid_connections(client);
1277 DBG_DEBUG("conn[%s] num_ok[%zu] reason[%s] at %s\n",
1278 smbXsrv_connection_dbg(xconn), num_ok,
1282 struct tevent_req *subreq = NULL;
1284 subreq = smbXsrv_connection_shutdown_send(client,
1287 if (subreq == NULL) {
1288 exit_server("smbXsrv_connection_shutdown_send failed");
1290 tevent_req_set_callback(subreq,
1291 smbd_server_connection_terminate_done,
1297 * The last connection was disconnected
1299 exit_server_cleanly(reason);
1302 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1303 struct iovec *outvec,
1304 const struct iovec *srcvec)
1306 const uint8_t *srctf;
1308 const uint8_t *srchdr;
1310 const uint8_t *srcbody;
1312 const uint8_t *expected_srcbody;
1313 const uint8_t *srcdyn;
1315 const uint8_t *expected_srcdyn;
1321 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1322 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1323 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1324 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1325 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1326 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1327 expected_srcbody = srchdr + SMB2_HDR_BODY;
1328 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1329 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1330 expected_srcdyn = srcbody + 8;
1332 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1336 if (srchdr_len != SMB2_HDR_BODY) {
1340 if (srctf_len == SMB2_TF_HDR_SIZE) {
1341 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1342 if (dsttf == NULL) {
1348 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1349 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1351 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1352 * be allocated with size OUTVEC_ALLOC_SIZE. */
1354 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1355 if (dsthdr == NULL) {
1358 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1359 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1362 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1363 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1364 * then duplicate this. Else use talloc_memdup().
1367 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1368 dstbody = dsthdr + SMB2_HDR_BODY;
1370 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1371 if (dstbody == NULL) {
1375 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1376 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1379 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1381 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1382 * then duplicate this. Else use talloc_memdup().
1385 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1386 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1387 } else if (srcdyn == NULL) {
1390 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1391 if (dstdyn == NULL) {
1395 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1396 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1401 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1403 struct smbd_smb2_request *newreq = NULL;
1404 struct iovec *outvec = NULL;
1405 int count = req->out.vector_count;
1409 newreq = smbd_smb2_request_allocate(req->xconn);
1414 newreq->sconn = req->sconn;
1415 newreq->xconn = req->xconn;
1416 newreq->session = req->session;
1417 newreq->do_encryption = req->do_encryption;
1418 newreq->do_signing = req->do_signing;
1419 newreq->current_idx = req->current_idx;
1421 outvec = talloc_zero_array(newreq, struct iovec, count);
1423 TALLOC_FREE(newreq);
1426 newreq->out.vector = outvec;
1427 newreq->out.vector_count = count;
1429 /* Setup the outvec's identically to req. */
1430 outvec[0].iov_base = newreq->out.nbt_hdr;
1431 outvec[0].iov_len = 4;
1432 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1434 /* Setup the vectors identically to the ones in req. */
1435 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1436 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1443 TALLOC_FREE(newreq);
1447 ok = smb2_setup_nbt_length(newreq->out.vector,
1448 newreq->out.vector_count);
1450 TALLOC_FREE(newreq);
1457 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1459 struct smbXsrv_connection *xconn = req->xconn;
1461 struct iovec *firsttf = NULL;
1462 struct iovec *outhdr_v = NULL;
1463 uint8_t *outhdr = NULL;
1464 struct smbd_smb2_request *nreq = NULL;
1468 /* Create a new smb2 request we'll use
1469 for the interim return. */
1470 nreq = dup_smb2_req(req);
1472 return NT_STATUS_NO_MEMORY;
1475 /* Lose the last X out vectors. They're the
1476 ones we'll be using for the async reply. */
1477 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1479 ok = smb2_setup_nbt_length(nreq->out.vector,
1480 nreq->out.vector_count);
1482 return NT_STATUS_INVALID_PARAMETER_MIX;
1485 /* Step back to the previous reply. */
1486 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1487 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1488 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1489 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1490 /* And end the chain. */
1491 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1493 /* Calculate outgoing credits */
1494 smb2_calculate_credits(req, nreq);
1496 if (DEBUGLEVEL >= 10) {
1497 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1498 (unsigned int)nreq->current_idx );
1499 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1500 (unsigned int)nreq->out.vector_count );
1501 print_req_vectors(nreq);
1505 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1506 * we need to sign/encrypt here with the last/first key we remembered
1508 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1509 struct smb2_signing_key key = {
1510 .blob = req->first_key,
1512 status = smb2_signing_encrypt_pdu(&key,
1513 xconn->smb2.server.cipher,
1515 nreq->out.vector_count - first_idx);
1516 smb2_signing_key_destructor(&key);
1517 if (!NT_STATUS_IS_OK(status)) {
1520 } else if (req->last_key.length > 0) {
1521 struct smb2_signing_key key = {
1522 .blob = req->last_key,
1525 status = smb2_signing_sign_pdu(&key,
1528 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1529 smb2_signing_key_destructor(&key);
1530 if (!NT_STATUS_IS_OK(status)) {
1535 nreq->queue_entry.mem_ctx = nreq;
1536 nreq->queue_entry.vector = nreq->out.vector;
1537 nreq->queue_entry.count = nreq->out.vector_count;
1538 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry);
1539 xconn->smb2.send_queue_len++;
1541 status = smbd_smb2_flush_send_queue(xconn);
1542 if (!NT_STATUS_IS_OK(status)) {
1546 return NT_STATUS_OK;
1549 struct smbd_smb2_request_pending_state {
1550 struct smbd_smb2_send_queue queue_entry;
1551 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1552 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1555 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1556 struct tevent_timer *te,
1557 struct timeval current_time,
1558 void *private_data);
1560 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1561 struct tevent_req *subreq,
1562 uint32_t defer_time)
1565 struct timeval defer_endtime;
1566 uint8_t *outhdr = NULL;
1569 if (!tevent_req_is_in_progress(subreq)) {
1571 * This is a performance optimization,
1572 * it avoids one tevent_loop iteration,
1573 * which means we avoid one
1574 * talloc_stackframe_pool/talloc_free pair.
1576 tevent_req_notify_callback(subreq);
1577 return NT_STATUS_OK;
1580 req->subreq = subreq;
1583 if (req->async_te) {
1584 /* We're already async. */
1585 return NT_STATUS_OK;
1588 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1589 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1590 if (flags & SMB2_HDR_FLAG_ASYNC) {
1591 /* We're already async. */
1592 return NT_STATUS_OK;
1595 if (req->async_internal || defer_time == 0) {
1597 * An SMB2 request implementation wants to handle the request
1598 * asynchronously "internally" while keeping synchronous
1599 * behaviour for the SMB2 request. This means we don't send an
1600 * interim response and we can allow processing of compound SMB2
1601 * requests (cf the subsequent check) for all cases.
1603 return NT_STATUS_OK;
1606 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1608 * We're trying to go async in a compound request
1609 * chain. This is only allowed for opens that cause an
1610 * oplock break or for the last operation in the
1611 * chain, otherwise it is not allowed. See
1612 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
1614 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1616 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1618 * Cancel the outstanding request.
1620 bool ok = tevent_req_cancel(req->subreq);
1622 return NT_STATUS_OK;
1624 TALLOC_FREE(req->subreq);
1625 return smbd_smb2_request_error(req,
1626 NT_STATUS_INTERNAL_ERROR);
1630 if (DEBUGLEVEL >= 10) {
1631 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1632 (unsigned int)req->current_idx );
1633 print_req_vectors(req);
1636 if (req->current_idx > 1) {
1638 * We're going async in a compound
1639 * chain after the first request has
1640 * already been processed. Send an
1641 * interim response containing the
1642 * set of replies already generated.
1644 int idx = req->current_idx;
1646 status = smb2_send_async_interim_response(req);
1647 if (!NT_STATUS_IS_OK(status)) {
1650 if (req->first_key.length > 0) {
1651 data_blob_clear_free(&req->first_key);
1654 req->current_idx = 1;
1657 * Re-arrange the in.vectors to remove what
1660 memmove(&req->in.vector[1],
1661 &req->in.vector[idx],
1662 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1663 req->in.vector_count = 1 + (req->in.vector_count - idx);
1665 /* Re-arrange the out.vectors to match. */
1666 memmove(&req->out.vector[1],
1667 &req->out.vector[idx],
1668 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1669 req->out.vector_count = 1 + (req->out.vector_count - idx);
1671 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1673 * We only have one remaining request as
1674 * we've processed everything else.
1675 * This is no longer a compound request.
1677 req->compound_related = false;
1678 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1679 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1680 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1683 if (req->last_key.length > 0) {
1684 data_blob_clear_free(&req->last_key);
1688 * smbd_smb2_request_pending_timer() just send a packet
1689 * to the client and doesn't need any impersonation.
1690 * So we use req->xconn->client->raw_ev_ctx instead
1691 * of req->ev_ctx here.
1693 defer_endtime = timeval_current_ofs_usec(defer_time);
1694 req->async_te = tevent_add_timer(req->xconn->client->raw_ev_ctx,
1696 smbd_smb2_request_pending_timer,
1698 if (req->async_te == NULL) {
1699 return NT_STATUS_NO_MEMORY;
1702 return NT_STATUS_OK;
1706 struct smb2_signing_key *smbd_smb2_signing_key(struct smbXsrv_session *session,
1707 struct smbXsrv_connection *xconn)
1709 struct smbXsrv_channel_global0 *c = NULL;
1711 struct smb2_signing_key *key = NULL;
1713 status = smbXsrv_session_find_channel(session, xconn, &c);
1714 if (NT_STATUS_IS_OK(status)) {
1715 key = c->signing_key;
1718 if (!smb2_signing_key_valid(key)) {
1719 key = session->global->signing_key;
1725 static NTSTATUS smb2_get_new_nonce(struct smbXsrv_session *session,
1726 uint64_t *new_nonce_high,
1727 uint64_t *new_nonce_low)
1729 uint64_t nonce_high;
1732 session->nonce_low += 1;
1733 if (session->nonce_low == 0) {
1734 session->nonce_low += 1;
1735 session->nonce_high += 1;
1739 * CCM and GCM algorithms must never have their
1740 * nonce wrap, or the security of the whole
1741 * communication and the keys is destroyed.
1742 * We must drop the connection once we have
1743 * transfered too much data.
1745 * NOTE: We assume nonces greater than 8 bytes.
1747 if (session->nonce_high >= session->nonce_high_max) {
1748 return NT_STATUS_ENCRYPTION_FAILED;
1751 nonce_high = session->nonce_high_random;
1752 nonce_high += session->nonce_high;
1753 nonce_low = session->nonce_low;
1755 *new_nonce_high = nonce_high;
1756 *new_nonce_low = nonce_low;
1757 return NT_STATUS_OK;
1760 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1761 struct tevent_timer *te,
1762 struct timeval current_time,
1765 struct smbd_smb2_request *req =
1766 talloc_get_type_abort(private_data,
1767 struct smbd_smb2_request);
1768 struct smbXsrv_connection *xconn = req->xconn;
1769 struct smbd_smb2_request_pending_state *state = NULL;
1770 uint8_t *outhdr = NULL;
1771 const uint8_t *inhdr = NULL;
1773 uint8_t *hdr = NULL;
1774 uint8_t *body = NULL;
1775 uint8_t *dyn = NULL;
1777 uint64_t message_id = 0;
1778 uint64_t async_id = 0;
1782 TALLOC_FREE(req->async_te);
1784 /* Ensure our final reply matches the interim one. */
1785 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1786 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1787 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1788 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1790 async_id = message_id; /* keep it simple for now... */
1792 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1793 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1795 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1797 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1798 (unsigned long long)async_id ));
1801 * What we send is identical to a smbd_smb2_request_error
1802 * packet with an error status of STATUS_PENDING. Make use
1803 * of this fact sometime when refactoring. JRA.
1806 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
1807 if (state == NULL) {
1808 smbd_server_connection_terminate(xconn,
1809 nt_errstr(NT_STATUS_NO_MEMORY));
1813 tf = state->buf + NBT_HDR_SIZE;
1815 hdr = tf + SMB2_TF_HDR_SIZE;
1816 body = hdr + SMB2_HDR_BODY;
1819 if (req->do_encryption) {
1820 uint64_t nonce_high = 0;
1821 uint64_t nonce_low = 0;
1822 uint64_t session_id = req->session->global->session_wire_id;
1824 status = smb2_get_new_nonce(req->session,
1827 if (!NT_STATUS_IS_OK(status)) {
1828 smbd_server_connection_terminate(xconn,
1833 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1834 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1835 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1836 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1839 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1840 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1841 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1842 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(NT_STATUS_PENDING));
1843 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1845 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1846 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1847 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1848 SBVAL(hdr, SMB2_HDR_PID, async_id);
1849 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1850 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1851 memcpy(hdr+SMB2_HDR_SIGNATURE,
1852 outhdr+SMB2_HDR_SIGNATURE, 16);
1854 SSVAL(body, 0x00, 0x08 + 1);
1856 SCVAL(body, 0x02, 0);
1857 SCVAL(body, 0x03, 0);
1858 SIVAL(body, 0x04, 0);
1859 /* Match W2K8R2... */
1860 SCVAL(dyn, 0x00, 0x21);
1862 state->vector[0].iov_base = (void *)state->buf;
1863 state->vector[0].iov_len = NBT_HDR_SIZE;
1865 if (req->do_encryption) {
1866 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1867 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len =
1870 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1871 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1874 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1875 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1877 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1878 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1880 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1881 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1883 ok = smb2_setup_nbt_length(state->vector,
1884 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1886 smbd_server_connection_terminate(
1887 xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
1891 /* Ensure we correctly go through crediting. Grant
1892 the credits now, and zero credits on the final
1894 smb2_set_operation_credit(req->xconn,
1895 SMBD_SMB2_IN_HDR_IOV(req),
1896 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1898 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1903 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1904 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1906 (unsigned int)ARRAY_SIZE(state->vector),
1907 (unsigned int)state->vector[i].iov_len);
1911 if (req->do_encryption) {
1912 struct smbXsrv_session *x = req->session;
1913 struct smb2_signing_key *encryption_key = x->global->encryption_key;
1915 status = smb2_signing_encrypt_pdu(encryption_key,
1916 xconn->smb2.server.cipher,
1917 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1918 SMBD_SMB2_NUM_IOV_PER_REQ);
1919 if (!NT_STATUS_IS_OK(status)) {
1920 smbd_server_connection_terminate(xconn,
1924 } else if (req->do_signing) {
1925 struct smbXsrv_session *x = req->session;
1926 struct smb2_signing_key *signing_key =
1927 smbd_smb2_signing_key(x, xconn);
1929 status = smb2_signing_sign_pdu(signing_key,
1931 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1932 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1933 if (!NT_STATUS_IS_OK(status)) {
1934 smbd_server_connection_terminate(xconn,
1940 state->queue_entry.mem_ctx = state;
1941 state->queue_entry.vector = state->vector;
1942 state->queue_entry.count = ARRAY_SIZE(state->vector);
1943 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
1944 xconn->smb2.send_queue_len++;
1946 status = smbd_smb2_flush_send_queue(xconn);
1947 if (!NT_STATUS_IS_OK(status)) {
1948 smbd_server_connection_terminate(xconn,
1954 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1956 struct smbXsrv_connection *xconn = req->xconn;
1957 struct smbd_smb2_request *cur;
1958 const uint8_t *inhdr;
1960 uint64_t search_message_id;
1961 uint64_t search_async_id;
1964 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1966 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1967 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1968 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1971 * We don't need the request anymore cancel requests never
1974 * We defer the TALLOC_FREE(req) to the caller.
1976 DLIST_REMOVE(xconn->smb2.requests, req);
1978 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1979 const uint8_t *outhdr;
1980 uint64_t message_id;
1983 if (cur->compound_related) {
1985 * Never cancel anything in a compound request.
1986 * Way too hard to deal with the result.
1991 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1993 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1994 async_id = BVAL(outhdr, SMB2_HDR_PID);
1996 if (flags & SMB2_HDR_FLAG_ASYNC) {
1997 if (search_async_id == async_id) {
1998 found_id = async_id;
2002 if (search_message_id == message_id) {
2003 found_id = message_id;
2009 if (cur && cur->subreq) {
2010 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
2011 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
2012 "cancel opcode[%s] mid %llu\n",
2013 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
2014 (unsigned long long)found_id ));
2015 tevent_req_cancel(cur->subreq);
2018 return NT_STATUS_OK;
2021 /*************************************************************
2022 Ensure an incoming tid is a valid one for us to access.
2023 Change to the associated uid credentials and chdir to the
2024 valid tid directory.
2025 *************************************************************/
2027 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
2029 const uint8_t *inhdr;
2032 struct smbXsrv_tcon *tcon;
2034 NTTIME now = timeval_to_nttime(&req->request_time);
2038 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2040 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2041 in_tid = IVAL(inhdr, SMB2_HDR_TID);
2043 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
2044 in_tid = req->last_tid;
2049 status = smb2srv_tcon_lookup(req->session,
2050 in_tid, now, &tcon);
2051 if (!NT_STATUS_IS_OK(status)) {
2055 if (!change_to_user_and_service(
2057 req->session->global->session_wire_id))
2059 return NT_STATUS_ACCESS_DENIED;
2063 req->last_tid = in_tid;
2065 return NT_STATUS_OK;
2068 /*************************************************************
2069 Ensure an incoming session_id is a valid one for us to access.
2070 *************************************************************/
2072 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
2074 const uint8_t *inhdr;
2077 uint64_t in_session_id;
2078 struct smbXsrv_session *session = NULL;
2079 struct auth_session_info *session_info;
2081 NTTIME now = timeval_to_nttime(&req->request_time);
2083 req->session = NULL;
2086 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2088 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2089 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2090 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
2092 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
2093 in_session_id = req->last_session_id;
2096 req->last_session_id = 0;
2098 /* look an existing session up */
2099 switch (in_opcode) {
2100 case SMB2_OP_SESSSETUP:
2102 * For a session bind request, we don't have the
2103 * channel set up at this point yet, so we defer
2104 * the verification that the connection belongs
2105 * to the session to the session setup code, which
2106 * can look at the session binding flags.
2108 status = smb2srv_session_lookup_client(req->xconn->client,
2113 status = smb2srv_session_lookup_conn(req->xconn,
2119 req->session = session;
2120 req->last_session_id = in_session_id;
2122 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
2123 switch (in_opcode) {
2124 case SMB2_OP_SESSSETUP:
2125 status = NT_STATUS_OK;
2127 case SMB2_OP_LOGOFF:
2130 case SMB2_OP_CANCEL:
2131 case SMB2_OP_KEEPALIVE:
2133 * [MS-SMB2] 3.3.5.2.9 Verifying the Session
2134 * specifies that LOGOFF, CLOSE and (UN)LOCK
2135 * should always be processed even on expired sessions.
2137 * Also see the logic in
2138 * smbd_smb2_request_process_lock().
2140 * The smb2.session.expire2 test shows that
2141 * CANCEL and KEEPALIVE/ECHO should also
2144 status = NT_STATUS_OK;
2150 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2151 switch (in_opcode) {
2153 case SMB2_OP_CREATE:
2154 case SMB2_OP_GETINFO:
2155 case SMB2_OP_SETINFO:
2156 return NT_STATUS_INVALID_HANDLE;
2159 * Notice the check for
2160 * (session_info == NULL)
2163 status = NT_STATUS_OK;
2167 if (!NT_STATUS_IS_OK(status)) {
2171 session_info = session->global->auth_session_info;
2172 if (session_info == NULL) {
2173 return NT_STATUS_INVALID_HANDLE;
2176 return NT_STATUS_OK;
2179 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
2180 uint32_t data_length)
2182 struct smbXsrv_connection *xconn = req->xconn;
2183 uint16_t needed_charge;
2184 uint16_t credit_charge = 1;
2185 const uint8_t *inhdr;
2187 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2189 if (xconn->smb2.credits.multicredit) {
2190 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
2191 credit_charge = MAX(credit_charge, 1);
2194 needed_charge = (data_length - 1)/ 65536 + 1;
2196 DBGC_DEBUG(DBGC_SMB2_CREDITS,
2197 "mid %llu, CreditCharge: %d, NeededCharge: %d\n",
2198 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
2199 credit_charge, needed_charge);
2201 if (needed_charge > credit_charge) {
2202 DBGC_WARNING(DBGC_SMB2_CREDITS,
2203 "CreditCharge too low, given %d, needed %d\n",
2204 credit_charge, needed_charge);
2205 return NT_STATUS_INVALID_PARAMETER;
2208 return NT_STATUS_OK;
2211 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
2212 size_t expected_body_size)
2214 struct iovec *inhdr_v;
2215 const uint8_t *inhdr;
2217 const uint8_t *inbody;
2219 size_t min_dyn_size = expected_body_size & 0x00000001;
2220 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
2223 * The following should be checked already.
2225 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
2226 return NT_STATUS_INTERNAL_ERROR;
2228 if (req->current_idx > max_idx) {
2229 return NT_STATUS_INTERNAL_ERROR;
2232 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
2233 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
2234 return NT_STATUS_INTERNAL_ERROR;
2236 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
2237 return NT_STATUS_INTERNAL_ERROR;
2240 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2241 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2245 case SMB2_OP_GETINFO:
2252 * Now check the expected body size,
2253 * where the last byte might be in the
2256 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
2257 return NT_STATUS_INVALID_PARAMETER;
2259 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
2260 return NT_STATUS_INVALID_PARAMETER;
2263 inbody = SMBD_SMB2_IN_BODY_PTR(req);
2265 body_size = SVAL(inbody, 0x00);
2266 if (body_size != expected_body_size) {
2267 return NT_STATUS_INVALID_PARAMETER;
2270 return NT_STATUS_OK;
2273 bool smbXsrv_is_encrypted(uint8_t encryption_flags)
2275 return (!(encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)
2277 (encryption_flags & (SMBXSRV_PROCESSED_ENCRYPTED_PACKET |
2278 SMBXSRV_ENCRYPTION_DESIRED |
2279 SMBXSRV_ENCRYPTION_REQUIRED)));
2282 bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags)
2284 return ((encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET) &&
2285 (encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET));
2288 /* Set a flag if not already set, return true if set */
2289 bool smbXsrv_set_crypto_flag(uint8_t *flags, uint8_t flag)
2291 if ((flag == 0) || (*flags & flag)) {
2300 * Update encryption state tracking flags, this can be used to
2301 * determine whether whether the session or tcon is "encrypted".
2303 static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
2305 bool *update_session_globalp,
2306 bool *update_tcon_globalp)
2308 /* Default: assume unecrypted and unsigned */
2309 struct smbXsrv_session *session = req->session;
2310 struct smbXsrv_tcon *tcon = req->tcon;
2311 uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
2312 uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2313 bool update_session = false;
2314 bool update_tcon = false;
2316 if (req->was_encrypted && req->do_encryption) {
2317 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
2318 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2320 /* Unencrypted packet, can be signed */
2321 if (req->do_signing) {
2322 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2323 } else if (opcode == SMB2_OP_CANCEL) {
2324 /* Cancel requests are allowed to skip signing */
2325 sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2329 update_session |= smbXsrv_set_crypto_flag(
2330 &session->global->encryption_flags, encrypt_flag);
2331 update_session |= smbXsrv_set_crypto_flag(
2332 &session->global->signing_flags, sign_flag);
2335 update_tcon |= smbXsrv_set_crypto_flag(
2336 &tcon->global->encryption_flags, encrypt_flag);
2337 update_tcon |= smbXsrv_set_crypto_flag(
2338 &tcon->global->signing_flags, sign_flag);
2341 *update_session_globalp = update_session;
2342 *update_tcon_globalp = update_tcon;
2346 bool smbXsrv_is_signed(uint8_t signing_flags)
2349 * Signing is always enabled, so unless we got an unsigned
2350 * packet and at least one signed packet that was not
2351 * encrypted, the session or tcon is "signed".
2353 return (!(signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2354 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2357 bool smbXsrv_is_partially_signed(uint8_t signing_flags)
2359 return ((signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2360 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2363 static NTSTATUS smbd_smb2_request_dispatch_update_counts(
2364 struct smbd_smb2_request *req,
2367 struct smbXsrv_connection *xconn = req->xconn;
2368 const uint8_t *inhdr;
2369 uint16_t channel_sequence;
2370 uint8_t generation_wrap = 0;
2373 struct smbXsrv_open *op;
2374 bool update_open = false;
2375 NTSTATUS status = NT_STATUS_OK;
2377 SMB_ASSERT(!req->request_counters_updated);
2379 if (xconn->protocol < PROTOCOL_SMB2_22) {
2380 return NT_STATUS_OK;
2383 if (req->compat_chain_fsp == NULL) {
2384 return NT_STATUS_OK;
2387 op = req->compat_chain_fsp->op;
2389 return NT_STATUS_OK;
2392 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2393 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2394 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2396 cmp = channel_sequence - op->global->channel_sequence;
2399 * csn wrap. We need to watch out for long-running
2400 * requests that are still sitting on a previously
2401 * used csn. SMB2_OP_NOTIFY can take VERY long.
2403 generation_wrap += 1;
2406 if (abs(cmp) > INT16_MAX) {
2408 * [MS-SMB2] 3.3.5.2.10 - Verifying the Channel Sequence Number:
2410 * If the channel sequence number of the request and the one
2411 * known to the server are not equal, the channel sequence
2412 * number and outstanding request counts are only updated
2413 * "... if the unsigned difference using 16-bit arithmetic
2414 * between ChannelSequence and Open.ChannelSequence is less than
2415 * or equal to 0x7FFF ...".
2416 * Otherwise, an error is returned for the modifying
2417 * calls write, set_info, and ioctl.
2419 * There are currently two issues with the description:
2421 * * For the other calls, the document seems to imply
2422 * that processing continues without adapting the
2423 * counters (if the sequence numbers are not equal).
2425 * TODO: This needs clarification!
2427 * * Also, the behaviour if the difference is larger
2428 * than 0x7FFF is not clear. The document seems to
2429 * imply that if such a difference is reached,
2430 * the server starts to ignore the counters or
2431 * in the case of the modifying calls, return errors.
2433 * TODO: This needs clarification!
2435 * At this point Samba tries to be a little more
2436 * clever than the description in the MS-SMB2 document
2437 * by heuristically detecting and properly treating
2438 * a 16 bit overflow of the client-submitted sequence
2441 * If the stored channel sequence number is more than
2442 * 0x7FFF larger than the one from the request, then
2443 * the client-provided sequence number has likely
2444 * overflown. We treat this case as valid instead
2447 * The MS-SMB2 behaviour would be setting cmp = -1.
2452 if (flags & SMB2_HDR_FLAG_REPLAY_OPERATION) {
2453 if (cmp == 0 && op->pre_request_count == 0) {
2454 op->request_count += 1;
2455 req->request_counters_updated = true;
2456 } else if (cmp > 0 && op->pre_request_count == 0) {
2457 op->pre_request_count += op->request_count;
2458 op->request_count = 1;
2459 op->global->channel_sequence = channel_sequence;
2460 op->global->channel_generation += generation_wrap;
2462 req->request_counters_updated = true;
2463 } else if (modify_call) {
2464 return NT_STATUS_FILE_NOT_AVAILABLE;
2468 op->request_count += 1;
2469 req->request_counters_updated = true;
2470 } else if (cmp > 0) {
2471 op->pre_request_count += op->request_count;
2472 op->request_count = 1;
2473 op->global->channel_sequence = channel_sequence;
2474 op->global->channel_generation += generation_wrap;
2476 req->request_counters_updated = true;
2477 } else if (modify_call) {
2478 return NT_STATUS_FILE_NOT_AVAILABLE;
2481 req->channel_generation = op->global->channel_generation;
2484 status = smbXsrv_open_update(op);
2490 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
2492 struct smbXsrv_connection *xconn = req->xconn;
2493 const struct smbd_smb2_dispatch_table *call = NULL;
2494 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
2495 const uint8_t *inhdr;
2500 NTSTATUS session_status;
2501 uint32_t allowed_flags;
2502 NTSTATUS return_value;
2503 struct smbXsrv_session *x = NULL;
2504 bool signing_required = false;
2505 bool encryption_desired = false;
2506 bool encryption_required = false;
2508 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2510 DO_PROFILE_INC(request);
2512 SMB_ASSERT(!req->request_counters_updated);
2514 /* TODO: verify more things */
2516 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2517 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2518 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2519 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
2520 smb2_opcode_name(opcode),
2521 (unsigned long long)mid));
2523 if (xconn->protocol >= PROTOCOL_SMB2_02) {
2525 * once the protocol is negotiated
2526 * SMB2_OP_NEGPROT is not allowed anymore
2528 if (opcode == SMB2_OP_NEGPROT) {
2529 /* drop the connection */
2530 return NT_STATUS_INVALID_PARAMETER;
2534 * if the protocol is not negotiated yet
2535 * only SMB2_OP_NEGPROT is allowed.
2537 if (opcode != SMB2_OP_NEGPROT) {
2538 /* drop the connection */
2539 return NT_STATUS_INVALID_PARAMETER;
2544 * Check if the client provided a valid session id.
2546 * As some command don't require a valid session id
2547 * we defer the check of the session_status
2549 session_status = smbd_smb2_request_check_session(req);
2552 signing_required = x->global->signing_flags & SMBXSRV_SIGNING_REQUIRED;
2553 encryption_desired = x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
2554 encryption_required = x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
2557 req->async_internal = false;
2558 req->do_signing = false;
2559 if (opcode != SMB2_OP_SESSSETUP) {
2560 req->do_encryption = encryption_desired;
2562 req->do_encryption = false;
2564 req->was_encrypted = false;
2565 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
2566 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
2567 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
2569 if (x != NULL && x->global->session_wire_id != tf_session_id) {
2570 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2571 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
2572 (unsigned long long)x->global->session_wire_id,
2573 (unsigned long long)tf_session_id));
2575 * TODO: windows allows this...
2576 * should we drop the connection?
2578 * For now we just return ACCESS_DENIED
2579 * (Windows clients never trigger this)
2580 * and wait for an update of [MS-SMB2].
2582 return smbd_smb2_request_error(req,
2583 NT_STATUS_ACCESS_DENIED);
2586 req->was_encrypted = true;
2587 req->do_encryption = true;
2590 if (encryption_required && !req->was_encrypted) {
2591 req->do_encryption = true;
2592 return smbd_smb2_request_error(req,
2593 NT_STATUS_ACCESS_DENIED);
2596 call = smbd_smb2_call(opcode);
2598 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2601 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2602 SMB2_HDR_FLAG_SIGNED |
2604 if (xconn->protocol >= PROTOCOL_SMB3_11) {
2605 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2607 if (opcode == SMB2_OP_NEGPROT) {
2608 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11) {
2609 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2612 if (opcode == SMB2_OP_CANCEL) {
2613 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2615 if (xconn->protocol >= PROTOCOL_SMB2_22) {
2616 allowed_flags |= SMB2_HDR_FLAG_REPLAY_OPERATION;
2618 if ((flags & ~allowed_flags) != 0) {
2619 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2622 if (flags & SMB2_HDR_FLAG_CHAINED) {
2624 * This check is mostly for giving the correct error code
2625 * for compounded requests.
2627 if (!NT_STATUS_IS_OK(session_status)) {
2628 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2631 req->compat_chain_fsp = NULL;
2634 if (req->was_encrypted) {
2635 signing_required = false;
2636 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2637 struct smb2_signing_key *signing_key = NULL;
2641 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2642 * If the SMB2 header of the SMB2 NEGOTIATE
2643 * request has the SMB2_FLAGS_SIGNED bit set in the
2644 * Flags field, the server MUST fail the request
2645 * with STATUS_INVALID_PARAMETER.
2647 * Microsoft test tool checks this.
2650 if ((opcode == SMB2_OP_NEGPROT) &&
2651 (flags & SMB2_HDR_FLAG_SIGNED)) {
2652 status = NT_STATUS_INVALID_PARAMETER;
2654 status = NT_STATUS_USER_SESSION_DELETED;
2656 return smbd_smb2_request_error(req, status);
2659 signing_key = smbd_smb2_signing_key(x, xconn);
2662 * If we have a signing key, we should
2665 if (smb2_signing_key_valid(signing_key)) {
2666 req->do_signing = true;
2669 status = smb2_signing_check_pdu(signing_key,
2671 SMBD_SMB2_IN_HDR_IOV(req),
2672 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2673 if (!NT_STATUS_IS_OK(status)) {
2674 return smbd_smb2_request_error(req, status);
2678 * Now that we know the request was correctly signed
2679 * we have to sign the response too.
2681 req->do_signing = true;
2683 if (!NT_STATUS_IS_OK(session_status)) {
2684 return smbd_smb2_request_error(req, session_status);
2686 } else if (opcode == SMB2_OP_CANCEL) {
2687 /* Cancel requests are allowed to skip the signing */
2688 } else if (signing_required) {
2690 * If signing is required we try to sign
2691 * a possible error response
2693 req->do_signing = true;
2694 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2697 if (flags & SMB2_HDR_FLAG_CHAINED) {
2698 req->compound_related = true;
2701 if (call->need_session) {
2702 if (!NT_STATUS_IS_OK(session_status)) {
2703 return smbd_smb2_request_error(req, session_status);
2707 if (call->need_tcon) {
2708 SMB_ASSERT(call->need_session);
2711 * This call needs to be run as user.
2713 * smbd_smb2_request_check_tcon()
2714 * calls change_to_user() on success.
2715 * Which implies set_current_user_info()
2716 * and chdir_current_service().
2718 status = smbd_smb2_request_check_tcon(req);
2719 if (!NT_STATUS_IS_OK(status)) {
2720 return smbd_smb2_request_error(req, status);
2722 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
2723 encryption_desired = true;
2725 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
2726 encryption_required = true;
2728 if (encryption_required && !req->was_encrypted) {
2729 req->do_encryption = true;
2730 return smbd_smb2_request_error(req,
2731 NT_STATUS_ACCESS_DENIED);
2732 } else if (encryption_desired) {
2733 req->do_encryption = true;
2735 } else if (call->need_session) {
2736 struct auth_session_info *session_info = NULL;
2739 * Unless we also have need_tcon (see above),
2740 * we still need to call set_current_user_info().
2743 session_info = req->session->global->auth_session_info;
2744 if (session_info == NULL) {
2745 return NT_STATUS_INVALID_HANDLE;
2748 set_current_user_info(session_info->unix_info->sanitized_username,
2749 session_info->unix_info->unix_name,
2750 session_info->info->domain_name);
2754 bool update_session_global = false;
2755 bool update_tcon_global = false;
2757 smb2srv_update_crypto_flags(req, opcode,
2758 &update_session_global,
2759 &update_tcon_global);
2761 if (update_session_global) {
2762 status = smbXsrv_session_update(x);
2763 if (!NT_STATUS_IS_OK(status)) {
2764 return smbd_smb2_request_error(req, status);
2767 if (update_tcon_global) {
2768 status = smbXsrv_tcon_update(req->tcon);
2769 if (!NT_STATUS_IS_OK(status)) {
2770 return smbd_smb2_request_error(req, status);
2775 if (call->fileid_ofs != 0) {
2776 size_t needed = call->fileid_ofs + 16;
2777 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2778 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2779 uint64_t file_id_persistent;
2780 uint64_t file_id_volatile;
2781 struct files_struct *fsp;
2783 SMB_ASSERT(call->need_tcon);
2785 if (needed > body_size) {
2786 return smbd_smb2_request_error(req,
2787 NT_STATUS_INVALID_PARAMETER);
2790 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2791 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2793 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2795 if (!call->allow_invalid_fileid) {
2796 return smbd_smb2_request_error(req,
2797 NT_STATUS_FILE_CLOSED);
2800 if (file_id_persistent != UINT64_MAX) {
2801 return smbd_smb2_request_error(req,
2802 NT_STATUS_FILE_CLOSED);
2804 if (file_id_volatile != UINT64_MAX) {
2805 return smbd_smb2_request_error(req,
2806 NT_STATUS_FILE_CLOSED);
2811 status = smbd_smb2_request_dispatch_update_counts(req, call->modify);
2812 if (!NT_STATUS_IS_OK(status)) {
2813 return smbd_smb2_request_error(req, status);
2816 if (call->as_root) {
2817 SMB_ASSERT(call->fileid_ofs == 0);
2818 /* This call needs to be run as root */
2819 change_to_root_user();
2821 SMB_ASSERT(call->need_tcon);
2824 #define _INBYTES(_r) \
2825 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
2828 case SMB2_OP_NEGPROT:
2829 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
2830 req->profile, _INBYTES(req));
2831 return_value = smbd_smb2_request_process_negprot(req);
2834 case SMB2_OP_SESSSETUP:
2835 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
2836 req->profile, _INBYTES(req));
2837 return_value = smbd_smb2_request_process_sesssetup(req);
2840 case SMB2_OP_LOGOFF:
2841 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
2842 req->profile, _INBYTES(req));
2843 return_value = smbd_smb2_request_process_logoff(req);
2847 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
2848 req->profile, _INBYTES(req));
2849 return_value = smbd_smb2_request_process_tcon(req);
2853 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
2854 req->profile, _INBYTES(req));
2855 return_value = smbd_smb2_request_process_tdis(req);
2858 case SMB2_OP_CREATE:
2859 if (req->subreq == NULL) {
2860 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
2861 req->profile, _INBYTES(req));
2863 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
2865 return_value = smbd_smb2_request_process_create(req);
2869 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
2870 req->profile, _INBYTES(req));
2871 return_value = smbd_smb2_request_process_close(req);
2875 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
2876 req->profile, _INBYTES(req));
2877 return_value = smbd_smb2_request_process_flush(req);
2881 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
2882 req->profile, _INBYTES(req));
2883 return_value = smbd_smb2_request_process_read(req);
2887 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
2888 req->profile, _INBYTES(req));
2889 return_value = smbd_smb2_request_process_write(req);
2893 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
2894 req->profile, _INBYTES(req));
2895 return_value = smbd_smb2_request_process_lock(req);
2899 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
2900 req->profile, _INBYTES(req));
2901 return_value = smbd_smb2_request_process_ioctl(req);
2904 case SMB2_OP_CANCEL:
2905 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
2906 req->profile, _INBYTES(req));
2907 return_value = smbd_smb2_request_process_cancel(req);
2908 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
2911 * We don't need the request anymore cancel requests never
2914 * smbd_smb2_request_process_cancel() already called
2915 * DLIST_REMOVE(xconn->smb2.requests, req);
2921 case SMB2_OP_KEEPALIVE:
2922 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
2923 req->profile, _INBYTES(req));
2924 return_value = smbd_smb2_request_process_keepalive(req);
2927 case SMB2_OP_QUERY_DIRECTORY:
2928 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
2929 req->profile, _INBYTES(req));
2930 return_value = smbd_smb2_request_process_query_directory(req);
2933 case SMB2_OP_NOTIFY:
2934 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
2935 req->profile, _INBYTES(req));
2936 return_value = smbd_smb2_request_process_notify(req);
2939 case SMB2_OP_GETINFO:
2940 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
2941 req->profile, _INBYTES(req));
2942 return_value = smbd_smb2_request_process_getinfo(req);
2945 case SMB2_OP_SETINFO:
2946 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
2947 req->profile, _INBYTES(req));
2948 return_value = smbd_smb2_request_process_setinfo(req);
2952 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
2953 req->profile, _INBYTES(req));
2954 return_value = smbd_smb2_request_process_break(req);
2958 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2961 return return_value;
2964 static void smbd_smb2_request_reply_update_counts(struct smbd_smb2_request *req)
2966 struct smbXsrv_connection *xconn = req->xconn;
2967 const uint8_t *inhdr;
2968 uint16_t channel_sequence;
2969 struct smbXsrv_open *op;
2971 if (!req->request_counters_updated) {
2975 req->request_counters_updated = false;
2977 if (xconn->protocol < PROTOCOL_SMB2_22) {
2981 if (req->compat_chain_fsp == NULL) {
2985 op = req->compat_chain_fsp->op;
2990 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2991 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2993 if ((op->global->channel_sequence == channel_sequence) &&
2994 (op->global->channel_generation == req->channel_generation)) {
2995 SMB_ASSERT(op->request_count > 0);
2996 op->request_count -= 1;
2998 SMB_ASSERT(op->pre_request_count > 0);
2999 op->pre_request_count -= 1;
3003 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
3005 struct smbXsrv_connection *xconn = req->xconn;
3007 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
3008 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
3009 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
3014 TALLOC_FREE(req->async_te);
3016 /* MS-SMB2: 3.3.4.1 Sending Any Outgoing Message */
3017 smbd_smb2_request_reply_update_counts(req);
3019 if (req->do_encryption &&
3020 (firsttf->iov_len == 0) &&
3021 (req->first_key.length == 0) &&
3022 (req->session != NULL) &&
3023 smb2_signing_key_valid(req->session->global->encryption_key))
3025 struct smb2_signing_key *encryption_key =
3026 req->session->global->encryption_key;
3028 uint64_t session_id = req->session->global->session_wire_id;
3029 uint64_t nonce_high;
3032 status = smb2_get_new_nonce(req->session,
3035 if (!NT_STATUS_IS_OK(status)) {
3040 * We need to place the SMB2_TRANSFORM header before the
3045 * we need to remember the encryption key
3046 * and defer the signing/encryption until
3047 * we are sure that we do not change
3050 req->first_key = data_blob_dup_talloc(req,
3051 encryption_key->blob);
3052 if (req->first_key.data == NULL) {
3053 return NT_STATUS_NO_MEMORY;
3056 tf = talloc_zero_array(req, uint8_t,
3059 return NT_STATUS_NO_MEMORY;
3062 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
3063 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
3064 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
3065 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
3067 firsttf->iov_base = (void *)tf;
3068 firsttf->iov_len = SMB2_TF_HDR_SIZE;
3071 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
3072 (req->last_key.length > 0) &&
3073 (firsttf->iov_len == 0))
3075 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
3076 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
3077 struct smb2_signing_key key = {
3078 .blob = req->last_key,
3082 * As we are sure the header of the last request in the
3083 * compound chain will not change, we can to sign here
3084 * with the last signing key we remembered.
3086 status = smb2_signing_sign_pdu(&key,
3089 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
3090 smb2_signing_key_destructor(&key);
3091 if (!NT_STATUS_IS_OK(status)) {
3095 if (req->last_key.length > 0) {
3096 data_blob_clear_free(&req->last_key);
3099 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
3100 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
3102 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
3104 if (req->current_idx < req->out.vector_count) {
3106 * We must process the remaining compound
3107 * SMB2 requests before any new incoming SMB2
3108 * requests. This is because incoming SMB2
3109 * requests may include a cancel for a
3110 * compound request we haven't processed
3113 struct tevent_immediate *im = tevent_create_immediate(req);
3115 return NT_STATUS_NO_MEMORY;
3118 if (req->do_signing && firsttf->iov_len == 0) {
3119 struct smbXsrv_session *x = req->session;
3120 struct smb2_signing_key *signing_key =
3121 smbd_smb2_signing_key(x, xconn);
3124 * we need to remember the signing key
3125 * and defer the signing until
3126 * we are sure that we do not change
3129 req->last_key = data_blob_dup_talloc(req,
3131 if (req->last_key.data == NULL) {
3132 return NT_STATUS_NO_MEMORY;
3137 * smbd_smb2_request_dispatch() will redo the impersonation.
3138 * So we use req->xconn->client->raw_ev_ctx instead
3139 * of req->ev_ctx here.
3141 tevent_schedule_immediate(im,
3142 req->xconn->client->raw_ev_ctx,
3143 smbd_smb2_request_dispatch_immediate,
3145 return NT_STATUS_OK;
3148 if (req->compound_related) {
3149 req->compound_related = false;
3152 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
3154 return NT_STATUS_INVALID_PARAMETER_MIX;
3157 /* Set credit for these operations (zero credits if this
3158 is a final reply for an async operation). */
3159 smb2_calculate_credits(req, req);
3162 * now check if we need to sign the current response
3164 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
3165 struct smb2_signing_key key = {
3166 .blob = req->first_key,
3168 status = smb2_signing_encrypt_pdu(&key,
3169 xconn->smb2.server.cipher,
3171 req->out.vector_count - first_idx);
3172 smb2_signing_key_destructor(&key);
3173 if (!NT_STATUS_IS_OK(status)) {
3176 } else if (req->do_signing) {
3177 struct smbXsrv_session *x = req->session;
3178 struct smb2_signing_key *signing_key =
3179 smbd_smb2_signing_key(x, xconn);
3181 status = smb2_signing_sign_pdu(signing_key,
3184 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
3185 if (!NT_STATUS_IS_OK(status)) {
3189 if (req->first_key.length > 0) {
3190 data_blob_clear_free(&req->first_key);
3193 if (req->preauth != NULL) {
3194 gnutls_hash_hd_t hash_hnd = NULL;
3198 rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_SHA512);
3200 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3202 rc = gnutls_hash(hash_hnd,
3203 req->preauth->sha512_value,
3204 sizeof(req->preauth->sha512_value));
3206 gnutls_hash_deinit(hash_hnd, NULL);
3207 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3209 for (i = 1; i < req->in.vector_count; i++) {
3210 rc = gnutls_hash(hash_hnd,
3211 req->in.vector[i].iov_base,
3212 req->in.vector[i].iov_len);
3214 gnutls_hash_deinit(hash_hnd, NULL);
3215 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3219 gnutls_hash_deinit(hash_hnd, NULL);
3220 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3222 gnutls_hash_output(hash_hnd, req->preauth->sha512_value);
3224 rc = gnutls_hash(hash_hnd,
3225 req->preauth->sha512_value,
3226 sizeof(req->preauth->sha512_value));
3228 gnutls_hash_deinit(hash_hnd, NULL);
3229 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3231 for (i = 1; i < req->out.vector_count; i++) {
3232 rc = gnutls_hash(hash_hnd,
3233 req->out.vector[i].iov_base,
3234 req->out.vector[i].iov_len);
3236 gnutls_hash_deinit(hash_hnd, NULL);
3237 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3241 gnutls_hash_deinit(hash_hnd, req->preauth->sha512_value);
3243 req->preauth = NULL;
3246 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
3247 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
3248 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
3249 /* Dynamic part is NULL. Chop it off,
3250 We're going to send it via sendfile. */
3251 req->out.vector_count -= 1;
3255 * We're done with this request -
3256 * move it off the "being processed" queue.
3258 DLIST_REMOVE(xconn->smb2.requests, req);
3260 req->queue_entry.mem_ctx = req;
3261 req->queue_entry.vector = req->out.vector;
3262 req->queue_entry.count = req->out.vector_count;
3263 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry);
3264 xconn->smb2.send_queue_len++;
3266 status = smbd_smb2_flush_send_queue(xconn);
3267 if (!NT_STATUS_IS_OK(status)) {
3271 return NT_STATUS_OK;
3274 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
3276 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
3277 struct tevent_immediate *im,
3280 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
3281 struct smbd_smb2_request);
3282 struct smbXsrv_connection *xconn = req->xconn;
3287 if (DEBUGLEVEL >= 10) {
3288 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
3289 req->current_idx, req->in.vector_count));
3290 print_req_vectors(req);
3293 status = smbd_smb2_request_dispatch(req);
3294 if (!NT_STATUS_IS_OK(status)) {
3295 smbd_server_connection_terminate(xconn, nt_errstr(status));
3299 status = smbd_smb2_request_next_incoming(xconn);
3300 if (!NT_STATUS_IS_OK(status)) {
3301 smbd_server_connection_terminate(xconn, nt_errstr(status));
3306 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
3308 DATA_BLOB body, DATA_BLOB *dyn,
3309 const char *location)
3312 struct iovec *outbody_v;
3313 struct iovec *outdyn_v;
3314 uint32_t next_command_ofs;
3317 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3318 mid = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
3320 DBG_DEBUG("mid [%"PRIu64"] idx[%d] status[%s] "
3321 "body[%u] dyn[%s:%u] at %s\n",
3325 (unsigned int)body.length,
3327 (unsigned int)(dyn ? dyn->length : 0),
3330 if (body.length < 2) {
3331 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3334 if ((body.length % 2) != 0) {
3335 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3338 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
3339 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
3341 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
3342 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
3344 outbody_v->iov_base = (void *)body.data;
3345 outbody_v->iov_len = body.length;
3348 outdyn_v->iov_base = (void *)dyn->data;
3349 outdyn_v->iov_len = dyn->length;
3351 outdyn_v->iov_base = NULL;
3352 outdyn_v->iov_len = 0;
3356 * See if we need to recalculate the offset to the next response
3358 * Note that all responses may require padding (including the very last
3361 if (req->out.vector_count >= (2 * SMBD_SMB2_NUM_IOV_PER_REQ)) {
3362 next_command_ofs = SMB2_HDR_BODY;
3363 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
3364 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
3367 if ((next_command_ofs % 8) != 0) {
3368 size_t pad_size = 8 - (next_command_ofs % 8);
3369 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
3371 * if the dyn buffer is empty
3372 * we can use it to add padding
3376 pad = talloc_zero_array(req,
3379 return smbd_smb2_request_error(req,
3380 NT_STATUS_NO_MEMORY);
3383 outdyn_v->iov_base = (void *)pad;
3384 outdyn_v->iov_len = pad_size;
3387 * For now we copy the dynamic buffer
3388 * and add the padding to the new buffer
3395 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
3396 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
3398 new_size = old_size + pad_size;
3399 new_dyn = talloc_zero_array(req,
3401 if (new_dyn == NULL) {
3402 return smbd_smb2_request_error(req,
3403 NT_STATUS_NO_MEMORY);
3406 memcpy(new_dyn, old_dyn, old_size);
3407 memset(new_dyn + old_size, 0, pad_size);
3409 outdyn_v->iov_base = (void *)new_dyn;
3410 outdyn_v->iov_len = new_size;
3412 next_command_ofs += pad_size;
3415 if ((req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) >= req->out.vector_count) {
3416 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
3418 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
3420 return smbd_smb2_request_reply(req);
3423 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
3426 const char *location)
3428 struct smbXsrv_connection *xconn = req->xconn;
3431 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3432 size_t unread_bytes = smbd_smb2_unread_bytes(req);
3434 DBG_NOTICE("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| "
3435 "at %s\n", req->current_idx, nt_errstr(status),
3436 info ? " +info" : "", location);
3439 /* Recvfile error. Drain incoming socket. */
3443 ret = drain_socket(xconn->transport.sock, unread_bytes);
3444 if (ret != unread_bytes) {
3448 error = NT_STATUS_IO_DEVICE_ERROR;
3450 error = map_nt_error_from_unix_common(errno);
3453 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
3454 "ret[%u] errno[%d] => %s\n",
3455 (unsigned)unread_bytes,
3456 (unsigned)ret, errno, nt_errstr(error)));
3461 body.data = outhdr + SMB2_HDR_BODY;
3463 SSVAL(body.data, 0, 9);
3466 SIVAL(body.data, 0x04, info->length);
3468 /* Allocated size of req->out.vector[i].iov_base
3469 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
3470 * 1 byte without having to do an alloc.
3473 info->data = ((uint8_t *)outhdr) +
3474 OUTVEC_ALLOC_SIZE - 1;
3476 SCVAL(info->data, 0, 0);
3480 * Note: Even if there is an error, continue to process the request.
3484 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
3488 struct smbd_smb2_send_break_state {
3489 struct smbd_smb2_send_queue queue_entry;
3490 uint8_t nbt_hdr[NBT_HDR_SIZE];
3491 uint8_t tf[SMB2_TF_HDR_SIZE];
3492 uint8_t hdr[SMB2_HDR_BODY];
3493 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
3497 static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
3498 struct smbXsrv_session *session,
3499 struct smbXsrv_tcon *tcon,
3500 const uint8_t *body,
3503 struct smbd_smb2_send_break_state *state;
3504 bool do_encryption = false;
3505 uint64_t session_wire_id = 0;
3506 uint64_t nonce_high = 0;
3507 uint64_t nonce_low = 0;
3512 if (session != NULL) {
3513 session_wire_id = session->global->session_wire_id;
3514 do_encryption = session->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
3515 if (tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
3516 do_encryption = true;
3520 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
3523 state = talloc_zero_size(xconn, statelen);
3524 if (state == NULL) {
3525 return NT_STATUS_NO_MEMORY;
3527 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
3529 if (do_encryption) {
3530 status = smb2_get_new_nonce(session,
3533 if (!NT_STATUS_IS_OK(status)) {
3538 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
3539 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
3540 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
3541 SBVAL(state->tf, SMB2_TF_SESSION_ID, session_wire_id);
3543 SIVAL(state->hdr, 0, SMB2_MAGIC);
3544 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
3545 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
3546 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
3547 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
3548 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
3549 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
3550 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
3551 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
3552 SIVAL(state->hdr, SMB2_HDR_PID, 0);
3553 SIVAL(state->hdr, SMB2_HDR_TID, 0);
3554 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
3555 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
3557 state->vector[0] = (struct iovec) {
3558 .iov_base = state->nbt_hdr,
3559 .iov_len = sizeof(state->nbt_hdr)
3562 if (do_encryption) {
3563 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3564 .iov_base = state->tf,
3565 .iov_len = sizeof(state->tf)
3568 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3574 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
3575 .iov_base = state->hdr,
3576 .iov_len = sizeof(state->hdr)
3579 memcpy(state->body, body, body_len);
3581 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
3582 .iov_base = state->body,
3583 .iov_len = body_len /* no sizeof(state->body) .. :-) */
3587 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
3590 ok = smb2_setup_nbt_length(state->vector,
3591 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
3593 return NT_STATUS_INVALID_PARAMETER_MIX;
3596 if (do_encryption) {
3597 struct smb2_signing_key *encryption_key =
3598 session->global->encryption_key;
3600 status = smb2_signing_encrypt_pdu(encryption_key,
3601 xconn->smb2.server.cipher,
3602 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
3603 SMBD_SMB2_NUM_IOV_PER_REQ);
3604 if (!NT_STATUS_IS_OK(status)) {
3609 state->queue_entry.mem_ctx = state;
3610 state->queue_entry.vector = state->vector;
3611 state->queue_entry.count = ARRAY_SIZE(state->vector);
3612 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
3613 xconn->smb2.send_queue_len++;
3615 status = smbd_smb2_flush_send_queue(xconn);
3616 if (!NT_STATUS_IS_OK(status)) {
3620 return NT_STATUS_OK;
3623 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_connection *xconn,
3624 struct smbXsrv_session *session,
3625 struct smbXsrv_tcon *tcon,
3626 struct smbXsrv_open *op,
3627 uint8_t oplock_level)
3631 SSVAL(body, 0x00, sizeof(body));
3632 SCVAL(body, 0x02, oplock_level);
3633 SCVAL(body, 0x03, 0); /* reserved */
3634 SIVAL(body, 0x04, 0); /* reserved */
3635 SBVAL(body, 0x08, op->global->open_persistent_id);
3636 SBVAL(body, 0x10, op->global->open_volatile_id);
3638 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3641 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_connection *xconn,
3643 uint32_t lease_flags,
3644 struct smb2_lease_key *lease_key,
3645 uint32_t current_lease_state,
3646 uint32_t new_lease_state)
3650 SSVAL(body, 0x00, sizeof(body));
3651 SSVAL(body, 0x02, new_epoch);
3652 SIVAL(body, 0x04, lease_flags);
3653 SBVAL(body, 0x08, lease_key->data[0]);
3654 SBVAL(body, 0x10, lease_key->data[1]);
3655 SIVAL(body, 0x18, current_lease_state);
3656 SIVAL(body, 0x1c, new_lease_state);
3657 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
3658 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
3659 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
3661 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3664 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
3668 uint64_t file_id_persistent;
3669 uint64_t file_id_volatile;
3670 struct smbXsrv_open *op = NULL;
3671 struct files_struct *fsp = NULL;
3672 const uint8_t *body = NULL;
3675 * This is only called with a pktbuf
3676 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
3680 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
3681 /* Transform header. Cannot recvfile. */
3684 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
3685 /* Not SMB2. Normal error path will cope. */
3688 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
3689 /* Not SMB2. Normal error path will cope. */
3692 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
3693 /* Needs to be a WRITE. */
3696 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
3697 /* Chained. Cannot recvfile. */
3700 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
3701 if (flags & SMB2_HDR_FLAG_CHAINED) {
3702 /* Chained. Cannot recvfile. */
3705 if (flags & SMB2_HDR_FLAG_SIGNED) {
3706 /* Signed. Cannot recvfile. */
3710 body = &state->pktbuf[SMB2_HDR_BODY];
3712 file_id_persistent = BVAL(body, 0x10);
3713 file_id_volatile = BVAL(body, 0x18);
3715 status = smb2srv_open_lookup(state->req->xconn,
3720 if (!NT_STATUS_IS_OK(status)) {
3728 if (fsp->conn == NULL) {
3732 if (IS_IPC(fsp->conn)) {
3735 if (IS_PRINT(fsp->conn)) {
3738 if (fsp->base_fsp != NULL) {
3742 DEBUG(10,("Doing recvfile write len = %u\n",
3743 (unsigned int)(state->pktfull - state->pktlen)));
3748 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
3750 struct smbd_server_connection *sconn = xconn->client->sconn;
3751 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3752 size_t max_send_queue_len;
3753 size_t cur_send_queue_len;
3755 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3757 * we're not supposed to do any io
3759 return NT_STATUS_OK;
3762 if (state->req != NULL) {
3764 * if there is already a tstream_readv_pdu
3765 * pending, we are done.
3767 return NT_STATUS_OK;
3770 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
3771 cur_send_queue_len = xconn->smb2.send_queue_len;
3773 if (cur_send_queue_len > max_send_queue_len) {
3775 * if we have a lot of requests to send,
3776 * we wait until they are on the wire until we
3777 * ask for the next request.
3779 return NT_STATUS_OK;
3782 /* ask for the next request */
3783 ZERO_STRUCTP(state);
3784 state->req = smbd_smb2_request_allocate(xconn);
3785 if (state->req == NULL) {
3786 return NT_STATUS_NO_MEMORY;
3788 state->req->sconn = sconn;
3789 state->req->xconn = xconn;
3790 state->min_recv_size = lp_min_receive_file_size();
3792 TEVENT_FD_READABLE(xconn->transport.fde);
3794 return NT_STATUS_OK;
3797 NTSTATUS smbd_smb2_process_negprot(struct smbXsrv_connection *xconn,
3798 uint64_t expected_seq_low,
3799 const uint8_t *inpdu, size_t size)
3801 struct smbd_server_connection *sconn = xconn->client->sconn;
3803 struct smbd_smb2_request *req = NULL;
3805 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3806 (unsigned int)size));
3808 status = smbd_initialize_smb2(xconn, expected_seq_low);
3809 if (!NT_STATUS_IS_OK(status)) {
3810 smbd_server_connection_terminate(xconn, nt_errstr(status));
3814 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
3815 if (!NT_STATUS_IS_OK(status)) {
3816 smbd_server_connection_terminate(xconn, nt_errstr(status));
3820 status = smbd_smb2_request_validate(req);
3821 if (!NT_STATUS_IS_OK(status)) {
3822 smbd_server_connection_terminate(xconn, nt_errstr(status));
3826 status = smbd_smb2_request_setup_out(req);
3827 if (!NT_STATUS_IS_OK(status)) {
3828 smbd_server_connection_terminate(xconn, nt_errstr(status));
3834 * this was already counted at the SMB1 layer =>
3835 * smbd_smb2_request_dispatch() should not count it twice.
3837 if (profile_p->values.request_stats.count > 0) {
3838 profile_p->values.request_stats.count--;
3841 status = smbd_smb2_request_dispatch(req);
3842 if (!NT_STATUS_IS_OK(status)) {
3843 smbd_server_connection_terminate(xconn, nt_errstr(status));
3847 status = smbd_smb2_request_next_incoming(xconn);
3848 if (!NT_STATUS_IS_OK(status)) {
3849 smbd_server_connection_terminate(xconn, nt_errstr(status));
3853 sconn->num_requests++;
3854 return NT_STATUS_OK;
3857 static int socket_error_from_errno(int ret,
3871 if (sys_errno == 0) {
3875 if (sys_errno == EINTR) {
3880 if (sys_errno == EINPROGRESS) {
3885 if (sys_errno == EAGAIN) {
3890 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3891 if (sys_errno == ENOMEM) {
3897 #if EWOULDBLOCK != EAGAIN
3898 if (sys_errno == EWOULDBLOCK) {
3908 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3915 if (xconn->smb2.send_queue == NULL) {
3916 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3917 return NT_STATUS_OK;
3920 while (xconn->smb2.send_queue != NULL) {
3921 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3925 if (e->sendfile_header != NULL) {
3930 status = NT_STATUS_INTERNAL_ERROR;
3932 for (i=0; i < e->count; i++) {
3933 size += e->vector[i].iov_len;
3936 if (size <= e->sendfile_header->length) {
3937 buf = e->sendfile_header->data;
3939 buf = talloc_array(e->mem_ctx, uint8_t, size);
3941 return NT_STATUS_NO_MEMORY;
3946 for (i=0; i < e->count; i++) {
3948 e->vector[i].iov_base,
3949 e->vector[i].iov_len);
3950 size += e->vector[i].iov_len;
3953 e->sendfile_header->data = buf;
3954 e->sendfile_header->length = size;
3955 e->sendfile_status = &status;
3958 xconn->smb2.send_queue_len--;
3959 DLIST_REMOVE(xconn->smb2.send_queue, e);
3961 * This triggers the sendfile path via
3964 talloc_free(e->mem_ctx);
3966 if (!NT_STATUS_IS_OK(status)) {
3967 smbXsrv_connection_disconnect_transport(xconn,
3974 msg = (struct msghdr) {
3975 .msg_iov = e->vector,
3976 .msg_iovlen = e->count,
3979 ret = sendmsg(xconn->transport.sock, &msg, 0);
3981 /* propagate end of file */
3982 return NT_STATUS_INTERNAL_ERROR;
3984 err = socket_error_from_errno(ret, errno, &retry);
3987 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3988 return NT_STATUS_OK;
3991 status = map_nt_error_from_unix_common(err);
3992 smbXsrv_connection_disconnect_transport(xconn,
3997 ok = iov_advance(&e->vector, &e->count, ret);
3999 return NT_STATUS_INTERNAL_ERROR;
4003 /* we have more to write */
4004 TEVENT_FD_WRITEABLE(xconn->transport.fde);
4005 return NT_STATUS_OK;
4008 xconn->smb2.send_queue_len--;
4009 DLIST_REMOVE(xconn->smb2.send_queue, e);
4010 talloc_free(e->mem_ctx);
4014 * Restart reads if we were blocked on
4015 * draining the send queue.
4018 status = smbd_smb2_request_next_incoming(xconn);
4019 if (!NT_STATUS_IS_OK(status)) {
4023 return NT_STATUS_OK;
4026 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
4029 struct smbd_server_connection *sconn = xconn->client->sconn;
4030 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
4031 struct smbd_smb2_request *req = NULL;
4032 size_t min_recvfile_size = UINT32_MAX;
4040 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
4042 * we're not supposed to do any io
4044 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
4045 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
4046 return NT_STATUS_OK;
4049 if (fde_flags & TEVENT_FD_WRITE) {
4050 status = smbd_smb2_flush_send_queue(xconn);
4051 if (!NT_STATUS_IS_OK(status)) {
4056 if (!(fde_flags & TEVENT_FD_READ)) {
4057 return NT_STATUS_OK;
4060 if (state->req == NULL) {
4061 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
4062 return NT_STATUS_OK;
4066 if (!state->hdr.done) {
4067 state->hdr.done = true;
4069 state->vector.iov_base = (void *)state->hdr.nbt;
4070 state->vector.iov_len = NBT_HDR_SIZE;
4073 msg = (struct msghdr) {
4074 .msg_iov = &state->vector,
4078 ret = recvmsg(xconn->transport.sock, &msg, 0);
4080 /* propagate end of file */
4081 status = NT_STATUS_END_OF_FILE;
4082 smbXsrv_connection_disconnect_transport(xconn,
4086 err = socket_error_from_errno(ret, errno, &retry);
4089 TEVENT_FD_READABLE(xconn->transport.fde);
4090 return NT_STATUS_OK;
4093 status = map_nt_error_from_unix_common(err);
4094 smbXsrv_connection_disconnect_transport(xconn,
4099 if (ret < state->vector.iov_len) {
4101 base = (uint8_t *)state->vector.iov_base;
4103 state->vector.iov_base = (void *)base;
4104 state->vector.iov_len -= ret;
4105 /* we have more to read */
4106 TEVENT_FD_READABLE(xconn->transport.fde);
4107 return NT_STATUS_OK;
4110 if (state->pktlen > 0) {
4111 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
4113 * Not a possible receivefile write.
4114 * Read the rest of the data.
4116 state->doing_receivefile = false;
4118 state->pktbuf = talloc_realloc(state->req,
4122 if (state->pktbuf == NULL) {
4123 return NT_STATUS_NO_MEMORY;
4126 state->vector.iov_base = (void *)(state->pktbuf +
4128 state->vector.iov_len = (state->pktfull -
4131 state->pktlen = state->pktfull;
4136 * Either this is a receivefile write so we've
4137 * done a short read, or if not we have all the data.
4143 * Now we analyze the NBT header
4145 if (state->hdr.nbt[0] != 0x00) {
4146 state->min_recv_size = 0;
4148 state->pktfull = smb2_len(state->hdr.nbt);
4149 if (state->pktfull == 0) {
4153 if (state->min_recv_size != 0) {
4154 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
4155 min_recvfile_size += state->min_recv_size;
4158 if (state->pktfull > min_recvfile_size) {
4160 * Might be a receivefile write. Read the SMB2 HEADER +
4161 * SMB2_WRITE header first. Set 'doing_receivefile'
4162 * as we're *attempting* receivefile write. If this
4163 * turns out not to be a SMB2_WRITE request or otherwise
4164 * not suitable then we'll just read the rest of the data
4165 * the next time this function is called.
4167 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
4168 state->doing_receivefile = true;
4170 state->pktlen = state->pktfull;
4173 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
4174 if (state->pktbuf == NULL) {
4175 return NT_STATUS_NO_MEMORY;
4178 state->vector.iov_base = (void *)state->pktbuf;
4179 state->vector.iov_len = state->pktlen;
4185 if (state->hdr.nbt[0] != 0x00) {
4186 DEBUG(1,("ignore NBT[0x%02X] msg\n",
4187 state->hdr.nbt[0]));
4190 ZERO_STRUCTP(state);
4192 state->min_recv_size = lp_min_receive_file_size();
4200 req->request_time = timeval_current();
4201 now = timeval_to_nttime(&req->request_time);
4203 status = smbd_smb2_inbuf_parse_compound(xconn,
4209 &req->in.vector_count);
4210 if (!NT_STATUS_IS_OK(status)) {
4214 if (state->doing_receivefile) {
4215 req->smb1req = talloc_zero(req, struct smb_request);
4216 if (req->smb1req == NULL) {
4217 return NT_STATUS_NO_MEMORY;
4219 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
4222 ZERO_STRUCTP(state);
4224 req->current_idx = 1;
4226 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
4227 req->current_idx, req->in.vector_count));
4229 status = smbd_smb2_request_validate(req);
4230 if (!NT_STATUS_IS_OK(status)) {
4234 status = smbd_smb2_request_setup_out(req);
4235 if (!NT_STATUS_IS_OK(status)) {
4239 status = smbd_smb2_request_dispatch(req);
4240 if (!NT_STATUS_IS_OK(status)) {
4244 sconn->num_requests++;
4246 /* The timeout_processing function isn't run nearly
4247 often enough to implement 'max log size' without
4248 overrunning the size of the file by many megabytes.
4249 This is especially true if we are running at debug
4250 level 10. Checking every 50 SMB2s is a nice
4251 tradeoff of performance vs log file size overrun. */
4253 if ((sconn->num_requests % 50) == 0 &&
4254 need_to_check_log_size()) {
4255 change_to_root_user();
4259 status = smbd_smb2_request_next_incoming(xconn);
4260 if (!NT_STATUS_IS_OK(status)) {
4264 return NT_STATUS_OK;
4267 static void smbd_smb2_connection_handler(struct tevent_context *ev,
4268 struct tevent_fd *fde,
4272 struct smbXsrv_connection *xconn =
4273 talloc_get_type_abort(private_data,
4274 struct smbXsrv_connection);
4277 status = smbd_smb2_io_handler(xconn, flags);
4278 if (!NT_STATUS_IS_OK(status)) {
4279 smbd_server_connection_terminate(xconn, nt_errstr(status));