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 static void smbd_smb2_connection_handler(struct tevent_context *ev,
34 struct tevent_fd *fde,
37 static NTSTATUS smbd_smb2_io_handler(struct smbd_server_connection *sconn,
40 #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9)
42 static const struct smbd_smb2_dispatch_table {
49 bool allow_invalid_fileid;
50 } smbd_smb2_table[] = {
51 #define _OP(o) .opcode = o, .name = #o
56 _OP(SMB2_OP_SESSSETUP),
66 * This call needs to be run as root.
68 * smbd_smb2_request_process_tcon()
69 * calls make_connection_snum(), which will call
70 * change_to_user(), when needed.
104 .need_session = true,
109 .need_session = true,
112 .allow_invalid_fileid = true,
117 _OP(SMB2_OP_KEEPALIVE),
121 .need_session = true,
126 .need_session = true,
130 _OP(SMB2_OP_GETINFO),
131 .need_session = true,
135 _OP(SMB2_OP_SETINFO),
136 .need_session = true,
141 .need_session = true,
146 * as LEASE breaks does not
152 const char *smb2_opcode_name(uint16_t opcode)
154 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
155 return "Bad SMB2 opcode";
157 return smbd_smb2_table[opcode].name;
160 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
162 const struct smbd_smb2_dispatch_table *ret = NULL;
164 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
168 ret = &smbd_smb2_table[opcode];
170 SMB_ASSERT(ret->opcode == opcode);
175 static void print_req_vectors(const struct smbd_smb2_request *req)
179 for (i = 0; i < req->in.vector_count; i++) {
180 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
182 (unsigned int)req->in.vector[i].iov_len);
184 for (i = 0; i < req->out.vector_count; i++) {
185 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
187 (unsigned int)req->out.vector[i].iov_len);
191 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
193 if (size < (4 + SMB2_HDR_BODY)) {
197 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
204 static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
206 TALLOC_FREE(sconn->smb1.fde);
208 sconn->smb2.send_queue = NULL;
210 sconn->smb2.seqnum_low = 0;
211 sconn->smb2.seqnum_range = 1;
212 sconn->smb2.credits_granted = 1;
213 sconn->smb2.max_credits = lp_smb2_max_credits();
214 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
215 sconn->smb2.max_credits);
216 if (sconn->smb2.credits_bitmap == NULL) {
217 return NT_STATUS_NO_MEMORY;
220 sconn->smb2.fde = tevent_add_fd(sconn->ev_ctx,
224 smbd_smb2_connection_handler,
226 if (sconn->smb2.fde == NULL) {
227 return NT_STATUS_NO_MEMORY;
230 /* Ensure child is set to non-blocking mode */
231 set_blocking(sconn->sock, false);
235 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
236 #define _smb2_setlen(_buf,len) do { \
237 uint8_t *buf = (uint8_t *)_buf; \
239 buf[1] = ((len)&0xFF0000)>>16; \
240 buf[2] = ((len)&0xFF00)>>8; \
241 buf[3] = (len)&0xFF; \
244 static void smb2_setup_nbt_length(struct iovec *vector, int count)
249 for (i=1; i < count; i++) {
250 len += vector[i].iov_len;
253 _smb2_setlen(vector[0].iov_base, len);
256 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
258 data_blob_clear_free(&req->first_key);
259 data_blob_clear_free(&req->last_key);
263 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
265 TALLOC_CTX *mem_pool;
266 struct smbd_smb2_request *req;
269 /* Enable this to find subtle valgrind errors. */
270 mem_pool = talloc_init("smbd_smb2_request_allocate");
272 mem_pool = talloc_tos();
274 if (mem_pool == NULL) {
278 req = talloc_zero(mem_pool, struct smbd_smb2_request);
280 talloc_free(mem_pool);
283 talloc_reparent(mem_pool, mem_ctx, req);
285 TALLOC_FREE(mem_pool);
288 req->last_session_id = UINT64_MAX;
289 req->last_tid = UINT32_MAX;
291 talloc_set_destructor(req, smbd_smb2_request_destructor);
296 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn,
307 uint8_t *first_hdr = buf;
308 size_t verified_buflen = 0;
313 * Note: index '0' is reserved for the transport protocol
315 iov = talloc_zero_array(mem_ctx, struct iovec, num_iov);
317 return NT_STATUS_NO_MEMORY;
320 while (taken < buflen) {
321 size_t len = buflen - taken;
322 uint8_t *hdr = first_hdr + taken;
325 size_t next_command_ofs;
327 uint8_t *body = NULL;
330 struct iovec *iov_tmp;
332 if (verified_buflen > taken) {
333 len = verified_buflen - taken;
340 DEBUG(10, ("%d bytes left, expected at least %d\n",
344 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
345 struct smbXsrv_session *s = NULL;
347 struct iovec tf_iov[2];
351 if (conn->protocol < PROTOCOL_SMB2_24) {
352 DEBUG(10, ("Got SMB2_TRANSFORM header, "
353 "but dialect[0x%04X] is used\n",
354 conn->smb2.server.dialect));
358 if (!(conn->smb2.server.capabilities & SMB2_CAP_ENCRYPTION)) {
359 DEBUG(10, ("Got SMB2_TRANSFORM header, "
360 "but not negotiated "
361 "client[0x%08X] server[0x%08X]\n",
362 conn->smb2.client.capabilities,
363 conn->smb2.server.capabilities));
367 if (len < SMB2_TF_HDR_SIZE) {
368 DEBUG(1, ("%d bytes left, expected at least %d\n",
369 (int)len, SMB2_TF_HDR_SIZE));
373 tf_len = SMB2_TF_HDR_SIZE;
376 hdr = first_hdr + taken;
377 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
378 uid = BVAL(tf, SMB2_TF_SESSION_ID);
380 if (len < SMB2_TF_HDR_SIZE + enc_len) {
381 DEBUG(1, ("%d bytes left, expected at least %d\n",
383 (int)(SMB2_TF_HDR_SIZE + enc_len)));
387 status = smb2srv_session_lookup(conn, uid, now, &s);
389 DEBUG(1, ("invalid session[%llu] in "
390 "SMB2_TRANSFORM header\n",
391 (unsigned long long)uid));
393 return NT_STATUS_USER_SESSION_DELETED;
396 tf_iov[0].iov_base = (void *)tf;
397 tf_iov[0].iov_len = tf_len;
398 tf_iov[1].iov_base = (void *)hdr;
399 tf_iov[1].iov_len = enc_len;
401 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
404 if (!NT_STATUS_IS_OK(status)) {
409 verified_buflen = taken + enc_len;
414 * We need the header plus the body length field
417 if (len < SMB2_HDR_BODY + 2) {
418 DEBUG(10, ("%d bytes left, expected at least %d\n",
419 (int)len, SMB2_HDR_BODY));
422 if (IVAL(hdr, 0) != SMB2_MAGIC) {
423 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
427 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
428 DEBUG(10, ("Got HDR len %d, expected %d\n",
429 SVAL(hdr, 4), SMB2_HDR_BODY));
434 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
435 body_size = SVAL(hdr, SMB2_HDR_BODY);
437 if (next_command_ofs != 0) {
438 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
441 if (next_command_ofs > full_size) {
444 full_size = next_command_ofs;
451 if (body_size > (full_size - SMB2_HDR_BODY)) {
453 * let the caller handle the error
455 body_size = full_size - SMB2_HDR_BODY;
457 body = hdr + SMB2_HDR_BODY;
458 dyn = body + body_size;
459 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
461 iov_tmp = talloc_realloc(mem_ctx, iov, struct iovec,
462 num_iov + SMBD_SMB2_NUM_IOV_PER_REQ);
463 if (iov_tmp == NULL) {
465 return NT_STATUS_NO_MEMORY;
469 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
471 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
472 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
473 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
474 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
475 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
476 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
477 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
478 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
489 return NT_STATUS_INVALID_PARAMETER;
492 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
493 uint8_t *inbuf, size_t size,
494 struct smbd_smb2_request **_req)
496 struct smbd_smb2_request *req;
497 uint32_t protocol_version;
498 const uint8_t *inhdr = NULL;
500 uint32_t next_command_ofs;
504 if (size < (4 + SMB2_HDR_BODY + 2)) {
505 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
506 return NT_STATUS_INVALID_PARAMETER;
511 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
512 if (protocol_version != SMB2_MAGIC) {
513 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
515 return NT_STATUS_INVALID_PARAMETER;
518 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
519 if (cmd != SMB2_OP_NEGPROT) {
520 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
522 return NT_STATUS_INVALID_PARAMETER;
525 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
526 if (next_command_ofs != 0) {
527 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
529 return NT_STATUS_INVALID_PARAMETER;
532 req = smbd_smb2_request_allocate(sconn);
534 return NT_STATUS_NO_MEMORY;
538 talloc_steal(req, inbuf);
540 req->request_time = timeval_current();
541 now = timeval_to_nttime(&req->request_time);
543 status = smbd_smb2_inbuf_parse_compound(sconn->conn,
545 inbuf + NBT_HDR_SIZE,
547 req, &req->in.vector,
548 &req->in.vector_count);
549 if (!NT_STATUS_IS_OK(status)) {
554 req->current_idx = 1;
560 static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
561 uint64_t message_id, uint64_t seq_id)
563 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
566 if (seq_id < sconn->smb2.seqnum_low) {
567 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
568 "%llu (sequence id %llu) "
569 "(granted = %u, low = %llu, range = %u)\n",
570 (unsigned long long)message_id,
571 (unsigned long long)seq_id,
572 (unsigned int)sconn->smb2.credits_granted,
573 (unsigned long long)sconn->smb2.seqnum_low,
574 (unsigned int)sconn->smb2.seqnum_range));
578 if (seq_id >= sconn->smb2.seqnum_low + sconn->smb2.seqnum_range) {
579 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
580 "%llu (sequence id %llu) "
581 "(granted = %u, low = %llu, range = %u)\n",
582 (unsigned long long)message_id,
583 (unsigned long long)seq_id,
584 (unsigned int)sconn->smb2.credits_granted,
585 (unsigned long long)sconn->smb2.seqnum_low,
586 (unsigned int)sconn->smb2.seqnum_range));
590 offset = seq_id % sconn->smb2.max_credits;
592 if (bitmap_query(credits_bm, offset)) {
593 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
594 "%llu (sequence id %llu) "
595 "(granted = %u, low = %llu, range = %u) "
597 (unsigned long long)message_id,
598 (unsigned long long)seq_id,
599 (unsigned int)sconn->smb2.credits_granted,
600 (unsigned long long)sconn->smb2.seqnum_low,
601 (unsigned int)sconn->smb2.seqnum_range,
606 /* Mark the message_ids as seen in the bitmap. */
607 bitmap_set(credits_bm, offset);
609 if (seq_id != sconn->smb2.seqnum_low) {
614 * Move the window forward by all the message_id's
617 while (bitmap_query(credits_bm, offset)) {
618 DEBUG(10,("smb2_validate_sequence_number: clearing "
619 "id %llu (position %u) from bitmap\n",
620 (unsigned long long)(sconn->smb2.seqnum_low),
622 bitmap_clear(credits_bm, offset);
624 sconn->smb2.seqnum_low += 1;
625 sconn->smb2.seqnum_range -= 1;
626 offset = sconn->smb2.seqnum_low % sconn->smb2.max_credits;
632 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
633 const uint8_t *inhdr)
635 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
636 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
637 uint16_t credit_charge = 1;
640 if (opcode == SMB2_OP_CANCEL) {
641 /* SMB2_CANCEL requests by definition resend messageids. */
645 if (sconn->smb2.supports_multicredit) {
646 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
647 credit_charge = MAX(credit_charge, 1);
650 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
651 "credits_granted %llu, "
652 "seqnum low/range: %llu/%llu\n",
653 (unsigned long long) message_id,
654 (unsigned long long) credit_charge,
655 (unsigned long long) sconn->smb2.credits_granted,
656 (unsigned long long) sconn->smb2.seqnum_low,
657 (unsigned long long) sconn->smb2.seqnum_range));
659 if (sconn->smb2.credits_granted < credit_charge) {
660 DEBUG(0, ("smb2_validate_message_id: client used more "
661 "credits than granted, mid %llu, charge %llu, "
662 "credits_granted %llu, "
663 "seqnum low/range: %llu/%llu\n",
664 (unsigned long long) message_id,
665 (unsigned long long) credit_charge,
666 (unsigned long long) sconn->smb2.credits_granted,
667 (unsigned long long) sconn->smb2.seqnum_low,
668 (unsigned long long) sconn->smb2.seqnum_range));
673 * now check the message ids
675 * for multi-credit requests we need to check all current mid plus
676 * the implicit mids caused by the credit charge
677 * e.g. current mid = 15, charge 5 => mark 15-19 as used
680 for (i = 0; i <= (credit_charge-1); i++) {
681 uint64_t id = message_id + i;
684 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
685 (unsigned long long)message_id,
687 (unsigned long long)id));
689 ok = smb2_validate_sequence_number(sconn, message_id, id);
695 /* substract used credits */
696 sconn->smb2.credits_granted -= credit_charge;
701 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
706 count = req->in.vector_count;
708 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
709 /* It's not a SMB2 request */
710 return NT_STATUS_INVALID_PARAMETER;
713 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
714 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
715 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
716 const uint8_t *inhdr = NULL;
718 if (hdr->iov_len != SMB2_HDR_BODY) {
719 return NT_STATUS_INVALID_PARAMETER;
722 if (body->iov_len < 2) {
723 return NT_STATUS_INVALID_PARAMETER;
726 inhdr = (const uint8_t *)hdr->iov_base;
728 /* Check the SMB2 header */
729 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
730 return NT_STATUS_INVALID_PARAMETER;
733 if (!smb2_validate_message_id(req->sconn, inhdr)) {
734 return NT_STATUS_INVALID_PARAMETER;
741 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
742 const struct iovec *in_vector,
743 struct iovec *out_vector)
745 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
746 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
747 uint16_t credit_charge = 1;
748 uint16_t credits_requested;
752 uint16_t credits_granted = 0;
753 uint64_t credits_possible;
754 uint16_t current_max_credits;
757 * first we grant only 1/16th of the max range.
759 * Windows also starts with the 1/16th and then grants
760 * more later. I was only able to trigger higher
761 * values, when using a verify high credit charge.
763 * TODO: scale up depending one load, free memory
765 * Maybe also on the relationship between number
766 * of requests and the used sequence number.
767 * Which means we would grant more credits
768 * for client which use multi credit requests.
770 current_max_credits = sconn->smb2.max_credits / 16;
771 current_max_credits = MAX(current_max_credits, 1);
773 if (sconn->smb2.supports_multicredit) {
774 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
775 credit_charge = MAX(credit_charge, 1);
778 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
779 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
780 credits_requested = MAX(credits_requested, 1);
781 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
782 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
784 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
786 if (sconn->smb2.max_credits < credit_charge) {
787 smbd_server_connection_terminate(sconn,
788 "client error: credit charge > max credits\n");
792 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
794 * In case we already send an async interim
795 * response, we should not grant
796 * credits on the final response.
800 uint16_t additional_max = 0;
801 uint16_t additional_credits = credits_requested - 1;
804 case SMB2_OP_NEGPROT:
806 case SMB2_OP_SESSSETUP:
808 * Windows 2012 RC1 starts to grant
810 * with a successful session setup
812 if (NT_STATUS_IS_OK(out_status)) {
818 * We match windows and only grant additional credits
825 additional_credits = MIN(additional_credits, additional_max);
827 credits_granted = credit_charge + additional_credits;
831 * sequence numbers should not wrap
833 * 1. calculate the possible credits until
834 * the sequence numbers start to wrap on 64-bit.
836 * 2. UINT64_MAX is used for Break Notifications.
838 * 2. truncate the possible credits to the maximum
839 * credits we want to grant to the client in total.
841 * 3. remove the range we'll already granted to the client
842 * this makes sure the client consumes the lowest sequence
843 * number, before we can grant additional credits.
845 credits_possible = UINT64_MAX - sconn->smb2.seqnum_low;
846 if (credits_possible > 0) {
847 /* remove UINT64_MAX */
848 credits_possible -= 1;
850 credits_possible = MIN(credits_possible, current_max_credits);
851 credits_possible -= sconn->smb2.seqnum_range;
853 credits_granted = MIN(credits_granted, credits_possible);
855 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
856 sconn->smb2.credits_granted += credits_granted;
857 sconn->smb2.seqnum_range += credits_granted;
859 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
860 "granted %u, current possible/max %u/%u, "
861 "total granted/max/low/range %u/%u/%llu/%u\n",
862 (unsigned int)credits_requested,
863 (unsigned int)credit_charge,
864 (unsigned int)credits_granted,
865 (unsigned int)credits_possible,
866 (unsigned int)current_max_credits,
867 (unsigned int)sconn->smb2.credits_granted,
868 (unsigned int)sconn->smb2.max_credits,
869 (unsigned long long)sconn->smb2.seqnum_low,
870 (unsigned int)sconn->smb2.seqnum_range));
873 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
874 struct smbd_smb2_request *outreq)
877 uint16_t total_credits = 0;
879 count = outreq->out.vector_count;
881 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
882 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
883 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
884 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
886 smb2_set_operation_credit(outreq->sconn, inhdr_v, outhdr_v);
888 /* To match Windows, count up what we
890 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
891 /* Set to zero in all but the last reply. */
892 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
893 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
895 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
900 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
902 struct iovec *vector;
906 count = req->in.vector_count;
907 vector = talloc_zero_array(req, struct iovec, count);
908 if (vector == NULL) {
909 return NT_STATUS_NO_MEMORY;
912 vector[0].iov_base = req->out.nbt_hdr;
913 vector[0].iov_len = 4;
914 SIVAL(req->out.nbt_hdr, 0, 0);
916 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
917 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
918 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
919 uint8_t *outhdr = NULL;
920 uint8_t *outbody = NULL;
921 uint32_t next_command_ofs = 0;
922 struct iovec *current = &vector[idx];
924 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
925 /* we have a next command -
926 * setup for the error case. */
927 next_command_ofs = SMB2_HDR_BODY + 9;
930 outhdr = talloc_zero_array(vector, uint8_t,
932 if (outhdr == NULL) {
933 return NT_STATUS_NO_MEMORY;
936 outbody = outhdr + SMB2_HDR_BODY;
939 * SMBD_SMB2_TF_IOV_OFS might be used later
941 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
942 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
944 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
945 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
947 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
948 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
950 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
951 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
953 /* setup the SMB2 header */
954 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
955 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
956 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
957 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
958 SIVAL(outhdr, SMB2_HDR_STATUS,
959 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
960 SSVAL(outhdr, SMB2_HDR_OPCODE,
961 SVAL(inhdr, SMB2_HDR_OPCODE));
962 SIVAL(outhdr, SMB2_HDR_FLAGS,
963 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
964 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
965 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
966 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
967 SIVAL(outhdr, SMB2_HDR_PID,
968 IVAL(inhdr, SMB2_HDR_PID));
969 SIVAL(outhdr, SMB2_HDR_TID,
970 IVAL(inhdr, SMB2_HDR_TID));
971 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
972 BVAL(inhdr, SMB2_HDR_SESSION_ID));
973 memcpy(outhdr + SMB2_HDR_SIGNATURE,
974 inhdr + SMB2_HDR_SIGNATURE, 16);
976 /* setup error body header */
977 SSVAL(outbody, 0x00, 0x08 + 1);
978 SSVAL(outbody, 0x02, 0);
979 SIVAL(outbody, 0x04, 0);
982 req->out.vector = vector;
983 req->out.vector_count = count;
985 /* setup the length of the NBT packet */
986 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
988 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
993 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
995 const char *location)
997 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
999 exit_server_cleanly(reason);
1002 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1003 struct iovec *outvec,
1004 const struct iovec *srcvec)
1006 const uint8_t *srctf;
1008 const uint8_t *srchdr;
1010 const uint8_t *srcbody;
1012 const uint8_t *expected_srcbody;
1013 const uint8_t *srcdyn;
1015 const uint8_t *expected_srcdyn;
1021 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1022 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1023 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1024 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1025 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1026 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1027 expected_srcbody = srchdr + SMB2_HDR_BODY;
1028 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1029 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1030 expected_srcdyn = srcbody + 8;
1032 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1036 if (srchdr_len != SMB2_HDR_BODY) {
1040 if (srctf_len == SMB2_TF_HDR_SIZE) {
1041 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1042 if (dsttf == NULL) {
1048 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1049 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1051 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1052 * be allocated with size OUTVEC_ALLOC_SIZE. */
1054 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1055 if (dsthdr == NULL) {
1058 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1059 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1062 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1063 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1064 * then duplicate this. Else use talloc_memdup().
1067 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1068 dstbody = dsthdr + SMB2_HDR_BODY;
1070 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1071 if (dstbody == NULL) {
1075 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1076 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1079 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1081 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1082 * then duplicate this. Else use talloc_memdup().
1085 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1086 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1087 } else if (srcdyn == NULL) {
1090 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1091 if (dstdyn == NULL) {
1095 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1096 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1101 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1103 struct smbd_smb2_request *newreq = NULL;
1104 struct iovec *outvec = NULL;
1105 int count = req->out.vector_count;
1108 newreq = smbd_smb2_request_allocate(req->sconn);
1113 newreq->sconn = req->sconn;
1114 newreq->session = req->session;
1115 newreq->do_encryption = req->do_encryption;
1116 newreq->do_signing = req->do_signing;
1117 newreq->current_idx = req->current_idx;
1119 outvec = talloc_zero_array(newreq, struct iovec, count);
1121 TALLOC_FREE(newreq);
1124 newreq->out.vector = outvec;
1125 newreq->out.vector_count = count;
1127 /* Setup the outvec's identically to req. */
1128 outvec[0].iov_base = newreq->out.nbt_hdr;
1129 outvec[0].iov_len = 4;
1130 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1132 /* Setup the vectors identically to the ones in req. */
1133 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1134 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1141 TALLOC_FREE(newreq);
1145 smb2_setup_nbt_length(newreq->out.vector,
1146 newreq->out.vector_count);
1151 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1153 struct smbd_server_connection *sconn = req->sconn;
1154 struct smbXsrv_connection *conn = req->sconn->conn;
1156 struct iovec *firsttf = NULL;
1157 struct iovec *outhdr_v = NULL;
1158 uint8_t *outhdr = NULL;
1159 struct smbd_smb2_request *nreq = NULL;
1162 /* Create a new smb2 request we'll use
1163 for the interim return. */
1164 nreq = dup_smb2_req(req);
1166 return NT_STATUS_NO_MEMORY;
1169 /* Lose the last X out vectors. They're the
1170 ones we'll be using for the async reply. */
1171 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1173 smb2_setup_nbt_length(nreq->out.vector,
1174 nreq->out.vector_count);
1176 /* Step back to the previous reply. */
1177 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1178 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1179 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1180 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1181 /* And end the chain. */
1182 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1184 /* Calculate outgoing credits */
1185 smb2_calculate_credits(req, nreq);
1187 if (DEBUGLEVEL >= 10) {
1188 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1189 (unsigned int)nreq->current_idx );
1190 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1191 (unsigned int)nreq->out.vector_count );
1192 print_req_vectors(nreq);
1196 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1197 * we need to sign/encrypt here with the last/first key we remembered
1199 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1200 status = smb2_signing_encrypt_pdu(req->first_key,
1203 nreq->out.vector_count - first_idx);
1204 if (!NT_STATUS_IS_OK(status)) {
1207 } else if (req->last_key.length > 0) {
1208 status = smb2_signing_sign_pdu(req->last_key,
1211 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1212 if (!NT_STATUS_IS_OK(status)) {
1217 nreq->queue_entry.mem_ctx = nreq;
1218 nreq->queue_entry.vector = nreq->out.vector;
1219 nreq->queue_entry.count = nreq->out.vector_count;
1220 DLIST_ADD_END(nreq->sconn->smb2.send_queue, &nreq->queue_entry, NULL);
1221 nreq->sconn->smb2.send_queue_len++;
1223 status = smbd_smb2_io_handler(sconn, TEVENT_FD_WRITE);
1224 if (!NT_STATUS_IS_OK(status)) {
1228 return NT_STATUS_OK;
1231 struct smbd_smb2_request_pending_state {
1232 struct smbd_server_connection *sconn;
1233 struct smbd_smb2_send_queue queue_entry;
1234 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1235 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1238 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1239 struct tevent_timer *te,
1240 struct timeval current_time,
1241 void *private_data);
1243 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1244 struct tevent_req *subreq,
1245 uint32_t defer_time)
1248 struct timeval defer_endtime;
1249 uint8_t *outhdr = NULL;
1252 if (!tevent_req_is_in_progress(subreq)) {
1254 * This is a performance optimization,
1255 * it avoids one tevent_loop iteration,
1256 * which means we avoid one
1257 * talloc_stackframe_pool/talloc_free pair.
1259 tevent_req_notify_callback(subreq);
1260 return NT_STATUS_OK;
1263 req->subreq = subreq;
1266 if (req->async_te) {
1267 /* We're already async. */
1268 return NT_STATUS_OK;
1271 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1272 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1273 if (flags & SMB2_HDR_FLAG_ASYNC) {
1274 /* We're already async. */
1275 return NT_STATUS_OK;
1278 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1280 * We're trying to go async in a compound
1282 * This is only allowed for opens that
1283 * cause an oplock break, otherwise it
1284 * is not allowed. See [MS-SMB2].pdf
1285 * note <194> on Section 3.3.5.2.7.
1287 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1289 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1291 * Cancel the outstanding request.
1293 bool ok = tevent_req_cancel(req->subreq);
1295 return NT_STATUS_OK;
1297 TALLOC_FREE(req->subreq);
1298 return smbd_smb2_request_error(req,
1299 NT_STATUS_INTERNAL_ERROR);
1303 if (DEBUGLEVEL >= 10) {
1304 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1305 (unsigned int)req->current_idx );
1306 print_req_vectors(req);
1309 if (req->current_idx > 1) {
1311 * We're going async in a compound
1312 * chain after the first request has
1313 * already been processed. Send an
1314 * interim response containing the
1315 * set of replies already generated.
1317 int idx = req->current_idx;
1319 status = smb2_send_async_interim_response(req);
1320 if (!NT_STATUS_IS_OK(status)) {
1323 data_blob_clear_free(&req->first_key);
1325 req->current_idx = 1;
1328 * Re-arrange the in.vectors to remove what
1331 memmove(&req->in.vector[1],
1332 &req->in.vector[idx],
1333 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1334 req->in.vector_count = 1 + (req->in.vector_count - idx);
1336 /* Re-arrange the out.vectors to match. */
1337 memmove(&req->out.vector[1],
1338 &req->out.vector[idx],
1339 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1340 req->out.vector_count = 1 + (req->out.vector_count - idx);
1342 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1344 * We only have one remaining request as
1345 * we've processed everything else.
1346 * This is no longer a compound request.
1348 req->compound_related = false;
1349 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1350 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1351 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1354 data_blob_clear_free(&req->last_key);
1356 defer_endtime = timeval_current_ofs_usec(defer_time);
1357 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1359 smbd_smb2_request_pending_timer,
1361 if (req->async_te == NULL) {
1362 return NT_STATUS_NO_MEMORY;
1365 return NT_STATUS_OK;
1368 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1369 struct tevent_timer *te,
1370 struct timeval current_time,
1373 struct smbd_smb2_request *req =
1374 talloc_get_type_abort(private_data,
1375 struct smbd_smb2_request);
1376 struct smbd_server_connection *sconn = req->sconn;
1377 struct smbd_smb2_request_pending_state *state = NULL;
1378 uint8_t *outhdr = NULL;
1379 const uint8_t *inhdr = NULL;
1382 uint8_t *hdr = NULL;
1383 uint8_t *body = NULL;
1384 uint8_t *dyn = NULL;
1386 uint64_t session_id = 0;
1387 uint64_t message_id = 0;
1388 uint64_t nonce_high = 0;
1389 uint64_t nonce_low = 0;
1390 uint64_t async_id = 0;
1393 TALLOC_FREE(req->async_te);
1395 /* Ensure our final reply matches the interim one. */
1396 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1397 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1398 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1399 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1400 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1402 async_id = message_id; /* keep it simple for now... */
1404 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1405 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1407 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1409 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1410 (unsigned long long)async_id ));
1413 * What we send is identical to a smbd_smb2_request_error
1414 * packet with an error status of STATUS_PENDING. Make use
1415 * of this fact sometime when refactoring. JRA.
1418 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1419 if (state == NULL) {
1420 smbd_server_connection_terminate(req->sconn,
1421 nt_errstr(NT_STATUS_NO_MEMORY));
1424 state->sconn = req->sconn;
1426 tf = state->buf + NBT_HDR_SIZE;
1427 tf_len = SMB2_TF_HDR_SIZE;
1429 hdr = tf + SMB2_TF_HDR_SIZE;
1430 body = hdr + SMB2_HDR_BODY;
1433 if (req->do_encryption) {
1434 struct smbXsrv_session *x = req->session;
1436 nonce_high = x->nonce_high;
1437 nonce_low = x->nonce_low;
1440 if (x->nonce_low == 0) {
1446 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1447 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1448 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1449 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1451 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1452 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1453 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1454 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1455 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1457 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1458 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1459 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1460 SBVAL(hdr, SMB2_HDR_PID, async_id);
1461 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1462 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1463 memcpy(hdr+SMB2_HDR_SIGNATURE,
1464 outhdr+SMB2_HDR_SIGNATURE, 16);
1466 SSVAL(body, 0x00, 0x08 + 1);
1468 SCVAL(body, 0x02, 0);
1469 SCVAL(body, 0x03, 0);
1470 SIVAL(body, 0x04, 0);
1471 /* Match W2K8R2... */
1472 SCVAL(dyn, 0x00, 0x21);
1474 state->vector[0].iov_base = (void *)state->buf;
1475 state->vector[0].iov_len = NBT_HDR_SIZE;
1477 if (req->do_encryption) {
1478 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1479 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1481 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1482 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1485 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1486 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1488 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1489 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1491 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1492 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1494 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1496 /* Ensure we correctly go through crediting. Grant
1497 the credits now, and zero credits on the final
1499 smb2_set_operation_credit(req->sconn,
1500 SMBD_SMB2_IN_HDR_IOV(req),
1501 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1503 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1508 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1509 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1511 (unsigned int)ARRAY_SIZE(state->vector),
1512 (unsigned int)state->vector[i].iov_len);
1516 if (req->do_encryption) {
1517 struct smbXsrv_session *x = req->session;
1518 struct smbXsrv_connection *conn = x->connection;
1519 DATA_BLOB encryption_key = x->global->encryption_key;
1521 status = smb2_signing_encrypt_pdu(encryption_key,
1523 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1524 SMBD_SMB2_NUM_IOV_PER_REQ);
1525 if (!NT_STATUS_IS_OK(status)) {
1526 smbd_server_connection_terminate(req->sconn,
1530 } else if (req->do_signing) {
1531 struct smbXsrv_session *x = req->session;
1532 struct smbXsrv_connection *conn = x->connection;
1533 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1535 status = smb2_signing_sign_pdu(signing_key,
1537 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1538 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1539 if (!NT_STATUS_IS_OK(status)) {
1540 smbd_server_connection_terminate(req->sconn,
1546 state->queue_entry.mem_ctx = state;
1547 state->queue_entry.vector = state->vector;
1548 state->queue_entry.count = ARRAY_SIZE(state->vector);
1549 DLIST_ADD_END(sconn->smb2.send_queue, &state->queue_entry, NULL);
1550 sconn->smb2.send_queue_len++;
1552 status = smbd_smb2_io_handler(sconn, TEVENT_FD_WRITE);
1553 if (!NT_STATUS_IS_OK(status)) {
1554 smbd_server_connection_terminate(sconn,
1560 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1562 struct smbd_server_connection *sconn = req->sconn;
1563 struct smbd_smb2_request *cur;
1564 const uint8_t *inhdr;
1566 uint64_t search_message_id;
1567 uint64_t search_async_id;
1570 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1572 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1573 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1574 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1577 * we don't need the request anymore
1578 * cancel requests never have a response
1580 DLIST_REMOVE(req->sconn->smb2.requests, req);
1583 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1584 const uint8_t *outhdr;
1585 uint64_t message_id;
1588 if (cur->compound_related) {
1590 * Never cancel anything in a compound request.
1591 * Way too hard to deal with the result.
1596 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1598 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1599 async_id = BVAL(outhdr, SMB2_HDR_PID);
1601 if (flags & SMB2_HDR_FLAG_ASYNC) {
1602 if (search_async_id == async_id) {
1603 found_id = async_id;
1607 if (search_message_id == message_id) {
1608 found_id = message_id;
1614 if (cur && cur->subreq) {
1615 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1616 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1617 "cancel opcode[%s] mid %llu\n",
1618 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1619 (unsigned long long)found_id ));
1620 tevent_req_cancel(cur->subreq);
1623 return NT_STATUS_OK;
1626 /*************************************************************
1627 Ensure an incoming tid is a valid one for us to access.
1628 Change to the associated uid credentials and chdir to the
1629 valid tid directory.
1630 *************************************************************/
1632 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1634 const uint8_t *inhdr;
1637 struct smbXsrv_tcon *tcon;
1639 NTTIME now = timeval_to_nttime(&req->request_time);
1643 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1645 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1646 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1648 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1649 in_tid = req->last_tid;
1654 status = smb2srv_tcon_lookup(req->session,
1655 in_tid, now, &tcon);
1656 if (!NT_STATUS_IS_OK(status)) {
1660 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1661 return NT_STATUS_ACCESS_DENIED;
1664 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1665 if (!set_current_service(tcon->compat, 0, true)) {
1666 return NT_STATUS_ACCESS_DENIED;
1670 req->last_tid = in_tid;
1672 return NT_STATUS_OK;
1675 /*************************************************************
1676 Ensure an incoming session_id is a valid one for us to access.
1677 *************************************************************/
1679 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1681 const uint8_t *inhdr;
1684 uint64_t in_session_id;
1685 struct smbXsrv_session *session = NULL;
1686 struct auth_session_info *session_info;
1688 NTTIME now = timeval_to_nttime(&req->request_time);
1690 req->session = NULL;
1693 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1695 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1696 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1697 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1699 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1700 in_session_id = req->last_session_id;
1703 req->last_session_id = 0;
1705 /* lookup an existing session */
1706 status = smb2srv_session_lookup(req->sconn->conn,
1710 req->session = session;
1711 req->last_session_id = in_session_id;
1713 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1714 switch (in_opcode) {
1715 case SMB2_OP_SESSSETUP:
1716 status = NT_STATUS_OK;
1722 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1723 switch (in_opcode) {
1725 case SMB2_OP_CREATE:
1726 case SMB2_OP_GETINFO:
1727 case SMB2_OP_SETINFO:
1728 return NT_STATUS_INVALID_HANDLE;
1731 * Notice the check for
1732 * (session_info == NULL)
1735 status = NT_STATUS_OK;
1739 if (!NT_STATUS_IS_OK(status)) {
1743 session_info = session->global->auth_session_info;
1744 if (session_info == NULL) {
1745 return NT_STATUS_INVALID_HANDLE;
1748 if (in_session_id != req->sconn->conn->last_session_id) {
1749 req->sconn->conn->last_session_id = in_session_id;
1750 set_current_user_info(session_info->unix_info->sanitized_username,
1751 session_info->unix_info->unix_name,
1752 session_info->info->domain_name);
1755 return NT_STATUS_OK;
1758 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1759 uint32_t data_length)
1761 uint16_t needed_charge;
1762 uint16_t credit_charge = 1;
1763 const uint8_t *inhdr;
1765 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1767 if (req->sconn->smb2.supports_multicredit) {
1768 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1769 credit_charge = MAX(credit_charge, 1);
1772 needed_charge = (data_length - 1)/ 65536 + 1;
1774 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1775 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1776 credit_charge, needed_charge));
1778 if (needed_charge > credit_charge) {
1779 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1780 credit_charge, needed_charge));
1781 return NT_STATUS_INVALID_PARAMETER;
1784 return NT_STATUS_OK;
1787 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1788 size_t expected_body_size)
1790 struct iovec *inhdr_v;
1791 const uint8_t *inhdr;
1793 const uint8_t *inbody;
1795 size_t min_dyn_size = expected_body_size & 0x00000001;
1796 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1799 * The following should be checked already.
1801 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1802 return NT_STATUS_INTERNAL_ERROR;
1804 if (req->current_idx > max_idx) {
1805 return NT_STATUS_INTERNAL_ERROR;
1808 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1809 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1810 return NT_STATUS_INTERNAL_ERROR;
1812 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1813 return NT_STATUS_INTERNAL_ERROR;
1816 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1817 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1821 case SMB2_OP_GETINFO:
1827 * Now check the expected body size,
1828 * where the last byte might be in the
1831 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1832 return NT_STATUS_INVALID_PARAMETER;
1834 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1835 return NT_STATUS_INVALID_PARAMETER;
1838 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1840 body_size = SVAL(inbody, 0x00);
1841 if (body_size != expected_body_size) {
1842 return NT_STATUS_INVALID_PARAMETER;
1845 return NT_STATUS_OK;
1848 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1850 struct smbXsrv_connection *conn = req->sconn->conn;
1851 const struct smbd_smb2_dispatch_table *call = NULL;
1852 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1853 const uint8_t *inhdr;
1858 NTSTATUS session_status;
1859 uint32_t allowed_flags;
1860 NTSTATUS return_value;
1861 struct smbXsrv_session *x = NULL;
1862 bool signing_required = false;
1863 bool encryption_required = false;
1865 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1867 /* TODO: verify more things */
1869 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1870 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1871 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1872 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1873 smb2_opcode_name(opcode),
1874 (unsigned long long)mid));
1876 if (conn->protocol >= PROTOCOL_SMB2_02) {
1878 * once the protocol is negotiated
1879 * SMB2_OP_NEGPROT is not allowed anymore
1881 if (opcode == SMB2_OP_NEGPROT) {
1882 /* drop the connection */
1883 return NT_STATUS_INVALID_PARAMETER;
1887 * if the protocol is not negotiated yet
1888 * only SMB2_OP_NEGPROT is allowed.
1890 if (opcode != SMB2_OP_NEGPROT) {
1891 /* drop the connection */
1892 return NT_STATUS_INVALID_PARAMETER;
1897 * Check if the client provided a valid session id,
1898 * if so smbd_smb2_request_check_session() calls
1899 * set_current_user_info().
1901 * As some command don't require a valid session id
1902 * we defer the check of the session_status
1904 session_status = smbd_smb2_request_check_session(req);
1907 signing_required = x->global->signing_required;
1908 encryption_required = x->global->encryption_required;
1911 req->do_signing = false;
1912 req->do_encryption = false;
1913 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
1914 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
1915 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
1917 if (x != NULL && x->global->session_wire_id != tf_session_id) {
1918 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1919 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1920 (unsigned long long)x->global->session_wire_id,
1921 (unsigned long long)tf_session_id));
1923 * TODO: windows allows this...
1924 * should we drop the connection?
1926 * For now we just return ACCESS_DENIED
1927 * (Windows clients never trigger this)
1928 * and wait for an update of [MS-SMB2].
1930 return smbd_smb2_request_error(req,
1931 NT_STATUS_ACCESS_DENIED);
1934 req->do_encryption = true;
1937 if (encryption_required && !req->do_encryption) {
1938 return smbd_smb2_request_error(req,
1939 NT_STATUS_ACCESS_DENIED);
1942 call = smbd_smb2_call(opcode);
1944 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1947 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1948 SMB2_HDR_FLAG_SIGNED |
1950 if (opcode == SMB2_OP_CANCEL) {
1951 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1953 if ((flags & ~allowed_flags) != 0) {
1954 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1957 if (flags & SMB2_HDR_FLAG_CHAINED) {
1959 * This check is mostly for giving the correct error code
1960 * for compounded requests.
1962 if (!NT_STATUS_IS_OK(session_status)) {
1963 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1966 req->compat_chain_fsp = NULL;
1969 if (req->do_encryption) {
1970 signing_required = false;
1971 } else if (flags & SMB2_HDR_FLAG_SIGNED) {
1972 DATA_BLOB signing_key;
1975 return smbd_smb2_request_error(
1976 req, NT_STATUS_ACCESS_DENIED);
1979 signing_key = x->global->channels[0].signing_key;
1982 * If we have a signing key, we should
1985 if (signing_key.length > 0) {
1986 req->do_signing = true;
1989 status = smb2_signing_check_pdu(signing_key,
1991 SMBD_SMB2_IN_HDR_IOV(req),
1992 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1993 if (!NT_STATUS_IS_OK(status)) {
1994 return smbd_smb2_request_error(req, status);
1998 * Now that we know the request was correctly signed
1999 * we have to sign the response too.
2001 req->do_signing = true;
2003 if (!NT_STATUS_IS_OK(session_status)) {
2004 return smbd_smb2_request_error(req, session_status);
2006 } else if (opcode == SMB2_OP_CANCEL) {
2007 /* Cancel requests are allowed to skip the signing */
2008 } else if (signing_required) {
2010 * If signing is required we try to sign
2011 * a possible error response
2013 req->do_signing = true;
2014 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2017 if (flags & SMB2_HDR_FLAG_CHAINED) {
2018 req->compound_related = true;
2021 if (call->need_session) {
2022 if (!NT_STATUS_IS_OK(session_status)) {
2023 return smbd_smb2_request_error(req, session_status);
2027 if (call->need_tcon) {
2028 SMB_ASSERT(call->need_session);
2031 * This call needs to be run as user.
2033 * smbd_smb2_request_check_tcon()
2034 * calls change_to_user() on success.
2036 status = smbd_smb2_request_check_tcon(req);
2037 if (!NT_STATUS_IS_OK(status)) {
2038 return smbd_smb2_request_error(req, status);
2040 if (req->tcon->global->encryption_required) {
2041 encryption_required = true;
2043 if (encryption_required && !req->do_encryption) {
2044 return smbd_smb2_request_error(req,
2045 NT_STATUS_ACCESS_DENIED);
2049 if (call->fileid_ofs != 0) {
2050 size_t needed = call->fileid_ofs + 16;
2051 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2052 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2053 uint64_t file_id_persistent;
2054 uint64_t file_id_volatile;
2055 struct files_struct *fsp;
2057 SMB_ASSERT(call->need_tcon);
2059 if (needed > body_size) {
2060 return smbd_smb2_request_error(req,
2061 NT_STATUS_INVALID_PARAMETER);
2064 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2065 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2067 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2069 if (!call->allow_invalid_fileid) {
2070 return smbd_smb2_request_error(req,
2071 NT_STATUS_FILE_CLOSED);
2074 if (file_id_persistent != UINT64_MAX) {
2075 return smbd_smb2_request_error(req,
2076 NT_STATUS_FILE_CLOSED);
2078 if (file_id_volatile != UINT64_MAX) {
2079 return smbd_smb2_request_error(req,
2080 NT_STATUS_FILE_CLOSED);
2085 if (call->as_root) {
2086 SMB_ASSERT(call->fileid_ofs == 0);
2087 /* This call needs to be run as root */
2088 change_to_root_user();
2090 SMB_ASSERT(call->need_tcon);
2094 case SMB2_OP_NEGPROT:
2096 START_PROFILE(smb2_negprot);
2097 return_value = smbd_smb2_request_process_negprot(req);
2098 END_PROFILE(smb2_negprot);
2102 case SMB2_OP_SESSSETUP:
2104 START_PROFILE(smb2_sesssetup);
2105 return_value = smbd_smb2_request_process_sesssetup(req);
2106 END_PROFILE(smb2_sesssetup);
2110 case SMB2_OP_LOGOFF:
2112 START_PROFILE(smb2_logoff);
2113 return_value = smbd_smb2_request_process_logoff(req);
2114 END_PROFILE(smb2_logoff);
2120 START_PROFILE(smb2_tcon);
2121 return_value = smbd_smb2_request_process_tcon(req);
2122 END_PROFILE(smb2_tcon);
2128 START_PROFILE(smb2_tdis);
2129 return_value = smbd_smb2_request_process_tdis(req);
2130 END_PROFILE(smb2_tdis);
2134 case SMB2_OP_CREATE:
2136 START_PROFILE(smb2_create);
2137 return_value = smbd_smb2_request_process_create(req);
2138 END_PROFILE(smb2_create);
2144 START_PROFILE(smb2_close);
2145 return_value = smbd_smb2_request_process_close(req);
2146 END_PROFILE(smb2_close);
2152 START_PROFILE(smb2_flush);
2153 return_value = smbd_smb2_request_process_flush(req);
2154 END_PROFILE(smb2_flush);
2160 START_PROFILE(smb2_read);
2161 return_value = smbd_smb2_request_process_read(req);
2162 END_PROFILE(smb2_read);
2168 START_PROFILE(smb2_write);
2169 return_value = smbd_smb2_request_process_write(req);
2170 END_PROFILE(smb2_write);
2176 START_PROFILE(smb2_lock);
2177 return_value = smbd_smb2_request_process_lock(req);
2178 END_PROFILE(smb2_lock);
2184 START_PROFILE(smb2_ioctl);
2185 return_value = smbd_smb2_request_process_ioctl(req);
2186 END_PROFILE(smb2_ioctl);
2190 case SMB2_OP_CANCEL:
2192 START_PROFILE(smb2_cancel);
2193 return_value = smbd_smb2_request_process_cancel(req);
2194 END_PROFILE(smb2_cancel);
2198 case SMB2_OP_KEEPALIVE:
2200 START_PROFILE(smb2_keepalive);
2201 return_value = smbd_smb2_request_process_keepalive(req);
2202 END_PROFILE(smb2_keepalive);
2208 START_PROFILE(smb2_find);
2209 return_value = smbd_smb2_request_process_find(req);
2210 END_PROFILE(smb2_find);
2214 case SMB2_OP_NOTIFY:
2216 START_PROFILE(smb2_notify);
2217 return_value = smbd_smb2_request_process_notify(req);
2218 END_PROFILE(smb2_notify);
2222 case SMB2_OP_GETINFO:
2224 START_PROFILE(smb2_getinfo);
2225 return_value = smbd_smb2_request_process_getinfo(req);
2226 END_PROFILE(smb2_getinfo);
2230 case SMB2_OP_SETINFO:
2232 START_PROFILE(smb2_setinfo);
2233 return_value = smbd_smb2_request_process_setinfo(req);
2234 END_PROFILE(smb2_setinfo);
2240 START_PROFILE(smb2_break);
2241 return_value = smbd_smb2_request_process_break(req);
2242 END_PROFILE(smb2_break);
2247 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2250 return return_value;
2253 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2255 struct smbd_server_connection *sconn = req->sconn;
2256 struct smbXsrv_connection *conn = req->sconn->conn;
2258 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2259 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2260 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2264 TALLOC_FREE(req->async_te);
2266 if (req->do_encryption &&
2267 (firsttf->iov_len == 0) &&
2268 (req->first_key.length == 0) &&
2269 (req->session != NULL) &&
2270 (req->session->global->encryption_key.length != 0))
2272 DATA_BLOB encryption_key = req->session->global->encryption_key;
2274 uint64_t session_id = req->session->global->session_wire_id;
2275 struct smbXsrv_session *x = req->session;
2276 uint64_t nonce_high;
2279 nonce_high = x->nonce_high;
2280 nonce_low = x->nonce_low;
2283 if (x->nonce_low == 0) {
2289 * We need to place the SMB2_TRANSFORM header before the
2294 * we need to remember the encryption key
2295 * and defer the signing/encryption until
2296 * we are sure that we do not change
2299 req->first_key = data_blob_dup_talloc(req, encryption_key);
2300 if (req->first_key.data == NULL) {
2301 return NT_STATUS_NO_MEMORY;
2304 tf = talloc_zero_array(req->out.vector, uint8_t,
2307 return NT_STATUS_NO_MEMORY;
2310 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2311 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2312 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2313 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2315 firsttf->iov_base = (void *)tf;
2316 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2319 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2320 (req->last_key.length > 0) &&
2321 (firsttf->iov_len == 0))
2323 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2324 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2327 * As we are sure the header of the last request in the
2328 * compound chain will not change, we can to sign here
2329 * with the last signing key we remembered.
2331 status = smb2_signing_sign_pdu(req->last_key,
2334 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2335 if (!NT_STATUS_IS_OK(status)) {
2339 data_blob_clear_free(&req->last_key);
2341 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2343 if (req->current_idx < req->out.vector_count) {
2345 * We must process the remaining compound
2346 * SMB2 requests before any new incoming SMB2
2347 * requests. This is because incoming SMB2
2348 * requests may include a cancel for a
2349 * compound request we haven't processed
2352 struct tevent_immediate *im = tevent_create_immediate(req);
2354 return NT_STATUS_NO_MEMORY;
2357 if (req->do_signing && firsttf->iov_len == 0) {
2358 struct smbXsrv_session *x = req->session;
2359 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2362 * we need to remember the signing key
2363 * and defer the signing until
2364 * we are sure that we do not change
2367 req->last_key = data_blob_dup_talloc(req, signing_key);
2368 if (req->last_key.data == NULL) {
2369 return NT_STATUS_NO_MEMORY;
2373 tevent_schedule_immediate(im,
2375 smbd_smb2_request_dispatch_immediate,
2377 return NT_STATUS_OK;
2380 if (req->compound_related) {
2381 req->compound_related = false;
2384 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2386 /* Set credit for these operations (zero credits if this
2387 is a final reply for an async operation). */
2388 smb2_calculate_credits(req, req);
2391 * now check if we need to sign the current response
2393 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2394 status = smb2_signing_encrypt_pdu(req->first_key,
2397 req->out.vector_count - first_idx);
2398 if (!NT_STATUS_IS_OK(status)) {
2401 } else if (req->do_signing) {
2402 struct smbXsrv_session *x = req->session;
2403 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2405 status = smb2_signing_sign_pdu(signing_key,
2408 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2409 if (!NT_STATUS_IS_OK(status)) {
2413 data_blob_clear_free(&req->first_key);
2415 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2416 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2417 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2418 /* Dynamic part is NULL. Chop it off,
2419 We're going to send it via sendfile. */
2420 req->out.vector_count -= 1;
2424 * We're done with this request -
2425 * move it off the "being processed" queue.
2427 DLIST_REMOVE(req->sconn->smb2.requests, req);
2429 req->queue_entry.mem_ctx = req;
2430 req->queue_entry.vector = req->out.vector;
2431 req->queue_entry.count = req->out.vector_count;
2432 DLIST_ADD_END(req->sconn->smb2.send_queue, &req->queue_entry, NULL);
2433 req->sconn->smb2.send_queue_len++;
2435 status = smbd_smb2_io_handler(sconn, TEVENT_FD_WRITE);
2436 if (!NT_STATUS_IS_OK(status)) {
2440 return NT_STATUS_OK;
2443 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2445 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2446 struct tevent_immediate *im,
2449 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2450 struct smbd_smb2_request);
2451 struct smbd_server_connection *sconn = req->sconn;
2456 if (DEBUGLEVEL >= 10) {
2457 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2458 req->current_idx, req->in.vector_count));
2459 print_req_vectors(req);
2462 status = smbd_smb2_request_dispatch(req);
2463 if (!NT_STATUS_IS_OK(status)) {
2464 smbd_server_connection_terminate(sconn, nt_errstr(status));
2468 status = smbd_smb2_request_next_incoming(sconn);
2469 if (!NT_STATUS_IS_OK(status)) {
2470 smbd_server_connection_terminate(sconn, nt_errstr(status));
2475 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2477 DATA_BLOB body, DATA_BLOB *dyn,
2478 const char *location)
2481 struct iovec *outbody_v;
2482 struct iovec *outdyn_v;
2483 uint32_t next_command_ofs;
2485 DEBUG(10,("smbd_smb2_request_done_ex: "
2486 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2487 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2489 (unsigned int)(dyn ? dyn->length : 0),
2492 if (body.length < 2) {
2493 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2496 if ((body.length % 2) != 0) {
2497 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2500 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2501 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2502 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2504 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2505 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2507 outbody_v->iov_base = (void *)body.data;
2508 outbody_v->iov_len = body.length;
2511 outdyn_v->iov_base = (void *)dyn->data;
2512 outdyn_v->iov_len = dyn->length;
2514 outdyn_v->iov_base = NULL;
2515 outdyn_v->iov_len = 0;
2518 /* see if we need to recalculate the offset to the next response */
2519 if (next_command_ofs > 0) {
2520 next_command_ofs = SMB2_HDR_BODY;
2521 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2522 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2525 if ((next_command_ofs % 8) != 0) {
2526 size_t pad_size = 8 - (next_command_ofs % 8);
2527 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2529 * if the dyn buffer is empty
2530 * we can use it to add padding
2534 pad = talloc_zero_array(req->out.vector,
2537 return smbd_smb2_request_error(req,
2538 NT_STATUS_NO_MEMORY);
2541 outdyn_v->iov_base = (void *)pad;
2542 outdyn_v->iov_len = pad_size;
2545 * For now we copy the dynamic buffer
2546 * and add the padding to the new buffer
2553 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2554 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2556 new_size = old_size + pad_size;
2557 new_dyn = talloc_zero_array(req->out.vector,
2559 if (new_dyn == NULL) {
2560 return smbd_smb2_request_error(req,
2561 NT_STATUS_NO_MEMORY);
2564 memcpy(new_dyn, old_dyn, old_size);
2565 memset(new_dyn + old_size, 0, pad_size);
2567 outdyn_v->iov_base = (void *)new_dyn;
2568 outdyn_v->iov_len = new_size;
2570 next_command_ofs += pad_size;
2573 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2575 return smbd_smb2_request_reply(req);
2578 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2581 const char *location)
2584 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2585 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2587 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2588 req->current_idx, nt_errstr(status), info ? " +info" : "",
2592 /* Recvfile error. Drain incoming socket. */
2596 ret = drain_socket(req->sconn->sock, unread_bytes);
2597 if (ret != unread_bytes) {
2601 error = NT_STATUS_IO_DEVICE_ERROR;
2603 error = map_nt_error_from_unix_common(errno);
2606 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2607 "ret[%u] errno[%d] => %s\n",
2608 (unsigned)unread_bytes,
2609 (unsigned)ret, errno, nt_errstr(error)));
2614 body.data = outhdr + SMB2_HDR_BODY;
2616 SSVAL(body.data, 0, 9);
2619 SIVAL(body.data, 0x04, info->length);
2621 /* Allocated size of req->out.vector[i].iov_base
2622 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2623 * 1 byte without having to do an alloc.
2625 info = talloc_zero_array(req->out.vector,
2629 return NT_STATUS_NO_MEMORY;
2631 info->data = ((uint8_t *)outhdr) +
2632 OUTVEC_ALLOC_SIZE - 1;
2634 SCVAL(info->data, 0, 0);
2638 * Note: Even if there is an error, continue to process the request.
2642 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2646 struct smbd_smb2_send_oplock_break_state {
2647 struct smbd_server_connection *sconn;
2648 struct smbd_smb2_send_queue queue_entry;
2649 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x18];
2650 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2653 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2654 struct smbXsrv_session *session,
2655 struct smbXsrv_tcon *tcon,
2656 struct smbXsrv_open *op,
2657 uint8_t oplock_level)
2659 struct smbd_smb2_send_oplock_break_state *state;
2660 struct smbXsrv_connection *conn = sconn->conn;
2668 bool do_encryption = session->global->encryption_required;
2669 uint64_t nonce_high = 0;
2670 uint64_t nonce_low = 0;
2673 if (tcon->global->encryption_required) {
2674 do_encryption = true;
2677 state = talloc_zero(sconn, struct smbd_smb2_send_oplock_break_state);
2678 if (state == NULL) {
2679 return NT_STATUS_NO_MEMORY;
2681 state->sconn = sconn;
2683 tf = state->buf + NBT_HDR_SIZE;
2684 tf_len = SMB2_TF_HDR_SIZE;
2686 body = hdr + SMB2_HDR_BODY;
2688 dyn = body + body_len;
2691 if (do_encryption) {
2692 nonce_high = session->nonce_high;
2693 nonce_low = session->nonce_low;
2695 session->nonce_low += 1;
2696 if (session->nonce_low == 0) {
2697 session->nonce_low += 1;
2698 session->nonce_high += 1;
2702 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2703 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2704 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2705 SBVAL(tf, SMB2_TF_SESSION_ID, session->global->session_wire_id);
2707 SIVAL(hdr, 0, SMB2_MAGIC);
2708 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2709 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2710 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2711 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2712 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2713 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2714 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2715 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2716 SIVAL(hdr, SMB2_HDR_PID, 0);
2717 SIVAL(hdr, SMB2_HDR_TID, 0);
2718 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2719 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2721 SSVAL(body, 0x00, body_len);
2723 SCVAL(body, 0x02, oplock_level);
2724 SCVAL(body, 0x03, 0); /* reserved */
2725 SIVAL(body, 0x04, 0); /* reserved */
2726 SBVAL(body, 0x08, op->global->open_persistent_id);
2727 SBVAL(body, 0x10, op->global->open_volatile_id);
2729 state->vector[0].iov_base = (void *)state->buf;
2730 state->vector[0].iov_len = NBT_HDR_SIZE;
2732 if (do_encryption) {
2733 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
2734 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
2736 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
2737 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
2740 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
2741 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
2743 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
2744 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = body_len;
2746 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
2747 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_len;
2749 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2751 if (do_encryption) {
2752 DATA_BLOB encryption_key = session->global->encryption_key;
2754 status = smb2_signing_encrypt_pdu(encryption_key,
2756 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2757 SMBD_SMB2_NUM_IOV_PER_REQ);
2758 if (!NT_STATUS_IS_OK(status)) {
2763 state->queue_entry.mem_ctx = state;
2764 state->queue_entry.vector = state->vector;
2765 state->queue_entry.count = ARRAY_SIZE(state->vector);
2766 DLIST_ADD_END(state->sconn->smb2.send_queue, &state->queue_entry, NULL);
2767 state->sconn->smb2.send_queue_len++;
2769 status = smbd_smb2_io_handler(sconn, TEVENT_FD_WRITE);
2770 if (!NT_STATUS_IS_OK(status)) {
2774 return NT_STATUS_OK;
2777 static size_t get_min_receive_file_size(struct smbd_smb2_request *smb2_req)
2779 if (smb2_req->do_signing) {
2782 if (smb2_req->do_encryption) {
2785 return (size_t)lp_min_receive_file_size();
2788 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2792 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
2793 /* Transform header. Cannot recvfile. */
2796 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
2797 /* Not SMB2. Normal error path will cope. */
2800 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
2801 /* Not SMB2. Normal error path will cope. */
2804 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
2805 /* Needs to be a WRITE. */
2808 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
2809 /* Chained. Cannot recvfile. */
2812 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
2813 if (flags & SMB2_HDR_FLAG_CHAINED) {
2814 /* Chained. Cannot recvfile. */
2817 if (flags & SMB2_HDR_FLAG_SIGNED) {
2818 /* Signed. Cannot recvfile. */
2822 DEBUG(10,("Doing recvfile write len = %u\n",
2823 (unsigned int)(state->pktlen -
2824 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN)));
2829 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2831 struct smbd_smb2_request_read_state *state = &sconn->smb2.request_read_state;
2832 size_t max_send_queue_len;
2833 size_t cur_send_queue_len;
2835 if (!NT_STATUS_IS_OK(sconn->status)) {
2837 * we're not supposed to do any io
2839 return NT_STATUS_OK;
2842 if (state->req != NULL) {
2844 * if there is already a tstream_readv_pdu
2845 * pending, we are done.
2847 return NT_STATUS_OK;
2850 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2851 cur_send_queue_len = sconn->smb2.send_queue_len;
2853 if (cur_send_queue_len > max_send_queue_len) {
2855 * if we have a lot of requests to send,
2856 * we wait until they are on the wire until we
2857 * ask for the next request.
2859 return NT_STATUS_OK;
2862 /* ask for the next request */
2863 ZERO_STRUCTP(state);
2864 state->req = smbd_smb2_request_allocate(sconn);
2865 if (state->req == NULL) {
2866 return NT_STATUS_NO_MEMORY;
2868 state->req->sconn = sconn;
2869 state->min_recv_size = get_min_receive_file_size(state->req);
2871 TEVENT_FD_READABLE(sconn->smb2.fde);
2873 return NT_STATUS_OK;
2876 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2877 uint8_t *inbuf, size_t size)
2880 struct smbd_smb2_request *req = NULL;
2882 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2883 (unsigned int)size));
2885 status = smbd_initialize_smb2(sconn);
2886 if (!NT_STATUS_IS_OK(status)) {
2887 smbd_server_connection_terminate(sconn, nt_errstr(status));
2891 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2892 if (!NT_STATUS_IS_OK(status)) {
2893 smbd_server_connection_terminate(sconn, nt_errstr(status));
2897 status = smbd_smb2_request_validate(req);
2898 if (!NT_STATUS_IS_OK(status)) {
2899 smbd_server_connection_terminate(sconn, nt_errstr(status));
2903 status = smbd_smb2_request_setup_out(req);
2904 if (!NT_STATUS_IS_OK(status)) {
2905 smbd_server_connection_terminate(sconn, nt_errstr(status));
2909 status = smbd_smb2_request_dispatch(req);
2910 if (!NT_STATUS_IS_OK(status)) {
2911 smbd_server_connection_terminate(sconn, nt_errstr(status));
2915 status = smbd_smb2_request_next_incoming(sconn);
2916 if (!NT_STATUS_IS_OK(status)) {
2917 smbd_server_connection_terminate(sconn, nt_errstr(status));
2921 sconn->num_requests++;
2924 static int socket_error_from_errno(int ret,
2938 if (sys_errno == 0) {
2942 if (sys_errno == EINTR) {
2947 if (sys_errno == EINPROGRESS) {
2952 if (sys_errno == EAGAIN) {
2957 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
2958 if (sys_errno == ENOMEM) {
2964 if (sys_errno == EWOULDBLOCK) {
2973 static NTSTATUS smbd_smb2_flush_send_queue(struct smbd_server_connection *sconn)
2979 if (sconn->smb2.send_queue == NULL) {
2980 TEVENT_FD_NOT_WRITEABLE(sconn->smb2.fde);
2981 return NT_STATUS_OK;
2984 while (sconn->smb2.send_queue != NULL) {
2985 struct smbd_smb2_send_queue *e = sconn->smb2.send_queue;
2987 if (e->sendfile_header != NULL) {
2992 for (i=0; i < e->count; i++) {
2993 size += e->vector[i].iov_len;
2996 buf = talloc_array(e->mem_ctx, uint8_t, size);
2998 return NT_STATUS_NO_MEMORY;
3002 for (i=0; i < e->count; i++) {
3004 e->vector[i].iov_base,
3005 e->vector[i].iov_len);
3006 size += e->vector[i].iov_len;
3009 e->sendfile_header->data = buf;
3010 e->sendfile_header->length = size;
3013 sconn->smb2.send_queue_len--;
3014 DLIST_REMOVE(sconn->smb2.send_queue, e);
3015 talloc_free(e->mem_ctx);
3019 ret = writev(sconn->sock, e->vector, e->count);
3021 /* propagate end of file */
3022 return NT_STATUS_INTERNAL_ERROR;
3024 err = socket_error_from_errno(ret, errno, &retry);
3027 TEVENT_FD_WRITEABLE(sconn->smb2.fde);
3028 return NT_STATUS_OK;
3031 return map_nt_error_from_unix_common(err);
3034 if (ret < e->vector[0].iov_len) {
3036 base = (uint8_t *)e->vector[0].iov_base;
3038 e->vector[0].iov_base = (void *)base;
3039 e->vector[0].iov_len -= ret;
3042 ret -= e->vector[0].iov_len;
3048 * there're maybe some empty vectors at the end
3049 * which we need to skip, otherwise we would get
3050 * ret == 0 from the readv() call and return EPIPE
3052 while (e->count > 0) {
3053 if (e->vector[0].iov_len > 0) {
3061 /* we have more to write */
3062 TEVENT_FD_WRITEABLE(sconn->smb2.fde);
3063 return NT_STATUS_OK;
3066 sconn->smb2.send_queue_len--;
3067 DLIST_REMOVE(sconn->smb2.send_queue, e);
3068 talloc_free(e->mem_ctx);
3071 return NT_STATUS_OK;
3074 static NTSTATUS smbd_smb2_io_handler(struct smbd_server_connection *sconn,
3077 struct smbd_smb2_request_read_state *state = &sconn->smb2.request_read_state;
3078 struct smbd_smb2_request *req = NULL;
3079 size_t min_recvfile_size = UINT32_MAX;
3086 if (!NT_STATUS_IS_OK(sconn->status)) {
3088 * we're not supposed to do any io
3090 TEVENT_FD_NOT_READABLE(sconn->smb2.fde);
3091 TEVENT_FD_NOT_WRITEABLE(sconn->smb2.fde);
3092 return NT_STATUS_OK;
3095 if (fde_flags & TEVENT_FD_WRITE) {
3096 status = smbd_smb2_flush_send_queue(sconn);
3097 if (!NT_STATUS_IS_OK(status)) {
3102 if (!(fde_flags & TEVENT_FD_READ)) {
3103 return NT_STATUS_OK;
3106 if (state->req == NULL) {
3107 TEVENT_FD_NOT_READABLE(sconn->smb2.fde);
3108 return NT_STATUS_OK;
3112 if (!state->hdr.done) {
3113 state->hdr.done = true;
3115 state->vector.iov_base = (void *)state->hdr.nbt;
3116 state->vector.iov_len = NBT_HDR_SIZE;
3119 ret = readv(sconn->sock, &state->vector, 1);
3121 /* propagate end of file */
3122 return NT_STATUS_END_OF_FILE;
3124 err = socket_error_from_errno(ret, errno, &retry);
3127 TEVENT_FD_READABLE(sconn->smb2.fde);
3128 return NT_STATUS_OK;
3131 return map_nt_error_from_unix_common(err);
3134 if (ret < state->vector.iov_len) {
3136 base = (uint8_t *)state->vector.iov_base;
3138 state->vector.iov_base = (void *)base;
3139 state->vector.iov_len -= ret;
3140 /* we have more to read */
3141 TEVENT_FD_READABLE(sconn->smb2.fde);
3142 return NT_STATUS_OK;
3145 if (state->pktlen > 0) {
3146 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3148 * Not a possible receivefile write.
3149 * Read the rest of the data.
3151 state->doing_receivefile = false;
3152 state->vector.iov_base = (void *)(state->pktbuf +
3153 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN);
3154 state->vector.iov_len = (state->pktlen -
3155 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN);
3160 * Either this is a receivefile write so we've
3161 * done a short read, or if not we have all the data.
3167 * Now we analyze the NBT header
3169 state->pktlen = smb2_len(state->hdr.nbt);
3170 if (state->pktlen == 0) {
3174 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3175 if (state->pktbuf == NULL) {
3176 return NT_STATUS_NO_MEMORY;
3179 state->vector.iov_base = (void *)state->pktbuf;
3181 if (state->min_recv_size != 0) {
3182 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3183 min_recvfile_size += state->min_recv_size;
3186 if (state->pktlen > min_recvfile_size) {
3188 * Might be a receivefile write. Read the SMB2 HEADER +
3189 * SMB2_WRITE header first. Set 'doing_receivefile'
3190 * as we're *attempting* receivefile write. If this
3191 * turns out not to be a SMB2_WRITE request or otherwise
3192 * not suitable then we'll just read the rest of the data
3193 * the next time this function is called.
3195 state->vector.iov_len = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3196 state->doing_receivefile = true;
3198 state->vector.iov_len = state->pktlen;
3205 if (state->hdr.nbt[0] != 0x00) {
3206 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3207 state->hdr.nbt[0]));
3210 ZERO_STRUCTP(state);
3212 state->min_recv_size = get_min_receive_file_size(state->req);
3220 req->request_time = timeval_current();
3221 now = timeval_to_nttime(&req->request_time);
3223 status = smbd_smb2_inbuf_parse_compound(req->sconn->conn,
3229 &req->in.vector_count);
3230 if (!NT_STATUS_IS_OK(status)) {
3234 if (state->doing_receivefile) {
3235 req->smb1req = talloc_zero(req, struct smb_request);
3236 if (req->smb1req == NULL) {
3237 return NT_STATUS_NO_MEMORY;
3239 req->smb1req->unread_bytes =
3240 state->pktlen - SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3243 ZERO_STRUCTP(state);
3245 req->current_idx = 1;
3247 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3248 req->current_idx, req->in.vector_count));
3250 status = smbd_smb2_request_validate(req);
3251 if (!NT_STATUS_IS_OK(status)) {
3255 status = smbd_smb2_request_setup_out(req);
3256 if (!NT_STATUS_IS_OK(status)) {
3260 status = smbd_smb2_request_dispatch(req);
3261 if (!NT_STATUS_IS_OK(status)) {
3265 sconn->num_requests++;
3267 /* The timeout_processing function isn't run nearly
3268 often enough to implement 'max log size' without
3269 overrunning the size of the file by many megabytes.
3270 This is especially true if we are running at debug
3271 level 10. Checking every 50 SMB2s is a nice
3272 tradeoff of performance vs log file size overrun. */
3274 if ((sconn->num_requests % 50) == 0 &&
3275 need_to_check_log_size()) {
3276 change_to_root_user();
3280 status = smbd_smb2_request_next_incoming(sconn);
3281 if (!NT_STATUS_IS_OK(status)) {
3285 return NT_STATUS_OK;
3288 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3289 struct tevent_fd *fde,
3293 struct smbd_server_connection *sconn =
3294 talloc_get_type_abort(private_data,
3295 struct smbd_server_connection);
3298 status = smbd_smb2_io_handler(sconn, flags);
3299 if (!NT_STATUS_IS_OK(status)) {
3300 smbd_server_connection_terminate(sconn, nt_errstr(status));