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 "lib/crypto/sha512.h"
35 static void smbd_smb2_connection_handler(struct tevent_context *ev,
36 struct tevent_fd *fde,
39 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn);
41 static const struct smbd_smb2_dispatch_table {
48 bool allow_invalid_fileid;
50 } smbd_smb2_table[] = {
51 #define _OP(o) .opcode = o, .name = #o
56 _OP(SMB2_OP_SESSSETUP),
66 * This call needs to be run as root.
68 * smbd_smb2_request_process_tcon()
69 * calls make_connection_snum(), which will call
70 * change_to_user(), when needed.
105 .need_session = true,
110 .need_session = true,
113 .allow_invalid_fileid = true,
119 _OP(SMB2_OP_KEEPALIVE),
122 _OP(SMB2_OP_QUERY_DIRECTORY),
123 .need_session = true,
128 .need_session = true,
132 _OP(SMB2_OP_GETINFO),
133 .need_session = true,
137 _OP(SMB2_OP_SETINFO),
138 .need_session = true,
144 .need_session = true,
149 * as LEASE breaks does not
155 const char *smb2_opcode_name(uint16_t opcode)
157 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
158 return "Bad SMB2 opcode";
160 return smbd_smb2_table[opcode].name;
163 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
165 const struct smbd_smb2_dispatch_table *ret = NULL;
167 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
171 ret = &smbd_smb2_table[opcode];
173 SMB_ASSERT(ret->opcode == opcode);
178 static void print_req_vectors(const struct smbd_smb2_request *req)
182 for (i = 0; i < req->in.vector_count; i++) {
183 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
185 (unsigned int)req->in.vector[i].iov_len);
187 for (i = 0; i < req->out.vector_count; i++) {
188 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
190 (unsigned int)req->out.vector[i].iov_len);
194 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
196 if (size < (4 + SMB2_HDR_BODY)) {
200 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
207 static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn,
208 uint64_t expected_seq_low)
210 TALLOC_FREE(xconn->transport.fde);
212 xconn->smb2.credits.seq_low = expected_seq_low;
213 xconn->smb2.credits.seq_range = 1;
214 xconn->smb2.credits.granted = 1;
215 xconn->smb2.credits.max = lp_smb2_max_credits();
216 xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
217 xconn->smb2.credits.max);
218 if (xconn->smb2.credits.bitmap == NULL) {
219 return NT_STATUS_NO_MEMORY;
222 xconn->transport.fde = tevent_add_fd(xconn->ev_ctx,
224 xconn->transport.sock,
226 smbd_smb2_connection_handler,
228 if (xconn->transport.fde == NULL) {
229 return NT_STATUS_NO_MEMORY;
232 /* Ensure child is set to non-blocking mode */
233 set_blocking(xconn->transport.sock, false);
237 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
238 #define _smb2_setlen(_buf,len) do { \
239 uint8_t *buf = (uint8_t *)_buf; \
241 buf[1] = ((len)&0xFF0000)>>16; \
242 buf[2] = ((len)&0xFF00)>>8; \
243 buf[3] = (len)&0xFF; \
246 static bool smb2_setup_nbt_length(struct iovec *vector, int count)
254 len = iov_buflen(vector+1, count-1);
256 if ((len == -1) || (len > 0xFFFFFF)) {
260 _smb2_setlen(vector[0].iov_base, len);
264 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
266 if (req->first_key.length > 0) {
267 data_blob_clear_free(&req->first_key);
269 if (req->last_key.length > 0) {
270 data_blob_clear_free(&req->last_key);
275 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
277 TALLOC_CTX *mem_pool;
278 struct smbd_smb2_request *req;
281 /* Enable this to find subtle valgrind errors. */
282 mem_pool = talloc_init("smbd_smb2_request_allocate");
284 mem_pool = talloc_tos();
286 if (mem_pool == NULL) {
290 req = talloc_zero(mem_pool, struct smbd_smb2_request);
292 talloc_free(mem_pool);
295 talloc_reparent(mem_pool, mem_ctx, req);
297 TALLOC_FREE(mem_pool);
300 req->last_session_id = UINT64_MAX;
301 req->last_tid = UINT32_MAX;
303 talloc_set_destructor(req, smbd_smb2_request_destructor);
308 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
312 struct smbd_smb2_request *req,
316 TALLOC_CTX *mem_ctx = req;
320 uint8_t *first_hdr = buf;
321 size_t verified_buflen = 0;
326 * Note: index '0' is reserved for the transport protocol
328 iov = req->in._vector;
330 while (taken < buflen) {
331 size_t len = buflen - taken;
332 uint8_t *hdr = first_hdr + taken;
335 size_t next_command_ofs;
337 uint8_t *body = NULL;
340 struct iovec *iov_alloc = NULL;
342 if (iov != req->in._vector) {
346 if (verified_buflen > taken) {
347 len = verified_buflen - taken;
354 DEBUG(10, ("%d bytes left, expected at least %d\n",
358 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
359 struct smbXsrv_session *s = NULL;
361 struct iovec tf_iov[2];
365 if (xconn->protocol < PROTOCOL_SMB2_24) {
366 DEBUG(10, ("Got SMB2_TRANSFORM header, "
367 "but dialect[0x%04X] is used\n",
368 xconn->smb2.server.dialect));
372 if (xconn->smb2.server.cipher == 0) {
373 DEBUG(10, ("Got SMB2_TRANSFORM header, "
374 "but not negotiated "
375 "client[0x%08X] server[0x%08X]\n",
376 xconn->smb2.client.capabilities,
377 xconn->smb2.server.capabilities));
381 if (len < SMB2_TF_HDR_SIZE) {
382 DEBUG(1, ("%d bytes left, expected at least %d\n",
383 (int)len, SMB2_TF_HDR_SIZE));
387 tf_len = SMB2_TF_HDR_SIZE;
390 hdr = first_hdr + taken;
391 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
392 uid = BVAL(tf, SMB2_TF_SESSION_ID);
394 if (len < SMB2_TF_HDR_SIZE + enc_len) {
395 DEBUG(1, ("%d bytes left, expected at least %d\n",
397 (int)(SMB2_TF_HDR_SIZE + enc_len)));
401 status = smb2srv_session_lookup_conn(xconn, uid, now,
404 DEBUG(1, ("invalid session[%llu] in "
405 "SMB2_TRANSFORM header\n",
406 (unsigned long long)uid));
407 TALLOC_FREE(iov_alloc);
408 return NT_STATUS_USER_SESSION_DELETED;
411 tf_iov[0].iov_base = (void *)tf;
412 tf_iov[0].iov_len = tf_len;
413 tf_iov[1].iov_base = (void *)hdr;
414 tf_iov[1].iov_len = enc_len;
416 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
417 xconn->smb2.server.cipher,
419 if (!NT_STATUS_IS_OK(status)) {
420 TALLOC_FREE(iov_alloc);
424 verified_buflen = taken + enc_len;
429 * We need the header plus the body length field
432 if (len < SMB2_HDR_BODY + 2) {
433 DEBUG(10, ("%d bytes left, expected at least %d\n",
434 (int)len, SMB2_HDR_BODY));
437 if (IVAL(hdr, 0) != SMB2_MAGIC) {
438 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
442 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
443 DEBUG(10, ("Got HDR len %d, expected %d\n",
444 SVAL(hdr, 4), SMB2_HDR_BODY));
449 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
450 body_size = SVAL(hdr, SMB2_HDR_BODY);
452 if (next_command_ofs != 0) {
453 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
456 if (next_command_ofs > full_size) {
459 full_size = next_command_ofs;
466 if (body_size > (full_size - SMB2_HDR_BODY)) {
468 * let the caller handle the error
470 body_size = full_size - SMB2_HDR_BODY;
472 body = hdr + SMB2_HDR_BODY;
473 dyn = body + body_size;
474 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
476 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
477 struct iovec *iov_tmp = NULL;
479 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
482 SMBD_SMB2_NUM_IOV_PER_REQ);
483 if (iov_tmp == NULL) {
484 TALLOC_FREE(iov_alloc);
485 return NT_STATUS_NO_MEMORY;
488 if (iov_alloc == NULL) {
491 sizeof(req->in._vector));
497 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
499 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
500 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
501 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
502 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
503 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
504 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
505 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
506 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
516 if (iov != req->in._vector) {
519 return NT_STATUS_INVALID_PARAMETER;
522 static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
523 const uint8_t *_inpdu, size_t size,
524 struct smbd_smb2_request **_req)
526 struct smbd_server_connection *sconn = xconn->client->sconn;
527 struct smbd_smb2_request *req;
528 uint32_t protocol_version;
529 uint8_t *inpdu = NULL;
530 const uint8_t *inhdr = NULL;
532 uint32_t next_command_ofs;
536 if (size < (SMB2_HDR_BODY + 2)) {
537 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
538 return NT_STATUS_INVALID_PARAMETER;
543 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
544 if (protocol_version != SMB2_MAGIC) {
545 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
547 return NT_STATUS_INVALID_PARAMETER;
550 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
551 if (cmd != SMB2_OP_NEGPROT) {
552 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
554 return NT_STATUS_INVALID_PARAMETER;
557 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
558 if (next_command_ofs != 0) {
559 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
561 return NT_STATUS_INVALID_PARAMETER;
564 req = smbd_smb2_request_allocate(xconn);
566 return NT_STATUS_NO_MEMORY;
571 inpdu = talloc_memdup(req, _inpdu, size);
573 return NT_STATUS_NO_MEMORY;
576 req->request_time = timeval_current();
577 now = timeval_to_nttime(&req->request_time);
579 status = smbd_smb2_inbuf_parse_compound(xconn,
583 req, &req->in.vector,
584 &req->in.vector_count);
585 if (!NT_STATUS_IS_OK(status)) {
590 req->current_idx = 1;
596 static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
597 uint64_t message_id, uint64_t seq_id)
599 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
603 seq_tmp = xconn->smb2.credits.seq_low;
604 if (seq_id < seq_tmp) {
605 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
606 "%llu (sequence id %llu) "
607 "(granted = %u, low = %llu, range = %u)\n",
608 (unsigned long long)message_id,
609 (unsigned long long)seq_id,
610 (unsigned int)xconn->smb2.credits.granted,
611 (unsigned long long)xconn->smb2.credits.seq_low,
612 (unsigned int)xconn->smb2.credits.seq_range));
616 seq_tmp += xconn->smb2.credits.seq_range;
617 if (seq_id >= seq_tmp) {
618 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
619 "%llu (sequence id %llu) "
620 "(granted = %u, low = %llu, range = %u)\n",
621 (unsigned long long)message_id,
622 (unsigned long long)seq_id,
623 (unsigned int)xconn->smb2.credits.granted,
624 (unsigned long long)xconn->smb2.credits.seq_low,
625 (unsigned int)xconn->smb2.credits.seq_range));
629 offset = seq_id % xconn->smb2.credits.max;
631 if (bitmap_query(credits_bm, offset)) {
632 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
633 "%llu (sequence id %llu) "
634 "(granted = %u, low = %llu, range = %u) "
636 (unsigned long long)message_id,
637 (unsigned long long)seq_id,
638 (unsigned int)xconn->smb2.credits.granted,
639 (unsigned long long)xconn->smb2.credits.seq_low,
640 (unsigned int)xconn->smb2.credits.seq_range,
645 /* Mark the message_ids as seen in the bitmap. */
646 bitmap_set(credits_bm, offset);
648 if (seq_id != xconn->smb2.credits.seq_low) {
653 * Move the window forward by all the message_id's
656 while (bitmap_query(credits_bm, offset)) {
657 DEBUG(10,("smb2_validate_sequence_number: clearing "
658 "id %llu (position %u) from bitmap\n",
659 (unsigned long long)(xconn->smb2.credits.seq_low),
661 bitmap_clear(credits_bm, offset);
663 xconn->smb2.credits.seq_low += 1;
664 xconn->smb2.credits.seq_range -= 1;
665 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
671 static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
672 const uint8_t *inhdr)
674 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
675 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
676 uint16_t credit_charge = 1;
679 if (opcode == SMB2_OP_CANCEL) {
680 /* SMB2_CANCEL requests by definition resend messageids. */
684 if (xconn->smb2.credits.multicredit) {
685 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
686 credit_charge = MAX(credit_charge, 1);
689 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
690 "credits_granted %llu, "
691 "seqnum low/range: %llu/%llu\n",
692 (unsigned long long) message_id,
693 (unsigned long long) credit_charge,
694 (unsigned long long) xconn->smb2.credits.granted,
695 (unsigned long long) xconn->smb2.credits.seq_low,
696 (unsigned long long) xconn->smb2.credits.seq_range));
698 if (xconn->smb2.credits.granted < credit_charge) {
699 DEBUG(0, ("smb2_validate_message_id: client used more "
700 "credits than granted, mid %llu, charge %llu, "
701 "credits_granted %llu, "
702 "seqnum low/range: %llu/%llu\n",
703 (unsigned long long) message_id,
704 (unsigned long long) credit_charge,
705 (unsigned long long) xconn->smb2.credits.granted,
706 (unsigned long long) xconn->smb2.credits.seq_low,
707 (unsigned long long) xconn->smb2.credits.seq_range));
712 * now check the message ids
714 * for multi-credit requests we need to check all current mid plus
715 * the implicit mids caused by the credit charge
716 * e.g. current mid = 15, charge 5 => mark 15-19 as used
719 for (i = 0; i <= (credit_charge-1); i++) {
720 uint64_t id = message_id + i;
723 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
724 (unsigned long long)message_id,
726 (unsigned long long)id));
728 ok = smb2_validate_sequence_number(xconn, message_id, id);
734 /* substract used credits */
735 xconn->smb2.credits.granted -= credit_charge;
740 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
745 count = req->in.vector_count;
747 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
748 /* It's not a SMB2 request */
749 return NT_STATUS_INVALID_PARAMETER;
752 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
753 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
754 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
755 const uint8_t *inhdr = NULL;
757 if (hdr->iov_len != SMB2_HDR_BODY) {
758 return NT_STATUS_INVALID_PARAMETER;
761 if (body->iov_len < 2) {
762 return NT_STATUS_INVALID_PARAMETER;
765 inhdr = (const uint8_t *)hdr->iov_base;
767 /* Check the SMB2 header */
768 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
769 return NT_STATUS_INVALID_PARAMETER;
772 if (!smb2_validate_message_id(req->xconn, inhdr)) {
773 return NT_STATUS_INVALID_PARAMETER;
780 static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
781 const struct iovec *in_vector,
782 struct iovec *out_vector)
784 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
785 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
786 uint16_t credit_charge = 1;
787 uint16_t credits_requested;
791 uint16_t credits_granted = 0;
792 uint64_t credits_possible;
793 uint16_t current_max_credits;
796 * first we grant only 1/16th of the max range.
798 * Windows also starts with the 1/16th and then grants
799 * more later. I was only able to trigger higher
800 * values, when using a very high credit charge.
802 * TODO: scale up depending on load, free memory
804 * Maybe also on the relationship between number
805 * of requests and the used sequence number.
806 * Which means we would grant more credits
807 * for client which use multi credit requests.
809 current_max_credits = xconn->smb2.credits.max / 16;
810 current_max_credits = MAX(current_max_credits, 1);
812 if (xconn->smb2.credits.multicredit) {
813 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
814 credit_charge = MAX(credit_charge, 1);
817 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
818 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
819 credits_requested = MAX(credits_requested, 1);
820 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
821 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
823 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
825 if (xconn->smb2.credits.max < credit_charge) {
826 smbd_server_connection_terminate(xconn,
827 "client error: credit charge > max credits\n");
831 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
833 * In case we already send an async interim
834 * response, we should not grant
835 * credits on the final response.
839 uint16_t additional_possible =
840 xconn->smb2.credits.max - credit_charge;
841 uint16_t additional_max = 0;
842 uint16_t additional_credits = credits_requested - 1;
845 case SMB2_OP_NEGPROT:
847 case SMB2_OP_SESSSETUP:
849 * Windows 2012 RC1 starts to grant
851 * with a successful session setup
853 if (NT_STATUS_IS_OK(out_status)) {
859 * We match windows and only grant additional credits
866 additional_max = MIN(additional_max, additional_possible);
867 additional_credits = MIN(additional_credits, additional_max);
869 credits_granted = credit_charge + additional_credits;
873 * sequence numbers should not wrap
875 * 1. calculate the possible credits until
876 * the sequence numbers start to wrap on 64-bit.
878 * 2. UINT64_MAX is used for Break Notifications.
880 * 2. truncate the possible credits to the maximum
881 * credits we want to grant to the client in total.
883 * 3. remove the range we'll already granted to the client
884 * this makes sure the client consumes the lowest sequence
885 * number, before we can grant additional credits.
887 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
888 if (credits_possible > 0) {
889 /* remove UINT64_MAX */
890 credits_possible -= 1;
892 credits_possible = MIN(credits_possible, current_max_credits);
893 credits_possible -= xconn->smb2.credits.seq_range;
895 credits_granted = MIN(credits_granted, credits_possible);
897 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
898 xconn->smb2.credits.granted += credits_granted;
899 xconn->smb2.credits.seq_range += credits_granted;
901 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
902 "granted %u, current possible/max %u/%u, "
903 "total granted/max/low/range %u/%u/%llu/%u\n",
904 (unsigned int)credits_requested,
905 (unsigned int)credit_charge,
906 (unsigned int)credits_granted,
907 (unsigned int)credits_possible,
908 (unsigned int)current_max_credits,
909 (unsigned int)xconn->smb2.credits.granted,
910 (unsigned int)xconn->smb2.credits.max,
911 (unsigned long long)xconn->smb2.credits.seq_low,
912 (unsigned int)xconn->smb2.credits.seq_range));
915 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
916 struct smbd_smb2_request *outreq)
919 uint16_t total_credits = 0;
921 count = outreq->out.vector_count;
923 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
924 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
925 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
926 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
928 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
930 /* To match Windows, count up what we
932 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
933 /* Set to zero in all but the last reply. */
934 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
935 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
937 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
942 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
944 if (req->current_idx <= 1) {
945 if (size <= sizeof(req->out._body)) {
946 return data_blob_const(req->out._body, size);
950 return data_blob_talloc(req, NULL, size);
953 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
955 struct smbXsrv_connection *xconn = req->xconn;
957 struct iovec *vector;
962 count = req->in.vector_count;
963 if (count <= ARRAY_SIZE(req->out._vector)) {
965 vector = req->out._vector;
967 vector = talloc_zero_array(req, struct iovec, count);
968 if (vector == NULL) {
969 return NT_STATUS_NO_MEMORY;
974 vector[0].iov_base = req->out.nbt_hdr;
975 vector[0].iov_len = 4;
976 SIVAL(req->out.nbt_hdr, 0, 0);
978 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
979 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
980 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
981 uint8_t *outhdr = NULL;
982 uint8_t *outbody = NULL;
983 uint32_t next_command_ofs = 0;
984 struct iovec *current = &vector[idx];
986 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
987 /* we have a next command -
988 * setup for the error case. */
989 next_command_ofs = SMB2_HDR_BODY + 9;
993 outhdr = req->out._hdr;
995 outhdr = talloc_zero_array(mem_ctx, uint8_t,
997 if (outhdr == NULL) {
998 return NT_STATUS_NO_MEMORY;
1002 outbody = outhdr + SMB2_HDR_BODY;
1005 * SMBD_SMB2_TF_IOV_OFS might be used later
1007 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1008 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1010 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
1011 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1013 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1014 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1016 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1017 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1019 /* setup the SMB2 header */
1020 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1021 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1022 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1023 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1024 SIVAL(outhdr, SMB2_HDR_STATUS,
1025 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1026 SSVAL(outhdr, SMB2_HDR_OPCODE,
1027 SVAL(inhdr, SMB2_HDR_OPCODE));
1028 SIVAL(outhdr, SMB2_HDR_FLAGS,
1029 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1030 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1031 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1032 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1033 SIVAL(outhdr, SMB2_HDR_PID,
1034 IVAL(inhdr, SMB2_HDR_PID));
1035 SIVAL(outhdr, SMB2_HDR_TID,
1036 IVAL(inhdr, SMB2_HDR_TID));
1037 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1038 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1039 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1040 inhdr + SMB2_HDR_SIGNATURE, 16);
1042 /* setup error body header */
1043 SSVAL(outbody, 0x00, 0x08 + 1);
1044 SSVAL(outbody, 0x02, 0);
1045 SIVAL(outbody, 0x04, 0);
1048 req->out.vector = vector;
1049 req->out.vector_count = count;
1051 /* setup the length of the NBT packet */
1052 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1054 return NT_STATUS_INVALID_PARAMETER_MIX;
1057 DLIST_ADD_END(xconn->smb2.requests, req);
1059 return NT_STATUS_OK;
1062 void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
1064 const char *location)
1066 struct smbXsrv_client *client = xconn->client;
1068 DEBUG(10,("smbd_server_connection_terminate_ex: conn[%s] reason[%s] at %s\n",
1069 smbXsrv_connection_dbg(xconn), reason, location));
1071 if (client->connections->next != NULL) {
1072 /* TODO: cancel pending requests */
1073 DLIST_REMOVE(client->connections, xconn);
1079 * The last connection was disconnected
1081 exit_server_cleanly(reason);
1084 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1085 struct iovec *outvec,
1086 const struct iovec *srcvec)
1088 const uint8_t *srctf;
1090 const uint8_t *srchdr;
1092 const uint8_t *srcbody;
1094 const uint8_t *expected_srcbody;
1095 const uint8_t *srcdyn;
1097 const uint8_t *expected_srcdyn;
1103 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1104 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1105 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1106 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1107 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1108 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1109 expected_srcbody = srchdr + SMB2_HDR_BODY;
1110 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1111 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1112 expected_srcdyn = srcbody + 8;
1114 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1118 if (srchdr_len != SMB2_HDR_BODY) {
1122 if (srctf_len == SMB2_TF_HDR_SIZE) {
1123 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1124 if (dsttf == NULL) {
1130 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1131 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1133 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1134 * be allocated with size OUTVEC_ALLOC_SIZE. */
1136 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1137 if (dsthdr == NULL) {
1140 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1141 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1144 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1145 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1146 * then duplicate this. Else use talloc_memdup().
1149 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1150 dstbody = dsthdr + SMB2_HDR_BODY;
1152 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1153 if (dstbody == NULL) {
1157 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1158 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1161 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1163 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1164 * then duplicate this. Else use talloc_memdup().
1167 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1168 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1169 } else if (srcdyn == NULL) {
1172 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1173 if (dstdyn == NULL) {
1177 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1178 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1183 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1185 struct smbd_smb2_request *newreq = NULL;
1186 struct iovec *outvec = NULL;
1187 int count = req->out.vector_count;
1191 newreq = smbd_smb2_request_allocate(req->xconn);
1196 newreq->sconn = req->sconn;
1197 newreq->xconn = req->xconn;
1198 newreq->session = req->session;
1199 newreq->do_encryption = req->do_encryption;
1200 newreq->do_signing = req->do_signing;
1201 newreq->current_idx = req->current_idx;
1203 outvec = talloc_zero_array(newreq, struct iovec, count);
1205 TALLOC_FREE(newreq);
1208 newreq->out.vector = outvec;
1209 newreq->out.vector_count = count;
1211 /* Setup the outvec's identically to req. */
1212 outvec[0].iov_base = newreq->out.nbt_hdr;
1213 outvec[0].iov_len = 4;
1214 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1216 /* Setup the vectors identically to the ones in req. */
1217 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1218 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1225 TALLOC_FREE(newreq);
1229 ok = smb2_setup_nbt_length(newreq->out.vector,
1230 newreq->out.vector_count);
1232 TALLOC_FREE(newreq);
1239 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1241 struct smbXsrv_connection *xconn = req->xconn;
1243 struct iovec *firsttf = NULL;
1244 struct iovec *outhdr_v = NULL;
1245 uint8_t *outhdr = NULL;
1246 struct smbd_smb2_request *nreq = NULL;
1250 /* Create a new smb2 request we'll use
1251 for the interim return. */
1252 nreq = dup_smb2_req(req);
1254 return NT_STATUS_NO_MEMORY;
1257 /* Lose the last X out vectors. They're the
1258 ones we'll be using for the async reply. */
1259 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1261 ok = smb2_setup_nbt_length(nreq->out.vector,
1262 nreq->out.vector_count);
1264 return NT_STATUS_INVALID_PARAMETER_MIX;
1267 /* Step back to the previous reply. */
1268 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1269 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1270 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1271 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1272 /* And end the chain. */
1273 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1275 /* Calculate outgoing credits */
1276 smb2_calculate_credits(req, nreq);
1278 if (DEBUGLEVEL >= 10) {
1279 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1280 (unsigned int)nreq->current_idx );
1281 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1282 (unsigned int)nreq->out.vector_count );
1283 print_req_vectors(nreq);
1287 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1288 * we need to sign/encrypt here with the last/first key we remembered
1290 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1291 status = smb2_signing_encrypt_pdu(req->first_key,
1292 xconn->smb2.server.cipher,
1294 nreq->out.vector_count - first_idx);
1295 if (!NT_STATUS_IS_OK(status)) {
1298 } else if (req->last_key.length > 0) {
1299 status = smb2_signing_sign_pdu(req->last_key,
1302 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1303 if (!NT_STATUS_IS_OK(status)) {
1308 nreq->queue_entry.mem_ctx = nreq;
1309 nreq->queue_entry.vector = nreq->out.vector;
1310 nreq->queue_entry.count = nreq->out.vector_count;
1311 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry);
1312 xconn->smb2.send_queue_len++;
1314 status = smbd_smb2_flush_send_queue(xconn);
1315 if (!NT_STATUS_IS_OK(status)) {
1319 return NT_STATUS_OK;
1322 struct smbd_smb2_request_pending_state {
1323 struct smbd_smb2_send_queue queue_entry;
1324 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1325 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1328 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1329 struct tevent_timer *te,
1330 struct timeval current_time,
1331 void *private_data);
1333 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1334 struct tevent_req *subreq,
1335 uint32_t defer_time)
1338 struct timeval defer_endtime;
1339 uint8_t *outhdr = NULL;
1342 if (!tevent_req_is_in_progress(subreq)) {
1344 * This is a performance optimization,
1345 * it avoids one tevent_loop iteration,
1346 * which means we avoid one
1347 * talloc_stackframe_pool/talloc_free pair.
1349 tevent_req_notify_callback(subreq);
1350 return NT_STATUS_OK;
1353 req->subreq = subreq;
1356 if (req->async_te) {
1357 /* We're already async. */
1358 return NT_STATUS_OK;
1361 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1362 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1363 if (flags & SMB2_HDR_FLAG_ASYNC) {
1364 /* We're already async. */
1365 return NT_STATUS_OK;
1368 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1370 * We're trying to go async in a compound request
1371 * chain. This is only allowed for opens that cause an
1372 * oplock break or for the last operation in the
1373 * chain, otherwise it is not allowed. See
1374 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
1376 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1378 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1380 * Cancel the outstanding request.
1382 bool ok = tevent_req_cancel(req->subreq);
1384 return NT_STATUS_OK;
1386 TALLOC_FREE(req->subreq);
1387 return smbd_smb2_request_error(req,
1388 NT_STATUS_INTERNAL_ERROR);
1392 if (DEBUGLEVEL >= 10) {
1393 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1394 (unsigned int)req->current_idx );
1395 print_req_vectors(req);
1398 if (req->current_idx > 1) {
1400 * We're going async in a compound
1401 * chain after the first request has
1402 * already been processed. Send an
1403 * interim response containing the
1404 * set of replies already generated.
1406 int idx = req->current_idx;
1408 status = smb2_send_async_interim_response(req);
1409 if (!NT_STATUS_IS_OK(status)) {
1412 if (req->first_key.length > 0) {
1413 data_blob_clear_free(&req->first_key);
1416 req->current_idx = 1;
1419 * Re-arrange the in.vectors to remove what
1422 memmove(&req->in.vector[1],
1423 &req->in.vector[idx],
1424 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1425 req->in.vector_count = 1 + (req->in.vector_count - idx);
1427 /* Re-arrange the out.vectors to match. */
1428 memmove(&req->out.vector[1],
1429 &req->out.vector[idx],
1430 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1431 req->out.vector_count = 1 + (req->out.vector_count - idx);
1433 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1435 * We only have one remaining request as
1436 * we've processed everything else.
1437 * This is no longer a compound request.
1439 req->compound_related = false;
1440 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1441 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1442 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1445 if (req->last_key.length > 0) {
1446 data_blob_clear_free(&req->last_key);
1449 defer_endtime = timeval_current_ofs_usec(defer_time);
1450 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1452 smbd_smb2_request_pending_timer,
1454 if (req->async_te == NULL) {
1455 return NT_STATUS_NO_MEMORY;
1458 return NT_STATUS_OK;
1461 static DATA_BLOB smbd_smb2_signing_key(struct smbXsrv_session *session,
1462 struct smbXsrv_connection *xconn)
1464 struct smbXsrv_channel_global0 *c = NULL;
1466 DATA_BLOB key = data_blob_null;
1468 status = smbXsrv_session_find_channel(session, xconn, &c);
1469 if (NT_STATUS_IS_OK(status)) {
1470 key = c->signing_key;
1473 if (key.length == 0) {
1474 key = session->global->signing_key;
1480 static NTSTATUS smb2_get_new_nonce(struct smbXsrv_session *session,
1481 uint64_t *new_nonce_high,
1482 uint64_t *new_nonce_low)
1484 uint64_t nonce_high;
1487 session->nonce_low += 1;
1488 if (session->nonce_low == 0) {
1489 session->nonce_low += 1;
1490 session->nonce_high += 1;
1494 * CCM and GCM algorithms must never have their
1495 * nonce wrap, or the security of the whole
1496 * communication and the keys is destroyed.
1497 * We must drop the connection once we have
1498 * transfered too much data.
1500 * NOTE: We assume nonces greater than 8 bytes.
1502 if (session->nonce_high >= session->nonce_high_max) {
1503 return NT_STATUS_ENCRYPTION_FAILED;
1506 nonce_high = session->nonce_high_random;
1507 nonce_high += session->nonce_high;
1508 nonce_low = session->nonce_low;
1510 *new_nonce_high = nonce_high;
1511 *new_nonce_low = nonce_low;
1512 return NT_STATUS_OK;
1515 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1516 struct tevent_timer *te,
1517 struct timeval current_time,
1520 struct smbd_smb2_request *req =
1521 talloc_get_type_abort(private_data,
1522 struct smbd_smb2_request);
1523 struct smbXsrv_connection *xconn = req->xconn;
1524 struct smbd_smb2_request_pending_state *state = NULL;
1525 uint8_t *outhdr = NULL;
1526 const uint8_t *inhdr = NULL;
1529 uint8_t *hdr = NULL;
1530 uint8_t *body = NULL;
1531 uint8_t *dyn = NULL;
1533 uint64_t session_id = 0;
1534 uint64_t message_id = 0;
1535 uint64_t nonce_high = 0;
1536 uint64_t nonce_low = 0;
1537 uint64_t async_id = 0;
1541 TALLOC_FREE(req->async_te);
1543 /* Ensure our final reply matches the interim one. */
1544 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1545 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1546 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1547 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1548 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1550 async_id = message_id; /* keep it simple for now... */
1552 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1553 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1555 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1557 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1558 (unsigned long long)async_id ));
1561 * What we send is identical to a smbd_smb2_request_error
1562 * packet with an error status of STATUS_PENDING. Make use
1563 * of this fact sometime when refactoring. JRA.
1566 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
1567 if (state == NULL) {
1568 smbd_server_connection_terminate(xconn,
1569 nt_errstr(NT_STATUS_NO_MEMORY));
1573 tf = state->buf + NBT_HDR_SIZE;
1574 tf_len = SMB2_TF_HDR_SIZE;
1576 hdr = tf + SMB2_TF_HDR_SIZE;
1577 body = hdr + SMB2_HDR_BODY;
1580 if (req->do_encryption) {
1581 status = smb2_get_new_nonce(req->session,
1584 if (!NT_STATUS_IS_OK(status)) {
1585 smbd_server_connection_terminate(xconn,
1591 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1592 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1593 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1594 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1596 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1597 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1598 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1599 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1600 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1602 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1603 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1604 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1605 SBVAL(hdr, SMB2_HDR_PID, async_id);
1606 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1607 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1608 memcpy(hdr+SMB2_HDR_SIGNATURE,
1609 outhdr+SMB2_HDR_SIGNATURE, 16);
1611 SSVAL(body, 0x00, 0x08 + 1);
1613 SCVAL(body, 0x02, 0);
1614 SCVAL(body, 0x03, 0);
1615 SIVAL(body, 0x04, 0);
1616 /* Match W2K8R2... */
1617 SCVAL(dyn, 0x00, 0x21);
1619 state->vector[0].iov_base = (void *)state->buf;
1620 state->vector[0].iov_len = NBT_HDR_SIZE;
1622 if (req->do_encryption) {
1623 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1624 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1626 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1627 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1630 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1631 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1633 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1634 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1636 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1637 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1639 ok = smb2_setup_nbt_length(state->vector,
1640 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1642 smbd_server_connection_terminate(
1643 xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
1647 /* Ensure we correctly go through crediting. Grant
1648 the credits now, and zero credits on the final
1650 smb2_set_operation_credit(req->xconn,
1651 SMBD_SMB2_IN_HDR_IOV(req),
1652 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1654 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1659 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1660 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1662 (unsigned int)ARRAY_SIZE(state->vector),
1663 (unsigned int)state->vector[i].iov_len);
1667 if (req->do_encryption) {
1668 struct smbXsrv_session *x = req->session;
1669 DATA_BLOB encryption_key = x->global->encryption_key;
1671 status = smb2_signing_encrypt_pdu(encryption_key,
1672 xconn->smb2.server.cipher,
1673 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1674 SMBD_SMB2_NUM_IOV_PER_REQ);
1675 if (!NT_STATUS_IS_OK(status)) {
1676 smbd_server_connection_terminate(xconn,
1680 } else if (req->do_signing) {
1681 struct smbXsrv_session *x = req->session;
1682 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
1684 status = smb2_signing_sign_pdu(signing_key,
1686 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1687 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1688 if (!NT_STATUS_IS_OK(status)) {
1689 smbd_server_connection_terminate(xconn,
1695 state->queue_entry.mem_ctx = state;
1696 state->queue_entry.vector = state->vector;
1697 state->queue_entry.count = ARRAY_SIZE(state->vector);
1698 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
1699 xconn->smb2.send_queue_len++;
1701 status = smbd_smb2_flush_send_queue(xconn);
1702 if (!NT_STATUS_IS_OK(status)) {
1703 smbd_server_connection_terminate(xconn,
1709 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1711 struct smbXsrv_connection *xconn = req->xconn;
1712 struct smbd_smb2_request *cur;
1713 const uint8_t *inhdr;
1715 uint64_t search_message_id;
1716 uint64_t search_async_id;
1719 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1721 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1722 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1723 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1726 * We don't need the request anymore cancel requests never
1729 * We defer the TALLOC_FREE(req) to the caller.
1731 DLIST_REMOVE(xconn->smb2.requests, req);
1733 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1734 const uint8_t *outhdr;
1735 uint64_t message_id;
1738 if (cur->compound_related) {
1740 * Never cancel anything in a compound request.
1741 * Way too hard to deal with the result.
1746 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1748 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1749 async_id = BVAL(outhdr, SMB2_HDR_PID);
1751 if (flags & SMB2_HDR_FLAG_ASYNC) {
1752 if (search_async_id == async_id) {
1753 found_id = async_id;
1757 if (search_message_id == message_id) {
1758 found_id = message_id;
1764 if (cur && cur->subreq) {
1765 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1766 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1767 "cancel opcode[%s] mid %llu\n",
1768 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1769 (unsigned long long)found_id ));
1770 tevent_req_cancel(cur->subreq);
1773 return NT_STATUS_OK;
1776 /*************************************************************
1777 Ensure an incoming tid is a valid one for us to access.
1778 Change to the associated uid credentials and chdir to the
1779 valid tid directory.
1780 *************************************************************/
1782 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1784 const uint8_t *inhdr;
1787 struct smbXsrv_tcon *tcon;
1789 NTTIME now = timeval_to_nttime(&req->request_time);
1793 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1795 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1796 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1798 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1799 in_tid = req->last_tid;
1804 status = smb2srv_tcon_lookup(req->session,
1805 in_tid, now, &tcon);
1806 if (!NT_STATUS_IS_OK(status)) {
1810 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1811 return NT_STATUS_ACCESS_DENIED;
1814 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1815 if (!set_current_service(tcon->compat, 0, true)) {
1816 return NT_STATUS_ACCESS_DENIED;
1820 req->last_tid = in_tid;
1822 return NT_STATUS_OK;
1825 /*************************************************************
1826 Ensure an incoming session_id is a valid one for us to access.
1827 *************************************************************/
1829 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1831 const uint8_t *inhdr;
1834 uint64_t in_session_id;
1835 struct smbXsrv_session *session = NULL;
1836 struct auth_session_info *session_info;
1838 NTTIME now = timeval_to_nttime(&req->request_time);
1840 req->session = NULL;
1843 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1845 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1846 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1847 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1849 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1850 in_session_id = req->last_session_id;
1853 req->last_session_id = 0;
1855 /* look an existing session up */
1856 switch (in_opcode) {
1857 case SMB2_OP_SESSSETUP:
1859 * For a session bind request, we don't have the
1860 * channel set up at this point yet, so we defer
1861 * the verification that the connection belongs
1862 * to the session to the session setup code, which
1863 * can look at the session binding flags.
1865 status = smb2srv_session_lookup_client(req->xconn->client,
1870 status = smb2srv_session_lookup_conn(req->xconn,
1876 req->session = session;
1877 req->last_session_id = in_session_id;
1879 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1880 switch (in_opcode) {
1881 case SMB2_OP_SESSSETUP:
1882 status = NT_STATUS_OK;
1888 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1889 switch (in_opcode) {
1891 case SMB2_OP_CREATE:
1892 case SMB2_OP_GETINFO:
1893 case SMB2_OP_SETINFO:
1894 return NT_STATUS_INVALID_HANDLE;
1897 * Notice the check for
1898 * (session_info == NULL)
1901 status = NT_STATUS_OK;
1905 if (!NT_STATUS_IS_OK(status)) {
1909 session_info = session->global->auth_session_info;
1910 if (session_info == NULL) {
1911 return NT_STATUS_INVALID_HANDLE;
1914 if (in_session_id != req->xconn->client->last_session_id) {
1915 req->xconn->client->last_session_id = in_session_id;
1916 set_current_user_info(session_info->unix_info->sanitized_username,
1917 session_info->unix_info->unix_name,
1918 session_info->info->domain_name);
1921 return NT_STATUS_OK;
1924 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1925 uint32_t data_length)
1927 struct smbXsrv_connection *xconn = req->xconn;
1928 uint16_t needed_charge;
1929 uint16_t credit_charge = 1;
1930 const uint8_t *inhdr;
1932 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1934 if (xconn->smb2.credits.multicredit) {
1935 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1936 credit_charge = MAX(credit_charge, 1);
1939 needed_charge = (data_length - 1)/ 65536 + 1;
1941 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1942 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1943 credit_charge, needed_charge));
1945 if (needed_charge > credit_charge) {
1946 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1947 credit_charge, needed_charge));
1948 return NT_STATUS_INVALID_PARAMETER;
1951 return NT_STATUS_OK;
1954 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1955 size_t expected_body_size)
1957 struct iovec *inhdr_v;
1958 const uint8_t *inhdr;
1960 const uint8_t *inbody;
1962 size_t min_dyn_size = expected_body_size & 0x00000001;
1963 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1966 * The following should be checked already.
1968 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1969 return NT_STATUS_INTERNAL_ERROR;
1971 if (req->current_idx > max_idx) {
1972 return NT_STATUS_INTERNAL_ERROR;
1975 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1976 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1977 return NT_STATUS_INTERNAL_ERROR;
1979 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1980 return NT_STATUS_INTERNAL_ERROR;
1983 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1984 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1988 case SMB2_OP_GETINFO:
1992 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
1993 if (req->smb1req->unread_bytes < min_dyn_size) {
1994 return NT_STATUS_INVALID_PARAMETER;
2003 * Now check the expected body size,
2004 * where the last byte might be in the
2007 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
2008 return NT_STATUS_INVALID_PARAMETER;
2010 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
2011 return NT_STATUS_INVALID_PARAMETER;
2014 inbody = SMBD_SMB2_IN_BODY_PTR(req);
2016 body_size = SVAL(inbody, 0x00);
2017 if (body_size != expected_body_size) {
2018 return NT_STATUS_INVALID_PARAMETER;
2021 return NT_STATUS_OK;
2024 bool smbXsrv_is_encrypted(uint8_t encryption_flags)
2026 return (!(encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)
2028 (encryption_flags & (SMBXSRV_PROCESSED_ENCRYPTED_PACKET |
2029 SMBXSRV_ENCRYPTION_DESIRED |
2030 SMBXSRV_ENCRYPTION_REQUIRED)));
2033 bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags)
2035 return ((encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET) &&
2036 (encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET));
2039 /* Set a flag if not already set, return true if set */
2040 bool smbXsrv_set_crypto_flag(uint8_t *flags, uint8_t flag)
2042 if ((flag == 0) || (*flags & flag)) {
2051 * Update encryption state tracking flags, this can be used to
2052 * determine whether whether the session or tcon is "encrypted".
2054 static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
2056 bool *update_session_globalp,
2057 bool *update_tcon_globalp)
2059 /* Default: assume unecrypted and unsigned */
2060 struct smbXsrv_session *session = req->session;
2061 struct smbXsrv_tcon *tcon = req->tcon;
2062 uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
2063 uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2064 bool update_session = false;
2065 bool update_tcon = false;
2067 if (req->was_encrypted && req->do_encryption) {
2068 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
2069 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2071 /* Unencrypted packet, can be signed */
2072 if (req->do_signing) {
2073 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2074 } else if (opcode == SMB2_OP_CANCEL) {
2075 /* Cancel requests are allowed to skip signing */
2076 sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2080 update_session |= smbXsrv_set_crypto_flag(
2081 &session->global->encryption_flags, encrypt_flag);
2082 update_session |= smbXsrv_set_crypto_flag(
2083 &session->global->signing_flags, sign_flag);
2086 update_tcon |= smbXsrv_set_crypto_flag(
2087 &tcon->global->encryption_flags, encrypt_flag);
2088 update_tcon |= smbXsrv_set_crypto_flag(
2089 &tcon->global->signing_flags, sign_flag);
2092 *update_session_globalp = update_session;
2093 *update_tcon_globalp = update_tcon;
2097 bool smbXsrv_is_signed(uint8_t signing_flags)
2100 * Signing is always enabled, so unless we got an unsigned
2101 * packet and at least one signed packet that was not
2102 * encrypted, the session or tcon is "signed".
2104 return (!(signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2105 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2108 bool smbXsrv_is_partially_signed(uint8_t signing_flags)
2110 return ((signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2111 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2114 static NTSTATUS smbd_smb2_request_dispatch_update_counts(
2115 struct smbd_smb2_request *req,
2118 struct smbXsrv_connection *xconn = req->xconn;
2119 const uint8_t *inhdr;
2120 uint16_t channel_sequence;
2123 struct smbXsrv_open *op;
2124 bool update_open = false;
2125 NTSTATUS status = NT_STATUS_OK;
2127 req->request_counters_updated = false;
2129 if (xconn->protocol < PROTOCOL_SMB2_22) {
2130 return NT_STATUS_OK;
2133 if (req->compat_chain_fsp == NULL) {
2134 return NT_STATUS_OK;
2137 op = req->compat_chain_fsp->op;
2139 return NT_STATUS_OK;
2142 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2143 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2144 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2146 cmp = channel_sequence - op->global->channel_sequence;
2148 if (abs(cmp) > INT16_MAX) {
2150 * [MS-SMB2] 3.3.5.2.10 - Verifying the Channel Sequence Number:
2152 * If the channel sequence number of the request and the one
2153 * known to the server are not equal, the channel sequence
2154 * number and outstanding request counts are only updated
2155 * "... if the unsigned difference using 16-bit arithmetic
2156 * between ChannelSequence and Open.ChannelSequence is less than
2157 * or equal to 0x7FFF ...".
2158 * Otherwise, an error is returned for the modifying
2159 * calls write, set_info, and ioctl.
2161 * There are currently two issues with the description:
2163 * * For the other calls, the document seems to imply
2164 * that processing continues without adapting the
2165 * counters (if the sequence numbers are not equal).
2167 * TODO: This needs clarification!
2169 * * Also, the behaviour if the difference is larger
2170 * than 0x7FFF is not clear. The document seems to
2171 * imply that if such a difference is reached,
2172 * the server starts to ignore the counters or
2173 * in the case of the modifying calls, return errors.
2175 * TODO: This needs clarification!
2177 * At this point Samba tries to be a little more
2178 * clever than the description in the MS-SMB2 document
2179 * by heuristically detecting and properly treating
2180 * a 16 bit overflow of the client-submitted sequence
2183 * If the stored channel squence number is more than
2184 * 0x7FFF larger than the one from the request, then
2185 * the client-provided sequence number has likely
2186 * overflown. We treat this case as valid instead
2189 * The MS-SMB2 behaviour would be setting cmp = -1.
2194 if (!(flags & SMB2_HDR_FLAG_REPLAY_OPERATION)) {
2196 op->request_count += 1;
2197 req->request_counters_updated = true;
2198 } else if (cmp > 0) {
2199 op->pre_request_count += op->request_count;
2200 op->request_count = 1;
2201 op->global->channel_sequence = channel_sequence;
2203 req->request_counters_updated = true;
2204 } else if (modify_call) {
2205 return NT_STATUS_FILE_NOT_AVAILABLE;
2208 if (cmp == 0 && op->pre_request_count == 0) {
2209 op->request_count += 1;
2210 req->request_counters_updated = true;
2211 } else if (cmp > 0 && op->pre_request_count == 0) {
2212 op->pre_request_count += op->request_count;
2213 op->request_count = 1;
2214 op->global->channel_sequence = channel_sequence;
2216 req->request_counters_updated = true;
2217 } else if (modify_call) {
2218 return NT_STATUS_FILE_NOT_AVAILABLE;
2223 status = smbXsrv_open_update(op);
2229 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
2231 struct smbXsrv_connection *xconn = req->xconn;
2232 const struct smbd_smb2_dispatch_table *call = NULL;
2233 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
2234 const uint8_t *inhdr;
2239 NTSTATUS session_status;
2240 uint32_t allowed_flags;
2241 NTSTATUS return_value;
2242 struct smbXsrv_session *x = NULL;
2243 bool signing_required = false;
2244 bool encryption_desired = false;
2245 bool encryption_required = false;
2247 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2249 DO_PROFILE_INC(request);
2251 /* TODO: verify more things */
2253 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2254 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2255 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2256 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
2257 smb2_opcode_name(opcode),
2258 (unsigned long long)mid));
2260 if (xconn->protocol >= PROTOCOL_SMB2_02) {
2262 * once the protocol is negotiated
2263 * SMB2_OP_NEGPROT is not allowed anymore
2265 if (opcode == SMB2_OP_NEGPROT) {
2266 /* drop the connection */
2267 return NT_STATUS_INVALID_PARAMETER;
2271 * if the protocol is not negotiated yet
2272 * only SMB2_OP_NEGPROT is allowed.
2274 if (opcode != SMB2_OP_NEGPROT) {
2275 /* drop the connection */
2276 return NT_STATUS_INVALID_PARAMETER;
2281 * Check if the client provided a valid session id,
2282 * if so smbd_smb2_request_check_session() calls
2283 * set_current_user_info().
2285 * As some command don't require a valid session id
2286 * we defer the check of the session_status
2288 session_status = smbd_smb2_request_check_session(req);
2291 signing_required = x->global->signing_flags & SMBXSRV_SIGNING_REQUIRED;
2292 encryption_desired = x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
2293 encryption_required = x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
2296 req->do_signing = false;
2297 req->do_encryption = false;
2298 req->was_encrypted = false;
2299 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
2300 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
2301 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
2303 if (x != NULL && x->global->session_wire_id != tf_session_id) {
2304 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2305 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
2306 (unsigned long long)x->global->session_wire_id,
2307 (unsigned long long)tf_session_id));
2309 * TODO: windows allows this...
2310 * should we drop the connection?
2312 * For now we just return ACCESS_DENIED
2313 * (Windows clients never trigger this)
2314 * and wait for an update of [MS-SMB2].
2316 return smbd_smb2_request_error(req,
2317 NT_STATUS_ACCESS_DENIED);
2320 req->was_encrypted = true;
2323 if (encryption_required && !req->was_encrypted) {
2324 return smbd_smb2_request_error(req,
2325 NT_STATUS_ACCESS_DENIED);
2328 call = smbd_smb2_call(opcode);
2330 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2333 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2334 SMB2_HDR_FLAG_SIGNED |
2336 if (xconn->protocol >= PROTOCOL_SMB3_11) {
2337 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2339 if (opcode == SMB2_OP_NEGPROT) {
2340 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11) {
2341 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2344 if (opcode == SMB2_OP_CANCEL) {
2345 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2347 if (xconn->protocol >= PROTOCOL_SMB2_22) {
2348 allowed_flags |= SMB2_HDR_FLAG_REPLAY_OPERATION;
2350 if ((flags & ~allowed_flags) != 0) {
2351 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2354 if (flags & SMB2_HDR_FLAG_CHAINED) {
2356 * This check is mostly for giving the correct error code
2357 * for compounded requests.
2359 if (!NT_STATUS_IS_OK(session_status)) {
2360 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2363 req->compat_chain_fsp = NULL;
2366 if (req->was_encrypted) {
2367 signing_required = false;
2368 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2369 DATA_BLOB signing_key = data_blob_null;
2373 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2374 * If the SMB2 header of the SMB2 NEGOTIATE
2375 * request has the SMB2_FLAGS_SIGNED bit set in the
2376 * Flags field, the server MUST fail the request
2377 * with STATUS_INVALID_PARAMETER.
2379 * Microsoft test tool checks this.
2382 if ((opcode == SMB2_OP_NEGPROT) &&
2383 (flags & SMB2_HDR_FLAG_SIGNED)) {
2384 status = NT_STATUS_INVALID_PARAMETER;
2386 status = NT_STATUS_USER_SESSION_DELETED;
2388 return smbd_smb2_request_error(req, status);
2391 signing_key = smbd_smb2_signing_key(x, xconn);
2394 * If we have a signing key, we should
2397 if (signing_key.length > 0) {
2398 req->do_signing = true;
2401 status = smb2_signing_check_pdu(signing_key,
2403 SMBD_SMB2_IN_HDR_IOV(req),
2404 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2405 if (!NT_STATUS_IS_OK(status)) {
2406 return smbd_smb2_request_error(req, status);
2410 * Now that we know the request was correctly signed
2411 * we have to sign the response too.
2413 req->do_signing = true;
2415 if (!NT_STATUS_IS_OK(session_status)) {
2416 return smbd_smb2_request_error(req, session_status);
2418 } else if (opcode == SMB2_OP_CANCEL) {
2419 /* Cancel requests are allowed to skip the signing */
2420 } else if (signing_required) {
2422 * If signing is required we try to sign
2423 * a possible error response
2425 req->do_signing = true;
2426 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2429 if (flags & SMB2_HDR_FLAG_CHAINED) {
2430 req->compound_related = true;
2433 if (call->need_session) {
2434 if (!NT_STATUS_IS_OK(session_status)) {
2435 return smbd_smb2_request_error(req, session_status);
2439 if (call->need_tcon) {
2440 SMB_ASSERT(call->need_session);
2443 * This call needs to be run as user.
2445 * smbd_smb2_request_check_tcon()
2446 * calls change_to_user() on success.
2448 status = smbd_smb2_request_check_tcon(req);
2449 if (!NT_STATUS_IS_OK(status)) {
2450 return smbd_smb2_request_error(req, status);
2452 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
2453 encryption_desired = true;
2455 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
2456 encryption_required = true;
2458 if (encryption_required && !req->was_encrypted) {
2459 return smbd_smb2_request_error(req,
2460 NT_STATUS_ACCESS_DENIED);
2464 if (req->was_encrypted || encryption_desired) {
2465 req->do_encryption = true;
2469 bool update_session_global = false;
2470 bool update_tcon_global = false;
2472 smb2srv_update_crypto_flags(req, opcode,
2473 &update_session_global,
2474 &update_tcon_global);
2476 if (update_session_global) {
2477 status = smbXsrv_session_update(x);
2478 if (!NT_STATUS_IS_OK(status)) {
2479 return smbd_smb2_request_error(req, status);
2482 if (update_tcon_global) {
2483 status = smbXsrv_tcon_update(req->tcon);
2484 if (!NT_STATUS_IS_OK(status)) {
2485 return smbd_smb2_request_error(req, status);
2490 if (call->fileid_ofs != 0) {
2491 size_t needed = call->fileid_ofs + 16;
2492 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2493 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2494 uint64_t file_id_persistent;
2495 uint64_t file_id_volatile;
2496 struct files_struct *fsp;
2498 SMB_ASSERT(call->need_tcon);
2500 if (needed > body_size) {
2501 return smbd_smb2_request_error(req,
2502 NT_STATUS_INVALID_PARAMETER);
2505 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2506 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2508 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2510 if (!call->allow_invalid_fileid) {
2511 return smbd_smb2_request_error(req,
2512 NT_STATUS_FILE_CLOSED);
2515 if (file_id_persistent != UINT64_MAX) {
2516 return smbd_smb2_request_error(req,
2517 NT_STATUS_FILE_CLOSED);
2519 if (file_id_volatile != UINT64_MAX) {
2520 return smbd_smb2_request_error(req,
2521 NT_STATUS_FILE_CLOSED);
2526 status = smbd_smb2_request_dispatch_update_counts(req, call->modify);
2527 if (!NT_STATUS_IS_OK(status)) {
2528 return smbd_smb2_request_error(req, status);
2531 if (call->as_root) {
2532 SMB_ASSERT(call->fileid_ofs == 0);
2533 /* This call needs to be run as root */
2534 change_to_root_user();
2536 SMB_ASSERT(call->need_tcon);
2539 #define _INBYTES(_r) \
2540 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
2543 case SMB2_OP_NEGPROT:
2544 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
2545 req->profile, _INBYTES(req));
2546 return_value = smbd_smb2_request_process_negprot(req);
2549 case SMB2_OP_SESSSETUP:
2550 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
2551 req->profile, _INBYTES(req));
2552 return_value = smbd_smb2_request_process_sesssetup(req);
2555 case SMB2_OP_LOGOFF:
2556 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
2557 req->profile, _INBYTES(req));
2558 return_value = smbd_smb2_request_process_logoff(req);
2562 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
2563 req->profile, _INBYTES(req));
2564 return_value = smbd_smb2_request_process_tcon(req);
2568 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
2569 req->profile, _INBYTES(req));
2570 return_value = smbd_smb2_request_process_tdis(req);
2573 case SMB2_OP_CREATE:
2574 if (req->subreq == NULL) {
2575 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
2576 req->profile, _INBYTES(req));
2578 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
2580 return_value = smbd_smb2_request_process_create(req);
2584 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
2585 req->profile, _INBYTES(req));
2586 return_value = smbd_smb2_request_process_close(req);
2590 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
2591 req->profile, _INBYTES(req));
2592 return_value = smbd_smb2_request_process_flush(req);
2596 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
2597 req->profile, _INBYTES(req));
2598 return_value = smbd_smb2_request_process_read(req);
2602 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
2603 req->profile, _INBYTES(req));
2604 return_value = smbd_smb2_request_process_write(req);
2608 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
2609 req->profile, _INBYTES(req));
2610 return_value = smbd_smb2_request_process_lock(req);
2614 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
2615 req->profile, _INBYTES(req));
2616 return_value = smbd_smb2_request_process_ioctl(req);
2619 case SMB2_OP_CANCEL:
2620 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
2621 req->profile, _INBYTES(req));
2622 return_value = smbd_smb2_request_process_cancel(req);
2623 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
2626 * We don't need the request anymore cancel requests never
2629 * smbd_smb2_request_process_cancel() already called
2630 * DLIST_REMOVE(xconn->smb2.requests, req);
2636 case SMB2_OP_KEEPALIVE:
2637 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
2638 req->profile, _INBYTES(req));
2639 return_value = smbd_smb2_request_process_keepalive(req);
2642 case SMB2_OP_QUERY_DIRECTORY:
2643 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
2644 req->profile, _INBYTES(req));
2645 return_value = smbd_smb2_request_process_query_directory(req);
2648 case SMB2_OP_NOTIFY:
2649 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
2650 req->profile, _INBYTES(req));
2651 return_value = smbd_smb2_request_process_notify(req);
2654 case SMB2_OP_GETINFO:
2655 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
2656 req->profile, _INBYTES(req));
2657 return_value = smbd_smb2_request_process_getinfo(req);
2660 case SMB2_OP_SETINFO:
2661 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
2662 req->profile, _INBYTES(req));
2663 return_value = smbd_smb2_request_process_setinfo(req);
2667 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
2668 req->profile, _INBYTES(req));
2669 return_value = smbd_smb2_request_process_break(req);
2673 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2676 return return_value;
2679 static void smbd_smb2_request_reply_update_counts(struct smbd_smb2_request *req)
2681 struct smbXsrv_connection *xconn = req->xconn;
2682 const uint8_t *inhdr;
2683 uint16_t channel_sequence;
2684 struct smbXsrv_open *op;
2686 if (!req->request_counters_updated) {
2690 if (xconn->protocol < PROTOCOL_SMB2_22) {
2694 if (req->compat_chain_fsp == NULL) {
2698 op = req->compat_chain_fsp->op;
2703 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2704 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2706 if (op->global->channel_sequence == channel_sequence) {
2707 SMB_ASSERT(op->request_count > 0);
2708 op->request_count -= 1;
2710 SMB_ASSERT(op->pre_request_count > 0);
2711 op->pre_request_count -= 1;
2715 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2717 struct smbXsrv_connection *xconn = req->xconn;
2719 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2720 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2721 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2726 TALLOC_FREE(req->async_te);
2728 /* MS-SMB2: 3.3.4.1 Sending Any Outgoing Message */
2729 smbd_smb2_request_reply_update_counts(req);
2731 if (req->do_encryption &&
2732 (firsttf->iov_len == 0) &&
2733 (req->first_key.length == 0) &&
2734 (req->session != NULL) &&
2735 (req->session->global->encryption_key.length != 0))
2737 DATA_BLOB encryption_key = req->session->global->encryption_key;
2739 uint64_t session_id = req->session->global->session_wire_id;
2740 uint64_t nonce_high;
2743 status = smb2_get_new_nonce(req->session,
2746 if (!NT_STATUS_IS_OK(status)) {
2751 * We need to place the SMB2_TRANSFORM header before the
2756 * we need to remember the encryption key
2757 * and defer the signing/encryption until
2758 * we are sure that we do not change
2761 req->first_key = data_blob_dup_talloc(req, encryption_key);
2762 if (req->first_key.data == NULL) {
2763 return NT_STATUS_NO_MEMORY;
2766 tf = talloc_zero_array(req, uint8_t,
2769 return NT_STATUS_NO_MEMORY;
2772 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2773 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2774 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2775 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2777 firsttf->iov_base = (void *)tf;
2778 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2781 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2782 (req->last_key.length > 0) &&
2783 (firsttf->iov_len == 0))
2785 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2786 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2789 * As we are sure the header of the last request in the
2790 * compound chain will not change, we can to sign here
2791 * with the last signing key we remembered.
2793 status = smb2_signing_sign_pdu(req->last_key,
2796 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2797 if (!NT_STATUS_IS_OK(status)) {
2801 if (req->last_key.length > 0) {
2802 data_blob_clear_free(&req->last_key);
2805 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
2806 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
2808 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2810 if (req->current_idx < req->out.vector_count) {
2812 * We must process the remaining compound
2813 * SMB2 requests before any new incoming SMB2
2814 * requests. This is because incoming SMB2
2815 * requests may include a cancel for a
2816 * compound request we haven't processed
2819 struct tevent_immediate *im = tevent_create_immediate(req);
2821 return NT_STATUS_NO_MEMORY;
2824 if (req->do_signing && firsttf->iov_len == 0) {
2825 struct smbXsrv_session *x = req->session;
2826 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2829 * we need to remember the signing key
2830 * and defer the signing until
2831 * we are sure that we do not change
2834 req->last_key = data_blob_dup_talloc(req, signing_key);
2835 if (req->last_key.data == NULL) {
2836 return NT_STATUS_NO_MEMORY;
2840 tevent_schedule_immediate(im,
2842 smbd_smb2_request_dispatch_immediate,
2844 return NT_STATUS_OK;
2847 if (req->compound_related) {
2848 req->compound_related = false;
2851 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2853 return NT_STATUS_INVALID_PARAMETER_MIX;
2856 /* Set credit for these operations (zero credits if this
2857 is a final reply for an async operation). */
2858 smb2_calculate_credits(req, req);
2861 * now check if we need to sign the current response
2863 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2864 status = smb2_signing_encrypt_pdu(req->first_key,
2865 xconn->smb2.server.cipher,
2867 req->out.vector_count - first_idx);
2868 if (!NT_STATUS_IS_OK(status)) {
2871 } else if (req->do_signing) {
2872 struct smbXsrv_session *x = req->session;
2873 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2875 status = smb2_signing_sign_pdu(signing_key,
2878 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2879 if (!NT_STATUS_IS_OK(status)) {
2883 if (req->first_key.length > 0) {
2884 data_blob_clear_free(&req->first_key);
2887 if (req->preauth != NULL) {
2888 struct hc_sha512state sctx;
2891 samba_SHA512_Init(&sctx);
2892 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2893 sizeof(req->preauth->sha512_value));
2894 for (i = 1; i < req->in.vector_count; i++) {
2895 samba_SHA512_Update(&sctx,
2896 req->in.vector[i].iov_base,
2897 req->in.vector[i].iov_len);
2899 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2901 samba_SHA512_Init(&sctx);
2902 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2903 sizeof(req->preauth->sha512_value));
2904 for (i = 1; i < req->out.vector_count; i++) {
2905 samba_SHA512_Update(&sctx,
2906 req->out.vector[i].iov_base,
2907 req->out.vector[i].iov_len);
2909 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2911 req->preauth = NULL;
2914 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2915 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2916 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2917 /* Dynamic part is NULL. Chop it off,
2918 We're going to send it via sendfile. */
2919 req->out.vector_count -= 1;
2923 * We're done with this request -
2924 * move it off the "being processed" queue.
2926 DLIST_REMOVE(xconn->smb2.requests, req);
2928 req->queue_entry.mem_ctx = req;
2929 req->queue_entry.vector = req->out.vector;
2930 req->queue_entry.count = req->out.vector_count;
2931 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry);
2932 xconn->smb2.send_queue_len++;
2934 status = smbd_smb2_flush_send_queue(xconn);
2935 if (!NT_STATUS_IS_OK(status)) {
2939 return NT_STATUS_OK;
2942 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
2944 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2945 struct tevent_immediate *im,
2948 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2949 struct smbd_smb2_request);
2950 struct smbXsrv_connection *xconn = req->xconn;
2955 if (DEBUGLEVEL >= 10) {
2956 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2957 req->current_idx, req->in.vector_count));
2958 print_req_vectors(req);
2961 status = smbd_smb2_request_dispatch(req);
2962 if (!NT_STATUS_IS_OK(status)) {
2963 smbd_server_connection_terminate(xconn, nt_errstr(status));
2967 status = smbd_smb2_request_next_incoming(xconn);
2968 if (!NT_STATUS_IS_OK(status)) {
2969 smbd_server_connection_terminate(xconn, nt_errstr(status));
2974 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2976 DATA_BLOB body, DATA_BLOB *dyn,
2977 const char *location)
2980 struct iovec *outbody_v;
2981 struct iovec *outdyn_v;
2982 uint32_t next_command_ofs;
2984 DEBUG(10,("smbd_smb2_request_done_ex: "
2985 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2986 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2988 (unsigned int)(dyn ? dyn->length : 0),
2991 if (body.length < 2) {
2992 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2995 if ((body.length % 2) != 0) {
2996 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2999 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3000 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
3001 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
3003 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
3004 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
3006 outbody_v->iov_base = (void *)body.data;
3007 outbody_v->iov_len = body.length;
3010 outdyn_v->iov_base = (void *)dyn->data;
3011 outdyn_v->iov_len = dyn->length;
3013 outdyn_v->iov_base = NULL;
3014 outdyn_v->iov_len = 0;
3018 * See if we need to recalculate the offset to the next response
3020 * Note that all responses may require padding (including the very last
3023 if (req->out.vector_count >= (2 * SMBD_SMB2_NUM_IOV_PER_REQ)) {
3024 next_command_ofs = SMB2_HDR_BODY;
3025 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
3026 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
3029 if ((next_command_ofs % 8) != 0) {
3030 size_t pad_size = 8 - (next_command_ofs % 8);
3031 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
3033 * if the dyn buffer is empty
3034 * we can use it to add padding
3038 pad = talloc_zero_array(req,
3041 return smbd_smb2_request_error(req,
3042 NT_STATUS_NO_MEMORY);
3045 outdyn_v->iov_base = (void *)pad;
3046 outdyn_v->iov_len = pad_size;
3049 * For now we copy the dynamic buffer
3050 * and add the padding to the new buffer
3057 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
3058 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
3060 new_size = old_size + pad_size;
3061 new_dyn = talloc_zero_array(req,
3063 if (new_dyn == NULL) {
3064 return smbd_smb2_request_error(req,
3065 NT_STATUS_NO_MEMORY);
3068 memcpy(new_dyn, old_dyn, old_size);
3069 memset(new_dyn + old_size, 0, pad_size);
3071 outdyn_v->iov_base = (void *)new_dyn;
3072 outdyn_v->iov_len = new_size;
3074 next_command_ofs += pad_size;
3077 if ((req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) >= req->out.vector_count) {
3078 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
3080 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
3082 return smbd_smb2_request_reply(req);
3085 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
3088 const char *location)
3090 struct smbXsrv_connection *xconn = req->xconn;
3093 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3094 size_t unread_bytes = smbd_smb2_unread_bytes(req);
3096 DBG_NOTICE("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| "
3097 "at %s\n", req->current_idx, nt_errstr(status),
3098 info ? " +info" : "", location);
3101 /* Recvfile error. Drain incoming socket. */
3105 ret = drain_socket(xconn->transport.sock, unread_bytes);
3106 if (ret != unread_bytes) {
3110 error = NT_STATUS_IO_DEVICE_ERROR;
3112 error = map_nt_error_from_unix_common(errno);
3115 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
3116 "ret[%u] errno[%d] => %s\n",
3117 (unsigned)unread_bytes,
3118 (unsigned)ret, errno, nt_errstr(error)));
3123 body.data = outhdr + SMB2_HDR_BODY;
3125 SSVAL(body.data, 0, 9);
3128 SIVAL(body.data, 0x04, info->length);
3130 /* Allocated size of req->out.vector[i].iov_base
3131 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
3132 * 1 byte without having to do an alloc.
3135 info->data = ((uint8_t *)outhdr) +
3136 OUTVEC_ALLOC_SIZE - 1;
3138 SCVAL(info->data, 0, 0);
3142 * Note: Even if there is an error, continue to process the request.
3146 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
3150 struct smbd_smb2_send_break_state {
3151 struct smbd_smb2_send_queue queue_entry;
3152 uint8_t nbt_hdr[NBT_HDR_SIZE];
3153 uint8_t tf[SMB2_TF_HDR_SIZE];
3154 uint8_t hdr[SMB2_HDR_BODY];
3155 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
3159 static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
3160 struct smbXsrv_session *session,
3161 struct smbXsrv_tcon *tcon,
3162 const uint8_t *body,
3165 struct smbd_smb2_send_break_state *state;
3166 bool do_encryption = false;
3167 uint64_t session_wire_id = 0;
3168 uint64_t nonce_high = 0;
3169 uint64_t nonce_low = 0;
3174 if (session != NULL) {
3175 session_wire_id = session->global->session_wire_id;
3176 do_encryption = session->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
3177 if (tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
3178 do_encryption = true;
3182 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
3185 state = talloc_zero_size(xconn, statelen);
3186 if (state == NULL) {
3187 return NT_STATUS_NO_MEMORY;
3189 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
3191 if (do_encryption) {
3192 status = smb2_get_new_nonce(session,
3195 if (!NT_STATUS_IS_OK(status)) {
3200 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
3201 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
3202 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
3203 SBVAL(state->tf, SMB2_TF_SESSION_ID, session_wire_id);
3205 SIVAL(state->hdr, 0, SMB2_MAGIC);
3206 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
3207 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
3208 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
3209 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
3210 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
3211 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
3212 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
3213 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
3214 SIVAL(state->hdr, SMB2_HDR_PID, 0);
3215 SIVAL(state->hdr, SMB2_HDR_TID, 0);
3216 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
3217 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
3219 state->vector[0] = (struct iovec) {
3220 .iov_base = state->nbt_hdr,
3221 .iov_len = sizeof(state->nbt_hdr)
3224 if (do_encryption) {
3225 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3226 .iov_base = state->tf,
3227 .iov_len = sizeof(state->tf)
3230 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3236 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
3237 .iov_base = state->hdr,
3238 .iov_len = sizeof(state->hdr)
3241 memcpy(state->body, body, body_len);
3243 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
3244 .iov_base = state->body,
3245 .iov_len = body_len /* no sizeof(state->body) .. :-) */
3249 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
3252 ok = smb2_setup_nbt_length(state->vector,
3253 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
3255 return NT_STATUS_INVALID_PARAMETER_MIX;
3258 if (do_encryption) {
3259 DATA_BLOB encryption_key = session->global->encryption_key;
3261 status = smb2_signing_encrypt_pdu(encryption_key,
3262 xconn->smb2.server.cipher,
3263 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
3264 SMBD_SMB2_NUM_IOV_PER_REQ);
3265 if (!NT_STATUS_IS_OK(status)) {
3270 state->queue_entry.mem_ctx = state;
3271 state->queue_entry.vector = state->vector;
3272 state->queue_entry.count = ARRAY_SIZE(state->vector);
3273 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
3274 xconn->smb2.send_queue_len++;
3276 status = smbd_smb2_flush_send_queue(xconn);
3277 if (!NT_STATUS_IS_OK(status)) {
3281 return NT_STATUS_OK;
3284 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_connection *xconn,
3285 struct smbXsrv_session *session,
3286 struct smbXsrv_tcon *tcon,
3287 struct smbXsrv_open *op,
3288 uint8_t oplock_level)
3292 SSVAL(body, 0x00, sizeof(body));
3293 SCVAL(body, 0x02, oplock_level);
3294 SCVAL(body, 0x03, 0); /* reserved */
3295 SIVAL(body, 0x04, 0); /* reserved */
3296 SBVAL(body, 0x08, op->global->open_persistent_id);
3297 SBVAL(body, 0x10, op->global->open_volatile_id);
3299 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3302 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_connection *xconn,
3304 uint32_t lease_flags,
3305 struct smb2_lease_key *lease_key,
3306 uint32_t current_lease_state,
3307 uint32_t new_lease_state)
3311 SSVAL(body, 0x00, sizeof(body));
3312 SSVAL(body, 0x02, new_epoch);
3313 SIVAL(body, 0x04, lease_flags);
3314 SBVAL(body, 0x08, lease_key->data[0]);
3315 SBVAL(body, 0x10, lease_key->data[1]);
3316 SIVAL(body, 0x18, current_lease_state);
3317 SIVAL(body, 0x1c, new_lease_state);
3318 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
3319 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
3320 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
3322 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3325 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
3329 uint64_t file_id_persistent;
3330 uint64_t file_id_volatile;
3331 struct smbXsrv_open *op = NULL;
3332 struct files_struct *fsp = NULL;
3333 const uint8_t *body = NULL;
3336 * This is only called with a pktbuf
3337 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
3341 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
3342 /* Transform header. Cannot recvfile. */
3345 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
3346 /* Not SMB2. Normal error path will cope. */
3349 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
3350 /* Not SMB2. Normal error path will cope. */
3353 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
3354 /* Needs to be a WRITE. */
3357 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
3358 /* Chained. Cannot recvfile. */
3361 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
3362 if (flags & SMB2_HDR_FLAG_CHAINED) {
3363 /* Chained. Cannot recvfile. */
3366 if (flags & SMB2_HDR_FLAG_SIGNED) {
3367 /* Signed. Cannot recvfile. */
3371 body = &state->pktbuf[SMB2_HDR_BODY];
3373 file_id_persistent = BVAL(body, 0x10);
3374 file_id_volatile = BVAL(body, 0x18);
3376 status = smb2srv_open_lookup(state->req->xconn,
3381 if (!NT_STATUS_IS_OK(status)) {
3389 if (fsp->conn == NULL) {
3393 if (IS_IPC(fsp->conn)) {
3396 if (IS_PRINT(fsp->conn)) {
3400 DEBUG(10,("Doing recvfile write len = %u\n",
3401 (unsigned int)(state->pktfull - state->pktlen)));
3406 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
3408 struct smbd_server_connection *sconn = xconn->client->sconn;
3409 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3410 size_t max_send_queue_len;
3411 size_t cur_send_queue_len;
3413 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3415 * we're not supposed to do any io
3417 return NT_STATUS_OK;
3420 if (state->req != NULL) {
3422 * if there is already a tstream_readv_pdu
3423 * pending, we are done.
3425 return NT_STATUS_OK;
3428 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
3429 cur_send_queue_len = xconn->smb2.send_queue_len;
3431 if (cur_send_queue_len > max_send_queue_len) {
3433 * if we have a lot of requests to send,
3434 * we wait until they are on the wire until we
3435 * ask for the next request.
3437 return NT_STATUS_OK;
3440 /* ask for the next request */
3441 ZERO_STRUCTP(state);
3442 state->req = smbd_smb2_request_allocate(xconn);
3443 if (state->req == NULL) {
3444 return NT_STATUS_NO_MEMORY;
3446 state->req->sconn = sconn;
3447 state->req->xconn = xconn;
3448 state->min_recv_size = lp_min_receive_file_size();
3450 TEVENT_FD_READABLE(xconn->transport.fde);
3452 return NT_STATUS_OK;
3455 void smbd_smb2_process_negprot(struct smbXsrv_connection *xconn,
3456 uint64_t expected_seq_low,
3457 const uint8_t *inpdu, size_t size)
3459 struct smbd_server_connection *sconn = xconn->client->sconn;
3461 struct smbd_smb2_request *req = NULL;
3463 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3464 (unsigned int)size));
3466 status = smbd_initialize_smb2(xconn, expected_seq_low);
3467 if (!NT_STATUS_IS_OK(status)) {
3468 smbd_server_connection_terminate(xconn, nt_errstr(status));
3472 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
3473 if (!NT_STATUS_IS_OK(status)) {
3474 smbd_server_connection_terminate(xconn, nt_errstr(status));
3478 status = smbd_smb2_request_validate(req);
3479 if (!NT_STATUS_IS_OK(status)) {
3480 smbd_server_connection_terminate(xconn, nt_errstr(status));
3484 status = smbd_smb2_request_setup_out(req);
3485 if (!NT_STATUS_IS_OK(status)) {
3486 smbd_server_connection_terminate(xconn, nt_errstr(status));
3492 * this was already counted at the SMB1 layer =>
3493 * smbd_smb2_request_dispatch() should not count it twice.
3495 if (profile_p->values.request_stats.count > 0) {
3496 profile_p->values.request_stats.count--;
3499 status = smbd_smb2_request_dispatch(req);
3500 if (!NT_STATUS_IS_OK(status)) {
3501 smbd_server_connection_terminate(xconn, nt_errstr(status));
3505 status = smbd_smb2_request_next_incoming(xconn);
3506 if (!NT_STATUS_IS_OK(status)) {
3507 smbd_server_connection_terminate(xconn, nt_errstr(status));
3511 sconn->num_requests++;
3514 static int socket_error_from_errno(int ret,
3528 if (sys_errno == 0) {
3532 if (sys_errno == EINTR) {
3537 if (sys_errno == EINPROGRESS) {
3542 if (sys_errno == EAGAIN) {
3547 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3548 if (sys_errno == ENOMEM) {
3554 #if EWOULDBLOCK != EAGAIN
3555 if (sys_errno == EWOULDBLOCK) {
3565 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3571 if (xconn->smb2.send_queue == NULL) {
3572 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3573 return NT_STATUS_OK;
3576 while (xconn->smb2.send_queue != NULL) {
3577 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3580 if (e->sendfile_header != NULL) {
3581 NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
3586 for (i=0; i < e->count; i++) {
3587 size += e->vector[i].iov_len;
3590 if (size <= e->sendfile_header->length) {
3591 buf = e->sendfile_header->data;
3593 buf = talloc_array(e->mem_ctx, uint8_t, size);
3595 return NT_STATUS_NO_MEMORY;
3600 for (i=0; i < e->count; i++) {
3602 e->vector[i].iov_base,
3603 e->vector[i].iov_len);
3604 size += e->vector[i].iov_len;
3607 e->sendfile_header->data = buf;
3608 e->sendfile_header->length = size;
3609 e->sendfile_status = &status;
3612 xconn->smb2.send_queue_len--;
3613 DLIST_REMOVE(xconn->smb2.send_queue, e);
3615 * This triggers the sendfile path via
3618 talloc_free(e->mem_ctx);
3620 if (!NT_STATUS_IS_OK(status)) {
3626 ret = writev(xconn->transport.sock, e->vector, e->count);
3628 /* propagate end of file */
3629 return NT_STATUS_INTERNAL_ERROR;
3631 err = socket_error_from_errno(ret, errno, &retry);
3634 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3635 return NT_STATUS_OK;
3638 return map_nt_error_from_unix_common(err);
3641 ok = iov_advance(&e->vector, &e->count, ret);
3643 return NT_STATUS_INTERNAL_ERROR;
3647 /* we have more to write */
3648 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3649 return NT_STATUS_OK;
3652 xconn->smb2.send_queue_len--;
3653 DLIST_REMOVE(xconn->smb2.send_queue, e);
3654 talloc_free(e->mem_ctx);
3657 return NT_STATUS_OK;
3660 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3663 struct smbd_server_connection *sconn = xconn->client->sconn;
3664 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3665 struct smbd_smb2_request *req = NULL;
3666 size_t min_recvfile_size = UINT32_MAX;
3673 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3675 * we're not supposed to do any io
3677 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3678 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3679 return NT_STATUS_OK;
3682 if (fde_flags & TEVENT_FD_WRITE) {
3683 status = smbd_smb2_flush_send_queue(xconn);
3684 if (!NT_STATUS_IS_OK(status)) {
3689 if (!(fde_flags & TEVENT_FD_READ)) {
3690 return NT_STATUS_OK;
3693 if (state->req == NULL) {
3694 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3695 return NT_STATUS_OK;
3699 if (!state->hdr.done) {
3700 state->hdr.done = true;
3702 state->vector.iov_base = (void *)state->hdr.nbt;
3703 state->vector.iov_len = NBT_HDR_SIZE;
3706 ret = readv(xconn->transport.sock, &state->vector, 1);
3708 /* propagate end of file */
3709 return NT_STATUS_END_OF_FILE;
3711 err = socket_error_from_errno(ret, errno, &retry);
3714 TEVENT_FD_READABLE(xconn->transport.fde);
3715 return NT_STATUS_OK;
3718 return map_nt_error_from_unix_common(err);
3721 if (ret < state->vector.iov_len) {
3723 base = (uint8_t *)state->vector.iov_base;
3725 state->vector.iov_base = (void *)base;
3726 state->vector.iov_len -= ret;
3727 /* we have more to read */
3728 TEVENT_FD_READABLE(xconn->transport.fde);
3729 return NT_STATUS_OK;
3732 if (state->pktlen > 0) {
3733 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3735 * Not a possible receivefile write.
3736 * Read the rest of the data.
3738 state->doing_receivefile = false;
3740 state->pktbuf = talloc_realloc(state->req,
3744 if (state->pktbuf == NULL) {
3745 return NT_STATUS_NO_MEMORY;
3748 state->vector.iov_base = (void *)(state->pktbuf +
3750 state->vector.iov_len = (state->pktfull -
3753 state->pktlen = state->pktfull;
3758 * Either this is a receivefile write so we've
3759 * done a short read, or if not we have all the data.
3765 * Now we analyze the NBT header
3767 if (state->hdr.nbt[0] != 0x00) {
3768 state->min_recv_size = 0;
3770 state->pktfull = smb2_len(state->hdr.nbt);
3771 if (state->pktfull == 0) {
3775 if (state->min_recv_size != 0) {
3776 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3777 min_recvfile_size += state->min_recv_size;
3780 if (state->pktfull > min_recvfile_size) {
3782 * Might be a receivefile write. Read the SMB2 HEADER +
3783 * SMB2_WRITE header first. Set 'doing_receivefile'
3784 * as we're *attempting* receivefile write. If this
3785 * turns out not to be a SMB2_WRITE request or otherwise
3786 * not suitable then we'll just read the rest of the data
3787 * the next time this function is called.
3789 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3790 state->doing_receivefile = true;
3792 state->pktlen = state->pktfull;
3795 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3796 if (state->pktbuf == NULL) {
3797 return NT_STATUS_NO_MEMORY;
3800 state->vector.iov_base = (void *)state->pktbuf;
3801 state->vector.iov_len = state->pktlen;
3807 if (state->hdr.nbt[0] != 0x00) {
3808 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3809 state->hdr.nbt[0]));
3812 ZERO_STRUCTP(state);
3814 state->min_recv_size = lp_min_receive_file_size();
3822 req->request_time = timeval_current();
3823 now = timeval_to_nttime(&req->request_time);
3825 status = smbd_smb2_inbuf_parse_compound(xconn,
3831 &req->in.vector_count);
3832 if (!NT_STATUS_IS_OK(status)) {
3836 if (state->doing_receivefile) {
3837 req->smb1req = talloc_zero(req, struct smb_request);
3838 if (req->smb1req == NULL) {
3839 return NT_STATUS_NO_MEMORY;
3841 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3844 ZERO_STRUCTP(state);
3846 req->current_idx = 1;
3848 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3849 req->current_idx, req->in.vector_count));
3851 status = smbd_smb2_request_validate(req);
3852 if (!NT_STATUS_IS_OK(status)) {
3856 status = smbd_smb2_request_setup_out(req);
3857 if (!NT_STATUS_IS_OK(status)) {
3861 status = smbd_smb2_request_dispatch(req);
3862 if (!NT_STATUS_IS_OK(status)) {
3866 sconn->num_requests++;
3868 /* The timeout_processing function isn't run nearly
3869 often enough to implement 'max log size' without
3870 overrunning the size of the file by many megabytes.
3871 This is especially true if we are running at debug
3872 level 10. Checking every 50 SMB2s is a nice
3873 tradeoff of performance vs log file size overrun. */
3875 if ((sconn->num_requests % 50) == 0 &&
3876 need_to_check_log_size()) {
3877 change_to_root_user();
3881 status = smbd_smb2_request_next_incoming(xconn);
3882 if (!NT_STATUS_IS_OK(status)) {
3886 return NT_STATUS_OK;
3889 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3890 struct tevent_fd *fde,
3894 struct smbXsrv_connection *xconn =
3895 talloc_get_type_abort(private_data,
3896 struct smbXsrv_connection);
3899 status = smbd_smb2_io_handler(xconn, flags);
3900 if (!NT_STATUS_IS_OK(status)) {
3901 smbd_server_connection_terminate(xconn, nt_errstr(status));