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 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1370 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1371 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1374 data_blob_clear_free(&req->last_key);
1376 defer_endtime = timeval_current_ofs_usec(defer_time);
1377 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1379 smbd_smb2_request_pending_timer,
1381 if (req->async_te == NULL) {
1382 return NT_STATUS_NO_MEMORY;
1385 return NT_STATUS_OK;
1388 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1389 struct tevent_timer *te,
1390 struct timeval current_time,
1393 struct smbd_smb2_request *req =
1394 talloc_get_type_abort(private_data,
1395 struct smbd_smb2_request);
1396 struct smbd_smb2_request_pending_state *state = NULL;
1397 uint8_t *outhdr = NULL;
1398 const uint8_t *inhdr = NULL;
1401 uint8_t *hdr = NULL;
1402 uint8_t *body = NULL;
1403 uint8_t *dyn = NULL;
1405 uint64_t session_id = 0;
1406 uint64_t message_id = 0;
1407 uint64_t nonce_high = 0;
1408 uint64_t nonce_low = 0;
1409 uint64_t async_id = 0;
1410 struct tevent_req *subreq = NULL;
1412 TALLOC_FREE(req->async_te);
1414 /* Ensure our final reply matches the interim one. */
1415 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1416 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1417 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1418 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1419 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1421 async_id = message_id; /* keep it simple for now... */
1423 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1424 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1426 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1428 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1429 (unsigned long long)async_id ));
1432 * What we send is identical to a smbd_smb2_request_error
1433 * packet with an error status of STATUS_PENDING. Make use
1434 * of this fact sometime when refactoring. JRA.
1437 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1438 if (state == NULL) {
1439 smbd_server_connection_terminate(req->sconn,
1440 nt_errstr(NT_STATUS_NO_MEMORY));
1443 state->sconn = req->sconn;
1445 tf = state->buf + NBT_HDR_SIZE;
1446 tf_len = SMB2_TF_HDR_SIZE;
1448 hdr = tf + SMB2_TF_HDR_SIZE;
1449 body = hdr + SMB2_HDR_BODY;
1452 if (req->do_encryption) {
1453 struct smbXsrv_session *x = req->session;
1455 nonce_high = x->nonce_high;
1456 nonce_low = x->nonce_low;
1459 if (x->nonce_low == 0) {
1465 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1466 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1467 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1468 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1470 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1471 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1472 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1473 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1474 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1476 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1477 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1478 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1479 SBVAL(hdr, SMB2_HDR_PID, async_id);
1480 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1481 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1482 memcpy(hdr+SMB2_HDR_SIGNATURE,
1483 outhdr+SMB2_HDR_SIGNATURE, 16);
1485 SSVAL(body, 0x00, 0x08 + 1);
1487 SCVAL(body, 0x02, 0);
1488 SCVAL(body, 0x03, 0);
1489 SIVAL(body, 0x04, 0);
1490 /* Match W2K8R2... */
1491 SCVAL(dyn, 0x00, 0x21);
1493 state->vector[0].iov_base = (void *)state->buf;
1494 state->vector[0].iov_len = NBT_HDR_SIZE;
1496 if (req->do_encryption) {
1497 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1498 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1500 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1501 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1504 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1505 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1507 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1508 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1510 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1511 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1513 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1515 /* Ensure we correctly go through crediting. Grant
1516 the credits now, and zero credits on the final
1518 smb2_set_operation_credit(req->sconn,
1519 SMBD_SMB2_IN_HDR_IOV(req),
1520 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1522 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1527 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1528 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1530 (unsigned int)ARRAY_SIZE(state->vector),
1531 (unsigned int)state->vector[i].iov_len);
1535 if (req->do_encryption) {
1537 struct smbXsrv_session *x = req->session;
1538 struct smbXsrv_connection *conn = x->connection;
1539 DATA_BLOB encryption_key = x->global->encryption_key;
1541 status = smb2_signing_encrypt_pdu(encryption_key,
1543 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1544 SMBD_SMB2_NUM_IOV_PER_REQ);
1545 if (!NT_STATUS_IS_OK(status)) {
1546 smbd_server_connection_terminate(req->sconn,
1550 } else if (req->do_signing) {
1552 struct smbXsrv_session *x = req->session;
1553 struct smbXsrv_connection *conn = x->connection;
1554 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1556 status = smb2_signing_sign_pdu(signing_key,
1558 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1559 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1560 if (!NT_STATUS_IS_OK(status)) {
1561 smbd_server_connection_terminate(req->sconn,
1567 subreq = tstream_writev_queue_send(state,
1568 state->sconn->ev_ctx,
1569 state->sconn->smb2.stream,
1570 state->sconn->smb2.send_queue,
1572 ARRAY_SIZE(state->vector));
1573 if (subreq == NULL) {
1574 smbd_server_connection_terminate(state->sconn,
1575 nt_errstr(NT_STATUS_NO_MEMORY));
1578 tevent_req_set_callback(subreq,
1579 smbd_smb2_request_pending_writev_done,
1583 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1585 struct smbd_server_connection *sconn = req->sconn;
1586 struct smbd_smb2_request *cur;
1587 const uint8_t *inhdr;
1589 uint64_t search_message_id;
1590 uint64_t search_async_id;
1593 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1595 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1596 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1597 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1600 * we don't need the request anymore
1601 * cancel requests never have a response
1603 DLIST_REMOVE(req->sconn->smb2.requests, req);
1606 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1607 const uint8_t *outhdr;
1608 uint64_t message_id;
1611 if (cur->compound_related) {
1613 * Never cancel anything in a compound request.
1614 * Way too hard to deal with the result.
1619 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1621 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1622 async_id = BVAL(outhdr, SMB2_HDR_PID);
1624 if (flags & SMB2_HDR_FLAG_ASYNC) {
1625 if (search_async_id == async_id) {
1626 found_id = async_id;
1630 if (search_message_id == message_id) {
1631 found_id = message_id;
1637 if (cur && cur->subreq) {
1638 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1639 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1640 "cancel opcode[%s] mid %llu\n",
1641 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1642 (unsigned long long)found_id ));
1643 tevent_req_cancel(cur->subreq);
1646 return NT_STATUS_OK;
1649 /*************************************************************
1650 Ensure an incoming tid is a valid one for us to access.
1651 Change to the associated uid credentials and chdir to the
1652 valid tid directory.
1653 *************************************************************/
1655 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1657 const uint8_t *inhdr;
1660 struct smbXsrv_tcon *tcon;
1662 NTTIME now = timeval_to_nttime(&req->request_time);
1666 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1668 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1669 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1671 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1672 in_tid = req->last_tid;
1677 status = smb2srv_tcon_lookup(req->session,
1678 in_tid, now, &tcon);
1679 if (!NT_STATUS_IS_OK(status)) {
1683 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1684 return NT_STATUS_ACCESS_DENIED;
1687 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1688 if (!set_current_service(tcon->compat, 0, true)) {
1689 return NT_STATUS_ACCESS_DENIED;
1693 req->last_tid = in_tid;
1695 return NT_STATUS_OK;
1698 /*************************************************************
1699 Ensure an incoming session_id is a valid one for us to access.
1700 *************************************************************/
1702 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1704 const uint8_t *inhdr;
1707 uint64_t in_session_id;
1708 struct smbXsrv_session *session = NULL;
1709 struct auth_session_info *session_info;
1711 NTTIME now = timeval_to_nttime(&req->request_time);
1713 req->session = NULL;
1716 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1718 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1719 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1720 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1722 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1723 in_session_id = req->last_session_id;
1726 req->last_session_id = 0;
1728 /* lookup an existing session */
1729 status = smb2srv_session_lookup(req->sconn->conn,
1733 req->session = session;
1734 req->last_session_id = in_session_id;
1736 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1737 switch (in_opcode) {
1738 case SMB2_OP_SESSSETUP:
1739 status = NT_STATUS_OK;
1745 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1746 switch (in_opcode) {
1748 case SMB2_OP_CREATE:
1749 case SMB2_OP_GETINFO:
1750 case SMB2_OP_SETINFO:
1751 return NT_STATUS_INVALID_HANDLE;
1754 * Notice the check for
1755 * (session_info == NULL)
1758 status = NT_STATUS_OK;
1762 if (!NT_STATUS_IS_OK(status)) {
1766 session_info = session->global->auth_session_info;
1767 if (session_info == NULL) {
1768 return NT_STATUS_INVALID_HANDLE;
1771 set_current_user_info(session_info->unix_info->sanitized_username,
1772 session_info->unix_info->unix_name,
1773 session_info->info->domain_name);
1775 return NT_STATUS_OK;
1778 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1779 uint32_t data_length)
1781 uint16_t needed_charge;
1782 uint16_t credit_charge = 1;
1783 const uint8_t *inhdr;
1785 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1787 if (req->sconn->smb2.supports_multicredit) {
1788 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1789 credit_charge = MAX(credit_charge, 1);
1792 needed_charge = (data_length - 1)/ 65536 + 1;
1794 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1795 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1796 credit_charge, needed_charge));
1798 if (needed_charge > credit_charge) {
1799 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1800 credit_charge, needed_charge));
1801 return NT_STATUS_INVALID_PARAMETER;
1804 return NT_STATUS_OK;
1807 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1808 size_t expected_body_size)
1810 struct iovec *inhdr_v;
1811 const uint8_t *inhdr;
1813 const uint8_t *inbody;
1815 size_t min_dyn_size = expected_body_size & 0x00000001;
1816 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1819 * The following should be checked already.
1821 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1822 return NT_STATUS_INTERNAL_ERROR;
1824 if (req->current_idx > max_idx) {
1825 return NT_STATUS_INTERNAL_ERROR;
1828 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1829 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1830 return NT_STATUS_INTERNAL_ERROR;
1832 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1833 return NT_STATUS_INTERNAL_ERROR;
1836 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1837 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1841 case SMB2_OP_GETINFO:
1847 * Now check the expected body size,
1848 * where the last byte might be in the
1851 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1852 return NT_STATUS_INVALID_PARAMETER;
1854 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1855 return NT_STATUS_INVALID_PARAMETER;
1858 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1860 body_size = SVAL(inbody, 0x00);
1861 if (body_size != expected_body_size) {
1862 return NT_STATUS_INVALID_PARAMETER;
1865 return NT_STATUS_OK;
1868 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1870 struct smbXsrv_connection *conn = req->sconn->conn;
1871 const struct smbd_smb2_dispatch_table *call = NULL;
1872 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1873 const uint8_t *inhdr;
1878 NTSTATUS session_status;
1879 uint32_t allowed_flags;
1880 NTSTATUS return_value;
1881 struct smbXsrv_session *x = NULL;
1882 bool signing_required = false;
1883 bool encryption_required = false;
1885 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1887 /* TODO: verify more things */
1889 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1890 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1891 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1892 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1893 smb2_opcode_name(opcode),
1894 (unsigned long long)mid));
1896 if (conn->protocol >= PROTOCOL_SMB2_02) {
1898 * once the protocol is negotiated
1899 * SMB2_OP_NEGPROT is not allowed anymore
1901 if (opcode == SMB2_OP_NEGPROT) {
1902 /* drop the connection */
1903 return NT_STATUS_INVALID_PARAMETER;
1907 * if the protocol is not negotiated yet
1908 * only SMB2_OP_NEGPROT is allowed.
1910 if (opcode != SMB2_OP_NEGPROT) {
1911 /* drop the connection */
1912 return NT_STATUS_INVALID_PARAMETER;
1917 * Check if the client provided a valid session id,
1918 * if so smbd_smb2_request_check_session() calls
1919 * set_current_user_info().
1921 * As some command don't require a valid session id
1922 * we defer the check of the session_status
1924 session_status = smbd_smb2_request_check_session(req);
1927 signing_required = x->global->signing_required;
1928 encryption_required = x->global->encryption_required;
1930 if (opcode == SMB2_OP_SESSSETUP &&
1931 x->global->channels[0].signing_key.length) {
1932 signing_required = true;
1936 req->do_signing = false;
1937 req->do_encryption = false;
1938 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
1939 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
1940 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
1942 if (x != NULL && x->global->session_wire_id != tf_session_id) {
1943 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1944 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1945 (unsigned long long)x->global->session_wire_id,
1946 (unsigned long long)tf_session_id));
1948 * TODO: windows allows this...
1949 * should we drop the connection?
1951 * For now we just return ACCESS_DENIED
1952 * (Windows clients never trigger this)
1953 * and wait for an update of [MS-SMB2].
1955 return smbd_smb2_request_error(req,
1956 NT_STATUS_ACCESS_DENIED);
1959 req->do_encryption = true;
1962 if (encryption_required && !req->do_encryption) {
1963 return smbd_smb2_request_error(req,
1964 NT_STATUS_ACCESS_DENIED);
1967 call = smbd_smb2_call(opcode);
1969 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1972 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1973 SMB2_HDR_FLAG_SIGNED |
1975 if (opcode == SMB2_OP_CANCEL) {
1976 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1978 if ((flags & ~allowed_flags) != 0) {
1979 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1982 if (flags & SMB2_HDR_FLAG_CHAINED) {
1984 * This check is mostly for giving the correct error code
1985 * for compounded requests.
1987 if (!NT_STATUS_IS_OK(session_status)) {
1988 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1991 req->compat_chain_fsp = NULL;
1994 if (req->do_encryption) {
1995 signing_required = false;
1996 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
1997 DATA_BLOB signing_key;
2000 return smbd_smb2_request_error(
2001 req, NT_STATUS_USER_SESSION_DELETED);
2004 signing_key = x->global->channels[0].signing_key;
2007 * If we have a signing key, we should
2010 if (signing_key.length > 0) {
2011 req->do_signing = true;
2014 status = smb2_signing_check_pdu(signing_key,
2016 SMBD_SMB2_IN_HDR_IOV(req),
2017 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2018 if (!NT_STATUS_IS_OK(status)) {
2019 return smbd_smb2_request_error(req, status);
2023 * Now that we know the request was correctly signed
2024 * we have to sign the response too.
2026 req->do_signing = true;
2028 if (!NT_STATUS_IS_OK(session_status)) {
2029 return smbd_smb2_request_error(req, session_status);
2031 } else if (opcode == SMB2_OP_CANCEL) {
2032 /* Cancel requests are allowed to skip the signing */
2033 } else if (signing_required) {
2035 * If signing is required we try to sign
2036 * a possible error response
2038 req->do_signing = true;
2039 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2042 if (flags & SMB2_HDR_FLAG_CHAINED) {
2043 req->compound_related = true;
2046 if (call->need_session) {
2047 if (!NT_STATUS_IS_OK(session_status)) {
2048 return smbd_smb2_request_error(req, session_status);
2052 if (call->need_tcon) {
2053 SMB_ASSERT(call->need_session);
2056 * This call needs to be run as user.
2058 * smbd_smb2_request_check_tcon()
2059 * calls change_to_user() on success.
2061 status = smbd_smb2_request_check_tcon(req);
2062 if (!NT_STATUS_IS_OK(status)) {
2063 return smbd_smb2_request_error(req, status);
2065 if (req->tcon->global->encryption_required) {
2066 encryption_required = true;
2068 if (encryption_required && !req->do_encryption) {
2069 return smbd_smb2_request_error(req,
2070 NT_STATUS_ACCESS_DENIED);
2074 if (call->fileid_ofs != 0) {
2075 size_t needed = call->fileid_ofs + 16;
2076 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2077 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2078 uint64_t file_id_persistent;
2079 uint64_t file_id_volatile;
2080 struct files_struct *fsp;
2082 SMB_ASSERT(call->need_tcon);
2084 if (needed > body_size) {
2085 return smbd_smb2_request_error(req,
2086 NT_STATUS_INVALID_PARAMETER);
2089 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2090 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2092 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2094 if (!call->allow_invalid_fileid) {
2095 return smbd_smb2_request_error(req,
2096 NT_STATUS_FILE_CLOSED);
2099 if (file_id_persistent != UINT64_MAX) {
2100 return smbd_smb2_request_error(req,
2101 NT_STATUS_FILE_CLOSED);
2103 if (file_id_volatile != UINT64_MAX) {
2104 return smbd_smb2_request_error(req,
2105 NT_STATUS_FILE_CLOSED);
2110 if (call->as_root) {
2111 SMB_ASSERT(call->fileid_ofs == 0);
2112 /* This call needs to be run as root */
2113 change_to_root_user();
2115 SMB_ASSERT(call->need_tcon);
2119 case SMB2_OP_NEGPROT:
2121 START_PROFILE(smb2_negprot);
2122 return_value = smbd_smb2_request_process_negprot(req);
2123 END_PROFILE(smb2_negprot);
2127 case SMB2_OP_SESSSETUP:
2129 START_PROFILE(smb2_sesssetup);
2130 return_value = smbd_smb2_request_process_sesssetup(req);
2131 END_PROFILE(smb2_sesssetup);
2135 case SMB2_OP_LOGOFF:
2137 START_PROFILE(smb2_logoff);
2138 return_value = smbd_smb2_request_process_logoff(req);
2139 END_PROFILE(smb2_logoff);
2145 START_PROFILE(smb2_tcon);
2146 return_value = smbd_smb2_request_process_tcon(req);
2147 END_PROFILE(smb2_tcon);
2153 START_PROFILE(smb2_tdis);
2154 return_value = smbd_smb2_request_process_tdis(req);
2155 END_PROFILE(smb2_tdis);
2159 case SMB2_OP_CREATE:
2161 START_PROFILE(smb2_create);
2162 return_value = smbd_smb2_request_process_create(req);
2163 END_PROFILE(smb2_create);
2169 START_PROFILE(smb2_close);
2170 return_value = smbd_smb2_request_process_close(req);
2171 END_PROFILE(smb2_close);
2177 START_PROFILE(smb2_flush);
2178 return_value = smbd_smb2_request_process_flush(req);
2179 END_PROFILE(smb2_flush);
2185 START_PROFILE(smb2_read);
2186 return_value = smbd_smb2_request_process_read(req);
2187 END_PROFILE(smb2_read);
2193 START_PROFILE(smb2_write);
2194 return_value = smbd_smb2_request_process_write(req);
2195 END_PROFILE(smb2_write);
2201 START_PROFILE(smb2_lock);
2202 return_value = smbd_smb2_request_process_lock(req);
2203 END_PROFILE(smb2_lock);
2209 START_PROFILE(smb2_ioctl);
2210 return_value = smbd_smb2_request_process_ioctl(req);
2211 END_PROFILE(smb2_ioctl);
2215 case SMB2_OP_CANCEL:
2217 START_PROFILE(smb2_cancel);
2218 return_value = smbd_smb2_request_process_cancel(req);
2219 END_PROFILE(smb2_cancel);
2223 case SMB2_OP_KEEPALIVE:
2225 START_PROFILE(smb2_keepalive);
2226 return_value = smbd_smb2_request_process_keepalive(req);
2227 END_PROFILE(smb2_keepalive);
2233 START_PROFILE(smb2_find);
2234 return_value = smbd_smb2_request_process_find(req);
2235 END_PROFILE(smb2_find);
2239 case SMB2_OP_NOTIFY:
2241 START_PROFILE(smb2_notify);
2242 return_value = smbd_smb2_request_process_notify(req);
2243 END_PROFILE(smb2_notify);
2247 case SMB2_OP_GETINFO:
2249 START_PROFILE(smb2_getinfo);
2250 return_value = smbd_smb2_request_process_getinfo(req);
2251 END_PROFILE(smb2_getinfo);
2255 case SMB2_OP_SETINFO:
2257 START_PROFILE(smb2_setinfo);
2258 return_value = smbd_smb2_request_process_setinfo(req);
2259 END_PROFILE(smb2_setinfo);
2265 START_PROFILE(smb2_break);
2266 return_value = smbd_smb2_request_process_break(req);
2267 END_PROFILE(smb2_break);
2272 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2275 return return_value;
2278 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2280 struct smbXsrv_connection *conn = req->sconn->conn;
2281 struct tevent_req *subreq;
2283 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2284 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2285 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2288 TALLOC_FREE(req->async_te);
2290 if (req->do_encryption &&
2291 (firsttf->iov_len == 0) &&
2292 (req->first_key.length == 0) &&
2293 (req->session != NULL) &&
2294 (req->session->global->encryption_key.length != 0))
2296 DATA_BLOB encryption_key = req->session->global->encryption_key;
2298 uint64_t session_id = req->session->global->session_wire_id;
2299 struct smbXsrv_session *x = req->session;
2300 uint64_t nonce_high;
2303 nonce_high = x->nonce_high;
2304 nonce_low = x->nonce_low;
2307 if (x->nonce_low == 0) {
2313 * We need to place the SMB2_TRANSFORM header before the
2318 * we need to remember the encryption key
2319 * and defer the signing/encryption until
2320 * we are sure that we do not change
2323 req->first_key = data_blob_dup_talloc(req, encryption_key);
2324 if (req->first_key.data == NULL) {
2325 return NT_STATUS_NO_MEMORY;
2328 tf = talloc_zero_array(req->out.vector, uint8_t,
2331 return NT_STATUS_NO_MEMORY;
2334 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2335 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2336 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2337 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2339 firsttf->iov_base = (void *)tf;
2340 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2343 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2344 (req->last_key.length > 0) &&
2345 (firsttf->iov_len == 0))
2347 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2348 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2352 * As we are sure the header of the last request in the
2353 * compound chain will not change, we can to sign here
2354 * with the last signing key we remembered.
2356 status = smb2_signing_sign_pdu(req->last_key,
2359 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2360 if (!NT_STATUS_IS_OK(status)) {
2364 data_blob_clear_free(&req->last_key);
2366 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2368 if (req->current_idx < req->out.vector_count) {
2370 * We must process the remaining compound
2371 * SMB2 requests before any new incoming SMB2
2372 * requests. This is because incoming SMB2
2373 * requests may include a cancel for a
2374 * compound request we haven't processed
2377 struct tevent_immediate *im = tevent_create_immediate(req);
2379 return NT_STATUS_NO_MEMORY;
2382 if (req->do_signing && firsttf->iov_len == 0) {
2383 struct smbXsrv_session *x = req->session;
2384 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2387 * we need to remember the signing key
2388 * and defer the signing until
2389 * we are sure that we do not change
2392 req->last_key = data_blob_dup_talloc(req, signing_key);
2393 if (req->last_key.data == NULL) {
2394 return NT_STATUS_NO_MEMORY;
2398 tevent_schedule_immediate(im,
2400 smbd_smb2_request_dispatch_immediate,
2402 return NT_STATUS_OK;
2405 if (req->compound_related) {
2406 req->compound_related = false;
2409 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2411 /* Set credit for these operations (zero credits if this
2412 is a final reply for an async operation). */
2413 smb2_calculate_credits(req, req);
2416 * now check if we need to sign the current response
2418 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2421 status = smb2_signing_encrypt_pdu(req->first_key,
2424 req->out.vector_count - first_idx);
2425 if (!NT_STATUS_IS_OK(status)) {
2428 } else if (req->do_signing) {
2430 struct smbXsrv_session *x = req->session;
2431 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2433 status = smb2_signing_sign_pdu(signing_key,
2436 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2437 if (!NT_STATUS_IS_OK(status)) {
2441 data_blob_clear_free(&req->first_key);
2443 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2444 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2445 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2446 /* Dynamic part is NULL. Chop it off,
2447 We're going to send it via sendfile. */
2448 req->out.vector_count -= 1;
2451 subreq = tstream_writev_queue_send(req,
2453 req->sconn->smb2.stream,
2454 req->sconn->smb2.send_queue,
2456 req->out.vector_count);
2457 if (subreq == NULL) {
2458 return NT_STATUS_NO_MEMORY;
2460 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
2462 * We're done with this request -
2463 * move it off the "being processed" queue.
2465 DLIST_REMOVE(req->sconn->smb2.requests, req);
2467 return NT_STATUS_OK;
2470 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2472 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2473 struct tevent_immediate *im,
2476 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2477 struct smbd_smb2_request);
2478 struct smbd_server_connection *sconn = req->sconn;
2483 if (DEBUGLEVEL >= 10) {
2484 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2485 req->current_idx, req->in.vector_count));
2486 print_req_vectors(req);
2489 status = smbd_smb2_request_dispatch(req);
2490 if (!NT_STATUS_IS_OK(status)) {
2491 smbd_server_connection_terminate(sconn, nt_errstr(status));
2495 status = smbd_smb2_request_next_incoming(sconn);
2496 if (!NT_STATUS_IS_OK(status)) {
2497 smbd_server_connection_terminate(sconn, nt_errstr(status));
2502 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
2504 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
2505 struct smbd_smb2_request);
2506 struct smbd_server_connection *sconn = req->sconn;
2511 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2512 TALLOC_FREE(subreq);
2515 status = map_nt_error_from_unix(sys_errno);
2516 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2517 nt_errstr(status)));
2518 smbd_server_connection_terminate(sconn, nt_errstr(status));
2522 status = smbd_smb2_request_next_incoming(sconn);
2523 if (!NT_STATUS_IS_OK(status)) {
2524 smbd_server_connection_terminate(sconn, nt_errstr(status));
2529 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2531 DATA_BLOB body, DATA_BLOB *dyn,
2532 const char *location)
2535 struct iovec *outbody_v;
2536 struct iovec *outdyn_v;
2537 uint32_t next_command_ofs;
2539 DEBUG(10,("smbd_smb2_request_done_ex: "
2540 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2541 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2543 (unsigned int)(dyn ? dyn->length : 0),
2546 if (body.length < 2) {
2547 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2550 if ((body.length % 2) != 0) {
2551 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2554 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2555 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2556 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2558 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2559 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2561 outbody_v->iov_base = (void *)body.data;
2562 outbody_v->iov_len = body.length;
2565 outdyn_v->iov_base = (void *)dyn->data;
2566 outdyn_v->iov_len = dyn->length;
2568 outdyn_v->iov_base = NULL;
2569 outdyn_v->iov_len = 0;
2572 /* see if we need to recalculate the offset to the next response */
2573 if (next_command_ofs > 0) {
2574 next_command_ofs = SMB2_HDR_BODY;
2575 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2576 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2579 if ((next_command_ofs % 8) != 0) {
2580 size_t pad_size = 8 - (next_command_ofs % 8);
2581 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2583 * if the dyn buffer is empty
2584 * we can use it to add padding
2588 pad = talloc_zero_array(req->out.vector,
2591 return smbd_smb2_request_error(req,
2592 NT_STATUS_NO_MEMORY);
2595 outdyn_v->iov_base = (void *)pad;
2596 outdyn_v->iov_len = pad_size;
2599 * For now we copy the dynamic buffer
2600 * and add the padding to the new buffer
2607 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2608 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2610 new_size = old_size + pad_size;
2611 new_dyn = talloc_zero_array(req->out.vector,
2613 if (new_dyn == NULL) {
2614 return smbd_smb2_request_error(req,
2615 NT_STATUS_NO_MEMORY);
2618 memcpy(new_dyn, old_dyn, old_size);
2619 memset(new_dyn + old_size, 0, pad_size);
2621 outdyn_v->iov_base = (void *)new_dyn;
2622 outdyn_v->iov_len = new_size;
2624 next_command_ofs += pad_size;
2627 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2629 return smbd_smb2_request_reply(req);
2632 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2635 const char *location)
2638 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2639 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2641 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2642 req->current_idx, nt_errstr(status), info ? " +info" : "",
2646 /* Recvfile error. Drain incoming socket. */
2647 size_t ret = drain_socket(req->sconn->sock, unread_bytes);
2648 if (ret != unread_bytes) {
2649 smbd_server_connection_terminate(req->sconn,
2650 "Failed to drain SMB2 socket\n");
2654 body.data = outhdr + SMB2_HDR_BODY;
2656 SSVAL(body.data, 0, 9);
2659 SIVAL(body.data, 0x04, info->length);
2661 /* Allocated size of req->out.vector[i].iov_base
2662 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2663 * 1 byte without having to do an alloc.
2665 info = talloc_zero_array(req->out.vector,
2669 return NT_STATUS_NO_MEMORY;
2671 info->data = ((uint8_t *)outhdr) +
2672 OUTVEC_ALLOC_SIZE - 1;
2674 SCVAL(info->data, 0, 0);
2678 * Note: Even if there is an error, continue to process the request.
2682 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2686 struct smbd_smb2_send_oplock_break_state {
2687 struct smbd_server_connection *sconn;
2688 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x18];
2689 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2692 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2694 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2695 struct smbXsrv_session *session,
2696 struct smbXsrv_tcon *tcon,
2697 struct smbXsrv_open *op,
2698 uint8_t oplock_level)
2700 struct smbd_smb2_send_oplock_break_state *state;
2701 struct smbXsrv_connection *conn = sconn->conn;
2702 struct tevent_req *subreq;
2710 bool do_encryption = session->global->encryption_required;
2711 uint64_t nonce_high = 0;
2712 uint64_t nonce_low = 0;
2714 if (tcon->global->encryption_required) {
2715 do_encryption = true;
2718 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2719 if (state == NULL) {
2720 return NT_STATUS_NO_MEMORY;
2722 state->sconn = sconn;
2724 tf = state->buf + NBT_HDR_SIZE;
2725 tf_len = SMB2_TF_HDR_SIZE;
2727 body = hdr + SMB2_HDR_BODY;
2729 dyn = body + body_len;
2732 if (do_encryption) {
2733 nonce_high = session->nonce_high;
2734 nonce_low = session->nonce_low;
2736 session->nonce_low += 1;
2737 if (session->nonce_low == 0) {
2738 session->nonce_low += 1;
2739 session->nonce_high += 1;
2743 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2744 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2745 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2746 SBVAL(tf, SMB2_TF_SESSION_ID, session->global->session_wire_id);
2748 SIVAL(hdr, 0, SMB2_MAGIC);
2749 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2750 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2751 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2752 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2753 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2754 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2755 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2756 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2757 SIVAL(hdr, SMB2_HDR_PID, 0);
2758 SIVAL(hdr, SMB2_HDR_TID, 0);
2759 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2760 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2762 SSVAL(body, 0x00, body_len);
2764 SCVAL(body, 0x02, oplock_level);
2765 SCVAL(body, 0x03, 0); /* reserved */
2766 SIVAL(body, 0x04, 0); /* reserved */
2767 SBVAL(body, 0x08, op->global->open_persistent_id);
2768 SBVAL(body, 0x10, op->global->open_volatile_id);
2770 state->vector[0].iov_base = (void *)state->buf;
2771 state->vector[0].iov_len = NBT_HDR_SIZE;
2773 if (do_encryption) {
2774 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
2775 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
2777 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
2778 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
2781 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
2782 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
2784 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
2785 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = body_len;
2787 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
2788 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_len;
2790 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2792 if (do_encryption) {
2794 DATA_BLOB encryption_key = session->global->encryption_key;
2796 status = smb2_signing_encrypt_pdu(encryption_key,
2798 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2799 SMBD_SMB2_NUM_IOV_PER_REQ);
2800 if (!NT_STATUS_IS_OK(status)) {
2805 subreq = tstream_writev_queue_send(state,
2808 sconn->smb2.send_queue,
2810 ARRAY_SIZE(state->vector));
2811 if (subreq == NULL) {
2812 return NT_STATUS_NO_MEMORY;
2814 tevent_req_set_callback(subreq,
2815 smbd_smb2_oplock_break_writev_done,
2818 return NT_STATUS_OK;
2821 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2823 struct smbd_smb2_send_oplock_break_state *state =
2824 tevent_req_callback_data(subreq,
2825 struct smbd_smb2_send_oplock_break_state);
2826 struct smbd_server_connection *sconn = state->sconn;
2830 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2831 TALLOC_FREE(subreq);
2833 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2834 smbd_server_connection_terminate(sconn, nt_errstr(status));
2841 struct smbd_smb2_request_read_state {
2842 struct tevent_context *ev;
2843 struct smbd_server_connection *sconn;
2844 struct smbd_smb2_request *smb2_req;
2846 uint8_t nbt[NBT_HDR_SIZE];
2849 bool doing_receivefile;
2850 size_t min_recv_size;
2855 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2857 TALLOC_CTX *mem_ctx,
2858 struct iovec **_vector,
2860 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2862 static size_t get_min_receive_file_size(struct smbd_smb2_request *smb2_req)
2864 if (smb2_req->do_signing) {
2867 if (smb2_req->do_encryption) {
2870 return (size_t)lp_min_receive_file_size();
2873 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2874 struct tevent_context *ev,
2875 struct smbd_server_connection *sconn)
2877 struct tevent_req *req;
2878 struct smbd_smb2_request_read_state *state;
2879 struct tevent_req *subreq;
2881 req = tevent_req_create(mem_ctx, &state,
2882 struct smbd_smb2_request_read_state);
2887 state->sconn = sconn;
2889 state->smb2_req = smbd_smb2_request_allocate(state);
2890 if (tevent_req_nomem(state->smb2_req, req)) {
2891 return tevent_req_post(req, ev);
2893 state->smb2_req->sconn = sconn;
2894 state->min_recv_size = get_min_receive_file_size(state->smb2_req);
2896 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
2898 state->sconn->smb2.stream,
2899 state->sconn->smb2.recv_queue,
2900 smbd_smb2_request_next_vector,
2902 if (tevent_req_nomem(subreq, req)) {
2903 return tevent_req_post(req, ev);
2905 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2910 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2914 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
2915 /* Transform header. Cannot recvfile. */
2918 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
2919 /* Not SMB2. Normal error path will cope. */
2922 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
2923 /* Not SMB2. Normal error path will cope. */
2926 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
2927 /* Needs to be a WRITE. */
2930 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
2931 /* Chained. Cannot recvfile. */
2934 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
2935 if (flags & SMB2_HDR_FLAG_CHAINED) {
2936 /* Chained. Cannot recvfile. */
2939 if (flags & SMB2_HDR_FLAG_SIGNED) {
2940 /* Signed. Cannot recvfile. */
2944 DEBUG(10,("Doing recvfile write len = %u\n",
2945 (unsigned int)(state->pktlen -
2946 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN)));
2951 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2953 TALLOC_CTX *mem_ctx,
2954 struct iovec **_vector,
2957 struct smbd_smb2_request_read_state *state =
2958 talloc_get_type_abort(private_data,
2959 struct smbd_smb2_request_read_state);
2960 struct iovec *vector = NULL;
2961 size_t min_recvfile_size = UINT32_MAX;
2963 if (state->pktlen > 0) {
2964 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
2966 * Not a possible receivefile write.
2967 * Read the rest of the data.
2969 state->doing_receivefile = false;
2970 vector = talloc_array(mem_ctx, struct iovec, 1);
2971 if (vector == NULL) {
2974 vector[0].iov_base = (void *)(state->pktbuf +
2975 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN);
2976 vector[0].iov_len = (state->pktlen -
2977 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN);
2982 * Either this is a receivefile write so we've
2983 * done a short read, or if not we have all the data.
2984 * Either way, we're done and
2985 * smbd_smb2_request_read_done() will handle
2986 * and short read case by looking at the
2987 * state->doing_receivefile value.
2995 if (!state->hdr.done) {
2997 * first we need to get the NBT header
2999 vector = talloc_array(mem_ctx, struct iovec, 1);
3000 if (vector == NULL) {
3004 vector[0].iov_base = (void *)state->hdr.nbt;
3005 vector[0].iov_len = NBT_HDR_SIZE;
3010 state->hdr.done = true;
3015 * Now we analyze the NBT header
3017 state->pktlen = smb2_len(state->hdr.nbt);
3019 if (state->pktlen == 0) {
3020 /* if there're no remaining bytes, we're done */
3026 state->pktbuf = talloc_array(state->smb2_req, uint8_t, state->pktlen);
3027 if (state->pktbuf == NULL) {
3031 vector = talloc_array(mem_ctx, struct iovec, 1);
3032 if (vector == NULL) {
3036 vector[0].iov_base = (void *)state->pktbuf;
3038 if (state->min_recv_size != 0) {
3039 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3040 min_recvfile_size += state->min_recv_size;
3043 if (state->pktlen > min_recvfile_size) {
3045 * Might be a receivefile write. Read the SMB2 HEADER +
3046 * SMB2_WRITE header first. Set 'doing_receivefile'
3047 * as we're *attempting* receivefile write. If this
3048 * turns out not to be a SMB2_WRITE request or otherwise
3049 * not suitable then we'll just read the rest of the data
3050 * the next time this function is called.
3052 vector[0].iov_len = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3053 state->doing_receivefile = true;
3055 vector[0].iov_len = state->pktlen;
3063 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
3065 struct tevent_req *req =
3066 tevent_req_callback_data(subreq,
3068 struct smbd_smb2_request_read_state *state =
3069 tevent_req_data(req,
3070 struct smbd_smb2_request_read_state);
3076 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
3077 TALLOC_FREE(subreq);
3079 status = map_nt_error_from_unix(sys_errno);
3080 tevent_req_nterror(req, status);
3084 if (state->hdr.nbt[0] != 0x00) {
3085 DEBUG(1,("smbd_smb2_request_read_done: ignore NBT[0x%02X] msg\n",
3086 state->hdr.nbt[0]));
3088 ZERO_STRUCT(state->hdr);
3089 TALLOC_FREE(state->pktbuf);
3092 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
3094 state->sconn->smb2.stream,
3095 state->sconn->smb2.recv_queue,
3096 smbd_smb2_request_next_vector,
3098 if (tevent_req_nomem(subreq, req)) {
3101 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
3105 state->smb2_req->request_time = timeval_current();
3106 now = timeval_to_nttime(&state->smb2_req->request_time);
3108 status = smbd_smb2_inbuf_parse_compound(state->smb2_req->sconn->conn,
3113 &state->smb2_req->in.vector,
3114 &state->smb2_req->in.vector_count);
3115 if (tevent_req_nterror(req, status)) {
3119 if (state->doing_receivefile) {
3120 state->smb2_req->smb1req = talloc_zero(state->smb2_req,
3121 struct smb_request);
3122 if (tevent_req_nomem(state->smb2_req->smb1req, req)) {
3125 state->smb2_req->smb1req->unread_bytes =
3126 state->pktlen - SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3129 state->smb2_req->current_idx = 1;
3131 tevent_req_done(req);
3134 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
3135 TALLOC_CTX *mem_ctx,
3136 struct smbd_smb2_request **_smb2_req)
3138 struct smbd_smb2_request_read_state *state =
3139 tevent_req_data(req,
3140 struct smbd_smb2_request_read_state);
3143 if (tevent_req_is_nterror(req, &status)) {
3144 tevent_req_received(req);
3148 *_smb2_req = talloc_move(mem_ctx, &state->smb2_req);
3149 tevent_req_received(req);
3150 return NT_STATUS_OK;
3153 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
3155 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
3157 size_t max_send_queue_len;
3158 size_t cur_send_queue_len;
3159 struct tevent_req *subreq;
3161 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
3163 * if there is already a smbd_smb2_request_read
3164 * pending, we are done.
3166 return NT_STATUS_OK;
3169 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
3170 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
3172 if (cur_send_queue_len > max_send_queue_len) {
3174 * if we have a lot of requests to send,
3175 * we wait until they are on the wire until we
3176 * ask for the next request.
3178 return NT_STATUS_OK;
3181 /* ask for the next request */
3182 subreq = smbd_smb2_request_read_send(sconn, sconn->ev_ctx, sconn);
3183 if (subreq == NULL) {
3184 return NT_STATUS_NO_MEMORY;
3186 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
3188 return NT_STATUS_OK;
3191 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
3192 uint8_t *inbuf, size_t size)
3195 struct smbd_smb2_request *req = NULL;
3197 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3198 (unsigned int)size));
3200 status = smbd_initialize_smb2(sconn);
3201 if (!NT_STATUS_IS_OK(status)) {
3202 smbd_server_connection_terminate(sconn, nt_errstr(status));
3206 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
3207 if (!NT_STATUS_IS_OK(status)) {
3208 smbd_server_connection_terminate(sconn, nt_errstr(status));
3212 status = smbd_smb2_request_validate(req);
3213 if (!NT_STATUS_IS_OK(status)) {
3214 smbd_server_connection_terminate(sconn, nt_errstr(status));
3218 status = smbd_smb2_request_setup_out(req);
3219 if (!NT_STATUS_IS_OK(status)) {
3220 smbd_server_connection_terminate(sconn, nt_errstr(status));
3224 status = smbd_smb2_request_dispatch(req);
3225 if (!NT_STATUS_IS_OK(status)) {
3226 smbd_server_connection_terminate(sconn, nt_errstr(status));
3230 status = smbd_smb2_request_next_incoming(sconn);
3231 if (!NT_STATUS_IS_OK(status)) {
3232 smbd_server_connection_terminate(sconn, nt_errstr(status));
3236 sconn->num_requests++;
3239 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
3241 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
3242 struct smbd_server_connection);
3244 struct smbd_smb2_request *req = NULL;
3246 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
3247 TALLOC_FREE(subreq);
3248 if (!NT_STATUS_IS_OK(status)) {
3249 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
3250 nt_errstr(status)));
3251 smbd_server_connection_terminate(sconn, nt_errstr(status));
3255 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
3256 req->current_idx, req->in.vector_count));
3258 status = smbd_smb2_request_validate(req);
3259 if (!NT_STATUS_IS_OK(status)) {
3260 smbd_server_connection_terminate(sconn, nt_errstr(status));
3264 status = smbd_smb2_request_setup_out(req);
3265 if (!NT_STATUS_IS_OK(status)) {
3266 smbd_server_connection_terminate(sconn, nt_errstr(status));
3270 status = smbd_smb2_request_dispatch(req);
3271 if (!NT_STATUS_IS_OK(status)) {
3272 smbd_server_connection_terminate(sconn, nt_errstr(status));
3276 status = smbd_smb2_request_next_incoming(sconn);
3277 if (!NT_STATUS_IS_OK(status)) {
3278 smbd_server_connection_terminate(sconn, nt_errstr(status));
3282 sconn->num_requests++;
3284 /* The timeout_processing function isn't run nearly
3285 often enough to implement 'max log size' without
3286 overrunning the size of the file by many megabytes.
3287 This is especially true if we are running at debug
3288 level 10. Checking every 50 SMB2s is a nice
3289 tradeoff of performance vs log file size overrun. */
3291 if ((sconn->num_requests % 50) == 0 &&
3292 need_to_check_log_size()) {
3293 change_to_root_user();