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"
33 #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9)
35 static const struct smbd_smb2_dispatch_table {
42 bool allow_invalid_fileid;
43 } smbd_smb2_table[] = {
44 #define _OP(o) .opcode = o, .name = #o
49 _OP(SMB2_OP_SESSSETUP),
59 * This call needs to be run as root.
61 * smbd_smb2_request_process_tcon()
62 * calls make_connection_snum(), which will call
63 * change_to_user(), when needed.
102 .need_session = true,
105 .allow_invalid_fileid = true,
110 _OP(SMB2_OP_KEEPALIVE),
114 .need_session = true,
119 .need_session = true,
123 _OP(SMB2_OP_GETINFO),
124 .need_session = true,
128 _OP(SMB2_OP_SETINFO),
129 .need_session = true,
134 .need_session = true,
139 * as LEASE breaks does not
145 const char *smb2_opcode_name(uint16_t opcode)
147 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
148 return "Bad SMB2 opcode";
150 return smbd_smb2_table[opcode].name;
153 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
155 const struct smbd_smb2_dispatch_table *ret = NULL;
157 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
161 ret = &smbd_smb2_table[opcode];
163 SMB_ASSERT(ret->opcode == opcode);
168 static void print_req_vectors(const struct smbd_smb2_request *req)
172 for (i = 0; i < req->in.vector_count; i++) {
173 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
175 (unsigned int)req->in.vector[i].iov_len);
177 for (i = 0; i < req->out.vector_count; i++) {
178 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
180 (unsigned int)req->out.vector[i].iov_len);
184 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
186 if (size < (4 + SMB2_HDR_BODY)) {
190 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
197 static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
202 TALLOC_FREE(sconn->smb1.fde);
204 sconn->smb2.recv_queue = tevent_queue_create(sconn, "smb2 recv queue");
205 if (sconn->smb2.recv_queue == NULL) {
206 return NT_STATUS_NO_MEMORY;
209 sconn->smb2.send_queue = tevent_queue_create(sconn, "smb2 send queue");
210 if (sconn->smb2.send_queue == NULL) {
211 return NT_STATUS_NO_MEMORY;
214 sconn->smb2.seqnum_low = 0;
215 sconn->smb2.seqnum_range = 1;
216 sconn->smb2.credits_granted = 1;
217 sconn->smb2.max_credits = lp_smb2_max_credits();
218 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
219 sconn->smb2.max_credits);
220 if (sconn->smb2.credits_bitmap == NULL) {
221 return NT_STATUS_NO_MEMORY;
224 ret = tstream_bsd_existing_socket(sconn, sconn->sock,
225 &sconn->smb2.stream);
227 status = map_nt_error_from_unix(errno);
231 /* Ensure child is set to non-blocking mode */
232 set_blocking(sconn->sock, false);
236 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
237 #define _smb2_setlen(_buf,len) do { \
238 uint8_t *buf = (uint8_t *)_buf; \
240 buf[1] = ((len)&0xFF0000)>>16; \
241 buf[2] = ((len)&0xFF00)>>8; \
242 buf[3] = (len)&0xFF; \
245 static void smb2_setup_nbt_length(struct iovec *vector, int count)
250 for (i=1; i < count; i++) {
251 len += vector[i].iov_len;
254 _smb2_setlen(vector[0].iov_base, len);
257 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
259 data_blob_clear_free(&req->first_key);
260 data_blob_clear_free(&req->last_key);
264 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
266 TALLOC_CTX *mem_pool;
267 struct smbd_smb2_request *req;
270 /* Enable this to find subtle valgrind errors. */
271 mem_pool = talloc_init("smbd_smb2_request_allocate");
273 mem_pool = talloc_pool(mem_ctx, 8192);
275 if (mem_pool == NULL) {
279 req = talloc_zero(mem_pool, struct smbd_smb2_request);
281 talloc_free(mem_pool);
284 talloc_reparent(mem_pool, mem_ctx, req);
285 TALLOC_FREE(mem_pool);
287 req->last_session_id = UINT64_MAX;
288 req->last_tid = UINT32_MAX;
290 talloc_set_destructor(req, smbd_smb2_request_destructor);
295 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn,
306 uint8_t *first_hdr = buf;
307 size_t verified_buflen = 0;
312 * Note: index '0' is reserved for the transport protocol
314 iov = talloc_zero_array(mem_ctx, struct iovec, num_iov);
316 return NT_STATUS_NO_MEMORY;
319 while (taken < buflen) {
320 size_t len = buflen - taken;
321 uint8_t *hdr = first_hdr + taken;
324 size_t next_command_ofs;
326 uint8_t *body = NULL;
329 struct iovec *iov_tmp;
331 if (verified_buflen > taken) {
332 len = verified_buflen - taken;
339 DEBUG(10, ("%d bytes left, expected at least %d\n",
343 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
344 struct smbXsrv_session *s = NULL;
346 struct iovec tf_iov[2];
350 if (conn->protocol < PROTOCOL_SMB2_24) {
351 DEBUG(10, ("Got SMB2_TRANSFORM header, "
352 "but dialect[0x%04X] is used\n",
353 conn->smb2.server.dialect));
357 if (!(conn->smb2.server.capabilities & SMB2_CAP_ENCRYPTION)) {
358 DEBUG(10, ("Got SMB2_TRANSFORM header, "
359 "but not negotiated "
360 "client[0x%08X] server[0x%08X]\n",
361 conn->smb2.client.capabilities,
362 conn->smb2.server.capabilities));
366 if (len < SMB2_TF_HDR_SIZE) {
367 DEBUG(1, ("%d bytes left, expected at least %d\n",
368 (int)len, SMB2_TF_HDR_SIZE));
372 tf_len = SMB2_TF_HDR_SIZE;
375 hdr = first_hdr + taken;
376 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
377 uid = BVAL(tf, SMB2_TF_SESSION_ID);
379 if (len < SMB2_TF_HDR_SIZE + enc_len) {
380 DEBUG(1, ("%d bytes left, expected at least %d\n",
382 (int)(SMB2_TF_HDR_SIZE + enc_len)));
386 status = smb2srv_session_lookup(conn, uid, now, &s);
388 DEBUG(1, ("invalid session[%llu] in "
389 "SMB2_TRANSFORM header\n",
390 (unsigned long long)uid));
392 return NT_STATUS_USER_SESSION_DELETED;
395 tf_iov[0].iov_base = (void *)tf;
396 tf_iov[0].iov_len = tf_len;
397 tf_iov[1].iov_base = (void *)hdr;
398 tf_iov[1].iov_len = enc_len;
400 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
403 if (!NT_STATUS_IS_OK(status)) {
408 verified_buflen = taken + enc_len;
413 * We need the header plus the body length field
416 if (len < SMB2_HDR_BODY + 2) {
417 DEBUG(10, ("%d bytes left, expected at least %d\n",
418 (int)len, SMB2_HDR_BODY));
421 if (IVAL(hdr, 0) != SMB2_MAGIC) {
422 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
426 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
427 DEBUG(10, ("Got HDR len %d, expected %d\n",
428 SVAL(hdr, 4), SMB2_HDR_BODY));
433 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
434 body_size = SVAL(hdr, SMB2_HDR_BODY);
436 if (next_command_ofs != 0) {
437 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
440 if (next_command_ofs > full_size) {
443 full_size = next_command_ofs;
450 if (body_size > (full_size - SMB2_HDR_BODY)) {
452 * let the caller handle the error
454 body_size = full_size - SMB2_HDR_BODY;
456 body = hdr + SMB2_HDR_BODY;
457 dyn = body + body_size;
458 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
460 iov_tmp = talloc_realloc(mem_ctx, iov, struct iovec,
461 num_iov + SMBD_SMB2_NUM_IOV_PER_REQ);
462 if (iov_tmp == NULL) {
464 return NT_STATUS_NO_MEMORY;
468 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
470 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
471 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
472 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
473 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
474 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
475 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
476 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
477 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
488 return NT_STATUS_INVALID_PARAMETER;
491 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
492 uint8_t *inbuf, size_t size,
493 struct smbd_smb2_request **_req)
495 struct smbd_smb2_request *req;
496 uint32_t protocol_version;
497 const uint8_t *inhdr = NULL;
499 uint32_t next_command_ofs;
503 if (size < (4 + SMB2_HDR_BODY + 2)) {
504 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
505 return NT_STATUS_INVALID_PARAMETER;
510 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
511 if (protocol_version != SMB2_MAGIC) {
512 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
514 return NT_STATUS_INVALID_PARAMETER;
517 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
518 if (cmd != SMB2_OP_NEGPROT) {
519 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
521 return NT_STATUS_INVALID_PARAMETER;
524 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
525 if (next_command_ofs != 0) {
526 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
528 return NT_STATUS_INVALID_PARAMETER;
531 req = smbd_smb2_request_allocate(sconn);
533 return NT_STATUS_NO_MEMORY;
537 talloc_steal(req, inbuf);
539 req->request_time = timeval_current();
540 now = timeval_to_nttime(&req->request_time);
542 status = smbd_smb2_inbuf_parse_compound(sconn->conn,
544 inbuf + NBT_HDR_SIZE,
546 req, &req->in.vector,
547 &req->in.vector_count);
548 if (!NT_STATUS_IS_OK(status)) {
553 req->current_idx = 1;
559 static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
560 uint64_t message_id, uint64_t seq_id)
562 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
565 if (seq_id < sconn->smb2.seqnum_low) {
566 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
567 "%llu (sequence id %llu) "
568 "(granted = %u, low = %llu, range = %u)\n",
569 (unsigned long long)message_id,
570 (unsigned long long)seq_id,
571 (unsigned int)sconn->smb2.credits_granted,
572 (unsigned long long)sconn->smb2.seqnum_low,
573 (unsigned int)sconn->smb2.seqnum_range));
577 if (seq_id >= sconn->smb2.seqnum_low + sconn->smb2.seqnum_range) {
578 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
579 "%llu (sequence id %llu) "
580 "(granted = %u, low = %llu, range = %u)\n",
581 (unsigned long long)message_id,
582 (unsigned long long)seq_id,
583 (unsigned int)sconn->smb2.credits_granted,
584 (unsigned long long)sconn->smb2.seqnum_low,
585 (unsigned int)sconn->smb2.seqnum_range));
589 offset = seq_id % sconn->smb2.max_credits;
591 if (bitmap_query(credits_bm, offset)) {
592 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
593 "%llu (sequence id %llu) "
594 "(granted = %u, low = %llu, range = %u) "
596 (unsigned long long)message_id,
597 (unsigned long long)seq_id,
598 (unsigned int)sconn->smb2.credits_granted,
599 (unsigned long long)sconn->smb2.seqnum_low,
600 (unsigned int)sconn->smb2.seqnum_range,
605 /* Mark the message_ids as seen in the bitmap. */
606 bitmap_set(credits_bm, offset);
608 if (seq_id != sconn->smb2.seqnum_low) {
613 * Move the window forward by all the message_id's
616 while (bitmap_query(credits_bm, offset)) {
617 DEBUG(10,("smb2_validate_sequence_number: clearing "
618 "id %llu (position %u) from bitmap\n",
619 (unsigned long long)(sconn->smb2.seqnum_low),
621 bitmap_clear(credits_bm, offset);
623 sconn->smb2.seqnum_low += 1;
624 sconn->smb2.seqnum_range -= 1;
625 offset = sconn->smb2.seqnum_low % sconn->smb2.max_credits;
631 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
632 const uint8_t *inhdr)
634 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
635 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
636 uint16_t credit_charge = 1;
639 if (opcode == SMB2_OP_CANCEL) {
640 /* SMB2_CANCEL requests by definition resend messageids. */
644 if (sconn->smb2.supports_multicredit) {
645 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
646 credit_charge = MAX(credit_charge, 1);
649 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
650 "credits_granted %llu, "
651 "seqnum low/range: %llu/%llu\n",
652 (unsigned long long) message_id,
653 (unsigned long long) credit_charge,
654 (unsigned long long) sconn->smb2.credits_granted,
655 (unsigned long long) sconn->smb2.seqnum_low,
656 (unsigned long long) sconn->smb2.seqnum_range));
658 if (sconn->smb2.credits_granted < credit_charge) {
659 DEBUG(0, ("smb2_validate_message_id: client used more "
660 "credits than granted, mid %llu, charge %llu, "
661 "credits_granted %llu, "
662 "seqnum low/range: %llu/%llu\n",
663 (unsigned long long) message_id,
664 (unsigned long long) credit_charge,
665 (unsigned long long) sconn->smb2.credits_granted,
666 (unsigned long long) sconn->smb2.seqnum_low,
667 (unsigned long long) sconn->smb2.seqnum_range));
672 * now check the message ids
674 * for multi-credit requests we need to check all current mid plus
675 * the implicit mids caused by the credit charge
676 * e.g. current mid = 15, charge 5 => mark 15-19 as used
679 for (i = 0; i <= (credit_charge-1); i++) {
680 uint64_t id = message_id + i;
683 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
684 (unsigned long long)message_id,
686 (unsigned long long)id));
688 ok = smb2_validate_sequence_number(sconn, message_id, id);
694 /* substract used credits */
695 sconn->smb2.credits_granted -= credit_charge;
700 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
705 count = req->in.vector_count;
707 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
708 /* It's not a SMB2 request */
709 return NT_STATUS_INVALID_PARAMETER;
712 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
713 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
714 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
715 const uint8_t *inhdr = NULL;
717 if (hdr->iov_len != SMB2_HDR_BODY) {
718 return NT_STATUS_INVALID_PARAMETER;
721 if (body->iov_len < 2) {
722 return NT_STATUS_INVALID_PARAMETER;
725 inhdr = (const uint8_t *)hdr->iov_base;
727 /* Check the SMB2 header */
728 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
729 return NT_STATUS_INVALID_PARAMETER;
732 if (!smb2_validate_message_id(req->sconn, inhdr)) {
733 return NT_STATUS_INVALID_PARAMETER;
740 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
741 const struct iovec *in_vector,
742 struct iovec *out_vector)
744 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
745 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
746 uint16_t credit_charge = 1;
747 uint16_t credits_requested;
751 uint16_t credits_granted = 0;
752 uint64_t credits_possible;
753 uint16_t current_max_credits;
756 * first we grant only 1/16th of the max range.
758 * Windows also starts with the 1/16th and then grants
759 * more later. I was only able to trigger higher
760 * values, when using a very high credit charge.
762 * TODO: scale up depending on load, free memory
764 * Maybe also on the relationship between number
765 * of requests and the used sequence number.
766 * Which means we would grant more credits
767 * for client which use multi credit requests.
769 current_max_credits = sconn->smb2.max_credits / 16;
770 current_max_credits = MAX(current_max_credits, 1);
772 if (sconn->smb2.supports_multicredit) {
773 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
774 credit_charge = MAX(credit_charge, 1);
777 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
778 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
779 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
780 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
782 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
784 if (sconn->smb2.max_credits < credit_charge) {
785 smbd_server_connection_terminate(sconn,
786 "client error: credit charge > max credits\n");
790 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
792 * In case we already send an async interim
793 * response, we should not grant
794 * credits on the final response.
797 } else if (credits_requested > 0) {
798 uint16_t additional_max = 0;
799 uint16_t additional_credits = credits_requested - 1;
802 case SMB2_OP_NEGPROT:
804 case SMB2_OP_SESSSETUP:
806 * Windows 2012 RC1 starts to grant
808 * with a successful session setup
810 if (NT_STATUS_IS_OK(out_status)) {
816 * We match windows and only grant additional credits
823 additional_credits = MIN(additional_credits, additional_max);
825 credits_granted = credit_charge + additional_credits;
826 } else if (sconn->smb2.credits_granted == 0) {
828 * Make sure the client has always at least one credit
834 * sequence numbers should not wrap
836 * 1. calculate the possible credits until
837 * the sequence numbers start to wrap on 64-bit.
839 * 2. UINT64_MAX is used for Break Notifications.
841 * 2. truncate the possible credits to the maximum
842 * credits we want to grant to the client in total.
844 * 3. remove the range we'll already granted to the client
845 * this makes sure the client consumes the lowest sequence
846 * number, before we can grant additional credits.
848 credits_possible = UINT64_MAX - sconn->smb2.seqnum_low;
849 if (credits_possible > 0) {
850 /* remove UINT64_MAX */
851 credits_possible -= 1;
853 credits_possible = MIN(credits_possible, current_max_credits);
854 credits_possible -= sconn->smb2.seqnum_range;
856 credits_granted = MIN(credits_granted, credits_possible);
858 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
859 sconn->smb2.credits_granted += credits_granted;
860 sconn->smb2.seqnum_range += credits_granted;
862 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
863 "granted %u, current possible/max %u/%u, "
864 "total granted/max/low/range %u/%u/%llu/%u\n",
865 (unsigned int)credits_requested,
866 (unsigned int)credit_charge,
867 (unsigned int)credits_granted,
868 (unsigned int)credits_possible,
869 (unsigned int)current_max_credits,
870 (unsigned int)sconn->smb2.credits_granted,
871 (unsigned int)sconn->smb2.max_credits,
872 (unsigned long long)sconn->smb2.seqnum_low,
873 (unsigned int)sconn->smb2.seqnum_range));
876 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
877 struct smbd_smb2_request *outreq)
880 uint16_t total_credits = 0;
882 count = outreq->out.vector_count;
884 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
885 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
886 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
887 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
889 smb2_set_operation_credit(outreq->sconn, inhdr_v, outhdr_v);
891 /* To match Windows, count up what we
893 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
894 /* Set to zero in all but the last reply. */
895 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
896 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
898 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
903 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
905 struct iovec *vector;
909 count = req->in.vector_count;
910 vector = talloc_zero_array(req, struct iovec, count);
911 if (vector == NULL) {
912 return NT_STATUS_NO_MEMORY;
915 vector[0].iov_base = req->out.nbt_hdr;
916 vector[0].iov_len = 4;
917 SIVAL(req->out.nbt_hdr, 0, 0);
919 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
920 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
921 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
922 uint8_t *outhdr = NULL;
923 uint8_t *outbody = NULL;
924 uint32_t next_command_ofs = 0;
925 struct iovec *current = &vector[idx];
927 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
928 /* we have a next command -
929 * setup for the error case. */
930 next_command_ofs = SMB2_HDR_BODY + 9;
933 outhdr = talloc_zero_array(vector, uint8_t,
935 if (outhdr == NULL) {
936 return NT_STATUS_NO_MEMORY;
939 outbody = outhdr + SMB2_HDR_BODY;
942 * SMBD_SMB2_TF_IOV_OFS might be used later
944 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
945 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
947 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
948 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
950 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
951 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
953 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
954 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
956 /* setup the SMB2 header */
957 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
958 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
959 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
960 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
961 SIVAL(outhdr, SMB2_HDR_STATUS,
962 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
963 SSVAL(outhdr, SMB2_HDR_OPCODE,
964 SVAL(inhdr, SMB2_HDR_OPCODE));
965 SIVAL(outhdr, SMB2_HDR_FLAGS,
966 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
967 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
968 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
969 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
970 SIVAL(outhdr, SMB2_HDR_PID,
971 IVAL(inhdr, SMB2_HDR_PID));
972 SIVAL(outhdr, SMB2_HDR_TID,
973 IVAL(inhdr, SMB2_HDR_TID));
974 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
975 BVAL(inhdr, SMB2_HDR_SESSION_ID));
976 memcpy(outhdr + SMB2_HDR_SIGNATURE,
977 inhdr + SMB2_HDR_SIGNATURE, 16);
979 /* setup error body header */
980 SSVAL(outbody, 0x00, 0x08 + 1);
981 SSVAL(outbody, 0x02, 0);
982 SIVAL(outbody, 0x04, 0);
985 req->out.vector = vector;
986 req->out.vector_count = count;
988 /* setup the length of the NBT packet */
989 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
991 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
996 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
998 const char *location)
1000 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1002 exit_server_cleanly(reason);
1005 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1006 struct iovec *outvec,
1007 const struct iovec *srcvec)
1009 const uint8_t *srctf;
1011 const uint8_t *srchdr;
1013 const uint8_t *srcbody;
1015 const uint8_t *expected_srcbody;
1016 const uint8_t *srcdyn;
1018 const uint8_t *expected_srcdyn;
1024 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1025 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1026 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1027 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1028 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1029 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1030 expected_srcbody = srchdr + SMB2_HDR_BODY;
1031 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1032 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1033 expected_srcdyn = srcbody + 8;
1035 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1039 if (srchdr_len != SMB2_HDR_BODY) {
1043 if (srctf_len == SMB2_TF_HDR_SIZE) {
1044 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1045 if (dsttf == NULL) {
1051 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1052 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1054 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1055 * be allocated with size OUTVEC_ALLOC_SIZE. */
1057 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1058 if (dsthdr == NULL) {
1061 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1062 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1065 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1066 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1067 * then duplicate this. Else use talloc_memdup().
1070 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1071 dstbody = dsthdr + SMB2_HDR_BODY;
1073 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1074 if (dstbody == NULL) {
1078 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1079 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1082 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1084 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1085 * then duplicate this. Else use talloc_memdup().
1088 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1089 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1090 } else if (srcdyn == NULL) {
1093 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1094 if (dstdyn == NULL) {
1098 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1099 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1104 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1106 struct smbd_smb2_request *newreq = NULL;
1107 struct iovec *outvec = NULL;
1108 int count = req->out.vector_count;
1111 newreq = smbd_smb2_request_allocate(req->sconn);
1116 newreq->sconn = req->sconn;
1117 newreq->session = req->session;
1118 newreq->do_encryption = req->do_encryption;
1119 newreq->do_signing = req->do_signing;
1120 newreq->current_idx = req->current_idx;
1122 outvec = talloc_zero_array(newreq, struct iovec, count);
1124 TALLOC_FREE(newreq);
1127 newreq->out.vector = outvec;
1128 newreq->out.vector_count = count;
1130 /* Setup the outvec's identically to req. */
1131 outvec[0].iov_base = newreq->out.nbt_hdr;
1132 outvec[0].iov_len = 4;
1133 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1135 /* Setup the vectors identically to the ones in req. */
1136 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1137 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1144 TALLOC_FREE(newreq);
1148 smb2_setup_nbt_length(newreq->out.vector,
1149 newreq->out.vector_count);
1154 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
1156 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1158 struct smbXsrv_connection *conn = req->sconn->conn;
1160 struct iovec *firsttf = NULL;
1161 struct iovec *outhdr_v = NULL;
1162 uint8_t *outhdr = NULL;
1163 struct smbd_smb2_request *nreq = NULL;
1166 /* Create a new smb2 request we'll use
1167 for the interim return. */
1168 nreq = dup_smb2_req(req);
1170 return NT_STATUS_NO_MEMORY;
1173 /* Lose the last X out vectors. They're the
1174 ones we'll be using for the async reply. */
1175 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1177 smb2_setup_nbt_length(nreq->out.vector,
1178 nreq->out.vector_count);
1180 /* Step back to the previous reply. */
1181 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1182 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1183 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1184 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1185 /* And end the chain. */
1186 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1188 /* Calculate outgoing credits */
1189 smb2_calculate_credits(req, nreq);
1191 if (DEBUGLEVEL >= 10) {
1192 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1193 (unsigned int)nreq->current_idx );
1194 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1195 (unsigned int)nreq->out.vector_count );
1196 print_req_vectors(nreq);
1200 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1201 * we need to sign/encrypt here with the last/first key we remembered
1203 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1204 status = smb2_signing_encrypt_pdu(req->first_key,
1207 nreq->out.vector_count - first_idx);
1208 if (!NT_STATUS_IS_OK(status)) {
1211 } else if (req->last_key.length > 0) {
1212 status = smb2_signing_sign_pdu(req->last_key,
1215 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1216 if (!NT_STATUS_IS_OK(status)) {
1221 nreq->subreq = tstream_writev_queue_send(nreq,
1222 nreq->sconn->ev_ctx,
1223 nreq->sconn->smb2.stream,
1224 nreq->sconn->smb2.send_queue,
1226 nreq->out.vector_count);
1228 if (nreq->subreq == NULL) {
1229 return NT_STATUS_NO_MEMORY;
1232 tevent_req_set_callback(nreq->subreq,
1233 smbd_smb2_request_writev_done,
1236 return NT_STATUS_OK;
1239 struct smbd_smb2_request_pending_state {
1240 struct smbd_server_connection *sconn;
1241 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1242 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1245 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
1247 struct smbd_smb2_request_pending_state *state =
1248 tevent_req_callback_data(subreq,
1249 struct smbd_smb2_request_pending_state);
1250 struct smbd_server_connection *sconn = state->sconn;
1254 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1255 TALLOC_FREE(subreq);
1257 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1258 smbd_server_connection_terminate(sconn, nt_errstr(status));
1265 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1266 struct tevent_timer *te,
1267 struct timeval current_time,
1268 void *private_data);
1270 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1271 struct tevent_req *subreq,
1272 uint32_t defer_time)
1275 struct timeval defer_endtime;
1276 uint8_t *outhdr = NULL;
1279 if (!tevent_req_is_in_progress(subreq)) {
1280 return NT_STATUS_OK;
1283 req->subreq = subreq;
1286 if (req->async_te) {
1287 /* We're already async. */
1288 return NT_STATUS_OK;
1291 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1292 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1293 if (flags & SMB2_HDR_FLAG_ASYNC) {
1294 /* We're already async. */
1295 return NT_STATUS_OK;
1298 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1300 * We're trying to go async in a compound
1302 * This is only allowed for opens that
1303 * cause an oplock break, otherwise it
1304 * is not allowed. See [MS-SMB2].pdf
1305 * note <194> on Section 3.3.5.2.7.
1307 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1309 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1311 * Cancel the outstanding request.
1313 bool ok = tevent_req_cancel(req->subreq);
1315 return NT_STATUS_OK;
1317 TALLOC_FREE(req->subreq);
1318 return smbd_smb2_request_error(req,
1319 NT_STATUS_INTERNAL_ERROR);
1323 if (DEBUGLEVEL >= 10) {
1324 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1325 (unsigned int)req->current_idx );
1326 print_req_vectors(req);
1329 if (req->current_idx > 1) {
1331 * We're going async in a compound
1332 * chain after the first request has
1333 * already been processed. Send an
1334 * interim response containing the
1335 * set of replies already generated.
1337 int idx = req->current_idx;
1339 status = smb2_send_async_interim_response(req);
1340 if (!NT_STATUS_IS_OK(status)) {
1343 data_blob_clear_free(&req->first_key);
1345 req->current_idx = 1;
1348 * Re-arrange the in.vectors to remove what
1351 memmove(&req->in.vector[1],
1352 &req->in.vector[idx],
1353 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1354 req->in.vector_count = 1 + (req->in.vector_count - idx);
1356 /* Re-arrange the out.vectors to match. */
1357 memmove(&req->out.vector[1],
1358 &req->out.vector[idx],
1359 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1360 req->out.vector_count = 1 + (req->out.vector_count - idx);
1362 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1364 * We only have one remaining request as
1365 * we've processed everything else.
1366 * This is no longer a compound request.
1368 req->compound_related = false;
1369 req->sconn->smb2.compound_related_in_progress = false;
1370 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1371 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1372 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1375 data_blob_clear_free(&req->last_key);
1377 defer_endtime = timeval_current_ofs_usec(defer_time);
1378 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1380 smbd_smb2_request_pending_timer,
1382 if (req->async_te == NULL) {
1383 return NT_STATUS_NO_MEMORY;
1386 return NT_STATUS_OK;
1389 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1390 struct tevent_timer *te,
1391 struct timeval current_time,
1394 struct smbd_smb2_request *req =
1395 talloc_get_type_abort(private_data,
1396 struct smbd_smb2_request);
1397 struct smbd_smb2_request_pending_state *state = NULL;
1398 uint8_t *outhdr = NULL;
1399 const uint8_t *inhdr = NULL;
1402 uint8_t *hdr = NULL;
1403 uint8_t *body = NULL;
1404 uint8_t *dyn = NULL;
1406 uint64_t session_id = 0;
1407 uint64_t message_id = 0;
1408 uint64_t nonce_high = 0;
1409 uint64_t nonce_low = 0;
1410 uint64_t async_id = 0;
1411 struct tevent_req *subreq = NULL;
1413 TALLOC_FREE(req->async_te);
1415 /* Ensure our final reply matches the interim one. */
1416 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1417 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1418 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1419 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1420 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1422 async_id = message_id; /* keep it simple for now... */
1424 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1425 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1427 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1429 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1430 (unsigned long long)async_id ));
1433 * What we send is identical to a smbd_smb2_request_error
1434 * packet with an error status of STATUS_PENDING. Make use
1435 * of this fact sometime when refactoring. JRA.
1438 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1439 if (state == NULL) {
1440 smbd_server_connection_terminate(req->sconn,
1441 nt_errstr(NT_STATUS_NO_MEMORY));
1444 state->sconn = req->sconn;
1446 tf = state->buf + NBT_HDR_SIZE;
1447 tf_len = SMB2_TF_HDR_SIZE;
1449 hdr = tf + SMB2_TF_HDR_SIZE;
1450 body = hdr + SMB2_HDR_BODY;
1453 if (req->do_encryption) {
1454 struct smbXsrv_session *x = req->session;
1456 nonce_high = x->nonce_high;
1457 nonce_low = x->nonce_low;
1460 if (x->nonce_low == 0) {
1466 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1467 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1468 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1469 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1471 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1472 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1473 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1474 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1475 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1477 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1478 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1479 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1480 SBVAL(hdr, SMB2_HDR_PID, async_id);
1481 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1482 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1483 memcpy(hdr+SMB2_HDR_SIGNATURE,
1484 outhdr+SMB2_HDR_SIGNATURE, 16);
1486 SSVAL(body, 0x00, 0x08 + 1);
1488 SCVAL(body, 0x02, 0);
1489 SCVAL(body, 0x03, 0);
1490 SIVAL(body, 0x04, 0);
1491 /* Match W2K8R2... */
1492 SCVAL(dyn, 0x00, 0x21);
1494 state->vector[0].iov_base = (void *)state->buf;
1495 state->vector[0].iov_len = NBT_HDR_SIZE;
1497 if (req->do_encryption) {
1498 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1499 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1501 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1502 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1505 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1506 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1508 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1509 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1511 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1512 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1514 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1516 /* Ensure we correctly go through crediting. Grant
1517 the credits now, and zero credits on the final
1519 smb2_set_operation_credit(req->sconn,
1520 SMBD_SMB2_IN_HDR_IOV(req),
1521 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1523 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1528 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1529 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1531 (unsigned int)ARRAY_SIZE(state->vector),
1532 (unsigned int)state->vector[i].iov_len);
1536 if (req->do_encryption) {
1538 struct smbXsrv_session *x = req->session;
1539 struct smbXsrv_connection *conn = x->connection;
1540 DATA_BLOB encryption_key = x->global->encryption_key;
1542 status = smb2_signing_encrypt_pdu(encryption_key,
1544 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1545 SMBD_SMB2_NUM_IOV_PER_REQ);
1546 if (!NT_STATUS_IS_OK(status)) {
1547 smbd_server_connection_terminate(req->sconn,
1551 } else if (req->do_signing) {
1553 struct smbXsrv_session *x = req->session;
1554 struct smbXsrv_connection *conn = x->connection;
1555 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1557 status = smb2_signing_sign_pdu(signing_key,
1559 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1560 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1561 if (!NT_STATUS_IS_OK(status)) {
1562 smbd_server_connection_terminate(req->sconn,
1568 subreq = tstream_writev_queue_send(state,
1569 state->sconn->ev_ctx,
1570 state->sconn->smb2.stream,
1571 state->sconn->smb2.send_queue,
1573 ARRAY_SIZE(state->vector));
1574 if (subreq == NULL) {
1575 smbd_server_connection_terminate(state->sconn,
1576 nt_errstr(NT_STATUS_NO_MEMORY));
1579 tevent_req_set_callback(subreq,
1580 smbd_smb2_request_pending_writev_done,
1584 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1586 struct smbd_server_connection *sconn = req->sconn;
1587 struct smbd_smb2_request *cur;
1588 const uint8_t *inhdr;
1590 uint64_t search_message_id;
1591 uint64_t search_async_id;
1594 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1596 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1597 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1598 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1601 * we don't need the request anymore
1602 * cancel requests never have a response
1604 DLIST_REMOVE(req->sconn->smb2.requests, req);
1607 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1608 const uint8_t *outhdr;
1609 uint64_t message_id;
1612 if (cur->compound_related) {
1614 * Never cancel anything in a compound request.
1615 * Way too hard to deal with the result.
1620 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1622 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1623 async_id = BVAL(outhdr, SMB2_HDR_PID);
1625 if (flags & SMB2_HDR_FLAG_ASYNC) {
1626 if (search_async_id == async_id) {
1627 found_id = async_id;
1631 if (search_message_id == message_id) {
1632 found_id = message_id;
1638 if (cur && cur->subreq) {
1639 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1640 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1641 "cancel opcode[%s] mid %llu\n",
1642 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1643 (unsigned long long)found_id ));
1644 tevent_req_cancel(cur->subreq);
1647 return NT_STATUS_OK;
1650 /*************************************************************
1651 Ensure an incoming tid is a valid one for us to access.
1652 Change to the associated uid credentials and chdir to the
1653 valid tid directory.
1654 *************************************************************/
1656 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1658 const uint8_t *inhdr;
1661 struct smbXsrv_tcon *tcon;
1663 NTTIME now = timeval_to_nttime(&req->request_time);
1667 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1669 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1670 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1672 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1673 in_tid = req->last_tid;
1678 status = smb2srv_tcon_lookup(req->session,
1679 in_tid, now, &tcon);
1680 if (!NT_STATUS_IS_OK(status)) {
1684 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1685 return NT_STATUS_ACCESS_DENIED;
1688 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1689 if (!set_current_service(tcon->compat, 0, true)) {
1690 return NT_STATUS_ACCESS_DENIED;
1694 req->last_tid = in_tid;
1696 return NT_STATUS_OK;
1699 /*************************************************************
1700 Ensure an incoming session_id is a valid one for us to access.
1701 *************************************************************/
1703 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1705 const uint8_t *inhdr;
1708 uint64_t in_session_id;
1709 struct smbXsrv_session *session = NULL;
1710 struct auth_session_info *session_info;
1712 NTTIME now = timeval_to_nttime(&req->request_time);
1714 req->session = NULL;
1717 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1719 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1720 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1721 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1723 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1724 in_session_id = req->last_session_id;
1727 req->last_session_id = 0;
1729 /* lookup an existing session */
1730 status = smb2srv_session_lookup(req->sconn->conn,
1734 req->session = session;
1735 req->last_session_id = in_session_id;
1737 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1738 switch (in_opcode) {
1739 case SMB2_OP_SESSSETUP:
1740 status = NT_STATUS_OK;
1746 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1747 switch (in_opcode) {
1749 case SMB2_OP_CREATE:
1750 case SMB2_OP_GETINFO:
1751 case SMB2_OP_SETINFO:
1752 return NT_STATUS_INVALID_HANDLE;
1755 * Notice the check for
1756 * (session_info == NULL)
1759 status = NT_STATUS_OK;
1763 if (!NT_STATUS_IS_OK(status)) {
1767 session_info = session->global->auth_session_info;
1768 if (session_info == NULL) {
1769 return NT_STATUS_INVALID_HANDLE;
1772 set_current_user_info(session_info->unix_info->sanitized_username,
1773 session_info->unix_info->unix_name,
1774 session_info->info->domain_name);
1776 return NT_STATUS_OK;
1779 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1780 uint32_t data_length)
1782 uint16_t needed_charge;
1783 uint16_t credit_charge = 1;
1784 const uint8_t *inhdr;
1786 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1788 if (req->sconn->smb2.supports_multicredit) {
1789 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1790 credit_charge = MAX(credit_charge, 1);
1793 needed_charge = (data_length - 1)/ 65536 + 1;
1795 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1796 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1797 credit_charge, needed_charge));
1799 if (needed_charge > credit_charge) {
1800 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1801 credit_charge, needed_charge));
1802 return NT_STATUS_INVALID_PARAMETER;
1805 return NT_STATUS_OK;
1808 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1809 size_t expected_body_size)
1811 struct iovec *inhdr_v;
1812 const uint8_t *inhdr;
1814 const uint8_t *inbody;
1816 size_t min_dyn_size = expected_body_size & 0x00000001;
1817 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1820 * The following should be checked already.
1822 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1823 return NT_STATUS_INTERNAL_ERROR;
1825 if (req->current_idx > max_idx) {
1826 return NT_STATUS_INTERNAL_ERROR;
1829 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1830 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1831 return NT_STATUS_INTERNAL_ERROR;
1833 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1834 return NT_STATUS_INTERNAL_ERROR;
1837 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1838 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1842 case SMB2_OP_GETINFO:
1848 * Now check the expected body size,
1849 * where the last byte might be in the
1852 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1853 return NT_STATUS_INVALID_PARAMETER;
1855 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1856 return NT_STATUS_INVALID_PARAMETER;
1859 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1861 body_size = SVAL(inbody, 0x00);
1862 if (body_size != expected_body_size) {
1863 return NT_STATUS_INVALID_PARAMETER;
1866 return NT_STATUS_OK;
1869 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1871 struct smbXsrv_connection *conn = req->sconn->conn;
1872 const struct smbd_smb2_dispatch_table *call = NULL;
1873 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1874 const uint8_t *inhdr;
1879 NTSTATUS session_status;
1880 uint32_t allowed_flags;
1881 NTSTATUS return_value;
1882 struct smbXsrv_session *x = NULL;
1883 bool signing_required = false;
1884 bool encryption_required = false;
1886 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1888 /* TODO: verify more things */
1890 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1891 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1892 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1893 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1894 smb2_opcode_name(opcode),
1895 (unsigned long long)mid));
1897 if (conn->protocol >= PROTOCOL_SMB2_02) {
1899 * once the protocol is negotiated
1900 * SMB2_OP_NEGPROT is not allowed anymore
1902 if (opcode == SMB2_OP_NEGPROT) {
1903 /* drop the connection */
1904 return NT_STATUS_INVALID_PARAMETER;
1908 * if the protocol is not negotiated yet
1909 * only SMB2_OP_NEGPROT is allowed.
1911 if (opcode != SMB2_OP_NEGPROT) {
1912 /* drop the connection */
1913 return NT_STATUS_INVALID_PARAMETER;
1918 * Check if the client provided a valid session id,
1919 * if so smbd_smb2_request_check_session() calls
1920 * set_current_user_info().
1922 * As some command don't require a valid session id
1923 * we defer the check of the session_status
1925 session_status = smbd_smb2_request_check_session(req);
1928 signing_required = x->global->signing_required;
1929 encryption_required = x->global->encryption_required;
1931 if (opcode == SMB2_OP_SESSSETUP &&
1932 x->global->channels[0].signing_key.length) {
1933 signing_required = true;
1937 req->do_signing = false;
1938 req->do_encryption = false;
1939 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
1940 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
1941 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
1943 if (x != NULL && x->global->session_wire_id != tf_session_id) {
1944 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1945 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1946 (unsigned long long)x->global->session_wire_id,
1947 (unsigned long long)tf_session_id));
1949 * TODO: windows allows this...
1950 * should we drop the connection?
1952 * For now we just return ACCESS_DENIED
1953 * (Windows clients never trigger this)
1954 * and wait for an update of [MS-SMB2].
1956 return smbd_smb2_request_error(req,
1957 NT_STATUS_ACCESS_DENIED);
1960 req->do_encryption = true;
1963 if (encryption_required && !req->do_encryption) {
1964 return smbd_smb2_request_error(req,
1965 NT_STATUS_ACCESS_DENIED);
1968 call = smbd_smb2_call(opcode);
1970 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1973 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1974 SMB2_HDR_FLAG_SIGNED |
1976 if (opcode == SMB2_OP_CANCEL) {
1977 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1979 if ((flags & ~allowed_flags) != 0) {
1980 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1983 if (flags & SMB2_HDR_FLAG_CHAINED) {
1985 * This check is mostly for giving the correct error code
1986 * for compounded requests.
1988 if (!NT_STATUS_IS_OK(session_status)) {
1989 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1992 req->compat_chain_fsp = NULL;
1995 if (req->do_encryption) {
1996 signing_required = false;
1997 } else if (flags & SMB2_HDR_FLAG_SIGNED) {
1998 DATA_BLOB signing_key;
2001 return smbd_smb2_request_error(
2002 req, NT_STATUS_ACCESS_DENIED);
2005 signing_key = x->global->channels[0].signing_key;
2008 * If we have a signing key, we should
2011 if (signing_key.length > 0) {
2012 req->do_signing = true;
2015 status = smb2_signing_check_pdu(signing_key,
2017 SMBD_SMB2_IN_HDR_IOV(req),
2018 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2019 if (!NT_STATUS_IS_OK(status)) {
2020 return smbd_smb2_request_error(req, status);
2024 * Now that we know the request was correctly signed
2025 * we have to sign the response too.
2027 req->do_signing = true;
2029 if (!NT_STATUS_IS_OK(session_status)) {
2030 return smbd_smb2_request_error(req, session_status);
2032 } else if (opcode == SMB2_OP_CANCEL) {
2033 /* Cancel requests are allowed to skip the signing */
2034 } else if (signing_required) {
2036 * If signing is required we try to sign
2037 * a possible error response
2039 req->do_signing = true;
2040 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2043 if (flags & SMB2_HDR_FLAG_CHAINED) {
2044 req->compound_related = true;
2045 req->sconn->smb2.compound_related_in_progress = true;
2048 if (call->need_session) {
2049 if (!NT_STATUS_IS_OK(session_status)) {
2050 return smbd_smb2_request_error(req, session_status);
2054 if (call->need_tcon) {
2055 SMB_ASSERT(call->need_session);
2058 * This call needs to be run as user.
2060 * smbd_smb2_request_check_tcon()
2061 * calls change_to_user() on success.
2063 status = smbd_smb2_request_check_tcon(req);
2064 if (!NT_STATUS_IS_OK(status)) {
2065 return smbd_smb2_request_error(req, status);
2067 if (req->tcon->global->encryption_required) {
2068 encryption_required = true;
2070 if (encryption_required && !req->do_encryption) {
2071 return smbd_smb2_request_error(req,
2072 NT_STATUS_ACCESS_DENIED);
2076 if (call->fileid_ofs != 0) {
2077 size_t needed = call->fileid_ofs + 16;
2078 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2079 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2080 uint64_t file_id_persistent;
2081 uint64_t file_id_volatile;
2082 struct files_struct *fsp;
2084 SMB_ASSERT(call->need_tcon);
2086 if (needed > body_size) {
2087 return smbd_smb2_request_error(req,
2088 NT_STATUS_INVALID_PARAMETER);
2091 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2092 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2094 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2096 if (!call->allow_invalid_fileid) {
2097 return smbd_smb2_request_error(req,
2098 NT_STATUS_FILE_CLOSED);
2101 if (file_id_persistent != UINT64_MAX) {
2102 return smbd_smb2_request_error(req,
2103 NT_STATUS_FILE_CLOSED);
2105 if (file_id_volatile != UINT64_MAX) {
2106 return smbd_smb2_request_error(req,
2107 NT_STATUS_FILE_CLOSED);
2112 if (call->as_root) {
2113 SMB_ASSERT(call->fileid_ofs == 0);
2114 /* This call needs to be run as root */
2115 change_to_root_user();
2117 SMB_ASSERT(call->need_tcon);
2121 case SMB2_OP_NEGPROT:
2123 START_PROFILE(smb2_negprot);
2124 return_value = smbd_smb2_request_process_negprot(req);
2125 END_PROFILE(smb2_negprot);
2129 case SMB2_OP_SESSSETUP:
2131 START_PROFILE(smb2_sesssetup);
2132 return_value = smbd_smb2_request_process_sesssetup(req);
2133 END_PROFILE(smb2_sesssetup);
2137 case SMB2_OP_LOGOFF:
2139 START_PROFILE(smb2_logoff);
2140 return_value = smbd_smb2_request_process_logoff(req);
2141 END_PROFILE(smb2_logoff);
2147 START_PROFILE(smb2_tcon);
2148 return_value = smbd_smb2_request_process_tcon(req);
2149 END_PROFILE(smb2_tcon);
2155 START_PROFILE(smb2_tdis);
2156 return_value = smbd_smb2_request_process_tdis(req);
2157 END_PROFILE(smb2_tdis);
2161 case SMB2_OP_CREATE:
2163 START_PROFILE(smb2_create);
2164 return_value = smbd_smb2_request_process_create(req);
2165 END_PROFILE(smb2_create);
2171 START_PROFILE(smb2_close);
2172 return_value = smbd_smb2_request_process_close(req);
2173 END_PROFILE(smb2_close);
2179 START_PROFILE(smb2_flush);
2180 return_value = smbd_smb2_request_process_flush(req);
2181 END_PROFILE(smb2_flush);
2187 START_PROFILE(smb2_read);
2188 return_value = smbd_smb2_request_process_read(req);
2189 END_PROFILE(smb2_read);
2195 START_PROFILE(smb2_write);
2196 return_value = smbd_smb2_request_process_write(req);
2197 END_PROFILE(smb2_write);
2203 START_PROFILE(smb2_lock);
2204 return_value = smbd_smb2_request_process_lock(req);
2205 END_PROFILE(smb2_lock);
2211 START_PROFILE(smb2_ioctl);
2212 return_value = smbd_smb2_request_process_ioctl(req);
2213 END_PROFILE(smb2_ioctl);
2217 case SMB2_OP_CANCEL:
2219 START_PROFILE(smb2_cancel);
2220 return_value = smbd_smb2_request_process_cancel(req);
2221 END_PROFILE(smb2_cancel);
2225 case SMB2_OP_KEEPALIVE:
2227 START_PROFILE(smb2_keepalive);
2228 return_value = smbd_smb2_request_process_keepalive(req);
2229 END_PROFILE(smb2_keepalive);
2235 START_PROFILE(smb2_find);
2236 return_value = smbd_smb2_request_process_find(req);
2237 END_PROFILE(smb2_find);
2241 case SMB2_OP_NOTIFY:
2243 START_PROFILE(smb2_notify);
2244 return_value = smbd_smb2_request_process_notify(req);
2245 END_PROFILE(smb2_notify);
2249 case SMB2_OP_GETINFO:
2251 START_PROFILE(smb2_getinfo);
2252 return_value = smbd_smb2_request_process_getinfo(req);
2253 END_PROFILE(smb2_getinfo);
2257 case SMB2_OP_SETINFO:
2259 START_PROFILE(smb2_setinfo);
2260 return_value = smbd_smb2_request_process_setinfo(req);
2261 END_PROFILE(smb2_setinfo);
2267 START_PROFILE(smb2_break);
2268 return_value = smbd_smb2_request_process_break(req);
2269 END_PROFILE(smb2_break);
2274 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2277 return return_value;
2280 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2282 struct smbXsrv_connection *conn = req->sconn->conn;
2283 struct tevent_req *subreq;
2285 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2286 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2287 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2290 TALLOC_FREE(req->async_te);
2292 if (req->do_encryption &&
2293 (firsttf->iov_len == 0) &&
2294 (req->first_key.length == 0) &&
2295 (req->session != NULL) &&
2296 (req->session->global->encryption_key.length != 0))
2298 DATA_BLOB encryption_key = req->session->global->encryption_key;
2300 uint64_t session_id = req->session->global->session_wire_id;
2301 struct smbXsrv_session *x = req->session;
2302 uint64_t nonce_high;
2305 nonce_high = x->nonce_high;
2306 nonce_low = x->nonce_low;
2309 if (x->nonce_low == 0) {
2315 * We need to place the SMB2_TRANSFORM header before the
2320 * we need to remember the encryption key
2321 * and defer the signing/encryption until
2322 * we are sure that we do not change
2325 req->first_key = data_blob_dup_talloc(req, encryption_key);
2326 if (req->first_key.data == NULL) {
2327 return NT_STATUS_NO_MEMORY;
2330 tf = talloc_zero_array(req->out.vector, uint8_t,
2333 return NT_STATUS_NO_MEMORY;
2336 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2337 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2338 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2339 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2341 firsttf->iov_base = (void *)tf;
2342 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2345 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2346 (req->last_key.length > 0) &&
2347 (firsttf->iov_len == 0))
2349 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2350 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2354 * As we are sure the header of the last request in the
2355 * compound chain will not change, we can to sign here
2356 * with the last signing key we remembered.
2358 status = smb2_signing_sign_pdu(req->last_key,
2361 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2362 if (!NT_STATUS_IS_OK(status)) {
2366 data_blob_clear_free(&req->last_key);
2368 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2370 if (req->current_idx < req->out.vector_count) {
2372 * We must process the remaining compound
2373 * SMB2 requests before any new incoming SMB2
2374 * requests. This is because incoming SMB2
2375 * requests may include a cancel for a
2376 * compound request we haven't processed
2379 struct tevent_immediate *im = tevent_create_immediate(req);
2381 return NT_STATUS_NO_MEMORY;
2384 if (req->do_signing && firsttf->iov_len == 0) {
2385 struct smbXsrv_session *x = req->session;
2386 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2389 * we need to remember the signing key
2390 * and defer the signing until
2391 * we are sure that we do not change
2394 req->last_key = data_blob_dup_talloc(req, signing_key);
2395 if (req->last_key.data == NULL) {
2396 return NT_STATUS_NO_MEMORY;
2400 tevent_schedule_immediate(im,
2402 smbd_smb2_request_dispatch_immediate,
2404 return NT_STATUS_OK;
2407 if (req->compound_related) {
2408 req->compound_related = false;
2409 req->sconn->smb2.compound_related_in_progress = false;
2412 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2414 /* Set credit for these operations (zero credits if this
2415 is a final reply for an async operation). */
2416 smb2_calculate_credits(req, req);
2419 * now check if we need to sign the current response
2421 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2424 status = smb2_signing_encrypt_pdu(req->first_key,
2427 req->out.vector_count - first_idx);
2428 if (!NT_STATUS_IS_OK(status)) {
2431 } else if (req->do_signing) {
2433 struct smbXsrv_session *x = req->session;
2434 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2436 status = smb2_signing_sign_pdu(signing_key,
2439 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2440 if (!NT_STATUS_IS_OK(status)) {
2444 data_blob_clear_free(&req->first_key);
2446 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2447 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2448 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2449 /* Dynamic part is NULL. Chop it off,
2450 We're going to send it via sendfile. */
2451 req->out.vector_count -= 1;
2454 subreq = tstream_writev_queue_send(req,
2456 req->sconn->smb2.stream,
2457 req->sconn->smb2.send_queue,
2459 req->out.vector_count);
2460 if (subreq == NULL) {
2461 return NT_STATUS_NO_MEMORY;
2463 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
2465 * We're done with this request -
2466 * move it off the "being processed" queue.
2468 DLIST_REMOVE(req->sconn->smb2.requests, req);
2470 return NT_STATUS_OK;
2473 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2475 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2476 struct tevent_immediate *im,
2479 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2480 struct smbd_smb2_request);
2481 struct smbd_server_connection *sconn = req->sconn;
2486 if (DEBUGLEVEL >= 10) {
2487 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2488 req->current_idx, req->in.vector_count));
2489 print_req_vectors(req);
2492 status = smbd_smb2_request_dispatch(req);
2493 if (!NT_STATUS_IS_OK(status)) {
2494 smbd_server_connection_terminate(sconn, nt_errstr(status));
2498 status = smbd_smb2_request_next_incoming(sconn);
2499 if (!NT_STATUS_IS_OK(status)) {
2500 smbd_server_connection_terminate(sconn, nt_errstr(status));
2505 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
2507 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
2508 struct smbd_smb2_request);
2509 struct smbd_server_connection *sconn = req->sconn;
2514 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2515 TALLOC_FREE(subreq);
2518 status = map_nt_error_from_unix(sys_errno);
2519 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2520 nt_errstr(status)));
2521 smbd_server_connection_terminate(sconn, nt_errstr(status));
2525 status = smbd_smb2_request_next_incoming(sconn);
2526 if (!NT_STATUS_IS_OK(status)) {
2527 smbd_server_connection_terminate(sconn, nt_errstr(status));
2532 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2534 DATA_BLOB body, DATA_BLOB *dyn,
2535 const char *location)
2538 struct iovec *outbody_v;
2539 struct iovec *outdyn_v;
2540 uint32_t next_command_ofs;
2542 DEBUG(10,("smbd_smb2_request_done_ex: "
2543 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2544 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2546 (unsigned int)(dyn ? dyn->length : 0),
2549 if (body.length < 2) {
2550 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2553 if ((body.length % 2) != 0) {
2554 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2557 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2558 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2559 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2561 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2562 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2564 outbody_v->iov_base = (void *)body.data;
2565 outbody_v->iov_len = body.length;
2568 outdyn_v->iov_base = (void *)dyn->data;
2569 outdyn_v->iov_len = dyn->length;
2571 outdyn_v->iov_base = NULL;
2572 outdyn_v->iov_len = 0;
2575 /* see if we need to recalculate the offset to the next response */
2576 if (next_command_ofs > 0) {
2577 next_command_ofs = SMB2_HDR_BODY;
2578 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2579 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2582 if ((next_command_ofs % 8) != 0) {
2583 size_t pad_size = 8 - (next_command_ofs % 8);
2584 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2586 * if the dyn buffer is empty
2587 * we can use it to add padding
2591 pad = talloc_zero_array(req->out.vector,
2594 return smbd_smb2_request_error(req,
2595 NT_STATUS_NO_MEMORY);
2598 outdyn_v->iov_base = (void *)pad;
2599 outdyn_v->iov_len = pad_size;
2602 * For now we copy the dynamic buffer
2603 * and add the padding to the new buffer
2610 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2611 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2613 new_size = old_size + pad_size;
2614 new_dyn = talloc_zero_array(req->out.vector,
2616 if (new_dyn == NULL) {
2617 return smbd_smb2_request_error(req,
2618 NT_STATUS_NO_MEMORY);
2621 memcpy(new_dyn, old_dyn, old_size);
2622 memset(new_dyn + old_size, 0, pad_size);
2624 outdyn_v->iov_base = (void *)new_dyn;
2625 outdyn_v->iov_len = new_size;
2627 next_command_ofs += pad_size;
2630 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2632 return smbd_smb2_request_reply(req);
2635 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2638 const char *location)
2641 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2642 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2644 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2645 req->current_idx, nt_errstr(status), info ? " +info" : "",
2649 /* Recvfile error. Drain incoming socket. */
2650 size_t ret = drain_socket(req->sconn->sock, unread_bytes);
2651 if (ret != unread_bytes) {
2652 smbd_server_connection_terminate(req->sconn,
2653 "Failed to drain SMB2 socket\n");
2657 body.data = outhdr + SMB2_HDR_BODY;
2659 SSVAL(body.data, 0, 9);
2662 SIVAL(body.data, 0x04, info->length);
2664 /* Allocated size of req->out.vector[i].iov_base
2665 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2666 * 1 byte without having to do an alloc.
2668 info = talloc_zero_array(req->out.vector,
2672 return NT_STATUS_NO_MEMORY;
2674 info->data = ((uint8_t *)outhdr) +
2675 OUTVEC_ALLOC_SIZE - 1;
2677 SCVAL(info->data, 0, 0);
2681 * Note: Even if there is an error, continue to process the request.
2685 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2689 struct smbd_smb2_send_oplock_break_state {
2690 struct smbd_server_connection *sconn;
2691 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x18];
2692 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2695 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2697 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2698 struct smbXsrv_session *session,
2699 struct smbXsrv_tcon *tcon,
2700 struct smbXsrv_open *op,
2701 uint8_t oplock_level)
2703 struct smbd_smb2_send_oplock_break_state *state;
2704 struct smbXsrv_connection *conn = sconn->conn;
2705 struct tevent_req *subreq;
2713 bool do_encryption = session->global->encryption_required;
2714 uint64_t nonce_high = 0;
2715 uint64_t nonce_low = 0;
2717 if (tcon->global->encryption_required) {
2718 do_encryption = true;
2721 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2722 if (state == NULL) {
2723 return NT_STATUS_NO_MEMORY;
2725 state->sconn = sconn;
2727 tf = state->buf + NBT_HDR_SIZE;
2728 tf_len = SMB2_TF_HDR_SIZE;
2730 body = hdr + SMB2_HDR_BODY;
2732 dyn = body + body_len;
2735 if (do_encryption) {
2736 nonce_high = session->nonce_high;
2737 nonce_low = session->nonce_low;
2739 session->nonce_low += 1;
2740 if (session->nonce_low == 0) {
2741 session->nonce_low += 1;
2742 session->nonce_high += 1;
2746 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2747 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2748 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2749 SBVAL(tf, SMB2_TF_SESSION_ID, session->global->session_wire_id);
2751 SIVAL(hdr, 0, SMB2_MAGIC);
2752 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2753 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2754 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2755 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2756 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2757 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2758 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2759 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2760 SIVAL(hdr, SMB2_HDR_PID, 0);
2761 SIVAL(hdr, SMB2_HDR_TID, 0);
2762 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2763 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2765 SSVAL(body, 0x00, body_len);
2767 SCVAL(body, 0x02, oplock_level);
2768 SCVAL(body, 0x03, 0); /* reserved */
2769 SIVAL(body, 0x04, 0); /* reserved */
2770 SBVAL(body, 0x08, op->global->open_persistent_id);
2771 SBVAL(body, 0x10, op->global->open_volatile_id);
2773 state->vector[0].iov_base = (void *)state->buf;
2774 state->vector[0].iov_len = NBT_HDR_SIZE;
2776 if (do_encryption) {
2777 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
2778 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
2780 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
2781 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
2784 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
2785 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
2787 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
2788 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = body_len;
2790 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
2791 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_len;
2793 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2795 if (do_encryption) {
2797 DATA_BLOB encryption_key = session->global->encryption_key;
2799 status = smb2_signing_encrypt_pdu(encryption_key,
2801 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2802 SMBD_SMB2_NUM_IOV_PER_REQ);
2803 if (!NT_STATUS_IS_OK(status)) {
2808 subreq = tstream_writev_queue_send(state,
2811 sconn->smb2.send_queue,
2813 ARRAY_SIZE(state->vector));
2814 if (subreq == NULL) {
2815 return NT_STATUS_NO_MEMORY;
2817 tevent_req_set_callback(subreq,
2818 smbd_smb2_oplock_break_writev_done,
2821 return NT_STATUS_OK;
2824 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2826 struct smbd_smb2_send_oplock_break_state *state =
2827 tevent_req_callback_data(subreq,
2828 struct smbd_smb2_send_oplock_break_state);
2829 struct smbd_server_connection *sconn = state->sconn;
2833 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2834 TALLOC_FREE(subreq);
2836 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2837 smbd_server_connection_terminate(sconn, nt_errstr(status));
2844 struct smbd_smb2_request_read_state {
2845 struct tevent_context *ev;
2846 struct smbd_server_connection *sconn;
2847 struct smbd_smb2_request *smb2_req;
2849 uint8_t nbt[NBT_HDR_SIZE];
2852 bool doing_receivefile;
2853 size_t min_recv_size;
2858 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2860 TALLOC_CTX *mem_ctx,
2861 struct iovec **_vector,
2863 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2865 static size_t get_min_receive_file_size(struct smbd_smb2_request *smb2_req)
2867 if (smb2_req->do_signing) {
2870 if (smb2_req->do_encryption) {
2873 return (size_t)lp_min_receive_file_size();
2876 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2877 struct tevent_context *ev,
2878 struct smbd_server_connection *sconn)
2880 struct tevent_req *req;
2881 struct smbd_smb2_request_read_state *state;
2882 struct tevent_req *subreq;
2884 req = tevent_req_create(mem_ctx, &state,
2885 struct smbd_smb2_request_read_state);
2890 state->sconn = sconn;
2892 state->smb2_req = smbd_smb2_request_allocate(state);
2893 if (tevent_req_nomem(state->smb2_req, req)) {
2894 return tevent_req_post(req, ev);
2896 state->smb2_req->sconn = sconn;
2897 state->min_recv_size = get_min_receive_file_size(state->smb2_req);
2899 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
2901 state->sconn->smb2.stream,
2902 state->sconn->smb2.recv_queue,
2903 smbd_smb2_request_next_vector,
2905 if (tevent_req_nomem(subreq, req)) {
2906 return tevent_req_post(req, ev);
2908 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2913 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2917 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
2918 /* Transform header. Cannot recvfile. */
2921 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
2922 /* Not SMB2. Normal error path will cope. */
2925 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
2926 /* Not SMB2. Normal error path will cope. */
2929 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
2930 /* Needs to be a WRITE. */
2933 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
2934 /* Chained. Cannot recvfile. */
2937 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
2938 if (flags & SMB2_HDR_FLAG_CHAINED) {
2939 /* Chained. Cannot recvfile. */
2942 if (flags & SMB2_HDR_FLAG_SIGNED) {
2943 /* Signed. Cannot recvfile. */
2947 DEBUG(10,("Doing recvfile write len = %u\n",
2948 (unsigned int)(state->pktlen -
2949 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN)));
2954 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2956 TALLOC_CTX *mem_ctx,
2957 struct iovec **_vector,
2960 struct smbd_smb2_request_read_state *state =
2961 talloc_get_type_abort(private_data,
2962 struct smbd_smb2_request_read_state);
2963 struct iovec *vector = NULL;
2964 size_t min_recvfile_size = UINT32_MAX;
2966 if (state->pktlen > 0) {
2967 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
2969 * Not a possible receivefile write.
2970 * Read the rest of the data.
2972 state->doing_receivefile = false;
2973 vector = talloc_array(mem_ctx, struct iovec, 1);
2974 if (vector == NULL) {
2977 vector[0].iov_base = (void *)(state->pktbuf +
2978 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN);
2979 vector[0].iov_len = (state->pktlen -
2980 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN);
2985 * Either this is a receivefile write so we've
2986 * done a short read, or if not we have all the data.
2987 * Either way, we're done and
2988 * smbd_smb2_request_read_done() will handle
2989 * and short read case by looking at the
2990 * state->doing_receivefile value.
2998 if (!state->hdr.done) {
3000 * first we need to get the NBT header
3002 vector = talloc_array(mem_ctx, struct iovec, 1);
3003 if (vector == NULL) {
3007 vector[0].iov_base = (void *)state->hdr.nbt;
3008 vector[0].iov_len = NBT_HDR_SIZE;
3013 state->hdr.done = true;
3018 * Now we analyze the NBT header
3020 state->pktlen = smb2_len(state->hdr.nbt);
3022 if (state->pktlen == 0) {
3023 /* if there're no remaining bytes, we're done */
3029 state->pktbuf = talloc_array(state->smb2_req, uint8_t, state->pktlen);
3030 if (state->pktbuf == NULL) {
3034 vector = talloc_array(mem_ctx, struct iovec, 1);
3035 if (vector == NULL) {
3039 vector[0].iov_base = (void *)state->pktbuf;
3041 if (state->min_recv_size != 0) {
3042 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3043 min_recvfile_size += state->min_recv_size;
3046 if (state->pktlen > min_recvfile_size) {
3048 * Might be a receivefile write. Read the SMB2 HEADER +
3049 * SMB2_WRITE header first. Set 'doing_receivefile'
3050 * as we're *attempting* receivefile write. If this
3051 * turns out not to be a SMB2_WRITE request or otherwise
3052 * not suitable then we'll just read the rest of the data
3053 * the next time this function is called.
3055 vector[0].iov_len = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3056 state->doing_receivefile = true;
3058 vector[0].iov_len = state->pktlen;
3066 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
3068 struct tevent_req *req =
3069 tevent_req_callback_data(subreq,
3071 struct smbd_smb2_request_read_state *state =
3072 tevent_req_data(req,
3073 struct smbd_smb2_request_read_state);
3079 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
3080 TALLOC_FREE(subreq);
3082 status = map_nt_error_from_unix(sys_errno);
3083 tevent_req_nterror(req, status);
3087 if (state->hdr.nbt[0] != 0x00) {
3088 DEBUG(1,("smbd_smb2_request_read_done: ignore NBT[0x%02X] msg\n",
3089 state->hdr.nbt[0]));
3091 ZERO_STRUCT(state->hdr);
3092 TALLOC_FREE(state->pktbuf);
3095 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
3097 state->sconn->smb2.stream,
3098 state->sconn->smb2.recv_queue,
3099 smbd_smb2_request_next_vector,
3101 if (tevent_req_nomem(subreq, req)) {
3104 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
3108 state->smb2_req->request_time = timeval_current();
3109 now = timeval_to_nttime(&state->smb2_req->request_time);
3111 status = smbd_smb2_inbuf_parse_compound(state->smb2_req->sconn->conn,
3116 &state->smb2_req->in.vector,
3117 &state->smb2_req->in.vector_count);
3118 if (tevent_req_nterror(req, status)) {
3122 if (state->doing_receivefile) {
3123 state->smb2_req->smb1req = talloc_zero(state->smb2_req,
3124 struct smb_request);
3125 if (tevent_req_nomem(state->smb2_req->smb1req, req)) {
3128 state->smb2_req->smb1req->unread_bytes =
3129 state->pktlen - SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3132 state->smb2_req->current_idx = 1;
3134 tevent_req_done(req);
3137 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
3138 TALLOC_CTX *mem_ctx,
3139 struct smbd_smb2_request **_smb2_req)
3141 struct smbd_smb2_request_read_state *state =
3142 tevent_req_data(req,
3143 struct smbd_smb2_request_read_state);
3146 if (tevent_req_is_nterror(req, &status)) {
3147 tevent_req_received(req);
3151 *_smb2_req = talloc_move(mem_ctx, &state->smb2_req);
3152 tevent_req_received(req);
3153 return NT_STATUS_OK;
3156 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
3158 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
3160 size_t max_send_queue_len;
3161 size_t cur_send_queue_len;
3162 struct tevent_req *subreq;
3164 if (sconn->smb2.compound_related_in_progress) {
3166 * Can't read another until the related
3169 return NT_STATUS_OK;
3172 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
3174 * if there is already a smbd_smb2_request_read
3175 * pending, we are done.
3177 return NT_STATUS_OK;
3180 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
3181 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
3183 if (cur_send_queue_len > max_send_queue_len) {
3185 * if we have a lot of requests to send,
3186 * we wait until they are on the wire until we
3187 * ask for the next request.
3189 return NT_STATUS_OK;
3192 /* ask for the next request */
3193 subreq = smbd_smb2_request_read_send(sconn, sconn->ev_ctx, sconn);
3194 if (subreq == NULL) {
3195 return NT_STATUS_NO_MEMORY;
3197 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
3199 return NT_STATUS_OK;
3202 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
3203 uint8_t *inbuf, size_t size)
3206 struct smbd_smb2_request *req = NULL;
3208 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3209 (unsigned int)size));
3211 status = smbd_initialize_smb2(sconn);
3212 if (!NT_STATUS_IS_OK(status)) {
3213 smbd_server_connection_terminate(sconn, nt_errstr(status));
3217 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
3218 if (!NT_STATUS_IS_OK(status)) {
3219 smbd_server_connection_terminate(sconn, nt_errstr(status));
3223 status = smbd_smb2_request_validate(req);
3224 if (!NT_STATUS_IS_OK(status)) {
3225 smbd_server_connection_terminate(sconn, nt_errstr(status));
3229 status = smbd_smb2_request_setup_out(req);
3230 if (!NT_STATUS_IS_OK(status)) {
3231 smbd_server_connection_terminate(sconn, nt_errstr(status));
3235 status = smbd_smb2_request_dispatch(req);
3236 if (!NT_STATUS_IS_OK(status)) {
3237 smbd_server_connection_terminate(sconn, nt_errstr(status));
3241 status = smbd_smb2_request_next_incoming(sconn);
3242 if (!NT_STATUS_IS_OK(status)) {
3243 smbd_server_connection_terminate(sconn, nt_errstr(status));
3247 sconn->num_requests++;
3250 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
3252 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
3253 struct smbd_server_connection);
3255 struct smbd_smb2_request *req = NULL;
3257 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
3258 TALLOC_FREE(subreq);
3259 if (!NT_STATUS_IS_OK(status)) {
3260 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
3261 nt_errstr(status)));
3262 smbd_server_connection_terminate(sconn, nt_errstr(status));
3266 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
3267 req->current_idx, req->in.vector_count));
3269 status = smbd_smb2_request_validate(req);
3270 if (!NT_STATUS_IS_OK(status)) {
3271 smbd_server_connection_terminate(sconn, nt_errstr(status));
3275 status = smbd_smb2_request_setup_out(req);
3276 if (!NT_STATUS_IS_OK(status)) {
3277 smbd_server_connection_terminate(sconn, nt_errstr(status));
3281 status = smbd_smb2_request_dispatch(req);
3282 if (!NT_STATUS_IS_OK(status)) {
3283 smbd_server_connection_terminate(sconn, nt_errstr(status));
3287 status = smbd_smb2_request_next_incoming(sconn);
3288 if (!NT_STATUS_IS_OK(status)) {
3289 smbd_server_connection_terminate(sconn, nt_errstr(status));
3293 sconn->num_requests++;
3295 /* The timeout_processing function isn't run nearly
3296 often enough to implement 'max log size' without
3297 overrunning the size of the file by many megabytes.
3298 This is especially true if we are running at debug
3299 level 10. Checking every 50 SMB2s is a nice
3300 tradeoff of performance vs log file size overrun. */
3302 if ((sconn->num_requests % 50) == 0 &&
3303 need_to_check_log_size()) {
3304 change_to_root_user();