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_flush_send_queue(struct smbd_server_connection *sconn);
39 static const struct smbd_smb2_dispatch_table {
46 bool allow_invalid_fileid;
47 } smbd_smb2_table[] = {
48 #define _OP(o) .opcode = o, .name = #o
53 _OP(SMB2_OP_SESSSETUP),
63 * This call needs to be run as root.
65 * smbd_smb2_request_process_tcon()
66 * calls make_connection_snum(), which will call
67 * change_to_user(), when needed.
101 .need_session = true,
106 .need_session = true,
109 .allow_invalid_fileid = true,
114 _OP(SMB2_OP_KEEPALIVE),
118 .need_session = true,
123 .need_session = true,
127 _OP(SMB2_OP_GETINFO),
128 .need_session = true,
132 _OP(SMB2_OP_SETINFO),
133 .need_session = true,
138 .need_session = true,
143 * as LEASE breaks does not
149 const char *smb2_opcode_name(uint16_t opcode)
151 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
152 return "Bad SMB2 opcode";
154 return smbd_smb2_table[opcode].name;
157 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
159 const struct smbd_smb2_dispatch_table *ret = NULL;
161 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
165 ret = &smbd_smb2_table[opcode];
167 SMB_ASSERT(ret->opcode == opcode);
172 static void print_req_vectors(const struct smbd_smb2_request *req)
176 for (i = 0; i < req->in.vector_count; i++) {
177 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
179 (unsigned int)req->in.vector[i].iov_len);
181 for (i = 0; i < req->out.vector_count; i++) {
182 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
184 (unsigned int)req->out.vector[i].iov_len);
188 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
190 if (size < (4 + SMB2_HDR_BODY)) {
194 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
201 static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
203 struct smbXsrv_connection *xconn = sconn->conn;
205 TALLOC_FREE(xconn->transport.fde);
207 xconn->smb2.credits.seq_low = 0;
208 xconn->smb2.credits.seq_range = 1;
209 xconn->smb2.credits.granted = 1;
210 xconn->smb2.credits.max = lp_smb2_max_credits();
211 xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
212 xconn->smb2.credits.max);
213 if (xconn->smb2.credits.bitmap == NULL) {
214 return NT_STATUS_NO_MEMORY;
217 xconn->transport.fde = tevent_add_fd(xconn->ev_ctx,
219 xconn->transport.sock,
221 smbd_smb2_connection_handler,
223 if (xconn->transport.fde == NULL) {
224 return NT_STATUS_NO_MEMORY;
227 /* Ensure child is set to non-blocking mode */
228 set_blocking(xconn->transport.sock, false);
232 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
233 #define _smb2_setlen(_buf,len) do { \
234 uint8_t *buf = (uint8_t *)_buf; \
236 buf[1] = ((len)&0xFF0000)>>16; \
237 buf[2] = ((len)&0xFF00)>>8; \
238 buf[3] = (len)&0xFF; \
241 static void smb2_setup_nbt_length(struct iovec *vector, int count)
246 for (i=1; i < count; i++) {
247 len += vector[i].iov_len;
250 _smb2_setlen(vector[0].iov_base, len);
253 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
255 if (req->first_key.length > 0) {
256 data_blob_clear_free(&req->first_key);
258 if (req->last_key.length > 0) {
259 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_tos();
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);
286 TALLOC_FREE(mem_pool);
289 req->last_session_id = UINT64_MAX;
290 req->last_tid = UINT32_MAX;
292 talloc_set_destructor(req, smbd_smb2_request_destructor);
297 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
301 struct smbd_smb2_request *req,
305 TALLOC_CTX *mem_ctx = req;
309 uint8_t *first_hdr = buf;
310 size_t verified_buflen = 0;
315 * Note: index '0' is reserved for the transport protocol
317 iov = req->in._vector;
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_alloc = NULL;
331 if (iov != req->in._vector) {
335 if (verified_buflen > taken) {
336 len = verified_buflen - taken;
343 DEBUG(10, ("%d bytes left, expected at least %d\n",
347 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
348 struct smbXsrv_session *s = NULL;
350 struct iovec tf_iov[2];
354 if (xconn->protocol < PROTOCOL_SMB2_24) {
355 DEBUG(10, ("Got SMB2_TRANSFORM header, "
356 "but dialect[0x%04X] is used\n",
357 xconn->smb2.server.dialect));
361 if (!(xconn->smb2.server.capabilities & SMB2_CAP_ENCRYPTION)) {
362 DEBUG(10, ("Got SMB2_TRANSFORM header, "
363 "but not negotiated "
364 "client[0x%08X] server[0x%08X]\n",
365 xconn->smb2.client.capabilities,
366 xconn->smb2.server.capabilities));
370 if (len < SMB2_TF_HDR_SIZE) {
371 DEBUG(1, ("%d bytes left, expected at least %d\n",
372 (int)len, SMB2_TF_HDR_SIZE));
376 tf_len = SMB2_TF_HDR_SIZE;
379 hdr = first_hdr + taken;
380 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
381 uid = BVAL(tf, SMB2_TF_SESSION_ID);
383 if (len < SMB2_TF_HDR_SIZE + enc_len) {
384 DEBUG(1, ("%d bytes left, expected at least %d\n",
386 (int)(SMB2_TF_HDR_SIZE + enc_len)));
390 status = smb2srv_session_lookup(xconn, uid, now, &s);
392 DEBUG(1, ("invalid session[%llu] in "
393 "SMB2_TRANSFORM header\n",
394 (unsigned long long)uid));
395 TALLOC_FREE(iov_alloc);
396 return NT_STATUS_USER_SESSION_DELETED;
399 tf_iov[0].iov_base = (void *)tf;
400 tf_iov[0].iov_len = tf_len;
401 tf_iov[1].iov_base = (void *)hdr;
402 tf_iov[1].iov_len = enc_len;
404 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
407 if (!NT_STATUS_IS_OK(status)) {
408 TALLOC_FREE(iov_alloc);
412 verified_buflen = taken + enc_len;
417 * We need the header plus the body length field
420 if (len < SMB2_HDR_BODY + 2) {
421 DEBUG(10, ("%d bytes left, expected at least %d\n",
422 (int)len, SMB2_HDR_BODY));
425 if (IVAL(hdr, 0) != SMB2_MAGIC) {
426 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
430 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
431 DEBUG(10, ("Got HDR len %d, expected %d\n",
432 SVAL(hdr, 4), SMB2_HDR_BODY));
437 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
438 body_size = SVAL(hdr, SMB2_HDR_BODY);
440 if (next_command_ofs != 0) {
441 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
444 if (next_command_ofs > full_size) {
447 full_size = next_command_ofs;
454 if (body_size > (full_size - SMB2_HDR_BODY)) {
456 * let the caller handle the error
458 body_size = full_size - SMB2_HDR_BODY;
460 body = hdr + SMB2_HDR_BODY;
461 dyn = body + body_size;
462 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
464 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
465 struct iovec *iov_tmp = NULL;
467 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
470 SMBD_SMB2_NUM_IOV_PER_REQ);
471 if (iov_tmp == NULL) {
472 TALLOC_FREE(iov_alloc);
473 return NT_STATUS_NO_MEMORY;
476 if (iov_alloc == NULL) {
479 sizeof(req->in._vector));
485 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
487 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
488 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
489 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
490 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
491 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
492 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
493 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
494 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
504 if (iov != req->in._vector) {
507 return NT_STATUS_INVALID_PARAMETER;
510 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
511 uint8_t *inbuf, size_t size,
512 struct smbd_smb2_request **_req)
514 struct smbXsrv_connection *xconn = sconn->conn;
515 struct smbd_smb2_request *req;
516 uint32_t protocol_version;
517 const uint8_t *inhdr = NULL;
519 uint32_t next_command_ofs;
523 if (size < (4 + SMB2_HDR_BODY + 2)) {
524 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
525 return NT_STATUS_INVALID_PARAMETER;
530 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
531 if (protocol_version != SMB2_MAGIC) {
532 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
534 return NT_STATUS_INVALID_PARAMETER;
537 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
538 if (cmd != SMB2_OP_NEGPROT) {
539 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
541 return NT_STATUS_INVALID_PARAMETER;
544 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
545 if (next_command_ofs != 0) {
546 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
548 return NT_STATUS_INVALID_PARAMETER;
551 req = smbd_smb2_request_allocate(xconn);
553 return NT_STATUS_NO_MEMORY;
558 talloc_steal(req, inbuf);
560 req->request_time = timeval_current();
561 now = timeval_to_nttime(&req->request_time);
563 status = smbd_smb2_inbuf_parse_compound(sconn->conn,
565 inbuf + NBT_HDR_SIZE,
567 req, &req->in.vector,
568 &req->in.vector_count);
569 if (!NT_STATUS_IS_OK(status)) {
574 req->current_idx = 1;
580 static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
581 uint64_t message_id, uint64_t seq_id)
583 struct smbXsrv_connection *xconn = sconn->conn;
584 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
588 seq_tmp = xconn->smb2.credits.seq_low;
589 if (seq_id < seq_tmp) {
590 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
591 "%llu (sequence id %llu) "
592 "(granted = %u, low = %llu, range = %u)\n",
593 (unsigned long long)message_id,
594 (unsigned long long)seq_id,
595 (unsigned int)xconn->smb2.credits.granted,
596 (unsigned long long)xconn->smb2.credits.seq_low,
597 (unsigned int)xconn->smb2.credits.seq_range));
601 seq_tmp += xconn->smb2.credits.seq_range;
602 if (seq_id >= seq_tmp) {
603 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
604 "%llu (sequence id %llu) "
605 "(granted = %u, low = %llu, range = %u)\n",
606 (unsigned long long)message_id,
607 (unsigned long long)seq_id,
608 (unsigned int)xconn->smb2.credits.granted,
609 (unsigned long long)xconn->smb2.credits.seq_low,
610 (unsigned int)xconn->smb2.credits.seq_range));
614 offset = seq_id % xconn->smb2.credits.max;
616 if (bitmap_query(credits_bm, offset)) {
617 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
618 "%llu (sequence id %llu) "
619 "(granted = %u, low = %llu, range = %u) "
621 (unsigned long long)message_id,
622 (unsigned long long)seq_id,
623 (unsigned int)xconn->smb2.credits.granted,
624 (unsigned long long)xconn->smb2.credits.seq_low,
625 (unsigned int)xconn->smb2.credits.seq_range,
630 /* Mark the message_ids as seen in the bitmap. */
631 bitmap_set(credits_bm, offset);
633 if (seq_id != xconn->smb2.credits.seq_low) {
638 * Move the window forward by all the message_id's
641 while (bitmap_query(credits_bm, offset)) {
642 DEBUG(10,("smb2_validate_sequence_number: clearing "
643 "id %llu (position %u) from bitmap\n",
644 (unsigned long long)(xconn->smb2.credits.seq_low),
646 bitmap_clear(credits_bm, offset);
648 xconn->smb2.credits.seq_low += 1;
649 xconn->smb2.credits.seq_range -= 1;
650 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
656 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
657 const uint8_t *inhdr)
659 struct smbXsrv_connection *xconn = sconn->conn;
660 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
661 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
662 uint16_t credit_charge = 1;
665 if (opcode == SMB2_OP_CANCEL) {
666 /* SMB2_CANCEL requests by definition resend messageids. */
670 if (xconn->smb2.credits.multicredit) {
671 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
672 credit_charge = MAX(credit_charge, 1);
675 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
676 "credits_granted %llu, "
677 "seqnum low/range: %llu/%llu\n",
678 (unsigned long long) message_id,
679 (unsigned long long) credit_charge,
680 (unsigned long long) xconn->smb2.credits.granted,
681 (unsigned long long) xconn->smb2.credits.seq_low,
682 (unsigned long long) xconn->smb2.credits.seq_range));
684 if (xconn->smb2.credits.granted < credit_charge) {
685 DEBUG(0, ("smb2_validate_message_id: client used more "
686 "credits than granted, mid %llu, charge %llu, "
687 "credits_granted %llu, "
688 "seqnum low/range: %llu/%llu\n",
689 (unsigned long long) message_id,
690 (unsigned long long) credit_charge,
691 (unsigned long long) xconn->smb2.credits.granted,
692 (unsigned long long) xconn->smb2.credits.seq_low,
693 (unsigned long long) xconn->smb2.credits.seq_range));
698 * now check the message ids
700 * for multi-credit requests we need to check all current mid plus
701 * the implicit mids caused by the credit charge
702 * e.g. current mid = 15, charge 5 => mark 15-19 as used
705 for (i = 0; i <= (credit_charge-1); i++) {
706 uint64_t id = message_id + i;
709 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
710 (unsigned long long)message_id,
712 (unsigned long long)id));
714 ok = smb2_validate_sequence_number(sconn, message_id, id);
720 /* substract used credits */
721 xconn->smb2.credits.granted -= credit_charge;
726 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
731 count = req->in.vector_count;
733 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
734 /* It's not a SMB2 request */
735 return NT_STATUS_INVALID_PARAMETER;
738 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
739 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
740 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
741 const uint8_t *inhdr = NULL;
743 if (hdr->iov_len != SMB2_HDR_BODY) {
744 return NT_STATUS_INVALID_PARAMETER;
747 if (body->iov_len < 2) {
748 return NT_STATUS_INVALID_PARAMETER;
751 inhdr = (const uint8_t *)hdr->iov_base;
753 /* Check the SMB2 header */
754 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
755 return NT_STATUS_INVALID_PARAMETER;
758 if (!smb2_validate_message_id(req->sconn, inhdr)) {
759 return NT_STATUS_INVALID_PARAMETER;
766 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
767 const struct iovec *in_vector,
768 struct iovec *out_vector)
770 struct smbXsrv_connection *xconn = sconn->conn;
771 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
772 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
773 uint16_t credit_charge = 1;
774 uint16_t credits_requested;
778 uint16_t credits_granted = 0;
779 uint64_t credits_possible;
780 uint16_t current_max_credits;
783 * first we grant only 1/16th of the max range.
785 * Windows also starts with the 1/16th and then grants
786 * more later. I was only able to trigger higher
787 * values, when using a very high credit charge.
789 * TODO: scale up depending on load, free memory
791 * Maybe also on the relationship between number
792 * of requests and the used sequence number.
793 * Which means we would grant more credits
794 * for client which use multi credit requests.
796 current_max_credits = xconn->smb2.credits.max / 16;
797 current_max_credits = MAX(current_max_credits, 1);
799 if (xconn->smb2.credits.multicredit) {
800 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
801 credit_charge = MAX(credit_charge, 1);
804 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
805 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
806 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
807 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
809 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
811 if (xconn->smb2.credits.max < credit_charge) {
812 smbd_server_connection_terminate(sconn,
813 "client error: credit charge > max credits\n");
817 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
819 * In case we already send an async interim
820 * response, we should not grant
821 * credits on the final response.
824 } else if (credits_requested > 0) {
825 uint16_t additional_max = 0;
826 uint16_t additional_credits = credits_requested - 1;
829 case SMB2_OP_NEGPROT:
831 case SMB2_OP_SESSSETUP:
833 * Windows 2012 RC1 starts to grant
835 * with a successful session setup
837 if (NT_STATUS_IS_OK(out_status)) {
843 * We match windows and only grant additional credits
850 additional_credits = MIN(additional_credits, additional_max);
852 credits_granted = credit_charge + additional_credits;
853 } else if (xconn->smb2.credits.granted == 0) {
855 * Make sure the client has always at least one credit
861 * sequence numbers should not wrap
863 * 1. calculate the possible credits until
864 * the sequence numbers start to wrap on 64-bit.
866 * 2. UINT64_MAX is used for Break Notifications.
868 * 2. truncate the possible credits to the maximum
869 * credits we want to grant to the client in total.
871 * 3. remove the range we'll already granted to the client
872 * this makes sure the client consumes the lowest sequence
873 * number, before we can grant additional credits.
875 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
876 if (credits_possible > 0) {
877 /* remove UINT64_MAX */
878 credits_possible -= 1;
880 credits_possible = MIN(credits_possible, current_max_credits);
881 credits_possible -= xconn->smb2.credits.seq_range;
883 credits_granted = MIN(credits_granted, credits_possible);
885 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
886 xconn->smb2.credits.granted += credits_granted;
887 xconn->smb2.credits.seq_range += credits_granted;
889 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
890 "granted %u, current possible/max %u/%u, "
891 "total granted/max/low/range %u/%u/%llu/%u\n",
892 (unsigned int)credits_requested,
893 (unsigned int)credit_charge,
894 (unsigned int)credits_granted,
895 (unsigned int)credits_possible,
896 (unsigned int)current_max_credits,
897 (unsigned int)xconn->smb2.credits.granted,
898 (unsigned int)xconn->smb2.credits.max,
899 (unsigned long long)xconn->smb2.credits.seq_low,
900 (unsigned int)xconn->smb2.credits.seq_range));
903 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
904 struct smbd_smb2_request *outreq)
907 uint16_t total_credits = 0;
909 count = outreq->out.vector_count;
911 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
912 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
913 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
914 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
916 smb2_set_operation_credit(outreq->sconn, inhdr_v, outhdr_v);
918 /* To match Windows, count up what we
920 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
921 /* Set to zero in all but the last reply. */
922 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
923 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
925 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
930 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
932 if (req->current_idx <= 1) {
933 if (size <= sizeof(req->out._body)) {
934 return data_blob_const(req->out._body, size);
938 return data_blob_talloc(req, NULL, size);
941 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
943 struct smbXsrv_connection *xconn = req->sconn->conn;
945 struct iovec *vector;
949 count = req->in.vector_count;
950 if (count <= ARRAY_SIZE(req->out._vector)) {
952 vector = req->out._vector;
954 vector = talloc_zero_array(req, struct iovec, count);
955 if (vector == NULL) {
956 return NT_STATUS_NO_MEMORY;
961 vector[0].iov_base = req->out.nbt_hdr;
962 vector[0].iov_len = 4;
963 SIVAL(req->out.nbt_hdr, 0, 0);
965 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
966 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
967 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
968 uint8_t *outhdr = NULL;
969 uint8_t *outbody = NULL;
970 uint32_t next_command_ofs = 0;
971 struct iovec *current = &vector[idx];
973 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
974 /* we have a next command -
975 * setup for the error case. */
976 next_command_ofs = SMB2_HDR_BODY + 9;
980 outhdr = req->out._hdr;
982 outhdr = talloc_zero_array(mem_ctx, uint8_t,
984 if (outhdr == NULL) {
985 return NT_STATUS_NO_MEMORY;
989 outbody = outhdr + SMB2_HDR_BODY;
992 * SMBD_SMB2_TF_IOV_OFS might be used later
994 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
995 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
997 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
998 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1000 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1001 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1003 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1004 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1006 /* setup the SMB2 header */
1007 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1008 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1009 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1010 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1011 SIVAL(outhdr, SMB2_HDR_STATUS,
1012 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1013 SSVAL(outhdr, SMB2_HDR_OPCODE,
1014 SVAL(inhdr, SMB2_HDR_OPCODE));
1015 SIVAL(outhdr, SMB2_HDR_FLAGS,
1016 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1017 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1018 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1019 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1020 SIVAL(outhdr, SMB2_HDR_PID,
1021 IVAL(inhdr, SMB2_HDR_PID));
1022 SIVAL(outhdr, SMB2_HDR_TID,
1023 IVAL(inhdr, SMB2_HDR_TID));
1024 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1025 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1026 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1027 inhdr + SMB2_HDR_SIGNATURE, 16);
1029 /* setup error body header */
1030 SSVAL(outbody, 0x00, 0x08 + 1);
1031 SSVAL(outbody, 0x02, 0);
1032 SIVAL(outbody, 0x04, 0);
1035 req->out.vector = vector;
1036 req->out.vector_count = count;
1038 /* setup the length of the NBT packet */
1039 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1041 DLIST_ADD_END(xconn->smb2.requests, req, struct smbd_smb2_request *);
1043 return NT_STATUS_OK;
1046 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
1048 const char *location)
1050 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1052 exit_server_cleanly(reason);
1055 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1056 struct iovec *outvec,
1057 const struct iovec *srcvec)
1059 const uint8_t *srctf;
1061 const uint8_t *srchdr;
1063 const uint8_t *srcbody;
1065 const uint8_t *expected_srcbody;
1066 const uint8_t *srcdyn;
1068 const uint8_t *expected_srcdyn;
1074 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1075 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1076 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1077 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1078 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1079 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1080 expected_srcbody = srchdr + SMB2_HDR_BODY;
1081 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1082 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1083 expected_srcdyn = srcbody + 8;
1085 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1089 if (srchdr_len != SMB2_HDR_BODY) {
1093 if (srctf_len == SMB2_TF_HDR_SIZE) {
1094 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1095 if (dsttf == NULL) {
1101 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1102 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1104 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1105 * be allocated with size OUTVEC_ALLOC_SIZE. */
1107 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1108 if (dsthdr == NULL) {
1111 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1112 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1115 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1116 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1117 * then duplicate this. Else use talloc_memdup().
1120 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1121 dstbody = dsthdr + SMB2_HDR_BODY;
1123 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1124 if (dstbody == NULL) {
1128 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1129 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1132 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1134 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1135 * then duplicate this. Else use talloc_memdup().
1138 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1139 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1140 } else if (srcdyn == NULL) {
1143 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1144 if (dstdyn == NULL) {
1148 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1149 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1154 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1156 struct smbd_smb2_request *newreq = NULL;
1157 struct iovec *outvec = NULL;
1158 int count = req->out.vector_count;
1161 newreq = smbd_smb2_request_allocate(req->xconn);
1166 newreq->sconn = req->sconn;
1167 newreq->xconn = req->xconn;
1168 newreq->session = req->session;
1169 newreq->do_encryption = req->do_encryption;
1170 newreq->do_signing = req->do_signing;
1171 newreq->current_idx = req->current_idx;
1173 outvec = talloc_zero_array(newreq, struct iovec, count);
1175 TALLOC_FREE(newreq);
1178 newreq->out.vector = outvec;
1179 newreq->out.vector_count = count;
1181 /* Setup the outvec's identically to req. */
1182 outvec[0].iov_base = newreq->out.nbt_hdr;
1183 outvec[0].iov_len = 4;
1184 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1186 /* Setup the vectors identically to the ones in req. */
1187 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1188 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1195 TALLOC_FREE(newreq);
1199 smb2_setup_nbt_length(newreq->out.vector,
1200 newreq->out.vector_count);
1205 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1207 struct smbd_server_connection *sconn = req->sconn;
1208 struct smbXsrv_connection *xconn = req->sconn->conn;
1210 struct iovec *firsttf = NULL;
1211 struct iovec *outhdr_v = NULL;
1212 uint8_t *outhdr = NULL;
1213 struct smbd_smb2_request *nreq = NULL;
1216 /* Create a new smb2 request we'll use
1217 for the interim return. */
1218 nreq = dup_smb2_req(req);
1220 return NT_STATUS_NO_MEMORY;
1223 /* Lose the last X out vectors. They're the
1224 ones we'll be using for the async reply. */
1225 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1227 smb2_setup_nbt_length(nreq->out.vector,
1228 nreq->out.vector_count);
1230 /* Step back to the previous reply. */
1231 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1232 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1233 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1234 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1235 /* And end the chain. */
1236 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1238 /* Calculate outgoing credits */
1239 smb2_calculate_credits(req, nreq);
1241 if (DEBUGLEVEL >= 10) {
1242 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1243 (unsigned int)nreq->current_idx );
1244 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1245 (unsigned int)nreq->out.vector_count );
1246 print_req_vectors(nreq);
1250 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1251 * we need to sign/encrypt here with the last/first key we remembered
1253 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1254 status = smb2_signing_encrypt_pdu(req->first_key,
1257 nreq->out.vector_count - first_idx);
1258 if (!NT_STATUS_IS_OK(status)) {
1261 } else if (req->last_key.length > 0) {
1262 status = smb2_signing_sign_pdu(req->last_key,
1265 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1266 if (!NT_STATUS_IS_OK(status)) {
1271 nreq->queue_entry.mem_ctx = nreq;
1272 nreq->queue_entry.vector = nreq->out.vector;
1273 nreq->queue_entry.count = nreq->out.vector_count;
1274 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry, NULL);
1275 xconn->smb2.send_queue_len++;
1277 status = smbd_smb2_flush_send_queue(sconn);
1278 if (!NT_STATUS_IS_OK(status)) {
1282 return NT_STATUS_OK;
1285 struct smbd_smb2_request_pending_state {
1286 struct smbd_server_connection *sconn;
1287 struct smbd_smb2_send_queue queue_entry;
1288 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1289 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1292 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1293 struct tevent_timer *te,
1294 struct timeval current_time,
1295 void *private_data);
1297 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1298 struct tevent_req *subreq,
1299 uint32_t defer_time)
1302 struct timeval defer_endtime;
1303 uint8_t *outhdr = NULL;
1306 if (!tevent_req_is_in_progress(subreq)) {
1308 * This is a performance optimization,
1309 * it avoids one tevent_loop iteration,
1310 * which means we avoid one
1311 * talloc_stackframe_pool/talloc_free pair.
1313 tevent_req_notify_callback(subreq);
1314 return NT_STATUS_OK;
1317 req->subreq = subreq;
1320 if (req->async_te) {
1321 /* We're already async. */
1322 return NT_STATUS_OK;
1325 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1326 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1327 if (flags & SMB2_HDR_FLAG_ASYNC) {
1328 /* We're already async. */
1329 return NT_STATUS_OK;
1332 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1334 * We're trying to go async in a compound
1336 * This is only allowed for opens that
1337 * cause an oplock break, otherwise it
1338 * is not allowed. See [MS-SMB2].pdf
1339 * note <194> on Section 3.3.5.2.7.
1341 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1343 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1345 * Cancel the outstanding request.
1347 bool ok = tevent_req_cancel(req->subreq);
1349 return NT_STATUS_OK;
1351 TALLOC_FREE(req->subreq);
1352 return smbd_smb2_request_error(req,
1353 NT_STATUS_INTERNAL_ERROR);
1357 if (DEBUGLEVEL >= 10) {
1358 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1359 (unsigned int)req->current_idx );
1360 print_req_vectors(req);
1363 if (req->current_idx > 1) {
1365 * We're going async in a compound
1366 * chain after the first request has
1367 * already been processed. Send an
1368 * interim response containing the
1369 * set of replies already generated.
1371 int idx = req->current_idx;
1373 status = smb2_send_async_interim_response(req);
1374 if (!NT_STATUS_IS_OK(status)) {
1377 if (req->first_key.length > 0) {
1378 data_blob_clear_free(&req->first_key);
1381 req->current_idx = 1;
1384 * Re-arrange the in.vectors to remove what
1387 memmove(&req->in.vector[1],
1388 &req->in.vector[idx],
1389 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1390 req->in.vector_count = 1 + (req->in.vector_count - idx);
1392 /* Re-arrange the out.vectors to match. */
1393 memmove(&req->out.vector[1],
1394 &req->out.vector[idx],
1395 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1396 req->out.vector_count = 1 + (req->out.vector_count - idx);
1398 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1400 * We only have one remaining request as
1401 * we've processed everything else.
1402 * This is no longer a compound request.
1404 req->compound_related = false;
1405 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1406 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1407 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1410 if (req->last_key.length > 0) {
1411 data_blob_clear_free(&req->last_key);
1414 defer_endtime = timeval_current_ofs_usec(defer_time);
1415 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1417 smbd_smb2_request_pending_timer,
1419 if (req->async_te == NULL) {
1420 return NT_STATUS_NO_MEMORY;
1423 return NT_STATUS_OK;
1426 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1427 struct tevent_timer *te,
1428 struct timeval current_time,
1431 struct smbd_smb2_request *req =
1432 talloc_get_type_abort(private_data,
1433 struct smbd_smb2_request);
1434 struct smbd_server_connection *sconn = req->sconn;
1435 struct smbXsrv_connection *xconn = sconn->conn;
1436 struct smbd_smb2_request_pending_state *state = NULL;
1437 uint8_t *outhdr = NULL;
1438 const uint8_t *inhdr = NULL;
1441 uint8_t *hdr = NULL;
1442 uint8_t *body = NULL;
1443 uint8_t *dyn = NULL;
1445 uint64_t session_id = 0;
1446 uint64_t message_id = 0;
1447 uint64_t nonce_high = 0;
1448 uint64_t nonce_low = 0;
1449 uint64_t async_id = 0;
1452 TALLOC_FREE(req->async_te);
1454 /* Ensure our final reply matches the interim one. */
1455 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1456 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1457 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1458 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1459 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1461 async_id = message_id; /* keep it simple for now... */
1463 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1464 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1466 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1468 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1469 (unsigned long long)async_id ));
1472 * What we send is identical to a smbd_smb2_request_error
1473 * packet with an error status of STATUS_PENDING. Make use
1474 * of this fact sometime when refactoring. JRA.
1477 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1478 if (state == NULL) {
1479 smbd_server_connection_terminate(req->sconn,
1480 nt_errstr(NT_STATUS_NO_MEMORY));
1483 state->sconn = req->sconn;
1485 tf = state->buf + NBT_HDR_SIZE;
1486 tf_len = SMB2_TF_HDR_SIZE;
1488 hdr = tf + SMB2_TF_HDR_SIZE;
1489 body = hdr + SMB2_HDR_BODY;
1492 if (req->do_encryption) {
1493 struct smbXsrv_session *x = req->session;
1495 nonce_high = x->nonce_high;
1496 nonce_low = x->nonce_low;
1499 if (x->nonce_low == 0) {
1505 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1506 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1507 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1508 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1510 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1511 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1512 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1513 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1514 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1516 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1517 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1518 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1519 SBVAL(hdr, SMB2_HDR_PID, async_id);
1520 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1521 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1522 memcpy(hdr+SMB2_HDR_SIGNATURE,
1523 outhdr+SMB2_HDR_SIGNATURE, 16);
1525 SSVAL(body, 0x00, 0x08 + 1);
1527 SCVAL(body, 0x02, 0);
1528 SCVAL(body, 0x03, 0);
1529 SIVAL(body, 0x04, 0);
1530 /* Match W2K8R2... */
1531 SCVAL(dyn, 0x00, 0x21);
1533 state->vector[0].iov_base = (void *)state->buf;
1534 state->vector[0].iov_len = NBT_HDR_SIZE;
1536 if (req->do_encryption) {
1537 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1538 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1540 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1541 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1544 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1545 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1547 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1548 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1550 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1551 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1553 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1555 /* Ensure we correctly go through crediting. Grant
1556 the credits now, and zero credits on the final
1558 smb2_set_operation_credit(req->sconn,
1559 SMBD_SMB2_IN_HDR_IOV(req),
1560 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1562 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1567 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1568 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1570 (unsigned int)ARRAY_SIZE(state->vector),
1571 (unsigned int)state->vector[i].iov_len);
1575 if (req->do_encryption) {
1576 struct smbXsrv_session *x = req->session;
1577 DATA_BLOB encryption_key = x->global->encryption_key;
1579 status = smb2_signing_encrypt_pdu(encryption_key,
1581 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1582 SMBD_SMB2_NUM_IOV_PER_REQ);
1583 if (!NT_STATUS_IS_OK(status)) {
1584 smbd_server_connection_terminate(req->sconn,
1588 } else if (req->do_signing) {
1589 struct smbXsrv_session *x = req->session;
1590 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1592 status = smb2_signing_sign_pdu(signing_key,
1594 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1595 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1596 if (!NT_STATUS_IS_OK(status)) {
1597 smbd_server_connection_terminate(req->sconn,
1603 state->queue_entry.mem_ctx = state;
1604 state->queue_entry.vector = state->vector;
1605 state->queue_entry.count = ARRAY_SIZE(state->vector);
1606 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
1607 xconn->smb2.send_queue_len++;
1609 status = smbd_smb2_flush_send_queue(sconn);
1610 if (!NT_STATUS_IS_OK(status)) {
1611 smbd_server_connection_terminate(sconn,
1617 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1619 struct smbd_server_connection *sconn = req->sconn;
1620 struct smbXsrv_connection *xconn = sconn->conn;
1621 struct smbd_smb2_request *cur;
1622 const uint8_t *inhdr;
1624 uint64_t search_message_id;
1625 uint64_t search_async_id;
1628 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1630 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1631 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1632 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1635 * we don't need the request anymore
1636 * cancel requests never have a response
1638 DLIST_REMOVE(xconn->smb2.requests, req);
1641 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1642 const uint8_t *outhdr;
1643 uint64_t message_id;
1646 if (cur->compound_related) {
1648 * Never cancel anything in a compound request.
1649 * Way too hard to deal with the result.
1654 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1656 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1657 async_id = BVAL(outhdr, SMB2_HDR_PID);
1659 if (flags & SMB2_HDR_FLAG_ASYNC) {
1660 if (search_async_id == async_id) {
1661 found_id = async_id;
1665 if (search_message_id == message_id) {
1666 found_id = message_id;
1672 if (cur && cur->subreq) {
1673 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1674 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1675 "cancel opcode[%s] mid %llu\n",
1676 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1677 (unsigned long long)found_id ));
1678 tevent_req_cancel(cur->subreq);
1681 return NT_STATUS_OK;
1684 /*************************************************************
1685 Ensure an incoming tid is a valid one for us to access.
1686 Change to the associated uid credentials and chdir to the
1687 valid tid directory.
1688 *************************************************************/
1690 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1692 const uint8_t *inhdr;
1695 struct smbXsrv_tcon *tcon;
1697 NTTIME now = timeval_to_nttime(&req->request_time);
1701 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1703 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1704 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1706 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1707 in_tid = req->last_tid;
1712 status = smb2srv_tcon_lookup(req->session,
1713 in_tid, now, &tcon);
1714 if (!NT_STATUS_IS_OK(status)) {
1718 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1719 return NT_STATUS_ACCESS_DENIED;
1722 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1723 if (!set_current_service(tcon->compat, 0, true)) {
1724 return NT_STATUS_ACCESS_DENIED;
1728 req->last_tid = in_tid;
1730 return NT_STATUS_OK;
1733 /*************************************************************
1734 Ensure an incoming session_id is a valid one for us to access.
1735 *************************************************************/
1737 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1739 const uint8_t *inhdr;
1742 uint64_t in_session_id;
1743 struct smbXsrv_session *session = NULL;
1744 struct auth_session_info *session_info;
1746 NTTIME now = timeval_to_nttime(&req->request_time);
1748 req->session = NULL;
1751 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1753 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1754 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1755 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1757 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1758 in_session_id = req->last_session_id;
1761 req->last_session_id = 0;
1763 /* lookup an existing session */
1764 status = smb2srv_session_lookup(req->sconn->conn,
1768 req->session = session;
1769 req->last_session_id = in_session_id;
1771 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1772 switch (in_opcode) {
1773 case SMB2_OP_SESSSETUP:
1774 status = NT_STATUS_OK;
1780 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1781 switch (in_opcode) {
1783 case SMB2_OP_CREATE:
1784 case SMB2_OP_GETINFO:
1785 case SMB2_OP_SETINFO:
1786 return NT_STATUS_INVALID_HANDLE;
1789 * Notice the check for
1790 * (session_info == NULL)
1793 status = NT_STATUS_OK;
1797 if (!NT_STATUS_IS_OK(status)) {
1801 session_info = session->global->auth_session_info;
1802 if (session_info == NULL) {
1803 return NT_STATUS_INVALID_HANDLE;
1806 if (in_session_id != req->sconn->conn->last_session_id) {
1807 req->sconn->conn->last_session_id = in_session_id;
1808 set_current_user_info(session_info->unix_info->sanitized_username,
1809 session_info->unix_info->unix_name,
1810 session_info->info->domain_name);
1813 return NT_STATUS_OK;
1816 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1817 uint32_t data_length)
1819 struct smbXsrv_connection *xconn = req->sconn->conn;
1820 uint16_t needed_charge;
1821 uint16_t credit_charge = 1;
1822 const uint8_t *inhdr;
1824 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1826 if (xconn->smb2.credits.multicredit) {
1827 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1828 credit_charge = MAX(credit_charge, 1);
1831 needed_charge = (data_length - 1)/ 65536 + 1;
1833 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1834 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1835 credit_charge, needed_charge));
1837 if (needed_charge > credit_charge) {
1838 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1839 credit_charge, needed_charge));
1840 return NT_STATUS_INVALID_PARAMETER;
1843 return NT_STATUS_OK;
1846 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1847 size_t expected_body_size)
1849 struct iovec *inhdr_v;
1850 const uint8_t *inhdr;
1852 const uint8_t *inbody;
1854 size_t min_dyn_size = expected_body_size & 0x00000001;
1855 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1858 * The following should be checked already.
1860 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1861 return NT_STATUS_INTERNAL_ERROR;
1863 if (req->current_idx > max_idx) {
1864 return NT_STATUS_INTERNAL_ERROR;
1867 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1868 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1869 return NT_STATUS_INTERNAL_ERROR;
1871 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1872 return NT_STATUS_INTERNAL_ERROR;
1875 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1876 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1880 case SMB2_OP_GETINFO:
1884 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
1885 if (req->smb1req->unread_bytes < min_dyn_size) {
1886 return NT_STATUS_INVALID_PARAMETER;
1895 * Now check the expected body size,
1896 * where the last byte might be in the
1899 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1900 return NT_STATUS_INVALID_PARAMETER;
1902 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1903 return NT_STATUS_INVALID_PARAMETER;
1906 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1908 body_size = SVAL(inbody, 0x00);
1909 if (body_size != expected_body_size) {
1910 return NT_STATUS_INVALID_PARAMETER;
1913 return NT_STATUS_OK;
1916 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1918 struct smbXsrv_connection *xconn = req->sconn->conn;
1919 const struct smbd_smb2_dispatch_table *call = NULL;
1920 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1921 const uint8_t *inhdr;
1926 NTSTATUS session_status;
1927 uint32_t allowed_flags;
1928 NTSTATUS return_value;
1929 struct smbXsrv_session *x = NULL;
1930 bool signing_required = false;
1931 bool encryption_required = false;
1933 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1935 /* TODO: verify more things */
1937 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1938 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1939 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1940 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1941 smb2_opcode_name(opcode),
1942 (unsigned long long)mid));
1944 if (xconn->protocol >= PROTOCOL_SMB2_02) {
1946 * once the protocol is negotiated
1947 * SMB2_OP_NEGPROT is not allowed anymore
1949 if (opcode == SMB2_OP_NEGPROT) {
1950 /* drop the connection */
1951 return NT_STATUS_INVALID_PARAMETER;
1955 * if the protocol is not negotiated yet
1956 * only SMB2_OP_NEGPROT is allowed.
1958 if (opcode != SMB2_OP_NEGPROT) {
1959 /* drop the connection */
1960 return NT_STATUS_INVALID_PARAMETER;
1965 * Check if the client provided a valid session id,
1966 * if so smbd_smb2_request_check_session() calls
1967 * set_current_user_info().
1969 * As some command don't require a valid session id
1970 * we defer the check of the session_status
1972 session_status = smbd_smb2_request_check_session(req);
1975 signing_required = x->global->signing_required;
1976 encryption_required = x->global->encryption_required;
1978 if (opcode == SMB2_OP_SESSSETUP &&
1979 x->global->channels[0].signing_key.length) {
1980 signing_required = true;
1984 req->do_signing = false;
1985 req->do_encryption = false;
1986 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
1987 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
1988 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
1990 if (x != NULL && x->global->session_wire_id != tf_session_id) {
1991 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1992 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1993 (unsigned long long)x->global->session_wire_id,
1994 (unsigned long long)tf_session_id));
1996 * TODO: windows allows this...
1997 * should we drop the connection?
1999 * For now we just return ACCESS_DENIED
2000 * (Windows clients never trigger this)
2001 * and wait for an update of [MS-SMB2].
2003 return smbd_smb2_request_error(req,
2004 NT_STATUS_ACCESS_DENIED);
2007 req->do_encryption = true;
2010 if (encryption_required && !req->do_encryption) {
2011 return smbd_smb2_request_error(req,
2012 NT_STATUS_ACCESS_DENIED);
2015 call = smbd_smb2_call(opcode);
2017 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2020 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2021 SMB2_HDR_FLAG_SIGNED |
2023 if (opcode == SMB2_OP_CANCEL) {
2024 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2026 if ((flags & ~allowed_flags) != 0) {
2027 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2030 if (flags & SMB2_HDR_FLAG_CHAINED) {
2032 * This check is mostly for giving the correct error code
2033 * for compounded requests.
2035 if (!NT_STATUS_IS_OK(session_status)) {
2036 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2039 req->compat_chain_fsp = NULL;
2042 if (req->do_encryption) {
2043 signing_required = false;
2044 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2045 DATA_BLOB signing_key;
2049 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2050 * If the SMB2 header of the SMB2 NEGOTIATE
2051 * request has the SMB2_FLAGS_SIGNED bit set in the
2052 * Flags field, the server MUST fail the request
2053 * with STATUS_INVALID_PARAMETER.
2055 * Microsoft test tool checks this.
2058 if ((opcode == SMB2_OP_NEGPROT) &&
2059 (flags & SMB2_HDR_FLAG_SIGNED)) {
2060 status = NT_STATUS_INVALID_PARAMETER;
2062 status = NT_STATUS_USER_SESSION_DELETED;
2064 return smbd_smb2_request_error(req, status);
2067 signing_key = x->global->channels[0].signing_key;
2070 * If we have a signing key, we should
2073 if (signing_key.length > 0) {
2074 req->do_signing = true;
2077 status = smb2_signing_check_pdu(signing_key,
2079 SMBD_SMB2_IN_HDR_IOV(req),
2080 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2081 if (!NT_STATUS_IS_OK(status)) {
2082 return smbd_smb2_request_error(req, status);
2086 * Now that we know the request was correctly signed
2087 * we have to sign the response too.
2089 req->do_signing = true;
2091 if (!NT_STATUS_IS_OK(session_status)) {
2092 return smbd_smb2_request_error(req, session_status);
2094 } else if (opcode == SMB2_OP_CANCEL) {
2095 /* Cancel requests are allowed to skip the signing */
2096 } else if (signing_required) {
2098 * If signing is required we try to sign
2099 * a possible error response
2101 req->do_signing = true;
2102 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2105 if (flags & SMB2_HDR_FLAG_CHAINED) {
2106 req->compound_related = true;
2109 if (call->need_session) {
2110 if (!NT_STATUS_IS_OK(session_status)) {
2111 return smbd_smb2_request_error(req, session_status);
2115 if (call->need_tcon) {
2116 SMB_ASSERT(call->need_session);
2119 * This call needs to be run as user.
2121 * smbd_smb2_request_check_tcon()
2122 * calls change_to_user() on success.
2124 status = smbd_smb2_request_check_tcon(req);
2125 if (!NT_STATUS_IS_OK(status)) {
2126 return smbd_smb2_request_error(req, status);
2128 if (req->tcon->global->encryption_required) {
2129 encryption_required = true;
2131 if (encryption_required && !req->do_encryption) {
2132 return smbd_smb2_request_error(req,
2133 NT_STATUS_ACCESS_DENIED);
2137 if (call->fileid_ofs != 0) {
2138 size_t needed = call->fileid_ofs + 16;
2139 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2140 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2141 uint64_t file_id_persistent;
2142 uint64_t file_id_volatile;
2143 struct files_struct *fsp;
2145 SMB_ASSERT(call->need_tcon);
2147 if (needed > body_size) {
2148 return smbd_smb2_request_error(req,
2149 NT_STATUS_INVALID_PARAMETER);
2152 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2153 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2155 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2157 if (!call->allow_invalid_fileid) {
2158 return smbd_smb2_request_error(req,
2159 NT_STATUS_FILE_CLOSED);
2162 if (file_id_persistent != UINT64_MAX) {
2163 return smbd_smb2_request_error(req,
2164 NT_STATUS_FILE_CLOSED);
2166 if (file_id_volatile != UINT64_MAX) {
2167 return smbd_smb2_request_error(req,
2168 NT_STATUS_FILE_CLOSED);
2173 if (call->as_root) {
2174 SMB_ASSERT(call->fileid_ofs == 0);
2175 /* This call needs to be run as root */
2176 change_to_root_user();
2178 SMB_ASSERT(call->need_tcon);
2182 case SMB2_OP_NEGPROT:
2184 START_PROFILE(smb2_negprot);
2185 return_value = smbd_smb2_request_process_negprot(req);
2186 END_PROFILE(smb2_negprot);
2190 case SMB2_OP_SESSSETUP:
2192 START_PROFILE(smb2_sesssetup);
2193 return_value = smbd_smb2_request_process_sesssetup(req);
2194 END_PROFILE(smb2_sesssetup);
2198 case SMB2_OP_LOGOFF:
2200 START_PROFILE(smb2_logoff);
2201 return_value = smbd_smb2_request_process_logoff(req);
2202 END_PROFILE(smb2_logoff);
2208 START_PROFILE(smb2_tcon);
2209 return_value = smbd_smb2_request_process_tcon(req);
2210 END_PROFILE(smb2_tcon);
2216 START_PROFILE(smb2_tdis);
2217 return_value = smbd_smb2_request_process_tdis(req);
2218 END_PROFILE(smb2_tdis);
2222 case SMB2_OP_CREATE:
2224 START_PROFILE(smb2_create);
2225 return_value = smbd_smb2_request_process_create(req);
2226 END_PROFILE(smb2_create);
2232 START_PROFILE(smb2_close);
2233 return_value = smbd_smb2_request_process_close(req);
2234 END_PROFILE(smb2_close);
2240 START_PROFILE(smb2_flush);
2241 return_value = smbd_smb2_request_process_flush(req);
2242 END_PROFILE(smb2_flush);
2248 START_PROFILE(smb2_read);
2249 return_value = smbd_smb2_request_process_read(req);
2250 END_PROFILE(smb2_read);
2256 START_PROFILE(smb2_write);
2257 return_value = smbd_smb2_request_process_write(req);
2258 END_PROFILE(smb2_write);
2264 START_PROFILE(smb2_lock);
2265 return_value = smbd_smb2_request_process_lock(req);
2266 END_PROFILE(smb2_lock);
2272 START_PROFILE(smb2_ioctl);
2273 return_value = smbd_smb2_request_process_ioctl(req);
2274 END_PROFILE(smb2_ioctl);
2278 case SMB2_OP_CANCEL:
2280 START_PROFILE(smb2_cancel);
2281 return_value = smbd_smb2_request_process_cancel(req);
2282 END_PROFILE(smb2_cancel);
2286 case SMB2_OP_KEEPALIVE:
2288 START_PROFILE(smb2_keepalive);
2289 return_value = smbd_smb2_request_process_keepalive(req);
2290 END_PROFILE(smb2_keepalive);
2296 START_PROFILE(smb2_find);
2297 return_value = smbd_smb2_request_process_find(req);
2298 END_PROFILE(smb2_find);
2302 case SMB2_OP_NOTIFY:
2304 START_PROFILE(smb2_notify);
2305 return_value = smbd_smb2_request_process_notify(req);
2306 END_PROFILE(smb2_notify);
2310 case SMB2_OP_GETINFO:
2312 START_PROFILE(smb2_getinfo);
2313 return_value = smbd_smb2_request_process_getinfo(req);
2314 END_PROFILE(smb2_getinfo);
2318 case SMB2_OP_SETINFO:
2320 START_PROFILE(smb2_setinfo);
2321 return_value = smbd_smb2_request_process_setinfo(req);
2322 END_PROFILE(smb2_setinfo);
2328 START_PROFILE(smb2_break);
2329 return_value = smbd_smb2_request_process_break(req);
2330 END_PROFILE(smb2_break);
2335 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2338 return return_value;
2341 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2343 struct smbd_server_connection *sconn = req->sconn;
2344 struct smbXsrv_connection *xconn = req->sconn->conn;
2346 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2347 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2348 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2352 TALLOC_FREE(req->async_te);
2354 if (req->do_encryption &&
2355 (firsttf->iov_len == 0) &&
2356 (req->first_key.length == 0) &&
2357 (req->session != NULL) &&
2358 (req->session->global->encryption_key.length != 0))
2360 DATA_BLOB encryption_key = req->session->global->encryption_key;
2362 uint64_t session_id = req->session->global->session_wire_id;
2363 struct smbXsrv_session *x = req->session;
2364 uint64_t nonce_high;
2367 nonce_high = x->nonce_high;
2368 nonce_low = x->nonce_low;
2371 if (x->nonce_low == 0) {
2377 * We need to place the SMB2_TRANSFORM header before the
2382 * we need to remember the encryption key
2383 * and defer the signing/encryption until
2384 * we are sure that we do not change
2387 req->first_key = data_blob_dup_talloc(req, encryption_key);
2388 if (req->first_key.data == NULL) {
2389 return NT_STATUS_NO_MEMORY;
2392 tf = talloc_zero_array(req, uint8_t,
2395 return NT_STATUS_NO_MEMORY;
2398 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2399 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2400 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2401 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2403 firsttf->iov_base = (void *)tf;
2404 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2407 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2408 (req->last_key.length > 0) &&
2409 (firsttf->iov_len == 0))
2411 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2412 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2415 * As we are sure the header of the last request in the
2416 * compound chain will not change, we can to sign here
2417 * with the last signing key we remembered.
2419 status = smb2_signing_sign_pdu(req->last_key,
2422 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2423 if (!NT_STATUS_IS_OK(status)) {
2427 if (req->last_key.length > 0) {
2428 data_blob_clear_free(&req->last_key);
2431 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2433 if (req->current_idx < req->out.vector_count) {
2435 * We must process the remaining compound
2436 * SMB2 requests before any new incoming SMB2
2437 * requests. This is because incoming SMB2
2438 * requests may include a cancel for a
2439 * compound request we haven't processed
2442 struct tevent_immediate *im = tevent_create_immediate(req);
2444 return NT_STATUS_NO_MEMORY;
2447 if (req->do_signing && firsttf->iov_len == 0) {
2448 struct smbXsrv_session *x = req->session;
2449 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2452 * we need to remember the signing key
2453 * and defer the signing until
2454 * we are sure that we do not change
2457 req->last_key = data_blob_dup_talloc(req, signing_key);
2458 if (req->last_key.data == NULL) {
2459 return NT_STATUS_NO_MEMORY;
2463 tevent_schedule_immediate(im,
2465 smbd_smb2_request_dispatch_immediate,
2467 return NT_STATUS_OK;
2470 if (req->compound_related) {
2471 req->compound_related = false;
2474 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2476 /* Set credit for these operations (zero credits if this
2477 is a final reply for an async operation). */
2478 smb2_calculate_credits(req, req);
2481 * now check if we need to sign the current response
2483 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2484 status = smb2_signing_encrypt_pdu(req->first_key,
2487 req->out.vector_count - first_idx);
2488 if (!NT_STATUS_IS_OK(status)) {
2491 } else if (req->do_signing) {
2492 struct smbXsrv_session *x = req->session;
2493 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2495 status = smb2_signing_sign_pdu(signing_key,
2498 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2499 if (!NT_STATUS_IS_OK(status)) {
2503 if (req->first_key.length > 0) {
2504 data_blob_clear_free(&req->first_key);
2507 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2508 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2509 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2510 /* Dynamic part is NULL. Chop it off,
2511 We're going to send it via sendfile. */
2512 req->out.vector_count -= 1;
2516 * We're done with this request -
2517 * move it off the "being processed" queue.
2519 DLIST_REMOVE(xconn->smb2.requests, req);
2521 req->queue_entry.mem_ctx = req;
2522 req->queue_entry.vector = req->out.vector;
2523 req->queue_entry.count = req->out.vector_count;
2524 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry, NULL);
2525 xconn->smb2.send_queue_len++;
2527 status = smbd_smb2_flush_send_queue(sconn);
2528 if (!NT_STATUS_IS_OK(status)) {
2532 return NT_STATUS_OK;
2535 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2537 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2538 struct tevent_immediate *im,
2541 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2542 struct smbd_smb2_request);
2543 struct smbd_server_connection *sconn = req->sconn;
2548 if (DEBUGLEVEL >= 10) {
2549 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2550 req->current_idx, req->in.vector_count));
2551 print_req_vectors(req);
2554 status = smbd_smb2_request_dispatch(req);
2555 if (!NT_STATUS_IS_OK(status)) {
2556 smbd_server_connection_terminate(sconn, nt_errstr(status));
2560 status = smbd_smb2_request_next_incoming(sconn);
2561 if (!NT_STATUS_IS_OK(status)) {
2562 smbd_server_connection_terminate(sconn, nt_errstr(status));
2567 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2569 DATA_BLOB body, DATA_BLOB *dyn,
2570 const char *location)
2573 struct iovec *outbody_v;
2574 struct iovec *outdyn_v;
2575 uint32_t next_command_ofs;
2577 DEBUG(10,("smbd_smb2_request_done_ex: "
2578 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2579 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2581 (unsigned int)(dyn ? dyn->length : 0),
2584 if (body.length < 2) {
2585 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2588 if ((body.length % 2) != 0) {
2589 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2592 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2593 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2594 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2596 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2597 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2599 outbody_v->iov_base = (void *)body.data;
2600 outbody_v->iov_len = body.length;
2603 outdyn_v->iov_base = (void *)dyn->data;
2604 outdyn_v->iov_len = dyn->length;
2606 outdyn_v->iov_base = NULL;
2607 outdyn_v->iov_len = 0;
2610 /* see if we need to recalculate the offset to the next response */
2611 if (next_command_ofs > 0) {
2612 next_command_ofs = SMB2_HDR_BODY;
2613 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2614 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2617 if ((next_command_ofs % 8) != 0) {
2618 size_t pad_size = 8 - (next_command_ofs % 8);
2619 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2621 * if the dyn buffer is empty
2622 * we can use it to add padding
2626 pad = talloc_zero_array(req,
2629 return smbd_smb2_request_error(req,
2630 NT_STATUS_NO_MEMORY);
2633 outdyn_v->iov_base = (void *)pad;
2634 outdyn_v->iov_len = pad_size;
2637 * For now we copy the dynamic buffer
2638 * and add the padding to the new buffer
2645 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2646 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2648 new_size = old_size + pad_size;
2649 new_dyn = talloc_zero_array(req,
2651 if (new_dyn == NULL) {
2652 return smbd_smb2_request_error(req,
2653 NT_STATUS_NO_MEMORY);
2656 memcpy(new_dyn, old_dyn, old_size);
2657 memset(new_dyn + old_size, 0, pad_size);
2659 outdyn_v->iov_base = (void *)new_dyn;
2660 outdyn_v->iov_len = new_size;
2662 next_command_ofs += pad_size;
2665 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2667 return smbd_smb2_request_reply(req);
2670 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2673 const char *location)
2675 struct smbXsrv_connection *xconn = req->sconn->conn;
2678 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2679 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2681 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2682 req->current_idx, nt_errstr(status), info ? " +info" : "",
2686 /* Recvfile error. Drain incoming socket. */
2690 ret = drain_socket(xconn->transport.sock, unread_bytes);
2691 if (ret != unread_bytes) {
2695 error = NT_STATUS_IO_DEVICE_ERROR;
2697 error = map_nt_error_from_unix_common(errno);
2700 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2701 "ret[%u] errno[%d] => %s\n",
2702 (unsigned)unread_bytes,
2703 (unsigned)ret, errno, nt_errstr(error)));
2708 body.data = outhdr + SMB2_HDR_BODY;
2710 SSVAL(body.data, 0, 9);
2713 SIVAL(body.data, 0x04, info->length);
2715 /* Allocated size of req->out.vector[i].iov_base
2716 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2717 * 1 byte without having to do an alloc.
2720 info->data = ((uint8_t *)outhdr) +
2721 OUTVEC_ALLOC_SIZE - 1;
2723 SCVAL(info->data, 0, 0);
2727 * Note: Even if there is an error, continue to process the request.
2731 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2735 struct smbd_smb2_send_break_state {
2736 struct smbd_server_connection *sconn;
2737 struct smbd_smb2_send_queue queue_entry;
2738 uint8_t nbt_hdr[NBT_HDR_SIZE];
2739 uint8_t tf[SMB2_TF_HDR_SIZE];
2740 uint8_t hdr[SMB2_HDR_BODY];
2741 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2745 static NTSTATUS smbd_smb2_send_break(struct smbd_server_connection *sconn,
2746 struct smbXsrv_session *session,
2747 struct smbXsrv_tcon *tcon,
2748 const uint8_t *body,
2751 struct smbd_smb2_send_break_state *state;
2752 struct smbXsrv_connection *xconn = sconn->conn;
2753 bool do_encryption = session->global->encryption_required;
2754 uint64_t nonce_high = 0;
2755 uint64_t nonce_low = 0;
2759 if (tcon->global->encryption_required) {
2760 do_encryption = true;
2763 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
2766 state = talloc_zero_size(sconn, statelen);
2767 if (state == NULL) {
2768 return NT_STATUS_NO_MEMORY;
2770 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
2771 state->sconn = sconn;
2773 if (do_encryption) {
2774 nonce_high = session->nonce_high;
2775 nonce_low = session->nonce_low;
2777 session->nonce_low += 1;
2778 if (session->nonce_low == 0) {
2779 session->nonce_low += 1;
2780 session->nonce_high += 1;
2784 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2785 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
2786 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
2787 SBVAL(state->tf, SMB2_TF_SESSION_ID, session->global->session_wire_id);
2789 SIVAL(state->hdr, 0, SMB2_MAGIC);
2790 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2791 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
2792 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
2793 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2794 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
2795 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2796 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
2797 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2798 SIVAL(state->hdr, SMB2_HDR_PID, 0);
2799 SIVAL(state->hdr, SMB2_HDR_TID, 0);
2800 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
2801 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
2803 state->vector[0] = (struct iovec) {
2804 .iov_base = state->nbt_hdr,
2805 .iov_len = sizeof(state->nbt_hdr)
2808 if (do_encryption) {
2809 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2810 .iov_base = state->tf,
2811 .iov_len = sizeof(state->tf)
2814 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2820 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
2821 .iov_base = state->hdr,
2822 .iov_len = sizeof(state->hdr)
2825 memcpy(state->body, body, body_len);
2827 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
2828 .iov_base = state->body,
2829 .iov_len = body_len /* no sizeof(state->body) .. :-) */
2833 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
2836 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2838 if (do_encryption) {
2839 DATA_BLOB encryption_key = session->global->encryption_key;
2841 status = smb2_signing_encrypt_pdu(encryption_key,
2843 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2844 SMBD_SMB2_NUM_IOV_PER_REQ);
2845 if (!NT_STATUS_IS_OK(status)) {
2850 state->queue_entry.mem_ctx = state;
2851 state->queue_entry.vector = state->vector;
2852 state->queue_entry.count = ARRAY_SIZE(state->vector);
2853 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
2854 xconn->smb2.send_queue_len++;
2856 status = smbd_smb2_flush_send_queue(sconn);
2857 if (!NT_STATUS_IS_OK(status)) {
2861 return NT_STATUS_OK;
2864 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2865 struct smbXsrv_session *session,
2866 struct smbXsrv_tcon *tcon,
2867 struct smbXsrv_open *op,
2868 uint8_t oplock_level)
2872 SSVAL(body, 0x00, sizeof(body));
2873 SCVAL(body, 0x02, oplock_level);
2874 SCVAL(body, 0x03, 0); /* reserved */
2875 SIVAL(body, 0x04, 0); /* reserved */
2876 SBVAL(body, 0x08, op->global->open_persistent_id);
2877 SBVAL(body, 0x10, op->global->open_volatile_id);
2879 return smbd_smb2_send_break(sconn, session, tcon, body, sizeof(body));
2882 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2886 uint64_t file_id_persistent;
2887 uint64_t file_id_volatile;
2888 struct smbXsrv_open *op = NULL;
2889 struct files_struct *fsp = NULL;
2890 const uint8_t *body = NULL;
2893 * This is only called with a pktbuf
2894 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
2898 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
2899 /* Transform header. Cannot recvfile. */
2902 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
2903 /* Not SMB2. Normal error path will cope. */
2906 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
2907 /* Not SMB2. Normal error path will cope. */
2910 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
2911 /* Needs to be a WRITE. */
2914 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
2915 /* Chained. Cannot recvfile. */
2918 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
2919 if (flags & SMB2_HDR_FLAG_CHAINED) {
2920 /* Chained. Cannot recvfile. */
2923 if (flags & SMB2_HDR_FLAG_SIGNED) {
2924 /* Signed. Cannot recvfile. */
2928 body = &state->pktbuf[SMB2_HDR_BODY];
2930 file_id_persistent = BVAL(body, 0x10);
2931 file_id_volatile = BVAL(body, 0x18);
2933 status = smb2srv_open_lookup(state->req->sconn->conn,
2938 if (!NT_STATUS_IS_OK(status)) {
2946 if (fsp->conn == NULL) {
2950 if (IS_IPC(fsp->conn)) {
2953 if (IS_PRINT(fsp->conn)) {
2957 DEBUG(10,("Doing recvfile write len = %u\n",
2958 (unsigned int)(state->pktfull - state->pktlen)));
2963 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2965 struct smbXsrv_connection *xconn = sconn->conn;
2966 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
2967 size_t max_send_queue_len;
2968 size_t cur_send_queue_len;
2970 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
2972 * we're not supposed to do any io
2974 return NT_STATUS_OK;
2977 if (state->req != NULL) {
2979 * if there is already a tstream_readv_pdu
2980 * pending, we are done.
2982 return NT_STATUS_OK;
2985 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
2986 cur_send_queue_len = xconn->smb2.send_queue_len;
2988 if (cur_send_queue_len > max_send_queue_len) {
2990 * if we have a lot of requests to send,
2991 * we wait until they are on the wire until we
2992 * ask for the next request.
2994 return NT_STATUS_OK;
2997 /* ask for the next request */
2998 ZERO_STRUCTP(state);
2999 state->req = smbd_smb2_request_allocate(xconn);
3000 if (state->req == NULL) {
3001 return NT_STATUS_NO_MEMORY;
3003 state->req->sconn = sconn;
3004 state->req->xconn = xconn;
3005 state->min_recv_size = lp_min_receive_file_size();
3007 TEVENT_FD_READABLE(xconn->transport.fde);
3009 return NT_STATUS_OK;
3012 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
3013 uint8_t *inbuf, size_t size)
3016 struct smbd_smb2_request *req = NULL;
3018 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3019 (unsigned int)size));
3021 status = smbd_initialize_smb2(sconn);
3022 if (!NT_STATUS_IS_OK(status)) {
3023 smbd_server_connection_terminate(sconn, nt_errstr(status));
3027 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
3028 if (!NT_STATUS_IS_OK(status)) {
3029 smbd_server_connection_terminate(sconn, nt_errstr(status));
3033 status = smbd_smb2_request_validate(req);
3034 if (!NT_STATUS_IS_OK(status)) {
3035 smbd_server_connection_terminate(sconn, nt_errstr(status));
3039 status = smbd_smb2_request_setup_out(req);
3040 if (!NT_STATUS_IS_OK(status)) {
3041 smbd_server_connection_terminate(sconn, nt_errstr(status));
3045 status = smbd_smb2_request_dispatch(req);
3046 if (!NT_STATUS_IS_OK(status)) {
3047 smbd_server_connection_terminate(sconn, nt_errstr(status));
3051 status = smbd_smb2_request_next_incoming(sconn);
3052 if (!NT_STATUS_IS_OK(status)) {
3053 smbd_server_connection_terminate(sconn, nt_errstr(status));
3057 sconn->num_requests++;
3060 static int socket_error_from_errno(int ret,
3074 if (sys_errno == 0) {
3078 if (sys_errno == EINTR) {
3083 if (sys_errno == EINPROGRESS) {
3088 if (sys_errno == EAGAIN) {
3093 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3094 if (sys_errno == ENOMEM) {
3100 #if EWOULDBLOCK != EAGAIN
3101 if (sys_errno == EWOULDBLOCK) {
3111 static NTSTATUS smbd_smb2_flush_send_queue(struct smbd_server_connection *sconn)
3113 struct smbXsrv_connection *xconn = sconn->conn;
3118 if (xconn->smb2.send_queue == NULL) {
3119 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3120 return NT_STATUS_OK;
3123 while (xconn->smb2.send_queue != NULL) {
3124 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3126 if (e->sendfile_header != NULL) {
3131 for (i=0; i < e->count; i++) {
3132 size += e->vector[i].iov_len;
3135 if (size <= e->sendfile_header->length) {
3136 buf = e->sendfile_header->data;
3138 buf = talloc_array(e->mem_ctx, uint8_t, size);
3140 return NT_STATUS_NO_MEMORY;
3145 for (i=0; i < e->count; i++) {
3147 e->vector[i].iov_base,
3148 e->vector[i].iov_len);
3149 size += e->vector[i].iov_len;
3152 e->sendfile_header->data = buf;
3153 e->sendfile_header->length = size;
3156 xconn->smb2.send_queue_len--;
3157 DLIST_REMOVE(xconn->smb2.send_queue, e);
3159 * This triggers the sendfile path via
3162 talloc_free(e->mem_ctx);
3166 ret = writev(xconn->transport.sock, e->vector, e->count);
3168 /* propagate end of file */
3169 return NT_STATUS_INTERNAL_ERROR;
3171 err = socket_error_from_errno(ret, errno, &retry);
3174 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3175 return NT_STATUS_OK;
3178 return map_nt_error_from_unix_common(err);
3181 if (ret < e->vector[0].iov_len) {
3183 base = (uint8_t *)e->vector[0].iov_base;
3185 e->vector[0].iov_base = (void *)base;
3186 e->vector[0].iov_len -= ret;
3189 ret -= e->vector[0].iov_len;
3195 * there're maybe some empty vectors at the end
3196 * which we need to skip, otherwise we would get
3197 * ret == 0 from the readv() call and return EPIPE
3199 while (e->count > 0) {
3200 if (e->vector[0].iov_len > 0) {
3208 /* we have more to write */
3209 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3210 return NT_STATUS_OK;
3213 xconn->smb2.send_queue_len--;
3214 DLIST_REMOVE(xconn->smb2.send_queue, e);
3215 talloc_free(e->mem_ctx);
3218 return NT_STATUS_OK;
3221 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3224 struct smbd_server_connection *sconn = xconn->sconn;
3225 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3226 struct smbd_smb2_request *req = NULL;
3227 size_t min_recvfile_size = UINT32_MAX;
3234 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3236 * we're not supposed to do any io
3238 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3239 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3240 return NT_STATUS_OK;
3243 if (fde_flags & TEVENT_FD_WRITE) {
3244 status = smbd_smb2_flush_send_queue(sconn);
3245 if (!NT_STATUS_IS_OK(status)) {
3250 if (!(fde_flags & TEVENT_FD_READ)) {
3251 return NT_STATUS_OK;
3254 if (state->req == NULL) {
3255 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3256 return NT_STATUS_OK;
3260 if (!state->hdr.done) {
3261 state->hdr.done = true;
3263 state->vector.iov_base = (void *)state->hdr.nbt;
3264 state->vector.iov_len = NBT_HDR_SIZE;
3267 ret = readv(xconn->transport.sock, &state->vector, 1);
3269 /* propagate end of file */
3270 return NT_STATUS_END_OF_FILE;
3272 err = socket_error_from_errno(ret, errno, &retry);
3275 TEVENT_FD_READABLE(xconn->transport.fde);
3276 return NT_STATUS_OK;
3279 return map_nt_error_from_unix_common(err);
3282 if (ret < state->vector.iov_len) {
3284 base = (uint8_t *)state->vector.iov_base;
3286 state->vector.iov_base = (void *)base;
3287 state->vector.iov_len -= ret;
3288 /* we have more to read */
3289 TEVENT_FD_READABLE(xconn->transport.fde);
3290 return NT_STATUS_OK;
3293 if (state->pktlen > 0) {
3294 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3296 * Not a possible receivefile write.
3297 * Read the rest of the data.
3299 state->doing_receivefile = false;
3301 state->pktbuf = talloc_realloc(state->req,
3305 if (state->pktbuf == NULL) {
3306 return NT_STATUS_NO_MEMORY;
3309 state->vector.iov_base = (void *)(state->pktbuf +
3311 state->vector.iov_len = (state->pktfull -
3314 state->pktlen = state->pktfull;
3319 * Either this is a receivefile write so we've
3320 * done a short read, or if not we have all the data.
3326 * Now we analyze the NBT header
3328 if (state->hdr.nbt[0] != 0x00) {
3329 state->min_recv_size = 0;
3331 state->pktfull = smb2_len(state->hdr.nbt);
3332 if (state->pktfull == 0) {
3336 if (state->min_recv_size != 0) {
3337 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3338 min_recvfile_size += state->min_recv_size;
3341 if (state->pktfull > min_recvfile_size) {
3343 * Might be a receivefile write. Read the SMB2 HEADER +
3344 * SMB2_WRITE header first. Set 'doing_receivefile'
3345 * as we're *attempting* receivefile write. If this
3346 * turns out not to be a SMB2_WRITE request or otherwise
3347 * not suitable then we'll just read the rest of the data
3348 * the next time this function is called.
3350 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3351 state->doing_receivefile = true;
3353 state->pktlen = state->pktfull;
3356 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3357 if (state->pktbuf == NULL) {
3358 return NT_STATUS_NO_MEMORY;
3361 state->vector.iov_base = (void *)state->pktbuf;
3362 state->vector.iov_len = state->pktlen;
3368 if (state->hdr.nbt[0] != 0x00) {
3369 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3370 state->hdr.nbt[0]));
3373 ZERO_STRUCTP(state);
3375 state->min_recv_size = lp_min_receive_file_size();
3383 req->request_time = timeval_current();
3384 now = timeval_to_nttime(&req->request_time);
3386 status = smbd_smb2_inbuf_parse_compound(xconn,
3392 &req->in.vector_count);
3393 if (!NT_STATUS_IS_OK(status)) {
3397 if (state->doing_receivefile) {
3398 req->smb1req = talloc_zero(req, struct smb_request);
3399 if (req->smb1req == NULL) {
3400 return NT_STATUS_NO_MEMORY;
3402 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3405 ZERO_STRUCTP(state);
3407 req->current_idx = 1;
3409 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3410 req->current_idx, req->in.vector_count));
3412 status = smbd_smb2_request_validate(req);
3413 if (!NT_STATUS_IS_OK(status)) {
3417 status = smbd_smb2_request_setup_out(req);
3418 if (!NT_STATUS_IS_OK(status)) {
3422 status = smbd_smb2_request_dispatch(req);
3423 if (!NT_STATUS_IS_OK(status)) {
3427 sconn->num_requests++;
3429 /* The timeout_processing function isn't run nearly
3430 often enough to implement 'max log size' without
3431 overrunning the size of the file by many megabytes.
3432 This is especially true if we are running at debug
3433 level 10. Checking every 50 SMB2s is a nice
3434 tradeoff of performance vs log file size overrun. */
3436 if ((sconn->num_requests % 50) == 0 &&
3437 need_to_check_log_size()) {
3438 change_to_root_user();
3442 status = smbd_smb2_request_next_incoming(sconn);
3443 if (!NT_STATUS_IS_OK(status)) {
3447 return NT_STATUS_OK;
3450 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3451 struct tevent_fd *fde,
3455 struct smbXsrv_connection *xconn =
3456 talloc_get_type_abort(private_data,
3457 struct smbXsrv_connection);
3458 struct smbd_server_connection *sconn = xconn->sconn;
3461 status = smbd_smb2_io_handler(xconn, flags);
3462 if (!NT_STATUS_IS_OK(status)) {
3463 smbd_server_connection_terminate(sconn, nt_errstr(status));