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;
49 } smbd_smb2_table[] = {
50 #define _OP(o) .opcode = o, .name = #o
55 _OP(SMB2_OP_SESSSETUP),
65 * This call needs to be run as root.
67 * smbd_smb2_request_process_tcon()
68 * calls make_connection_snum(), which will call
69 * change_to_user(), when needed.
103 .need_session = true,
108 .need_session = true,
111 .allow_invalid_fileid = true,
116 _OP(SMB2_OP_KEEPALIVE),
119 _OP(SMB2_OP_QUERY_DIRECTORY),
120 .need_session = true,
125 .need_session = true,
129 _OP(SMB2_OP_GETINFO),
130 .need_session = true,
134 _OP(SMB2_OP_SETINFO),
135 .need_session = true,
140 .need_session = true,
145 * as LEASE breaks does not
151 const char *smb2_opcode_name(uint16_t opcode)
153 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
154 return "Bad SMB2 opcode";
156 return smbd_smb2_table[opcode].name;
159 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
161 const struct smbd_smb2_dispatch_table *ret = NULL;
163 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
167 ret = &smbd_smb2_table[opcode];
169 SMB_ASSERT(ret->opcode == opcode);
174 static void print_req_vectors(const struct smbd_smb2_request *req)
178 for (i = 0; i < req->in.vector_count; i++) {
179 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
181 (unsigned int)req->in.vector[i].iov_len);
183 for (i = 0; i < req->out.vector_count; i++) {
184 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
186 (unsigned int)req->out.vector[i].iov_len);
190 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
192 if (size < (4 + SMB2_HDR_BODY)) {
196 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
203 static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn,
204 uint64_t expected_seq_low)
206 TALLOC_FREE(xconn->transport.fde);
208 xconn->smb2.credits.seq_low = expected_seq_low;
209 xconn->smb2.credits.seq_range = 1;
210 xconn->smb2.credits.granted = 1;
211 xconn->smb2.credits.max = lp_smb2_max_credits();
212 xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
213 xconn->smb2.credits.max);
214 if (xconn->smb2.credits.bitmap == NULL) {
215 return NT_STATUS_NO_MEMORY;
218 xconn->transport.fde = tevent_add_fd(xconn->ev_ctx,
220 xconn->transport.sock,
222 smbd_smb2_connection_handler,
224 if (xconn->transport.fde == NULL) {
225 return NT_STATUS_NO_MEMORY;
228 /* Ensure child is set to non-blocking mode */
229 set_blocking(xconn->transport.sock, false);
233 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
234 #define _smb2_setlen(_buf,len) do { \
235 uint8_t *buf = (uint8_t *)_buf; \
237 buf[1] = ((len)&0xFF0000)>>16; \
238 buf[2] = ((len)&0xFF00)>>8; \
239 buf[3] = (len)&0xFF; \
242 static bool smb2_setup_nbt_length(struct iovec *vector, int count)
250 len = iov_buflen(vector+1, count-1);
252 if ((len == -1) || (len > 0xFFFFFF)) {
256 _smb2_setlen(vector[0].iov_base, len);
260 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
262 if (req->first_key.length > 0) {
263 data_blob_clear_free(&req->first_key);
265 if (req->last_key.length > 0) {
266 data_blob_clear_free(&req->last_key);
271 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
273 TALLOC_CTX *mem_pool;
274 struct smbd_smb2_request *req;
277 /* Enable this to find subtle valgrind errors. */
278 mem_pool = talloc_init("smbd_smb2_request_allocate");
280 mem_pool = talloc_tos();
282 if (mem_pool == NULL) {
286 req = talloc_zero(mem_pool, struct smbd_smb2_request);
288 talloc_free(mem_pool);
291 talloc_reparent(mem_pool, mem_ctx, req);
293 TALLOC_FREE(mem_pool);
296 req->last_session_id = UINT64_MAX;
297 req->last_tid = UINT32_MAX;
299 talloc_set_destructor(req, smbd_smb2_request_destructor);
304 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
308 struct smbd_smb2_request *req,
312 TALLOC_CTX *mem_ctx = req;
316 uint8_t *first_hdr = buf;
317 size_t verified_buflen = 0;
322 * Note: index '0' is reserved for the transport protocol
324 iov = req->in._vector;
326 while (taken < buflen) {
327 size_t len = buflen - taken;
328 uint8_t *hdr = first_hdr + taken;
331 size_t next_command_ofs;
333 uint8_t *body = NULL;
336 struct iovec *iov_alloc = NULL;
338 if (iov != req->in._vector) {
342 if (verified_buflen > taken) {
343 len = verified_buflen - taken;
350 DEBUG(10, ("%d bytes left, expected at least %d\n",
354 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
355 struct smbXsrv_session *s = NULL;
357 struct iovec tf_iov[2];
361 if (xconn->protocol < PROTOCOL_SMB2_24) {
362 DEBUG(10, ("Got SMB2_TRANSFORM header, "
363 "but dialect[0x%04X] is used\n",
364 xconn->smb2.server.dialect));
368 if (xconn->smb2.server.cipher == 0) {
369 DEBUG(10, ("Got SMB2_TRANSFORM header, "
370 "but not negotiated "
371 "client[0x%08X] server[0x%08X]\n",
372 xconn->smb2.client.capabilities,
373 xconn->smb2.server.capabilities));
377 if (len < SMB2_TF_HDR_SIZE) {
378 DEBUG(1, ("%d bytes left, expected at least %d\n",
379 (int)len, SMB2_TF_HDR_SIZE));
383 tf_len = SMB2_TF_HDR_SIZE;
386 hdr = first_hdr + taken;
387 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
388 uid = BVAL(tf, SMB2_TF_SESSION_ID);
390 if (len < SMB2_TF_HDR_SIZE + enc_len) {
391 DEBUG(1, ("%d bytes left, expected at least %d\n",
393 (int)(SMB2_TF_HDR_SIZE + enc_len)));
397 status = smb2srv_session_lookup_conn(xconn, uid, now,
400 DEBUG(1, ("invalid session[%llu] in "
401 "SMB2_TRANSFORM header\n",
402 (unsigned long long)uid));
403 TALLOC_FREE(iov_alloc);
404 return NT_STATUS_USER_SESSION_DELETED;
407 tf_iov[0].iov_base = (void *)tf;
408 tf_iov[0].iov_len = tf_len;
409 tf_iov[1].iov_base = (void *)hdr;
410 tf_iov[1].iov_len = enc_len;
412 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
413 xconn->smb2.server.cipher,
415 if (!NT_STATUS_IS_OK(status)) {
416 TALLOC_FREE(iov_alloc);
420 verified_buflen = taken + enc_len;
425 * We need the header plus the body length field
428 if (len < SMB2_HDR_BODY + 2) {
429 DEBUG(10, ("%d bytes left, expected at least %d\n",
430 (int)len, SMB2_HDR_BODY));
433 if (IVAL(hdr, 0) != SMB2_MAGIC) {
434 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
438 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
439 DEBUG(10, ("Got HDR len %d, expected %d\n",
440 SVAL(hdr, 4), SMB2_HDR_BODY));
445 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
446 body_size = SVAL(hdr, SMB2_HDR_BODY);
448 if (next_command_ofs != 0) {
449 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
452 if (next_command_ofs > full_size) {
455 full_size = next_command_ofs;
462 if (body_size > (full_size - SMB2_HDR_BODY)) {
464 * let the caller handle the error
466 body_size = full_size - SMB2_HDR_BODY;
468 body = hdr + SMB2_HDR_BODY;
469 dyn = body + body_size;
470 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
472 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
473 struct iovec *iov_tmp = NULL;
475 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
478 SMBD_SMB2_NUM_IOV_PER_REQ);
479 if (iov_tmp == NULL) {
480 TALLOC_FREE(iov_alloc);
481 return NT_STATUS_NO_MEMORY;
484 if (iov_alloc == NULL) {
487 sizeof(req->in._vector));
493 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
495 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
496 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
497 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
498 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
499 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
500 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
501 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
502 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
512 if (iov != req->in._vector) {
515 return NT_STATUS_INVALID_PARAMETER;
518 static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
519 const uint8_t *_inpdu, size_t size,
520 struct smbd_smb2_request **_req)
522 struct smbd_server_connection *sconn = xconn->client->sconn;
523 struct smbd_smb2_request *req;
524 uint32_t protocol_version;
525 uint8_t *inpdu = NULL;
526 const uint8_t *inhdr = NULL;
528 uint32_t next_command_ofs;
532 if (size < (SMB2_HDR_BODY + 2)) {
533 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
534 return NT_STATUS_INVALID_PARAMETER;
539 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
540 if (protocol_version != SMB2_MAGIC) {
541 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
543 return NT_STATUS_INVALID_PARAMETER;
546 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
547 if (cmd != SMB2_OP_NEGPROT) {
548 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
550 return NT_STATUS_INVALID_PARAMETER;
553 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
554 if (next_command_ofs != 0) {
555 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
557 return NT_STATUS_INVALID_PARAMETER;
560 req = smbd_smb2_request_allocate(xconn);
562 return NT_STATUS_NO_MEMORY;
567 inpdu = talloc_memdup(req, _inpdu, size);
569 return NT_STATUS_NO_MEMORY;
572 req->request_time = timeval_current();
573 now = timeval_to_nttime(&req->request_time);
575 status = smbd_smb2_inbuf_parse_compound(xconn,
579 req, &req->in.vector,
580 &req->in.vector_count);
581 if (!NT_STATUS_IS_OK(status)) {
586 req->current_idx = 1;
592 static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
593 uint64_t message_id, uint64_t seq_id)
595 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
599 seq_tmp = xconn->smb2.credits.seq_low;
600 if (seq_id < seq_tmp) {
601 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
602 "%llu (sequence id %llu) "
603 "(granted = %u, low = %llu, range = %u)\n",
604 (unsigned long long)message_id,
605 (unsigned long long)seq_id,
606 (unsigned int)xconn->smb2.credits.granted,
607 (unsigned long long)xconn->smb2.credits.seq_low,
608 (unsigned int)xconn->smb2.credits.seq_range));
612 seq_tmp += xconn->smb2.credits.seq_range;
613 if (seq_id >= seq_tmp) {
614 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
615 "%llu (sequence id %llu) "
616 "(granted = %u, low = %llu, range = %u)\n",
617 (unsigned long long)message_id,
618 (unsigned long long)seq_id,
619 (unsigned int)xconn->smb2.credits.granted,
620 (unsigned long long)xconn->smb2.credits.seq_low,
621 (unsigned int)xconn->smb2.credits.seq_range));
625 offset = seq_id % xconn->smb2.credits.max;
627 if (bitmap_query(credits_bm, offset)) {
628 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
629 "%llu (sequence id %llu) "
630 "(granted = %u, low = %llu, range = %u) "
632 (unsigned long long)message_id,
633 (unsigned long long)seq_id,
634 (unsigned int)xconn->smb2.credits.granted,
635 (unsigned long long)xconn->smb2.credits.seq_low,
636 (unsigned int)xconn->smb2.credits.seq_range,
641 /* Mark the message_ids as seen in the bitmap. */
642 bitmap_set(credits_bm, offset);
644 if (seq_id != xconn->smb2.credits.seq_low) {
649 * Move the window forward by all the message_id's
652 while (bitmap_query(credits_bm, offset)) {
653 DEBUG(10,("smb2_validate_sequence_number: clearing "
654 "id %llu (position %u) from bitmap\n",
655 (unsigned long long)(xconn->smb2.credits.seq_low),
657 bitmap_clear(credits_bm, offset);
659 xconn->smb2.credits.seq_low += 1;
660 xconn->smb2.credits.seq_range -= 1;
661 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
667 static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
668 const uint8_t *inhdr)
670 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
671 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
672 uint16_t credit_charge = 1;
675 if (opcode == SMB2_OP_CANCEL) {
676 /* SMB2_CANCEL requests by definition resend messageids. */
680 if (xconn->smb2.credits.multicredit) {
681 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
682 credit_charge = MAX(credit_charge, 1);
685 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
686 "credits_granted %llu, "
687 "seqnum low/range: %llu/%llu\n",
688 (unsigned long long) message_id,
689 (unsigned long long) credit_charge,
690 (unsigned long long) xconn->smb2.credits.granted,
691 (unsigned long long) xconn->smb2.credits.seq_low,
692 (unsigned long long) xconn->smb2.credits.seq_range));
694 if (xconn->smb2.credits.granted < credit_charge) {
695 DEBUG(0, ("smb2_validate_message_id: client used more "
696 "credits than granted, mid %llu, charge %llu, "
697 "credits_granted %llu, "
698 "seqnum low/range: %llu/%llu\n",
699 (unsigned long long) message_id,
700 (unsigned long long) credit_charge,
701 (unsigned long long) xconn->smb2.credits.granted,
702 (unsigned long long) xconn->smb2.credits.seq_low,
703 (unsigned long long) xconn->smb2.credits.seq_range));
708 * now check the message ids
710 * for multi-credit requests we need to check all current mid plus
711 * the implicit mids caused by the credit charge
712 * e.g. current mid = 15, charge 5 => mark 15-19 as used
715 for (i = 0; i <= (credit_charge-1); i++) {
716 uint64_t id = message_id + i;
719 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
720 (unsigned long long)message_id,
722 (unsigned long long)id));
724 ok = smb2_validate_sequence_number(xconn, message_id, id);
730 /* substract used credits */
731 xconn->smb2.credits.granted -= credit_charge;
736 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
741 count = req->in.vector_count;
743 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
744 /* It's not a SMB2 request */
745 return NT_STATUS_INVALID_PARAMETER;
748 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
749 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
750 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
751 const uint8_t *inhdr = NULL;
753 if (hdr->iov_len != SMB2_HDR_BODY) {
754 return NT_STATUS_INVALID_PARAMETER;
757 if (body->iov_len < 2) {
758 return NT_STATUS_INVALID_PARAMETER;
761 inhdr = (const uint8_t *)hdr->iov_base;
763 /* Check the SMB2 header */
764 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
765 return NT_STATUS_INVALID_PARAMETER;
768 if (!smb2_validate_message_id(req->xconn, inhdr)) {
769 return NT_STATUS_INVALID_PARAMETER;
776 static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
777 const struct iovec *in_vector,
778 struct iovec *out_vector)
780 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
781 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
782 uint16_t credit_charge = 1;
783 uint16_t credits_requested;
787 uint16_t credits_granted = 0;
788 uint64_t credits_possible;
789 uint16_t current_max_credits;
792 * first we grant only 1/16th of the max range.
794 * Windows also starts with the 1/16th and then grants
795 * more later. I was only able to trigger higher
796 * values, when using a very high credit charge.
798 * TODO: scale up depending on load, free memory
800 * Maybe also on the relationship between number
801 * of requests and the used sequence number.
802 * Which means we would grant more credits
803 * for client which use multi credit requests.
805 current_max_credits = xconn->smb2.credits.max / 16;
806 current_max_credits = MAX(current_max_credits, 1);
808 if (xconn->smb2.credits.multicredit) {
809 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
810 credit_charge = MAX(credit_charge, 1);
813 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
814 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
815 credits_requested = MAX(credits_requested, 1);
816 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
817 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
819 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
821 if (xconn->smb2.credits.max < credit_charge) {
822 smbd_server_connection_terminate(xconn,
823 "client error: credit charge > max credits\n");
827 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
829 * In case we already send an async interim
830 * response, we should not grant
831 * credits on the final response.
835 uint16_t additional_possible =
836 xconn->smb2.credits.max - credit_charge;
837 uint16_t additional_max = 0;
838 uint16_t additional_credits = credits_requested - 1;
841 case SMB2_OP_NEGPROT:
843 case SMB2_OP_SESSSETUP:
845 * Windows 2012 RC1 starts to grant
847 * with a successful session setup
849 if (NT_STATUS_IS_OK(out_status)) {
855 * We match windows and only grant additional credits
862 additional_max = MIN(additional_max, additional_possible);
863 additional_credits = MIN(additional_credits, additional_max);
865 credits_granted = credit_charge + additional_credits;
869 * sequence numbers should not wrap
871 * 1. calculate the possible credits until
872 * the sequence numbers start to wrap on 64-bit.
874 * 2. UINT64_MAX is used for Break Notifications.
876 * 2. truncate the possible credits to the maximum
877 * credits we want to grant to the client in total.
879 * 3. remove the range we'll already granted to the client
880 * this makes sure the client consumes the lowest sequence
881 * number, before we can grant additional credits.
883 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
884 if (credits_possible > 0) {
885 /* remove UINT64_MAX */
886 credits_possible -= 1;
888 credits_possible = MIN(credits_possible, current_max_credits);
889 credits_possible -= xconn->smb2.credits.seq_range;
891 credits_granted = MIN(credits_granted, credits_possible);
893 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
894 xconn->smb2.credits.granted += credits_granted;
895 xconn->smb2.credits.seq_range += credits_granted;
897 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
898 "granted %u, current possible/max %u/%u, "
899 "total granted/max/low/range %u/%u/%llu/%u\n",
900 (unsigned int)credits_requested,
901 (unsigned int)credit_charge,
902 (unsigned int)credits_granted,
903 (unsigned int)credits_possible,
904 (unsigned int)current_max_credits,
905 (unsigned int)xconn->smb2.credits.granted,
906 (unsigned int)xconn->smb2.credits.max,
907 (unsigned long long)xconn->smb2.credits.seq_low,
908 (unsigned int)xconn->smb2.credits.seq_range));
911 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
912 struct smbd_smb2_request *outreq)
915 uint16_t total_credits = 0;
917 count = outreq->out.vector_count;
919 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
920 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
921 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
922 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
924 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
926 /* To match Windows, count up what we
928 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
929 /* Set to zero in all but the last reply. */
930 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
931 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
933 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
938 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
940 if (req->current_idx <= 1) {
941 if (size <= sizeof(req->out._body)) {
942 return data_blob_const(req->out._body, size);
946 return data_blob_talloc(req, NULL, size);
949 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
951 struct smbXsrv_connection *xconn = req->xconn;
953 struct iovec *vector;
958 count = req->in.vector_count;
959 if (count <= ARRAY_SIZE(req->out._vector)) {
961 vector = req->out._vector;
963 vector = talloc_zero_array(req, struct iovec, count);
964 if (vector == NULL) {
965 return NT_STATUS_NO_MEMORY;
970 vector[0].iov_base = req->out.nbt_hdr;
971 vector[0].iov_len = 4;
972 SIVAL(req->out.nbt_hdr, 0, 0);
974 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
975 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
976 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
977 uint8_t *outhdr = NULL;
978 uint8_t *outbody = NULL;
979 uint32_t next_command_ofs = 0;
980 struct iovec *current = &vector[idx];
982 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
983 /* we have a next command -
984 * setup for the error case. */
985 next_command_ofs = SMB2_HDR_BODY + 9;
989 outhdr = req->out._hdr;
991 outhdr = talloc_zero_array(mem_ctx, uint8_t,
993 if (outhdr == NULL) {
994 return NT_STATUS_NO_MEMORY;
998 outbody = outhdr + SMB2_HDR_BODY;
1001 * SMBD_SMB2_TF_IOV_OFS might be used later
1003 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1004 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1006 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
1007 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1009 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1010 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1012 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1013 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1015 /* setup the SMB2 header */
1016 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1017 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1018 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1019 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1020 SIVAL(outhdr, SMB2_HDR_STATUS,
1021 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1022 SSVAL(outhdr, SMB2_HDR_OPCODE,
1023 SVAL(inhdr, SMB2_HDR_OPCODE));
1024 SIVAL(outhdr, SMB2_HDR_FLAGS,
1025 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1026 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1027 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1028 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1029 SIVAL(outhdr, SMB2_HDR_PID,
1030 IVAL(inhdr, SMB2_HDR_PID));
1031 SIVAL(outhdr, SMB2_HDR_TID,
1032 IVAL(inhdr, SMB2_HDR_TID));
1033 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1034 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1035 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1036 inhdr + SMB2_HDR_SIGNATURE, 16);
1038 /* setup error body header */
1039 SSVAL(outbody, 0x00, 0x08 + 1);
1040 SSVAL(outbody, 0x02, 0);
1041 SIVAL(outbody, 0x04, 0);
1044 req->out.vector = vector;
1045 req->out.vector_count = count;
1047 /* setup the length of the NBT packet */
1048 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1050 return NT_STATUS_INVALID_PARAMETER_MIX;
1053 DLIST_ADD_END(xconn->smb2.requests, req);
1055 return NT_STATUS_OK;
1058 void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
1060 const char *location)
1062 struct smbXsrv_client *client = xconn->client;
1064 DEBUG(10,("smbd_server_connection_terminate_ex: conn[%s] reason[%s] at %s\n",
1065 smbXsrv_connection_dbg(xconn), reason, location));
1067 if (client->connections->next != NULL) {
1068 /* TODO: cancel pending requests */
1069 DLIST_REMOVE(client->connections, xconn);
1075 * The last connection was disconnected
1077 exit_server_cleanly(reason);
1080 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1081 struct iovec *outvec,
1082 const struct iovec *srcvec)
1084 const uint8_t *srctf;
1086 const uint8_t *srchdr;
1088 const uint8_t *srcbody;
1090 const uint8_t *expected_srcbody;
1091 const uint8_t *srcdyn;
1093 const uint8_t *expected_srcdyn;
1099 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1100 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1101 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1102 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1103 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1104 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1105 expected_srcbody = srchdr + SMB2_HDR_BODY;
1106 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1107 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1108 expected_srcdyn = srcbody + 8;
1110 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1114 if (srchdr_len != SMB2_HDR_BODY) {
1118 if (srctf_len == SMB2_TF_HDR_SIZE) {
1119 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1120 if (dsttf == NULL) {
1126 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1127 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1129 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1130 * be allocated with size OUTVEC_ALLOC_SIZE. */
1132 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1133 if (dsthdr == NULL) {
1136 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1137 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1140 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1141 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1142 * then duplicate this. Else use talloc_memdup().
1145 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1146 dstbody = dsthdr + SMB2_HDR_BODY;
1148 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1149 if (dstbody == NULL) {
1153 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1154 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1157 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1159 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1160 * then duplicate this. Else use talloc_memdup().
1163 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1164 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1165 } else if (srcdyn == NULL) {
1168 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1169 if (dstdyn == NULL) {
1173 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1174 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1179 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1181 struct smbd_smb2_request *newreq = NULL;
1182 struct iovec *outvec = NULL;
1183 int count = req->out.vector_count;
1187 newreq = smbd_smb2_request_allocate(req->xconn);
1192 newreq->sconn = req->sconn;
1193 newreq->xconn = req->xconn;
1194 newreq->session = req->session;
1195 newreq->do_encryption = req->do_encryption;
1196 newreq->do_signing = req->do_signing;
1197 newreq->current_idx = req->current_idx;
1199 outvec = talloc_zero_array(newreq, struct iovec, count);
1201 TALLOC_FREE(newreq);
1204 newreq->out.vector = outvec;
1205 newreq->out.vector_count = count;
1207 /* Setup the outvec's identically to req. */
1208 outvec[0].iov_base = newreq->out.nbt_hdr;
1209 outvec[0].iov_len = 4;
1210 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1212 /* Setup the vectors identically to the ones in req. */
1213 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1214 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1221 TALLOC_FREE(newreq);
1225 ok = smb2_setup_nbt_length(newreq->out.vector,
1226 newreq->out.vector_count);
1228 TALLOC_FREE(newreq);
1235 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1237 struct smbXsrv_connection *xconn = req->xconn;
1239 struct iovec *firsttf = NULL;
1240 struct iovec *outhdr_v = NULL;
1241 uint8_t *outhdr = NULL;
1242 struct smbd_smb2_request *nreq = NULL;
1246 /* Create a new smb2 request we'll use
1247 for the interim return. */
1248 nreq = dup_smb2_req(req);
1250 return NT_STATUS_NO_MEMORY;
1253 /* Lose the last X out vectors. They're the
1254 ones we'll be using for the async reply. */
1255 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1257 ok = smb2_setup_nbt_length(nreq->out.vector,
1258 nreq->out.vector_count);
1260 return NT_STATUS_INVALID_PARAMETER_MIX;
1263 /* Step back to the previous reply. */
1264 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1265 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1266 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1267 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1268 /* And end the chain. */
1269 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1271 /* Calculate outgoing credits */
1272 smb2_calculate_credits(req, nreq);
1274 if (DEBUGLEVEL >= 10) {
1275 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1276 (unsigned int)nreq->current_idx );
1277 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1278 (unsigned int)nreq->out.vector_count );
1279 print_req_vectors(nreq);
1283 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1284 * we need to sign/encrypt here with the last/first key we remembered
1286 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1287 status = smb2_signing_encrypt_pdu(req->first_key,
1288 xconn->smb2.server.cipher,
1290 nreq->out.vector_count - first_idx);
1291 if (!NT_STATUS_IS_OK(status)) {
1294 } else if (req->last_key.length > 0) {
1295 status = smb2_signing_sign_pdu(req->last_key,
1298 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1299 if (!NT_STATUS_IS_OK(status)) {
1304 nreq->queue_entry.mem_ctx = nreq;
1305 nreq->queue_entry.vector = nreq->out.vector;
1306 nreq->queue_entry.count = nreq->out.vector_count;
1307 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry);
1308 xconn->smb2.send_queue_len++;
1310 status = smbd_smb2_flush_send_queue(xconn);
1311 if (!NT_STATUS_IS_OK(status)) {
1315 return NT_STATUS_OK;
1318 struct smbd_smb2_request_pending_state {
1319 struct smbd_smb2_send_queue queue_entry;
1320 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1321 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1324 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1325 struct tevent_timer *te,
1326 struct timeval current_time,
1327 void *private_data);
1329 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1330 struct tevent_req *subreq,
1331 uint32_t defer_time)
1334 struct timeval defer_endtime;
1335 uint8_t *outhdr = NULL;
1338 if (!tevent_req_is_in_progress(subreq)) {
1340 * This is a performance optimization,
1341 * it avoids one tevent_loop iteration,
1342 * which means we avoid one
1343 * talloc_stackframe_pool/talloc_free pair.
1345 tevent_req_notify_callback(subreq);
1346 return NT_STATUS_OK;
1349 req->subreq = subreq;
1352 if (req->async_te) {
1353 /* We're already async. */
1354 return NT_STATUS_OK;
1357 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1358 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1359 if (flags & SMB2_HDR_FLAG_ASYNC) {
1360 /* We're already async. */
1361 return NT_STATUS_OK;
1364 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1366 * We're trying to go async in a compound request
1367 * chain. This is only allowed for opens that cause an
1368 * oplock break or for the last operation in the
1369 * chain, otherwise it is not allowed. See
1370 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
1372 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1374 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1376 * Cancel the outstanding request.
1378 bool ok = tevent_req_cancel(req->subreq);
1380 return NT_STATUS_OK;
1382 TALLOC_FREE(req->subreq);
1383 return smbd_smb2_request_error(req,
1384 NT_STATUS_INTERNAL_ERROR);
1388 if (DEBUGLEVEL >= 10) {
1389 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1390 (unsigned int)req->current_idx );
1391 print_req_vectors(req);
1394 if (req->current_idx > 1) {
1396 * We're going async in a compound
1397 * chain after the first request has
1398 * already been processed. Send an
1399 * interim response containing the
1400 * set of replies already generated.
1402 int idx = req->current_idx;
1404 status = smb2_send_async_interim_response(req);
1405 if (!NT_STATUS_IS_OK(status)) {
1408 if (req->first_key.length > 0) {
1409 data_blob_clear_free(&req->first_key);
1412 req->current_idx = 1;
1415 * Re-arrange the in.vectors to remove what
1418 memmove(&req->in.vector[1],
1419 &req->in.vector[idx],
1420 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1421 req->in.vector_count = 1 + (req->in.vector_count - idx);
1423 /* Re-arrange the out.vectors to match. */
1424 memmove(&req->out.vector[1],
1425 &req->out.vector[idx],
1426 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1427 req->out.vector_count = 1 + (req->out.vector_count - idx);
1429 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1431 * We only have one remaining request as
1432 * we've processed everything else.
1433 * This is no longer a compound request.
1435 req->compound_related = false;
1436 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1437 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1438 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1441 if (req->last_key.length > 0) {
1442 data_blob_clear_free(&req->last_key);
1445 defer_endtime = timeval_current_ofs_usec(defer_time);
1446 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1448 smbd_smb2_request_pending_timer,
1450 if (req->async_te == NULL) {
1451 return NT_STATUS_NO_MEMORY;
1454 return NT_STATUS_OK;
1457 static DATA_BLOB smbd_smb2_signing_key(struct smbXsrv_session *session,
1458 struct smbXsrv_connection *xconn)
1460 struct smbXsrv_channel_global0 *c = NULL;
1462 DATA_BLOB key = data_blob_null;
1464 status = smbXsrv_session_find_channel(session, xconn, &c);
1465 if (NT_STATUS_IS_OK(status)) {
1466 key = c->signing_key;
1469 if (key.length == 0) {
1470 key = session->global->signing_key;
1476 static NTSTATUS smb2_get_new_nonce(struct smbXsrv_session *session,
1477 uint64_t *new_nonce_high,
1478 uint64_t *new_nonce_low)
1480 uint64_t nonce_high;
1483 session->nonce_low += 1;
1484 if (session->nonce_low == 0) {
1485 session->nonce_low += 1;
1486 session->nonce_high += 1;
1490 * CCM and GCM algorithms must never have their
1491 * nonce wrap, or the security of the whole
1492 * communication and the keys is destroyed.
1493 * We must drop the connection once we have
1494 * transfered too much data.
1496 * NOTE: We assume nonces greater than 8 bytes.
1498 if (session->nonce_high >= session->nonce_high_max) {
1499 return NT_STATUS_ENCRYPTION_FAILED;
1502 nonce_high = session->nonce_high_random;
1503 nonce_high += session->nonce_high;
1504 nonce_low = session->nonce_low;
1506 *new_nonce_high = nonce_high;
1507 *new_nonce_low = nonce_low;
1508 return NT_STATUS_OK;
1511 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1512 struct tevent_timer *te,
1513 struct timeval current_time,
1516 struct smbd_smb2_request *req =
1517 talloc_get_type_abort(private_data,
1518 struct smbd_smb2_request);
1519 struct smbXsrv_connection *xconn = req->xconn;
1520 struct smbd_smb2_request_pending_state *state = NULL;
1521 uint8_t *outhdr = NULL;
1522 const uint8_t *inhdr = NULL;
1525 uint8_t *hdr = NULL;
1526 uint8_t *body = NULL;
1527 uint8_t *dyn = NULL;
1529 uint64_t session_id = 0;
1530 uint64_t message_id = 0;
1531 uint64_t nonce_high = 0;
1532 uint64_t nonce_low = 0;
1533 uint64_t async_id = 0;
1537 TALLOC_FREE(req->async_te);
1539 /* Ensure our final reply matches the interim one. */
1540 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1541 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1542 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1543 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1544 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1546 async_id = message_id; /* keep it simple for now... */
1548 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1549 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1551 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1553 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1554 (unsigned long long)async_id ));
1557 * What we send is identical to a smbd_smb2_request_error
1558 * packet with an error status of STATUS_PENDING. Make use
1559 * of this fact sometime when refactoring. JRA.
1562 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
1563 if (state == NULL) {
1564 smbd_server_connection_terminate(xconn,
1565 nt_errstr(NT_STATUS_NO_MEMORY));
1569 tf = state->buf + NBT_HDR_SIZE;
1570 tf_len = SMB2_TF_HDR_SIZE;
1572 hdr = tf + SMB2_TF_HDR_SIZE;
1573 body = hdr + SMB2_HDR_BODY;
1576 if (req->do_encryption) {
1577 status = smb2_get_new_nonce(req->session,
1580 if (!NT_STATUS_IS_OK(status)) {
1581 smbd_server_connection_terminate(xconn,
1587 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1588 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1589 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1590 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1592 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1593 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1594 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1595 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1596 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1598 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1599 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1600 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1601 SBVAL(hdr, SMB2_HDR_PID, async_id);
1602 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1603 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1604 memcpy(hdr+SMB2_HDR_SIGNATURE,
1605 outhdr+SMB2_HDR_SIGNATURE, 16);
1607 SSVAL(body, 0x00, 0x08 + 1);
1609 SCVAL(body, 0x02, 0);
1610 SCVAL(body, 0x03, 0);
1611 SIVAL(body, 0x04, 0);
1612 /* Match W2K8R2... */
1613 SCVAL(dyn, 0x00, 0x21);
1615 state->vector[0].iov_base = (void *)state->buf;
1616 state->vector[0].iov_len = NBT_HDR_SIZE;
1618 if (req->do_encryption) {
1619 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1620 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1622 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1623 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1626 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1627 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1629 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1630 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1632 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1633 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1635 ok = smb2_setup_nbt_length(state->vector,
1636 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1638 smbd_server_connection_terminate(
1639 xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
1643 /* Ensure we correctly go through crediting. Grant
1644 the credits now, and zero credits on the final
1646 smb2_set_operation_credit(req->xconn,
1647 SMBD_SMB2_IN_HDR_IOV(req),
1648 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1650 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1655 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1656 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1658 (unsigned int)ARRAY_SIZE(state->vector),
1659 (unsigned int)state->vector[i].iov_len);
1663 if (req->do_encryption) {
1664 struct smbXsrv_session *x = req->session;
1665 DATA_BLOB encryption_key = x->global->encryption_key;
1667 status = smb2_signing_encrypt_pdu(encryption_key,
1668 xconn->smb2.server.cipher,
1669 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1670 SMBD_SMB2_NUM_IOV_PER_REQ);
1671 if (!NT_STATUS_IS_OK(status)) {
1672 smbd_server_connection_terminate(xconn,
1676 } else if (req->do_signing) {
1677 struct smbXsrv_session *x = req->session;
1678 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
1680 status = smb2_signing_sign_pdu(signing_key,
1682 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1683 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1684 if (!NT_STATUS_IS_OK(status)) {
1685 smbd_server_connection_terminate(xconn,
1691 state->queue_entry.mem_ctx = state;
1692 state->queue_entry.vector = state->vector;
1693 state->queue_entry.count = ARRAY_SIZE(state->vector);
1694 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
1695 xconn->smb2.send_queue_len++;
1697 status = smbd_smb2_flush_send_queue(xconn);
1698 if (!NT_STATUS_IS_OK(status)) {
1699 smbd_server_connection_terminate(xconn,
1705 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1707 struct smbXsrv_connection *xconn = req->xconn;
1708 struct smbd_smb2_request *cur;
1709 const uint8_t *inhdr;
1711 uint64_t search_message_id;
1712 uint64_t search_async_id;
1715 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1717 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1718 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1719 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1722 * We don't need the request anymore cancel requests never
1725 * We defer the TALLOC_FREE(req) to the caller.
1727 DLIST_REMOVE(xconn->smb2.requests, req);
1729 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1730 const uint8_t *outhdr;
1731 uint64_t message_id;
1734 if (cur->compound_related) {
1736 * Never cancel anything in a compound request.
1737 * Way too hard to deal with the result.
1742 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1744 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1745 async_id = BVAL(outhdr, SMB2_HDR_PID);
1747 if (flags & SMB2_HDR_FLAG_ASYNC) {
1748 if (search_async_id == async_id) {
1749 found_id = async_id;
1753 if (search_message_id == message_id) {
1754 found_id = message_id;
1760 if (cur && cur->subreq) {
1761 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1762 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1763 "cancel opcode[%s] mid %llu\n",
1764 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1765 (unsigned long long)found_id ));
1766 tevent_req_cancel(cur->subreq);
1769 return NT_STATUS_OK;
1772 /*************************************************************
1773 Ensure an incoming tid is a valid one for us to access.
1774 Change to the associated uid credentials and chdir to the
1775 valid tid directory.
1776 *************************************************************/
1778 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1780 const uint8_t *inhdr;
1783 struct smbXsrv_tcon *tcon;
1785 NTTIME now = timeval_to_nttime(&req->request_time);
1789 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1791 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1792 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1794 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1795 in_tid = req->last_tid;
1800 status = smb2srv_tcon_lookup(req->session,
1801 in_tid, now, &tcon);
1802 if (!NT_STATUS_IS_OK(status)) {
1806 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1807 return NT_STATUS_ACCESS_DENIED;
1810 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1811 if (!set_current_service(tcon->compat, 0, true)) {
1812 return NT_STATUS_ACCESS_DENIED;
1816 req->last_tid = in_tid;
1818 return NT_STATUS_OK;
1821 /*************************************************************
1822 Ensure an incoming session_id is a valid one for us to access.
1823 *************************************************************/
1825 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1827 const uint8_t *inhdr;
1830 uint64_t in_session_id;
1831 struct smbXsrv_session *session = NULL;
1832 struct auth_session_info *session_info;
1834 NTTIME now = timeval_to_nttime(&req->request_time);
1836 req->session = NULL;
1839 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1841 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1842 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1843 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1845 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1846 in_session_id = req->last_session_id;
1849 req->last_session_id = 0;
1851 /* look an existing session up */
1852 switch (in_opcode) {
1853 case SMB2_OP_SESSSETUP:
1855 * For a session bind request, we don't have the
1856 * channel set up at this point yet, so we defer
1857 * the verification that the connection belongs
1858 * to the session to the session setup code, which
1859 * can look at the session binding flags.
1861 status = smb2srv_session_lookup_client(req->xconn->client,
1866 status = smb2srv_session_lookup_conn(req->xconn,
1872 req->session = session;
1873 req->last_session_id = in_session_id;
1875 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1876 switch (in_opcode) {
1877 case SMB2_OP_SESSSETUP:
1878 status = NT_STATUS_OK;
1884 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1885 switch (in_opcode) {
1887 case SMB2_OP_CREATE:
1888 case SMB2_OP_GETINFO:
1889 case SMB2_OP_SETINFO:
1890 return NT_STATUS_INVALID_HANDLE;
1893 * Notice the check for
1894 * (session_info == NULL)
1897 status = NT_STATUS_OK;
1901 if (!NT_STATUS_IS_OK(status)) {
1905 session_info = session->global->auth_session_info;
1906 if (session_info == NULL) {
1907 return NT_STATUS_INVALID_HANDLE;
1910 if (in_session_id != req->xconn->client->last_session_id) {
1911 req->xconn->client->last_session_id = in_session_id;
1912 set_current_user_info(session_info->unix_info->sanitized_username,
1913 session_info->unix_info->unix_name,
1914 session_info->info->domain_name);
1917 return NT_STATUS_OK;
1920 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1921 uint32_t data_length)
1923 struct smbXsrv_connection *xconn = req->xconn;
1924 uint16_t needed_charge;
1925 uint16_t credit_charge = 1;
1926 const uint8_t *inhdr;
1928 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1930 if (xconn->smb2.credits.multicredit) {
1931 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1932 credit_charge = MAX(credit_charge, 1);
1935 needed_charge = (data_length - 1)/ 65536 + 1;
1937 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1938 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1939 credit_charge, needed_charge));
1941 if (needed_charge > credit_charge) {
1942 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1943 credit_charge, needed_charge));
1944 return NT_STATUS_INVALID_PARAMETER;
1947 return NT_STATUS_OK;
1950 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1951 size_t expected_body_size)
1953 struct iovec *inhdr_v;
1954 const uint8_t *inhdr;
1956 const uint8_t *inbody;
1958 size_t min_dyn_size = expected_body_size & 0x00000001;
1959 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1962 * The following should be checked already.
1964 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1965 return NT_STATUS_INTERNAL_ERROR;
1967 if (req->current_idx > max_idx) {
1968 return NT_STATUS_INTERNAL_ERROR;
1971 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1972 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1973 return NT_STATUS_INTERNAL_ERROR;
1975 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1976 return NT_STATUS_INTERNAL_ERROR;
1979 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1980 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1984 case SMB2_OP_GETINFO:
1988 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
1989 if (req->smb1req->unread_bytes < min_dyn_size) {
1990 return NT_STATUS_INVALID_PARAMETER;
1999 * Now check the expected body size,
2000 * where the last byte might be in the
2003 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
2004 return NT_STATUS_INVALID_PARAMETER;
2006 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
2007 return NT_STATUS_INVALID_PARAMETER;
2010 inbody = SMBD_SMB2_IN_BODY_PTR(req);
2012 body_size = SVAL(inbody, 0x00);
2013 if (body_size != expected_body_size) {
2014 return NT_STATUS_INVALID_PARAMETER;
2017 return NT_STATUS_OK;
2020 bool smbXsrv_is_encrypted(uint8_t encryption_flags)
2022 return (!(encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)
2024 (encryption_flags & (SMBXSRV_PROCESSED_ENCRYPTED_PACKET |
2025 SMBXSRV_ENCRYPTION_DESIRED |
2026 SMBXSRV_ENCRYPTION_REQUIRED)));
2029 bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags)
2031 return ((encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET) &&
2032 (encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET));
2035 /* Set a flag if not already set, return true if set */
2036 bool smbXsrv_set_crypto_flag(uint8_t *flags, uint8_t flag)
2038 if ((flag == 0) || (*flags & flag)) {
2047 * Update encryption state tracking flags, this can be used to
2048 * determine whether whether the session or tcon is "encrypted".
2050 static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
2052 bool *update_session_globalp,
2053 bool *update_tcon_globalp)
2055 /* Default: assume unecrypted and unsigned */
2056 struct smbXsrv_session *session = req->session;
2057 struct smbXsrv_tcon *tcon = req->tcon;
2058 uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
2059 uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2060 bool update_session = false;
2061 bool update_tcon = false;
2063 if (req->was_encrypted && req->do_encryption) {
2064 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
2065 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2067 /* Unencrypted packet, can be signed */
2068 if (req->do_signing) {
2069 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2070 } else if (opcode == SMB2_OP_CANCEL) {
2071 /* Cancel requests are allowed to skip signing */
2072 sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2076 update_session |= smbXsrv_set_crypto_flag(
2077 &session->global->encryption_flags, encrypt_flag);
2078 update_session |= smbXsrv_set_crypto_flag(
2079 &session->global->signing_flags, sign_flag);
2082 update_tcon |= smbXsrv_set_crypto_flag(
2083 &tcon->global->encryption_flags, encrypt_flag);
2084 update_tcon |= smbXsrv_set_crypto_flag(
2085 &tcon->global->signing_flags, sign_flag);
2088 *update_session_globalp = update_session;
2089 *update_tcon_globalp = update_tcon;
2093 bool smbXsrv_is_signed(uint8_t signing_flags)
2096 * Signing is always enabled, so unless we got an unsigned
2097 * packet and at least one signed packet that was not
2098 * encrypted, the session or tcon is "signed".
2100 return (!(signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2101 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2104 bool smbXsrv_is_partially_signed(uint8_t signing_flags)
2106 return ((signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2107 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2110 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
2112 struct smbXsrv_connection *xconn = req->xconn;
2113 const struct smbd_smb2_dispatch_table *call = NULL;
2114 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
2115 const uint8_t *inhdr;
2120 NTSTATUS session_status;
2121 uint32_t allowed_flags;
2122 NTSTATUS return_value;
2123 struct smbXsrv_session *x = NULL;
2124 bool signing_required = false;
2125 bool encryption_desired = false;
2126 bool encryption_required = false;
2128 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2130 DO_PROFILE_INC(request);
2132 /* TODO: verify more things */
2134 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2135 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2136 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2137 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
2138 smb2_opcode_name(opcode),
2139 (unsigned long long)mid));
2141 if (xconn->protocol >= PROTOCOL_SMB2_02) {
2143 * once the protocol is negotiated
2144 * SMB2_OP_NEGPROT is not allowed anymore
2146 if (opcode == SMB2_OP_NEGPROT) {
2147 /* drop the connection */
2148 return NT_STATUS_INVALID_PARAMETER;
2152 * if the protocol is not negotiated yet
2153 * only SMB2_OP_NEGPROT is allowed.
2155 if (opcode != SMB2_OP_NEGPROT) {
2156 /* drop the connection */
2157 return NT_STATUS_INVALID_PARAMETER;
2162 * Check if the client provided a valid session id,
2163 * if so smbd_smb2_request_check_session() calls
2164 * set_current_user_info().
2166 * As some command don't require a valid session id
2167 * we defer the check of the session_status
2169 session_status = smbd_smb2_request_check_session(req);
2172 signing_required = x->global->signing_flags & SMBXSRV_SIGNING_REQUIRED;
2173 encryption_desired = x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
2174 encryption_required = x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
2177 req->do_signing = false;
2178 req->do_encryption = false;
2179 req->was_encrypted = false;
2180 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
2181 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
2182 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
2184 if (x != NULL && x->global->session_wire_id != tf_session_id) {
2185 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2186 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
2187 (unsigned long long)x->global->session_wire_id,
2188 (unsigned long long)tf_session_id));
2190 * TODO: windows allows this...
2191 * should we drop the connection?
2193 * For now we just return ACCESS_DENIED
2194 * (Windows clients never trigger this)
2195 * and wait for an update of [MS-SMB2].
2197 return smbd_smb2_request_error(req,
2198 NT_STATUS_ACCESS_DENIED);
2201 req->was_encrypted = true;
2204 if (encryption_required && !req->was_encrypted) {
2205 return smbd_smb2_request_error(req,
2206 NT_STATUS_ACCESS_DENIED);
2209 call = smbd_smb2_call(opcode);
2211 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2214 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2215 SMB2_HDR_FLAG_SIGNED |
2217 if (xconn->protocol >= PROTOCOL_SMB3_11) {
2218 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2220 if (opcode == SMB2_OP_NEGPROT) {
2221 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11) {
2222 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2225 if (opcode == SMB2_OP_CANCEL) {
2226 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2228 if ((flags & ~allowed_flags) != 0) {
2229 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2232 if (flags & SMB2_HDR_FLAG_CHAINED) {
2234 * This check is mostly for giving the correct error code
2235 * for compounded requests.
2237 if (!NT_STATUS_IS_OK(session_status)) {
2238 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2241 req->compat_chain_fsp = NULL;
2244 if (req->was_encrypted) {
2245 signing_required = false;
2246 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2247 DATA_BLOB signing_key = data_blob_null;
2251 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2252 * If the SMB2 header of the SMB2 NEGOTIATE
2253 * request has the SMB2_FLAGS_SIGNED bit set in the
2254 * Flags field, the server MUST fail the request
2255 * with STATUS_INVALID_PARAMETER.
2257 * Microsoft test tool checks this.
2260 if ((opcode == SMB2_OP_NEGPROT) &&
2261 (flags & SMB2_HDR_FLAG_SIGNED)) {
2262 status = NT_STATUS_INVALID_PARAMETER;
2264 status = NT_STATUS_USER_SESSION_DELETED;
2266 return smbd_smb2_request_error(req, status);
2269 signing_key = smbd_smb2_signing_key(x, xconn);
2272 * If we have a signing key, we should
2275 if (signing_key.length > 0) {
2276 req->do_signing = true;
2279 status = smb2_signing_check_pdu(signing_key,
2281 SMBD_SMB2_IN_HDR_IOV(req),
2282 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2283 if (!NT_STATUS_IS_OK(status)) {
2284 return smbd_smb2_request_error(req, status);
2288 * Now that we know the request was correctly signed
2289 * we have to sign the response too.
2291 req->do_signing = true;
2293 if (!NT_STATUS_IS_OK(session_status)) {
2294 return smbd_smb2_request_error(req, session_status);
2296 } else if (opcode == SMB2_OP_CANCEL) {
2297 /* Cancel requests are allowed to skip the signing */
2298 } else if (signing_required) {
2300 * If signing is required we try to sign
2301 * a possible error response
2303 req->do_signing = true;
2304 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2307 if (flags & SMB2_HDR_FLAG_CHAINED) {
2308 req->compound_related = true;
2311 if (call->need_session) {
2312 if (!NT_STATUS_IS_OK(session_status)) {
2313 return smbd_smb2_request_error(req, session_status);
2317 if (call->need_tcon) {
2318 SMB_ASSERT(call->need_session);
2321 * This call needs to be run as user.
2323 * smbd_smb2_request_check_tcon()
2324 * calls change_to_user() on success.
2326 status = smbd_smb2_request_check_tcon(req);
2327 if (!NT_STATUS_IS_OK(status)) {
2328 return smbd_smb2_request_error(req, status);
2330 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
2331 encryption_desired = true;
2333 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
2334 encryption_required = true;
2336 if (encryption_required && !req->was_encrypted) {
2337 return smbd_smb2_request_error(req,
2338 NT_STATUS_ACCESS_DENIED);
2342 if (req->was_encrypted || encryption_desired) {
2343 req->do_encryption = true;
2347 bool update_session_global = false;
2348 bool update_tcon_global = false;
2350 smb2srv_update_crypto_flags(req, opcode,
2351 &update_session_global,
2352 &update_tcon_global);
2354 if (update_session_global) {
2355 status = smbXsrv_session_update(x);
2356 if (!NT_STATUS_IS_OK(status)) {
2357 return smbd_smb2_request_error(req, status);
2360 if (update_tcon_global) {
2361 status = smbXsrv_tcon_update(req->tcon);
2362 if (!NT_STATUS_IS_OK(status)) {
2363 return smbd_smb2_request_error(req, status);
2368 if (call->fileid_ofs != 0) {
2369 size_t needed = call->fileid_ofs + 16;
2370 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2371 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2372 uint64_t file_id_persistent;
2373 uint64_t file_id_volatile;
2374 struct files_struct *fsp;
2376 SMB_ASSERT(call->need_tcon);
2378 if (needed > body_size) {
2379 return smbd_smb2_request_error(req,
2380 NT_STATUS_INVALID_PARAMETER);
2383 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2384 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2386 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2388 if (!call->allow_invalid_fileid) {
2389 return smbd_smb2_request_error(req,
2390 NT_STATUS_FILE_CLOSED);
2393 if (file_id_persistent != UINT64_MAX) {
2394 return smbd_smb2_request_error(req,
2395 NT_STATUS_FILE_CLOSED);
2397 if (file_id_volatile != UINT64_MAX) {
2398 return smbd_smb2_request_error(req,
2399 NT_STATUS_FILE_CLOSED);
2404 if (call->as_root) {
2405 SMB_ASSERT(call->fileid_ofs == 0);
2406 /* This call needs to be run as root */
2407 change_to_root_user();
2409 SMB_ASSERT(call->need_tcon);
2412 #define _INBYTES(_r) \
2413 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
2416 case SMB2_OP_NEGPROT:
2417 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
2418 req->profile, _INBYTES(req));
2419 return_value = smbd_smb2_request_process_negprot(req);
2422 case SMB2_OP_SESSSETUP:
2423 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
2424 req->profile, _INBYTES(req));
2425 return_value = smbd_smb2_request_process_sesssetup(req);
2428 case SMB2_OP_LOGOFF:
2429 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
2430 req->profile, _INBYTES(req));
2431 return_value = smbd_smb2_request_process_logoff(req);
2435 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
2436 req->profile, _INBYTES(req));
2437 return_value = smbd_smb2_request_process_tcon(req);
2441 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
2442 req->profile, _INBYTES(req));
2443 return_value = smbd_smb2_request_process_tdis(req);
2446 case SMB2_OP_CREATE:
2447 if (req->subreq == NULL) {
2448 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
2449 req->profile, _INBYTES(req));
2451 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
2453 return_value = smbd_smb2_request_process_create(req);
2457 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
2458 req->profile, _INBYTES(req));
2459 return_value = smbd_smb2_request_process_close(req);
2463 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
2464 req->profile, _INBYTES(req));
2465 return_value = smbd_smb2_request_process_flush(req);
2469 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
2470 req->profile, _INBYTES(req));
2471 return_value = smbd_smb2_request_process_read(req);
2475 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
2476 req->profile, _INBYTES(req));
2477 return_value = smbd_smb2_request_process_write(req);
2481 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
2482 req->profile, _INBYTES(req));
2483 return_value = smbd_smb2_request_process_lock(req);
2487 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
2488 req->profile, _INBYTES(req));
2489 return_value = smbd_smb2_request_process_ioctl(req);
2492 case SMB2_OP_CANCEL:
2493 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
2494 req->profile, _INBYTES(req));
2495 return_value = smbd_smb2_request_process_cancel(req);
2496 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
2499 * We don't need the request anymore cancel requests never
2502 * smbd_smb2_request_process_cancel() already called
2503 * DLIST_REMOVE(xconn->smb2.requests, req);
2509 case SMB2_OP_KEEPALIVE:
2510 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
2511 req->profile, _INBYTES(req));
2512 return_value = smbd_smb2_request_process_keepalive(req);
2515 case SMB2_OP_QUERY_DIRECTORY:
2516 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
2517 req->profile, _INBYTES(req));
2518 return_value = smbd_smb2_request_process_query_directory(req);
2521 case SMB2_OP_NOTIFY:
2522 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
2523 req->profile, _INBYTES(req));
2524 return_value = smbd_smb2_request_process_notify(req);
2527 case SMB2_OP_GETINFO:
2528 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
2529 req->profile, _INBYTES(req));
2530 return_value = smbd_smb2_request_process_getinfo(req);
2533 case SMB2_OP_SETINFO:
2534 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
2535 req->profile, _INBYTES(req));
2536 return_value = smbd_smb2_request_process_setinfo(req);
2540 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
2541 req->profile, _INBYTES(req));
2542 return_value = smbd_smb2_request_process_break(req);
2546 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2549 return return_value;
2552 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2554 struct smbXsrv_connection *xconn = req->xconn;
2556 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2557 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2558 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2563 TALLOC_FREE(req->async_te);
2565 if (req->do_encryption &&
2566 (firsttf->iov_len == 0) &&
2567 (req->first_key.length == 0) &&
2568 (req->session != NULL) &&
2569 (req->session->global->encryption_key.length != 0))
2571 DATA_BLOB encryption_key = req->session->global->encryption_key;
2573 uint64_t session_id = req->session->global->session_wire_id;
2574 uint64_t nonce_high;
2577 status = smb2_get_new_nonce(req->session,
2580 if (!NT_STATUS_IS_OK(status)) {
2585 * We need to place the SMB2_TRANSFORM header before the
2590 * we need to remember the encryption key
2591 * and defer the signing/encryption until
2592 * we are sure that we do not change
2595 req->first_key = data_blob_dup_talloc(req, encryption_key);
2596 if (req->first_key.data == NULL) {
2597 return NT_STATUS_NO_MEMORY;
2600 tf = talloc_zero_array(req, uint8_t,
2603 return NT_STATUS_NO_MEMORY;
2606 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2607 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2608 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2609 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2611 firsttf->iov_base = (void *)tf;
2612 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2615 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2616 (req->last_key.length > 0) &&
2617 (firsttf->iov_len == 0))
2619 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2620 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2623 * As we are sure the header of the last request in the
2624 * compound chain will not change, we can to sign here
2625 * with the last signing key we remembered.
2627 status = smb2_signing_sign_pdu(req->last_key,
2630 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2631 if (!NT_STATUS_IS_OK(status)) {
2635 if (req->last_key.length > 0) {
2636 data_blob_clear_free(&req->last_key);
2639 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
2640 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
2642 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2644 if (req->current_idx < req->out.vector_count) {
2646 * We must process the remaining compound
2647 * SMB2 requests before any new incoming SMB2
2648 * requests. This is because incoming SMB2
2649 * requests may include a cancel for a
2650 * compound request we haven't processed
2653 struct tevent_immediate *im = tevent_create_immediate(req);
2655 return NT_STATUS_NO_MEMORY;
2658 if (req->do_signing && firsttf->iov_len == 0) {
2659 struct smbXsrv_session *x = req->session;
2660 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2663 * we need to remember the signing key
2664 * and defer the signing until
2665 * we are sure that we do not change
2668 req->last_key = data_blob_dup_talloc(req, signing_key);
2669 if (req->last_key.data == NULL) {
2670 return NT_STATUS_NO_MEMORY;
2674 tevent_schedule_immediate(im,
2676 smbd_smb2_request_dispatch_immediate,
2678 return NT_STATUS_OK;
2681 if (req->compound_related) {
2682 req->compound_related = false;
2685 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2687 return NT_STATUS_INVALID_PARAMETER_MIX;
2690 /* Set credit for these operations (zero credits if this
2691 is a final reply for an async operation). */
2692 smb2_calculate_credits(req, req);
2695 * now check if we need to sign the current response
2697 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2698 status = smb2_signing_encrypt_pdu(req->first_key,
2699 xconn->smb2.server.cipher,
2701 req->out.vector_count - first_idx);
2702 if (!NT_STATUS_IS_OK(status)) {
2705 } else if (req->do_signing) {
2706 struct smbXsrv_session *x = req->session;
2707 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2709 status = smb2_signing_sign_pdu(signing_key,
2712 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2713 if (!NT_STATUS_IS_OK(status)) {
2717 if (req->first_key.length > 0) {
2718 data_blob_clear_free(&req->first_key);
2721 if (req->preauth != NULL) {
2722 struct hc_sha512state sctx;
2725 samba_SHA512_Init(&sctx);
2726 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2727 sizeof(req->preauth->sha512_value));
2728 for (i = 1; i < req->in.vector_count; i++) {
2729 samba_SHA512_Update(&sctx,
2730 req->in.vector[i].iov_base,
2731 req->in.vector[i].iov_len);
2733 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2735 samba_SHA512_Init(&sctx);
2736 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2737 sizeof(req->preauth->sha512_value));
2738 for (i = 1; i < req->out.vector_count; i++) {
2739 samba_SHA512_Update(&sctx,
2740 req->out.vector[i].iov_base,
2741 req->out.vector[i].iov_len);
2743 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2745 req->preauth = NULL;
2748 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2749 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2750 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2751 /* Dynamic part is NULL. Chop it off,
2752 We're going to send it via sendfile. */
2753 req->out.vector_count -= 1;
2757 * We're done with this request -
2758 * move it off the "being processed" queue.
2760 DLIST_REMOVE(xconn->smb2.requests, req);
2762 req->queue_entry.mem_ctx = req;
2763 req->queue_entry.vector = req->out.vector;
2764 req->queue_entry.count = req->out.vector_count;
2765 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry);
2766 xconn->smb2.send_queue_len++;
2768 status = smbd_smb2_flush_send_queue(xconn);
2769 if (!NT_STATUS_IS_OK(status)) {
2773 return NT_STATUS_OK;
2776 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
2778 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2779 struct tevent_immediate *im,
2782 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2783 struct smbd_smb2_request);
2784 struct smbXsrv_connection *xconn = req->xconn;
2789 if (DEBUGLEVEL >= 10) {
2790 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2791 req->current_idx, req->in.vector_count));
2792 print_req_vectors(req);
2795 status = smbd_smb2_request_dispatch(req);
2796 if (!NT_STATUS_IS_OK(status)) {
2797 smbd_server_connection_terminate(xconn, nt_errstr(status));
2801 status = smbd_smb2_request_next_incoming(xconn);
2802 if (!NT_STATUS_IS_OK(status)) {
2803 smbd_server_connection_terminate(xconn, nt_errstr(status));
2808 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2810 DATA_BLOB body, DATA_BLOB *dyn,
2811 const char *location)
2814 struct iovec *outbody_v;
2815 struct iovec *outdyn_v;
2816 uint32_t next_command_ofs;
2818 DEBUG(10,("smbd_smb2_request_done_ex: "
2819 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2820 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2822 (unsigned int)(dyn ? dyn->length : 0),
2825 if (body.length < 2) {
2826 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2829 if ((body.length % 2) != 0) {
2830 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2833 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2834 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2835 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2837 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2838 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2840 outbody_v->iov_base = (void *)body.data;
2841 outbody_v->iov_len = body.length;
2844 outdyn_v->iov_base = (void *)dyn->data;
2845 outdyn_v->iov_len = dyn->length;
2847 outdyn_v->iov_base = NULL;
2848 outdyn_v->iov_len = 0;
2852 * See if we need to recalculate the offset to the next response
2854 * Note that all responses may require padding (including the very last
2857 if (req->out.vector_count >= (2 * SMBD_SMB2_NUM_IOV_PER_REQ)) {
2858 next_command_ofs = SMB2_HDR_BODY;
2859 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2860 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2863 if ((next_command_ofs % 8) != 0) {
2864 size_t pad_size = 8 - (next_command_ofs % 8);
2865 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2867 * if the dyn buffer is empty
2868 * we can use it to add padding
2872 pad = talloc_zero_array(req,
2875 return smbd_smb2_request_error(req,
2876 NT_STATUS_NO_MEMORY);
2879 outdyn_v->iov_base = (void *)pad;
2880 outdyn_v->iov_len = pad_size;
2883 * For now we copy the dynamic buffer
2884 * and add the padding to the new buffer
2891 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2892 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2894 new_size = old_size + pad_size;
2895 new_dyn = talloc_zero_array(req,
2897 if (new_dyn == NULL) {
2898 return smbd_smb2_request_error(req,
2899 NT_STATUS_NO_MEMORY);
2902 memcpy(new_dyn, old_dyn, old_size);
2903 memset(new_dyn + old_size, 0, pad_size);
2905 outdyn_v->iov_base = (void *)new_dyn;
2906 outdyn_v->iov_len = new_size;
2908 next_command_ofs += pad_size;
2911 if ((req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) >= req->out.vector_count) {
2912 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
2914 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2916 return smbd_smb2_request_reply(req);
2919 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2922 const char *location)
2924 struct smbXsrv_connection *xconn = req->xconn;
2927 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2928 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2930 DBG_NOTICE("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| "
2931 "at %s\n", req->current_idx, nt_errstr(status),
2932 info ? " +info" : "", location);
2935 /* Recvfile error. Drain incoming socket. */
2939 ret = drain_socket(xconn->transport.sock, unread_bytes);
2940 if (ret != unread_bytes) {
2944 error = NT_STATUS_IO_DEVICE_ERROR;
2946 error = map_nt_error_from_unix_common(errno);
2949 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2950 "ret[%u] errno[%d] => %s\n",
2951 (unsigned)unread_bytes,
2952 (unsigned)ret, errno, nt_errstr(error)));
2957 body.data = outhdr + SMB2_HDR_BODY;
2959 SSVAL(body.data, 0, 9);
2962 SIVAL(body.data, 0x04, info->length);
2964 /* Allocated size of req->out.vector[i].iov_base
2965 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2966 * 1 byte without having to do an alloc.
2969 info->data = ((uint8_t *)outhdr) +
2970 OUTVEC_ALLOC_SIZE - 1;
2972 SCVAL(info->data, 0, 0);
2976 * Note: Even if there is an error, continue to process the request.
2980 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2984 struct smbd_smb2_send_break_state {
2985 struct smbd_smb2_send_queue queue_entry;
2986 uint8_t nbt_hdr[NBT_HDR_SIZE];
2987 uint8_t tf[SMB2_TF_HDR_SIZE];
2988 uint8_t hdr[SMB2_HDR_BODY];
2989 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2993 static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
2994 struct smbXsrv_session *session,
2995 struct smbXsrv_tcon *tcon,
2996 const uint8_t *body,
2999 struct smbd_smb2_send_break_state *state;
3000 bool do_encryption = false;
3001 uint64_t session_wire_id = 0;
3002 uint64_t nonce_high = 0;
3003 uint64_t nonce_low = 0;
3008 if (session != NULL) {
3009 session_wire_id = session->global->session_wire_id;
3010 do_encryption = session->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
3011 if (tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
3012 do_encryption = true;
3016 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
3019 state = talloc_zero_size(xconn, statelen);
3020 if (state == NULL) {
3021 return NT_STATUS_NO_MEMORY;
3023 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
3025 if (do_encryption) {
3026 status = smb2_get_new_nonce(session,
3029 if (!NT_STATUS_IS_OK(status)) {
3034 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
3035 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
3036 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
3037 SBVAL(state->tf, SMB2_TF_SESSION_ID, session_wire_id);
3039 SIVAL(state->hdr, 0, SMB2_MAGIC);
3040 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
3041 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
3042 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
3043 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
3044 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
3045 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
3046 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
3047 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
3048 SIVAL(state->hdr, SMB2_HDR_PID, 0);
3049 SIVAL(state->hdr, SMB2_HDR_TID, 0);
3050 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
3051 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
3053 state->vector[0] = (struct iovec) {
3054 .iov_base = state->nbt_hdr,
3055 .iov_len = sizeof(state->nbt_hdr)
3058 if (do_encryption) {
3059 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3060 .iov_base = state->tf,
3061 .iov_len = sizeof(state->tf)
3064 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3070 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
3071 .iov_base = state->hdr,
3072 .iov_len = sizeof(state->hdr)
3075 memcpy(state->body, body, body_len);
3077 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
3078 .iov_base = state->body,
3079 .iov_len = body_len /* no sizeof(state->body) .. :-) */
3083 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
3086 ok = smb2_setup_nbt_length(state->vector,
3087 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
3089 return NT_STATUS_INVALID_PARAMETER_MIX;
3092 if (do_encryption) {
3093 DATA_BLOB encryption_key = session->global->encryption_key;
3095 status = smb2_signing_encrypt_pdu(encryption_key,
3096 xconn->smb2.server.cipher,
3097 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
3098 SMBD_SMB2_NUM_IOV_PER_REQ);
3099 if (!NT_STATUS_IS_OK(status)) {
3104 state->queue_entry.mem_ctx = state;
3105 state->queue_entry.vector = state->vector;
3106 state->queue_entry.count = ARRAY_SIZE(state->vector);
3107 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
3108 xconn->smb2.send_queue_len++;
3110 status = smbd_smb2_flush_send_queue(xconn);
3111 if (!NT_STATUS_IS_OK(status)) {
3115 return NT_STATUS_OK;
3118 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_connection *xconn,
3119 struct smbXsrv_session *session,
3120 struct smbXsrv_tcon *tcon,
3121 struct smbXsrv_open *op,
3122 uint8_t oplock_level)
3126 SSVAL(body, 0x00, sizeof(body));
3127 SCVAL(body, 0x02, oplock_level);
3128 SCVAL(body, 0x03, 0); /* reserved */
3129 SIVAL(body, 0x04, 0); /* reserved */
3130 SBVAL(body, 0x08, op->global->open_persistent_id);
3131 SBVAL(body, 0x10, op->global->open_volatile_id);
3133 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3136 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_connection *xconn,
3138 uint32_t lease_flags,
3139 struct smb2_lease_key *lease_key,
3140 uint32_t current_lease_state,
3141 uint32_t new_lease_state)
3145 SSVAL(body, 0x00, sizeof(body));
3146 SSVAL(body, 0x02, new_epoch);
3147 SIVAL(body, 0x04, lease_flags);
3148 SBVAL(body, 0x08, lease_key->data[0]);
3149 SBVAL(body, 0x10, lease_key->data[1]);
3150 SIVAL(body, 0x18, current_lease_state);
3151 SIVAL(body, 0x1c, new_lease_state);
3152 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
3153 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
3154 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
3156 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3159 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
3163 uint64_t file_id_persistent;
3164 uint64_t file_id_volatile;
3165 struct smbXsrv_open *op = NULL;
3166 struct files_struct *fsp = NULL;
3167 const uint8_t *body = NULL;
3170 * This is only called with a pktbuf
3171 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
3175 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
3176 /* Transform header. Cannot recvfile. */
3179 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
3180 /* Not SMB2. Normal error path will cope. */
3183 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
3184 /* Not SMB2. Normal error path will cope. */
3187 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
3188 /* Needs to be a WRITE. */
3191 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
3192 /* Chained. Cannot recvfile. */
3195 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
3196 if (flags & SMB2_HDR_FLAG_CHAINED) {
3197 /* Chained. Cannot recvfile. */
3200 if (flags & SMB2_HDR_FLAG_SIGNED) {
3201 /* Signed. Cannot recvfile. */
3205 body = &state->pktbuf[SMB2_HDR_BODY];
3207 file_id_persistent = BVAL(body, 0x10);
3208 file_id_volatile = BVAL(body, 0x18);
3210 status = smb2srv_open_lookup(state->req->xconn,
3215 if (!NT_STATUS_IS_OK(status)) {
3223 if (fsp->conn == NULL) {
3227 if (IS_IPC(fsp->conn)) {
3230 if (IS_PRINT(fsp->conn)) {
3234 DEBUG(10,("Doing recvfile write len = %u\n",
3235 (unsigned int)(state->pktfull - state->pktlen)));
3240 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
3242 struct smbd_server_connection *sconn = xconn->client->sconn;
3243 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3244 size_t max_send_queue_len;
3245 size_t cur_send_queue_len;
3247 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3249 * we're not supposed to do any io
3251 return NT_STATUS_OK;
3254 if (state->req != NULL) {
3256 * if there is already a tstream_readv_pdu
3257 * pending, we are done.
3259 return NT_STATUS_OK;
3262 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
3263 cur_send_queue_len = xconn->smb2.send_queue_len;
3265 if (cur_send_queue_len > max_send_queue_len) {
3267 * if we have a lot of requests to send,
3268 * we wait until they are on the wire until we
3269 * ask for the next request.
3271 return NT_STATUS_OK;
3274 /* ask for the next request */
3275 ZERO_STRUCTP(state);
3276 state->req = smbd_smb2_request_allocate(xconn);
3277 if (state->req == NULL) {
3278 return NT_STATUS_NO_MEMORY;
3280 state->req->sconn = sconn;
3281 state->req->xconn = xconn;
3282 state->min_recv_size = lp_min_receive_file_size();
3284 TEVENT_FD_READABLE(xconn->transport.fde);
3286 return NT_STATUS_OK;
3289 void smbd_smb2_process_negprot(struct smbXsrv_connection *xconn,
3290 uint64_t expected_seq_low,
3291 const uint8_t *inpdu, size_t size)
3293 struct smbd_server_connection *sconn = xconn->client->sconn;
3295 struct smbd_smb2_request *req = NULL;
3297 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3298 (unsigned int)size));
3300 status = smbd_initialize_smb2(xconn, expected_seq_low);
3301 if (!NT_STATUS_IS_OK(status)) {
3302 smbd_server_connection_terminate(xconn, nt_errstr(status));
3306 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
3307 if (!NT_STATUS_IS_OK(status)) {
3308 smbd_server_connection_terminate(xconn, nt_errstr(status));
3312 status = smbd_smb2_request_validate(req);
3313 if (!NT_STATUS_IS_OK(status)) {
3314 smbd_server_connection_terminate(xconn, nt_errstr(status));
3318 status = smbd_smb2_request_setup_out(req);
3319 if (!NT_STATUS_IS_OK(status)) {
3320 smbd_server_connection_terminate(xconn, nt_errstr(status));
3326 * this was already counted at the SMB1 layer =>
3327 * smbd_smb2_request_dispatch() should not count it twice.
3329 if (profile_p->values.request_stats.count > 0) {
3330 profile_p->values.request_stats.count--;
3333 status = smbd_smb2_request_dispatch(req);
3334 if (!NT_STATUS_IS_OK(status)) {
3335 smbd_server_connection_terminate(xconn, nt_errstr(status));
3339 status = smbd_smb2_request_next_incoming(xconn);
3340 if (!NT_STATUS_IS_OK(status)) {
3341 smbd_server_connection_terminate(xconn, nt_errstr(status));
3345 sconn->num_requests++;
3348 static int socket_error_from_errno(int ret,
3362 if (sys_errno == 0) {
3366 if (sys_errno == EINTR) {
3371 if (sys_errno == EINPROGRESS) {
3376 if (sys_errno == EAGAIN) {
3381 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3382 if (sys_errno == ENOMEM) {
3388 #if EWOULDBLOCK != EAGAIN
3389 if (sys_errno == EWOULDBLOCK) {
3399 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3405 if (xconn->smb2.send_queue == NULL) {
3406 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3407 return NT_STATUS_OK;
3410 while (xconn->smb2.send_queue != NULL) {
3411 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3414 if (e->sendfile_header != NULL) {
3415 NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
3420 for (i=0; i < e->count; i++) {
3421 size += e->vector[i].iov_len;
3424 if (size <= e->sendfile_header->length) {
3425 buf = e->sendfile_header->data;
3427 buf = talloc_array(e->mem_ctx, uint8_t, size);
3429 return NT_STATUS_NO_MEMORY;
3434 for (i=0; i < e->count; i++) {
3436 e->vector[i].iov_base,
3437 e->vector[i].iov_len);
3438 size += e->vector[i].iov_len;
3441 e->sendfile_header->data = buf;
3442 e->sendfile_header->length = size;
3443 e->sendfile_status = &status;
3446 xconn->smb2.send_queue_len--;
3447 DLIST_REMOVE(xconn->smb2.send_queue, e);
3449 * This triggers the sendfile path via
3452 talloc_free(e->mem_ctx);
3454 if (!NT_STATUS_IS_OK(status)) {
3460 ret = writev(xconn->transport.sock, e->vector, e->count);
3462 /* propagate end of file */
3463 return NT_STATUS_INTERNAL_ERROR;
3465 err = socket_error_from_errno(ret, errno, &retry);
3468 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3469 return NT_STATUS_OK;
3472 return map_nt_error_from_unix_common(err);
3475 ok = iov_advance(&e->vector, &e->count, ret);
3477 return NT_STATUS_INTERNAL_ERROR;
3481 /* we have more to write */
3482 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3483 return NT_STATUS_OK;
3486 xconn->smb2.send_queue_len--;
3487 DLIST_REMOVE(xconn->smb2.send_queue, e);
3488 talloc_free(e->mem_ctx);
3491 return NT_STATUS_OK;
3494 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3497 struct smbd_server_connection *sconn = xconn->client->sconn;
3498 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3499 struct smbd_smb2_request *req = NULL;
3500 size_t min_recvfile_size = UINT32_MAX;
3507 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3509 * we're not supposed to do any io
3511 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3512 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3513 return NT_STATUS_OK;
3516 if (fde_flags & TEVENT_FD_WRITE) {
3517 status = smbd_smb2_flush_send_queue(xconn);
3518 if (!NT_STATUS_IS_OK(status)) {
3523 if (!(fde_flags & TEVENT_FD_READ)) {
3524 return NT_STATUS_OK;
3527 if (state->req == NULL) {
3528 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3529 return NT_STATUS_OK;
3533 if (!state->hdr.done) {
3534 state->hdr.done = true;
3536 state->vector.iov_base = (void *)state->hdr.nbt;
3537 state->vector.iov_len = NBT_HDR_SIZE;
3540 ret = readv(xconn->transport.sock, &state->vector, 1);
3542 /* propagate end of file */
3543 return NT_STATUS_END_OF_FILE;
3545 err = socket_error_from_errno(ret, errno, &retry);
3548 TEVENT_FD_READABLE(xconn->transport.fde);
3549 return NT_STATUS_OK;
3552 return map_nt_error_from_unix_common(err);
3555 if (ret < state->vector.iov_len) {
3557 base = (uint8_t *)state->vector.iov_base;
3559 state->vector.iov_base = (void *)base;
3560 state->vector.iov_len -= ret;
3561 /* we have more to read */
3562 TEVENT_FD_READABLE(xconn->transport.fde);
3563 return NT_STATUS_OK;
3566 if (state->pktlen > 0) {
3567 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3569 * Not a possible receivefile write.
3570 * Read the rest of the data.
3572 state->doing_receivefile = false;
3574 state->pktbuf = talloc_realloc(state->req,
3578 if (state->pktbuf == NULL) {
3579 return NT_STATUS_NO_MEMORY;
3582 state->vector.iov_base = (void *)(state->pktbuf +
3584 state->vector.iov_len = (state->pktfull -
3587 state->pktlen = state->pktfull;
3592 * Either this is a receivefile write so we've
3593 * done a short read, or if not we have all the data.
3599 * Now we analyze the NBT header
3601 if (state->hdr.nbt[0] != 0x00) {
3602 state->min_recv_size = 0;
3604 state->pktfull = smb2_len(state->hdr.nbt);
3605 if (state->pktfull == 0) {
3609 if (state->min_recv_size != 0) {
3610 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3611 min_recvfile_size += state->min_recv_size;
3614 if (state->pktfull > min_recvfile_size) {
3616 * Might be a receivefile write. Read the SMB2 HEADER +
3617 * SMB2_WRITE header first. Set 'doing_receivefile'
3618 * as we're *attempting* receivefile write. If this
3619 * turns out not to be a SMB2_WRITE request or otherwise
3620 * not suitable then we'll just read the rest of the data
3621 * the next time this function is called.
3623 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3624 state->doing_receivefile = true;
3626 state->pktlen = state->pktfull;
3629 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3630 if (state->pktbuf == NULL) {
3631 return NT_STATUS_NO_MEMORY;
3634 state->vector.iov_base = (void *)state->pktbuf;
3635 state->vector.iov_len = state->pktlen;
3641 if (state->hdr.nbt[0] != 0x00) {
3642 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3643 state->hdr.nbt[0]));
3646 ZERO_STRUCTP(state);
3648 state->min_recv_size = lp_min_receive_file_size();
3656 req->request_time = timeval_current();
3657 now = timeval_to_nttime(&req->request_time);
3659 status = smbd_smb2_inbuf_parse_compound(xconn,
3665 &req->in.vector_count);
3666 if (!NT_STATUS_IS_OK(status)) {
3670 if (state->doing_receivefile) {
3671 req->smb1req = talloc_zero(req, struct smb_request);
3672 if (req->smb1req == NULL) {
3673 return NT_STATUS_NO_MEMORY;
3675 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3678 ZERO_STRUCTP(state);
3680 req->current_idx = 1;
3682 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3683 req->current_idx, req->in.vector_count));
3685 status = smbd_smb2_request_validate(req);
3686 if (!NT_STATUS_IS_OK(status)) {
3690 status = smbd_smb2_request_setup_out(req);
3691 if (!NT_STATUS_IS_OK(status)) {
3695 status = smbd_smb2_request_dispatch(req);
3696 if (!NT_STATUS_IS_OK(status)) {
3700 sconn->num_requests++;
3702 /* The timeout_processing function isn't run nearly
3703 often enough to implement 'max log size' without
3704 overrunning the size of the file by many megabytes.
3705 This is especially true if we are running at debug
3706 level 10. Checking every 50 SMB2s is a nice
3707 tradeoff of performance vs log file size overrun. */
3709 if ((sconn->num_requests % 50) == 0 &&
3710 need_to_check_log_size()) {
3711 change_to_root_user();
3715 status = smbd_smb2_request_next_incoming(xconn);
3716 if (!NT_STATUS_IS_OK(status)) {
3720 return NT_STATUS_OK;
3723 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3724 struct tevent_fd *fde,
3728 struct smbXsrv_connection *xconn =
3729 talloc_get_type_abort(private_data,
3730 struct smbXsrv_connection);
3733 status = smbd_smb2_io_handler(xconn, flags);
3734 if (!NT_STATUS_IS_OK(status)) {
3735 smbd_server_connection_terminate(xconn, nt_errstr(status));