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 verify high credit charge.
762 * TODO: scale up depending one 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 int idx = req->current_idx;
1276 struct timeval defer_endtime;
1277 uint8_t *outhdr = NULL;
1280 if (!tevent_req_is_in_progress(subreq)) {
1281 return NT_STATUS_OK;
1284 req->subreq = subreq;
1287 if (req->async_te) {
1288 /* We're already async. */
1289 return NT_STATUS_OK;
1292 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1293 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1294 if (flags & SMB2_HDR_FLAG_ASYNC) {
1295 /* We're already async. */
1296 return NT_STATUS_OK;
1299 if (req->in.vector_count > idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1301 * We're trying to go async in a compound
1302 * request chain. This is not allowed.
1303 * Cancel the outstanding request.
1305 bool ok = tevent_req_cancel(req->subreq);
1307 return NT_STATUS_OK;
1309 TALLOC_FREE(req->subreq);
1310 return smbd_smb2_request_error(req,
1311 NT_STATUS_INTERNAL_ERROR);
1314 if (DEBUGLEVEL >= 10) {
1315 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1316 (unsigned int)req->current_idx );
1317 print_req_vectors(req);
1320 if (req->out.vector_count >= (2*SMBD_SMB2_NUM_IOV_PER_REQ)) {
1322 * This is a compound reply. We
1323 * must do an interim response
1324 * followed by the async response
1327 status = smb2_send_async_interim_response(req);
1328 if (!NT_STATUS_IS_OK(status)) {
1331 data_blob_clear_free(&req->first_key);
1334 * We're splitting off the last SMB2
1335 * request in a compound set, and the
1336 * smb2_send_async_interim_response()
1337 * call above just sent all the replies
1338 * for the previous SMB2 requests in
1339 * this compound set. So we're no longer
1340 * in the "compound_related_in_progress"
1341 * state, and this is no longer a compound
1344 req->compound_related = false;
1345 req->sconn->smb2.compound_related_in_progress = false;
1347 req->current_idx = 1;
1349 /* Re-arrange the in.vectors. */
1350 memmove(&req->in.vector[req->current_idx],
1351 &req->in.vector[idx],
1352 sizeof(req->in.vector[0])*SMBD_SMB2_NUM_IOV_PER_REQ);
1353 req->in.vector_count = req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ;
1355 /* Re-arrange the out.vectors. */
1356 memmove(&req->out.vector[req->current_idx],
1357 &req->out.vector[idx],
1358 sizeof(req->out.vector[0])*SMBD_SMB2_NUM_IOV_PER_REQ);
1359 req->out.vector_count = req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ;
1361 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1362 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1363 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1365 data_blob_clear_free(&req->last_key);
1367 defer_endtime = timeval_current_ofs_usec(defer_time);
1368 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1370 smbd_smb2_request_pending_timer,
1372 if (req->async_te == NULL) {
1373 return NT_STATUS_NO_MEMORY;
1376 return NT_STATUS_OK;
1379 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1380 struct tevent_timer *te,
1381 struct timeval current_time,
1384 struct smbd_smb2_request *req =
1385 talloc_get_type_abort(private_data,
1386 struct smbd_smb2_request);
1387 struct smbd_smb2_request_pending_state *state = NULL;
1388 uint8_t *outhdr = NULL;
1389 const uint8_t *inhdr = NULL;
1392 uint8_t *hdr = NULL;
1393 uint8_t *body = NULL;
1394 uint8_t *dyn = NULL;
1396 uint64_t session_id = 0;
1397 uint64_t message_id = 0;
1398 uint64_t nonce_high = 0;
1399 uint64_t nonce_low = 0;
1400 uint64_t async_id = 0;
1401 struct tevent_req *subreq = NULL;
1403 TALLOC_FREE(req->async_te);
1405 /* Ensure our final reply matches the interim one. */
1406 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1407 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1408 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1409 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1410 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1412 async_id = message_id; /* keep it simple for now... */
1414 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1415 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1417 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1419 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1420 (unsigned long long)async_id ));
1423 * What we send is identical to a smbd_smb2_request_error
1424 * packet with an error status of STATUS_PENDING. Make use
1425 * of this fact sometime when refactoring. JRA.
1428 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1429 if (state == NULL) {
1430 smbd_server_connection_terminate(req->sconn,
1431 nt_errstr(NT_STATUS_NO_MEMORY));
1434 state->sconn = req->sconn;
1436 tf = state->buf + NBT_HDR_SIZE;
1437 tf_len = SMB2_TF_HDR_SIZE;
1439 hdr = tf + SMB2_TF_HDR_SIZE;
1440 body = hdr + SMB2_HDR_BODY;
1443 if (req->do_encryption) {
1444 struct smbXsrv_session *x = req->session;
1446 nonce_high = x->nonce_high;
1447 nonce_low = x->nonce_low;
1450 if (x->nonce_low == 0) {
1456 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1457 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1458 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1459 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1461 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1462 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1463 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1464 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1465 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1467 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1468 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1469 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1470 SBVAL(hdr, SMB2_HDR_PID, async_id);
1471 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1472 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1473 memcpy(hdr+SMB2_HDR_SIGNATURE,
1474 outhdr+SMB2_HDR_SIGNATURE, 16);
1476 SSVAL(body, 0x00, 0x08 + 1);
1478 SCVAL(body, 0x02, 0);
1479 SCVAL(body, 0x03, 0);
1480 SIVAL(body, 0x04, 0);
1481 /* Match W2K8R2... */
1482 SCVAL(dyn, 0x00, 0x21);
1484 state->vector[0].iov_base = (void *)state->buf;
1485 state->vector[0].iov_len = NBT_HDR_SIZE;
1487 if (req->do_encryption) {
1488 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1489 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1491 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1492 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1495 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1496 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1498 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1499 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1501 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1502 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1504 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1506 /* Ensure we correctly go through crediting. Grant
1507 the credits now, and zero credits on the final
1509 smb2_set_operation_credit(req->sconn,
1510 SMBD_SMB2_IN_HDR_IOV(req),
1511 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1513 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1518 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1519 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1521 (unsigned int)ARRAY_SIZE(state->vector),
1522 (unsigned int)state->vector[i].iov_len);
1526 if (req->do_encryption) {
1528 struct smbXsrv_session *x = req->session;
1529 struct smbXsrv_connection *conn = x->connection;
1530 DATA_BLOB encryption_key = x->global->encryption_key;
1532 status = smb2_signing_encrypt_pdu(encryption_key,
1534 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1535 SMBD_SMB2_NUM_IOV_PER_REQ);
1536 if (!NT_STATUS_IS_OK(status)) {
1537 smbd_server_connection_terminate(req->sconn,
1541 } else if (req->do_signing) {
1543 struct smbXsrv_session *x = req->session;
1544 struct smbXsrv_connection *conn = x->connection;
1545 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1547 status = smb2_signing_sign_pdu(signing_key,
1549 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1550 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1551 if (!NT_STATUS_IS_OK(status)) {
1552 smbd_server_connection_terminate(req->sconn,
1558 subreq = tstream_writev_queue_send(state,
1559 state->sconn->ev_ctx,
1560 state->sconn->smb2.stream,
1561 state->sconn->smb2.send_queue,
1563 ARRAY_SIZE(state->vector));
1564 if (subreq == NULL) {
1565 smbd_server_connection_terminate(state->sconn,
1566 nt_errstr(NT_STATUS_NO_MEMORY));
1569 tevent_req_set_callback(subreq,
1570 smbd_smb2_request_pending_writev_done,
1574 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1576 struct smbd_server_connection *sconn = req->sconn;
1577 struct smbd_smb2_request *cur;
1578 const uint8_t *inhdr;
1580 uint64_t search_message_id;
1581 uint64_t search_async_id;
1584 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1586 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1587 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1588 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1591 * we don't need the request anymore
1592 * cancel requests never have a response
1594 DLIST_REMOVE(req->sconn->smb2.requests, req);
1597 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1598 const uint8_t *outhdr;
1599 uint64_t message_id;
1602 if (cur->compound_related) {
1604 * Never cancel anything in a compound request.
1605 * Way too hard to deal with the result.
1610 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1612 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1613 async_id = BVAL(outhdr, SMB2_HDR_PID);
1615 if (flags & SMB2_HDR_FLAG_ASYNC) {
1616 if (search_async_id == async_id) {
1617 found_id = async_id;
1621 if (search_message_id == message_id) {
1622 found_id = message_id;
1628 if (cur && cur->subreq) {
1629 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1630 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1631 "cancel opcode[%s] mid %llu\n",
1632 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1633 (unsigned long long)found_id ));
1634 tevent_req_cancel(cur->subreq);
1637 return NT_STATUS_OK;
1640 /*************************************************************
1641 Ensure an incoming tid is a valid one for us to access.
1642 Change to the associated uid credentials and chdir to the
1643 valid tid directory.
1644 *************************************************************/
1646 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1648 const uint8_t *inhdr;
1651 struct smbXsrv_tcon *tcon;
1653 NTTIME now = timeval_to_nttime(&req->request_time);
1657 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1659 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1660 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1662 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1663 in_tid = req->last_tid;
1668 status = smb2srv_tcon_lookup(req->session,
1669 in_tid, now, &tcon);
1670 if (!NT_STATUS_IS_OK(status)) {
1674 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1675 return NT_STATUS_ACCESS_DENIED;
1678 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1679 if (!set_current_service(tcon->compat, 0, true)) {
1680 return NT_STATUS_ACCESS_DENIED;
1684 req->last_tid = in_tid;
1686 return NT_STATUS_OK;
1689 /*************************************************************
1690 Ensure an incoming session_id is a valid one for us to access.
1691 *************************************************************/
1693 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1695 const uint8_t *inhdr;
1698 uint64_t in_session_id;
1699 struct smbXsrv_session *session = NULL;
1700 struct auth_session_info *session_info;
1702 NTTIME now = timeval_to_nttime(&req->request_time);
1704 req->session = NULL;
1707 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1709 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1710 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1711 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1713 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1714 in_session_id = req->last_session_id;
1717 req->last_session_id = 0;
1719 /* lookup an existing session */
1720 status = smb2srv_session_lookup(req->sconn->conn,
1724 req->session = session;
1725 req->last_session_id = in_session_id;
1727 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1728 switch (in_opcode) {
1729 case SMB2_OP_SESSSETUP:
1730 status = NT_STATUS_OK;
1736 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1737 switch (in_opcode) {
1739 case SMB2_OP_CREATE:
1740 case SMB2_OP_GETINFO:
1741 case SMB2_OP_SETINFO:
1742 return NT_STATUS_INVALID_HANDLE;
1745 * Notice the check for
1746 * (session_info == NULL)
1749 status = NT_STATUS_OK;
1753 if (!NT_STATUS_IS_OK(status)) {
1757 session_info = session->global->auth_session_info;
1758 if (session_info == NULL) {
1759 return NT_STATUS_INVALID_HANDLE;
1762 set_current_user_info(session_info->unix_info->sanitized_username,
1763 session_info->unix_info->unix_name,
1764 session_info->info->domain_name);
1766 return NT_STATUS_OK;
1769 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1770 uint32_t data_length)
1772 uint16_t needed_charge;
1773 uint16_t credit_charge = 1;
1774 const uint8_t *inhdr;
1776 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1778 if (req->sconn->smb2.supports_multicredit) {
1779 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1780 credit_charge = MAX(credit_charge, 1);
1783 needed_charge = (data_length - 1)/ 65536 + 1;
1785 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1786 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1787 credit_charge, needed_charge));
1789 if (needed_charge > credit_charge) {
1790 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1791 credit_charge, needed_charge));
1792 return NT_STATUS_INVALID_PARAMETER;
1795 return NT_STATUS_OK;
1798 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1799 size_t expected_body_size)
1801 struct iovec *inhdr_v;
1802 const uint8_t *inhdr;
1804 const uint8_t *inbody;
1806 size_t min_dyn_size = expected_body_size & 0x00000001;
1807 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1810 * The following should be checked already.
1812 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1813 return NT_STATUS_INTERNAL_ERROR;
1815 if (req->current_idx > max_idx) {
1816 return NT_STATUS_INTERNAL_ERROR;
1819 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1820 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1821 return NT_STATUS_INTERNAL_ERROR;
1823 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1824 return NT_STATUS_INTERNAL_ERROR;
1827 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1828 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1832 case SMB2_OP_GETINFO:
1838 * Now check the expected body size,
1839 * where the last byte might be in the
1842 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1843 return NT_STATUS_INVALID_PARAMETER;
1845 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1846 return NT_STATUS_INVALID_PARAMETER;
1849 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1851 body_size = SVAL(inbody, 0x00);
1852 if (body_size != expected_body_size) {
1853 return NT_STATUS_INVALID_PARAMETER;
1856 return NT_STATUS_OK;
1859 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1861 struct smbXsrv_connection *conn = req->sconn->conn;
1862 const struct smbd_smb2_dispatch_table *call = NULL;
1863 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1864 const uint8_t *inhdr;
1869 NTSTATUS session_status;
1870 uint32_t allowed_flags;
1871 NTSTATUS return_value;
1872 struct smbXsrv_session *x = NULL;
1873 bool signing_required = false;
1874 bool encryption_required = false;
1876 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1878 /* TODO: verify more things */
1880 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1881 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1882 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1883 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1884 smb2_opcode_name(opcode),
1885 (unsigned long long)mid));
1887 if (conn->protocol >= PROTOCOL_SMB2_02) {
1889 * once the protocol is negotiated
1890 * SMB2_OP_NEGPROT is not allowed anymore
1892 if (opcode == SMB2_OP_NEGPROT) {
1893 /* drop the connection */
1894 return NT_STATUS_INVALID_PARAMETER;
1898 * if the protocol is not negotiated yet
1899 * only SMB2_OP_NEGPROT is allowed.
1901 if (opcode != SMB2_OP_NEGPROT) {
1902 /* drop the connection */
1903 return NT_STATUS_INVALID_PARAMETER;
1908 * Check if the client provided a valid session id,
1909 * if so smbd_smb2_request_check_session() calls
1910 * set_current_user_info().
1912 * As some command don't require a valid session id
1913 * we defer the check of the session_status
1915 session_status = smbd_smb2_request_check_session(req);
1918 signing_required = x->global->signing_required;
1919 encryption_required = x->global->encryption_required;
1921 if (opcode == SMB2_OP_SESSSETUP &&
1922 x->global->channels[0].signing_key.length) {
1923 signing_required = true;
1927 req->do_signing = false;
1928 req->do_encryption = false;
1929 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
1930 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
1931 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
1933 if (x != NULL && x->global->session_wire_id != tf_session_id) {
1934 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1935 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1936 (unsigned long long)x->global->session_wire_id,
1937 (unsigned long long)tf_session_id));
1939 * TODO: windows allows this...
1940 * should we drop the connection?
1942 * For now we just return ACCESS_DENIED
1943 * (Windows clients never trigger this)
1944 * and wait for an update of [MS-SMB2].
1946 return smbd_smb2_request_error(req,
1947 NT_STATUS_ACCESS_DENIED);
1950 req->do_encryption = true;
1953 if (encryption_required && !req->do_encryption) {
1954 return smbd_smb2_request_error(req,
1955 NT_STATUS_ACCESS_DENIED);
1958 call = smbd_smb2_call(opcode);
1960 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1963 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1964 SMB2_HDR_FLAG_SIGNED |
1966 if (opcode == SMB2_OP_CANCEL) {
1967 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1969 if ((flags & ~allowed_flags) != 0) {
1970 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1973 if (flags & SMB2_HDR_FLAG_CHAINED) {
1975 * This check is mostly for giving the correct error code
1976 * for compounded requests.
1978 if (!NT_STATUS_IS_OK(session_status)) {
1979 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1982 req->compat_chain_fsp = NULL;
1985 if (req->do_encryption) {
1986 signing_required = false;
1987 } else if (flags & SMB2_HDR_FLAG_SIGNED) {
1988 DATA_BLOB signing_key;
1991 return smbd_smb2_request_error(
1992 req, NT_STATUS_ACCESS_DENIED);
1995 signing_key = x->global->channels[0].signing_key;
1998 * If we have a signing key, we should
2001 if (signing_key.length > 0) {
2002 req->do_signing = true;
2005 status = smb2_signing_check_pdu(signing_key,
2007 SMBD_SMB2_IN_HDR_IOV(req),
2008 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2009 if (!NT_STATUS_IS_OK(status)) {
2010 return smbd_smb2_request_error(req, status);
2014 * Now that we know the request was correctly signed
2015 * we have to sign the response too.
2017 req->do_signing = true;
2019 if (!NT_STATUS_IS_OK(session_status)) {
2020 return smbd_smb2_request_error(req, session_status);
2022 } else if (opcode == SMB2_OP_CANCEL) {
2023 /* Cancel requests are allowed to skip the signing */
2024 } else if (signing_required) {
2026 * If signing is required we try to sign
2027 * a possible error response
2029 req->do_signing = true;
2030 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2033 if (flags & SMB2_HDR_FLAG_CHAINED) {
2034 req->compound_related = true;
2035 req->sconn->smb2.compound_related_in_progress = true;
2038 if (call->need_session) {
2039 if (!NT_STATUS_IS_OK(session_status)) {
2040 return smbd_smb2_request_error(req, session_status);
2044 if (call->need_tcon) {
2045 SMB_ASSERT(call->need_session);
2048 * This call needs to be run as user.
2050 * smbd_smb2_request_check_tcon()
2051 * calls change_to_user() on success.
2053 status = smbd_smb2_request_check_tcon(req);
2054 if (!NT_STATUS_IS_OK(status)) {
2055 return smbd_smb2_request_error(req, status);
2057 if (req->tcon->global->encryption_required) {
2058 encryption_required = true;
2060 if (encryption_required && !req->do_encryption) {
2061 return smbd_smb2_request_error(req,
2062 NT_STATUS_ACCESS_DENIED);
2066 if (call->fileid_ofs != 0) {
2067 size_t needed = call->fileid_ofs + 16;
2068 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2069 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2070 uint64_t file_id_persistent;
2071 uint64_t file_id_volatile;
2072 struct files_struct *fsp;
2074 SMB_ASSERT(call->need_tcon);
2076 if (needed > body_size) {
2077 return smbd_smb2_request_error(req,
2078 NT_STATUS_INVALID_PARAMETER);
2081 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2082 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2084 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2086 if (!call->allow_invalid_fileid) {
2087 return smbd_smb2_request_error(req,
2088 NT_STATUS_FILE_CLOSED);
2091 if (file_id_persistent != UINT64_MAX) {
2092 return smbd_smb2_request_error(req,
2093 NT_STATUS_FILE_CLOSED);
2095 if (file_id_volatile != UINT64_MAX) {
2096 return smbd_smb2_request_error(req,
2097 NT_STATUS_FILE_CLOSED);
2102 if (call->as_root) {
2103 SMB_ASSERT(call->fileid_ofs == 0);
2104 /* This call needs to be run as root */
2105 change_to_root_user();
2107 SMB_ASSERT(call->need_tcon);
2111 case SMB2_OP_NEGPROT:
2113 START_PROFILE(smb2_negprot);
2114 return_value = smbd_smb2_request_process_negprot(req);
2115 END_PROFILE(smb2_negprot);
2119 case SMB2_OP_SESSSETUP:
2121 START_PROFILE(smb2_sesssetup);
2122 return_value = smbd_smb2_request_process_sesssetup(req);
2123 END_PROFILE(smb2_sesssetup);
2127 case SMB2_OP_LOGOFF:
2129 START_PROFILE(smb2_logoff);
2130 return_value = smbd_smb2_request_process_logoff(req);
2131 END_PROFILE(smb2_logoff);
2137 START_PROFILE(smb2_tcon);
2138 return_value = smbd_smb2_request_process_tcon(req);
2139 END_PROFILE(smb2_tcon);
2145 START_PROFILE(smb2_tdis);
2146 return_value = smbd_smb2_request_process_tdis(req);
2147 END_PROFILE(smb2_tdis);
2151 case SMB2_OP_CREATE:
2153 START_PROFILE(smb2_create);
2154 return_value = smbd_smb2_request_process_create(req);
2155 END_PROFILE(smb2_create);
2161 START_PROFILE(smb2_close);
2162 return_value = smbd_smb2_request_process_close(req);
2163 END_PROFILE(smb2_close);
2169 START_PROFILE(smb2_flush);
2170 return_value = smbd_smb2_request_process_flush(req);
2171 END_PROFILE(smb2_flush);
2177 START_PROFILE(smb2_read);
2178 return_value = smbd_smb2_request_process_read(req);
2179 END_PROFILE(smb2_read);
2185 START_PROFILE(smb2_write);
2186 return_value = smbd_smb2_request_process_write(req);
2187 END_PROFILE(smb2_write);
2193 START_PROFILE(smb2_lock);
2194 return_value = smbd_smb2_request_process_lock(req);
2195 END_PROFILE(smb2_lock);
2201 START_PROFILE(smb2_ioctl);
2202 return_value = smbd_smb2_request_process_ioctl(req);
2203 END_PROFILE(smb2_ioctl);
2207 case SMB2_OP_CANCEL:
2209 START_PROFILE(smb2_cancel);
2210 return_value = smbd_smb2_request_process_cancel(req);
2211 END_PROFILE(smb2_cancel);
2215 case SMB2_OP_KEEPALIVE:
2217 START_PROFILE(smb2_keepalive);
2218 return_value = smbd_smb2_request_process_keepalive(req);
2219 END_PROFILE(smb2_keepalive);
2225 START_PROFILE(smb2_find);
2226 return_value = smbd_smb2_request_process_find(req);
2227 END_PROFILE(smb2_find);
2231 case SMB2_OP_NOTIFY:
2233 START_PROFILE(smb2_notify);
2234 return_value = smbd_smb2_request_process_notify(req);
2235 END_PROFILE(smb2_notify);
2239 case SMB2_OP_GETINFO:
2241 START_PROFILE(smb2_getinfo);
2242 return_value = smbd_smb2_request_process_getinfo(req);
2243 END_PROFILE(smb2_getinfo);
2247 case SMB2_OP_SETINFO:
2249 START_PROFILE(smb2_setinfo);
2250 return_value = smbd_smb2_request_process_setinfo(req);
2251 END_PROFILE(smb2_setinfo);
2257 START_PROFILE(smb2_break);
2258 return_value = smbd_smb2_request_process_break(req);
2259 END_PROFILE(smb2_break);
2264 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2267 return return_value;
2270 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2272 struct smbXsrv_connection *conn = req->sconn->conn;
2273 struct tevent_req *subreq;
2275 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2276 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2277 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2280 TALLOC_FREE(req->async_te);
2282 if (req->do_encryption &&
2283 (firsttf->iov_len == 0) &&
2284 (req->first_key.length == 0) &&
2285 (req->session != NULL) &&
2286 (req->session->global->encryption_key.length != 0))
2288 DATA_BLOB encryption_key = req->session->global->encryption_key;
2290 uint64_t session_id = req->session->global->session_wire_id;
2291 struct smbXsrv_session *x = req->session;
2292 uint64_t nonce_high;
2295 nonce_high = x->nonce_high;
2296 nonce_low = x->nonce_low;
2299 if (x->nonce_low == 0) {
2305 * We need to place the SMB2_TRANSFORM header before the
2310 * we need to remember the encryption key
2311 * and defer the signing/encryption until
2312 * we are sure that we do not change
2315 req->first_key = data_blob_dup_talloc(req, encryption_key);
2316 if (req->first_key.data == NULL) {
2317 return NT_STATUS_NO_MEMORY;
2320 tf = talloc_zero_array(req->out.vector, uint8_t,
2323 return NT_STATUS_NO_MEMORY;
2326 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2327 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2328 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2329 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2331 firsttf->iov_base = (void *)tf;
2332 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2335 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2336 (req->last_key.length > 0) &&
2337 (firsttf->iov_len == 0))
2339 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2340 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2344 * As we are sure the header of the last request in the
2345 * compound chain will not change, we can to sign here
2346 * with the last signing key we remembered.
2348 status = smb2_signing_sign_pdu(req->last_key,
2351 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2352 if (!NT_STATUS_IS_OK(status)) {
2356 data_blob_clear_free(&req->last_key);
2358 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2360 if (req->current_idx < req->out.vector_count) {
2362 * We must process the remaining compound
2363 * SMB2 requests before any new incoming SMB2
2364 * requests. This is because incoming SMB2
2365 * requests may include a cancel for a
2366 * compound request we haven't processed
2369 struct tevent_immediate *im = tevent_create_immediate(req);
2371 return NT_STATUS_NO_MEMORY;
2374 if (req->do_signing && firsttf->iov_len == 0) {
2375 struct smbXsrv_session *x = req->session;
2376 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2379 * we need to remember the signing key
2380 * and defer the signing until
2381 * we are sure that we do not change
2384 req->last_key = data_blob_dup_talloc(req, signing_key);
2385 if (req->last_key.data == NULL) {
2386 return NT_STATUS_NO_MEMORY;
2390 tevent_schedule_immediate(im,
2392 smbd_smb2_request_dispatch_immediate,
2394 return NT_STATUS_OK;
2397 if (req->compound_related) {
2398 req->compound_related = false;
2399 req->sconn->smb2.compound_related_in_progress = false;
2402 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2404 /* Set credit for these operations (zero credits if this
2405 is a final reply for an async operation). */
2406 smb2_calculate_credits(req, req);
2409 * now check if we need to sign the current response
2411 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2414 status = smb2_signing_encrypt_pdu(req->first_key,
2417 req->out.vector_count - first_idx);
2418 if (!NT_STATUS_IS_OK(status)) {
2421 } else if (req->do_signing) {
2423 struct smbXsrv_session *x = req->session;
2424 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2426 status = smb2_signing_sign_pdu(signing_key,
2429 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2430 if (!NT_STATUS_IS_OK(status)) {
2434 data_blob_clear_free(&req->first_key);
2436 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2437 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2438 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2439 /* Dynamic part is NULL. Chop it off,
2440 We're going to send it via sendfile. */
2441 req->out.vector_count -= 1;
2444 subreq = tstream_writev_queue_send(req,
2446 req->sconn->smb2.stream,
2447 req->sconn->smb2.send_queue,
2449 req->out.vector_count);
2450 if (subreq == NULL) {
2451 return NT_STATUS_NO_MEMORY;
2453 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
2455 * We're done with this request -
2456 * move it off the "being processed" queue.
2458 DLIST_REMOVE(req->sconn->smb2.requests, req);
2460 return NT_STATUS_OK;
2463 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2465 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2466 struct tevent_immediate *im,
2469 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2470 struct smbd_smb2_request);
2471 struct smbd_server_connection *sconn = req->sconn;
2476 if (DEBUGLEVEL >= 10) {
2477 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2478 req->current_idx, req->in.vector_count));
2479 print_req_vectors(req);
2482 status = smbd_smb2_request_dispatch(req);
2483 if (!NT_STATUS_IS_OK(status)) {
2484 smbd_server_connection_terminate(sconn, nt_errstr(status));
2488 status = smbd_smb2_request_next_incoming(sconn);
2489 if (!NT_STATUS_IS_OK(status)) {
2490 smbd_server_connection_terminate(sconn, nt_errstr(status));
2495 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
2497 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
2498 struct smbd_smb2_request);
2499 struct smbd_server_connection *sconn = req->sconn;
2504 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2505 TALLOC_FREE(subreq);
2508 status = map_nt_error_from_unix(sys_errno);
2509 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2510 nt_errstr(status)));
2511 smbd_server_connection_terminate(sconn, nt_errstr(status));
2515 status = smbd_smb2_request_next_incoming(sconn);
2516 if (!NT_STATUS_IS_OK(status)) {
2517 smbd_server_connection_terminate(sconn, nt_errstr(status));
2522 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2524 DATA_BLOB body, DATA_BLOB *dyn,
2525 const char *location)
2528 struct iovec *outbody_v;
2529 struct iovec *outdyn_v;
2530 uint32_t next_command_ofs;
2532 DEBUG(10,("smbd_smb2_request_done_ex: "
2533 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2534 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2536 (unsigned int)(dyn ? dyn->length : 0),
2539 if (body.length < 2) {
2540 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2543 if ((body.length % 2) != 0) {
2544 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2547 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2548 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2549 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2551 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2552 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2554 outbody_v->iov_base = (void *)body.data;
2555 outbody_v->iov_len = body.length;
2558 outdyn_v->iov_base = (void *)dyn->data;
2559 outdyn_v->iov_len = dyn->length;
2561 outdyn_v->iov_base = NULL;
2562 outdyn_v->iov_len = 0;
2565 /* see if we need to recalculate the offset to the next response */
2566 if (next_command_ofs > 0) {
2567 next_command_ofs = SMB2_HDR_BODY;
2568 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2569 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2572 if ((next_command_ofs % 8) != 0) {
2573 size_t pad_size = 8 - (next_command_ofs % 8);
2574 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2576 * if the dyn buffer is empty
2577 * we can use it to add padding
2581 pad = talloc_zero_array(req->out.vector,
2584 return smbd_smb2_request_error(req,
2585 NT_STATUS_NO_MEMORY);
2588 outdyn_v->iov_base = (void *)pad;
2589 outdyn_v->iov_len = pad_size;
2592 * For now we copy the dynamic buffer
2593 * and add the padding to the new buffer
2600 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2601 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2603 new_size = old_size + pad_size;
2604 new_dyn = talloc_zero_array(req->out.vector,
2606 if (new_dyn == NULL) {
2607 return smbd_smb2_request_error(req,
2608 NT_STATUS_NO_MEMORY);
2611 memcpy(new_dyn, old_dyn, old_size);
2612 memset(new_dyn + old_size, 0, pad_size);
2614 outdyn_v->iov_base = (void *)new_dyn;
2615 outdyn_v->iov_len = new_size;
2617 next_command_ofs += pad_size;
2620 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2622 return smbd_smb2_request_reply(req);
2625 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2628 const char *location)
2631 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2632 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2634 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2635 req->current_idx, nt_errstr(status), info ? " +info" : "",
2639 /* Recvfile error. Drain incoming socket. */
2640 size_t ret = drain_socket(req->sconn->sock, unread_bytes);
2641 if (ret != unread_bytes) {
2642 smbd_server_connection_terminate(req->sconn,
2643 "Failed to drain SMB2 socket\n");
2647 body.data = outhdr + SMB2_HDR_BODY;
2649 SSVAL(body.data, 0, 9);
2652 SIVAL(body.data, 0x04, info->length);
2654 /* Allocated size of req->out.vector[i].iov_base
2655 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2656 * 1 byte without having to do an alloc.
2658 info = talloc_zero_array(req->out.vector,
2662 return NT_STATUS_NO_MEMORY;
2664 info->data = ((uint8_t *)outhdr) +
2665 OUTVEC_ALLOC_SIZE - 1;
2667 SCVAL(info->data, 0, 0);
2671 * Note: Even if there is an error, continue to process the request.
2675 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2679 struct smbd_smb2_send_oplock_break_state {
2680 struct smbd_server_connection *sconn;
2681 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x18];
2682 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2685 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2687 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2688 struct smbXsrv_session *session,
2689 struct smbXsrv_tcon *tcon,
2690 struct smbXsrv_open *op,
2691 uint8_t oplock_level)
2693 struct smbd_smb2_send_oplock_break_state *state;
2694 struct smbXsrv_connection *conn = sconn->conn;
2695 struct tevent_req *subreq;
2703 bool do_encryption = session->global->encryption_required;
2704 uint64_t nonce_high = 0;
2705 uint64_t nonce_low = 0;
2707 if (tcon->global->encryption_required) {
2708 do_encryption = true;
2711 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2712 if (state == NULL) {
2713 return NT_STATUS_NO_MEMORY;
2715 state->sconn = sconn;
2717 tf = state->buf + NBT_HDR_SIZE;
2718 tf_len = SMB2_TF_HDR_SIZE;
2720 body = hdr + SMB2_HDR_BODY;
2722 dyn = body + body_len;
2725 if (do_encryption) {
2726 nonce_high = session->nonce_high;
2727 nonce_low = session->nonce_low;
2729 session->nonce_low += 1;
2730 if (session->nonce_low == 0) {
2731 session->nonce_low += 1;
2732 session->nonce_high += 1;
2736 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2737 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2738 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2739 SBVAL(tf, SMB2_TF_SESSION_ID, session->global->session_wire_id);
2741 SIVAL(hdr, 0, SMB2_MAGIC);
2742 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2743 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2744 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2745 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2746 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2747 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2748 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2749 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2750 SIVAL(hdr, SMB2_HDR_PID, 0);
2751 SIVAL(hdr, SMB2_HDR_TID, 0);
2752 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2753 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2755 SSVAL(body, 0x00, body_len);
2757 SCVAL(body, 0x02, oplock_level);
2758 SCVAL(body, 0x03, 0); /* reserved */
2759 SIVAL(body, 0x04, 0); /* reserved */
2760 SBVAL(body, 0x08, op->global->open_persistent_id);
2761 SBVAL(body, 0x10, op->global->open_volatile_id);
2763 state->vector[0].iov_base = (void *)state->buf;
2764 state->vector[0].iov_len = NBT_HDR_SIZE;
2766 if (do_encryption) {
2767 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
2768 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
2770 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
2771 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
2774 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
2775 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
2777 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
2778 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = body_len;
2780 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
2781 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_len;
2783 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2785 if (do_encryption) {
2787 DATA_BLOB encryption_key = session->global->encryption_key;
2789 status = smb2_signing_encrypt_pdu(encryption_key,
2791 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2792 SMBD_SMB2_NUM_IOV_PER_REQ);
2793 if (!NT_STATUS_IS_OK(status)) {
2798 subreq = tstream_writev_queue_send(state,
2801 sconn->smb2.send_queue,
2803 ARRAY_SIZE(state->vector));
2804 if (subreq == NULL) {
2805 return NT_STATUS_NO_MEMORY;
2807 tevent_req_set_callback(subreq,
2808 smbd_smb2_oplock_break_writev_done,
2811 return NT_STATUS_OK;
2814 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2816 struct smbd_smb2_send_oplock_break_state *state =
2817 tevent_req_callback_data(subreq,
2818 struct smbd_smb2_send_oplock_break_state);
2819 struct smbd_server_connection *sconn = state->sconn;
2823 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2824 TALLOC_FREE(subreq);
2826 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2827 smbd_server_connection_terminate(sconn, nt_errstr(status));
2834 struct smbd_smb2_request_read_state {
2835 struct tevent_context *ev;
2836 struct smbd_server_connection *sconn;
2837 struct smbd_smb2_request *smb2_req;
2839 uint8_t nbt[NBT_HDR_SIZE];
2842 bool doing_receivefile;
2843 size_t min_recv_size;
2848 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2850 TALLOC_CTX *mem_ctx,
2851 struct iovec **_vector,
2853 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2855 static size_t get_min_receive_file_size(struct smbd_smb2_request *smb2_req)
2857 if (smb2_req->do_signing) {
2860 if (smb2_req->do_encryption) {
2863 return (size_t)lp_min_receive_file_size();
2866 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2867 struct tevent_context *ev,
2868 struct smbd_server_connection *sconn)
2870 struct tevent_req *req;
2871 struct smbd_smb2_request_read_state *state;
2872 struct tevent_req *subreq;
2874 req = tevent_req_create(mem_ctx, &state,
2875 struct smbd_smb2_request_read_state);
2880 state->sconn = sconn;
2882 state->smb2_req = smbd_smb2_request_allocate(state);
2883 if (tevent_req_nomem(state->smb2_req, req)) {
2884 return tevent_req_post(req, ev);
2886 state->smb2_req->sconn = sconn;
2887 state->min_recv_size = get_min_receive_file_size(state->smb2_req);
2889 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
2891 state->sconn->smb2.stream,
2892 state->sconn->smb2.recv_queue,
2893 smbd_smb2_request_next_vector,
2895 if (tevent_req_nomem(subreq, req)) {
2896 return tevent_req_post(req, ev);
2898 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2903 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2907 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
2908 /* Transform header. Cannot recvfile. */
2911 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
2912 /* Not SMB2. Normal error path will cope. */
2915 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
2916 /* Not SMB2. Normal error path will cope. */
2919 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
2920 /* Needs to be a WRITE. */
2923 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
2924 /* Chained. Cannot recvfile. */
2927 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
2928 if (flags & SMB2_HDR_FLAG_CHAINED) {
2929 /* Chained. Cannot recvfile. */
2932 if (flags & SMB2_HDR_FLAG_SIGNED) {
2933 /* Signed. Cannot recvfile. */
2937 DEBUG(10,("Doing recvfile write len = %u\n",
2938 (unsigned int)(state->pktlen -
2939 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN)));
2944 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2946 TALLOC_CTX *mem_ctx,
2947 struct iovec **_vector,
2950 struct smbd_smb2_request_read_state *state =
2951 talloc_get_type_abort(private_data,
2952 struct smbd_smb2_request_read_state);
2953 struct iovec *vector = NULL;
2954 size_t min_recvfile_size = UINT32_MAX;
2956 if (state->pktlen > 0) {
2957 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
2959 * Not a possible receivefile write.
2960 * Read the rest of the data.
2962 state->doing_receivefile = false;
2963 vector = talloc_array(mem_ctx, struct iovec, 1);
2964 if (vector == NULL) {
2967 vector[0].iov_base = (void *)(state->pktbuf +
2968 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN);
2969 vector[0].iov_len = (state->pktlen -
2970 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN);
2975 * Either this is a receivefile write so we've
2976 * done a short read, or if not we have all the data.
2977 * Either way, we're done and
2978 * smbd_smb2_request_read_done() will handle
2979 * and short read case by looking at the
2980 * state->doing_receivefile value.
2988 if (!state->hdr.done) {
2990 * first we need to get the NBT header
2992 vector = talloc_array(mem_ctx, struct iovec, 1);
2993 if (vector == NULL) {
2997 vector[0].iov_base = (void *)state->hdr.nbt;
2998 vector[0].iov_len = NBT_HDR_SIZE;
3003 state->hdr.done = true;
3008 * Now we analyze the NBT header
3010 state->pktlen = smb2_len(state->hdr.nbt);
3012 if (state->pktlen == 0) {
3013 /* if there're no remaining bytes, we're done */
3019 state->pktbuf = talloc_array(state->smb2_req, uint8_t, state->pktlen);
3020 if (state->pktbuf == NULL) {
3024 vector = talloc_array(mem_ctx, struct iovec, 1);
3025 if (vector == NULL) {
3029 vector[0].iov_base = (void *)state->pktbuf;
3031 if (state->min_recv_size != 0) {
3032 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3033 min_recvfile_size += state->min_recv_size;
3036 if (state->pktlen > min_recvfile_size) {
3038 * Might be a receivefile write. Read the SMB2 HEADER +
3039 * SMB2_WRITE header first. Set 'doing_receivefile'
3040 * as we're *attempting* receivefile write. If this
3041 * turns out not to be a SMB2_WRITE request or otherwise
3042 * not suitable then we'll just read the rest of the data
3043 * the next time this function is called.
3045 vector[0].iov_len = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3046 state->doing_receivefile = true;
3048 vector[0].iov_len = state->pktlen;
3056 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
3058 struct tevent_req *req =
3059 tevent_req_callback_data(subreq,
3061 struct smbd_smb2_request_read_state *state =
3062 tevent_req_data(req,
3063 struct smbd_smb2_request_read_state);
3069 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
3070 TALLOC_FREE(subreq);
3072 status = map_nt_error_from_unix(sys_errno);
3073 tevent_req_nterror(req, status);
3077 if (state->hdr.nbt[0] != 0x00) {
3078 DEBUG(1,("smbd_smb2_request_read_done: ignore NBT[0x%02X] msg\n",
3079 state->hdr.nbt[0]));
3081 ZERO_STRUCT(state->hdr);
3082 TALLOC_FREE(state->pktbuf);
3085 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
3087 state->sconn->smb2.stream,
3088 state->sconn->smb2.recv_queue,
3089 smbd_smb2_request_next_vector,
3091 if (tevent_req_nomem(subreq, req)) {
3094 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
3098 state->smb2_req->request_time = timeval_current();
3099 now = timeval_to_nttime(&state->smb2_req->request_time);
3101 status = smbd_smb2_inbuf_parse_compound(state->smb2_req->sconn->conn,
3106 &state->smb2_req->in.vector,
3107 &state->smb2_req->in.vector_count);
3108 if (tevent_req_nterror(req, status)) {
3112 if (state->doing_receivefile) {
3113 state->smb2_req->smb1req = talloc_zero(state->smb2_req,
3114 struct smb_request);
3115 if (tevent_req_nomem(state->smb2_req->smb1req, req)) {
3118 state->smb2_req->smb1req->unread_bytes =
3119 state->pktlen - SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3122 state->smb2_req->current_idx = 1;
3124 tevent_req_done(req);
3127 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
3128 TALLOC_CTX *mem_ctx,
3129 struct smbd_smb2_request **_smb2_req)
3131 struct smbd_smb2_request_read_state *state =
3132 tevent_req_data(req,
3133 struct smbd_smb2_request_read_state);
3136 if (tevent_req_is_nterror(req, &status)) {
3137 tevent_req_received(req);
3141 *_smb2_req = talloc_move(mem_ctx, &state->smb2_req);
3142 tevent_req_received(req);
3143 return NT_STATUS_OK;
3146 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
3148 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
3150 size_t max_send_queue_len;
3151 size_t cur_send_queue_len;
3152 struct tevent_req *subreq;
3154 if (sconn->smb2.compound_related_in_progress) {
3156 * Can't read another until the related
3159 return NT_STATUS_OK;
3162 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
3164 * if there is already a smbd_smb2_request_read
3165 * pending, we are done.
3167 return NT_STATUS_OK;
3170 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
3171 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
3173 if (cur_send_queue_len > max_send_queue_len) {
3175 * if we have a lot of requests to send,
3176 * we wait until they are on the wire until we
3177 * ask for the next request.
3179 return NT_STATUS_OK;
3182 /* ask for the next request */
3183 subreq = smbd_smb2_request_read_send(sconn, sconn->ev_ctx, sconn);
3184 if (subreq == NULL) {
3185 return NT_STATUS_NO_MEMORY;
3187 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
3189 return NT_STATUS_OK;
3192 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
3193 uint8_t *inbuf, size_t size)
3196 struct smbd_smb2_request *req = NULL;
3198 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3199 (unsigned int)size));
3201 status = smbd_initialize_smb2(sconn);
3202 if (!NT_STATUS_IS_OK(status)) {
3203 smbd_server_connection_terminate(sconn, nt_errstr(status));
3207 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
3208 if (!NT_STATUS_IS_OK(status)) {
3209 smbd_server_connection_terminate(sconn, nt_errstr(status));
3213 status = smbd_smb2_request_validate(req);
3214 if (!NT_STATUS_IS_OK(status)) {
3215 smbd_server_connection_terminate(sconn, nt_errstr(status));
3219 status = smbd_smb2_request_setup_out(req);
3220 if (!NT_STATUS_IS_OK(status)) {
3221 smbd_server_connection_terminate(sconn, nt_errstr(status));
3225 status = smbd_smb2_request_dispatch(req);
3226 if (!NT_STATUS_IS_OK(status)) {
3227 smbd_server_connection_terminate(sconn, nt_errstr(status));
3231 status = smbd_smb2_request_next_incoming(sconn);
3232 if (!NT_STATUS_IS_OK(status)) {
3233 smbd_server_connection_terminate(sconn, nt_errstr(status));
3237 sconn->num_requests++;
3240 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
3242 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
3243 struct smbd_server_connection);
3245 struct smbd_smb2_request *req = NULL;
3247 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
3248 TALLOC_FREE(subreq);
3249 if (!NT_STATUS_IS_OK(status)) {
3250 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
3251 nt_errstr(status)));
3252 smbd_server_connection_terminate(sconn, nt_errstr(status));
3256 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
3257 req->current_idx, req->in.vector_count));
3259 status = smbd_smb2_request_validate(req);
3260 if (!NT_STATUS_IS_OK(status)) {
3261 smbd_server_connection_terminate(sconn, nt_errstr(status));
3265 status = smbd_smb2_request_setup_out(req);
3266 if (!NT_STATUS_IS_OK(status)) {
3267 smbd_server_connection_terminate(sconn, nt_errstr(status));
3271 status = smbd_smb2_request_dispatch(req);
3272 if (!NT_STATUS_IS_OK(status)) {
3273 smbd_server_connection_terminate(sconn, nt_errstr(status));
3277 status = smbd_smb2_request_next_incoming(sconn);
3278 if (!NT_STATUS_IS_OK(status)) {
3279 smbd_server_connection_terminate(sconn, nt_errstr(status));
3283 sconn->num_requests++;
3285 /* The timeout_processing function isn't run nearly
3286 often enough to implement 'max log size' without
3287 overrunning the size of the file by many megabytes.
3288 This is especially true if we are running at debug
3289 level 10. Checking every 50 SMB2s is a nice
3290 tradeoff of performance vs log file size overrun. */
3292 if ((sconn->num_requests % 50) == 0 &&
3293 need_to_check_log_size()) {
3294 change_to_root_user();