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_blob,
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 status = smb2_signing_encrypt_pdu(req->first_key,
1340 xconn->smb2.server.cipher,
1342 nreq->out.vector_count - first_idx);
1343 if (!NT_STATUS_IS_OK(status)) {
1346 } else if (req->last_key.length > 0) {
1347 struct smb2_signing_key key = {
1348 .blob = req->last_key,
1351 status = smb2_signing_sign_pdu(&key,
1354 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1355 smb2_signing_key_destructor(&key);
1356 if (!NT_STATUS_IS_OK(status)) {
1361 nreq->queue_entry.mem_ctx = nreq;
1362 nreq->queue_entry.vector = nreq->out.vector;
1363 nreq->queue_entry.count = nreq->out.vector_count;
1364 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry);
1365 xconn->smb2.send_queue_len++;
1367 status = smbd_smb2_flush_send_queue(xconn);
1368 if (!NT_STATUS_IS_OK(status)) {
1372 return NT_STATUS_OK;
1375 struct smbd_smb2_request_pending_state {
1376 struct smbd_smb2_send_queue queue_entry;
1377 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1378 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1381 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1382 struct tevent_timer *te,
1383 struct timeval current_time,
1384 void *private_data);
1386 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1387 struct tevent_req *subreq,
1388 uint32_t defer_time)
1391 struct timeval defer_endtime;
1392 uint8_t *outhdr = NULL;
1395 if (!tevent_req_is_in_progress(subreq)) {
1397 * This is a performance optimization,
1398 * it avoids one tevent_loop iteration,
1399 * which means we avoid one
1400 * talloc_stackframe_pool/talloc_free pair.
1402 tevent_req_notify_callback(subreq);
1403 return NT_STATUS_OK;
1406 req->subreq = subreq;
1409 if (req->async_te) {
1410 /* We're already async. */
1411 return NT_STATUS_OK;
1414 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1415 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1416 if (flags & SMB2_HDR_FLAG_ASYNC) {
1417 /* We're already async. */
1418 return NT_STATUS_OK;
1421 if (req->async_internal || defer_time == 0) {
1423 * An SMB2 request implementation wants to handle the request
1424 * asynchronously "internally" while keeping synchronous
1425 * behaviour for the SMB2 request. This means we don't send an
1426 * interim response and we can allow processing of compound SMB2
1427 * requests (cf the subsequent check) for all cases.
1429 return NT_STATUS_OK;
1432 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1434 * We're trying to go async in a compound request
1435 * chain. This is only allowed for opens that cause an
1436 * oplock break or for the last operation in the
1437 * chain, otherwise it is not allowed. See
1438 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
1440 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1442 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1444 * Cancel the outstanding request.
1446 bool ok = tevent_req_cancel(req->subreq);
1448 return NT_STATUS_OK;
1450 TALLOC_FREE(req->subreq);
1451 return smbd_smb2_request_error(req,
1452 NT_STATUS_INTERNAL_ERROR);
1456 if (DEBUGLEVEL >= 10) {
1457 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1458 (unsigned int)req->current_idx );
1459 print_req_vectors(req);
1462 if (req->current_idx > 1) {
1464 * We're going async in a compound
1465 * chain after the first request has
1466 * already been processed. Send an
1467 * interim response containing the
1468 * set of replies already generated.
1470 int idx = req->current_idx;
1472 status = smb2_send_async_interim_response(req);
1473 if (!NT_STATUS_IS_OK(status)) {
1476 if (req->first_key.length > 0) {
1477 data_blob_clear_free(&req->first_key);
1480 req->current_idx = 1;
1483 * Re-arrange the in.vectors to remove what
1486 memmove(&req->in.vector[1],
1487 &req->in.vector[idx],
1488 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1489 req->in.vector_count = 1 + (req->in.vector_count - idx);
1491 /* Re-arrange the out.vectors to match. */
1492 memmove(&req->out.vector[1],
1493 &req->out.vector[idx],
1494 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1495 req->out.vector_count = 1 + (req->out.vector_count - idx);
1497 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1499 * We only have one remaining request as
1500 * we've processed everything else.
1501 * This is no longer a compound request.
1503 req->compound_related = false;
1504 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1505 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1506 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1509 if (req->last_key.length > 0) {
1510 data_blob_clear_free(&req->last_key);
1514 * smbd_smb2_request_pending_timer() just send a packet
1515 * to the client and doesn't need any impersonation.
1516 * So we use req->xconn->client->raw_ev_ctx instead
1517 * of req->ev_ctx here.
1519 defer_endtime = timeval_current_ofs_usec(defer_time);
1520 req->async_te = tevent_add_timer(req->xconn->client->raw_ev_ctx,
1522 smbd_smb2_request_pending_timer,
1524 if (req->async_te == NULL) {
1525 return NT_STATUS_NO_MEMORY;
1528 return NT_STATUS_OK;
1532 struct smb2_signing_key *smbd_smb2_signing_key(struct smbXsrv_session *session,
1533 struct smbXsrv_connection *xconn)
1535 struct smbXsrv_channel_global0 *c = NULL;
1537 struct smb2_signing_key *key = NULL;
1539 status = smbXsrv_session_find_channel(session, xconn, &c);
1540 if (NT_STATUS_IS_OK(status)) {
1541 key = c->signing_key;
1544 if (!smb2_signing_key_valid(key)) {
1545 key = session->global->signing_key;
1551 static NTSTATUS smb2_get_new_nonce(struct smbXsrv_session *session,
1552 uint64_t *new_nonce_high,
1553 uint64_t *new_nonce_low)
1555 uint64_t nonce_high;
1558 session->nonce_low += 1;
1559 if (session->nonce_low == 0) {
1560 session->nonce_low += 1;
1561 session->nonce_high += 1;
1565 * CCM and GCM algorithms must never have their
1566 * nonce wrap, or the security of the whole
1567 * communication and the keys is destroyed.
1568 * We must drop the connection once we have
1569 * transfered too much data.
1571 * NOTE: We assume nonces greater than 8 bytes.
1573 if (session->nonce_high >= session->nonce_high_max) {
1574 return NT_STATUS_ENCRYPTION_FAILED;
1577 nonce_high = session->nonce_high_random;
1578 nonce_high += session->nonce_high;
1579 nonce_low = session->nonce_low;
1581 *new_nonce_high = nonce_high;
1582 *new_nonce_low = nonce_low;
1583 return NT_STATUS_OK;
1586 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1587 struct tevent_timer *te,
1588 struct timeval current_time,
1591 struct smbd_smb2_request *req =
1592 talloc_get_type_abort(private_data,
1593 struct smbd_smb2_request);
1594 struct smbXsrv_connection *xconn = req->xconn;
1595 struct smbd_smb2_request_pending_state *state = NULL;
1596 uint8_t *outhdr = NULL;
1597 const uint8_t *inhdr = NULL;
1600 uint8_t *hdr = NULL;
1601 uint8_t *body = NULL;
1602 uint8_t *dyn = NULL;
1604 uint64_t session_id = 0;
1605 uint64_t message_id = 0;
1606 uint64_t nonce_high = 0;
1607 uint64_t nonce_low = 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);
1619 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1621 async_id = message_id; /* keep it simple for now... */
1623 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1624 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1626 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1628 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1629 (unsigned long long)async_id ));
1632 * What we send is identical to a smbd_smb2_request_error
1633 * packet with an error status of STATUS_PENDING. Make use
1634 * of this fact sometime when refactoring. JRA.
1637 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
1638 if (state == NULL) {
1639 smbd_server_connection_terminate(xconn,
1640 nt_errstr(NT_STATUS_NO_MEMORY));
1644 tf = state->buf + NBT_HDR_SIZE;
1645 tf_len = SMB2_TF_HDR_SIZE;
1647 hdr = tf + SMB2_TF_HDR_SIZE;
1648 body = hdr + SMB2_HDR_BODY;
1651 if (req->do_encryption) {
1652 status = smb2_get_new_nonce(req->session,
1655 if (!NT_STATUS_IS_OK(status)) {
1656 smbd_server_connection_terminate(xconn,
1662 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1663 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1664 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1665 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1667 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1668 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1669 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1670 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1671 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1673 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1674 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1675 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1676 SBVAL(hdr, SMB2_HDR_PID, async_id);
1677 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1678 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1679 memcpy(hdr+SMB2_HDR_SIGNATURE,
1680 outhdr+SMB2_HDR_SIGNATURE, 16);
1682 SSVAL(body, 0x00, 0x08 + 1);
1684 SCVAL(body, 0x02, 0);
1685 SCVAL(body, 0x03, 0);
1686 SIVAL(body, 0x04, 0);
1687 /* Match W2K8R2... */
1688 SCVAL(dyn, 0x00, 0x21);
1690 state->vector[0].iov_base = (void *)state->buf;
1691 state->vector[0].iov_len = NBT_HDR_SIZE;
1693 if (req->do_encryption) {
1694 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1695 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1697 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1698 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1701 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1702 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1704 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1705 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1707 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1708 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1710 ok = smb2_setup_nbt_length(state->vector,
1711 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1713 smbd_server_connection_terminate(
1714 xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
1718 /* Ensure we correctly go through crediting. Grant
1719 the credits now, and zero credits on the final
1721 smb2_set_operation_credit(req->xconn,
1722 SMBD_SMB2_IN_HDR_IOV(req),
1723 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1725 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1730 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1731 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1733 (unsigned int)ARRAY_SIZE(state->vector),
1734 (unsigned int)state->vector[i].iov_len);
1738 if (req->do_encryption) {
1739 struct smbXsrv_session *x = req->session;
1740 DATA_BLOB encryption_key = x->global->encryption_key_blob;
1742 status = smb2_signing_encrypt_pdu(encryption_key,
1743 xconn->smb2.server.cipher,
1744 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1745 SMBD_SMB2_NUM_IOV_PER_REQ);
1746 if (!NT_STATUS_IS_OK(status)) {
1747 smbd_server_connection_terminate(xconn,
1751 } else if (req->do_signing) {
1752 struct smbXsrv_session *x = req->session;
1753 struct smb2_signing_key *signing_key =
1754 smbd_smb2_signing_key(x, xconn);
1756 status = smb2_signing_sign_pdu(signing_key,
1758 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1759 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1760 if (!NT_STATUS_IS_OK(status)) {
1761 smbd_server_connection_terminate(xconn,
1767 state->queue_entry.mem_ctx = state;
1768 state->queue_entry.vector = state->vector;
1769 state->queue_entry.count = ARRAY_SIZE(state->vector);
1770 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
1771 xconn->smb2.send_queue_len++;
1773 status = smbd_smb2_flush_send_queue(xconn);
1774 if (!NT_STATUS_IS_OK(status)) {
1775 smbd_server_connection_terminate(xconn,
1781 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1783 struct smbXsrv_connection *xconn = req->xconn;
1784 struct smbd_smb2_request *cur;
1785 const uint8_t *inhdr;
1787 uint64_t search_message_id;
1788 uint64_t search_async_id;
1791 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1793 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1794 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1795 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1798 * We don't need the request anymore cancel requests never
1801 * We defer the TALLOC_FREE(req) to the caller.
1803 DLIST_REMOVE(xconn->smb2.requests, req);
1805 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1806 const uint8_t *outhdr;
1807 uint64_t message_id;
1810 if (cur->compound_related) {
1812 * Never cancel anything in a compound request.
1813 * Way too hard to deal with the result.
1818 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1820 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1821 async_id = BVAL(outhdr, SMB2_HDR_PID);
1823 if (flags & SMB2_HDR_FLAG_ASYNC) {
1824 if (search_async_id == async_id) {
1825 found_id = async_id;
1829 if (search_message_id == message_id) {
1830 found_id = message_id;
1836 if (cur && cur->subreq) {
1837 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1838 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1839 "cancel opcode[%s] mid %llu\n",
1840 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1841 (unsigned long long)found_id ));
1842 tevent_req_cancel(cur->subreq);
1845 return NT_STATUS_OK;
1848 /*************************************************************
1849 Ensure an incoming tid is a valid one for us to access.
1850 Change to the associated uid credentials and chdir to the
1851 valid tid directory.
1852 *************************************************************/
1854 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1856 const uint8_t *inhdr;
1859 struct smbXsrv_tcon *tcon;
1861 NTTIME now = timeval_to_nttime(&req->request_time);
1865 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1867 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1868 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1870 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1871 in_tid = req->last_tid;
1876 status = smb2srv_tcon_lookup(req->session,
1877 in_tid, now, &tcon);
1878 if (!NT_STATUS_IS_OK(status)) {
1882 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1883 return NT_STATUS_ACCESS_DENIED;
1887 req->last_tid = in_tid;
1889 return NT_STATUS_OK;
1892 /*************************************************************
1893 Ensure an incoming session_id is a valid one for us to access.
1894 *************************************************************/
1896 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1898 const uint8_t *inhdr;
1901 uint64_t in_session_id;
1902 struct smbXsrv_session *session = NULL;
1903 struct auth_session_info *session_info;
1905 NTTIME now = timeval_to_nttime(&req->request_time);
1907 req->session = NULL;
1910 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1912 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1913 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1914 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1916 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1917 in_session_id = req->last_session_id;
1920 req->last_session_id = 0;
1922 /* look an existing session up */
1923 switch (in_opcode) {
1924 case SMB2_OP_SESSSETUP:
1926 * For a session bind request, we don't have the
1927 * channel set up at this point yet, so we defer
1928 * the verification that the connection belongs
1929 * to the session to the session setup code, which
1930 * can look at the session binding flags.
1932 status = smb2srv_session_lookup_client(req->xconn->client,
1937 status = smb2srv_session_lookup_conn(req->xconn,
1943 req->session = session;
1944 req->last_session_id = in_session_id;
1946 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1947 switch (in_opcode) {
1948 case SMB2_OP_SESSSETUP:
1949 status = NT_STATUS_OK;
1951 case SMB2_OP_LOGOFF:
1954 case SMB2_OP_CANCEL:
1955 case SMB2_OP_KEEPALIVE:
1957 * [MS-SMB2] 3.3.5.2.9 Verifying the Session
1958 * specifies that LOGOFF, CLOSE and (UN)LOCK
1959 * should always be processed even on expired sessions.
1961 * Also see the logic in
1962 * smbd_smb2_request_process_lock().
1964 * The smb2.session.expire2 test shows that
1965 * CANCEL and KEEPALIVE/ECHO should also
1968 status = NT_STATUS_OK;
1974 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1975 switch (in_opcode) {
1977 case SMB2_OP_CREATE:
1978 case SMB2_OP_GETINFO:
1979 case SMB2_OP_SETINFO:
1980 return NT_STATUS_INVALID_HANDLE;
1983 * Notice the check for
1984 * (session_info == NULL)
1987 status = NT_STATUS_OK;
1991 if (!NT_STATUS_IS_OK(status)) {
1995 session_info = session->global->auth_session_info;
1996 if (session_info == NULL) {
1997 return NT_STATUS_INVALID_HANDLE;
2000 return NT_STATUS_OK;
2003 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
2004 uint32_t data_length)
2006 struct smbXsrv_connection *xconn = req->xconn;
2007 uint16_t needed_charge;
2008 uint16_t credit_charge = 1;
2009 const uint8_t *inhdr;
2011 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2013 if (xconn->smb2.credits.multicredit) {
2014 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
2015 credit_charge = MAX(credit_charge, 1);
2018 needed_charge = (data_length - 1)/ 65536 + 1;
2020 DBGC_DEBUG(DBGC_SMB2_CREDITS,
2021 "mid %llu, CreditCharge: %d, NeededCharge: %d\n",
2022 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
2023 credit_charge, needed_charge);
2025 if (needed_charge > credit_charge) {
2026 DBGC_WARNING(DBGC_SMB2_CREDITS,
2027 "CreditCharge too low, given %d, needed %d\n",
2028 credit_charge, needed_charge);
2029 return NT_STATUS_INVALID_PARAMETER;
2032 return NT_STATUS_OK;
2035 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
2036 size_t expected_body_size)
2038 struct iovec *inhdr_v;
2039 const uint8_t *inhdr;
2041 const uint8_t *inbody;
2043 size_t min_dyn_size = expected_body_size & 0x00000001;
2044 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
2047 * The following should be checked already.
2049 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
2050 return NT_STATUS_INTERNAL_ERROR;
2052 if (req->current_idx > max_idx) {
2053 return NT_STATUS_INTERNAL_ERROR;
2056 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
2057 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
2058 return NT_STATUS_INTERNAL_ERROR;
2060 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
2061 return NT_STATUS_INTERNAL_ERROR;
2064 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2065 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2069 case SMB2_OP_GETINFO:
2073 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
2074 if (req->smb1req->unread_bytes < min_dyn_size) {
2075 return NT_STATUS_INVALID_PARAMETER;
2084 * Now check the expected body size,
2085 * where the last byte might be in the
2088 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
2089 return NT_STATUS_INVALID_PARAMETER;
2091 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
2092 return NT_STATUS_INVALID_PARAMETER;
2095 inbody = SMBD_SMB2_IN_BODY_PTR(req);
2097 body_size = SVAL(inbody, 0x00);
2098 if (body_size != expected_body_size) {
2099 return NT_STATUS_INVALID_PARAMETER;
2102 return NT_STATUS_OK;
2105 bool smbXsrv_is_encrypted(uint8_t encryption_flags)
2107 return (!(encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)
2109 (encryption_flags & (SMBXSRV_PROCESSED_ENCRYPTED_PACKET |
2110 SMBXSRV_ENCRYPTION_DESIRED |
2111 SMBXSRV_ENCRYPTION_REQUIRED)));
2114 bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags)
2116 return ((encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET) &&
2117 (encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET));
2120 /* Set a flag if not already set, return true if set */
2121 bool smbXsrv_set_crypto_flag(uint8_t *flags, uint8_t flag)
2123 if ((flag == 0) || (*flags & flag)) {
2132 * Update encryption state tracking flags, this can be used to
2133 * determine whether whether the session or tcon is "encrypted".
2135 static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
2137 bool *update_session_globalp,
2138 bool *update_tcon_globalp)
2140 /* Default: assume unecrypted and unsigned */
2141 struct smbXsrv_session *session = req->session;
2142 struct smbXsrv_tcon *tcon = req->tcon;
2143 uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
2144 uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2145 bool update_session = false;
2146 bool update_tcon = false;
2148 if (req->was_encrypted && req->do_encryption) {
2149 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
2150 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2152 /* Unencrypted packet, can be signed */
2153 if (req->do_signing) {
2154 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2155 } else if (opcode == SMB2_OP_CANCEL) {
2156 /* Cancel requests are allowed to skip signing */
2157 sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2161 update_session |= smbXsrv_set_crypto_flag(
2162 &session->global->encryption_flags, encrypt_flag);
2163 update_session |= smbXsrv_set_crypto_flag(
2164 &session->global->signing_flags, sign_flag);
2167 update_tcon |= smbXsrv_set_crypto_flag(
2168 &tcon->global->encryption_flags, encrypt_flag);
2169 update_tcon |= smbXsrv_set_crypto_flag(
2170 &tcon->global->signing_flags, sign_flag);
2173 *update_session_globalp = update_session;
2174 *update_tcon_globalp = update_tcon;
2178 bool smbXsrv_is_signed(uint8_t signing_flags)
2181 * Signing is always enabled, so unless we got an unsigned
2182 * packet and at least one signed packet that was not
2183 * encrypted, the session or tcon is "signed".
2185 return (!(signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2186 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2189 bool smbXsrv_is_partially_signed(uint8_t signing_flags)
2191 return ((signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2192 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2195 static NTSTATUS smbd_smb2_request_dispatch_update_counts(
2196 struct smbd_smb2_request *req,
2199 struct smbXsrv_connection *xconn = req->xconn;
2200 const uint8_t *inhdr;
2201 uint16_t channel_sequence;
2202 uint8_t generation_wrap = 0;
2205 struct smbXsrv_open *op;
2206 bool update_open = false;
2207 NTSTATUS status = NT_STATUS_OK;
2209 SMB_ASSERT(!req->request_counters_updated);
2211 if (xconn->protocol < PROTOCOL_SMB2_22) {
2212 return NT_STATUS_OK;
2215 if (req->compat_chain_fsp == NULL) {
2216 return NT_STATUS_OK;
2219 op = req->compat_chain_fsp->op;
2221 return NT_STATUS_OK;
2224 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2225 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2226 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2228 cmp = channel_sequence - op->global->channel_sequence;
2231 * csn wrap. We need to watch out for long-running
2232 * requests that are still sitting on a previously
2233 * used csn. SMB2_OP_NOTIFY can take VERY long.
2235 generation_wrap += 1;
2238 if (abs(cmp) > INT16_MAX) {
2240 * [MS-SMB2] 3.3.5.2.10 - Verifying the Channel Sequence Number:
2242 * If the channel sequence number of the request and the one
2243 * known to the server are not equal, the channel sequence
2244 * number and outstanding request counts are only updated
2245 * "... if the unsigned difference using 16-bit arithmetic
2246 * between ChannelSequence and Open.ChannelSequence is less than
2247 * or equal to 0x7FFF ...".
2248 * Otherwise, an error is returned for the modifying
2249 * calls write, set_info, and ioctl.
2251 * There are currently two issues with the description:
2253 * * For the other calls, the document seems to imply
2254 * that processing continues without adapting the
2255 * counters (if the sequence numbers are not equal).
2257 * TODO: This needs clarification!
2259 * * Also, the behaviour if the difference is larger
2260 * than 0x7FFF is not clear. The document seems to
2261 * imply that if such a difference is reached,
2262 * the server starts to ignore the counters or
2263 * in the case of the modifying calls, return errors.
2265 * TODO: This needs clarification!
2267 * At this point Samba tries to be a little more
2268 * clever than the description in the MS-SMB2 document
2269 * by heuristically detecting and properly treating
2270 * a 16 bit overflow of the client-submitted sequence
2273 * If the stored channel sequence number is more than
2274 * 0x7FFF larger than the one from the request, then
2275 * the client-provided sequence number has likely
2276 * overflown. We treat this case as valid instead
2279 * The MS-SMB2 behaviour would be setting cmp = -1.
2284 if (flags & SMB2_HDR_FLAG_REPLAY_OPERATION) {
2285 if (cmp == 0 && op->pre_request_count == 0) {
2286 op->request_count += 1;
2287 req->request_counters_updated = true;
2288 } else if (cmp > 0 && op->pre_request_count == 0) {
2289 op->pre_request_count += op->request_count;
2290 op->request_count = 1;
2291 op->global->channel_sequence = channel_sequence;
2292 op->global->channel_generation += generation_wrap;
2294 req->request_counters_updated = true;
2295 } else if (modify_call) {
2296 return NT_STATUS_FILE_NOT_AVAILABLE;
2300 op->request_count += 1;
2301 req->request_counters_updated = true;
2302 } else if (cmp > 0) {
2303 op->pre_request_count += op->request_count;
2304 op->request_count = 1;
2305 op->global->channel_sequence = channel_sequence;
2306 op->global->channel_generation += generation_wrap;
2308 req->request_counters_updated = true;
2309 } else if (modify_call) {
2310 return NT_STATUS_FILE_NOT_AVAILABLE;
2313 req->channel_generation = op->global->channel_generation;
2316 status = smbXsrv_open_update(op);
2322 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
2324 struct smbXsrv_connection *xconn = req->xconn;
2325 const struct smbd_smb2_dispatch_table *call = NULL;
2326 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
2327 const uint8_t *inhdr;
2332 NTSTATUS session_status;
2333 uint32_t allowed_flags;
2334 NTSTATUS return_value;
2335 struct smbXsrv_session *x = NULL;
2336 bool signing_required = false;
2337 bool encryption_desired = false;
2338 bool encryption_required = false;
2340 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2342 DO_PROFILE_INC(request);
2344 SMB_ASSERT(!req->request_counters_updated);
2346 /* TODO: verify more things */
2348 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2349 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2350 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2351 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
2352 smb2_opcode_name(opcode),
2353 (unsigned long long)mid));
2355 if (xconn->protocol >= PROTOCOL_SMB2_02) {
2357 * once the protocol is negotiated
2358 * SMB2_OP_NEGPROT is not allowed anymore
2360 if (opcode == SMB2_OP_NEGPROT) {
2361 /* drop the connection */
2362 return NT_STATUS_INVALID_PARAMETER;
2366 * if the protocol is not negotiated yet
2367 * only SMB2_OP_NEGPROT is allowed.
2369 if (opcode != SMB2_OP_NEGPROT) {
2370 /* drop the connection */
2371 return NT_STATUS_INVALID_PARAMETER;
2376 * Check if the client provided a valid session id.
2378 * As some command don't require a valid session id
2379 * we defer the check of the session_status
2381 session_status = smbd_smb2_request_check_session(req);
2384 signing_required = x->global->signing_flags & SMBXSRV_SIGNING_REQUIRED;
2385 encryption_desired = x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
2386 encryption_required = x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
2389 req->async_internal = false;
2390 req->do_signing = false;
2391 if (opcode != SMB2_OP_SESSSETUP) {
2392 req->do_encryption = encryption_desired;
2394 req->do_encryption = false;
2396 req->was_encrypted = false;
2397 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
2398 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
2399 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
2401 if (x != NULL && x->global->session_wire_id != tf_session_id) {
2402 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2403 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
2404 (unsigned long long)x->global->session_wire_id,
2405 (unsigned long long)tf_session_id));
2407 * TODO: windows allows this...
2408 * should we drop the connection?
2410 * For now we just return ACCESS_DENIED
2411 * (Windows clients never trigger this)
2412 * and wait for an update of [MS-SMB2].
2414 return smbd_smb2_request_error(req,
2415 NT_STATUS_ACCESS_DENIED);
2418 req->was_encrypted = true;
2419 req->do_encryption = true;
2422 if (encryption_required && !req->was_encrypted) {
2423 req->do_encryption = true;
2424 return smbd_smb2_request_error(req,
2425 NT_STATUS_ACCESS_DENIED);
2428 call = smbd_smb2_call(opcode);
2430 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2433 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2434 SMB2_HDR_FLAG_SIGNED |
2436 if (xconn->protocol >= PROTOCOL_SMB3_11) {
2437 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2439 if (opcode == SMB2_OP_NEGPROT) {
2440 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11) {
2441 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2444 if (opcode == SMB2_OP_CANCEL) {
2445 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2447 if (xconn->protocol >= PROTOCOL_SMB2_22) {
2448 allowed_flags |= SMB2_HDR_FLAG_REPLAY_OPERATION;
2450 if ((flags & ~allowed_flags) != 0) {
2451 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2454 if (flags & SMB2_HDR_FLAG_CHAINED) {
2456 * This check is mostly for giving the correct error code
2457 * for compounded requests.
2459 if (!NT_STATUS_IS_OK(session_status)) {
2460 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2463 req->compat_chain_fsp = NULL;
2466 if (req->was_encrypted) {
2467 signing_required = false;
2468 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2469 struct smb2_signing_key *signing_key = NULL;
2473 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2474 * If the SMB2 header of the SMB2 NEGOTIATE
2475 * request has the SMB2_FLAGS_SIGNED bit set in the
2476 * Flags field, the server MUST fail the request
2477 * with STATUS_INVALID_PARAMETER.
2479 * Microsoft test tool checks this.
2482 if ((opcode == SMB2_OP_NEGPROT) &&
2483 (flags & SMB2_HDR_FLAG_SIGNED)) {
2484 status = NT_STATUS_INVALID_PARAMETER;
2486 status = NT_STATUS_USER_SESSION_DELETED;
2488 return smbd_smb2_request_error(req, status);
2491 signing_key = smbd_smb2_signing_key(x, xconn);
2494 * If we have a signing key, we should
2497 if (smb2_signing_key_valid(signing_key)) {
2498 req->do_signing = true;
2501 status = smb2_signing_check_pdu(signing_key,
2503 SMBD_SMB2_IN_HDR_IOV(req),
2504 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2505 if (!NT_STATUS_IS_OK(status)) {
2506 return smbd_smb2_request_error(req, status);
2510 * Now that we know the request was correctly signed
2511 * we have to sign the response too.
2513 req->do_signing = true;
2515 if (!NT_STATUS_IS_OK(session_status)) {
2516 return smbd_smb2_request_error(req, session_status);
2518 } else if (opcode == SMB2_OP_CANCEL) {
2519 /* Cancel requests are allowed to skip the signing */
2520 } else if (signing_required) {
2522 * If signing is required we try to sign
2523 * a possible error response
2525 req->do_signing = true;
2526 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2529 if (flags & SMB2_HDR_FLAG_CHAINED) {
2530 req->compound_related = true;
2533 if (call->need_session) {
2534 if (!NT_STATUS_IS_OK(session_status)) {
2535 return smbd_smb2_request_error(req, session_status);
2539 if (call->need_tcon) {
2540 SMB_ASSERT(call->need_session);
2543 * This call needs to be run as user.
2545 * smbd_smb2_request_check_tcon()
2546 * calls change_to_user() on success.
2547 * Which implies set_current_user_info()
2548 * and chdir_current_service().
2550 status = smbd_smb2_request_check_tcon(req);
2551 if (!NT_STATUS_IS_OK(status)) {
2552 return smbd_smb2_request_error(req, status);
2554 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
2555 encryption_desired = true;
2557 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
2558 encryption_required = true;
2560 if (encryption_required && !req->was_encrypted) {
2561 req->do_encryption = true;
2562 return smbd_smb2_request_error(req,
2563 NT_STATUS_ACCESS_DENIED);
2564 } else if (encryption_desired) {
2565 req->do_encryption = true;
2567 } else if (call->need_session) {
2568 struct auth_session_info *session_info = NULL;
2571 * Unless we also have need_tcon (see above),
2572 * we still need to call set_current_user_info().
2575 session_info = req->session->global->auth_session_info;
2576 if (session_info == NULL) {
2577 return NT_STATUS_INVALID_HANDLE;
2580 set_current_user_info(session_info->unix_info->sanitized_username,
2581 session_info->unix_info->unix_name,
2582 session_info->info->domain_name);
2586 bool update_session_global = false;
2587 bool update_tcon_global = false;
2589 smb2srv_update_crypto_flags(req, opcode,
2590 &update_session_global,
2591 &update_tcon_global);
2593 if (update_session_global) {
2594 status = smbXsrv_session_update(x);
2595 if (!NT_STATUS_IS_OK(status)) {
2596 return smbd_smb2_request_error(req, status);
2599 if (update_tcon_global) {
2600 status = smbXsrv_tcon_update(req->tcon);
2601 if (!NT_STATUS_IS_OK(status)) {
2602 return smbd_smb2_request_error(req, status);
2607 if (call->fileid_ofs != 0) {
2608 size_t needed = call->fileid_ofs + 16;
2609 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2610 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2611 uint64_t file_id_persistent;
2612 uint64_t file_id_volatile;
2613 struct files_struct *fsp;
2615 SMB_ASSERT(call->need_tcon);
2617 if (needed > body_size) {
2618 return smbd_smb2_request_error(req,
2619 NT_STATUS_INVALID_PARAMETER);
2622 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2623 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2625 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2627 if (!call->allow_invalid_fileid) {
2628 return smbd_smb2_request_error(req,
2629 NT_STATUS_FILE_CLOSED);
2632 if (file_id_persistent != UINT64_MAX) {
2633 return smbd_smb2_request_error(req,
2634 NT_STATUS_FILE_CLOSED);
2636 if (file_id_volatile != UINT64_MAX) {
2637 return smbd_smb2_request_error(req,
2638 NT_STATUS_FILE_CLOSED);
2643 status = smbd_smb2_request_dispatch_update_counts(req, call->modify);
2644 if (!NT_STATUS_IS_OK(status)) {
2645 return smbd_smb2_request_error(req, status);
2648 if (call->as_root) {
2649 SMB_ASSERT(call->fileid_ofs == 0);
2650 /* This call needs to be run as root */
2651 change_to_root_user();
2653 SMB_ASSERT(call->need_tcon);
2656 #define _INBYTES(_r) \
2657 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
2660 case SMB2_OP_NEGPROT:
2661 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
2662 req->profile, _INBYTES(req));
2663 return_value = smbd_smb2_request_process_negprot(req);
2666 case SMB2_OP_SESSSETUP:
2667 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
2668 req->profile, _INBYTES(req));
2669 return_value = smbd_smb2_request_process_sesssetup(req);
2672 case SMB2_OP_LOGOFF:
2673 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
2674 req->profile, _INBYTES(req));
2675 return_value = smbd_smb2_request_process_logoff(req);
2679 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
2680 req->profile, _INBYTES(req));
2681 return_value = smbd_smb2_request_process_tcon(req);
2685 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
2686 req->profile, _INBYTES(req));
2687 return_value = smbd_smb2_request_process_tdis(req);
2690 case SMB2_OP_CREATE:
2691 if (req->subreq == NULL) {
2692 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
2693 req->profile, _INBYTES(req));
2695 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
2697 return_value = smbd_smb2_request_process_create(req);
2701 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
2702 req->profile, _INBYTES(req));
2703 return_value = smbd_smb2_request_process_close(req);
2707 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
2708 req->profile, _INBYTES(req));
2709 return_value = smbd_smb2_request_process_flush(req);
2713 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
2714 req->profile, _INBYTES(req));
2715 return_value = smbd_smb2_request_process_read(req);
2719 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
2720 req->profile, _INBYTES(req));
2721 return_value = smbd_smb2_request_process_write(req);
2725 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
2726 req->profile, _INBYTES(req));
2727 return_value = smbd_smb2_request_process_lock(req);
2731 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
2732 req->profile, _INBYTES(req));
2733 return_value = smbd_smb2_request_process_ioctl(req);
2736 case SMB2_OP_CANCEL:
2737 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
2738 req->profile, _INBYTES(req));
2739 return_value = smbd_smb2_request_process_cancel(req);
2740 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
2743 * We don't need the request anymore cancel requests never
2746 * smbd_smb2_request_process_cancel() already called
2747 * DLIST_REMOVE(xconn->smb2.requests, req);
2753 case SMB2_OP_KEEPALIVE:
2754 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
2755 req->profile, _INBYTES(req));
2756 return_value = smbd_smb2_request_process_keepalive(req);
2759 case SMB2_OP_QUERY_DIRECTORY:
2760 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
2761 req->profile, _INBYTES(req));
2762 return_value = smbd_smb2_request_process_query_directory(req);
2765 case SMB2_OP_NOTIFY:
2766 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
2767 req->profile, _INBYTES(req));
2768 return_value = smbd_smb2_request_process_notify(req);
2771 case SMB2_OP_GETINFO:
2772 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
2773 req->profile, _INBYTES(req));
2774 return_value = smbd_smb2_request_process_getinfo(req);
2777 case SMB2_OP_SETINFO:
2778 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
2779 req->profile, _INBYTES(req));
2780 return_value = smbd_smb2_request_process_setinfo(req);
2784 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
2785 req->profile, _INBYTES(req));
2786 return_value = smbd_smb2_request_process_break(req);
2790 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2793 return return_value;
2796 static void smbd_smb2_request_reply_update_counts(struct smbd_smb2_request *req)
2798 struct smbXsrv_connection *xconn = req->xconn;
2799 const uint8_t *inhdr;
2800 uint16_t channel_sequence;
2801 struct smbXsrv_open *op;
2803 if (!req->request_counters_updated) {
2807 req->request_counters_updated = false;
2809 if (xconn->protocol < PROTOCOL_SMB2_22) {
2813 if (req->compat_chain_fsp == NULL) {
2817 op = req->compat_chain_fsp->op;
2822 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2823 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2825 if ((op->global->channel_sequence == channel_sequence) &&
2826 (op->global->channel_generation == req->channel_generation)) {
2827 SMB_ASSERT(op->request_count > 0);
2828 op->request_count -= 1;
2830 SMB_ASSERT(op->pre_request_count > 0);
2831 op->pre_request_count -= 1;
2835 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2837 struct smbXsrv_connection *xconn = req->xconn;
2839 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2840 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2841 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2846 TALLOC_FREE(req->async_te);
2848 /* MS-SMB2: 3.3.4.1 Sending Any Outgoing Message */
2849 smbd_smb2_request_reply_update_counts(req);
2851 if (req->do_encryption &&
2852 (firsttf->iov_len == 0) &&
2853 (req->first_key.length == 0) &&
2854 (req->session != NULL) &&
2855 (req->session->global->encryption_key_blob.length != 0))
2857 DATA_BLOB encryption_key = req->session->global->encryption_key_blob;
2859 uint64_t session_id = req->session->global->session_wire_id;
2860 uint64_t nonce_high;
2863 status = smb2_get_new_nonce(req->session,
2866 if (!NT_STATUS_IS_OK(status)) {
2871 * We need to place the SMB2_TRANSFORM header before the
2876 * we need to remember the encryption key
2877 * and defer the signing/encryption until
2878 * we are sure that we do not change
2881 req->first_key = data_blob_dup_talloc(req, encryption_key);
2882 if (req->first_key.data == NULL) {
2883 return NT_STATUS_NO_MEMORY;
2886 tf = talloc_zero_array(req, uint8_t,
2889 return NT_STATUS_NO_MEMORY;
2892 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2893 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2894 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2895 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2897 firsttf->iov_base = (void *)tf;
2898 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2901 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2902 (req->last_key.length > 0) &&
2903 (firsttf->iov_len == 0))
2905 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2906 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2907 struct smb2_signing_key key = {
2908 .blob = req->last_key,
2912 * As we are sure the header of the last request in the
2913 * compound chain will not change, we can to sign here
2914 * with the last signing key we remembered.
2916 status = smb2_signing_sign_pdu(&key,
2919 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2920 smb2_signing_key_destructor(&key);
2921 if (!NT_STATUS_IS_OK(status)) {
2925 if (req->last_key.length > 0) {
2926 data_blob_clear_free(&req->last_key);
2929 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
2930 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
2932 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2934 if (req->current_idx < req->out.vector_count) {
2936 * We must process the remaining compound
2937 * SMB2 requests before any new incoming SMB2
2938 * requests. This is because incoming SMB2
2939 * requests may include a cancel for a
2940 * compound request we haven't processed
2943 struct tevent_immediate *im = tevent_create_immediate(req);
2945 return NT_STATUS_NO_MEMORY;
2948 if (req->do_signing && firsttf->iov_len == 0) {
2949 struct smbXsrv_session *x = req->session;
2950 struct smb2_signing_key *signing_key =
2951 smbd_smb2_signing_key(x, xconn);
2954 * we need to remember the signing key
2955 * and defer the signing until
2956 * we are sure that we do not change
2959 req->last_key = data_blob_dup_talloc(req,
2961 if (req->last_key.data == NULL) {
2962 return NT_STATUS_NO_MEMORY;
2967 * smbd_smb2_request_dispatch() will redo the impersonation.
2968 * So we use req->xconn->client->raw_ev_ctx instead
2969 * of req->ev_ctx here.
2971 tevent_schedule_immediate(im,
2972 req->xconn->client->raw_ev_ctx,
2973 smbd_smb2_request_dispatch_immediate,
2975 return NT_STATUS_OK;
2978 if (req->compound_related) {
2979 req->compound_related = false;
2982 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2984 return NT_STATUS_INVALID_PARAMETER_MIX;
2987 /* Set credit for these operations (zero credits if this
2988 is a final reply for an async operation). */
2989 smb2_calculate_credits(req, req);
2992 * now check if we need to sign the current response
2994 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2995 status = smb2_signing_encrypt_pdu(req->first_key,
2996 xconn->smb2.server.cipher,
2998 req->out.vector_count - first_idx);
2999 if (!NT_STATUS_IS_OK(status)) {
3002 } else if (req->do_signing) {
3003 struct smbXsrv_session *x = req->session;
3004 struct smb2_signing_key *signing_key =
3005 smbd_smb2_signing_key(x, xconn);
3007 status = smb2_signing_sign_pdu(signing_key,
3010 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
3011 if (!NT_STATUS_IS_OK(status)) {
3015 if (req->first_key.length > 0) {
3016 data_blob_clear_free(&req->first_key);
3019 if (req->preauth != NULL) {
3020 gnutls_hash_hd_t hash_hnd = NULL;
3024 rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_SHA512);
3026 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3028 rc = gnutls_hash(hash_hnd,
3029 req->preauth->sha512_value,
3030 sizeof(req->preauth->sha512_value));
3032 gnutls_hash_deinit(hash_hnd, NULL);
3033 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3035 for (i = 1; i < req->in.vector_count; i++) {
3036 rc = gnutls_hash(hash_hnd,
3037 req->in.vector[i].iov_base,
3038 req->in.vector[i].iov_len);
3040 gnutls_hash_deinit(hash_hnd, NULL);
3041 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3045 gnutls_hash_deinit(hash_hnd, NULL);
3046 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3048 gnutls_hash_output(hash_hnd, req->preauth->sha512_value);
3050 rc = gnutls_hash(hash_hnd,
3051 req->preauth->sha512_value,
3052 sizeof(req->preauth->sha512_value));
3054 gnutls_hash_deinit(hash_hnd, NULL);
3055 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3057 for (i = 1; i < req->out.vector_count; i++) {
3058 rc = gnutls_hash(hash_hnd,
3059 req->out.vector[i].iov_base,
3060 req->out.vector[i].iov_len);
3062 gnutls_hash_deinit(hash_hnd, NULL);
3063 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3067 gnutls_hash_deinit(hash_hnd, req->preauth->sha512_value);
3069 req->preauth = NULL;
3072 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
3073 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
3074 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
3075 /* Dynamic part is NULL. Chop it off,
3076 We're going to send it via sendfile. */
3077 req->out.vector_count -= 1;
3081 * We're done with this request -
3082 * move it off the "being processed" queue.
3084 DLIST_REMOVE(xconn->smb2.requests, req);
3086 req->queue_entry.mem_ctx = req;
3087 req->queue_entry.vector = req->out.vector;
3088 req->queue_entry.count = req->out.vector_count;
3089 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry);
3090 xconn->smb2.send_queue_len++;
3092 status = smbd_smb2_flush_send_queue(xconn);
3093 if (!NT_STATUS_IS_OK(status)) {
3097 return NT_STATUS_OK;
3100 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
3102 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
3103 struct tevent_immediate *im,
3106 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
3107 struct smbd_smb2_request);
3108 struct smbXsrv_connection *xconn = req->xconn;
3113 if (DEBUGLEVEL >= 10) {
3114 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
3115 req->current_idx, req->in.vector_count));
3116 print_req_vectors(req);
3119 status = smbd_smb2_request_dispatch(req);
3120 if (!NT_STATUS_IS_OK(status)) {
3121 smbd_server_connection_terminate(xconn, nt_errstr(status));
3125 status = smbd_smb2_request_next_incoming(xconn);
3126 if (!NT_STATUS_IS_OK(status)) {
3127 smbd_server_connection_terminate(xconn, nt_errstr(status));
3132 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
3134 DATA_BLOB body, DATA_BLOB *dyn,
3135 const char *location)
3138 struct iovec *outbody_v;
3139 struct iovec *outdyn_v;
3140 uint32_t next_command_ofs;
3142 DEBUG(10,("smbd_smb2_request_done_ex: "
3143 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
3144 req->current_idx, nt_errstr(status), (unsigned int)body.length,
3146 (unsigned int)(dyn ? dyn->length : 0),
3149 if (body.length < 2) {
3150 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3153 if ((body.length % 2) != 0) {
3154 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3157 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3158 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
3159 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
3161 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
3162 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
3164 outbody_v->iov_base = (void *)body.data;
3165 outbody_v->iov_len = body.length;
3168 outdyn_v->iov_base = (void *)dyn->data;
3169 outdyn_v->iov_len = dyn->length;
3171 outdyn_v->iov_base = NULL;
3172 outdyn_v->iov_len = 0;
3176 * See if we need to recalculate the offset to the next response
3178 * Note that all responses may require padding (including the very last
3181 if (req->out.vector_count >= (2 * SMBD_SMB2_NUM_IOV_PER_REQ)) {
3182 next_command_ofs = SMB2_HDR_BODY;
3183 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
3184 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
3187 if ((next_command_ofs % 8) != 0) {
3188 size_t pad_size = 8 - (next_command_ofs % 8);
3189 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
3191 * if the dyn buffer is empty
3192 * we can use it to add padding
3196 pad = talloc_zero_array(req,
3199 return smbd_smb2_request_error(req,
3200 NT_STATUS_NO_MEMORY);
3203 outdyn_v->iov_base = (void *)pad;
3204 outdyn_v->iov_len = pad_size;
3207 * For now we copy the dynamic buffer
3208 * and add the padding to the new buffer
3215 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
3216 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
3218 new_size = old_size + pad_size;
3219 new_dyn = talloc_zero_array(req,
3221 if (new_dyn == NULL) {
3222 return smbd_smb2_request_error(req,
3223 NT_STATUS_NO_MEMORY);
3226 memcpy(new_dyn, old_dyn, old_size);
3227 memset(new_dyn + old_size, 0, pad_size);
3229 outdyn_v->iov_base = (void *)new_dyn;
3230 outdyn_v->iov_len = new_size;
3232 next_command_ofs += pad_size;
3235 if ((req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) >= req->out.vector_count) {
3236 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
3238 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
3240 return smbd_smb2_request_reply(req);
3243 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
3246 const char *location)
3248 struct smbXsrv_connection *xconn = req->xconn;
3251 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3252 size_t unread_bytes = smbd_smb2_unread_bytes(req);
3254 DBG_NOTICE("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| "
3255 "at %s\n", req->current_idx, nt_errstr(status),
3256 info ? " +info" : "", location);
3259 /* Recvfile error. Drain incoming socket. */
3263 ret = drain_socket(xconn->transport.sock, unread_bytes);
3264 if (ret != unread_bytes) {
3268 error = NT_STATUS_IO_DEVICE_ERROR;
3270 error = map_nt_error_from_unix_common(errno);
3273 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
3274 "ret[%u] errno[%d] => %s\n",
3275 (unsigned)unread_bytes,
3276 (unsigned)ret, errno, nt_errstr(error)));
3281 body.data = outhdr + SMB2_HDR_BODY;
3283 SSVAL(body.data, 0, 9);
3286 SIVAL(body.data, 0x04, info->length);
3288 /* Allocated size of req->out.vector[i].iov_base
3289 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
3290 * 1 byte without having to do an alloc.
3293 info->data = ((uint8_t *)outhdr) +
3294 OUTVEC_ALLOC_SIZE - 1;
3296 SCVAL(info->data, 0, 0);
3300 * Note: Even if there is an error, continue to process the request.
3304 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
3308 struct smbd_smb2_send_break_state {
3309 struct smbd_smb2_send_queue queue_entry;
3310 uint8_t nbt_hdr[NBT_HDR_SIZE];
3311 uint8_t tf[SMB2_TF_HDR_SIZE];
3312 uint8_t hdr[SMB2_HDR_BODY];
3313 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
3317 static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
3318 struct smbXsrv_session *session,
3319 struct smbXsrv_tcon *tcon,
3320 const uint8_t *body,
3323 struct smbd_smb2_send_break_state *state;
3324 bool do_encryption = false;
3325 uint64_t session_wire_id = 0;
3326 uint64_t nonce_high = 0;
3327 uint64_t nonce_low = 0;
3332 if (session != NULL) {
3333 session_wire_id = session->global->session_wire_id;
3334 do_encryption = session->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
3335 if (tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
3336 do_encryption = true;
3340 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
3343 state = talloc_zero_size(xconn, statelen);
3344 if (state == NULL) {
3345 return NT_STATUS_NO_MEMORY;
3347 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
3349 if (do_encryption) {
3350 status = smb2_get_new_nonce(session,
3353 if (!NT_STATUS_IS_OK(status)) {
3358 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
3359 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
3360 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
3361 SBVAL(state->tf, SMB2_TF_SESSION_ID, session_wire_id);
3363 SIVAL(state->hdr, 0, SMB2_MAGIC);
3364 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
3365 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
3366 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
3367 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
3368 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
3369 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
3370 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
3371 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
3372 SIVAL(state->hdr, SMB2_HDR_PID, 0);
3373 SIVAL(state->hdr, SMB2_HDR_TID, 0);
3374 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
3375 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
3377 state->vector[0] = (struct iovec) {
3378 .iov_base = state->nbt_hdr,
3379 .iov_len = sizeof(state->nbt_hdr)
3382 if (do_encryption) {
3383 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3384 .iov_base = state->tf,
3385 .iov_len = sizeof(state->tf)
3388 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3394 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
3395 .iov_base = state->hdr,
3396 .iov_len = sizeof(state->hdr)
3399 memcpy(state->body, body, body_len);
3401 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
3402 .iov_base = state->body,
3403 .iov_len = body_len /* no sizeof(state->body) .. :-) */
3407 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
3410 ok = smb2_setup_nbt_length(state->vector,
3411 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
3413 return NT_STATUS_INVALID_PARAMETER_MIX;
3416 if (do_encryption) {
3417 DATA_BLOB encryption_key = session->global->encryption_key_blob;
3419 status = smb2_signing_encrypt_pdu(encryption_key,
3420 xconn->smb2.server.cipher,
3421 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
3422 SMBD_SMB2_NUM_IOV_PER_REQ);
3423 if (!NT_STATUS_IS_OK(status)) {
3428 state->queue_entry.mem_ctx = state;
3429 state->queue_entry.vector = state->vector;
3430 state->queue_entry.count = ARRAY_SIZE(state->vector);
3431 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
3432 xconn->smb2.send_queue_len++;
3434 status = smbd_smb2_flush_send_queue(xconn);
3435 if (!NT_STATUS_IS_OK(status)) {
3439 return NT_STATUS_OK;
3442 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_connection *xconn,
3443 struct smbXsrv_session *session,
3444 struct smbXsrv_tcon *tcon,
3445 struct smbXsrv_open *op,
3446 uint8_t oplock_level)
3450 SSVAL(body, 0x00, sizeof(body));
3451 SCVAL(body, 0x02, oplock_level);
3452 SCVAL(body, 0x03, 0); /* reserved */
3453 SIVAL(body, 0x04, 0); /* reserved */
3454 SBVAL(body, 0x08, op->global->open_persistent_id);
3455 SBVAL(body, 0x10, op->global->open_volatile_id);
3457 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3460 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_connection *xconn,
3462 uint32_t lease_flags,
3463 struct smb2_lease_key *lease_key,
3464 uint32_t current_lease_state,
3465 uint32_t new_lease_state)
3469 SSVAL(body, 0x00, sizeof(body));
3470 SSVAL(body, 0x02, new_epoch);
3471 SIVAL(body, 0x04, lease_flags);
3472 SBVAL(body, 0x08, lease_key->data[0]);
3473 SBVAL(body, 0x10, lease_key->data[1]);
3474 SIVAL(body, 0x18, current_lease_state);
3475 SIVAL(body, 0x1c, new_lease_state);
3476 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
3477 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
3478 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
3480 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3483 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
3487 uint64_t file_id_persistent;
3488 uint64_t file_id_volatile;
3489 struct smbXsrv_open *op = NULL;
3490 struct files_struct *fsp = NULL;
3491 const uint8_t *body = NULL;
3494 * This is only called with a pktbuf
3495 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
3499 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
3500 /* Transform header. Cannot recvfile. */
3503 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
3504 /* Not SMB2. Normal error path will cope. */
3507 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
3508 /* Not SMB2. Normal error path will cope. */
3511 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
3512 /* Needs to be a WRITE. */
3515 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
3516 /* Chained. Cannot recvfile. */
3519 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
3520 if (flags & SMB2_HDR_FLAG_CHAINED) {
3521 /* Chained. Cannot recvfile. */
3524 if (flags & SMB2_HDR_FLAG_SIGNED) {
3525 /* Signed. Cannot recvfile. */
3529 body = &state->pktbuf[SMB2_HDR_BODY];
3531 file_id_persistent = BVAL(body, 0x10);
3532 file_id_volatile = BVAL(body, 0x18);
3534 status = smb2srv_open_lookup(state->req->xconn,
3539 if (!NT_STATUS_IS_OK(status)) {
3547 if (fsp->conn == NULL) {
3551 if (IS_IPC(fsp->conn)) {
3554 if (IS_PRINT(fsp->conn)) {
3557 if (fsp->base_fsp != NULL) {
3561 DEBUG(10,("Doing recvfile write len = %u\n",
3562 (unsigned int)(state->pktfull - state->pktlen)));
3567 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
3569 struct smbd_server_connection *sconn = xconn->client->sconn;
3570 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3571 size_t max_send_queue_len;
3572 size_t cur_send_queue_len;
3574 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3576 * we're not supposed to do any io
3578 return NT_STATUS_OK;
3581 if (state->req != NULL) {
3583 * if there is already a tstream_readv_pdu
3584 * pending, we are done.
3586 return NT_STATUS_OK;
3589 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
3590 cur_send_queue_len = xconn->smb2.send_queue_len;
3592 if (cur_send_queue_len > max_send_queue_len) {
3594 * if we have a lot of requests to send,
3595 * we wait until they are on the wire until we
3596 * ask for the next request.
3598 return NT_STATUS_OK;
3601 /* ask for the next request */
3602 ZERO_STRUCTP(state);
3603 state->req = smbd_smb2_request_allocate(xconn);
3604 if (state->req == NULL) {
3605 return NT_STATUS_NO_MEMORY;
3607 state->req->sconn = sconn;
3608 state->req->xconn = xconn;
3609 state->min_recv_size = lp_min_receive_file_size();
3611 TEVENT_FD_READABLE(xconn->transport.fde);
3613 return NT_STATUS_OK;
3616 void smbd_smb2_process_negprot(struct smbXsrv_connection *xconn,
3617 uint64_t expected_seq_low,
3618 const uint8_t *inpdu, size_t size)
3620 struct smbd_server_connection *sconn = xconn->client->sconn;
3622 struct smbd_smb2_request *req = NULL;
3624 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3625 (unsigned int)size));
3627 status = smbd_initialize_smb2(xconn, expected_seq_low);
3628 if (!NT_STATUS_IS_OK(status)) {
3629 smbd_server_connection_terminate(xconn, nt_errstr(status));
3633 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
3634 if (!NT_STATUS_IS_OK(status)) {
3635 smbd_server_connection_terminate(xconn, nt_errstr(status));
3639 status = smbd_smb2_request_validate(req);
3640 if (!NT_STATUS_IS_OK(status)) {
3641 smbd_server_connection_terminate(xconn, nt_errstr(status));
3645 status = smbd_smb2_request_setup_out(req);
3646 if (!NT_STATUS_IS_OK(status)) {
3647 smbd_server_connection_terminate(xconn, nt_errstr(status));
3653 * this was already counted at the SMB1 layer =>
3654 * smbd_smb2_request_dispatch() should not count it twice.
3656 if (profile_p->values.request_stats.count > 0) {
3657 profile_p->values.request_stats.count--;
3660 status = smbd_smb2_request_dispatch(req);
3661 if (!NT_STATUS_IS_OK(status)) {
3662 smbd_server_connection_terminate(xconn, nt_errstr(status));
3666 status = smbd_smb2_request_next_incoming(xconn);
3667 if (!NT_STATUS_IS_OK(status)) {
3668 smbd_server_connection_terminate(xconn, nt_errstr(status));
3672 sconn->num_requests++;
3675 static int socket_error_from_errno(int ret,
3689 if (sys_errno == 0) {
3693 if (sys_errno == EINTR) {
3698 if (sys_errno == EINPROGRESS) {
3703 if (sys_errno == EAGAIN) {
3708 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3709 if (sys_errno == ENOMEM) {
3715 #if EWOULDBLOCK != EAGAIN
3716 if (sys_errno == EWOULDBLOCK) {
3726 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3733 if (xconn->smb2.send_queue == NULL) {
3734 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3735 return NT_STATUS_OK;
3738 while (xconn->smb2.send_queue != NULL) {
3739 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3742 if (e->sendfile_header != NULL) {
3747 status = NT_STATUS_INTERNAL_ERROR;
3749 for (i=0; i < e->count; i++) {
3750 size += e->vector[i].iov_len;
3753 if (size <= e->sendfile_header->length) {
3754 buf = e->sendfile_header->data;
3756 buf = talloc_array(e->mem_ctx, uint8_t, size);
3758 return NT_STATUS_NO_MEMORY;
3763 for (i=0; i < e->count; i++) {
3765 e->vector[i].iov_base,
3766 e->vector[i].iov_len);
3767 size += e->vector[i].iov_len;
3770 e->sendfile_header->data = buf;
3771 e->sendfile_header->length = size;
3772 e->sendfile_status = &status;
3775 xconn->smb2.send_queue_len--;
3776 DLIST_REMOVE(xconn->smb2.send_queue, e);
3778 * This triggers the sendfile path via
3781 talloc_free(e->mem_ctx);
3783 if (!NT_STATUS_IS_OK(status)) {
3789 ret = writev(xconn->transport.sock, e->vector, e->count);
3791 /* propagate end of file */
3792 return NT_STATUS_INTERNAL_ERROR;
3794 err = socket_error_from_errno(ret, errno, &retry);
3797 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3798 return NT_STATUS_OK;
3801 return map_nt_error_from_unix_common(err);
3804 ok = iov_advance(&e->vector, &e->count, ret);
3806 return NT_STATUS_INTERNAL_ERROR;
3810 /* we have more to write */
3811 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3812 return NT_STATUS_OK;
3815 xconn->smb2.send_queue_len--;
3816 DLIST_REMOVE(xconn->smb2.send_queue, e);
3817 talloc_free(e->mem_ctx);
3821 * Restart reads if we were blocked on
3822 * draining the send queue.
3825 status = smbd_smb2_request_next_incoming(xconn);
3826 if (!NT_STATUS_IS_OK(status)) {
3830 return NT_STATUS_OK;
3833 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3836 struct smbd_server_connection *sconn = xconn->client->sconn;
3837 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3838 struct smbd_smb2_request *req = NULL;
3839 size_t min_recvfile_size = UINT32_MAX;
3846 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3848 * we're not supposed to do any io
3850 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3851 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3852 return NT_STATUS_OK;
3855 if (fde_flags & TEVENT_FD_WRITE) {
3856 status = smbd_smb2_flush_send_queue(xconn);
3857 if (!NT_STATUS_IS_OK(status)) {
3862 if (!(fde_flags & TEVENT_FD_READ)) {
3863 return NT_STATUS_OK;
3866 if (state->req == NULL) {
3867 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3868 return NT_STATUS_OK;
3872 if (!state->hdr.done) {
3873 state->hdr.done = true;
3875 state->vector.iov_base = (void *)state->hdr.nbt;
3876 state->vector.iov_len = NBT_HDR_SIZE;
3879 ret = readv(xconn->transport.sock, &state->vector, 1);
3881 /* propagate end of file */
3882 return NT_STATUS_END_OF_FILE;
3884 err = socket_error_from_errno(ret, errno, &retry);
3887 TEVENT_FD_READABLE(xconn->transport.fde);
3888 return NT_STATUS_OK;
3891 return map_nt_error_from_unix_common(err);
3894 if (ret < state->vector.iov_len) {
3896 base = (uint8_t *)state->vector.iov_base;
3898 state->vector.iov_base = (void *)base;
3899 state->vector.iov_len -= ret;
3900 /* we have more to read */
3901 TEVENT_FD_READABLE(xconn->transport.fde);
3902 return NT_STATUS_OK;
3905 if (state->pktlen > 0) {
3906 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3908 * Not a possible receivefile write.
3909 * Read the rest of the data.
3911 state->doing_receivefile = false;
3913 state->pktbuf = talloc_realloc(state->req,
3917 if (state->pktbuf == NULL) {
3918 return NT_STATUS_NO_MEMORY;
3921 state->vector.iov_base = (void *)(state->pktbuf +
3923 state->vector.iov_len = (state->pktfull -
3926 state->pktlen = state->pktfull;
3931 * Either this is a receivefile write so we've
3932 * done a short read, or if not we have all the data.
3938 * Now we analyze the NBT header
3940 if (state->hdr.nbt[0] != 0x00) {
3941 state->min_recv_size = 0;
3943 state->pktfull = smb2_len(state->hdr.nbt);
3944 if (state->pktfull == 0) {
3948 if (state->min_recv_size != 0) {
3949 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3950 min_recvfile_size += state->min_recv_size;
3953 if (state->pktfull > min_recvfile_size) {
3955 * Might be a receivefile write. Read the SMB2 HEADER +
3956 * SMB2_WRITE header first. Set 'doing_receivefile'
3957 * as we're *attempting* receivefile write. If this
3958 * turns out not to be a SMB2_WRITE request or otherwise
3959 * not suitable then we'll just read the rest of the data
3960 * the next time this function is called.
3962 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3963 state->doing_receivefile = true;
3965 state->pktlen = state->pktfull;
3968 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3969 if (state->pktbuf == NULL) {
3970 return NT_STATUS_NO_MEMORY;
3973 state->vector.iov_base = (void *)state->pktbuf;
3974 state->vector.iov_len = state->pktlen;
3980 if (state->hdr.nbt[0] != 0x00) {
3981 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3982 state->hdr.nbt[0]));
3985 ZERO_STRUCTP(state);
3987 state->min_recv_size = lp_min_receive_file_size();
3995 req->request_time = timeval_current();
3996 now = timeval_to_nttime(&req->request_time);
3998 status = smbd_smb2_inbuf_parse_compound(xconn,
4004 &req->in.vector_count);
4005 if (!NT_STATUS_IS_OK(status)) {
4009 if (state->doing_receivefile) {
4010 req->smb1req = talloc_zero(req, struct smb_request);
4011 if (req->smb1req == NULL) {
4012 return NT_STATUS_NO_MEMORY;
4014 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
4017 ZERO_STRUCTP(state);
4019 req->current_idx = 1;
4021 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
4022 req->current_idx, req->in.vector_count));
4024 status = smbd_smb2_request_validate(req);
4025 if (!NT_STATUS_IS_OK(status)) {
4029 status = smbd_smb2_request_setup_out(req);
4030 if (!NT_STATUS_IS_OK(status)) {
4034 status = smbd_smb2_request_dispatch(req);
4035 if (!NT_STATUS_IS_OK(status)) {
4039 sconn->num_requests++;
4041 /* The timeout_processing function isn't run nearly
4042 often enough to implement 'max log size' without
4043 overrunning the size of the file by many megabytes.
4044 This is especially true if we are running at debug
4045 level 10. Checking every 50 SMB2s is a nice
4046 tradeoff of performance vs log file size overrun. */
4048 if ((sconn->num_requests % 50) == 0 &&
4049 need_to_check_log_size()) {
4050 change_to_root_user();
4054 status = smbd_smb2_request_next_incoming(xconn);
4055 if (!NT_STATUS_IS_OK(status)) {
4059 return NT_STATUS_OK;
4062 static void smbd_smb2_connection_handler(struct tevent_context *ev,
4063 struct tevent_fd *fde,
4067 struct smbXsrv_connection *xconn =
4068 talloc_get_type_abort(private_data,
4069 struct smbXsrv_connection);
4072 status = smbd_smb2_io_handler(xconn, flags);
4073 if (!NT_STATUS_IS_OK(status)) {
4074 smbd_server_connection_terminate(xconn, nt_errstr(status));