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 smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
1111 const char *location)
1113 struct smbXsrv_client *client = xconn->client;
1115 DEBUG(10,("smbd_server_connection_terminate_ex: conn[%s] reason[%s] at %s\n",
1116 smbXsrv_connection_dbg(xconn), reason, location));
1118 if (client->connections->next != NULL) {
1119 /* TODO: cancel pending requests */
1120 DLIST_REMOVE(client->connections, xconn);
1122 DO_PROFILE_INC(disconnect);
1127 * The last connection was disconnected
1129 exit_server_cleanly(reason);
1132 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1133 struct iovec *outvec,
1134 const struct iovec *srcvec)
1136 const uint8_t *srctf;
1138 const uint8_t *srchdr;
1140 const uint8_t *srcbody;
1142 const uint8_t *expected_srcbody;
1143 const uint8_t *srcdyn;
1145 const uint8_t *expected_srcdyn;
1151 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1152 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1153 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1154 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1155 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1156 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1157 expected_srcbody = srchdr + SMB2_HDR_BODY;
1158 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1159 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1160 expected_srcdyn = srcbody + 8;
1162 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1166 if (srchdr_len != SMB2_HDR_BODY) {
1170 if (srctf_len == SMB2_TF_HDR_SIZE) {
1171 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1172 if (dsttf == NULL) {
1178 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1179 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1181 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1182 * be allocated with size OUTVEC_ALLOC_SIZE. */
1184 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1185 if (dsthdr == NULL) {
1188 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1189 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1192 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1193 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1194 * then duplicate this. Else use talloc_memdup().
1197 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1198 dstbody = dsthdr + SMB2_HDR_BODY;
1200 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1201 if (dstbody == NULL) {
1205 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1206 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1209 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1211 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1212 * then duplicate this. Else use talloc_memdup().
1215 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1216 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1217 } else if (srcdyn == NULL) {
1220 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1221 if (dstdyn == NULL) {
1225 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1226 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1231 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1233 struct smbd_smb2_request *newreq = NULL;
1234 struct iovec *outvec = NULL;
1235 int count = req->out.vector_count;
1239 newreq = smbd_smb2_request_allocate(req->xconn);
1244 newreq->sconn = req->sconn;
1245 newreq->xconn = req->xconn;
1246 newreq->session = req->session;
1247 newreq->do_encryption = req->do_encryption;
1248 newreq->do_signing = req->do_signing;
1249 newreq->current_idx = req->current_idx;
1251 outvec = talloc_zero_array(newreq, struct iovec, count);
1253 TALLOC_FREE(newreq);
1256 newreq->out.vector = outvec;
1257 newreq->out.vector_count = count;
1259 /* Setup the outvec's identically to req. */
1260 outvec[0].iov_base = newreq->out.nbt_hdr;
1261 outvec[0].iov_len = 4;
1262 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1264 /* Setup the vectors identically to the ones in req. */
1265 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1266 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1273 TALLOC_FREE(newreq);
1277 ok = smb2_setup_nbt_length(newreq->out.vector,
1278 newreq->out.vector_count);
1280 TALLOC_FREE(newreq);
1287 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1289 struct smbXsrv_connection *xconn = req->xconn;
1291 struct iovec *firsttf = NULL;
1292 struct iovec *outhdr_v = NULL;
1293 uint8_t *outhdr = NULL;
1294 struct smbd_smb2_request *nreq = NULL;
1298 /* Create a new smb2 request we'll use
1299 for the interim return. */
1300 nreq = dup_smb2_req(req);
1302 return NT_STATUS_NO_MEMORY;
1305 /* Lose the last X out vectors. They're the
1306 ones we'll be using for the async reply. */
1307 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1309 ok = smb2_setup_nbt_length(nreq->out.vector,
1310 nreq->out.vector_count);
1312 return NT_STATUS_INVALID_PARAMETER_MIX;
1315 /* Step back to the previous reply. */
1316 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1317 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1318 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1319 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1320 /* And end the chain. */
1321 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1323 /* Calculate outgoing credits */
1324 smb2_calculate_credits(req, nreq);
1326 if (DEBUGLEVEL >= 10) {
1327 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1328 (unsigned int)nreq->current_idx );
1329 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1330 (unsigned int)nreq->out.vector_count );
1331 print_req_vectors(nreq);
1335 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1336 * we need to sign/encrypt here with the last/first key we remembered
1338 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1339 struct smb2_signing_key key = {
1340 .blob = req->first_key,
1342 status = smb2_signing_encrypt_pdu(&key,
1343 xconn->smb2.server.cipher,
1345 nreq->out.vector_count - first_idx);
1346 smb2_signing_key_destructor(&key);
1347 if (!NT_STATUS_IS_OK(status)) {
1350 } else if (req->last_key.length > 0) {
1351 struct smb2_signing_key key = {
1352 .blob = req->last_key,
1355 status = smb2_signing_sign_pdu(&key,
1358 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1359 smb2_signing_key_destructor(&key);
1360 if (!NT_STATUS_IS_OK(status)) {
1365 nreq->queue_entry.mem_ctx = nreq;
1366 nreq->queue_entry.vector = nreq->out.vector;
1367 nreq->queue_entry.count = nreq->out.vector_count;
1368 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry);
1369 xconn->smb2.send_queue_len++;
1371 status = smbd_smb2_flush_send_queue(xconn);
1372 if (!NT_STATUS_IS_OK(status)) {
1376 return NT_STATUS_OK;
1379 struct smbd_smb2_request_pending_state {
1380 struct smbd_smb2_send_queue queue_entry;
1381 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1382 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1385 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1386 struct tevent_timer *te,
1387 struct timeval current_time,
1388 void *private_data);
1390 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1391 struct tevent_req *subreq,
1392 uint32_t defer_time)
1395 struct timeval defer_endtime;
1396 uint8_t *outhdr = NULL;
1399 if (!tevent_req_is_in_progress(subreq)) {
1401 * This is a performance optimization,
1402 * it avoids one tevent_loop iteration,
1403 * which means we avoid one
1404 * talloc_stackframe_pool/talloc_free pair.
1406 tevent_req_notify_callback(subreq);
1407 return NT_STATUS_OK;
1410 req->subreq = subreq;
1413 if (req->async_te) {
1414 /* We're already async. */
1415 return NT_STATUS_OK;
1418 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1419 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1420 if (flags & SMB2_HDR_FLAG_ASYNC) {
1421 /* We're already async. */
1422 return NT_STATUS_OK;
1425 if (req->async_internal || defer_time == 0) {
1427 * An SMB2 request implementation wants to handle the request
1428 * asynchronously "internally" while keeping synchronous
1429 * behaviour for the SMB2 request. This means we don't send an
1430 * interim response and we can allow processing of compound SMB2
1431 * requests (cf the subsequent check) for all cases.
1433 return NT_STATUS_OK;
1436 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1438 * We're trying to go async in a compound request
1439 * chain. This is only allowed for opens that cause an
1440 * oplock break or for the last operation in the
1441 * chain, otherwise it is not allowed. See
1442 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
1444 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1446 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1448 * Cancel the outstanding request.
1450 bool ok = tevent_req_cancel(req->subreq);
1452 return NT_STATUS_OK;
1454 TALLOC_FREE(req->subreq);
1455 return smbd_smb2_request_error(req,
1456 NT_STATUS_INTERNAL_ERROR);
1460 if (DEBUGLEVEL >= 10) {
1461 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1462 (unsigned int)req->current_idx );
1463 print_req_vectors(req);
1466 if (req->current_idx > 1) {
1468 * We're going async in a compound
1469 * chain after the first request has
1470 * already been processed. Send an
1471 * interim response containing the
1472 * set of replies already generated.
1474 int idx = req->current_idx;
1476 status = smb2_send_async_interim_response(req);
1477 if (!NT_STATUS_IS_OK(status)) {
1480 if (req->first_key.length > 0) {
1481 data_blob_clear_free(&req->first_key);
1484 req->current_idx = 1;
1487 * Re-arrange the in.vectors to remove what
1490 memmove(&req->in.vector[1],
1491 &req->in.vector[idx],
1492 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1493 req->in.vector_count = 1 + (req->in.vector_count - idx);
1495 /* Re-arrange the out.vectors to match. */
1496 memmove(&req->out.vector[1],
1497 &req->out.vector[idx],
1498 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1499 req->out.vector_count = 1 + (req->out.vector_count - idx);
1501 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1503 * We only have one remaining request as
1504 * we've processed everything else.
1505 * This is no longer a compound request.
1507 req->compound_related = false;
1508 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1509 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1510 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1513 if (req->last_key.length > 0) {
1514 data_blob_clear_free(&req->last_key);
1518 * smbd_smb2_request_pending_timer() just send a packet
1519 * to the client and doesn't need any impersonation.
1520 * So we use req->xconn->client->raw_ev_ctx instead
1521 * of req->ev_ctx here.
1523 defer_endtime = timeval_current_ofs_usec(defer_time);
1524 req->async_te = tevent_add_timer(req->xconn->client->raw_ev_ctx,
1526 smbd_smb2_request_pending_timer,
1528 if (req->async_te == NULL) {
1529 return NT_STATUS_NO_MEMORY;
1532 return NT_STATUS_OK;
1536 struct smb2_signing_key *smbd_smb2_signing_key(struct smbXsrv_session *session,
1537 struct smbXsrv_connection *xconn)
1539 struct smbXsrv_channel_global0 *c = NULL;
1541 struct smb2_signing_key *key = NULL;
1543 status = smbXsrv_session_find_channel(session, xconn, &c);
1544 if (NT_STATUS_IS_OK(status)) {
1545 key = c->signing_key;
1548 if (!smb2_signing_key_valid(key)) {
1549 key = session->global->signing_key;
1555 static NTSTATUS smb2_get_new_nonce(struct smbXsrv_session *session,
1556 uint64_t *new_nonce_high,
1557 uint64_t *new_nonce_low)
1559 uint64_t nonce_high;
1562 session->nonce_low += 1;
1563 if (session->nonce_low == 0) {
1564 session->nonce_low += 1;
1565 session->nonce_high += 1;
1569 * CCM and GCM algorithms must never have their
1570 * nonce wrap, or the security of the whole
1571 * communication and the keys is destroyed.
1572 * We must drop the connection once we have
1573 * transfered too much data.
1575 * NOTE: We assume nonces greater than 8 bytes.
1577 if (session->nonce_high >= session->nonce_high_max) {
1578 return NT_STATUS_ENCRYPTION_FAILED;
1581 nonce_high = session->nonce_high_random;
1582 nonce_high += session->nonce_high;
1583 nonce_low = session->nonce_low;
1585 *new_nonce_high = nonce_high;
1586 *new_nonce_low = nonce_low;
1587 return NT_STATUS_OK;
1590 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1591 struct tevent_timer *te,
1592 struct timeval current_time,
1595 struct smbd_smb2_request *req =
1596 talloc_get_type_abort(private_data,
1597 struct smbd_smb2_request);
1598 struct smbXsrv_connection *xconn = req->xconn;
1599 struct smbd_smb2_request_pending_state *state = NULL;
1600 uint8_t *outhdr = NULL;
1601 const uint8_t *inhdr = NULL;
1603 uint8_t *hdr = NULL;
1604 uint8_t *body = NULL;
1605 uint8_t *dyn = NULL;
1607 uint64_t message_id = 0;
1608 uint64_t async_id = 0;
1612 TALLOC_FREE(req->async_te);
1614 /* Ensure our final reply matches the interim one. */
1615 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1616 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1617 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1618 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1620 async_id = message_id; /* keep it simple for now... */
1622 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1623 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1625 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1627 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1628 (unsigned long long)async_id ));
1631 * What we send is identical to a smbd_smb2_request_error
1632 * packet with an error status of STATUS_PENDING. Make use
1633 * of this fact sometime when refactoring. JRA.
1636 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
1637 if (state == NULL) {
1638 smbd_server_connection_terminate(xconn,
1639 nt_errstr(NT_STATUS_NO_MEMORY));
1643 tf = state->buf + NBT_HDR_SIZE;
1645 hdr = tf + SMB2_TF_HDR_SIZE;
1646 body = hdr + SMB2_HDR_BODY;
1649 if (req->do_encryption) {
1650 uint64_t nonce_high = 0;
1651 uint64_t nonce_low = 0;
1652 uint64_t session_id = req->session->global->session_wire_id;
1654 status = smb2_get_new_nonce(req->session,
1657 if (!NT_STATUS_IS_OK(status)) {
1658 smbd_server_connection_terminate(xconn,
1663 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1664 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1665 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1666 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1669 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1670 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1671 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1672 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1673 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1675 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1676 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1677 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1678 SBVAL(hdr, SMB2_HDR_PID, async_id);
1679 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1680 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1681 memcpy(hdr+SMB2_HDR_SIGNATURE,
1682 outhdr+SMB2_HDR_SIGNATURE, 16);
1684 SSVAL(body, 0x00, 0x08 + 1);
1686 SCVAL(body, 0x02, 0);
1687 SCVAL(body, 0x03, 0);
1688 SIVAL(body, 0x04, 0);
1689 /* Match W2K8R2... */
1690 SCVAL(dyn, 0x00, 0x21);
1692 state->vector[0].iov_base = (void *)state->buf;
1693 state->vector[0].iov_len = NBT_HDR_SIZE;
1695 if (req->do_encryption) {
1696 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1697 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len =
1700 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1701 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1704 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1705 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1707 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1708 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1710 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1711 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1713 ok = smb2_setup_nbt_length(state->vector,
1714 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1716 smbd_server_connection_terminate(
1717 xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
1721 /* Ensure we correctly go through crediting. Grant
1722 the credits now, and zero credits on the final
1724 smb2_set_operation_credit(req->xconn,
1725 SMBD_SMB2_IN_HDR_IOV(req),
1726 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1728 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1733 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1734 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1736 (unsigned int)ARRAY_SIZE(state->vector),
1737 (unsigned int)state->vector[i].iov_len);
1741 if (req->do_encryption) {
1742 struct smbXsrv_session *x = req->session;
1743 struct smb2_signing_key *encryption_key = x->global->encryption_key;
1745 status = smb2_signing_encrypt_pdu(encryption_key,
1746 xconn->smb2.server.cipher,
1747 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1748 SMBD_SMB2_NUM_IOV_PER_REQ);
1749 if (!NT_STATUS_IS_OK(status)) {
1750 smbd_server_connection_terminate(xconn,
1754 } else if (req->do_signing) {
1755 struct smbXsrv_session *x = req->session;
1756 struct smb2_signing_key *signing_key =
1757 smbd_smb2_signing_key(x, xconn);
1759 status = smb2_signing_sign_pdu(signing_key,
1761 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1762 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1763 if (!NT_STATUS_IS_OK(status)) {
1764 smbd_server_connection_terminate(xconn,
1770 state->queue_entry.mem_ctx = state;
1771 state->queue_entry.vector = state->vector;
1772 state->queue_entry.count = ARRAY_SIZE(state->vector);
1773 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
1774 xconn->smb2.send_queue_len++;
1776 status = smbd_smb2_flush_send_queue(xconn);
1777 if (!NT_STATUS_IS_OK(status)) {
1778 smbd_server_connection_terminate(xconn,
1784 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1786 struct smbXsrv_connection *xconn = req->xconn;
1787 struct smbd_smb2_request *cur;
1788 const uint8_t *inhdr;
1790 uint64_t search_message_id;
1791 uint64_t search_async_id;
1794 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1796 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1797 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1798 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1801 * We don't need the request anymore cancel requests never
1804 * We defer the TALLOC_FREE(req) to the caller.
1806 DLIST_REMOVE(xconn->smb2.requests, req);
1808 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1809 const uint8_t *outhdr;
1810 uint64_t message_id;
1813 if (cur->compound_related) {
1815 * Never cancel anything in a compound request.
1816 * Way too hard to deal with the result.
1821 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1823 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1824 async_id = BVAL(outhdr, SMB2_HDR_PID);
1826 if (flags & SMB2_HDR_FLAG_ASYNC) {
1827 if (search_async_id == async_id) {
1828 found_id = async_id;
1832 if (search_message_id == message_id) {
1833 found_id = message_id;
1839 if (cur && cur->subreq) {
1840 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1841 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1842 "cancel opcode[%s] mid %llu\n",
1843 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1844 (unsigned long long)found_id ));
1845 tevent_req_cancel(cur->subreq);
1848 return NT_STATUS_OK;
1851 /*************************************************************
1852 Ensure an incoming tid is a valid one for us to access.
1853 Change to the associated uid credentials and chdir to the
1854 valid tid directory.
1855 *************************************************************/
1857 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1859 const uint8_t *inhdr;
1862 struct smbXsrv_tcon *tcon;
1864 NTTIME now = timeval_to_nttime(&req->request_time);
1868 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1870 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1871 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1873 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1874 in_tid = req->last_tid;
1879 status = smb2srv_tcon_lookup(req->session,
1880 in_tid, now, &tcon);
1881 if (!NT_STATUS_IS_OK(status)) {
1885 if (!change_to_user_and_service(
1887 req->session->global->session_wire_id))
1889 return NT_STATUS_ACCESS_DENIED;
1893 req->last_tid = in_tid;
1895 return NT_STATUS_OK;
1898 /*************************************************************
1899 Ensure an incoming session_id is a valid one for us to access.
1900 *************************************************************/
1902 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1904 const uint8_t *inhdr;
1907 uint64_t in_session_id;
1908 struct smbXsrv_session *session = NULL;
1909 struct auth_session_info *session_info;
1911 NTTIME now = timeval_to_nttime(&req->request_time);
1913 req->session = NULL;
1916 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1918 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1919 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1920 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1922 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1923 in_session_id = req->last_session_id;
1926 req->last_session_id = 0;
1928 /* look an existing session up */
1929 switch (in_opcode) {
1930 case SMB2_OP_SESSSETUP:
1932 * For a session bind request, we don't have the
1933 * channel set up at this point yet, so we defer
1934 * the verification that the connection belongs
1935 * to the session to the session setup code, which
1936 * can look at the session binding flags.
1938 status = smb2srv_session_lookup_client(req->xconn->client,
1943 status = smb2srv_session_lookup_conn(req->xconn,
1949 req->session = session;
1950 req->last_session_id = in_session_id;
1952 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1953 switch (in_opcode) {
1954 case SMB2_OP_SESSSETUP:
1955 status = NT_STATUS_OK;
1957 case SMB2_OP_LOGOFF:
1960 case SMB2_OP_CANCEL:
1961 case SMB2_OP_KEEPALIVE:
1963 * [MS-SMB2] 3.3.5.2.9 Verifying the Session
1964 * specifies that LOGOFF, CLOSE and (UN)LOCK
1965 * should always be processed even on expired sessions.
1967 * Also see the logic in
1968 * smbd_smb2_request_process_lock().
1970 * The smb2.session.expire2 test shows that
1971 * CANCEL and KEEPALIVE/ECHO should also
1974 status = NT_STATUS_OK;
1980 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1981 switch (in_opcode) {
1983 case SMB2_OP_CREATE:
1984 case SMB2_OP_GETINFO:
1985 case SMB2_OP_SETINFO:
1986 return NT_STATUS_INVALID_HANDLE;
1989 * Notice the check for
1990 * (session_info == NULL)
1993 status = NT_STATUS_OK;
1997 if (!NT_STATUS_IS_OK(status)) {
2001 session_info = session->global->auth_session_info;
2002 if (session_info == NULL) {
2003 return NT_STATUS_INVALID_HANDLE;
2006 return NT_STATUS_OK;
2009 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
2010 uint32_t data_length)
2012 struct smbXsrv_connection *xconn = req->xconn;
2013 uint16_t needed_charge;
2014 uint16_t credit_charge = 1;
2015 const uint8_t *inhdr;
2017 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2019 if (xconn->smb2.credits.multicredit) {
2020 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
2021 credit_charge = MAX(credit_charge, 1);
2024 needed_charge = (data_length - 1)/ 65536 + 1;
2026 DBGC_DEBUG(DBGC_SMB2_CREDITS,
2027 "mid %llu, CreditCharge: %d, NeededCharge: %d\n",
2028 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
2029 credit_charge, needed_charge);
2031 if (needed_charge > credit_charge) {
2032 DBGC_WARNING(DBGC_SMB2_CREDITS,
2033 "CreditCharge too low, given %d, needed %d\n",
2034 credit_charge, needed_charge);
2035 return NT_STATUS_INVALID_PARAMETER;
2038 return NT_STATUS_OK;
2041 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
2042 size_t expected_body_size)
2044 struct iovec *inhdr_v;
2045 const uint8_t *inhdr;
2047 const uint8_t *inbody;
2049 size_t min_dyn_size = expected_body_size & 0x00000001;
2050 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
2053 * The following should be checked already.
2055 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
2056 return NT_STATUS_INTERNAL_ERROR;
2058 if (req->current_idx > max_idx) {
2059 return NT_STATUS_INTERNAL_ERROR;
2062 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
2063 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
2064 return NT_STATUS_INTERNAL_ERROR;
2066 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
2067 return NT_STATUS_INTERNAL_ERROR;
2070 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2071 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2075 case SMB2_OP_GETINFO:
2079 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
2080 if (req->smb1req->unread_bytes < min_dyn_size) {
2081 return NT_STATUS_INVALID_PARAMETER;
2090 * Now check the expected body size,
2091 * where the last byte might be in the
2094 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
2095 return NT_STATUS_INVALID_PARAMETER;
2097 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
2098 return NT_STATUS_INVALID_PARAMETER;
2101 inbody = SMBD_SMB2_IN_BODY_PTR(req);
2103 body_size = SVAL(inbody, 0x00);
2104 if (body_size != expected_body_size) {
2105 return NT_STATUS_INVALID_PARAMETER;
2108 return NT_STATUS_OK;
2111 bool smbXsrv_is_encrypted(uint8_t encryption_flags)
2113 return (!(encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)
2115 (encryption_flags & (SMBXSRV_PROCESSED_ENCRYPTED_PACKET |
2116 SMBXSRV_ENCRYPTION_DESIRED |
2117 SMBXSRV_ENCRYPTION_REQUIRED)));
2120 bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags)
2122 return ((encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET) &&
2123 (encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET));
2126 /* Set a flag if not already set, return true if set */
2127 bool smbXsrv_set_crypto_flag(uint8_t *flags, uint8_t flag)
2129 if ((flag == 0) || (*flags & flag)) {
2138 * Update encryption state tracking flags, this can be used to
2139 * determine whether whether the session or tcon is "encrypted".
2141 static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
2143 bool *update_session_globalp,
2144 bool *update_tcon_globalp)
2146 /* Default: assume unecrypted and unsigned */
2147 struct smbXsrv_session *session = req->session;
2148 struct smbXsrv_tcon *tcon = req->tcon;
2149 uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
2150 uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2151 bool update_session = false;
2152 bool update_tcon = false;
2154 if (req->was_encrypted && req->do_encryption) {
2155 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
2156 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2158 /* Unencrypted packet, can be signed */
2159 if (req->do_signing) {
2160 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2161 } else if (opcode == SMB2_OP_CANCEL) {
2162 /* Cancel requests are allowed to skip signing */
2163 sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2167 update_session |= smbXsrv_set_crypto_flag(
2168 &session->global->encryption_flags, encrypt_flag);
2169 update_session |= smbXsrv_set_crypto_flag(
2170 &session->global->signing_flags, sign_flag);
2173 update_tcon |= smbXsrv_set_crypto_flag(
2174 &tcon->global->encryption_flags, encrypt_flag);
2175 update_tcon |= smbXsrv_set_crypto_flag(
2176 &tcon->global->signing_flags, sign_flag);
2179 *update_session_globalp = update_session;
2180 *update_tcon_globalp = update_tcon;
2184 bool smbXsrv_is_signed(uint8_t signing_flags)
2187 * Signing is always enabled, so unless we got an unsigned
2188 * packet and at least one signed packet that was not
2189 * encrypted, the session or tcon is "signed".
2191 return (!(signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2192 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2195 bool smbXsrv_is_partially_signed(uint8_t signing_flags)
2197 return ((signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2198 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2201 static NTSTATUS smbd_smb2_request_dispatch_update_counts(
2202 struct smbd_smb2_request *req,
2205 struct smbXsrv_connection *xconn = req->xconn;
2206 const uint8_t *inhdr;
2207 uint16_t channel_sequence;
2208 uint8_t generation_wrap = 0;
2211 struct smbXsrv_open *op;
2212 bool update_open = false;
2213 NTSTATUS status = NT_STATUS_OK;
2215 SMB_ASSERT(!req->request_counters_updated);
2217 if (xconn->protocol < PROTOCOL_SMB2_22) {
2218 return NT_STATUS_OK;
2221 if (req->compat_chain_fsp == NULL) {
2222 return NT_STATUS_OK;
2225 op = req->compat_chain_fsp->op;
2227 return NT_STATUS_OK;
2230 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2231 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2232 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2234 cmp = channel_sequence - op->global->channel_sequence;
2237 * csn wrap. We need to watch out for long-running
2238 * requests that are still sitting on a previously
2239 * used csn. SMB2_OP_NOTIFY can take VERY long.
2241 generation_wrap += 1;
2244 if (abs(cmp) > INT16_MAX) {
2246 * [MS-SMB2] 3.3.5.2.10 - Verifying the Channel Sequence Number:
2248 * If the channel sequence number of the request and the one
2249 * known to the server are not equal, the channel sequence
2250 * number and outstanding request counts are only updated
2251 * "... if the unsigned difference using 16-bit arithmetic
2252 * between ChannelSequence and Open.ChannelSequence is less than
2253 * or equal to 0x7FFF ...".
2254 * Otherwise, an error is returned for the modifying
2255 * calls write, set_info, and ioctl.
2257 * There are currently two issues with the description:
2259 * * For the other calls, the document seems to imply
2260 * that processing continues without adapting the
2261 * counters (if the sequence numbers are not equal).
2263 * TODO: This needs clarification!
2265 * * Also, the behaviour if the difference is larger
2266 * than 0x7FFF is not clear. The document seems to
2267 * imply that if such a difference is reached,
2268 * the server starts to ignore the counters or
2269 * in the case of the modifying calls, return errors.
2271 * TODO: This needs clarification!
2273 * At this point Samba tries to be a little more
2274 * clever than the description in the MS-SMB2 document
2275 * by heuristically detecting and properly treating
2276 * a 16 bit overflow of the client-submitted sequence
2279 * If the stored channel sequence number is more than
2280 * 0x7FFF larger than the one from the request, then
2281 * the client-provided sequence number has likely
2282 * overflown. We treat this case as valid instead
2285 * The MS-SMB2 behaviour would be setting cmp = -1.
2290 if (flags & SMB2_HDR_FLAG_REPLAY_OPERATION) {
2291 if (cmp == 0 && op->pre_request_count == 0) {
2292 op->request_count += 1;
2293 req->request_counters_updated = true;
2294 } else if (cmp > 0 && op->pre_request_count == 0) {
2295 op->pre_request_count += op->request_count;
2296 op->request_count = 1;
2297 op->global->channel_sequence = channel_sequence;
2298 op->global->channel_generation += generation_wrap;
2300 req->request_counters_updated = true;
2301 } else if (modify_call) {
2302 return NT_STATUS_FILE_NOT_AVAILABLE;
2306 op->request_count += 1;
2307 req->request_counters_updated = true;
2308 } else if (cmp > 0) {
2309 op->pre_request_count += op->request_count;
2310 op->request_count = 1;
2311 op->global->channel_sequence = channel_sequence;
2312 op->global->channel_generation += generation_wrap;
2314 req->request_counters_updated = true;
2315 } else if (modify_call) {
2316 return NT_STATUS_FILE_NOT_AVAILABLE;
2319 req->channel_generation = op->global->channel_generation;
2322 status = smbXsrv_open_update(op);
2328 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
2330 struct smbXsrv_connection *xconn = req->xconn;
2331 const struct smbd_smb2_dispatch_table *call = NULL;
2332 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
2333 const uint8_t *inhdr;
2338 NTSTATUS session_status;
2339 uint32_t allowed_flags;
2340 NTSTATUS return_value;
2341 struct smbXsrv_session *x = NULL;
2342 bool signing_required = false;
2343 bool encryption_desired = false;
2344 bool encryption_required = false;
2346 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2348 DO_PROFILE_INC(request);
2350 SMB_ASSERT(!req->request_counters_updated);
2352 /* TODO: verify more things */
2354 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2355 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2356 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2357 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
2358 smb2_opcode_name(opcode),
2359 (unsigned long long)mid));
2361 if (xconn->protocol >= PROTOCOL_SMB2_02) {
2363 * once the protocol is negotiated
2364 * SMB2_OP_NEGPROT is not allowed anymore
2366 if (opcode == SMB2_OP_NEGPROT) {
2367 /* drop the connection */
2368 return NT_STATUS_INVALID_PARAMETER;
2372 * if the protocol is not negotiated yet
2373 * only SMB2_OP_NEGPROT is allowed.
2375 if (opcode != SMB2_OP_NEGPROT) {
2376 /* drop the connection */
2377 return NT_STATUS_INVALID_PARAMETER;
2382 * Check if the client provided a valid session id.
2384 * As some command don't require a valid session id
2385 * we defer the check of the session_status
2387 session_status = smbd_smb2_request_check_session(req);
2390 signing_required = x->global->signing_flags & SMBXSRV_SIGNING_REQUIRED;
2391 encryption_desired = x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
2392 encryption_required = x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
2395 req->async_internal = false;
2396 req->do_signing = false;
2397 if (opcode != SMB2_OP_SESSSETUP) {
2398 req->do_encryption = encryption_desired;
2400 req->do_encryption = false;
2402 req->was_encrypted = false;
2403 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
2404 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
2405 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
2407 if (x != NULL && x->global->session_wire_id != tf_session_id) {
2408 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2409 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
2410 (unsigned long long)x->global->session_wire_id,
2411 (unsigned long long)tf_session_id));
2413 * TODO: windows allows this...
2414 * should we drop the connection?
2416 * For now we just return ACCESS_DENIED
2417 * (Windows clients never trigger this)
2418 * and wait for an update of [MS-SMB2].
2420 return smbd_smb2_request_error(req,
2421 NT_STATUS_ACCESS_DENIED);
2424 req->was_encrypted = true;
2425 req->do_encryption = true;
2428 if (encryption_required && !req->was_encrypted) {
2429 req->do_encryption = true;
2430 return smbd_smb2_request_error(req,
2431 NT_STATUS_ACCESS_DENIED);
2434 call = smbd_smb2_call(opcode);
2436 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2439 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2440 SMB2_HDR_FLAG_SIGNED |
2442 if (xconn->protocol >= PROTOCOL_SMB3_11) {
2443 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2445 if (opcode == SMB2_OP_NEGPROT) {
2446 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11) {
2447 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2450 if (opcode == SMB2_OP_CANCEL) {
2451 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2453 if (xconn->protocol >= PROTOCOL_SMB2_22) {
2454 allowed_flags |= SMB2_HDR_FLAG_REPLAY_OPERATION;
2456 if ((flags & ~allowed_flags) != 0) {
2457 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2460 if (flags & SMB2_HDR_FLAG_CHAINED) {
2462 * This check is mostly for giving the correct error code
2463 * for compounded requests.
2465 if (!NT_STATUS_IS_OK(session_status)) {
2466 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2469 req->compat_chain_fsp = NULL;
2472 if (req->was_encrypted) {
2473 signing_required = false;
2474 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2475 struct smb2_signing_key *signing_key = NULL;
2479 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2480 * If the SMB2 header of the SMB2 NEGOTIATE
2481 * request has the SMB2_FLAGS_SIGNED bit set in the
2482 * Flags field, the server MUST fail the request
2483 * with STATUS_INVALID_PARAMETER.
2485 * Microsoft test tool checks this.
2488 if ((opcode == SMB2_OP_NEGPROT) &&
2489 (flags & SMB2_HDR_FLAG_SIGNED)) {
2490 status = NT_STATUS_INVALID_PARAMETER;
2492 status = NT_STATUS_USER_SESSION_DELETED;
2494 return smbd_smb2_request_error(req, status);
2497 signing_key = smbd_smb2_signing_key(x, xconn);
2500 * If we have a signing key, we should
2503 if (smb2_signing_key_valid(signing_key)) {
2504 req->do_signing = true;
2507 status = smb2_signing_check_pdu(signing_key,
2509 SMBD_SMB2_IN_HDR_IOV(req),
2510 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2511 if (!NT_STATUS_IS_OK(status)) {
2512 return smbd_smb2_request_error(req, status);
2516 * Now that we know the request was correctly signed
2517 * we have to sign the response too.
2519 req->do_signing = true;
2521 if (!NT_STATUS_IS_OK(session_status)) {
2522 return smbd_smb2_request_error(req, session_status);
2524 } else if (opcode == SMB2_OP_CANCEL) {
2525 /* Cancel requests are allowed to skip the signing */
2526 } else if (signing_required) {
2528 * If signing is required we try to sign
2529 * a possible error response
2531 req->do_signing = true;
2532 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2535 if (flags & SMB2_HDR_FLAG_CHAINED) {
2536 req->compound_related = true;
2539 if (call->need_session) {
2540 if (!NT_STATUS_IS_OK(session_status)) {
2541 return smbd_smb2_request_error(req, session_status);
2545 if (call->need_tcon) {
2546 SMB_ASSERT(call->need_session);
2549 * This call needs to be run as user.
2551 * smbd_smb2_request_check_tcon()
2552 * calls change_to_user() on success.
2553 * Which implies set_current_user_info()
2554 * and chdir_current_service().
2556 status = smbd_smb2_request_check_tcon(req);
2557 if (!NT_STATUS_IS_OK(status)) {
2558 return smbd_smb2_request_error(req, status);
2560 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
2561 encryption_desired = true;
2563 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
2564 encryption_required = true;
2566 if (encryption_required && !req->was_encrypted) {
2567 req->do_encryption = true;
2568 return smbd_smb2_request_error(req,
2569 NT_STATUS_ACCESS_DENIED);
2570 } else if (encryption_desired) {
2571 req->do_encryption = true;
2573 } else if (call->need_session) {
2574 struct auth_session_info *session_info = NULL;
2577 * Unless we also have need_tcon (see above),
2578 * we still need to call set_current_user_info().
2581 session_info = req->session->global->auth_session_info;
2582 if (session_info == NULL) {
2583 return NT_STATUS_INVALID_HANDLE;
2586 set_current_user_info(session_info->unix_info->sanitized_username,
2587 session_info->unix_info->unix_name,
2588 session_info->info->domain_name);
2592 bool update_session_global = false;
2593 bool update_tcon_global = false;
2595 smb2srv_update_crypto_flags(req, opcode,
2596 &update_session_global,
2597 &update_tcon_global);
2599 if (update_session_global) {
2600 status = smbXsrv_session_update(x);
2601 if (!NT_STATUS_IS_OK(status)) {
2602 return smbd_smb2_request_error(req, status);
2605 if (update_tcon_global) {
2606 status = smbXsrv_tcon_update(req->tcon);
2607 if (!NT_STATUS_IS_OK(status)) {
2608 return smbd_smb2_request_error(req, status);
2613 if (call->fileid_ofs != 0) {
2614 size_t needed = call->fileid_ofs + 16;
2615 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2616 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2617 uint64_t file_id_persistent;
2618 uint64_t file_id_volatile;
2619 struct files_struct *fsp;
2621 SMB_ASSERT(call->need_tcon);
2623 if (needed > body_size) {
2624 return smbd_smb2_request_error(req,
2625 NT_STATUS_INVALID_PARAMETER);
2628 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2629 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2631 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2633 if (!call->allow_invalid_fileid) {
2634 return smbd_smb2_request_error(req,
2635 NT_STATUS_FILE_CLOSED);
2638 if (file_id_persistent != UINT64_MAX) {
2639 return smbd_smb2_request_error(req,
2640 NT_STATUS_FILE_CLOSED);
2642 if (file_id_volatile != UINT64_MAX) {
2643 return smbd_smb2_request_error(req,
2644 NT_STATUS_FILE_CLOSED);
2649 status = smbd_smb2_request_dispatch_update_counts(req, call->modify);
2650 if (!NT_STATUS_IS_OK(status)) {
2651 return smbd_smb2_request_error(req, status);
2654 if (call->as_root) {
2655 SMB_ASSERT(call->fileid_ofs == 0);
2656 /* This call needs to be run as root */
2657 change_to_root_user();
2659 SMB_ASSERT(call->need_tcon);
2662 #define _INBYTES(_r) \
2663 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
2666 case SMB2_OP_NEGPROT:
2667 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
2668 req->profile, _INBYTES(req));
2669 return_value = smbd_smb2_request_process_negprot(req);
2672 case SMB2_OP_SESSSETUP:
2673 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
2674 req->profile, _INBYTES(req));
2675 return_value = smbd_smb2_request_process_sesssetup(req);
2678 case SMB2_OP_LOGOFF:
2679 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
2680 req->profile, _INBYTES(req));
2681 return_value = smbd_smb2_request_process_logoff(req);
2685 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
2686 req->profile, _INBYTES(req));
2687 return_value = smbd_smb2_request_process_tcon(req);
2691 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
2692 req->profile, _INBYTES(req));
2693 return_value = smbd_smb2_request_process_tdis(req);
2696 case SMB2_OP_CREATE:
2697 if (req->subreq == NULL) {
2698 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
2699 req->profile, _INBYTES(req));
2701 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
2703 return_value = smbd_smb2_request_process_create(req);
2707 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
2708 req->profile, _INBYTES(req));
2709 return_value = smbd_smb2_request_process_close(req);
2713 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
2714 req->profile, _INBYTES(req));
2715 return_value = smbd_smb2_request_process_flush(req);
2719 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
2720 req->profile, _INBYTES(req));
2721 return_value = smbd_smb2_request_process_read(req);
2725 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
2726 req->profile, _INBYTES(req));
2727 return_value = smbd_smb2_request_process_write(req);
2731 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
2732 req->profile, _INBYTES(req));
2733 return_value = smbd_smb2_request_process_lock(req);
2737 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
2738 req->profile, _INBYTES(req));
2739 return_value = smbd_smb2_request_process_ioctl(req);
2742 case SMB2_OP_CANCEL:
2743 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
2744 req->profile, _INBYTES(req));
2745 return_value = smbd_smb2_request_process_cancel(req);
2746 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
2749 * We don't need the request anymore cancel requests never
2752 * smbd_smb2_request_process_cancel() already called
2753 * DLIST_REMOVE(xconn->smb2.requests, req);
2759 case SMB2_OP_KEEPALIVE:
2760 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
2761 req->profile, _INBYTES(req));
2762 return_value = smbd_smb2_request_process_keepalive(req);
2765 case SMB2_OP_QUERY_DIRECTORY:
2766 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
2767 req->profile, _INBYTES(req));
2768 return_value = smbd_smb2_request_process_query_directory(req);
2771 case SMB2_OP_NOTIFY:
2772 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
2773 req->profile, _INBYTES(req));
2774 return_value = smbd_smb2_request_process_notify(req);
2777 case SMB2_OP_GETINFO:
2778 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
2779 req->profile, _INBYTES(req));
2780 return_value = smbd_smb2_request_process_getinfo(req);
2783 case SMB2_OP_SETINFO:
2784 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
2785 req->profile, _INBYTES(req));
2786 return_value = smbd_smb2_request_process_setinfo(req);
2790 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
2791 req->profile, _INBYTES(req));
2792 return_value = smbd_smb2_request_process_break(req);
2796 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2799 return return_value;
2802 static void smbd_smb2_request_reply_update_counts(struct smbd_smb2_request *req)
2804 struct smbXsrv_connection *xconn = req->xconn;
2805 const uint8_t *inhdr;
2806 uint16_t channel_sequence;
2807 struct smbXsrv_open *op;
2809 if (!req->request_counters_updated) {
2813 req->request_counters_updated = false;
2815 if (xconn->protocol < PROTOCOL_SMB2_22) {
2819 if (req->compat_chain_fsp == NULL) {
2823 op = req->compat_chain_fsp->op;
2828 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2829 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2831 if ((op->global->channel_sequence == channel_sequence) &&
2832 (op->global->channel_generation == req->channel_generation)) {
2833 SMB_ASSERT(op->request_count > 0);
2834 op->request_count -= 1;
2836 SMB_ASSERT(op->pre_request_count > 0);
2837 op->pre_request_count -= 1;
2841 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2843 struct smbXsrv_connection *xconn = req->xconn;
2845 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2846 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2847 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2852 TALLOC_FREE(req->async_te);
2854 /* MS-SMB2: 3.3.4.1 Sending Any Outgoing Message */
2855 smbd_smb2_request_reply_update_counts(req);
2857 if (req->do_encryption &&
2858 (firsttf->iov_len == 0) &&
2859 (req->first_key.length == 0) &&
2860 (req->session != NULL) &&
2861 smb2_signing_key_valid(req->session->global->encryption_key))
2863 struct smb2_signing_key *encryption_key =
2864 req->session->global->encryption_key;
2866 uint64_t session_id = req->session->global->session_wire_id;
2867 uint64_t nonce_high;
2870 status = smb2_get_new_nonce(req->session,
2873 if (!NT_STATUS_IS_OK(status)) {
2878 * We need to place the SMB2_TRANSFORM header before the
2883 * we need to remember the encryption key
2884 * and defer the signing/encryption until
2885 * we are sure that we do not change
2888 req->first_key = data_blob_dup_talloc(req,
2889 encryption_key->blob);
2890 if (req->first_key.data == NULL) {
2891 return NT_STATUS_NO_MEMORY;
2894 tf = talloc_zero_array(req, uint8_t,
2897 return NT_STATUS_NO_MEMORY;
2900 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2901 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2902 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2903 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2905 firsttf->iov_base = (void *)tf;
2906 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2909 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2910 (req->last_key.length > 0) &&
2911 (firsttf->iov_len == 0))
2913 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2914 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2915 struct smb2_signing_key key = {
2916 .blob = req->last_key,
2920 * As we are sure the header of the last request in the
2921 * compound chain will not change, we can to sign here
2922 * with the last signing key we remembered.
2924 status = smb2_signing_sign_pdu(&key,
2927 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2928 smb2_signing_key_destructor(&key);
2929 if (!NT_STATUS_IS_OK(status)) {
2933 if (req->last_key.length > 0) {
2934 data_blob_clear_free(&req->last_key);
2937 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
2938 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
2940 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2942 if (req->current_idx < req->out.vector_count) {
2944 * We must process the remaining compound
2945 * SMB2 requests before any new incoming SMB2
2946 * requests. This is because incoming SMB2
2947 * requests may include a cancel for a
2948 * compound request we haven't processed
2951 struct tevent_immediate *im = tevent_create_immediate(req);
2953 return NT_STATUS_NO_MEMORY;
2956 if (req->do_signing && firsttf->iov_len == 0) {
2957 struct smbXsrv_session *x = req->session;
2958 struct smb2_signing_key *signing_key =
2959 smbd_smb2_signing_key(x, xconn);
2962 * we need to remember the signing key
2963 * and defer the signing until
2964 * we are sure that we do not change
2967 req->last_key = data_blob_dup_talloc(req,
2969 if (req->last_key.data == NULL) {
2970 return NT_STATUS_NO_MEMORY;
2975 * smbd_smb2_request_dispatch() will redo the impersonation.
2976 * So we use req->xconn->client->raw_ev_ctx instead
2977 * of req->ev_ctx here.
2979 tevent_schedule_immediate(im,
2980 req->xconn->client->raw_ev_ctx,
2981 smbd_smb2_request_dispatch_immediate,
2983 return NT_STATUS_OK;
2986 if (req->compound_related) {
2987 req->compound_related = false;
2990 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2992 return NT_STATUS_INVALID_PARAMETER_MIX;
2995 /* Set credit for these operations (zero credits if this
2996 is a final reply for an async operation). */
2997 smb2_calculate_credits(req, req);
3000 * now check if we need to sign the current response
3002 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
3003 struct smb2_signing_key key = {
3004 .blob = req->first_key,
3006 status = smb2_signing_encrypt_pdu(&key,
3007 xconn->smb2.server.cipher,
3009 req->out.vector_count - first_idx);
3010 smb2_signing_key_destructor(&key);
3011 if (!NT_STATUS_IS_OK(status)) {
3014 } else if (req->do_signing) {
3015 struct smbXsrv_session *x = req->session;
3016 struct smb2_signing_key *signing_key =
3017 smbd_smb2_signing_key(x, xconn);
3019 status = smb2_signing_sign_pdu(signing_key,
3022 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
3023 if (!NT_STATUS_IS_OK(status)) {
3027 if (req->first_key.length > 0) {
3028 data_blob_clear_free(&req->first_key);
3031 if (req->preauth != NULL) {
3032 gnutls_hash_hd_t hash_hnd = NULL;
3036 rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_SHA512);
3038 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3040 rc = gnutls_hash(hash_hnd,
3041 req->preauth->sha512_value,
3042 sizeof(req->preauth->sha512_value));
3044 gnutls_hash_deinit(hash_hnd, NULL);
3045 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3047 for (i = 1; i < req->in.vector_count; i++) {
3048 rc = gnutls_hash(hash_hnd,
3049 req->in.vector[i].iov_base,
3050 req->in.vector[i].iov_len);
3052 gnutls_hash_deinit(hash_hnd, NULL);
3053 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3057 gnutls_hash_deinit(hash_hnd, NULL);
3058 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3060 gnutls_hash_output(hash_hnd, req->preauth->sha512_value);
3062 rc = gnutls_hash(hash_hnd,
3063 req->preauth->sha512_value,
3064 sizeof(req->preauth->sha512_value));
3066 gnutls_hash_deinit(hash_hnd, NULL);
3067 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3069 for (i = 1; i < req->out.vector_count; i++) {
3070 rc = gnutls_hash(hash_hnd,
3071 req->out.vector[i].iov_base,
3072 req->out.vector[i].iov_len);
3074 gnutls_hash_deinit(hash_hnd, NULL);
3075 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3079 gnutls_hash_deinit(hash_hnd, req->preauth->sha512_value);
3081 req->preauth = NULL;
3084 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
3085 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
3086 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
3087 /* Dynamic part is NULL. Chop it off,
3088 We're going to send it via sendfile. */
3089 req->out.vector_count -= 1;
3093 * We're done with this request -
3094 * move it off the "being processed" queue.
3096 DLIST_REMOVE(xconn->smb2.requests, req);
3098 req->queue_entry.mem_ctx = req;
3099 req->queue_entry.vector = req->out.vector;
3100 req->queue_entry.count = req->out.vector_count;
3101 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry);
3102 xconn->smb2.send_queue_len++;
3104 status = smbd_smb2_flush_send_queue(xconn);
3105 if (!NT_STATUS_IS_OK(status)) {
3109 return NT_STATUS_OK;
3112 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
3114 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
3115 struct tevent_immediate *im,
3118 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
3119 struct smbd_smb2_request);
3120 struct smbXsrv_connection *xconn = req->xconn;
3125 if (DEBUGLEVEL >= 10) {
3126 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
3127 req->current_idx, req->in.vector_count));
3128 print_req_vectors(req);
3131 status = smbd_smb2_request_dispatch(req);
3132 if (!NT_STATUS_IS_OK(status)) {
3133 smbd_server_connection_terminate(xconn, nt_errstr(status));
3137 status = smbd_smb2_request_next_incoming(xconn);
3138 if (!NT_STATUS_IS_OK(status)) {
3139 smbd_server_connection_terminate(xconn, nt_errstr(status));
3144 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
3146 DATA_BLOB body, DATA_BLOB *dyn,
3147 const char *location)
3150 struct iovec *outbody_v;
3151 struct iovec *outdyn_v;
3152 uint32_t next_command_ofs;
3155 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3156 mid = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
3158 DBG_DEBUG("mid [%"PRIu64"] idx[%d] status[%s] "
3159 "body[%u] dyn[%s:%u] at %s\n",
3163 (unsigned int)body.length,
3165 (unsigned int)(dyn ? dyn->length : 0),
3168 if (body.length < 2) {
3169 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3172 if ((body.length % 2) != 0) {
3173 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3176 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
3177 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
3179 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
3180 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
3182 outbody_v->iov_base = (void *)body.data;
3183 outbody_v->iov_len = body.length;
3186 outdyn_v->iov_base = (void *)dyn->data;
3187 outdyn_v->iov_len = dyn->length;
3189 outdyn_v->iov_base = NULL;
3190 outdyn_v->iov_len = 0;
3194 * See if we need to recalculate the offset to the next response
3196 * Note that all responses may require padding (including the very last
3199 if (req->out.vector_count >= (2 * SMBD_SMB2_NUM_IOV_PER_REQ)) {
3200 next_command_ofs = SMB2_HDR_BODY;
3201 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
3202 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
3205 if ((next_command_ofs % 8) != 0) {
3206 size_t pad_size = 8 - (next_command_ofs % 8);
3207 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
3209 * if the dyn buffer is empty
3210 * we can use it to add padding
3214 pad = talloc_zero_array(req,
3217 return smbd_smb2_request_error(req,
3218 NT_STATUS_NO_MEMORY);
3221 outdyn_v->iov_base = (void *)pad;
3222 outdyn_v->iov_len = pad_size;
3225 * For now we copy the dynamic buffer
3226 * and add the padding to the new buffer
3233 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
3234 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
3236 new_size = old_size + pad_size;
3237 new_dyn = talloc_zero_array(req,
3239 if (new_dyn == NULL) {
3240 return smbd_smb2_request_error(req,
3241 NT_STATUS_NO_MEMORY);
3244 memcpy(new_dyn, old_dyn, old_size);
3245 memset(new_dyn + old_size, 0, pad_size);
3247 outdyn_v->iov_base = (void *)new_dyn;
3248 outdyn_v->iov_len = new_size;
3250 next_command_ofs += pad_size;
3253 if ((req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) >= req->out.vector_count) {
3254 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
3256 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
3258 return smbd_smb2_request_reply(req);
3261 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
3264 const char *location)
3266 struct smbXsrv_connection *xconn = req->xconn;
3269 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3270 size_t unread_bytes = smbd_smb2_unread_bytes(req);
3272 DBG_NOTICE("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| "
3273 "at %s\n", req->current_idx, nt_errstr(status),
3274 info ? " +info" : "", location);
3277 /* Recvfile error. Drain incoming socket. */
3281 ret = drain_socket(xconn->transport.sock, unread_bytes);
3282 if (ret != unread_bytes) {
3286 error = NT_STATUS_IO_DEVICE_ERROR;
3288 error = map_nt_error_from_unix_common(errno);
3291 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
3292 "ret[%u] errno[%d] => %s\n",
3293 (unsigned)unread_bytes,
3294 (unsigned)ret, errno, nt_errstr(error)));
3299 body.data = outhdr + SMB2_HDR_BODY;
3301 SSVAL(body.data, 0, 9);
3304 SIVAL(body.data, 0x04, info->length);
3306 /* Allocated size of req->out.vector[i].iov_base
3307 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
3308 * 1 byte without having to do an alloc.
3311 info->data = ((uint8_t *)outhdr) +
3312 OUTVEC_ALLOC_SIZE - 1;
3314 SCVAL(info->data, 0, 0);
3318 * Note: Even if there is an error, continue to process the request.
3322 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
3326 struct smbd_smb2_send_break_state {
3327 struct smbd_smb2_send_queue queue_entry;
3328 uint8_t nbt_hdr[NBT_HDR_SIZE];
3329 uint8_t tf[SMB2_TF_HDR_SIZE];
3330 uint8_t hdr[SMB2_HDR_BODY];
3331 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
3335 static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
3336 struct smbXsrv_session *session,
3337 struct smbXsrv_tcon *tcon,
3338 const uint8_t *body,
3341 struct smbd_smb2_send_break_state *state;
3342 bool do_encryption = false;
3343 uint64_t session_wire_id = 0;
3344 uint64_t nonce_high = 0;
3345 uint64_t nonce_low = 0;
3350 if (session != NULL) {
3351 session_wire_id = session->global->session_wire_id;
3352 do_encryption = session->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
3353 if (tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
3354 do_encryption = true;
3358 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
3361 state = talloc_zero_size(xconn, statelen);
3362 if (state == NULL) {
3363 return NT_STATUS_NO_MEMORY;
3365 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
3367 if (do_encryption) {
3368 status = smb2_get_new_nonce(session,
3371 if (!NT_STATUS_IS_OK(status)) {
3376 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
3377 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
3378 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
3379 SBVAL(state->tf, SMB2_TF_SESSION_ID, session_wire_id);
3381 SIVAL(state->hdr, 0, SMB2_MAGIC);
3382 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
3383 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
3384 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
3385 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
3386 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
3387 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
3388 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
3389 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
3390 SIVAL(state->hdr, SMB2_HDR_PID, 0);
3391 SIVAL(state->hdr, SMB2_HDR_TID, 0);
3392 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
3393 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
3395 state->vector[0] = (struct iovec) {
3396 .iov_base = state->nbt_hdr,
3397 .iov_len = sizeof(state->nbt_hdr)
3400 if (do_encryption) {
3401 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3402 .iov_base = state->tf,
3403 .iov_len = sizeof(state->tf)
3406 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3412 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
3413 .iov_base = state->hdr,
3414 .iov_len = sizeof(state->hdr)
3417 memcpy(state->body, body, body_len);
3419 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
3420 .iov_base = state->body,
3421 .iov_len = body_len /* no sizeof(state->body) .. :-) */
3425 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
3428 ok = smb2_setup_nbt_length(state->vector,
3429 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
3431 return NT_STATUS_INVALID_PARAMETER_MIX;
3434 if (do_encryption) {
3435 struct smb2_signing_key *encryption_key =
3436 session->global->encryption_key;
3438 status = smb2_signing_encrypt_pdu(encryption_key,
3439 xconn->smb2.server.cipher,
3440 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
3441 SMBD_SMB2_NUM_IOV_PER_REQ);
3442 if (!NT_STATUS_IS_OK(status)) {
3447 state->queue_entry.mem_ctx = state;
3448 state->queue_entry.vector = state->vector;
3449 state->queue_entry.count = ARRAY_SIZE(state->vector);
3450 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
3451 xconn->smb2.send_queue_len++;
3453 status = smbd_smb2_flush_send_queue(xconn);
3454 if (!NT_STATUS_IS_OK(status)) {
3458 return NT_STATUS_OK;
3461 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_connection *xconn,
3462 struct smbXsrv_session *session,
3463 struct smbXsrv_tcon *tcon,
3464 struct smbXsrv_open *op,
3465 uint8_t oplock_level)
3469 SSVAL(body, 0x00, sizeof(body));
3470 SCVAL(body, 0x02, oplock_level);
3471 SCVAL(body, 0x03, 0); /* reserved */
3472 SIVAL(body, 0x04, 0); /* reserved */
3473 SBVAL(body, 0x08, op->global->open_persistent_id);
3474 SBVAL(body, 0x10, op->global->open_volatile_id);
3476 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3479 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_connection *xconn,
3481 uint32_t lease_flags,
3482 struct smb2_lease_key *lease_key,
3483 uint32_t current_lease_state,
3484 uint32_t new_lease_state)
3488 SSVAL(body, 0x00, sizeof(body));
3489 SSVAL(body, 0x02, new_epoch);
3490 SIVAL(body, 0x04, lease_flags);
3491 SBVAL(body, 0x08, lease_key->data[0]);
3492 SBVAL(body, 0x10, lease_key->data[1]);
3493 SIVAL(body, 0x18, current_lease_state);
3494 SIVAL(body, 0x1c, new_lease_state);
3495 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
3496 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
3497 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
3499 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3502 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
3506 uint64_t file_id_persistent;
3507 uint64_t file_id_volatile;
3508 struct smbXsrv_open *op = NULL;
3509 struct files_struct *fsp = NULL;
3510 const uint8_t *body = NULL;
3513 * This is only called with a pktbuf
3514 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
3518 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
3519 /* Transform header. Cannot recvfile. */
3522 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
3523 /* Not SMB2. Normal error path will cope. */
3526 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
3527 /* Not SMB2. Normal error path will cope. */
3530 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
3531 /* Needs to be a WRITE. */
3534 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
3535 /* Chained. Cannot recvfile. */
3538 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
3539 if (flags & SMB2_HDR_FLAG_CHAINED) {
3540 /* Chained. Cannot recvfile. */
3543 if (flags & SMB2_HDR_FLAG_SIGNED) {
3544 /* Signed. Cannot recvfile. */
3548 body = &state->pktbuf[SMB2_HDR_BODY];
3550 file_id_persistent = BVAL(body, 0x10);
3551 file_id_volatile = BVAL(body, 0x18);
3553 status = smb2srv_open_lookup(state->req->xconn,
3558 if (!NT_STATUS_IS_OK(status)) {
3566 if (fsp->conn == NULL) {
3570 if (IS_IPC(fsp->conn)) {
3573 if (IS_PRINT(fsp->conn)) {
3576 if (fsp->base_fsp != NULL) {
3580 DEBUG(10,("Doing recvfile write len = %u\n",
3581 (unsigned int)(state->pktfull - state->pktlen)));
3586 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
3588 struct smbd_server_connection *sconn = xconn->client->sconn;
3589 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3590 size_t max_send_queue_len;
3591 size_t cur_send_queue_len;
3593 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3595 * we're not supposed to do any io
3597 return NT_STATUS_OK;
3600 if (state->req != NULL) {
3602 * if there is already a tstream_readv_pdu
3603 * pending, we are done.
3605 return NT_STATUS_OK;
3608 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
3609 cur_send_queue_len = xconn->smb2.send_queue_len;
3611 if (cur_send_queue_len > max_send_queue_len) {
3613 * if we have a lot of requests to send,
3614 * we wait until they are on the wire until we
3615 * ask for the next request.
3617 return NT_STATUS_OK;
3620 /* ask for the next request */
3621 ZERO_STRUCTP(state);
3622 state->req = smbd_smb2_request_allocate(xconn);
3623 if (state->req == NULL) {
3624 return NT_STATUS_NO_MEMORY;
3626 state->req->sconn = sconn;
3627 state->req->xconn = xconn;
3628 state->min_recv_size = lp_min_receive_file_size();
3630 TEVENT_FD_READABLE(xconn->transport.fde);
3632 return NT_STATUS_OK;
3635 NTSTATUS smbd_smb2_process_negprot(struct smbXsrv_connection *xconn,
3636 uint64_t expected_seq_low,
3637 const uint8_t *inpdu, size_t size)
3639 struct smbd_server_connection *sconn = xconn->client->sconn;
3641 struct smbd_smb2_request *req = NULL;
3643 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3644 (unsigned int)size));
3646 status = smbd_initialize_smb2(xconn, expected_seq_low);
3647 if (!NT_STATUS_IS_OK(status)) {
3648 smbd_server_connection_terminate(xconn, nt_errstr(status));
3652 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
3653 if (!NT_STATUS_IS_OK(status)) {
3654 smbd_server_connection_terminate(xconn, nt_errstr(status));
3658 status = smbd_smb2_request_validate(req);
3659 if (!NT_STATUS_IS_OK(status)) {
3660 smbd_server_connection_terminate(xconn, nt_errstr(status));
3664 status = smbd_smb2_request_setup_out(req);
3665 if (!NT_STATUS_IS_OK(status)) {
3666 smbd_server_connection_terminate(xconn, nt_errstr(status));
3672 * this was already counted at the SMB1 layer =>
3673 * smbd_smb2_request_dispatch() should not count it twice.
3675 if (profile_p->values.request_stats.count > 0) {
3676 profile_p->values.request_stats.count--;
3679 status = smbd_smb2_request_dispatch(req);
3680 if (!NT_STATUS_IS_OK(status)) {
3681 smbd_server_connection_terminate(xconn, nt_errstr(status));
3685 status = smbd_smb2_request_next_incoming(xconn);
3686 if (!NT_STATUS_IS_OK(status)) {
3687 smbd_server_connection_terminate(xconn, nt_errstr(status));
3691 sconn->num_requests++;
3692 return NT_STATUS_OK;
3695 static int socket_error_from_errno(int ret,
3709 if (sys_errno == 0) {
3713 if (sys_errno == EINTR) {
3718 if (sys_errno == EINPROGRESS) {
3723 if (sys_errno == EAGAIN) {
3728 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3729 if (sys_errno == ENOMEM) {
3735 #if EWOULDBLOCK != EAGAIN
3736 if (sys_errno == EWOULDBLOCK) {
3746 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3753 if (xconn->smb2.send_queue == NULL) {
3754 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3755 return NT_STATUS_OK;
3758 while (xconn->smb2.send_queue != NULL) {
3759 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3763 if (e->sendfile_header != NULL) {
3768 status = NT_STATUS_INTERNAL_ERROR;
3770 for (i=0; i < e->count; i++) {
3771 size += e->vector[i].iov_len;
3774 if (size <= e->sendfile_header->length) {
3775 buf = e->sendfile_header->data;
3777 buf = talloc_array(e->mem_ctx, uint8_t, size);
3779 return NT_STATUS_NO_MEMORY;
3784 for (i=0; i < e->count; i++) {
3786 e->vector[i].iov_base,
3787 e->vector[i].iov_len);
3788 size += e->vector[i].iov_len;
3791 e->sendfile_header->data = buf;
3792 e->sendfile_header->length = size;
3793 e->sendfile_status = &status;
3796 xconn->smb2.send_queue_len--;
3797 DLIST_REMOVE(xconn->smb2.send_queue, e);
3799 * This triggers the sendfile path via
3802 talloc_free(e->mem_ctx);
3804 if (!NT_STATUS_IS_OK(status)) {
3810 msg = (struct msghdr) {
3811 .msg_iov = e->vector,
3812 .msg_iovlen = e->count,
3815 ret = sendmsg(xconn->transport.sock, &msg, 0);
3817 /* propagate end of file */
3818 return NT_STATUS_INTERNAL_ERROR;
3820 err = socket_error_from_errno(ret, errno, &retry);
3823 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3824 return NT_STATUS_OK;
3827 return map_nt_error_from_unix_common(err);
3830 ok = iov_advance(&e->vector, &e->count, ret);
3832 return NT_STATUS_INTERNAL_ERROR;
3836 /* we have more to write */
3837 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3838 return NT_STATUS_OK;
3841 xconn->smb2.send_queue_len--;
3842 DLIST_REMOVE(xconn->smb2.send_queue, e);
3843 talloc_free(e->mem_ctx);
3847 * Restart reads if we were blocked on
3848 * draining the send queue.
3851 status = smbd_smb2_request_next_incoming(xconn);
3852 if (!NT_STATUS_IS_OK(status)) {
3856 return NT_STATUS_OK;
3859 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3862 struct smbd_server_connection *sconn = xconn->client->sconn;
3863 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3864 struct smbd_smb2_request *req = NULL;
3865 size_t min_recvfile_size = UINT32_MAX;
3873 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3875 * we're not supposed to do any io
3877 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3878 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3879 return NT_STATUS_OK;
3882 if (fde_flags & TEVENT_FD_WRITE) {
3883 status = smbd_smb2_flush_send_queue(xconn);
3884 if (!NT_STATUS_IS_OK(status)) {
3889 if (!(fde_flags & TEVENT_FD_READ)) {
3890 return NT_STATUS_OK;
3893 if (state->req == NULL) {
3894 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3895 return NT_STATUS_OK;
3899 if (!state->hdr.done) {
3900 state->hdr.done = true;
3902 state->vector.iov_base = (void *)state->hdr.nbt;
3903 state->vector.iov_len = NBT_HDR_SIZE;
3906 msg = (struct msghdr) {
3907 .msg_iov = &state->vector,
3911 ret = recvmsg(xconn->transport.sock, &msg, 0);
3913 /* propagate end of file */
3914 return NT_STATUS_END_OF_FILE;
3916 err = socket_error_from_errno(ret, errno, &retry);
3919 TEVENT_FD_READABLE(xconn->transport.fde);
3920 return NT_STATUS_OK;
3923 return map_nt_error_from_unix_common(err);
3926 if (ret < state->vector.iov_len) {
3928 base = (uint8_t *)state->vector.iov_base;
3930 state->vector.iov_base = (void *)base;
3931 state->vector.iov_len -= ret;
3932 /* we have more to read */
3933 TEVENT_FD_READABLE(xconn->transport.fde);
3934 return NT_STATUS_OK;
3937 if (state->pktlen > 0) {
3938 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3940 * Not a possible receivefile write.
3941 * Read the rest of the data.
3943 state->doing_receivefile = false;
3945 state->pktbuf = talloc_realloc(state->req,
3949 if (state->pktbuf == NULL) {
3950 return NT_STATUS_NO_MEMORY;
3953 state->vector.iov_base = (void *)(state->pktbuf +
3955 state->vector.iov_len = (state->pktfull -
3958 state->pktlen = state->pktfull;
3963 * Either this is a receivefile write so we've
3964 * done a short read, or if not we have all the data.
3970 * Now we analyze the NBT header
3972 if (state->hdr.nbt[0] != 0x00) {
3973 state->min_recv_size = 0;
3975 state->pktfull = smb2_len(state->hdr.nbt);
3976 if (state->pktfull == 0) {
3980 if (state->min_recv_size != 0) {
3981 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3982 min_recvfile_size += state->min_recv_size;
3985 if (state->pktfull > min_recvfile_size) {
3987 * Might be a receivefile write. Read the SMB2 HEADER +
3988 * SMB2_WRITE header first. Set 'doing_receivefile'
3989 * as we're *attempting* receivefile write. If this
3990 * turns out not to be a SMB2_WRITE request or otherwise
3991 * not suitable then we'll just read the rest of the data
3992 * the next time this function is called.
3994 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3995 state->doing_receivefile = true;
3997 state->pktlen = state->pktfull;
4000 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
4001 if (state->pktbuf == NULL) {
4002 return NT_STATUS_NO_MEMORY;
4005 state->vector.iov_base = (void *)state->pktbuf;
4006 state->vector.iov_len = state->pktlen;
4012 if (state->hdr.nbt[0] != 0x00) {
4013 DEBUG(1,("ignore NBT[0x%02X] msg\n",
4014 state->hdr.nbt[0]));
4017 ZERO_STRUCTP(state);
4019 state->min_recv_size = lp_min_receive_file_size();
4027 req->request_time = timeval_current();
4028 now = timeval_to_nttime(&req->request_time);
4030 status = smbd_smb2_inbuf_parse_compound(xconn,
4036 &req->in.vector_count);
4037 if (!NT_STATUS_IS_OK(status)) {
4041 if (state->doing_receivefile) {
4042 req->smb1req = talloc_zero(req, struct smb_request);
4043 if (req->smb1req == NULL) {
4044 return NT_STATUS_NO_MEMORY;
4046 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
4049 ZERO_STRUCTP(state);
4051 req->current_idx = 1;
4053 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
4054 req->current_idx, req->in.vector_count));
4056 status = smbd_smb2_request_validate(req);
4057 if (!NT_STATUS_IS_OK(status)) {
4061 status = smbd_smb2_request_setup_out(req);
4062 if (!NT_STATUS_IS_OK(status)) {
4066 status = smbd_smb2_request_dispatch(req);
4067 if (!NT_STATUS_IS_OK(status)) {
4071 sconn->num_requests++;
4073 /* The timeout_processing function isn't run nearly
4074 often enough to implement 'max log size' without
4075 overrunning the size of the file by many megabytes.
4076 This is especially true if we are running at debug
4077 level 10. Checking every 50 SMB2s is a nice
4078 tradeoff of performance vs log file size overrun. */
4080 if ((sconn->num_requests % 50) == 0 &&
4081 need_to_check_log_size()) {
4082 change_to_root_user();
4086 status = smbd_smb2_request_next_incoming(xconn);
4087 if (!NT_STATUS_IS_OK(status)) {
4091 return NT_STATUS_OK;
4094 static void smbd_smb2_connection_handler(struct tevent_context *ev,
4095 struct tevent_fd *fde,
4099 struct smbXsrv_connection *xconn =
4100 talloc_get_type_abort(private_data,
4101 struct smbXsrv_connection);
4104 status = smbd_smb2_io_handler(xconn, flags);
4105 if (!NT_STATUS_IS_OK(status)) {
4106 smbd_server_connection_terminate(xconn, nt_errstr(status));