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 smbXsrv_connection *xconn);
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 smbXsrv_connection *xconn)
203 TALLOC_FREE(xconn->transport.fde);
205 xconn->smb2.credits.seq_low = 0;
206 xconn->smb2.credits.seq_range = 1;
207 xconn->smb2.credits.granted = 1;
208 xconn->smb2.credits.max = lp_smb2_max_credits();
209 xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
210 xconn->smb2.credits.max);
211 if (xconn->smb2.credits.bitmap == NULL) {
212 return NT_STATUS_NO_MEMORY;
215 xconn->transport.fde = tevent_add_fd(xconn->ev_ctx,
217 xconn->transport.sock,
219 smbd_smb2_connection_handler,
221 if (xconn->transport.fde == NULL) {
222 return NT_STATUS_NO_MEMORY;
225 /* Ensure child is set to non-blocking mode */
226 set_blocking(xconn->transport.sock, false);
230 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
231 #define _smb2_setlen(_buf,len) do { \
232 uint8_t *buf = (uint8_t *)_buf; \
234 buf[1] = ((len)&0xFF0000)>>16; \
235 buf[2] = ((len)&0xFF00)>>8; \
236 buf[3] = (len)&0xFF; \
239 static void smb2_setup_nbt_length(struct iovec *vector, int count)
244 for (i=1; i < count; i++) {
245 len += vector[i].iov_len;
248 _smb2_setlen(vector[0].iov_base, len);
251 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
253 if (req->first_key.length > 0) {
254 data_blob_clear_free(&req->first_key);
256 if (req->last_key.length > 0) {
257 data_blob_clear_free(&req->last_key);
262 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
264 TALLOC_CTX *mem_pool;
265 struct smbd_smb2_request *req;
268 /* Enable this to find subtle valgrind errors. */
269 mem_pool = talloc_init("smbd_smb2_request_allocate");
271 mem_pool = talloc_tos();
273 if (mem_pool == NULL) {
277 req = talloc_zero(mem_pool, struct smbd_smb2_request);
279 talloc_free(mem_pool);
282 talloc_reparent(mem_pool, mem_ctx, req);
284 TALLOC_FREE(mem_pool);
287 req->last_session_id = UINT64_MAX;
288 req->last_tid = UINT32_MAX;
290 talloc_set_destructor(req, smbd_smb2_request_destructor);
295 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
299 struct smbd_smb2_request *req,
303 TALLOC_CTX *mem_ctx = req;
307 uint8_t *first_hdr = buf;
308 size_t verified_buflen = 0;
313 * Note: index '0' is reserved for the transport protocol
315 iov = req->in._vector;
317 while (taken < buflen) {
318 size_t len = buflen - taken;
319 uint8_t *hdr = first_hdr + taken;
322 size_t next_command_ofs;
324 uint8_t *body = NULL;
327 struct iovec *iov_alloc = NULL;
329 if (iov != req->in._vector) {
333 if (verified_buflen > taken) {
334 len = verified_buflen - taken;
341 DEBUG(10, ("%d bytes left, expected at least %d\n",
345 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
346 struct smbXsrv_session *s = NULL;
348 struct iovec tf_iov[2];
352 if (xconn->protocol < PROTOCOL_SMB2_24) {
353 DEBUG(10, ("Got SMB2_TRANSFORM header, "
354 "but dialect[0x%04X] is used\n",
355 xconn->smb2.server.dialect));
359 if (!(xconn->smb2.server.capabilities & SMB2_CAP_ENCRYPTION)) {
360 DEBUG(10, ("Got SMB2_TRANSFORM header, "
361 "but not negotiated "
362 "client[0x%08X] server[0x%08X]\n",
363 xconn->smb2.client.capabilities,
364 xconn->smb2.server.capabilities));
368 if (len < SMB2_TF_HDR_SIZE) {
369 DEBUG(1, ("%d bytes left, expected at least %d\n",
370 (int)len, SMB2_TF_HDR_SIZE));
374 tf_len = SMB2_TF_HDR_SIZE;
377 hdr = first_hdr + taken;
378 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
379 uid = BVAL(tf, SMB2_TF_SESSION_ID);
381 if (len < SMB2_TF_HDR_SIZE + enc_len) {
382 DEBUG(1, ("%d bytes left, expected at least %d\n",
384 (int)(SMB2_TF_HDR_SIZE + enc_len)));
388 status = smb2srv_session_lookup(xconn, uid, now, &s);
390 DEBUG(1, ("invalid session[%llu] in "
391 "SMB2_TRANSFORM header\n",
392 (unsigned long long)uid));
393 TALLOC_FREE(iov_alloc);
394 return NT_STATUS_USER_SESSION_DELETED;
397 tf_iov[0].iov_base = (void *)tf;
398 tf_iov[0].iov_len = tf_len;
399 tf_iov[1].iov_base = (void *)hdr;
400 tf_iov[1].iov_len = enc_len;
402 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
405 if (!NT_STATUS_IS_OK(status)) {
406 TALLOC_FREE(iov_alloc);
410 verified_buflen = taken + enc_len;
415 * We need the header plus the body length field
418 if (len < SMB2_HDR_BODY + 2) {
419 DEBUG(10, ("%d bytes left, expected at least %d\n",
420 (int)len, SMB2_HDR_BODY));
423 if (IVAL(hdr, 0) != SMB2_MAGIC) {
424 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
428 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
429 DEBUG(10, ("Got HDR len %d, expected %d\n",
430 SVAL(hdr, 4), SMB2_HDR_BODY));
435 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
436 body_size = SVAL(hdr, SMB2_HDR_BODY);
438 if (next_command_ofs != 0) {
439 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
442 if (next_command_ofs > full_size) {
445 full_size = next_command_ofs;
452 if (body_size > (full_size - SMB2_HDR_BODY)) {
454 * let the caller handle the error
456 body_size = full_size - SMB2_HDR_BODY;
458 body = hdr + SMB2_HDR_BODY;
459 dyn = body + body_size;
460 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
462 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
463 struct iovec *iov_tmp = NULL;
465 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
468 SMBD_SMB2_NUM_IOV_PER_REQ);
469 if (iov_tmp == NULL) {
470 TALLOC_FREE(iov_alloc);
471 return NT_STATUS_NO_MEMORY;
474 if (iov_alloc == NULL) {
477 sizeof(req->in._vector));
483 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
485 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
486 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
487 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
488 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
489 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
490 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
491 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
492 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
502 if (iov != req->in._vector) {
505 return NT_STATUS_INVALID_PARAMETER;
508 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
509 uint8_t *inbuf, size_t size,
510 struct smbd_smb2_request **_req)
512 struct smbXsrv_connection *xconn = sconn->conn;
513 struct smbd_smb2_request *req;
514 uint32_t protocol_version;
515 const uint8_t *inhdr = NULL;
517 uint32_t next_command_ofs;
521 if (size < (4 + SMB2_HDR_BODY + 2)) {
522 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
523 return NT_STATUS_INVALID_PARAMETER;
528 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
529 if (protocol_version != SMB2_MAGIC) {
530 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
532 return NT_STATUS_INVALID_PARAMETER;
535 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
536 if (cmd != SMB2_OP_NEGPROT) {
537 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
539 return NT_STATUS_INVALID_PARAMETER;
542 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
543 if (next_command_ofs != 0) {
544 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
546 return NT_STATUS_INVALID_PARAMETER;
549 req = smbd_smb2_request_allocate(xconn);
551 return NT_STATUS_NO_MEMORY;
556 talloc_steal(req, inbuf);
558 req->request_time = timeval_current();
559 now = timeval_to_nttime(&req->request_time);
561 status = smbd_smb2_inbuf_parse_compound(sconn->conn,
563 inbuf + NBT_HDR_SIZE,
565 req, &req->in.vector,
566 &req->in.vector_count);
567 if (!NT_STATUS_IS_OK(status)) {
572 req->current_idx = 1;
578 static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
579 uint64_t message_id, uint64_t seq_id)
581 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
585 seq_tmp = xconn->smb2.credits.seq_low;
586 if (seq_id < seq_tmp) {
587 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
588 "%llu (sequence id %llu) "
589 "(granted = %u, low = %llu, range = %u)\n",
590 (unsigned long long)message_id,
591 (unsigned long long)seq_id,
592 (unsigned int)xconn->smb2.credits.granted,
593 (unsigned long long)xconn->smb2.credits.seq_low,
594 (unsigned int)xconn->smb2.credits.seq_range));
598 seq_tmp += xconn->smb2.credits.seq_range;
599 if (seq_id >= seq_tmp) {
600 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
601 "%llu (sequence id %llu) "
602 "(granted = %u, low = %llu, range = %u)\n",
603 (unsigned long long)message_id,
604 (unsigned long long)seq_id,
605 (unsigned int)xconn->smb2.credits.granted,
606 (unsigned long long)xconn->smb2.credits.seq_low,
607 (unsigned int)xconn->smb2.credits.seq_range));
611 offset = seq_id % xconn->smb2.credits.max;
613 if (bitmap_query(credits_bm, offset)) {
614 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
615 "%llu (sequence id %llu) "
616 "(granted = %u, low = %llu, range = %u) "
618 (unsigned long long)message_id,
619 (unsigned long long)seq_id,
620 (unsigned int)xconn->smb2.credits.granted,
621 (unsigned long long)xconn->smb2.credits.seq_low,
622 (unsigned int)xconn->smb2.credits.seq_range,
627 /* Mark the message_ids as seen in the bitmap. */
628 bitmap_set(credits_bm, offset);
630 if (seq_id != xconn->smb2.credits.seq_low) {
635 * Move the window forward by all the message_id's
638 while (bitmap_query(credits_bm, offset)) {
639 DEBUG(10,("smb2_validate_sequence_number: clearing "
640 "id %llu (position %u) from bitmap\n",
641 (unsigned long long)(xconn->smb2.credits.seq_low),
643 bitmap_clear(credits_bm, offset);
645 xconn->smb2.credits.seq_low += 1;
646 xconn->smb2.credits.seq_range -= 1;
647 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
653 static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
654 const uint8_t *inhdr)
656 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
657 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
658 uint16_t credit_charge = 1;
661 if (opcode == SMB2_OP_CANCEL) {
662 /* SMB2_CANCEL requests by definition resend messageids. */
666 if (xconn->smb2.credits.multicredit) {
667 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
668 credit_charge = MAX(credit_charge, 1);
671 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
672 "credits_granted %llu, "
673 "seqnum low/range: %llu/%llu\n",
674 (unsigned long long) message_id,
675 (unsigned long long) credit_charge,
676 (unsigned long long) xconn->smb2.credits.granted,
677 (unsigned long long) xconn->smb2.credits.seq_low,
678 (unsigned long long) xconn->smb2.credits.seq_range));
680 if (xconn->smb2.credits.granted < credit_charge) {
681 DEBUG(0, ("smb2_validate_message_id: client used more "
682 "credits than granted, mid %llu, charge %llu, "
683 "credits_granted %llu, "
684 "seqnum low/range: %llu/%llu\n",
685 (unsigned long long) message_id,
686 (unsigned long long) credit_charge,
687 (unsigned long long) xconn->smb2.credits.granted,
688 (unsigned long long) xconn->smb2.credits.seq_low,
689 (unsigned long long) xconn->smb2.credits.seq_range));
694 * now check the message ids
696 * for multi-credit requests we need to check all current mid plus
697 * the implicit mids caused by the credit charge
698 * e.g. current mid = 15, charge 5 => mark 15-19 as used
701 for (i = 0; i <= (credit_charge-1); i++) {
702 uint64_t id = message_id + i;
705 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
706 (unsigned long long)message_id,
708 (unsigned long long)id));
710 ok = smb2_validate_sequence_number(xconn, message_id, id);
716 /* substract used credits */
717 xconn->smb2.credits.granted -= credit_charge;
722 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
727 count = req->in.vector_count;
729 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
730 /* It's not a SMB2 request */
731 return NT_STATUS_INVALID_PARAMETER;
734 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
735 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
736 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
737 const uint8_t *inhdr = NULL;
739 if (hdr->iov_len != SMB2_HDR_BODY) {
740 return NT_STATUS_INVALID_PARAMETER;
743 if (body->iov_len < 2) {
744 return NT_STATUS_INVALID_PARAMETER;
747 inhdr = (const uint8_t *)hdr->iov_base;
749 /* Check the SMB2 header */
750 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
751 return NT_STATUS_INVALID_PARAMETER;
754 if (!smb2_validate_message_id(req->xconn, inhdr)) {
755 return NT_STATUS_INVALID_PARAMETER;
762 static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
763 const struct iovec *in_vector,
764 struct iovec *out_vector)
766 struct smbd_server_connection *sconn = xconn->sconn;
767 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
768 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
769 uint16_t credit_charge = 1;
770 uint16_t credits_requested;
774 uint16_t credits_granted = 0;
775 uint64_t credits_possible;
776 uint16_t current_max_credits;
779 * first we grant only 1/16th of the max range.
781 * Windows also starts with the 1/16th and then grants
782 * more later. I was only able to trigger higher
783 * values, when using a very high credit charge.
785 * TODO: scale up depending on load, free memory
787 * Maybe also on the relationship between number
788 * of requests and the used sequence number.
789 * Which means we would grant more credits
790 * for client which use multi credit requests.
792 current_max_credits = xconn->smb2.credits.max / 16;
793 current_max_credits = MAX(current_max_credits, 1);
795 if (xconn->smb2.credits.multicredit) {
796 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
797 credit_charge = MAX(credit_charge, 1);
800 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
801 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
802 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
803 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
805 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
807 if (xconn->smb2.credits.max < credit_charge) {
808 smbd_server_connection_terminate(sconn,
809 "client error: credit charge > max credits\n");
813 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
815 * In case we already send an async interim
816 * response, we should not grant
817 * credits on the final response.
820 } else if (credits_requested > 0) {
821 uint16_t additional_max = 0;
822 uint16_t additional_credits = credits_requested - 1;
825 case SMB2_OP_NEGPROT:
827 case SMB2_OP_SESSSETUP:
829 * Windows 2012 RC1 starts to grant
831 * with a successful session setup
833 if (NT_STATUS_IS_OK(out_status)) {
839 * We match windows and only grant additional credits
846 additional_credits = MIN(additional_credits, additional_max);
848 credits_granted = credit_charge + additional_credits;
849 } else if (xconn->smb2.credits.granted == 0) {
851 * Make sure the client has always at least one credit
857 * sequence numbers should not wrap
859 * 1. calculate the possible credits until
860 * the sequence numbers start to wrap on 64-bit.
862 * 2. UINT64_MAX is used for Break Notifications.
864 * 2. truncate the possible credits to the maximum
865 * credits we want to grant to the client in total.
867 * 3. remove the range we'll already granted to the client
868 * this makes sure the client consumes the lowest sequence
869 * number, before we can grant additional credits.
871 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
872 if (credits_possible > 0) {
873 /* remove UINT64_MAX */
874 credits_possible -= 1;
876 credits_possible = MIN(credits_possible, current_max_credits);
877 credits_possible -= xconn->smb2.credits.seq_range;
879 credits_granted = MIN(credits_granted, credits_possible);
881 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
882 xconn->smb2.credits.granted += credits_granted;
883 xconn->smb2.credits.seq_range += credits_granted;
885 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
886 "granted %u, current possible/max %u/%u, "
887 "total granted/max/low/range %u/%u/%llu/%u\n",
888 (unsigned int)credits_requested,
889 (unsigned int)credit_charge,
890 (unsigned int)credits_granted,
891 (unsigned int)credits_possible,
892 (unsigned int)current_max_credits,
893 (unsigned int)xconn->smb2.credits.granted,
894 (unsigned int)xconn->smb2.credits.max,
895 (unsigned long long)xconn->smb2.credits.seq_low,
896 (unsigned int)xconn->smb2.credits.seq_range));
899 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
900 struct smbd_smb2_request *outreq)
903 uint16_t total_credits = 0;
905 count = outreq->out.vector_count;
907 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
908 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
909 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
910 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
912 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
914 /* To match Windows, count up what we
916 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
917 /* Set to zero in all but the last reply. */
918 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
919 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
921 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
926 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
928 if (req->current_idx <= 1) {
929 if (size <= sizeof(req->out._body)) {
930 return data_blob_const(req->out._body, size);
934 return data_blob_talloc(req, NULL, size);
937 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
939 struct smbXsrv_connection *xconn = req->sconn->conn;
941 struct iovec *vector;
945 count = req->in.vector_count;
946 if (count <= ARRAY_SIZE(req->out._vector)) {
948 vector = req->out._vector;
950 vector = talloc_zero_array(req, struct iovec, count);
951 if (vector == NULL) {
952 return NT_STATUS_NO_MEMORY;
957 vector[0].iov_base = req->out.nbt_hdr;
958 vector[0].iov_len = 4;
959 SIVAL(req->out.nbt_hdr, 0, 0);
961 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
962 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
963 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
964 uint8_t *outhdr = NULL;
965 uint8_t *outbody = NULL;
966 uint32_t next_command_ofs = 0;
967 struct iovec *current = &vector[idx];
969 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
970 /* we have a next command -
971 * setup for the error case. */
972 next_command_ofs = SMB2_HDR_BODY + 9;
976 outhdr = req->out._hdr;
978 outhdr = talloc_zero_array(mem_ctx, uint8_t,
980 if (outhdr == NULL) {
981 return NT_STATUS_NO_MEMORY;
985 outbody = outhdr + SMB2_HDR_BODY;
988 * SMBD_SMB2_TF_IOV_OFS might be used later
990 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
991 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
993 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
994 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
996 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
997 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
999 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1000 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1002 /* setup the SMB2 header */
1003 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1004 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1005 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1006 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1007 SIVAL(outhdr, SMB2_HDR_STATUS,
1008 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1009 SSVAL(outhdr, SMB2_HDR_OPCODE,
1010 SVAL(inhdr, SMB2_HDR_OPCODE));
1011 SIVAL(outhdr, SMB2_HDR_FLAGS,
1012 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1013 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1014 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1015 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1016 SIVAL(outhdr, SMB2_HDR_PID,
1017 IVAL(inhdr, SMB2_HDR_PID));
1018 SIVAL(outhdr, SMB2_HDR_TID,
1019 IVAL(inhdr, SMB2_HDR_TID));
1020 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1021 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1022 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1023 inhdr + SMB2_HDR_SIGNATURE, 16);
1025 /* setup error body header */
1026 SSVAL(outbody, 0x00, 0x08 + 1);
1027 SSVAL(outbody, 0x02, 0);
1028 SIVAL(outbody, 0x04, 0);
1031 req->out.vector = vector;
1032 req->out.vector_count = count;
1034 /* setup the length of the NBT packet */
1035 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1037 DLIST_ADD_END(xconn->smb2.requests, req, struct smbd_smb2_request *);
1039 return NT_STATUS_OK;
1042 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
1044 const char *location)
1046 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1048 exit_server_cleanly(reason);
1051 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1052 struct iovec *outvec,
1053 const struct iovec *srcvec)
1055 const uint8_t *srctf;
1057 const uint8_t *srchdr;
1059 const uint8_t *srcbody;
1061 const uint8_t *expected_srcbody;
1062 const uint8_t *srcdyn;
1064 const uint8_t *expected_srcdyn;
1070 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1071 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1072 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1073 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1074 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1075 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1076 expected_srcbody = srchdr + SMB2_HDR_BODY;
1077 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1078 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1079 expected_srcdyn = srcbody + 8;
1081 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1085 if (srchdr_len != SMB2_HDR_BODY) {
1089 if (srctf_len == SMB2_TF_HDR_SIZE) {
1090 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1091 if (dsttf == NULL) {
1097 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1098 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1100 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1101 * be allocated with size OUTVEC_ALLOC_SIZE. */
1103 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1104 if (dsthdr == NULL) {
1107 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1108 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1111 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1112 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1113 * then duplicate this. Else use talloc_memdup().
1116 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1117 dstbody = dsthdr + SMB2_HDR_BODY;
1119 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1120 if (dstbody == NULL) {
1124 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1125 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1128 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1130 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1131 * then duplicate this. Else use talloc_memdup().
1134 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1135 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1136 } else if (srcdyn == NULL) {
1139 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1140 if (dstdyn == NULL) {
1144 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1145 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1150 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1152 struct smbd_smb2_request *newreq = NULL;
1153 struct iovec *outvec = NULL;
1154 int count = req->out.vector_count;
1157 newreq = smbd_smb2_request_allocate(req->xconn);
1162 newreq->sconn = req->sconn;
1163 newreq->xconn = req->xconn;
1164 newreq->session = req->session;
1165 newreq->do_encryption = req->do_encryption;
1166 newreq->do_signing = req->do_signing;
1167 newreq->current_idx = req->current_idx;
1169 outvec = talloc_zero_array(newreq, struct iovec, count);
1171 TALLOC_FREE(newreq);
1174 newreq->out.vector = outvec;
1175 newreq->out.vector_count = count;
1177 /* Setup the outvec's identically to req. */
1178 outvec[0].iov_base = newreq->out.nbt_hdr;
1179 outvec[0].iov_len = 4;
1180 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1182 /* Setup the vectors identically to the ones in req. */
1183 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1184 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1191 TALLOC_FREE(newreq);
1195 smb2_setup_nbt_length(newreq->out.vector,
1196 newreq->out.vector_count);
1201 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1203 struct smbXsrv_connection *xconn = req->xconn;
1205 struct iovec *firsttf = NULL;
1206 struct iovec *outhdr_v = NULL;
1207 uint8_t *outhdr = NULL;
1208 struct smbd_smb2_request *nreq = NULL;
1211 /* Create a new smb2 request we'll use
1212 for the interim return. */
1213 nreq = dup_smb2_req(req);
1215 return NT_STATUS_NO_MEMORY;
1218 /* Lose the last X out vectors. They're the
1219 ones we'll be using for the async reply. */
1220 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1222 smb2_setup_nbt_length(nreq->out.vector,
1223 nreq->out.vector_count);
1225 /* Step back to the previous reply. */
1226 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1227 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1228 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1229 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1230 /* And end the chain. */
1231 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1233 /* Calculate outgoing credits */
1234 smb2_calculate_credits(req, nreq);
1236 if (DEBUGLEVEL >= 10) {
1237 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1238 (unsigned int)nreq->current_idx );
1239 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1240 (unsigned int)nreq->out.vector_count );
1241 print_req_vectors(nreq);
1245 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1246 * we need to sign/encrypt here with the last/first key we remembered
1248 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1249 status = smb2_signing_encrypt_pdu(req->first_key,
1252 nreq->out.vector_count - first_idx);
1253 if (!NT_STATUS_IS_OK(status)) {
1256 } else if (req->last_key.length > 0) {
1257 status = smb2_signing_sign_pdu(req->last_key,
1260 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1261 if (!NT_STATUS_IS_OK(status)) {
1266 nreq->queue_entry.mem_ctx = nreq;
1267 nreq->queue_entry.vector = nreq->out.vector;
1268 nreq->queue_entry.count = nreq->out.vector_count;
1269 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry, NULL);
1270 xconn->smb2.send_queue_len++;
1272 status = smbd_smb2_flush_send_queue(xconn);
1273 if (!NT_STATUS_IS_OK(status)) {
1277 return NT_STATUS_OK;
1280 struct smbd_smb2_request_pending_state {
1281 struct smbd_server_connection *sconn;
1282 struct smbd_smb2_send_queue queue_entry;
1283 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1284 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1287 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1288 struct tevent_timer *te,
1289 struct timeval current_time,
1290 void *private_data);
1292 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1293 struct tevent_req *subreq,
1294 uint32_t defer_time)
1297 struct timeval defer_endtime;
1298 uint8_t *outhdr = NULL;
1301 if (!tevent_req_is_in_progress(subreq)) {
1303 * This is a performance optimization,
1304 * it avoids one tevent_loop iteration,
1305 * which means we avoid one
1306 * talloc_stackframe_pool/talloc_free pair.
1308 tevent_req_notify_callback(subreq);
1309 return NT_STATUS_OK;
1312 req->subreq = subreq;
1315 if (req->async_te) {
1316 /* We're already async. */
1317 return NT_STATUS_OK;
1320 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1321 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1322 if (flags & SMB2_HDR_FLAG_ASYNC) {
1323 /* We're already async. */
1324 return NT_STATUS_OK;
1327 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1329 * We're trying to go async in a compound
1331 * This is only allowed for opens that
1332 * cause an oplock break, otherwise it
1333 * is not allowed. See [MS-SMB2].pdf
1334 * note <194> on Section 3.3.5.2.7.
1336 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1338 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1340 * Cancel the outstanding request.
1342 bool ok = tevent_req_cancel(req->subreq);
1344 return NT_STATUS_OK;
1346 TALLOC_FREE(req->subreq);
1347 return smbd_smb2_request_error(req,
1348 NT_STATUS_INTERNAL_ERROR);
1352 if (DEBUGLEVEL >= 10) {
1353 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1354 (unsigned int)req->current_idx );
1355 print_req_vectors(req);
1358 if (req->current_idx > 1) {
1360 * We're going async in a compound
1361 * chain after the first request has
1362 * already been processed. Send an
1363 * interim response containing the
1364 * set of replies already generated.
1366 int idx = req->current_idx;
1368 status = smb2_send_async_interim_response(req);
1369 if (!NT_STATUS_IS_OK(status)) {
1372 if (req->first_key.length > 0) {
1373 data_blob_clear_free(&req->first_key);
1376 req->current_idx = 1;
1379 * Re-arrange the in.vectors to remove what
1382 memmove(&req->in.vector[1],
1383 &req->in.vector[idx],
1384 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1385 req->in.vector_count = 1 + (req->in.vector_count - idx);
1387 /* Re-arrange the out.vectors to match. */
1388 memmove(&req->out.vector[1],
1389 &req->out.vector[idx],
1390 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1391 req->out.vector_count = 1 + (req->out.vector_count - idx);
1393 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1395 * We only have one remaining request as
1396 * we've processed everything else.
1397 * This is no longer a compound request.
1399 req->compound_related = false;
1400 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1401 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1402 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1405 if (req->last_key.length > 0) {
1406 data_blob_clear_free(&req->last_key);
1409 defer_endtime = timeval_current_ofs_usec(defer_time);
1410 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1412 smbd_smb2_request_pending_timer,
1414 if (req->async_te == NULL) {
1415 return NT_STATUS_NO_MEMORY;
1418 return NT_STATUS_OK;
1421 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1422 struct tevent_timer *te,
1423 struct timeval current_time,
1426 struct smbd_smb2_request *req =
1427 talloc_get_type_abort(private_data,
1428 struct smbd_smb2_request);
1429 struct smbd_server_connection *sconn = req->sconn;
1430 struct smbXsrv_connection *xconn = sconn->conn;
1431 struct smbd_smb2_request_pending_state *state = NULL;
1432 uint8_t *outhdr = NULL;
1433 const uint8_t *inhdr = NULL;
1436 uint8_t *hdr = NULL;
1437 uint8_t *body = NULL;
1438 uint8_t *dyn = NULL;
1440 uint64_t session_id = 0;
1441 uint64_t message_id = 0;
1442 uint64_t nonce_high = 0;
1443 uint64_t nonce_low = 0;
1444 uint64_t async_id = 0;
1447 TALLOC_FREE(req->async_te);
1449 /* Ensure our final reply matches the interim one. */
1450 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1451 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1452 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1453 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1454 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1456 async_id = message_id; /* keep it simple for now... */
1458 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1459 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1461 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1463 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1464 (unsigned long long)async_id ));
1467 * What we send is identical to a smbd_smb2_request_error
1468 * packet with an error status of STATUS_PENDING. Make use
1469 * of this fact sometime when refactoring. JRA.
1472 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1473 if (state == NULL) {
1474 smbd_server_connection_terminate(req->sconn,
1475 nt_errstr(NT_STATUS_NO_MEMORY));
1478 state->sconn = req->sconn;
1480 tf = state->buf + NBT_HDR_SIZE;
1481 tf_len = SMB2_TF_HDR_SIZE;
1483 hdr = tf + SMB2_TF_HDR_SIZE;
1484 body = hdr + SMB2_HDR_BODY;
1487 if (req->do_encryption) {
1488 struct smbXsrv_session *x = req->session;
1490 nonce_high = x->nonce_high;
1491 nonce_low = x->nonce_low;
1494 if (x->nonce_low == 0) {
1500 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1501 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1502 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1503 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1505 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1506 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1507 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1508 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1509 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1511 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1512 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1513 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1514 SBVAL(hdr, SMB2_HDR_PID, async_id);
1515 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1516 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1517 memcpy(hdr+SMB2_HDR_SIGNATURE,
1518 outhdr+SMB2_HDR_SIGNATURE, 16);
1520 SSVAL(body, 0x00, 0x08 + 1);
1522 SCVAL(body, 0x02, 0);
1523 SCVAL(body, 0x03, 0);
1524 SIVAL(body, 0x04, 0);
1525 /* Match W2K8R2... */
1526 SCVAL(dyn, 0x00, 0x21);
1528 state->vector[0].iov_base = (void *)state->buf;
1529 state->vector[0].iov_len = NBT_HDR_SIZE;
1531 if (req->do_encryption) {
1532 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1533 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1535 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1536 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1539 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1540 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1542 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1543 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1545 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1546 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1548 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1550 /* Ensure we correctly go through crediting. Grant
1551 the credits now, and zero credits on the final
1553 smb2_set_operation_credit(req->xconn,
1554 SMBD_SMB2_IN_HDR_IOV(req),
1555 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1557 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1562 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1563 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1565 (unsigned int)ARRAY_SIZE(state->vector),
1566 (unsigned int)state->vector[i].iov_len);
1570 if (req->do_encryption) {
1571 struct smbXsrv_session *x = req->session;
1572 DATA_BLOB encryption_key = x->global->encryption_key;
1574 status = smb2_signing_encrypt_pdu(encryption_key,
1576 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1577 SMBD_SMB2_NUM_IOV_PER_REQ);
1578 if (!NT_STATUS_IS_OK(status)) {
1579 smbd_server_connection_terminate(req->sconn,
1583 } else if (req->do_signing) {
1584 struct smbXsrv_session *x = req->session;
1585 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1587 status = smb2_signing_sign_pdu(signing_key,
1589 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1590 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1591 if (!NT_STATUS_IS_OK(status)) {
1592 smbd_server_connection_terminate(req->sconn,
1598 state->queue_entry.mem_ctx = state;
1599 state->queue_entry.vector = state->vector;
1600 state->queue_entry.count = ARRAY_SIZE(state->vector);
1601 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
1602 xconn->smb2.send_queue_len++;
1604 status = smbd_smb2_flush_send_queue(xconn);
1605 if (!NT_STATUS_IS_OK(status)) {
1606 smbd_server_connection_terminate(sconn,
1612 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1614 struct smbd_server_connection *sconn = req->sconn;
1615 struct smbXsrv_connection *xconn = sconn->conn;
1616 struct smbd_smb2_request *cur;
1617 const uint8_t *inhdr;
1619 uint64_t search_message_id;
1620 uint64_t search_async_id;
1623 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1625 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1626 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1627 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1630 * we don't need the request anymore
1631 * cancel requests never have a response
1633 DLIST_REMOVE(xconn->smb2.requests, req);
1636 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1637 const uint8_t *outhdr;
1638 uint64_t message_id;
1641 if (cur->compound_related) {
1643 * Never cancel anything in a compound request.
1644 * Way too hard to deal with the result.
1649 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1651 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1652 async_id = BVAL(outhdr, SMB2_HDR_PID);
1654 if (flags & SMB2_HDR_FLAG_ASYNC) {
1655 if (search_async_id == async_id) {
1656 found_id = async_id;
1660 if (search_message_id == message_id) {
1661 found_id = message_id;
1667 if (cur && cur->subreq) {
1668 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1669 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1670 "cancel opcode[%s] mid %llu\n",
1671 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1672 (unsigned long long)found_id ));
1673 tevent_req_cancel(cur->subreq);
1676 return NT_STATUS_OK;
1679 /*************************************************************
1680 Ensure an incoming tid is a valid one for us to access.
1681 Change to the associated uid credentials and chdir to the
1682 valid tid directory.
1683 *************************************************************/
1685 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1687 const uint8_t *inhdr;
1690 struct smbXsrv_tcon *tcon;
1692 NTTIME now = timeval_to_nttime(&req->request_time);
1696 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1698 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1699 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1701 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1702 in_tid = req->last_tid;
1707 status = smb2srv_tcon_lookup(req->session,
1708 in_tid, now, &tcon);
1709 if (!NT_STATUS_IS_OK(status)) {
1713 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1714 return NT_STATUS_ACCESS_DENIED;
1717 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1718 if (!set_current_service(tcon->compat, 0, true)) {
1719 return NT_STATUS_ACCESS_DENIED;
1723 req->last_tid = in_tid;
1725 return NT_STATUS_OK;
1728 /*************************************************************
1729 Ensure an incoming session_id is a valid one for us to access.
1730 *************************************************************/
1732 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1734 const uint8_t *inhdr;
1737 uint64_t in_session_id;
1738 struct smbXsrv_session *session = NULL;
1739 struct auth_session_info *session_info;
1741 NTTIME now = timeval_to_nttime(&req->request_time);
1743 req->session = NULL;
1746 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1748 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1749 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1750 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1752 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1753 in_session_id = req->last_session_id;
1756 req->last_session_id = 0;
1758 /* lookup an existing session */
1759 status = smb2srv_session_lookup(req->sconn->conn,
1763 req->session = session;
1764 req->last_session_id = in_session_id;
1766 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1767 switch (in_opcode) {
1768 case SMB2_OP_SESSSETUP:
1769 status = NT_STATUS_OK;
1775 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1776 switch (in_opcode) {
1778 case SMB2_OP_CREATE:
1779 case SMB2_OP_GETINFO:
1780 case SMB2_OP_SETINFO:
1781 return NT_STATUS_INVALID_HANDLE;
1784 * Notice the check for
1785 * (session_info == NULL)
1788 status = NT_STATUS_OK;
1792 if (!NT_STATUS_IS_OK(status)) {
1796 session_info = session->global->auth_session_info;
1797 if (session_info == NULL) {
1798 return NT_STATUS_INVALID_HANDLE;
1801 if (in_session_id != req->sconn->conn->last_session_id) {
1802 req->sconn->conn->last_session_id = in_session_id;
1803 set_current_user_info(session_info->unix_info->sanitized_username,
1804 session_info->unix_info->unix_name,
1805 session_info->info->domain_name);
1808 return NT_STATUS_OK;
1811 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1812 uint32_t data_length)
1814 struct smbXsrv_connection *xconn = req->sconn->conn;
1815 uint16_t needed_charge;
1816 uint16_t credit_charge = 1;
1817 const uint8_t *inhdr;
1819 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1821 if (xconn->smb2.credits.multicredit) {
1822 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1823 credit_charge = MAX(credit_charge, 1);
1826 needed_charge = (data_length - 1)/ 65536 + 1;
1828 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1829 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1830 credit_charge, needed_charge));
1832 if (needed_charge > credit_charge) {
1833 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1834 credit_charge, needed_charge));
1835 return NT_STATUS_INVALID_PARAMETER;
1838 return NT_STATUS_OK;
1841 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1842 size_t expected_body_size)
1844 struct iovec *inhdr_v;
1845 const uint8_t *inhdr;
1847 const uint8_t *inbody;
1849 size_t min_dyn_size = expected_body_size & 0x00000001;
1850 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1853 * The following should be checked already.
1855 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1856 return NT_STATUS_INTERNAL_ERROR;
1858 if (req->current_idx > max_idx) {
1859 return NT_STATUS_INTERNAL_ERROR;
1862 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1863 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1864 return NT_STATUS_INTERNAL_ERROR;
1866 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1867 return NT_STATUS_INTERNAL_ERROR;
1870 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1871 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1875 case SMB2_OP_GETINFO:
1879 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
1880 if (req->smb1req->unread_bytes < min_dyn_size) {
1881 return NT_STATUS_INVALID_PARAMETER;
1890 * Now check the expected body size,
1891 * where the last byte might be in the
1894 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1895 return NT_STATUS_INVALID_PARAMETER;
1897 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1898 return NT_STATUS_INVALID_PARAMETER;
1901 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1903 body_size = SVAL(inbody, 0x00);
1904 if (body_size != expected_body_size) {
1905 return NT_STATUS_INVALID_PARAMETER;
1908 return NT_STATUS_OK;
1911 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1913 struct smbXsrv_connection *xconn = req->sconn->conn;
1914 const struct smbd_smb2_dispatch_table *call = NULL;
1915 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1916 const uint8_t *inhdr;
1921 NTSTATUS session_status;
1922 uint32_t allowed_flags;
1923 NTSTATUS return_value;
1924 struct smbXsrv_session *x = NULL;
1925 bool signing_required = false;
1926 bool encryption_required = false;
1928 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1930 /* TODO: verify more things */
1932 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1933 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1934 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1935 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1936 smb2_opcode_name(opcode),
1937 (unsigned long long)mid));
1939 if (xconn->protocol >= PROTOCOL_SMB2_02) {
1941 * once the protocol is negotiated
1942 * SMB2_OP_NEGPROT is not allowed anymore
1944 if (opcode == SMB2_OP_NEGPROT) {
1945 /* drop the connection */
1946 return NT_STATUS_INVALID_PARAMETER;
1950 * if the protocol is not negotiated yet
1951 * only SMB2_OP_NEGPROT is allowed.
1953 if (opcode != SMB2_OP_NEGPROT) {
1954 /* drop the connection */
1955 return NT_STATUS_INVALID_PARAMETER;
1960 * Check if the client provided a valid session id,
1961 * if so smbd_smb2_request_check_session() calls
1962 * set_current_user_info().
1964 * As some command don't require a valid session id
1965 * we defer the check of the session_status
1967 session_status = smbd_smb2_request_check_session(req);
1970 signing_required = x->global->signing_required;
1971 encryption_required = x->global->encryption_required;
1973 if (opcode == SMB2_OP_SESSSETUP &&
1974 x->global->channels[0].signing_key.length) {
1975 signing_required = true;
1979 req->do_signing = false;
1980 req->do_encryption = false;
1981 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
1982 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
1983 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
1985 if (x != NULL && x->global->session_wire_id != tf_session_id) {
1986 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1987 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1988 (unsigned long long)x->global->session_wire_id,
1989 (unsigned long long)tf_session_id));
1991 * TODO: windows allows this...
1992 * should we drop the connection?
1994 * For now we just return ACCESS_DENIED
1995 * (Windows clients never trigger this)
1996 * and wait for an update of [MS-SMB2].
1998 return smbd_smb2_request_error(req,
1999 NT_STATUS_ACCESS_DENIED);
2002 req->do_encryption = true;
2005 if (encryption_required && !req->do_encryption) {
2006 return smbd_smb2_request_error(req,
2007 NT_STATUS_ACCESS_DENIED);
2010 call = smbd_smb2_call(opcode);
2012 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2015 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2016 SMB2_HDR_FLAG_SIGNED |
2018 if (opcode == SMB2_OP_CANCEL) {
2019 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2021 if ((flags & ~allowed_flags) != 0) {
2022 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2025 if (flags & SMB2_HDR_FLAG_CHAINED) {
2027 * This check is mostly for giving the correct error code
2028 * for compounded requests.
2030 if (!NT_STATUS_IS_OK(session_status)) {
2031 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2034 req->compat_chain_fsp = NULL;
2037 if (req->do_encryption) {
2038 signing_required = false;
2039 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2040 DATA_BLOB signing_key;
2044 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2045 * If the SMB2 header of the SMB2 NEGOTIATE
2046 * request has the SMB2_FLAGS_SIGNED bit set in the
2047 * Flags field, the server MUST fail the request
2048 * with STATUS_INVALID_PARAMETER.
2050 * Microsoft test tool checks this.
2053 if ((opcode == SMB2_OP_NEGPROT) &&
2054 (flags & SMB2_HDR_FLAG_SIGNED)) {
2055 status = NT_STATUS_INVALID_PARAMETER;
2057 status = NT_STATUS_USER_SESSION_DELETED;
2059 return smbd_smb2_request_error(req, status);
2062 signing_key = x->global->channels[0].signing_key;
2065 * If we have a signing key, we should
2068 if (signing_key.length > 0) {
2069 req->do_signing = true;
2072 status = smb2_signing_check_pdu(signing_key,
2074 SMBD_SMB2_IN_HDR_IOV(req),
2075 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2076 if (!NT_STATUS_IS_OK(status)) {
2077 return smbd_smb2_request_error(req, status);
2081 * Now that we know the request was correctly signed
2082 * we have to sign the response too.
2084 req->do_signing = true;
2086 if (!NT_STATUS_IS_OK(session_status)) {
2087 return smbd_smb2_request_error(req, session_status);
2089 } else if (opcode == SMB2_OP_CANCEL) {
2090 /* Cancel requests are allowed to skip the signing */
2091 } else if (signing_required) {
2093 * If signing is required we try to sign
2094 * a possible error response
2096 req->do_signing = true;
2097 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2100 if (flags & SMB2_HDR_FLAG_CHAINED) {
2101 req->compound_related = true;
2104 if (call->need_session) {
2105 if (!NT_STATUS_IS_OK(session_status)) {
2106 return smbd_smb2_request_error(req, session_status);
2110 if (call->need_tcon) {
2111 SMB_ASSERT(call->need_session);
2114 * This call needs to be run as user.
2116 * smbd_smb2_request_check_tcon()
2117 * calls change_to_user() on success.
2119 status = smbd_smb2_request_check_tcon(req);
2120 if (!NT_STATUS_IS_OK(status)) {
2121 return smbd_smb2_request_error(req, status);
2123 if (req->tcon->global->encryption_required) {
2124 encryption_required = true;
2126 if (encryption_required && !req->do_encryption) {
2127 return smbd_smb2_request_error(req,
2128 NT_STATUS_ACCESS_DENIED);
2132 if (call->fileid_ofs != 0) {
2133 size_t needed = call->fileid_ofs + 16;
2134 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2135 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2136 uint64_t file_id_persistent;
2137 uint64_t file_id_volatile;
2138 struct files_struct *fsp;
2140 SMB_ASSERT(call->need_tcon);
2142 if (needed > body_size) {
2143 return smbd_smb2_request_error(req,
2144 NT_STATUS_INVALID_PARAMETER);
2147 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2148 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2150 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2152 if (!call->allow_invalid_fileid) {
2153 return smbd_smb2_request_error(req,
2154 NT_STATUS_FILE_CLOSED);
2157 if (file_id_persistent != UINT64_MAX) {
2158 return smbd_smb2_request_error(req,
2159 NT_STATUS_FILE_CLOSED);
2161 if (file_id_volatile != UINT64_MAX) {
2162 return smbd_smb2_request_error(req,
2163 NT_STATUS_FILE_CLOSED);
2168 if (call->as_root) {
2169 SMB_ASSERT(call->fileid_ofs == 0);
2170 /* This call needs to be run as root */
2171 change_to_root_user();
2173 SMB_ASSERT(call->need_tcon);
2177 case SMB2_OP_NEGPROT:
2179 START_PROFILE(smb2_negprot);
2180 return_value = smbd_smb2_request_process_negprot(req);
2181 END_PROFILE(smb2_negprot);
2185 case SMB2_OP_SESSSETUP:
2187 START_PROFILE(smb2_sesssetup);
2188 return_value = smbd_smb2_request_process_sesssetup(req);
2189 END_PROFILE(smb2_sesssetup);
2193 case SMB2_OP_LOGOFF:
2195 START_PROFILE(smb2_logoff);
2196 return_value = smbd_smb2_request_process_logoff(req);
2197 END_PROFILE(smb2_logoff);
2203 START_PROFILE(smb2_tcon);
2204 return_value = smbd_smb2_request_process_tcon(req);
2205 END_PROFILE(smb2_tcon);
2211 START_PROFILE(smb2_tdis);
2212 return_value = smbd_smb2_request_process_tdis(req);
2213 END_PROFILE(smb2_tdis);
2217 case SMB2_OP_CREATE:
2219 START_PROFILE(smb2_create);
2220 return_value = smbd_smb2_request_process_create(req);
2221 END_PROFILE(smb2_create);
2227 START_PROFILE(smb2_close);
2228 return_value = smbd_smb2_request_process_close(req);
2229 END_PROFILE(smb2_close);
2235 START_PROFILE(smb2_flush);
2236 return_value = smbd_smb2_request_process_flush(req);
2237 END_PROFILE(smb2_flush);
2243 START_PROFILE(smb2_read);
2244 return_value = smbd_smb2_request_process_read(req);
2245 END_PROFILE(smb2_read);
2251 START_PROFILE(smb2_write);
2252 return_value = smbd_smb2_request_process_write(req);
2253 END_PROFILE(smb2_write);
2259 START_PROFILE(smb2_lock);
2260 return_value = smbd_smb2_request_process_lock(req);
2261 END_PROFILE(smb2_lock);
2267 START_PROFILE(smb2_ioctl);
2268 return_value = smbd_smb2_request_process_ioctl(req);
2269 END_PROFILE(smb2_ioctl);
2273 case SMB2_OP_CANCEL:
2275 START_PROFILE(smb2_cancel);
2276 return_value = smbd_smb2_request_process_cancel(req);
2277 END_PROFILE(smb2_cancel);
2281 case SMB2_OP_KEEPALIVE:
2283 START_PROFILE(smb2_keepalive);
2284 return_value = smbd_smb2_request_process_keepalive(req);
2285 END_PROFILE(smb2_keepalive);
2291 START_PROFILE(smb2_find);
2292 return_value = smbd_smb2_request_process_find(req);
2293 END_PROFILE(smb2_find);
2297 case SMB2_OP_NOTIFY:
2299 START_PROFILE(smb2_notify);
2300 return_value = smbd_smb2_request_process_notify(req);
2301 END_PROFILE(smb2_notify);
2305 case SMB2_OP_GETINFO:
2307 START_PROFILE(smb2_getinfo);
2308 return_value = smbd_smb2_request_process_getinfo(req);
2309 END_PROFILE(smb2_getinfo);
2313 case SMB2_OP_SETINFO:
2315 START_PROFILE(smb2_setinfo);
2316 return_value = smbd_smb2_request_process_setinfo(req);
2317 END_PROFILE(smb2_setinfo);
2323 START_PROFILE(smb2_break);
2324 return_value = smbd_smb2_request_process_break(req);
2325 END_PROFILE(smb2_break);
2330 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2333 return return_value;
2336 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2338 struct smbXsrv_connection *xconn = req->xconn;
2340 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2341 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2342 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2346 TALLOC_FREE(req->async_te);
2348 if (req->do_encryption &&
2349 (firsttf->iov_len == 0) &&
2350 (req->first_key.length == 0) &&
2351 (req->session != NULL) &&
2352 (req->session->global->encryption_key.length != 0))
2354 DATA_BLOB encryption_key = req->session->global->encryption_key;
2356 uint64_t session_id = req->session->global->session_wire_id;
2357 struct smbXsrv_session *x = req->session;
2358 uint64_t nonce_high;
2361 nonce_high = x->nonce_high;
2362 nonce_low = x->nonce_low;
2365 if (x->nonce_low == 0) {
2371 * We need to place the SMB2_TRANSFORM header before the
2376 * we need to remember the encryption key
2377 * and defer the signing/encryption until
2378 * we are sure that we do not change
2381 req->first_key = data_blob_dup_talloc(req, encryption_key);
2382 if (req->first_key.data == NULL) {
2383 return NT_STATUS_NO_MEMORY;
2386 tf = talloc_zero_array(req, uint8_t,
2389 return NT_STATUS_NO_MEMORY;
2392 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2393 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2394 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2395 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2397 firsttf->iov_base = (void *)tf;
2398 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2401 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2402 (req->last_key.length > 0) &&
2403 (firsttf->iov_len == 0))
2405 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2406 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2409 * As we are sure the header of the last request in the
2410 * compound chain will not change, we can to sign here
2411 * with the last signing key we remembered.
2413 status = smb2_signing_sign_pdu(req->last_key,
2416 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2417 if (!NT_STATUS_IS_OK(status)) {
2421 if (req->last_key.length > 0) {
2422 data_blob_clear_free(&req->last_key);
2425 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2427 if (req->current_idx < req->out.vector_count) {
2429 * We must process the remaining compound
2430 * SMB2 requests before any new incoming SMB2
2431 * requests. This is because incoming SMB2
2432 * requests may include a cancel for a
2433 * compound request we haven't processed
2436 struct tevent_immediate *im = tevent_create_immediate(req);
2438 return NT_STATUS_NO_MEMORY;
2441 if (req->do_signing && firsttf->iov_len == 0) {
2442 struct smbXsrv_session *x = req->session;
2443 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2446 * we need to remember the signing key
2447 * and defer the signing until
2448 * we are sure that we do not change
2451 req->last_key = data_blob_dup_talloc(req, signing_key);
2452 if (req->last_key.data == NULL) {
2453 return NT_STATUS_NO_MEMORY;
2457 tevent_schedule_immediate(im,
2459 smbd_smb2_request_dispatch_immediate,
2461 return NT_STATUS_OK;
2464 if (req->compound_related) {
2465 req->compound_related = false;
2468 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2470 /* Set credit for these operations (zero credits if this
2471 is a final reply for an async operation). */
2472 smb2_calculate_credits(req, req);
2475 * now check if we need to sign the current response
2477 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2478 status = smb2_signing_encrypt_pdu(req->first_key,
2481 req->out.vector_count - first_idx);
2482 if (!NT_STATUS_IS_OK(status)) {
2485 } else if (req->do_signing) {
2486 struct smbXsrv_session *x = req->session;
2487 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2489 status = smb2_signing_sign_pdu(signing_key,
2492 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2493 if (!NT_STATUS_IS_OK(status)) {
2497 if (req->first_key.length > 0) {
2498 data_blob_clear_free(&req->first_key);
2501 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2502 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2503 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2504 /* Dynamic part is NULL. Chop it off,
2505 We're going to send it via sendfile. */
2506 req->out.vector_count -= 1;
2510 * We're done with this request -
2511 * move it off the "being processed" queue.
2513 DLIST_REMOVE(xconn->smb2.requests, req);
2515 req->queue_entry.mem_ctx = req;
2516 req->queue_entry.vector = req->out.vector;
2517 req->queue_entry.count = req->out.vector_count;
2518 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry, NULL);
2519 xconn->smb2.send_queue_len++;
2521 status = smbd_smb2_flush_send_queue(xconn);
2522 if (!NT_STATUS_IS_OK(status)) {
2526 return NT_STATUS_OK;
2529 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2531 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2532 struct tevent_immediate *im,
2535 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2536 struct smbd_smb2_request);
2537 struct smbd_server_connection *sconn = req->sconn;
2542 if (DEBUGLEVEL >= 10) {
2543 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2544 req->current_idx, req->in.vector_count));
2545 print_req_vectors(req);
2548 status = smbd_smb2_request_dispatch(req);
2549 if (!NT_STATUS_IS_OK(status)) {
2550 smbd_server_connection_terminate(sconn, nt_errstr(status));
2554 status = smbd_smb2_request_next_incoming(sconn);
2555 if (!NT_STATUS_IS_OK(status)) {
2556 smbd_server_connection_terminate(sconn, nt_errstr(status));
2561 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2563 DATA_BLOB body, DATA_BLOB *dyn,
2564 const char *location)
2567 struct iovec *outbody_v;
2568 struct iovec *outdyn_v;
2569 uint32_t next_command_ofs;
2571 DEBUG(10,("smbd_smb2_request_done_ex: "
2572 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2573 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2575 (unsigned int)(dyn ? dyn->length : 0),
2578 if (body.length < 2) {
2579 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2582 if ((body.length % 2) != 0) {
2583 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2586 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2587 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2588 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2590 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2591 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2593 outbody_v->iov_base = (void *)body.data;
2594 outbody_v->iov_len = body.length;
2597 outdyn_v->iov_base = (void *)dyn->data;
2598 outdyn_v->iov_len = dyn->length;
2600 outdyn_v->iov_base = NULL;
2601 outdyn_v->iov_len = 0;
2604 /* see if we need to recalculate the offset to the next response */
2605 if (next_command_ofs > 0) {
2606 next_command_ofs = SMB2_HDR_BODY;
2607 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2608 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2611 if ((next_command_ofs % 8) != 0) {
2612 size_t pad_size = 8 - (next_command_ofs % 8);
2613 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2615 * if the dyn buffer is empty
2616 * we can use it to add padding
2620 pad = talloc_zero_array(req,
2623 return smbd_smb2_request_error(req,
2624 NT_STATUS_NO_MEMORY);
2627 outdyn_v->iov_base = (void *)pad;
2628 outdyn_v->iov_len = pad_size;
2631 * For now we copy the dynamic buffer
2632 * and add the padding to the new buffer
2639 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2640 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2642 new_size = old_size + pad_size;
2643 new_dyn = talloc_zero_array(req,
2645 if (new_dyn == NULL) {
2646 return smbd_smb2_request_error(req,
2647 NT_STATUS_NO_MEMORY);
2650 memcpy(new_dyn, old_dyn, old_size);
2651 memset(new_dyn + old_size, 0, pad_size);
2653 outdyn_v->iov_base = (void *)new_dyn;
2654 outdyn_v->iov_len = new_size;
2656 next_command_ofs += pad_size;
2659 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2661 return smbd_smb2_request_reply(req);
2664 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2667 const char *location)
2669 struct smbXsrv_connection *xconn = req->sconn->conn;
2672 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2673 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2675 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2676 req->current_idx, nt_errstr(status), info ? " +info" : "",
2680 /* Recvfile error. Drain incoming socket. */
2684 ret = drain_socket(xconn->transport.sock, unread_bytes);
2685 if (ret != unread_bytes) {
2689 error = NT_STATUS_IO_DEVICE_ERROR;
2691 error = map_nt_error_from_unix_common(errno);
2694 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2695 "ret[%u] errno[%d] => %s\n",
2696 (unsigned)unread_bytes,
2697 (unsigned)ret, errno, nt_errstr(error)));
2702 body.data = outhdr + SMB2_HDR_BODY;
2704 SSVAL(body.data, 0, 9);
2707 SIVAL(body.data, 0x04, info->length);
2709 /* Allocated size of req->out.vector[i].iov_base
2710 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2711 * 1 byte without having to do an alloc.
2714 info->data = ((uint8_t *)outhdr) +
2715 OUTVEC_ALLOC_SIZE - 1;
2717 SCVAL(info->data, 0, 0);
2721 * Note: Even if there is an error, continue to process the request.
2725 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2729 struct smbd_smb2_send_break_state {
2730 struct smbd_server_connection *sconn;
2731 struct smbd_smb2_send_queue queue_entry;
2732 uint8_t nbt_hdr[NBT_HDR_SIZE];
2733 uint8_t tf[SMB2_TF_HDR_SIZE];
2734 uint8_t hdr[SMB2_HDR_BODY];
2735 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2739 static NTSTATUS smbd_smb2_send_break(struct smbd_server_connection *sconn,
2740 struct smbXsrv_session *session,
2741 struct smbXsrv_tcon *tcon,
2742 const uint8_t *body,
2745 struct smbd_smb2_send_break_state *state;
2746 struct smbXsrv_connection *xconn = sconn->conn;
2747 bool do_encryption = session->global->encryption_required;
2748 uint64_t nonce_high = 0;
2749 uint64_t nonce_low = 0;
2753 if (tcon->global->encryption_required) {
2754 do_encryption = true;
2757 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
2760 state = talloc_zero_size(sconn, statelen);
2761 if (state == NULL) {
2762 return NT_STATUS_NO_MEMORY;
2764 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
2765 state->sconn = sconn;
2767 if (do_encryption) {
2768 nonce_high = session->nonce_high;
2769 nonce_low = session->nonce_low;
2771 session->nonce_low += 1;
2772 if (session->nonce_low == 0) {
2773 session->nonce_low += 1;
2774 session->nonce_high += 1;
2778 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2779 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
2780 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
2781 SBVAL(state->tf, SMB2_TF_SESSION_ID, session->global->session_wire_id);
2783 SIVAL(state->hdr, 0, SMB2_MAGIC);
2784 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2785 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
2786 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
2787 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2788 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
2789 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2790 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
2791 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2792 SIVAL(state->hdr, SMB2_HDR_PID, 0);
2793 SIVAL(state->hdr, SMB2_HDR_TID, 0);
2794 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
2795 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
2797 state->vector[0] = (struct iovec) {
2798 .iov_base = state->nbt_hdr,
2799 .iov_len = sizeof(state->nbt_hdr)
2802 if (do_encryption) {
2803 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2804 .iov_base = state->tf,
2805 .iov_len = sizeof(state->tf)
2808 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2814 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
2815 .iov_base = state->hdr,
2816 .iov_len = sizeof(state->hdr)
2819 memcpy(state->body, body, body_len);
2821 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
2822 .iov_base = state->body,
2823 .iov_len = body_len /* no sizeof(state->body) .. :-) */
2827 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
2830 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2832 if (do_encryption) {
2833 DATA_BLOB encryption_key = session->global->encryption_key;
2835 status = smb2_signing_encrypt_pdu(encryption_key,
2837 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2838 SMBD_SMB2_NUM_IOV_PER_REQ);
2839 if (!NT_STATUS_IS_OK(status)) {
2844 state->queue_entry.mem_ctx = state;
2845 state->queue_entry.vector = state->vector;
2846 state->queue_entry.count = ARRAY_SIZE(state->vector);
2847 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
2848 xconn->smb2.send_queue_len++;
2850 status = smbd_smb2_flush_send_queue(xconn);
2851 if (!NT_STATUS_IS_OK(status)) {
2855 return NT_STATUS_OK;
2858 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2859 struct smbXsrv_session *session,
2860 struct smbXsrv_tcon *tcon,
2861 struct smbXsrv_open *op,
2862 uint8_t oplock_level)
2866 SSVAL(body, 0x00, sizeof(body));
2867 SCVAL(body, 0x02, oplock_level);
2868 SCVAL(body, 0x03, 0); /* reserved */
2869 SIVAL(body, 0x04, 0); /* reserved */
2870 SBVAL(body, 0x08, op->global->open_persistent_id);
2871 SBVAL(body, 0x10, op->global->open_volatile_id);
2873 return smbd_smb2_send_break(sconn, session, tcon, body, sizeof(body));
2876 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2880 uint64_t file_id_persistent;
2881 uint64_t file_id_volatile;
2882 struct smbXsrv_open *op = NULL;
2883 struct files_struct *fsp = NULL;
2884 const uint8_t *body = NULL;
2887 * This is only called with a pktbuf
2888 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
2892 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
2893 /* Transform header. Cannot recvfile. */
2896 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
2897 /* Not SMB2. Normal error path will cope. */
2900 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
2901 /* Not SMB2. Normal error path will cope. */
2904 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
2905 /* Needs to be a WRITE. */
2908 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
2909 /* Chained. Cannot recvfile. */
2912 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
2913 if (flags & SMB2_HDR_FLAG_CHAINED) {
2914 /* Chained. Cannot recvfile. */
2917 if (flags & SMB2_HDR_FLAG_SIGNED) {
2918 /* Signed. Cannot recvfile. */
2922 body = &state->pktbuf[SMB2_HDR_BODY];
2924 file_id_persistent = BVAL(body, 0x10);
2925 file_id_volatile = BVAL(body, 0x18);
2927 status = smb2srv_open_lookup(state->req->sconn->conn,
2932 if (!NT_STATUS_IS_OK(status)) {
2940 if (fsp->conn == NULL) {
2944 if (IS_IPC(fsp->conn)) {
2947 if (IS_PRINT(fsp->conn)) {
2951 DEBUG(10,("Doing recvfile write len = %u\n",
2952 (unsigned int)(state->pktfull - state->pktlen)));
2957 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2959 struct smbXsrv_connection *xconn = sconn->conn;
2960 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
2961 size_t max_send_queue_len;
2962 size_t cur_send_queue_len;
2964 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
2966 * we're not supposed to do any io
2968 return NT_STATUS_OK;
2971 if (state->req != NULL) {
2973 * if there is already a tstream_readv_pdu
2974 * pending, we are done.
2976 return NT_STATUS_OK;
2979 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
2980 cur_send_queue_len = xconn->smb2.send_queue_len;
2982 if (cur_send_queue_len > max_send_queue_len) {
2984 * if we have a lot of requests to send,
2985 * we wait until they are on the wire until we
2986 * ask for the next request.
2988 return NT_STATUS_OK;
2991 /* ask for the next request */
2992 ZERO_STRUCTP(state);
2993 state->req = smbd_smb2_request_allocate(xconn);
2994 if (state->req == NULL) {
2995 return NT_STATUS_NO_MEMORY;
2997 state->req->sconn = sconn;
2998 state->req->xconn = xconn;
2999 state->min_recv_size = lp_min_receive_file_size();
3001 TEVENT_FD_READABLE(xconn->transport.fde);
3003 return NT_STATUS_OK;
3006 void smbd_smb2_first_negprot(struct smbXsrv_connection *xconn,
3007 uint8_t *inbuf, size_t size)
3009 struct smbd_server_connection *sconn = xconn->sconn;
3011 struct smbd_smb2_request *req = NULL;
3013 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3014 (unsigned int)size));
3016 status = smbd_initialize_smb2(xconn);
3017 if (!NT_STATUS_IS_OK(status)) {
3018 smbd_server_connection_terminate(sconn, nt_errstr(status));
3022 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
3023 if (!NT_STATUS_IS_OK(status)) {
3024 smbd_server_connection_terminate(sconn, nt_errstr(status));
3028 status = smbd_smb2_request_validate(req);
3029 if (!NT_STATUS_IS_OK(status)) {
3030 smbd_server_connection_terminate(sconn, nt_errstr(status));
3034 status = smbd_smb2_request_setup_out(req);
3035 if (!NT_STATUS_IS_OK(status)) {
3036 smbd_server_connection_terminate(sconn, nt_errstr(status));
3040 status = smbd_smb2_request_dispatch(req);
3041 if (!NT_STATUS_IS_OK(status)) {
3042 smbd_server_connection_terminate(sconn, nt_errstr(status));
3046 status = smbd_smb2_request_next_incoming(sconn);
3047 if (!NT_STATUS_IS_OK(status)) {
3048 smbd_server_connection_terminate(sconn, nt_errstr(status));
3052 sconn->num_requests++;
3055 static int socket_error_from_errno(int ret,
3069 if (sys_errno == 0) {
3073 if (sys_errno == EINTR) {
3078 if (sys_errno == EINPROGRESS) {
3083 if (sys_errno == EAGAIN) {
3088 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3089 if (sys_errno == ENOMEM) {
3095 #if EWOULDBLOCK != EAGAIN
3096 if (sys_errno == EWOULDBLOCK) {
3106 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3112 if (xconn->smb2.send_queue == NULL) {
3113 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3114 return NT_STATUS_OK;
3117 while (xconn->smb2.send_queue != NULL) {
3118 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3120 if (e->sendfile_header != NULL) {
3125 for (i=0; i < e->count; i++) {
3126 size += e->vector[i].iov_len;
3129 if (size <= e->sendfile_header->length) {
3130 buf = e->sendfile_header->data;
3132 buf = talloc_array(e->mem_ctx, uint8_t, size);
3134 return NT_STATUS_NO_MEMORY;
3139 for (i=0; i < e->count; i++) {
3141 e->vector[i].iov_base,
3142 e->vector[i].iov_len);
3143 size += e->vector[i].iov_len;
3146 e->sendfile_header->data = buf;
3147 e->sendfile_header->length = size;
3150 xconn->smb2.send_queue_len--;
3151 DLIST_REMOVE(xconn->smb2.send_queue, e);
3153 * This triggers the sendfile path via
3156 talloc_free(e->mem_ctx);
3160 ret = writev(xconn->transport.sock, e->vector, e->count);
3162 /* propagate end of file */
3163 return NT_STATUS_INTERNAL_ERROR;
3165 err = socket_error_from_errno(ret, errno, &retry);
3168 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3169 return NT_STATUS_OK;
3172 return map_nt_error_from_unix_common(err);
3175 if (ret < e->vector[0].iov_len) {
3177 base = (uint8_t *)e->vector[0].iov_base;
3179 e->vector[0].iov_base = (void *)base;
3180 e->vector[0].iov_len -= ret;
3183 ret -= e->vector[0].iov_len;
3189 * there're maybe some empty vectors at the end
3190 * which we need to skip, otherwise we would get
3191 * ret == 0 from the readv() call and return EPIPE
3193 while (e->count > 0) {
3194 if (e->vector[0].iov_len > 0) {
3202 /* we have more to write */
3203 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3204 return NT_STATUS_OK;
3207 xconn->smb2.send_queue_len--;
3208 DLIST_REMOVE(xconn->smb2.send_queue, e);
3209 talloc_free(e->mem_ctx);
3212 return NT_STATUS_OK;
3215 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3218 struct smbd_server_connection *sconn = xconn->sconn;
3219 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3220 struct smbd_smb2_request *req = NULL;
3221 size_t min_recvfile_size = UINT32_MAX;
3228 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3230 * we're not supposed to do any io
3232 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3233 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3234 return NT_STATUS_OK;
3237 if (fde_flags & TEVENT_FD_WRITE) {
3238 status = smbd_smb2_flush_send_queue(xconn);
3239 if (!NT_STATUS_IS_OK(status)) {
3244 if (!(fde_flags & TEVENT_FD_READ)) {
3245 return NT_STATUS_OK;
3248 if (state->req == NULL) {
3249 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3250 return NT_STATUS_OK;
3254 if (!state->hdr.done) {
3255 state->hdr.done = true;
3257 state->vector.iov_base = (void *)state->hdr.nbt;
3258 state->vector.iov_len = NBT_HDR_SIZE;
3261 ret = readv(xconn->transport.sock, &state->vector, 1);
3263 /* propagate end of file */
3264 return NT_STATUS_END_OF_FILE;
3266 err = socket_error_from_errno(ret, errno, &retry);
3269 TEVENT_FD_READABLE(xconn->transport.fde);
3270 return NT_STATUS_OK;
3273 return map_nt_error_from_unix_common(err);
3276 if (ret < state->vector.iov_len) {
3278 base = (uint8_t *)state->vector.iov_base;
3280 state->vector.iov_base = (void *)base;
3281 state->vector.iov_len -= ret;
3282 /* we have more to read */
3283 TEVENT_FD_READABLE(xconn->transport.fde);
3284 return NT_STATUS_OK;
3287 if (state->pktlen > 0) {
3288 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3290 * Not a possible receivefile write.
3291 * Read the rest of the data.
3293 state->doing_receivefile = false;
3295 state->pktbuf = talloc_realloc(state->req,
3299 if (state->pktbuf == NULL) {
3300 return NT_STATUS_NO_MEMORY;
3303 state->vector.iov_base = (void *)(state->pktbuf +
3305 state->vector.iov_len = (state->pktfull -
3308 state->pktlen = state->pktfull;
3313 * Either this is a receivefile write so we've
3314 * done a short read, or if not we have all the data.
3320 * Now we analyze the NBT header
3322 if (state->hdr.nbt[0] != 0x00) {
3323 state->min_recv_size = 0;
3325 state->pktfull = smb2_len(state->hdr.nbt);
3326 if (state->pktfull == 0) {
3330 if (state->min_recv_size != 0) {
3331 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3332 min_recvfile_size += state->min_recv_size;
3335 if (state->pktfull > min_recvfile_size) {
3337 * Might be a receivefile write. Read the SMB2 HEADER +
3338 * SMB2_WRITE header first. Set 'doing_receivefile'
3339 * as we're *attempting* receivefile write. If this
3340 * turns out not to be a SMB2_WRITE request or otherwise
3341 * not suitable then we'll just read the rest of the data
3342 * the next time this function is called.
3344 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3345 state->doing_receivefile = true;
3347 state->pktlen = state->pktfull;
3350 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3351 if (state->pktbuf == NULL) {
3352 return NT_STATUS_NO_MEMORY;
3355 state->vector.iov_base = (void *)state->pktbuf;
3356 state->vector.iov_len = state->pktlen;
3362 if (state->hdr.nbt[0] != 0x00) {
3363 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3364 state->hdr.nbt[0]));
3367 ZERO_STRUCTP(state);
3369 state->min_recv_size = lp_min_receive_file_size();
3377 req->request_time = timeval_current();
3378 now = timeval_to_nttime(&req->request_time);
3380 status = smbd_smb2_inbuf_parse_compound(xconn,
3386 &req->in.vector_count);
3387 if (!NT_STATUS_IS_OK(status)) {
3391 if (state->doing_receivefile) {
3392 req->smb1req = talloc_zero(req, struct smb_request);
3393 if (req->smb1req == NULL) {
3394 return NT_STATUS_NO_MEMORY;
3396 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3399 ZERO_STRUCTP(state);
3401 req->current_idx = 1;
3403 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3404 req->current_idx, req->in.vector_count));
3406 status = smbd_smb2_request_validate(req);
3407 if (!NT_STATUS_IS_OK(status)) {
3411 status = smbd_smb2_request_setup_out(req);
3412 if (!NT_STATUS_IS_OK(status)) {
3416 status = smbd_smb2_request_dispatch(req);
3417 if (!NT_STATUS_IS_OK(status)) {
3421 sconn->num_requests++;
3423 /* The timeout_processing function isn't run nearly
3424 often enough to implement 'max log size' without
3425 overrunning the size of the file by many megabytes.
3426 This is especially true if we are running at debug
3427 level 10. Checking every 50 SMB2s is a nice
3428 tradeoff of performance vs log file size overrun. */
3430 if ((sconn->num_requests % 50) == 0 &&
3431 need_to_check_log_size()) {
3432 change_to_root_user();
3436 status = smbd_smb2_request_next_incoming(sconn);
3437 if (!NT_STATUS_IS_OK(status)) {
3441 return NT_STATUS_OK;
3444 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3445 struct tevent_fd *fde,
3449 struct smbXsrv_connection *xconn =
3450 talloc_get_type_abort(private_data,
3451 struct smbXsrv_connection);
3452 struct smbd_server_connection *sconn = xconn->sconn;
3455 status = smbd_smb2_io_handler(xconn, flags);
3456 if (!NT_STATUS_IS_OK(status)) {
3457 smbd_server_connection_terminate(sconn, nt_errstr(status));