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 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 void smbd_server_disconnect_client_ex(struct smbXsrv_client *client,
1304 const char *location)
1308 num_ok = smbXsrv_client_valid_connections(client);
1310 DBG_WARNING("client[%s] num_ok[%zu] reason[%s] at %s\n",
1311 client->global->remote_address, num_ok,
1315 * Something bad happened we need to disconnect all connections.
1317 exit_server_cleanly(reason);
1320 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1321 struct iovec *outvec,
1322 const struct iovec *srcvec)
1324 const uint8_t *srctf;
1326 const uint8_t *srchdr;
1328 const uint8_t *srcbody;
1330 const uint8_t *expected_srcbody;
1331 const uint8_t *srcdyn;
1333 const uint8_t *expected_srcdyn;
1339 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1340 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1341 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1342 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1343 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1344 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1345 expected_srcbody = srchdr + SMB2_HDR_BODY;
1346 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1347 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1348 expected_srcdyn = srcbody + 8;
1350 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1354 if (srchdr_len != SMB2_HDR_BODY) {
1358 if (srctf_len == SMB2_TF_HDR_SIZE) {
1359 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1360 if (dsttf == NULL) {
1366 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1367 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1369 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1370 * be allocated with size OUTVEC_ALLOC_SIZE. */
1372 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1373 if (dsthdr == NULL) {
1376 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1377 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1380 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1381 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1382 * then duplicate this. Else use talloc_memdup().
1385 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1386 dstbody = dsthdr + SMB2_HDR_BODY;
1388 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1389 if (dstbody == NULL) {
1393 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1394 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1397 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1399 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1400 * then duplicate this. Else use talloc_memdup().
1403 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1404 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1405 } else if (srcdyn == NULL) {
1408 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1409 if (dstdyn == NULL) {
1413 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1414 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1419 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1421 struct smbd_smb2_request *newreq = NULL;
1422 struct iovec *outvec = NULL;
1423 int count = req->out.vector_count;
1427 newreq = smbd_smb2_request_allocate(req->xconn);
1432 newreq->sconn = req->sconn;
1433 newreq->xconn = req->xconn;
1434 newreq->session = req->session;
1435 newreq->do_encryption = req->do_encryption;
1436 newreq->do_signing = req->do_signing;
1437 newreq->current_idx = req->current_idx;
1439 outvec = talloc_zero_array(newreq, struct iovec, count);
1441 TALLOC_FREE(newreq);
1444 newreq->out.vector = outvec;
1445 newreq->out.vector_count = count;
1447 /* Setup the outvec's identically to req. */
1448 outvec[0].iov_base = newreq->out.nbt_hdr;
1449 outvec[0].iov_len = 4;
1450 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1452 /* Setup the vectors identically to the ones in req. */
1453 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1454 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1461 TALLOC_FREE(newreq);
1465 ok = smb2_setup_nbt_length(newreq->out.vector,
1466 newreq->out.vector_count);
1468 TALLOC_FREE(newreq);
1475 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1477 struct smbXsrv_connection *xconn = req->xconn;
1479 struct iovec *firsttf = NULL;
1480 struct iovec *outhdr_v = NULL;
1481 uint8_t *outhdr = NULL;
1482 struct smbd_smb2_request *nreq = NULL;
1486 /* Create a new smb2 request we'll use
1487 for the interim return. */
1488 nreq = dup_smb2_req(req);
1490 return NT_STATUS_NO_MEMORY;
1493 /* Lose the last X out vectors. They're the
1494 ones we'll be using for the async reply. */
1495 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1497 ok = smb2_setup_nbt_length(nreq->out.vector,
1498 nreq->out.vector_count);
1500 return NT_STATUS_INVALID_PARAMETER_MIX;
1503 /* Step back to the previous reply. */
1504 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1505 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1506 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1507 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1508 /* And end the chain. */
1509 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1511 /* Calculate outgoing credits */
1512 smb2_calculate_credits(req, nreq);
1514 if (DEBUGLEVEL >= 10) {
1515 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1516 (unsigned int)nreq->current_idx );
1517 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1518 (unsigned int)nreq->out.vector_count );
1519 print_req_vectors(nreq);
1523 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1524 * we need to sign/encrypt here with the last/first key we remembered
1526 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1527 struct smb2_signing_key key = {
1528 .blob = req->first_key,
1530 status = smb2_signing_encrypt_pdu(&key,
1531 xconn->smb2.server.cipher,
1533 nreq->out.vector_count - first_idx);
1534 smb2_signing_key_destructor(&key);
1535 if (!NT_STATUS_IS_OK(status)) {
1538 } else if (req->last_key.length > 0) {
1539 struct smb2_signing_key key = {
1540 .blob = req->last_key,
1543 status = smb2_signing_sign_pdu(&key,
1546 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1547 smb2_signing_key_destructor(&key);
1548 if (!NT_STATUS_IS_OK(status)) {
1553 nreq->queue_entry.mem_ctx = nreq;
1554 nreq->queue_entry.vector = nreq->out.vector;
1555 nreq->queue_entry.count = nreq->out.vector_count;
1556 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry);
1557 xconn->smb2.send_queue_len++;
1559 status = smbd_smb2_flush_send_queue(xconn);
1560 if (!NT_STATUS_IS_OK(status)) {
1564 return NT_STATUS_OK;
1567 struct smbd_smb2_request_pending_state {
1568 struct smbd_smb2_send_queue queue_entry;
1569 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1570 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1573 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1574 struct tevent_timer *te,
1575 struct timeval current_time,
1576 void *private_data);
1578 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1579 struct tevent_req *subreq,
1580 uint32_t defer_time)
1583 struct timeval defer_endtime;
1584 uint8_t *outhdr = NULL;
1587 if (!tevent_req_is_in_progress(subreq)) {
1589 * This is a performance optimization,
1590 * it avoids one tevent_loop iteration,
1591 * which means we avoid one
1592 * talloc_stackframe_pool/talloc_free pair.
1594 tevent_req_notify_callback(subreq);
1595 return NT_STATUS_OK;
1598 req->subreq = subreq;
1601 if (req->async_te) {
1602 /* We're already async. */
1603 return NT_STATUS_OK;
1606 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1607 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1608 if (flags & SMB2_HDR_FLAG_ASYNC) {
1609 /* We're already async. */
1610 return NT_STATUS_OK;
1613 if (req->async_internal || defer_time == 0) {
1615 * An SMB2 request implementation wants to handle the request
1616 * asynchronously "internally" while keeping synchronous
1617 * behaviour for the SMB2 request. This means we don't send an
1618 * interim response and we can allow processing of compound SMB2
1619 * requests (cf the subsequent check) for all cases.
1621 return NT_STATUS_OK;
1624 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1626 * We're trying to go async in a compound request
1627 * chain. This is only allowed for opens that cause an
1628 * oplock break or for the last operation in the
1629 * chain, otherwise it is not allowed. See
1630 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
1632 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1634 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1636 * Cancel the outstanding request.
1638 bool ok = tevent_req_cancel(req->subreq);
1640 return NT_STATUS_OK;
1642 TALLOC_FREE(req->subreq);
1643 return smbd_smb2_request_error(req,
1644 NT_STATUS_INTERNAL_ERROR);
1648 if (DEBUGLEVEL >= 10) {
1649 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1650 (unsigned int)req->current_idx );
1651 print_req_vectors(req);
1654 if (req->current_idx > 1) {
1656 * We're going async in a compound
1657 * chain after the first request has
1658 * already been processed. Send an
1659 * interim response containing the
1660 * set of replies already generated.
1662 int idx = req->current_idx;
1664 status = smb2_send_async_interim_response(req);
1665 if (!NT_STATUS_IS_OK(status)) {
1668 if (req->first_key.length > 0) {
1669 data_blob_clear_free(&req->first_key);
1672 req->current_idx = 1;
1675 * Re-arrange the in.vectors to remove what
1678 memmove(&req->in.vector[1],
1679 &req->in.vector[idx],
1680 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1681 req->in.vector_count = 1 + (req->in.vector_count - idx);
1683 /* Re-arrange the out.vectors to match. */
1684 memmove(&req->out.vector[1],
1685 &req->out.vector[idx],
1686 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1687 req->out.vector_count = 1 + (req->out.vector_count - idx);
1689 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1691 * We only have one remaining request as
1692 * we've processed everything else.
1693 * This is no longer a compound request.
1695 req->compound_related = false;
1696 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1697 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1698 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1701 if (req->last_key.length > 0) {
1702 data_blob_clear_free(&req->last_key);
1706 * smbd_smb2_request_pending_timer() just send a packet
1707 * to the client and doesn't need any impersonation.
1708 * So we use req->xconn->client->raw_ev_ctx instead
1709 * of req->ev_ctx here.
1711 defer_endtime = timeval_current_ofs_usec(defer_time);
1712 req->async_te = tevent_add_timer(req->xconn->client->raw_ev_ctx,
1714 smbd_smb2_request_pending_timer,
1716 if (req->async_te == NULL) {
1717 return NT_STATUS_NO_MEMORY;
1720 return NT_STATUS_OK;
1724 struct smb2_signing_key *smbd_smb2_signing_key(struct smbXsrv_session *session,
1725 struct smbXsrv_connection *xconn)
1727 struct smbXsrv_channel_global0 *c = NULL;
1729 struct smb2_signing_key *key = NULL;
1731 status = smbXsrv_session_find_channel(session, xconn, &c);
1732 if (NT_STATUS_IS_OK(status)) {
1733 key = c->signing_key;
1736 if (!smb2_signing_key_valid(key)) {
1737 key = session->global->signing_key;
1743 static NTSTATUS smb2_get_new_nonce(struct smbXsrv_session *session,
1744 uint64_t *new_nonce_high,
1745 uint64_t *new_nonce_low)
1747 uint64_t nonce_high;
1750 session->nonce_low += 1;
1751 if (session->nonce_low == 0) {
1752 session->nonce_low += 1;
1753 session->nonce_high += 1;
1757 * CCM and GCM algorithms must never have their
1758 * nonce wrap, or the security of the whole
1759 * communication and the keys is destroyed.
1760 * We must drop the connection once we have
1761 * transfered too much data.
1763 * NOTE: We assume nonces greater than 8 bytes.
1765 if (session->nonce_high >= session->nonce_high_max) {
1766 return NT_STATUS_ENCRYPTION_FAILED;
1769 nonce_high = session->nonce_high_random;
1770 nonce_high += session->nonce_high;
1771 nonce_low = session->nonce_low;
1773 *new_nonce_high = nonce_high;
1774 *new_nonce_low = nonce_low;
1775 return NT_STATUS_OK;
1778 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1779 struct tevent_timer *te,
1780 struct timeval current_time,
1783 struct smbd_smb2_request *req =
1784 talloc_get_type_abort(private_data,
1785 struct smbd_smb2_request);
1786 struct smbXsrv_connection *xconn = req->xconn;
1787 struct smbd_smb2_request_pending_state *state = NULL;
1788 uint8_t *outhdr = NULL;
1789 const uint8_t *inhdr = NULL;
1791 uint8_t *hdr = NULL;
1792 uint8_t *body = NULL;
1793 uint8_t *dyn = NULL;
1795 uint64_t message_id = 0;
1796 uint64_t async_id = 0;
1800 TALLOC_FREE(req->async_te);
1802 /* Ensure our final reply matches the interim one. */
1803 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1804 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1805 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1806 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1808 async_id = message_id; /* keep it simple for now... */
1810 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1811 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1813 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1815 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1816 (unsigned long long)async_id ));
1819 * What we send is identical to a smbd_smb2_request_error
1820 * packet with an error status of STATUS_PENDING. Make use
1821 * of this fact sometime when refactoring. JRA.
1824 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
1825 if (state == NULL) {
1826 smbd_server_connection_terminate(xconn,
1827 nt_errstr(NT_STATUS_NO_MEMORY));
1831 tf = state->buf + NBT_HDR_SIZE;
1833 hdr = tf + SMB2_TF_HDR_SIZE;
1834 body = hdr + SMB2_HDR_BODY;
1837 if (req->do_encryption) {
1838 uint64_t nonce_high = 0;
1839 uint64_t nonce_low = 0;
1840 uint64_t session_id = req->session->global->session_wire_id;
1842 status = smb2_get_new_nonce(req->session,
1845 if (!NT_STATUS_IS_OK(status)) {
1846 smbd_server_connection_terminate(xconn,
1851 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1852 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1853 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1854 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1857 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1858 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1859 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1860 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(NT_STATUS_PENDING));
1861 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1863 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1864 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1865 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1866 SBVAL(hdr, SMB2_HDR_PID, async_id);
1867 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1868 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1869 memcpy(hdr+SMB2_HDR_SIGNATURE,
1870 outhdr+SMB2_HDR_SIGNATURE, 16);
1872 SSVAL(body, 0x00, 0x08 + 1);
1874 SCVAL(body, 0x02, 0);
1875 SCVAL(body, 0x03, 0);
1876 SIVAL(body, 0x04, 0);
1877 /* Match W2K8R2... */
1878 SCVAL(dyn, 0x00, 0x21);
1880 state->vector[0].iov_base = (void *)state->buf;
1881 state->vector[0].iov_len = NBT_HDR_SIZE;
1883 if (req->do_encryption) {
1884 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1885 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len =
1888 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1889 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1892 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1893 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1895 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1896 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1898 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1899 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1901 ok = smb2_setup_nbt_length(state->vector,
1902 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1904 smbd_server_connection_terminate(
1905 xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
1909 /* Ensure we correctly go through crediting. Grant
1910 the credits now, and zero credits on the final
1912 smb2_set_operation_credit(req->xconn,
1913 SMBD_SMB2_IN_HDR_IOV(req),
1914 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1916 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1921 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1922 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1924 (unsigned int)ARRAY_SIZE(state->vector),
1925 (unsigned int)state->vector[i].iov_len);
1929 if (req->do_encryption) {
1930 struct smbXsrv_session *x = req->session;
1931 struct smb2_signing_key *encryption_key = x->global->encryption_key;
1933 status = smb2_signing_encrypt_pdu(encryption_key,
1934 xconn->smb2.server.cipher,
1935 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1936 SMBD_SMB2_NUM_IOV_PER_REQ);
1937 if (!NT_STATUS_IS_OK(status)) {
1938 smbd_server_connection_terminate(xconn,
1942 } else if (req->do_signing) {
1943 struct smbXsrv_session *x = req->session;
1944 struct smb2_signing_key *signing_key =
1945 smbd_smb2_signing_key(x, xconn);
1947 status = smb2_signing_sign_pdu(signing_key,
1949 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1950 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1951 if (!NT_STATUS_IS_OK(status)) {
1952 smbd_server_connection_terminate(xconn,
1958 state->queue_entry.mem_ctx = state;
1959 state->queue_entry.vector = state->vector;
1960 state->queue_entry.count = ARRAY_SIZE(state->vector);
1961 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
1962 xconn->smb2.send_queue_len++;
1964 status = smbd_smb2_flush_send_queue(xconn);
1965 if (!NT_STATUS_IS_OK(status)) {
1966 smbd_server_connection_terminate(xconn,
1972 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1974 struct smbXsrv_connection *xconn = req->xconn;
1975 struct smbd_smb2_request *cur;
1976 const uint8_t *inhdr;
1978 uint64_t search_message_id;
1979 uint64_t search_async_id;
1982 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1984 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1985 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1986 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1989 * We don't need the request anymore cancel requests never
1992 * We defer the TALLOC_FREE(req) to the caller.
1994 DLIST_REMOVE(xconn->smb2.requests, req);
1996 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1997 const uint8_t *outhdr;
1998 uint64_t message_id;
2001 if (cur->compound_related) {
2003 * Never cancel anything in a compound request.
2004 * Way too hard to deal with the result.
2009 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
2011 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
2012 async_id = BVAL(outhdr, SMB2_HDR_PID);
2014 if (flags & SMB2_HDR_FLAG_ASYNC) {
2015 if (search_async_id == async_id) {
2016 found_id = async_id;
2020 if (search_message_id == message_id) {
2021 found_id = message_id;
2027 if (cur && cur->subreq) {
2028 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
2029 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
2030 "cancel opcode[%s] mid %llu\n",
2031 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
2032 (unsigned long long)found_id ));
2033 tevent_req_cancel(cur->subreq);
2036 return NT_STATUS_OK;
2039 /*************************************************************
2040 Ensure an incoming tid is a valid one for us to access.
2041 Change to the associated uid credentials and chdir to the
2042 valid tid directory.
2043 *************************************************************/
2045 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
2047 const uint8_t *inhdr;
2050 struct smbXsrv_tcon *tcon;
2052 NTTIME now = timeval_to_nttime(&req->request_time);
2056 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2058 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2059 in_tid = IVAL(inhdr, SMB2_HDR_TID);
2061 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
2062 in_tid = req->last_tid;
2067 status = smb2srv_tcon_lookup(req->session,
2068 in_tid, now, &tcon);
2069 if (!NT_STATUS_IS_OK(status)) {
2073 if (!change_to_user_and_service(
2075 req->session->global->session_wire_id))
2077 return NT_STATUS_ACCESS_DENIED;
2081 req->last_tid = in_tid;
2083 return NT_STATUS_OK;
2086 /*************************************************************
2087 Ensure an incoming session_id is a valid one for us to access.
2088 *************************************************************/
2090 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
2092 const uint8_t *inhdr;
2095 uint64_t in_session_id;
2096 struct smbXsrv_session *session = NULL;
2097 struct auth_session_info *session_info;
2099 NTTIME now = timeval_to_nttime(&req->request_time);
2101 req->session = NULL;
2104 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2106 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2107 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2108 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
2110 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
2111 in_session_id = req->last_session_id;
2114 req->last_session_id = 0;
2116 /* look an existing session up */
2117 switch (in_opcode) {
2118 case SMB2_OP_SESSSETUP:
2120 * For a session bind request, we don't have the
2121 * channel set up at this point yet, so we defer
2122 * the verification that the connection belongs
2123 * to the session to the session setup code, which
2124 * can look at the session binding flags.
2126 status = smb2srv_session_lookup_client(req->xconn->client,
2131 status = smb2srv_session_lookup_conn(req->xconn,
2137 req->session = session;
2138 req->last_session_id = in_session_id;
2140 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
2141 switch (in_opcode) {
2142 case SMB2_OP_SESSSETUP:
2143 status = NT_STATUS_OK;
2145 case SMB2_OP_LOGOFF:
2148 case SMB2_OP_CANCEL:
2149 case SMB2_OP_KEEPALIVE:
2151 * [MS-SMB2] 3.3.5.2.9 Verifying the Session
2152 * specifies that LOGOFF, CLOSE and (UN)LOCK
2153 * should always be processed even on expired sessions.
2155 * Also see the logic in
2156 * smbd_smb2_request_process_lock().
2158 * The smb2.session.expire2 test shows that
2159 * CANCEL and KEEPALIVE/ECHO should also
2162 status = NT_STATUS_OK;
2168 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2169 switch (in_opcode) {
2171 case SMB2_OP_CREATE:
2172 case SMB2_OP_GETINFO:
2173 case SMB2_OP_SETINFO:
2174 return NT_STATUS_INVALID_HANDLE;
2177 * Notice the check for
2178 * (session_info == NULL)
2181 status = NT_STATUS_OK;
2185 if (!NT_STATUS_IS_OK(status)) {
2189 session_info = session->global->auth_session_info;
2190 if (session_info == NULL) {
2191 return NT_STATUS_INVALID_HANDLE;
2194 return NT_STATUS_OK;
2197 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
2198 uint32_t data_length)
2200 struct smbXsrv_connection *xconn = req->xconn;
2201 uint16_t needed_charge;
2202 uint16_t credit_charge = 1;
2203 const uint8_t *inhdr;
2205 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2207 if (xconn->smb2.credits.multicredit) {
2208 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
2209 credit_charge = MAX(credit_charge, 1);
2212 needed_charge = (data_length - 1)/ 65536 + 1;
2214 DBGC_DEBUG(DBGC_SMB2_CREDITS,
2215 "mid %llu, CreditCharge: %d, NeededCharge: %d\n",
2216 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
2217 credit_charge, needed_charge);
2219 if (needed_charge > credit_charge) {
2220 DBGC_WARNING(DBGC_SMB2_CREDITS,
2221 "CreditCharge too low, given %d, needed %d\n",
2222 credit_charge, needed_charge);
2223 return NT_STATUS_INVALID_PARAMETER;
2226 return NT_STATUS_OK;
2229 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
2230 size_t expected_body_size)
2232 struct iovec *inhdr_v;
2233 const uint8_t *inhdr;
2235 const uint8_t *inbody;
2237 size_t min_dyn_size = expected_body_size & 0x00000001;
2238 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
2241 * The following should be checked already.
2243 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
2244 return NT_STATUS_INTERNAL_ERROR;
2246 if (req->current_idx > max_idx) {
2247 return NT_STATUS_INTERNAL_ERROR;
2250 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
2251 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
2252 return NT_STATUS_INTERNAL_ERROR;
2254 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
2255 return NT_STATUS_INTERNAL_ERROR;
2258 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2259 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2263 case SMB2_OP_GETINFO:
2270 * Now check the expected body size,
2271 * where the last byte might be in the
2274 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
2275 return NT_STATUS_INVALID_PARAMETER;
2277 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
2278 return NT_STATUS_INVALID_PARAMETER;
2281 inbody = SMBD_SMB2_IN_BODY_PTR(req);
2283 body_size = SVAL(inbody, 0x00);
2284 if (body_size != expected_body_size) {
2285 return NT_STATUS_INVALID_PARAMETER;
2288 return NT_STATUS_OK;
2291 bool smbXsrv_is_encrypted(uint8_t encryption_flags)
2293 return (!(encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)
2295 (encryption_flags & (SMBXSRV_PROCESSED_ENCRYPTED_PACKET |
2296 SMBXSRV_ENCRYPTION_DESIRED |
2297 SMBXSRV_ENCRYPTION_REQUIRED)));
2300 bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags)
2302 return ((encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET) &&
2303 (encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET));
2306 /* Set a flag if not already set, return true if set */
2307 bool smbXsrv_set_crypto_flag(uint8_t *flags, uint8_t flag)
2309 if ((flag == 0) || (*flags & flag)) {
2318 * Update encryption state tracking flags, this can be used to
2319 * determine whether whether the session or tcon is "encrypted".
2321 static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
2323 bool *update_session_globalp,
2324 bool *update_tcon_globalp)
2326 /* Default: assume unecrypted and unsigned */
2327 struct smbXsrv_session *session = req->session;
2328 struct smbXsrv_tcon *tcon = req->tcon;
2329 uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
2330 uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2331 bool update_session = false;
2332 bool update_tcon = false;
2334 if (req->was_encrypted && req->do_encryption) {
2335 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
2336 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2338 /* Unencrypted packet, can be signed */
2339 if (req->do_signing) {
2340 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2341 } else if (opcode == SMB2_OP_CANCEL) {
2342 /* Cancel requests are allowed to skip signing */
2343 sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2347 update_session |= smbXsrv_set_crypto_flag(
2348 &session->global->encryption_flags, encrypt_flag);
2349 update_session |= smbXsrv_set_crypto_flag(
2350 &session->global->signing_flags, sign_flag);
2353 update_tcon |= smbXsrv_set_crypto_flag(
2354 &tcon->global->encryption_flags, encrypt_flag);
2355 update_tcon |= smbXsrv_set_crypto_flag(
2356 &tcon->global->signing_flags, sign_flag);
2359 *update_session_globalp = update_session;
2360 *update_tcon_globalp = update_tcon;
2364 bool smbXsrv_is_signed(uint8_t signing_flags)
2367 * Signing is always enabled, so unless we got an unsigned
2368 * packet and at least one signed packet that was not
2369 * encrypted, the session or tcon is "signed".
2371 return (!(signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2372 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2375 bool smbXsrv_is_partially_signed(uint8_t signing_flags)
2377 return ((signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2378 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2381 static NTSTATUS smbd_smb2_request_dispatch_update_counts(
2382 struct smbd_smb2_request *req,
2385 struct smbXsrv_connection *xconn = req->xconn;
2386 const uint8_t *inhdr;
2387 uint16_t channel_sequence;
2388 uint8_t generation_wrap = 0;
2391 struct smbXsrv_open *op;
2392 bool update_open = false;
2393 NTSTATUS status = NT_STATUS_OK;
2395 SMB_ASSERT(!req->request_counters_updated);
2397 if (xconn->protocol < PROTOCOL_SMB2_22) {
2398 return NT_STATUS_OK;
2401 if (req->compat_chain_fsp == NULL) {
2402 return NT_STATUS_OK;
2405 op = req->compat_chain_fsp->op;
2407 return NT_STATUS_OK;
2410 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2411 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2412 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2414 cmp = channel_sequence - op->global->channel_sequence;
2417 * csn wrap. We need to watch out for long-running
2418 * requests that are still sitting on a previously
2419 * used csn. SMB2_OP_NOTIFY can take VERY long.
2421 generation_wrap += 1;
2424 if (abs(cmp) > INT16_MAX) {
2426 * [MS-SMB2] 3.3.5.2.10 - Verifying the Channel Sequence Number:
2428 * If the channel sequence number of the request and the one
2429 * known to the server are not equal, the channel sequence
2430 * number and outstanding request counts are only updated
2431 * "... if the unsigned difference using 16-bit arithmetic
2432 * between ChannelSequence and Open.ChannelSequence is less than
2433 * or equal to 0x7FFF ...".
2434 * Otherwise, an error is returned for the modifying
2435 * calls write, set_info, and ioctl.
2437 * There are currently two issues with the description:
2439 * * For the other calls, the document seems to imply
2440 * that processing continues without adapting the
2441 * counters (if the sequence numbers are not equal).
2443 * TODO: This needs clarification!
2445 * * Also, the behaviour if the difference is larger
2446 * than 0x7FFF is not clear. The document seems to
2447 * imply that if such a difference is reached,
2448 * the server starts to ignore the counters or
2449 * in the case of the modifying calls, return errors.
2451 * TODO: This needs clarification!
2453 * At this point Samba tries to be a little more
2454 * clever than the description in the MS-SMB2 document
2455 * by heuristically detecting and properly treating
2456 * a 16 bit overflow of the client-submitted sequence
2459 * If the stored channel sequence number is more than
2460 * 0x7FFF larger than the one from the request, then
2461 * the client-provided sequence number has likely
2462 * overflown. We treat this case as valid instead
2465 * The MS-SMB2 behaviour would be setting cmp = -1.
2470 if (flags & SMB2_HDR_FLAG_REPLAY_OPERATION) {
2471 if (cmp == 0 && op->pre_request_count == 0) {
2472 op->request_count += 1;
2473 req->request_counters_updated = true;
2474 } else if (cmp > 0 && op->pre_request_count == 0) {
2475 op->pre_request_count += op->request_count;
2476 op->request_count = 1;
2477 op->global->channel_sequence = channel_sequence;
2478 op->global->channel_generation += generation_wrap;
2480 req->request_counters_updated = true;
2481 } else if (modify_call) {
2482 return NT_STATUS_FILE_NOT_AVAILABLE;
2486 op->request_count += 1;
2487 req->request_counters_updated = true;
2488 } else if (cmp > 0) {
2489 op->pre_request_count += op->request_count;
2490 op->request_count = 1;
2491 op->global->channel_sequence = channel_sequence;
2492 op->global->channel_generation += generation_wrap;
2494 req->request_counters_updated = true;
2495 } else if (modify_call) {
2496 return NT_STATUS_FILE_NOT_AVAILABLE;
2499 req->channel_generation = op->global->channel_generation;
2502 status = smbXsrv_open_update(op);
2508 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
2510 struct smbXsrv_connection *xconn = req->xconn;
2511 const struct smbd_smb2_dispatch_table *call = NULL;
2512 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
2513 const uint8_t *inhdr;
2518 NTSTATUS session_status;
2519 uint32_t allowed_flags;
2520 NTSTATUS return_value;
2521 struct smbXsrv_session *x = NULL;
2522 bool signing_required = false;
2523 bool encryption_desired = false;
2524 bool encryption_required = false;
2526 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2528 DO_PROFILE_INC(request);
2530 SMB_ASSERT(!req->request_counters_updated);
2532 /* TODO: verify more things */
2534 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2535 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2536 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2537 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
2538 smb2_opcode_name(opcode),
2539 (unsigned long long)mid));
2541 if (xconn->protocol >= PROTOCOL_SMB2_02) {
2543 * once the protocol is negotiated
2544 * SMB2_OP_NEGPROT is not allowed anymore
2546 if (opcode == SMB2_OP_NEGPROT) {
2547 /* drop the connection */
2548 return NT_STATUS_INVALID_PARAMETER;
2552 * if the protocol is not negotiated yet
2553 * only SMB2_OP_NEGPROT is allowed.
2555 if (opcode != SMB2_OP_NEGPROT) {
2556 /* drop the connection */
2557 return NT_STATUS_INVALID_PARAMETER;
2562 * Check if the client provided a valid session id.
2564 * As some command don't require a valid session id
2565 * we defer the check of the session_status
2567 session_status = smbd_smb2_request_check_session(req);
2570 signing_required = x->global->signing_flags & SMBXSRV_SIGNING_REQUIRED;
2571 encryption_desired = x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
2572 encryption_required = x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
2575 req->async_internal = false;
2576 req->do_signing = false;
2577 if (opcode != SMB2_OP_SESSSETUP) {
2578 req->do_encryption = encryption_desired;
2580 req->do_encryption = false;
2582 req->was_encrypted = false;
2583 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
2584 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
2585 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
2587 if (x != NULL && x->global->session_wire_id != tf_session_id) {
2588 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2589 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
2590 (unsigned long long)x->global->session_wire_id,
2591 (unsigned long long)tf_session_id));
2593 * TODO: windows allows this...
2594 * should we drop the connection?
2596 * For now we just return ACCESS_DENIED
2597 * (Windows clients never trigger this)
2598 * and wait for an update of [MS-SMB2].
2600 return smbd_smb2_request_error(req,
2601 NT_STATUS_ACCESS_DENIED);
2604 req->was_encrypted = true;
2605 req->do_encryption = true;
2608 if (encryption_required && !req->was_encrypted) {
2609 req->do_encryption = true;
2610 return smbd_smb2_request_error(req,
2611 NT_STATUS_ACCESS_DENIED);
2614 call = smbd_smb2_call(opcode);
2616 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2619 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2620 SMB2_HDR_FLAG_SIGNED |
2622 if (xconn->protocol >= PROTOCOL_SMB3_11) {
2623 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2625 if (opcode == SMB2_OP_NEGPROT) {
2626 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11) {
2627 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2630 if (opcode == SMB2_OP_CANCEL) {
2631 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2633 if (xconn->protocol >= PROTOCOL_SMB2_22) {
2634 allowed_flags |= SMB2_HDR_FLAG_REPLAY_OPERATION;
2636 if ((flags & ~allowed_flags) != 0) {
2637 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2640 if (flags & SMB2_HDR_FLAG_CHAINED) {
2642 * This check is mostly for giving the correct error code
2643 * for compounded requests.
2645 if (!NT_STATUS_IS_OK(session_status)) {
2646 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2649 req->compat_chain_fsp = NULL;
2652 if (req->was_encrypted) {
2653 signing_required = false;
2654 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2655 struct smb2_signing_key *signing_key = NULL;
2659 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2660 * If the SMB2 header of the SMB2 NEGOTIATE
2661 * request has the SMB2_FLAGS_SIGNED bit set in the
2662 * Flags field, the server MUST fail the request
2663 * with STATUS_INVALID_PARAMETER.
2665 * Microsoft test tool checks this.
2668 if ((opcode == SMB2_OP_NEGPROT) &&
2669 (flags & SMB2_HDR_FLAG_SIGNED)) {
2670 status = NT_STATUS_INVALID_PARAMETER;
2672 status = NT_STATUS_USER_SESSION_DELETED;
2674 return smbd_smb2_request_error(req, status);
2677 signing_key = smbd_smb2_signing_key(x, xconn);
2680 * If we have a signing key, we should
2683 if (smb2_signing_key_valid(signing_key)) {
2684 req->do_signing = true;
2687 status = smb2_signing_check_pdu(signing_key,
2689 SMBD_SMB2_IN_HDR_IOV(req),
2690 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2691 if (!NT_STATUS_IS_OK(status)) {
2692 return smbd_smb2_request_error(req, status);
2696 * Now that we know the request was correctly signed
2697 * we have to sign the response too.
2699 req->do_signing = true;
2701 if (!NT_STATUS_IS_OK(session_status)) {
2702 return smbd_smb2_request_error(req, session_status);
2704 } else if (opcode == SMB2_OP_CANCEL) {
2705 /* Cancel requests are allowed to skip the signing */
2706 } else if (signing_required) {
2708 * If signing is required we try to sign
2709 * a possible error response
2711 req->do_signing = true;
2712 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2715 if (flags & SMB2_HDR_FLAG_CHAINED) {
2716 req->compound_related = true;
2719 if (call->need_session) {
2720 if (!NT_STATUS_IS_OK(session_status)) {
2721 return smbd_smb2_request_error(req, session_status);
2725 if (call->need_tcon) {
2726 SMB_ASSERT(call->need_session);
2729 * This call needs to be run as user.
2731 * smbd_smb2_request_check_tcon()
2732 * calls change_to_user() on success.
2733 * Which implies set_current_user_info()
2734 * and chdir_current_service().
2736 status = smbd_smb2_request_check_tcon(req);
2737 if (!NT_STATUS_IS_OK(status)) {
2738 return smbd_smb2_request_error(req, status);
2740 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
2741 encryption_desired = true;
2743 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
2744 encryption_required = true;
2746 if (encryption_required && !req->was_encrypted) {
2747 req->do_encryption = true;
2748 return smbd_smb2_request_error(req,
2749 NT_STATUS_ACCESS_DENIED);
2750 } else if (encryption_desired) {
2751 req->do_encryption = true;
2753 } else if (call->need_session) {
2754 struct auth_session_info *session_info = NULL;
2757 * Unless we also have need_tcon (see above),
2758 * we still need to call set_current_user_info().
2761 session_info = req->session->global->auth_session_info;
2762 if (session_info == NULL) {
2763 return NT_STATUS_INVALID_HANDLE;
2766 set_current_user_info(session_info->unix_info->sanitized_username,
2767 session_info->unix_info->unix_name,
2768 session_info->info->domain_name);
2772 bool update_session_global = false;
2773 bool update_tcon_global = false;
2775 smb2srv_update_crypto_flags(req, opcode,
2776 &update_session_global,
2777 &update_tcon_global);
2779 if (update_session_global) {
2780 status = smbXsrv_session_update(x);
2781 if (!NT_STATUS_IS_OK(status)) {
2782 return smbd_smb2_request_error(req, status);
2785 if (update_tcon_global) {
2786 status = smbXsrv_tcon_update(req->tcon);
2787 if (!NT_STATUS_IS_OK(status)) {
2788 return smbd_smb2_request_error(req, status);
2793 if (call->fileid_ofs != 0) {
2794 size_t needed = call->fileid_ofs + 16;
2795 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2796 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2797 uint64_t file_id_persistent;
2798 uint64_t file_id_volatile;
2799 struct files_struct *fsp;
2801 SMB_ASSERT(call->need_tcon);
2803 if (needed > body_size) {
2804 return smbd_smb2_request_error(req,
2805 NT_STATUS_INVALID_PARAMETER);
2808 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2809 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2811 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2813 if (!call->allow_invalid_fileid) {
2814 return smbd_smb2_request_error(req,
2815 NT_STATUS_FILE_CLOSED);
2818 if (file_id_persistent != UINT64_MAX) {
2819 return smbd_smb2_request_error(req,
2820 NT_STATUS_FILE_CLOSED);
2822 if (file_id_volatile != UINT64_MAX) {
2823 return smbd_smb2_request_error(req,
2824 NT_STATUS_FILE_CLOSED);
2829 status = smbd_smb2_request_dispatch_update_counts(req, call->modify);
2830 if (!NT_STATUS_IS_OK(status)) {
2831 return smbd_smb2_request_error(req, status);
2834 if (call->as_root) {
2835 SMB_ASSERT(call->fileid_ofs == 0);
2836 /* This call needs to be run as root */
2837 change_to_root_user();
2839 SMB_ASSERT(call->need_tcon);
2842 #define _INBYTES(_r) \
2843 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
2846 case SMB2_OP_NEGPROT:
2847 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
2848 req->profile, _INBYTES(req));
2849 return_value = smbd_smb2_request_process_negprot(req);
2852 case SMB2_OP_SESSSETUP:
2853 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
2854 req->profile, _INBYTES(req));
2855 return_value = smbd_smb2_request_process_sesssetup(req);
2858 case SMB2_OP_LOGOFF:
2859 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
2860 req->profile, _INBYTES(req));
2861 return_value = smbd_smb2_request_process_logoff(req);
2865 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
2866 req->profile, _INBYTES(req));
2867 return_value = smbd_smb2_request_process_tcon(req);
2871 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
2872 req->profile, _INBYTES(req));
2873 return_value = smbd_smb2_request_process_tdis(req);
2876 case SMB2_OP_CREATE:
2877 if (req->subreq == NULL) {
2878 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
2879 req->profile, _INBYTES(req));
2881 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
2883 return_value = smbd_smb2_request_process_create(req);
2887 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
2888 req->profile, _INBYTES(req));
2889 return_value = smbd_smb2_request_process_close(req);
2893 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
2894 req->profile, _INBYTES(req));
2895 return_value = smbd_smb2_request_process_flush(req);
2899 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
2900 req->profile, _INBYTES(req));
2901 return_value = smbd_smb2_request_process_read(req);
2905 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
2906 req->profile, _INBYTES(req));
2907 return_value = smbd_smb2_request_process_write(req);
2911 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
2912 req->profile, _INBYTES(req));
2913 return_value = smbd_smb2_request_process_lock(req);
2917 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
2918 req->profile, _INBYTES(req));
2919 return_value = smbd_smb2_request_process_ioctl(req);
2922 case SMB2_OP_CANCEL:
2923 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
2924 req->profile, _INBYTES(req));
2925 return_value = smbd_smb2_request_process_cancel(req);
2926 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
2929 * We don't need the request anymore cancel requests never
2932 * smbd_smb2_request_process_cancel() already called
2933 * DLIST_REMOVE(xconn->smb2.requests, req);
2939 case SMB2_OP_KEEPALIVE:
2940 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
2941 req->profile, _INBYTES(req));
2942 return_value = smbd_smb2_request_process_keepalive(req);
2945 case SMB2_OP_QUERY_DIRECTORY:
2946 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
2947 req->profile, _INBYTES(req));
2948 return_value = smbd_smb2_request_process_query_directory(req);
2951 case SMB2_OP_NOTIFY:
2952 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
2953 req->profile, _INBYTES(req));
2954 return_value = smbd_smb2_request_process_notify(req);
2957 case SMB2_OP_GETINFO:
2958 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
2959 req->profile, _INBYTES(req));
2960 return_value = smbd_smb2_request_process_getinfo(req);
2963 case SMB2_OP_SETINFO:
2964 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
2965 req->profile, _INBYTES(req));
2966 return_value = smbd_smb2_request_process_setinfo(req);
2970 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
2971 req->profile, _INBYTES(req));
2972 return_value = smbd_smb2_request_process_break(req);
2976 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2979 return return_value;
2982 static void smbd_smb2_request_reply_update_counts(struct smbd_smb2_request *req)
2984 struct smbXsrv_connection *xconn = req->xconn;
2985 const uint8_t *inhdr;
2986 uint16_t channel_sequence;
2987 struct smbXsrv_open *op;
2989 if (!req->request_counters_updated) {
2993 req->request_counters_updated = false;
2995 if (xconn->protocol < PROTOCOL_SMB2_22) {
2999 if (req->compat_chain_fsp == NULL) {
3003 op = req->compat_chain_fsp->op;
3008 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
3009 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
3011 if ((op->global->channel_sequence == channel_sequence) &&
3012 (op->global->channel_generation == req->channel_generation)) {
3013 SMB_ASSERT(op->request_count > 0);
3014 op->request_count -= 1;
3016 SMB_ASSERT(op->pre_request_count > 0);
3017 op->pre_request_count -= 1;
3021 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
3023 struct smbXsrv_connection *xconn = req->xconn;
3025 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
3026 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
3027 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
3032 TALLOC_FREE(req->async_te);
3034 /* MS-SMB2: 3.3.4.1 Sending Any Outgoing Message */
3035 smbd_smb2_request_reply_update_counts(req);
3037 if (req->do_encryption &&
3038 (firsttf->iov_len == 0) &&
3039 (req->first_key.length == 0) &&
3040 (req->session != NULL) &&
3041 smb2_signing_key_valid(req->session->global->encryption_key))
3043 struct smb2_signing_key *encryption_key =
3044 req->session->global->encryption_key;
3046 uint64_t session_id = req->session->global->session_wire_id;
3047 uint64_t nonce_high;
3050 status = smb2_get_new_nonce(req->session,
3053 if (!NT_STATUS_IS_OK(status)) {
3058 * We need to place the SMB2_TRANSFORM header before the
3063 * we need to remember the encryption key
3064 * and defer the signing/encryption until
3065 * we are sure that we do not change
3068 req->first_key = data_blob_dup_talloc(req,
3069 encryption_key->blob);
3070 if (req->first_key.data == NULL) {
3071 return NT_STATUS_NO_MEMORY;
3074 tf = talloc_zero_array(req, uint8_t,
3077 return NT_STATUS_NO_MEMORY;
3080 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
3081 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
3082 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
3083 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
3085 firsttf->iov_base = (void *)tf;
3086 firsttf->iov_len = SMB2_TF_HDR_SIZE;
3089 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
3090 (req->last_key.length > 0) &&
3091 (firsttf->iov_len == 0))
3093 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
3094 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
3095 struct smb2_signing_key key = {
3096 .blob = req->last_key,
3100 * As we are sure the header of the last request in the
3101 * compound chain will not change, we can to sign here
3102 * with the last signing key we remembered.
3104 status = smb2_signing_sign_pdu(&key,
3107 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
3108 smb2_signing_key_destructor(&key);
3109 if (!NT_STATUS_IS_OK(status)) {
3113 if (req->last_key.length > 0) {
3114 data_blob_clear_free(&req->last_key);
3117 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
3118 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
3120 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
3122 if (req->current_idx < req->out.vector_count) {
3124 * We must process the remaining compound
3125 * SMB2 requests before any new incoming SMB2
3126 * requests. This is because incoming SMB2
3127 * requests may include a cancel for a
3128 * compound request we haven't processed
3131 struct tevent_immediate *im = tevent_create_immediate(req);
3133 return NT_STATUS_NO_MEMORY;
3136 if (req->do_signing && firsttf->iov_len == 0) {
3137 struct smbXsrv_session *x = req->session;
3138 struct smb2_signing_key *signing_key =
3139 smbd_smb2_signing_key(x, xconn);
3142 * we need to remember the signing key
3143 * and defer the signing until
3144 * we are sure that we do not change
3147 req->last_key = data_blob_dup_talloc(req,
3149 if (req->last_key.data == NULL) {
3150 return NT_STATUS_NO_MEMORY;
3155 * smbd_smb2_request_dispatch() will redo the impersonation.
3156 * So we use req->xconn->client->raw_ev_ctx instead
3157 * of req->ev_ctx here.
3159 tevent_schedule_immediate(im,
3160 req->xconn->client->raw_ev_ctx,
3161 smbd_smb2_request_dispatch_immediate,
3163 return NT_STATUS_OK;
3166 if (req->compound_related) {
3167 req->compound_related = false;
3170 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
3172 return NT_STATUS_INVALID_PARAMETER_MIX;
3175 /* Set credit for these operations (zero credits if this
3176 is a final reply for an async operation). */
3177 smb2_calculate_credits(req, req);
3180 * now check if we need to sign the current response
3182 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
3183 struct smb2_signing_key key = {
3184 .blob = req->first_key,
3186 status = smb2_signing_encrypt_pdu(&key,
3187 xconn->smb2.server.cipher,
3189 req->out.vector_count - first_idx);
3190 smb2_signing_key_destructor(&key);
3191 if (!NT_STATUS_IS_OK(status)) {
3194 } else if (req->do_signing) {
3195 struct smbXsrv_session *x = req->session;
3196 struct smb2_signing_key *signing_key =
3197 smbd_smb2_signing_key(x, xconn);
3199 status = smb2_signing_sign_pdu(signing_key,
3202 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
3203 if (!NT_STATUS_IS_OK(status)) {
3207 if (req->first_key.length > 0) {
3208 data_blob_clear_free(&req->first_key);
3211 if (req->preauth != NULL) {
3212 gnutls_hash_hd_t hash_hnd = NULL;
3216 rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_SHA512);
3218 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3220 rc = gnutls_hash(hash_hnd,
3221 req->preauth->sha512_value,
3222 sizeof(req->preauth->sha512_value));
3224 gnutls_hash_deinit(hash_hnd, NULL);
3225 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3227 for (i = 1; i < req->in.vector_count; i++) {
3228 rc = gnutls_hash(hash_hnd,
3229 req->in.vector[i].iov_base,
3230 req->in.vector[i].iov_len);
3232 gnutls_hash_deinit(hash_hnd, NULL);
3233 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3237 gnutls_hash_deinit(hash_hnd, NULL);
3238 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3240 gnutls_hash_output(hash_hnd, req->preauth->sha512_value);
3242 rc = gnutls_hash(hash_hnd,
3243 req->preauth->sha512_value,
3244 sizeof(req->preauth->sha512_value));
3246 gnutls_hash_deinit(hash_hnd, NULL);
3247 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3249 for (i = 1; i < req->out.vector_count; i++) {
3250 rc = gnutls_hash(hash_hnd,
3251 req->out.vector[i].iov_base,
3252 req->out.vector[i].iov_len);
3254 gnutls_hash_deinit(hash_hnd, NULL);
3255 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3259 gnutls_hash_deinit(hash_hnd, req->preauth->sha512_value);
3261 req->preauth = NULL;
3264 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
3265 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
3266 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
3267 /* Dynamic part is NULL. Chop it off,
3268 We're going to send it via sendfile. */
3269 req->out.vector_count -= 1;
3273 * We're done with this request -
3274 * move it off the "being processed" queue.
3276 DLIST_REMOVE(xconn->smb2.requests, req);
3278 req->queue_entry.mem_ctx = req;
3279 req->queue_entry.vector = req->out.vector;
3280 req->queue_entry.count = req->out.vector_count;
3281 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry);
3282 xconn->smb2.send_queue_len++;
3284 status = smbd_smb2_flush_send_queue(xconn);
3285 if (!NT_STATUS_IS_OK(status)) {
3289 return NT_STATUS_OK;
3292 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
3294 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
3295 struct tevent_immediate *im,
3298 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
3299 struct smbd_smb2_request);
3300 struct smbXsrv_connection *xconn = req->xconn;
3305 if (DEBUGLEVEL >= 10) {
3306 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
3307 req->current_idx, req->in.vector_count));
3308 print_req_vectors(req);
3311 status = smbd_smb2_request_dispatch(req);
3312 if (!NT_STATUS_IS_OK(status)) {
3313 smbd_server_connection_terminate(xconn, nt_errstr(status));
3317 status = smbd_smb2_request_next_incoming(xconn);
3318 if (!NT_STATUS_IS_OK(status)) {
3319 smbd_server_connection_terminate(xconn, nt_errstr(status));
3324 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
3326 DATA_BLOB body, DATA_BLOB *dyn,
3327 const char *location)
3330 struct iovec *outbody_v;
3331 struct iovec *outdyn_v;
3332 uint32_t next_command_ofs;
3335 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3336 mid = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
3338 DBG_DEBUG("mid [%"PRIu64"] idx[%d] status[%s] "
3339 "body[%u] dyn[%s:%u] at %s\n",
3343 (unsigned int)body.length,
3345 (unsigned int)(dyn ? dyn->length : 0),
3348 if (body.length < 2) {
3349 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3352 if ((body.length % 2) != 0) {
3353 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3356 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
3357 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
3359 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
3360 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
3362 outbody_v->iov_base = (void *)body.data;
3363 outbody_v->iov_len = body.length;
3366 outdyn_v->iov_base = (void *)dyn->data;
3367 outdyn_v->iov_len = dyn->length;
3369 outdyn_v->iov_base = NULL;
3370 outdyn_v->iov_len = 0;
3374 * See if we need to recalculate the offset to the next response
3376 * Note that all responses may require padding (including the very last
3379 if (req->out.vector_count >= (2 * SMBD_SMB2_NUM_IOV_PER_REQ)) {
3380 next_command_ofs = SMB2_HDR_BODY;
3381 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
3382 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
3385 if ((next_command_ofs % 8) != 0) {
3386 size_t pad_size = 8 - (next_command_ofs % 8);
3387 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
3389 * if the dyn buffer is empty
3390 * we can use it to add padding
3394 pad = talloc_zero_array(req,
3397 return smbd_smb2_request_error(req,
3398 NT_STATUS_NO_MEMORY);
3401 outdyn_v->iov_base = (void *)pad;
3402 outdyn_v->iov_len = pad_size;
3405 * For now we copy the dynamic buffer
3406 * and add the padding to the new buffer
3413 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
3414 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
3416 new_size = old_size + pad_size;
3417 new_dyn = talloc_zero_array(req,
3419 if (new_dyn == NULL) {
3420 return smbd_smb2_request_error(req,
3421 NT_STATUS_NO_MEMORY);
3424 memcpy(new_dyn, old_dyn, old_size);
3425 memset(new_dyn + old_size, 0, pad_size);
3427 outdyn_v->iov_base = (void *)new_dyn;
3428 outdyn_v->iov_len = new_size;
3430 next_command_ofs += pad_size;
3433 if ((req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) >= req->out.vector_count) {
3434 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
3436 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
3438 return smbd_smb2_request_reply(req);
3441 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
3444 const char *location)
3446 struct smbXsrv_connection *xconn = req->xconn;
3449 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3450 size_t unread_bytes = smbd_smb2_unread_bytes(req);
3452 DBG_NOTICE("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| "
3453 "at %s\n", req->current_idx, nt_errstr(status),
3454 info ? " +info" : "", location);
3457 /* Recvfile error. Drain incoming socket. */
3461 ret = drain_socket(xconn->transport.sock, unread_bytes);
3462 if (ret != unread_bytes) {
3466 error = NT_STATUS_IO_DEVICE_ERROR;
3468 error = map_nt_error_from_unix_common(errno);
3471 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
3472 "ret[%u] errno[%d] => %s\n",
3473 (unsigned)unread_bytes,
3474 (unsigned)ret, errno, nt_errstr(error)));
3479 body.data = outhdr + SMB2_HDR_BODY;
3481 SSVAL(body.data, 0, 9);
3484 SIVAL(body.data, 0x04, info->length);
3486 /* Allocated size of req->out.vector[i].iov_base
3487 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
3488 * 1 byte without having to do an alloc.
3491 info->data = ((uint8_t *)outhdr) +
3492 OUTVEC_ALLOC_SIZE - 1;
3494 SCVAL(info->data, 0, 0);
3498 * Note: Even if there is an error, continue to process the request.
3502 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
3506 struct smbd_smb2_send_break_state {
3507 struct smbd_smb2_send_queue queue_entry;
3508 uint8_t nbt_hdr[NBT_HDR_SIZE];
3509 uint8_t hdr[SMB2_HDR_BODY];
3510 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
3514 static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
3515 uint64_t session_id,
3516 const uint8_t *body,
3519 struct smbd_smb2_send_break_state *state;
3524 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
3527 state = talloc_zero_size(xconn, statelen);
3528 if (state == NULL) {
3529 return NT_STATUS_NO_MEMORY;
3531 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
3533 SIVAL(state->hdr, 0, SMB2_MAGIC);
3534 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
3535 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
3536 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
3537 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
3538 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
3539 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
3540 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
3541 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
3542 SIVAL(state->hdr, SMB2_HDR_PID, 0);
3543 SIVAL(state->hdr, SMB2_HDR_TID, 0);
3544 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, session_id);
3545 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
3547 state->vector[0] = (struct iovec) {
3548 .iov_base = state->nbt_hdr,
3549 .iov_len = sizeof(state->nbt_hdr)
3552 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3557 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
3558 .iov_base = state->hdr,
3559 .iov_len = sizeof(state->hdr)
3562 memcpy(state->body, body, body_len);
3564 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
3565 .iov_base = state->body,
3566 .iov_len = body_len /* no sizeof(state->body) .. :-) */
3570 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
3573 ok = smb2_setup_nbt_length(state->vector,
3574 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
3576 return NT_STATUS_INVALID_PARAMETER_MIX;
3579 state->queue_entry.mem_ctx = state;
3580 state->queue_entry.vector = state->vector;
3581 state->queue_entry.count = ARRAY_SIZE(state->vector);
3582 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
3583 xconn->smb2.send_queue_len++;
3585 status = smbd_smb2_flush_send_queue(xconn);
3586 if (!NT_STATUS_IS_OK(status)) {
3590 return NT_STATUS_OK;
3593 struct smbXsrv_pending_break {
3594 struct smbXsrv_pending_break *prev, *next;
3595 struct smbXsrv_client *client;
3596 uint64_t session_id;
3599 uint8_t oplock[0x18];
3600 uint8_t lease[0x2c];
3605 static struct smbXsrv_pending_break *smbXsrv_pending_break_create(
3606 struct smbXsrv_client *client,
3607 uint64_t session_id)
3609 struct smbXsrv_pending_break *pb = NULL;
3611 pb = talloc_zero(client, struct smbXsrv_pending_break);
3615 pb->client = client;
3616 pb->session_id = session_id;
3621 static NTSTATUS smbXsrv_pending_break_schedule(struct smbXsrv_pending_break *pb)
3623 struct smbXsrv_connection *xconn = pb->client->connections;
3626 status = smbd_smb2_send_break(xconn,
3636 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_client *client,
3637 struct smbXsrv_open *op,
3638 uint8_t oplock_level)
3640 struct smbXsrv_pending_break *pb = NULL;
3641 uint8_t *body = NULL;
3643 pb = smbXsrv_pending_break_create(client,
3646 return NT_STATUS_NO_MEMORY;
3648 pb->body_len = sizeof(pb->body.oplock);
3649 body = pb->body.oplock;
3651 SSVAL(body, 0x00, pb->body_len);
3652 SCVAL(body, 0x02, oplock_level);
3653 SCVAL(body, 0x03, 0); /* reserved */
3654 SIVAL(body, 0x04, 0); /* reserved */
3655 SBVAL(body, 0x08, op->global->open_persistent_id);
3656 SBVAL(body, 0x10, op->global->open_volatile_id);
3658 return smbXsrv_pending_break_schedule(pb);
3661 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_client *client,
3663 uint32_t lease_flags,
3664 struct smb2_lease_key *lease_key,
3665 uint32_t current_lease_state,
3666 uint32_t new_lease_state)
3668 struct smbXsrv_pending_break *pb = NULL;
3669 uint8_t *body = NULL;
3671 pb = smbXsrv_pending_break_create(client,
3672 0); /* no session_id */
3674 return NT_STATUS_NO_MEMORY;
3676 pb->body_len = sizeof(pb->body.lease);
3677 body = pb->body.lease;
3679 SSVAL(body, 0x00, pb->body_len);
3680 SSVAL(body, 0x02, new_epoch);
3681 SIVAL(body, 0x04, lease_flags);
3682 SBVAL(body, 0x08, lease_key->data[0]);
3683 SBVAL(body, 0x10, lease_key->data[1]);
3684 SIVAL(body, 0x18, current_lease_state);
3685 SIVAL(body, 0x1c, new_lease_state);
3686 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
3687 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
3688 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
3690 return smbXsrv_pending_break_schedule(pb);
3693 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
3697 uint64_t file_id_persistent;
3698 uint64_t file_id_volatile;
3699 struct smbXsrv_open *op = NULL;
3700 struct files_struct *fsp = NULL;
3701 const uint8_t *body = NULL;
3704 * This is only called with a pktbuf
3705 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
3709 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
3710 /* Transform header. Cannot recvfile. */
3713 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
3714 /* Not SMB2. Normal error path will cope. */
3717 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
3718 /* Not SMB2. Normal error path will cope. */
3721 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
3722 /* Needs to be a WRITE. */
3725 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
3726 /* Chained. Cannot recvfile. */
3729 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
3730 if (flags & SMB2_HDR_FLAG_CHAINED) {
3731 /* Chained. Cannot recvfile. */
3734 if (flags & SMB2_HDR_FLAG_SIGNED) {
3735 /* Signed. Cannot recvfile. */
3739 body = &state->pktbuf[SMB2_HDR_BODY];
3741 file_id_persistent = BVAL(body, 0x10);
3742 file_id_volatile = BVAL(body, 0x18);
3744 status = smb2srv_open_lookup(state->req->xconn,
3749 if (!NT_STATUS_IS_OK(status)) {
3757 if (fsp->conn == NULL) {
3761 if (IS_IPC(fsp->conn)) {
3764 if (IS_PRINT(fsp->conn)) {
3767 if (fsp->base_fsp != NULL) {
3771 DEBUG(10,("Doing recvfile write len = %u\n",
3772 (unsigned int)(state->pktfull - state->pktlen)));
3777 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
3779 struct smbd_server_connection *sconn = xconn->client->sconn;
3780 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3781 size_t max_send_queue_len;
3782 size_t cur_send_queue_len;
3784 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3786 * we're not supposed to do any io
3788 return NT_STATUS_OK;
3791 if (state->req != NULL) {
3793 * if there is already a tstream_readv_pdu
3794 * pending, we are done.
3796 return NT_STATUS_OK;
3799 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
3800 cur_send_queue_len = xconn->smb2.send_queue_len;
3802 if (cur_send_queue_len > max_send_queue_len) {
3804 * if we have a lot of requests to send,
3805 * we wait until they are on the wire until we
3806 * ask for the next request.
3808 return NT_STATUS_OK;
3811 /* ask for the next request */
3812 ZERO_STRUCTP(state);
3813 state->req = smbd_smb2_request_allocate(xconn);
3814 if (state->req == NULL) {
3815 return NT_STATUS_NO_MEMORY;
3817 state->req->sconn = sconn;
3818 state->req->xconn = xconn;
3819 state->min_recv_size = lp_min_receive_file_size();
3821 TEVENT_FD_READABLE(xconn->transport.fde);
3823 return NT_STATUS_OK;
3826 NTSTATUS smbd_smb2_process_negprot(struct smbXsrv_connection *xconn,
3827 uint64_t expected_seq_low,
3828 const uint8_t *inpdu, size_t size)
3830 struct smbd_server_connection *sconn = xconn->client->sconn;
3832 struct smbd_smb2_request *req = NULL;
3834 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3835 (unsigned int)size));
3837 status = smbd_initialize_smb2(xconn, expected_seq_low);
3838 if (!NT_STATUS_IS_OK(status)) {
3839 smbd_server_connection_terminate(xconn, nt_errstr(status));
3843 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
3844 if (!NT_STATUS_IS_OK(status)) {
3845 smbd_server_connection_terminate(xconn, nt_errstr(status));
3849 status = smbd_smb2_request_validate(req);
3850 if (!NT_STATUS_IS_OK(status)) {
3851 smbd_server_connection_terminate(xconn, nt_errstr(status));
3855 status = smbd_smb2_request_setup_out(req);
3856 if (!NT_STATUS_IS_OK(status)) {
3857 smbd_server_connection_terminate(xconn, nt_errstr(status));
3863 * this was already counted at the SMB1 layer =>
3864 * smbd_smb2_request_dispatch() should not count it twice.
3866 if (profile_p->values.request_stats.count > 0) {
3867 profile_p->values.request_stats.count--;
3870 status = smbd_smb2_request_dispatch(req);
3871 if (!NT_STATUS_IS_OK(status)) {
3872 smbd_server_connection_terminate(xconn, nt_errstr(status));
3876 status = smbd_smb2_request_next_incoming(xconn);
3877 if (!NT_STATUS_IS_OK(status)) {
3878 smbd_server_connection_terminate(xconn, nt_errstr(status));
3882 sconn->num_requests++;
3883 return NT_STATUS_OK;
3886 static int socket_error_from_errno(int ret,
3900 if (sys_errno == 0) {
3904 if (sys_errno == EINTR) {
3909 if (sys_errno == EINPROGRESS) {
3914 if (sys_errno == EAGAIN) {
3919 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3920 if (sys_errno == ENOMEM) {
3926 #if EWOULDBLOCK != EAGAIN
3927 if (sys_errno == EWOULDBLOCK) {
3937 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3944 if (xconn->smb2.send_queue == NULL) {
3945 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3946 return NT_STATUS_OK;
3949 while (xconn->smb2.send_queue != NULL) {
3950 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3954 if (e->sendfile_header != NULL) {
3959 status = NT_STATUS_INTERNAL_ERROR;
3961 for (i=0; i < e->count; i++) {
3962 size += e->vector[i].iov_len;
3965 if (size <= e->sendfile_header->length) {
3966 buf = e->sendfile_header->data;
3968 buf = talloc_array(e->mem_ctx, uint8_t, size);
3970 return NT_STATUS_NO_MEMORY;
3975 for (i=0; i < e->count; i++) {
3977 e->vector[i].iov_base,
3978 e->vector[i].iov_len);
3979 size += e->vector[i].iov_len;
3982 e->sendfile_header->data = buf;
3983 e->sendfile_header->length = size;
3984 e->sendfile_status = &status;
3987 xconn->smb2.send_queue_len--;
3988 DLIST_REMOVE(xconn->smb2.send_queue, e);
3990 * This triggers the sendfile path via
3993 talloc_free(e->mem_ctx);
3995 if (!NT_STATUS_IS_OK(status)) {
3996 smbXsrv_connection_disconnect_transport(xconn,
4003 msg = (struct msghdr) {
4004 .msg_iov = e->vector,
4005 .msg_iovlen = e->count,
4008 ret = sendmsg(xconn->transport.sock, &msg, 0);
4010 /* propagate end of file */
4011 return NT_STATUS_INTERNAL_ERROR;
4013 err = socket_error_from_errno(ret, errno, &retry);
4016 TEVENT_FD_WRITEABLE(xconn->transport.fde);
4017 return NT_STATUS_OK;
4020 status = map_nt_error_from_unix_common(err);
4021 smbXsrv_connection_disconnect_transport(xconn,
4026 ok = iov_advance(&e->vector, &e->count, ret);
4028 return NT_STATUS_INTERNAL_ERROR;
4032 /* we have more to write */
4033 TEVENT_FD_WRITEABLE(xconn->transport.fde);
4034 return NT_STATUS_OK;
4037 xconn->smb2.send_queue_len--;
4038 DLIST_REMOVE(xconn->smb2.send_queue, e);
4039 talloc_free(e->mem_ctx);
4043 * Restart reads if we were blocked on
4044 * draining the send queue.
4047 status = smbd_smb2_request_next_incoming(xconn);
4048 if (!NT_STATUS_IS_OK(status)) {
4052 return NT_STATUS_OK;
4055 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
4058 struct smbd_server_connection *sconn = xconn->client->sconn;
4059 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
4060 struct smbd_smb2_request *req = NULL;
4061 size_t min_recvfile_size = UINT32_MAX;
4069 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
4071 * we're not supposed to do any io
4073 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
4074 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
4075 return NT_STATUS_OK;
4078 if (fde_flags & TEVENT_FD_WRITE) {
4079 status = smbd_smb2_flush_send_queue(xconn);
4080 if (!NT_STATUS_IS_OK(status)) {
4085 if (!(fde_flags & TEVENT_FD_READ)) {
4086 return NT_STATUS_OK;
4089 if (state->req == NULL) {
4090 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
4091 return NT_STATUS_OK;
4095 if (!state->hdr.done) {
4096 state->hdr.done = true;
4098 state->vector.iov_base = (void *)state->hdr.nbt;
4099 state->vector.iov_len = NBT_HDR_SIZE;
4102 msg = (struct msghdr) {
4103 .msg_iov = &state->vector,
4107 ret = recvmsg(xconn->transport.sock, &msg, 0);
4109 /* propagate end of file */
4110 status = NT_STATUS_END_OF_FILE;
4111 smbXsrv_connection_disconnect_transport(xconn,
4115 err = socket_error_from_errno(ret, errno, &retry);
4118 TEVENT_FD_READABLE(xconn->transport.fde);
4119 return NT_STATUS_OK;
4122 status = map_nt_error_from_unix_common(err);
4123 smbXsrv_connection_disconnect_transport(xconn,
4128 if (ret < state->vector.iov_len) {
4130 base = (uint8_t *)state->vector.iov_base;
4132 state->vector.iov_base = (void *)base;
4133 state->vector.iov_len -= ret;
4134 /* we have more to read */
4135 TEVENT_FD_READABLE(xconn->transport.fde);
4136 return NT_STATUS_OK;
4139 if (state->pktlen > 0) {
4140 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
4142 * Not a possible receivefile write.
4143 * Read the rest of the data.
4145 state->doing_receivefile = false;
4147 state->pktbuf = talloc_realloc(state->req,
4151 if (state->pktbuf == NULL) {
4152 return NT_STATUS_NO_MEMORY;
4155 state->vector.iov_base = (void *)(state->pktbuf +
4157 state->vector.iov_len = (state->pktfull -
4160 state->pktlen = state->pktfull;
4165 * Either this is a receivefile write so we've
4166 * done a short read, or if not we have all the data.
4172 * Now we analyze the NBT header
4174 if (state->hdr.nbt[0] != 0x00) {
4175 state->min_recv_size = 0;
4177 state->pktfull = smb2_len(state->hdr.nbt);
4178 if (state->pktfull == 0) {
4182 if (state->min_recv_size != 0) {
4183 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
4184 min_recvfile_size += state->min_recv_size;
4187 if (state->pktfull > min_recvfile_size) {
4189 * Might be a receivefile write. Read the SMB2 HEADER +
4190 * SMB2_WRITE header first. Set 'doing_receivefile'
4191 * as we're *attempting* receivefile write. If this
4192 * turns out not to be a SMB2_WRITE request or otherwise
4193 * not suitable then we'll just read the rest of the data
4194 * the next time this function is called.
4196 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
4197 state->doing_receivefile = true;
4199 state->pktlen = state->pktfull;
4202 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
4203 if (state->pktbuf == NULL) {
4204 return NT_STATUS_NO_MEMORY;
4207 state->vector.iov_base = (void *)state->pktbuf;
4208 state->vector.iov_len = state->pktlen;
4214 if (state->hdr.nbt[0] != 0x00) {
4215 DEBUG(1,("ignore NBT[0x%02X] msg\n",
4216 state->hdr.nbt[0]));
4219 ZERO_STRUCTP(state);
4221 state->min_recv_size = lp_min_receive_file_size();
4229 req->request_time = timeval_current();
4230 now = timeval_to_nttime(&req->request_time);
4232 status = smbd_smb2_inbuf_parse_compound(xconn,
4238 &req->in.vector_count);
4239 if (!NT_STATUS_IS_OK(status)) {
4243 if (state->doing_receivefile) {
4244 req->smb1req = talloc_zero(req, struct smb_request);
4245 if (req->smb1req == NULL) {
4246 return NT_STATUS_NO_MEMORY;
4248 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
4251 ZERO_STRUCTP(state);
4253 req->current_idx = 1;
4255 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
4256 req->current_idx, req->in.vector_count));
4258 status = smbd_smb2_request_validate(req);
4259 if (!NT_STATUS_IS_OK(status)) {
4263 status = smbd_smb2_request_setup_out(req);
4264 if (!NT_STATUS_IS_OK(status)) {
4268 status = smbd_smb2_request_dispatch(req);
4269 if (!NT_STATUS_IS_OK(status)) {
4273 sconn->num_requests++;
4275 /* The timeout_processing function isn't run nearly
4276 often enough to implement 'max log size' without
4277 overrunning the size of the file by many megabytes.
4278 This is especially true if we are running at debug
4279 level 10. Checking every 50 SMB2s is a nice
4280 tradeoff of performance vs log file size overrun. */
4282 if ((sconn->num_requests % 50) == 0 &&
4283 need_to_check_log_size()) {
4284 change_to_root_user();
4288 status = smbd_smb2_request_next_incoming(xconn);
4289 if (!NT_STATUS_IS_OK(status)) {
4293 return NT_STATUS_OK;
4296 static void smbd_smb2_connection_handler(struct tevent_context *ev,
4297 struct tevent_fd *fde,
4301 struct smbXsrv_connection *xconn =
4302 talloc_get_type_abort(private_data,
4303 struct smbXsrv_connection);
4306 status = smbd_smb2_io_handler(xconn, flags);
4307 if (!NT_STATUS_IS_OK(status)) {
4308 smbd_server_connection_terminate(xconn, nt_errstr(status));