2 Unix SMB/CIFS implementation.
5 Copyright (C) Stefan Metzmacher 2009
6 Copyright (C) Jeremy Allison 2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../libcli/smb/smb_common.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "../lib/util/tevent_ntstatus.h"
28 #include "smbprofile.h"
29 #include "../lib/util/bitmap.h"
30 #include "../librpc/gen_ndr/krb5pac.h"
33 static void smbd_smb2_connection_handler(struct tevent_context *ev,
34 struct tevent_fd *fde,
37 static NTSTATUS smbd_smb2_io_handler(struct smbd_server_connection *sconn,
40 static const struct smbd_smb2_dispatch_table {
47 bool allow_invalid_fileid;
48 } smbd_smb2_table[] = {
49 #define _OP(o) .opcode = o, .name = #o
54 _OP(SMB2_OP_SESSSETUP),
64 * This call needs to be run as root.
66 * smbd_smb2_request_process_tcon()
67 * calls make_connection_snum(), which will call
68 * change_to_user(), when needed.
102 .need_session = true,
107 .need_session = true,
110 .allow_invalid_fileid = true,
115 _OP(SMB2_OP_KEEPALIVE),
119 .need_session = true,
124 .need_session = true,
128 _OP(SMB2_OP_GETINFO),
129 .need_session = true,
133 _OP(SMB2_OP_SETINFO),
134 .need_session = true,
139 .need_session = true,
144 * as LEASE breaks does not
150 const char *smb2_opcode_name(uint16_t opcode)
152 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
153 return "Bad SMB2 opcode";
155 return smbd_smb2_table[opcode].name;
158 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
160 const struct smbd_smb2_dispatch_table *ret = NULL;
162 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
166 ret = &smbd_smb2_table[opcode];
168 SMB_ASSERT(ret->opcode == opcode);
173 static void print_req_vectors(const struct smbd_smb2_request *req)
177 for (i = 0; i < req->in.vector_count; i++) {
178 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
180 (unsigned int)req->in.vector[i].iov_len);
182 for (i = 0; i < req->out.vector_count; i++) {
183 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
185 (unsigned int)req->out.vector[i].iov_len);
189 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
191 if (size < (4 + SMB2_HDR_BODY)) {
195 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
202 static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
204 TALLOC_FREE(sconn->smb1.fde);
206 sconn->smb2.send_queue = NULL;
208 sconn->smb2.seqnum_low = 0;
209 sconn->smb2.seqnum_range = 1;
210 sconn->smb2.credits_granted = 1;
211 sconn->smb2.max_credits = lp_smb2_max_credits();
212 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
213 sconn->smb2.max_credits);
214 if (sconn->smb2.credits_bitmap == NULL) {
215 return NT_STATUS_NO_MEMORY;
218 sconn->smb2.fde = tevent_add_fd(sconn->ev_ctx,
222 smbd_smb2_connection_handler,
224 if (sconn->smb2.fde == NULL) {
225 return NT_STATUS_NO_MEMORY;
228 /* Ensure child is set to non-blocking mode */
229 set_blocking(sconn->sock, false);
233 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
234 #define _smb2_setlen(_buf,len) do { \
235 uint8_t *buf = (uint8_t *)_buf; \
237 buf[1] = ((len)&0xFF0000)>>16; \
238 buf[2] = ((len)&0xFF00)>>8; \
239 buf[3] = (len)&0xFF; \
242 static void smb2_setup_nbt_length(struct iovec *vector, int count)
247 for (i=1; i < count; i++) {
248 len += vector[i].iov_len;
251 _smb2_setlen(vector[0].iov_base, len);
254 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
256 data_blob_clear_free(&req->first_key);
257 data_blob_clear_free(&req->last_key);
261 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
263 TALLOC_CTX *mem_pool;
264 struct smbd_smb2_request *req;
267 /* Enable this to find subtle valgrind errors. */
268 mem_pool = talloc_init("smbd_smb2_request_allocate");
270 mem_pool = talloc_tos();
272 if (mem_pool == NULL) {
276 req = talloc_zero(mem_pool, struct smbd_smb2_request);
278 talloc_free(mem_pool);
281 talloc_reparent(mem_pool, mem_ctx, req);
283 TALLOC_FREE(mem_pool);
286 req->last_session_id = UINT64_MAX;
287 req->last_tid = UINT32_MAX;
289 talloc_set_destructor(req, smbd_smb2_request_destructor);
294 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn,
298 struct smbd_smb2_request *req,
302 TALLOC_CTX *mem_ctx = req;
306 uint8_t *first_hdr = buf;
307 size_t verified_buflen = 0;
312 * Note: index '0' is reserved for the transport protocol
314 iov = req->in._vector;
316 while (taken < buflen) {
317 size_t len = buflen - taken;
318 uint8_t *hdr = first_hdr + taken;
321 size_t next_command_ofs;
323 uint8_t *body = NULL;
327 if (verified_buflen > taken) {
328 len = verified_buflen - taken;
335 DEBUG(10, ("%d bytes left, expected at least %d\n",
339 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
340 struct smbXsrv_session *s = NULL;
342 struct iovec tf_iov[2];
346 if (conn->protocol < PROTOCOL_SMB2_24) {
347 DEBUG(10, ("Got SMB2_TRANSFORM header, "
348 "but dialect[0x%04X] is used\n",
349 conn->smb2.server.dialect));
353 if (!(conn->smb2.server.capabilities & SMB2_CAP_ENCRYPTION)) {
354 DEBUG(10, ("Got SMB2_TRANSFORM header, "
355 "but not negotiated "
356 "client[0x%08X] server[0x%08X]\n",
357 conn->smb2.client.capabilities,
358 conn->smb2.server.capabilities));
362 if (len < SMB2_TF_HDR_SIZE) {
363 DEBUG(1, ("%d bytes left, expected at least %d\n",
364 (int)len, SMB2_TF_HDR_SIZE));
368 tf_len = SMB2_TF_HDR_SIZE;
371 hdr = first_hdr + taken;
372 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
373 uid = BVAL(tf, SMB2_TF_SESSION_ID);
375 if (len < SMB2_TF_HDR_SIZE + enc_len) {
376 DEBUG(1, ("%d bytes left, expected at least %d\n",
378 (int)(SMB2_TF_HDR_SIZE + enc_len)));
382 status = smb2srv_session_lookup(conn, uid, now, &s);
384 DEBUG(1, ("invalid session[%llu] in "
385 "SMB2_TRANSFORM header\n",
386 (unsigned long long)uid));
388 return NT_STATUS_USER_SESSION_DELETED;
391 tf_iov[0].iov_base = (void *)tf;
392 tf_iov[0].iov_len = tf_len;
393 tf_iov[1].iov_base = (void *)hdr;
394 tf_iov[1].iov_len = enc_len;
396 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
399 if (!NT_STATUS_IS_OK(status)) {
404 verified_buflen = taken + enc_len;
409 * We need the header plus the body length field
412 if (len < SMB2_HDR_BODY + 2) {
413 DEBUG(10, ("%d bytes left, expected at least %d\n",
414 (int)len, SMB2_HDR_BODY));
417 if (IVAL(hdr, 0) != SMB2_MAGIC) {
418 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
422 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
423 DEBUG(10, ("Got HDR len %d, expected %d\n",
424 SVAL(hdr, 4), SMB2_HDR_BODY));
429 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
430 body_size = SVAL(hdr, SMB2_HDR_BODY);
432 if (next_command_ofs != 0) {
433 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
436 if (next_command_ofs > full_size) {
439 full_size = next_command_ofs;
446 if (body_size > (full_size - SMB2_HDR_BODY)) {
448 * let the caller handle the error
450 body_size = full_size - SMB2_HDR_BODY;
452 body = hdr + SMB2_HDR_BODY;
453 dyn = body + body_size;
454 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
456 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
457 struct iovec *iov_tmp = NULL;
458 struct iovec *iov_alloc = NULL;
460 if (iov != req->in._vector) {
464 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
467 SMBD_SMB2_NUM_IOV_PER_REQ);
468 if (iov_tmp == NULL) {
469 TALLOC_FREE(iov_alloc);
470 return NT_STATUS_NO_MEMORY;
473 if (iov_alloc == NULL) {
476 sizeof(req->in._vector));
482 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
484 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
485 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
486 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
487 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
488 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
489 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
490 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
491 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
501 if (iov != req->in._vector) {
504 return NT_STATUS_INVALID_PARAMETER;
507 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
508 uint8_t *inbuf, size_t size,
509 struct smbd_smb2_request **_req)
511 struct smbd_smb2_request *req;
512 uint32_t protocol_version;
513 const uint8_t *inhdr = NULL;
515 uint32_t next_command_ofs;
519 if (size < (4 + SMB2_HDR_BODY + 2)) {
520 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
521 return NT_STATUS_INVALID_PARAMETER;
526 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
527 if (protocol_version != SMB2_MAGIC) {
528 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
530 return NT_STATUS_INVALID_PARAMETER;
533 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
534 if (cmd != SMB2_OP_NEGPROT) {
535 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
537 return NT_STATUS_INVALID_PARAMETER;
540 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
541 if (next_command_ofs != 0) {
542 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
544 return NT_STATUS_INVALID_PARAMETER;
547 req = smbd_smb2_request_allocate(sconn);
549 return NT_STATUS_NO_MEMORY;
553 talloc_steal(req, inbuf);
555 req->request_time = timeval_current();
556 now = timeval_to_nttime(&req->request_time);
558 status = smbd_smb2_inbuf_parse_compound(sconn->conn,
560 inbuf + NBT_HDR_SIZE,
562 req, &req->in.vector,
563 &req->in.vector_count);
564 if (!NT_STATUS_IS_OK(status)) {
569 req->current_idx = 1;
575 static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
576 uint64_t message_id, uint64_t seq_id)
578 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
581 if (seq_id < sconn->smb2.seqnum_low) {
582 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
583 "%llu (sequence id %llu) "
584 "(granted = %u, low = %llu, range = %u)\n",
585 (unsigned long long)message_id,
586 (unsigned long long)seq_id,
587 (unsigned int)sconn->smb2.credits_granted,
588 (unsigned long long)sconn->smb2.seqnum_low,
589 (unsigned int)sconn->smb2.seqnum_range));
593 if (seq_id >= sconn->smb2.seqnum_low + sconn->smb2.seqnum_range) {
594 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
595 "%llu (sequence id %llu) "
596 "(granted = %u, low = %llu, range = %u)\n",
597 (unsigned long long)message_id,
598 (unsigned long long)seq_id,
599 (unsigned int)sconn->smb2.credits_granted,
600 (unsigned long long)sconn->smb2.seqnum_low,
601 (unsigned int)sconn->smb2.seqnum_range));
605 offset = seq_id % sconn->smb2.max_credits;
607 if (bitmap_query(credits_bm, offset)) {
608 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
609 "%llu (sequence id %llu) "
610 "(granted = %u, low = %llu, range = %u) "
612 (unsigned long long)message_id,
613 (unsigned long long)seq_id,
614 (unsigned int)sconn->smb2.credits_granted,
615 (unsigned long long)sconn->smb2.seqnum_low,
616 (unsigned int)sconn->smb2.seqnum_range,
621 /* Mark the message_ids as seen in the bitmap. */
622 bitmap_set(credits_bm, offset);
624 if (seq_id != sconn->smb2.seqnum_low) {
629 * Move the window forward by all the message_id's
632 while (bitmap_query(credits_bm, offset)) {
633 DEBUG(10,("smb2_validate_sequence_number: clearing "
634 "id %llu (position %u) from bitmap\n",
635 (unsigned long long)(sconn->smb2.seqnum_low),
637 bitmap_clear(credits_bm, offset);
639 sconn->smb2.seqnum_low += 1;
640 sconn->smb2.seqnum_range -= 1;
641 offset = sconn->smb2.seqnum_low % sconn->smb2.max_credits;
647 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
648 const uint8_t *inhdr)
650 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
651 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
652 uint16_t credit_charge = 1;
655 if (opcode == SMB2_OP_CANCEL) {
656 /* SMB2_CANCEL requests by definition resend messageids. */
660 if (sconn->smb2.supports_multicredit) {
661 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
662 credit_charge = MAX(credit_charge, 1);
665 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
666 "credits_granted %llu, "
667 "seqnum low/range: %llu/%llu\n",
668 (unsigned long long) message_id,
669 (unsigned long long) credit_charge,
670 (unsigned long long) sconn->smb2.credits_granted,
671 (unsigned long long) sconn->smb2.seqnum_low,
672 (unsigned long long) sconn->smb2.seqnum_range));
674 if (sconn->smb2.credits_granted < credit_charge) {
675 DEBUG(0, ("smb2_validate_message_id: client used more "
676 "credits than granted, mid %llu, charge %llu, "
677 "credits_granted %llu, "
678 "seqnum low/range: %llu/%llu\n",
679 (unsigned long long) message_id,
680 (unsigned long long) credit_charge,
681 (unsigned long long) sconn->smb2.credits_granted,
682 (unsigned long long) sconn->smb2.seqnum_low,
683 (unsigned long long) sconn->smb2.seqnum_range));
688 * now check the message ids
690 * for multi-credit requests we need to check all current mid plus
691 * the implicit mids caused by the credit charge
692 * e.g. current mid = 15, charge 5 => mark 15-19 as used
695 for (i = 0; i <= (credit_charge-1); i++) {
696 uint64_t id = message_id + i;
699 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
700 (unsigned long long)message_id,
702 (unsigned long long)id));
704 ok = smb2_validate_sequence_number(sconn, message_id, id);
710 /* substract used credits */
711 sconn->smb2.credits_granted -= credit_charge;
716 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
721 count = req->in.vector_count;
723 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
724 /* It's not a SMB2 request */
725 return NT_STATUS_INVALID_PARAMETER;
728 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
729 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
730 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
731 const uint8_t *inhdr = NULL;
733 if (hdr->iov_len != SMB2_HDR_BODY) {
734 return NT_STATUS_INVALID_PARAMETER;
737 if (body->iov_len < 2) {
738 return NT_STATUS_INVALID_PARAMETER;
741 inhdr = (const uint8_t *)hdr->iov_base;
743 /* Check the SMB2 header */
744 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
745 return NT_STATUS_INVALID_PARAMETER;
748 if (!smb2_validate_message_id(req->sconn, inhdr)) {
749 return NT_STATUS_INVALID_PARAMETER;
756 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
757 const struct iovec *in_vector,
758 struct iovec *out_vector)
760 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
761 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
762 uint16_t credit_charge = 1;
763 uint16_t credits_requested;
767 uint16_t credits_granted = 0;
768 uint64_t credits_possible;
769 uint16_t current_max_credits;
772 * first we grant only 1/16th of the max range.
774 * Windows also starts with the 1/16th and then grants
775 * more later. I was only able to trigger higher
776 * values, when using a very high credit charge.
778 * TODO: scale up depending on load, free memory
780 * Maybe also on the relationship between number
781 * of requests and the used sequence number.
782 * Which means we would grant more credits
783 * for client which use multi credit requests.
785 current_max_credits = sconn->smb2.max_credits / 16;
786 current_max_credits = MAX(current_max_credits, 1);
788 if (sconn->smb2.supports_multicredit) {
789 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
790 credit_charge = MAX(credit_charge, 1);
793 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
794 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
795 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
796 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
798 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
800 if (sconn->smb2.max_credits < credit_charge) {
801 smbd_server_connection_terminate(sconn,
802 "client error: credit charge > max credits\n");
806 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
808 * In case we already send an async interim
809 * response, we should not grant
810 * credits on the final response.
813 } else if (credits_requested > 0) {
814 uint16_t additional_max = 0;
815 uint16_t additional_credits = credits_requested - 1;
818 case SMB2_OP_NEGPROT:
820 case SMB2_OP_SESSSETUP:
822 * Windows 2012 RC1 starts to grant
824 * with a successful session setup
826 if (NT_STATUS_IS_OK(out_status)) {
832 * We match windows and only grant additional credits
839 additional_credits = MIN(additional_credits, additional_max);
841 credits_granted = credit_charge + additional_credits;
842 } else if (sconn->smb2.credits_granted == 0) {
844 * Make sure the client has always at least one credit
850 * sequence numbers should not wrap
852 * 1. calculate the possible credits until
853 * the sequence numbers start to wrap on 64-bit.
855 * 2. UINT64_MAX is used for Break Notifications.
857 * 2. truncate the possible credits to the maximum
858 * credits we want to grant to the client in total.
860 * 3. remove the range we'll already granted to the client
861 * this makes sure the client consumes the lowest sequence
862 * number, before we can grant additional credits.
864 credits_possible = UINT64_MAX - sconn->smb2.seqnum_low;
865 if (credits_possible > 0) {
866 /* remove UINT64_MAX */
867 credits_possible -= 1;
869 credits_possible = MIN(credits_possible, current_max_credits);
870 credits_possible -= sconn->smb2.seqnum_range;
872 credits_granted = MIN(credits_granted, credits_possible);
874 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
875 sconn->smb2.credits_granted += credits_granted;
876 sconn->smb2.seqnum_range += credits_granted;
878 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
879 "granted %u, current possible/max %u/%u, "
880 "total granted/max/low/range %u/%u/%llu/%u\n",
881 (unsigned int)credits_requested,
882 (unsigned int)credit_charge,
883 (unsigned int)credits_granted,
884 (unsigned int)credits_possible,
885 (unsigned int)current_max_credits,
886 (unsigned int)sconn->smb2.credits_granted,
887 (unsigned int)sconn->smb2.max_credits,
888 (unsigned long long)sconn->smb2.seqnum_low,
889 (unsigned int)sconn->smb2.seqnum_range));
892 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
893 struct smbd_smb2_request *outreq)
896 uint16_t total_credits = 0;
898 count = outreq->out.vector_count;
900 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
901 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
902 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
903 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
905 smb2_set_operation_credit(outreq->sconn, inhdr_v, outhdr_v);
907 /* To match Windows, count up what we
909 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
910 /* Set to zero in all but the last reply. */
911 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
912 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
914 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
919 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
921 struct iovec *vector;
925 count = req->in.vector_count;
926 vector = talloc_zero_array(req, struct iovec, count);
927 if (vector == NULL) {
928 return NT_STATUS_NO_MEMORY;
931 vector[0].iov_base = req->out.nbt_hdr;
932 vector[0].iov_len = 4;
933 SIVAL(req->out.nbt_hdr, 0, 0);
935 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
936 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
937 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
938 uint8_t *outhdr = NULL;
939 uint8_t *outbody = NULL;
940 uint32_t next_command_ofs = 0;
941 struct iovec *current = &vector[idx];
943 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
944 /* we have a next command -
945 * setup for the error case. */
946 next_command_ofs = SMB2_HDR_BODY + 9;
950 outhdr = req->out._hdr;
952 outhdr = talloc_zero_array(vector, uint8_t,
954 if (outhdr == NULL) {
955 return NT_STATUS_NO_MEMORY;
959 outbody = outhdr + SMB2_HDR_BODY;
962 * SMBD_SMB2_TF_IOV_OFS might be used later
964 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
965 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
967 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
968 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
970 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
971 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
973 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
974 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
976 /* setup the SMB2 header */
977 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
978 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
979 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
980 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
981 SIVAL(outhdr, SMB2_HDR_STATUS,
982 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
983 SSVAL(outhdr, SMB2_HDR_OPCODE,
984 SVAL(inhdr, SMB2_HDR_OPCODE));
985 SIVAL(outhdr, SMB2_HDR_FLAGS,
986 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
987 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
988 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
989 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
990 SIVAL(outhdr, SMB2_HDR_PID,
991 IVAL(inhdr, SMB2_HDR_PID));
992 SIVAL(outhdr, SMB2_HDR_TID,
993 IVAL(inhdr, SMB2_HDR_TID));
994 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
995 BVAL(inhdr, SMB2_HDR_SESSION_ID));
996 memcpy(outhdr + SMB2_HDR_SIGNATURE,
997 inhdr + SMB2_HDR_SIGNATURE, 16);
999 /* setup error body header */
1000 SSVAL(outbody, 0x00, 0x08 + 1);
1001 SSVAL(outbody, 0x02, 0);
1002 SIVAL(outbody, 0x04, 0);
1005 req->out.vector = vector;
1006 req->out.vector_count = count;
1008 /* setup the length of the NBT packet */
1009 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1011 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
1013 return NT_STATUS_OK;
1016 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
1018 const char *location)
1020 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1022 exit_server_cleanly(reason);
1025 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1026 struct iovec *outvec,
1027 const struct iovec *srcvec)
1029 const uint8_t *srctf;
1031 const uint8_t *srchdr;
1033 const uint8_t *srcbody;
1035 const uint8_t *expected_srcbody;
1036 const uint8_t *srcdyn;
1038 const uint8_t *expected_srcdyn;
1044 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1045 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1046 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1047 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1048 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1049 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1050 expected_srcbody = srchdr + SMB2_HDR_BODY;
1051 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1052 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1053 expected_srcdyn = srcbody + 8;
1055 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1059 if (srchdr_len != SMB2_HDR_BODY) {
1063 if (srctf_len == SMB2_TF_HDR_SIZE) {
1064 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1065 if (dsttf == NULL) {
1071 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1072 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1074 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1075 * be allocated with size OUTVEC_ALLOC_SIZE. */
1077 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1078 if (dsthdr == NULL) {
1081 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1082 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1085 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1086 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1087 * then duplicate this. Else use talloc_memdup().
1090 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1091 dstbody = dsthdr + SMB2_HDR_BODY;
1093 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1094 if (dstbody == NULL) {
1098 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1099 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1102 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1104 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1105 * then duplicate this. Else use talloc_memdup().
1108 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1109 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1110 } else if (srcdyn == NULL) {
1113 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1114 if (dstdyn == NULL) {
1118 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1119 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1124 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1126 struct smbd_smb2_request *newreq = NULL;
1127 struct iovec *outvec = NULL;
1128 int count = req->out.vector_count;
1131 newreq = smbd_smb2_request_allocate(req->sconn);
1136 newreq->sconn = req->sconn;
1137 newreq->session = req->session;
1138 newreq->do_encryption = req->do_encryption;
1139 newreq->do_signing = req->do_signing;
1140 newreq->current_idx = req->current_idx;
1142 outvec = talloc_zero_array(newreq, struct iovec, count);
1144 TALLOC_FREE(newreq);
1147 newreq->out.vector = outvec;
1148 newreq->out.vector_count = count;
1150 /* Setup the outvec's identically to req. */
1151 outvec[0].iov_base = newreq->out.nbt_hdr;
1152 outvec[0].iov_len = 4;
1153 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1155 /* Setup the vectors identically to the ones in req. */
1156 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1157 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1164 TALLOC_FREE(newreq);
1168 smb2_setup_nbt_length(newreq->out.vector,
1169 newreq->out.vector_count);
1174 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1176 struct smbd_server_connection *sconn = req->sconn;
1177 struct smbXsrv_connection *conn = req->sconn->conn;
1179 struct iovec *firsttf = NULL;
1180 struct iovec *outhdr_v = NULL;
1181 uint8_t *outhdr = NULL;
1182 struct smbd_smb2_request *nreq = NULL;
1185 /* Create a new smb2 request we'll use
1186 for the interim return. */
1187 nreq = dup_smb2_req(req);
1189 return NT_STATUS_NO_MEMORY;
1192 /* Lose the last X out vectors. They're the
1193 ones we'll be using for the async reply. */
1194 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1196 smb2_setup_nbt_length(nreq->out.vector,
1197 nreq->out.vector_count);
1199 /* Step back to the previous reply. */
1200 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1201 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1202 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1203 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1204 /* And end the chain. */
1205 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1207 /* Calculate outgoing credits */
1208 smb2_calculate_credits(req, nreq);
1210 if (DEBUGLEVEL >= 10) {
1211 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1212 (unsigned int)nreq->current_idx );
1213 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1214 (unsigned int)nreq->out.vector_count );
1215 print_req_vectors(nreq);
1219 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1220 * we need to sign/encrypt here with the last/first key we remembered
1222 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1223 status = smb2_signing_encrypt_pdu(req->first_key,
1226 nreq->out.vector_count - first_idx);
1227 if (!NT_STATUS_IS_OK(status)) {
1230 } else if (req->last_key.length > 0) {
1231 status = smb2_signing_sign_pdu(req->last_key,
1234 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1235 if (!NT_STATUS_IS_OK(status)) {
1240 nreq->queue_entry.mem_ctx = nreq;
1241 nreq->queue_entry.vector = nreq->out.vector;
1242 nreq->queue_entry.count = nreq->out.vector_count;
1243 DLIST_ADD_END(nreq->sconn->smb2.send_queue, &nreq->queue_entry, NULL);
1244 nreq->sconn->smb2.send_queue_len++;
1246 status = smbd_smb2_io_handler(sconn, TEVENT_FD_WRITE);
1247 if (!NT_STATUS_IS_OK(status)) {
1251 return NT_STATUS_OK;
1254 struct smbd_smb2_request_pending_state {
1255 struct smbd_server_connection *sconn;
1256 struct smbd_smb2_send_queue queue_entry;
1257 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1258 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1261 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1262 struct tevent_timer *te,
1263 struct timeval current_time,
1264 void *private_data);
1266 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1267 struct tevent_req *subreq,
1268 uint32_t defer_time)
1271 struct timeval defer_endtime;
1272 uint8_t *outhdr = NULL;
1275 if (!tevent_req_is_in_progress(subreq)) {
1277 * This is a performance optimization,
1278 * it avoids one tevent_loop iteration,
1279 * which means we avoid one
1280 * talloc_stackframe_pool/talloc_free pair.
1282 tevent_req_notify_callback(subreq);
1283 return NT_STATUS_OK;
1286 req->subreq = subreq;
1289 if (req->async_te) {
1290 /* We're already async. */
1291 return NT_STATUS_OK;
1294 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1295 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1296 if (flags & SMB2_HDR_FLAG_ASYNC) {
1297 /* We're already async. */
1298 return NT_STATUS_OK;
1301 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1303 * We're trying to go async in a compound
1305 * This is only allowed for opens that
1306 * cause an oplock break, otherwise it
1307 * is not allowed. See [MS-SMB2].pdf
1308 * note <194> on Section 3.3.5.2.7.
1310 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1312 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1314 * Cancel the outstanding request.
1316 bool ok = tevent_req_cancel(req->subreq);
1318 return NT_STATUS_OK;
1320 TALLOC_FREE(req->subreq);
1321 return smbd_smb2_request_error(req,
1322 NT_STATUS_INTERNAL_ERROR);
1326 if (DEBUGLEVEL >= 10) {
1327 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1328 (unsigned int)req->current_idx );
1329 print_req_vectors(req);
1332 if (req->current_idx > 1) {
1334 * We're going async in a compound
1335 * chain after the first request has
1336 * already been processed. Send an
1337 * interim response containing the
1338 * set of replies already generated.
1340 int idx = req->current_idx;
1342 status = smb2_send_async_interim_response(req);
1343 if (!NT_STATUS_IS_OK(status)) {
1346 data_blob_clear_free(&req->first_key);
1348 req->current_idx = 1;
1351 * Re-arrange the in.vectors to remove what
1354 memmove(&req->in.vector[1],
1355 &req->in.vector[idx],
1356 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1357 req->in.vector_count = 1 + (req->in.vector_count - idx);
1359 /* Re-arrange the out.vectors to match. */
1360 memmove(&req->out.vector[1],
1361 &req->out.vector[idx],
1362 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1363 req->out.vector_count = 1 + (req->out.vector_count - idx);
1365 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1367 * We only have one remaining request as
1368 * we've processed everything else.
1369 * This is no longer a compound request.
1371 req->compound_related = false;
1372 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1373 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1374 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1377 data_blob_clear_free(&req->last_key);
1379 defer_endtime = timeval_current_ofs_usec(defer_time);
1380 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1382 smbd_smb2_request_pending_timer,
1384 if (req->async_te == NULL) {
1385 return NT_STATUS_NO_MEMORY;
1388 return NT_STATUS_OK;
1391 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1392 struct tevent_timer *te,
1393 struct timeval current_time,
1396 struct smbd_smb2_request *req =
1397 talloc_get_type_abort(private_data,
1398 struct smbd_smb2_request);
1399 struct smbd_server_connection *sconn = req->sconn;
1400 struct smbd_smb2_request_pending_state *state = NULL;
1401 uint8_t *outhdr = NULL;
1402 const uint8_t *inhdr = NULL;
1405 uint8_t *hdr = NULL;
1406 uint8_t *body = NULL;
1407 uint8_t *dyn = NULL;
1409 uint64_t session_id = 0;
1410 uint64_t message_id = 0;
1411 uint64_t nonce_high = 0;
1412 uint64_t nonce_low = 0;
1413 uint64_t async_id = 0;
1416 TALLOC_FREE(req->async_te);
1418 /* Ensure our final reply matches the interim one. */
1419 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1420 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1421 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1422 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1423 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1425 async_id = message_id; /* keep it simple for now... */
1427 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1428 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1430 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1432 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1433 (unsigned long long)async_id ));
1436 * What we send is identical to a smbd_smb2_request_error
1437 * packet with an error status of STATUS_PENDING. Make use
1438 * of this fact sometime when refactoring. JRA.
1441 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1442 if (state == NULL) {
1443 smbd_server_connection_terminate(req->sconn,
1444 nt_errstr(NT_STATUS_NO_MEMORY));
1447 state->sconn = req->sconn;
1449 tf = state->buf + NBT_HDR_SIZE;
1450 tf_len = SMB2_TF_HDR_SIZE;
1452 hdr = tf + SMB2_TF_HDR_SIZE;
1453 body = hdr + SMB2_HDR_BODY;
1456 if (req->do_encryption) {
1457 struct smbXsrv_session *x = req->session;
1459 nonce_high = x->nonce_high;
1460 nonce_low = x->nonce_low;
1463 if (x->nonce_low == 0) {
1469 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1470 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1471 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1472 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1474 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1475 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1476 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1477 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1478 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1480 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1481 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1482 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1483 SBVAL(hdr, SMB2_HDR_PID, async_id);
1484 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1485 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1486 memcpy(hdr+SMB2_HDR_SIGNATURE,
1487 outhdr+SMB2_HDR_SIGNATURE, 16);
1489 SSVAL(body, 0x00, 0x08 + 1);
1491 SCVAL(body, 0x02, 0);
1492 SCVAL(body, 0x03, 0);
1493 SIVAL(body, 0x04, 0);
1494 /* Match W2K8R2... */
1495 SCVAL(dyn, 0x00, 0x21);
1497 state->vector[0].iov_base = (void *)state->buf;
1498 state->vector[0].iov_len = NBT_HDR_SIZE;
1500 if (req->do_encryption) {
1501 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1502 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1504 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1505 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1508 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1509 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1511 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1512 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1514 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1515 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1517 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1519 /* Ensure we correctly go through crediting. Grant
1520 the credits now, and zero credits on the final
1522 smb2_set_operation_credit(req->sconn,
1523 SMBD_SMB2_IN_HDR_IOV(req),
1524 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1526 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1531 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1532 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1534 (unsigned int)ARRAY_SIZE(state->vector),
1535 (unsigned int)state->vector[i].iov_len);
1539 if (req->do_encryption) {
1540 struct smbXsrv_session *x = req->session;
1541 struct smbXsrv_connection *conn = x->connection;
1542 DATA_BLOB encryption_key = x->global->encryption_key;
1544 status = smb2_signing_encrypt_pdu(encryption_key,
1546 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1547 SMBD_SMB2_NUM_IOV_PER_REQ);
1548 if (!NT_STATUS_IS_OK(status)) {
1549 smbd_server_connection_terminate(req->sconn,
1553 } else if (req->do_signing) {
1554 struct smbXsrv_session *x = req->session;
1555 struct smbXsrv_connection *conn = x->connection;
1556 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1558 status = smb2_signing_sign_pdu(signing_key,
1560 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1561 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1562 if (!NT_STATUS_IS_OK(status)) {
1563 smbd_server_connection_terminate(req->sconn,
1569 state->queue_entry.mem_ctx = state;
1570 state->queue_entry.vector = state->vector;
1571 state->queue_entry.count = ARRAY_SIZE(state->vector);
1572 DLIST_ADD_END(sconn->smb2.send_queue, &state->queue_entry, NULL);
1573 sconn->smb2.send_queue_len++;
1575 status = smbd_smb2_io_handler(sconn, TEVENT_FD_WRITE);
1576 if (!NT_STATUS_IS_OK(status)) {
1577 smbd_server_connection_terminate(sconn,
1583 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1585 struct smbd_server_connection *sconn = req->sconn;
1586 struct smbd_smb2_request *cur;
1587 const uint8_t *inhdr;
1589 uint64_t search_message_id;
1590 uint64_t search_async_id;
1593 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1595 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1596 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1597 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1600 * we don't need the request anymore
1601 * cancel requests never have a response
1603 DLIST_REMOVE(req->sconn->smb2.requests, req);
1606 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1607 const uint8_t *outhdr;
1608 uint64_t message_id;
1611 if (cur->compound_related) {
1613 * Never cancel anything in a compound request.
1614 * Way too hard to deal with the result.
1619 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1621 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1622 async_id = BVAL(outhdr, SMB2_HDR_PID);
1624 if (flags & SMB2_HDR_FLAG_ASYNC) {
1625 if (search_async_id == async_id) {
1626 found_id = async_id;
1630 if (search_message_id == message_id) {
1631 found_id = message_id;
1637 if (cur && cur->subreq) {
1638 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1639 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1640 "cancel opcode[%s] mid %llu\n",
1641 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1642 (unsigned long long)found_id ));
1643 tevent_req_cancel(cur->subreq);
1646 return NT_STATUS_OK;
1649 /*************************************************************
1650 Ensure an incoming tid is a valid one for us to access.
1651 Change to the associated uid credentials and chdir to the
1652 valid tid directory.
1653 *************************************************************/
1655 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1657 const uint8_t *inhdr;
1660 struct smbXsrv_tcon *tcon;
1662 NTTIME now = timeval_to_nttime(&req->request_time);
1666 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1668 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1669 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1671 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1672 in_tid = req->last_tid;
1677 status = smb2srv_tcon_lookup(req->session,
1678 in_tid, now, &tcon);
1679 if (!NT_STATUS_IS_OK(status)) {
1683 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1684 return NT_STATUS_ACCESS_DENIED;
1687 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1688 if (!set_current_service(tcon->compat, 0, true)) {
1689 return NT_STATUS_ACCESS_DENIED;
1693 req->last_tid = in_tid;
1695 return NT_STATUS_OK;
1698 /*************************************************************
1699 Ensure an incoming session_id is a valid one for us to access.
1700 *************************************************************/
1702 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1704 const uint8_t *inhdr;
1707 uint64_t in_session_id;
1708 struct smbXsrv_session *session = NULL;
1709 struct auth_session_info *session_info;
1711 NTTIME now = timeval_to_nttime(&req->request_time);
1713 req->session = NULL;
1716 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1718 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1719 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1720 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1722 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1723 in_session_id = req->last_session_id;
1726 req->last_session_id = 0;
1728 /* lookup an existing session */
1729 status = smb2srv_session_lookup(req->sconn->conn,
1733 req->session = session;
1734 req->last_session_id = in_session_id;
1736 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1737 switch (in_opcode) {
1738 case SMB2_OP_SESSSETUP:
1739 status = NT_STATUS_OK;
1745 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1746 switch (in_opcode) {
1748 case SMB2_OP_CREATE:
1749 case SMB2_OP_GETINFO:
1750 case SMB2_OP_SETINFO:
1751 return NT_STATUS_INVALID_HANDLE;
1754 * Notice the check for
1755 * (session_info == NULL)
1758 status = NT_STATUS_OK;
1762 if (!NT_STATUS_IS_OK(status)) {
1766 session_info = session->global->auth_session_info;
1767 if (session_info == NULL) {
1768 return NT_STATUS_INVALID_HANDLE;
1771 if (in_session_id != req->sconn->conn->last_session_id) {
1772 req->sconn->conn->last_session_id = in_session_id;
1773 set_current_user_info(session_info->unix_info->sanitized_username,
1774 session_info->unix_info->unix_name,
1775 session_info->info->domain_name);
1778 return NT_STATUS_OK;
1781 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1782 uint32_t data_length)
1784 uint16_t needed_charge;
1785 uint16_t credit_charge = 1;
1786 const uint8_t *inhdr;
1788 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1790 if (req->sconn->smb2.supports_multicredit) {
1791 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1792 credit_charge = MAX(credit_charge, 1);
1795 needed_charge = (data_length - 1)/ 65536 + 1;
1797 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1798 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1799 credit_charge, needed_charge));
1801 if (needed_charge > credit_charge) {
1802 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1803 credit_charge, needed_charge));
1804 return NT_STATUS_INVALID_PARAMETER;
1807 return NT_STATUS_OK;
1810 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1811 size_t expected_body_size)
1813 struct iovec *inhdr_v;
1814 const uint8_t *inhdr;
1816 const uint8_t *inbody;
1818 size_t min_dyn_size = expected_body_size & 0x00000001;
1819 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1822 * The following should be checked already.
1824 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1825 return NT_STATUS_INTERNAL_ERROR;
1827 if (req->current_idx > max_idx) {
1828 return NT_STATUS_INTERNAL_ERROR;
1831 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1832 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1833 return NT_STATUS_INTERNAL_ERROR;
1835 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1836 return NT_STATUS_INTERNAL_ERROR;
1839 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1840 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1844 case SMB2_OP_GETINFO:
1850 * Now check the expected body size,
1851 * where the last byte might be in the
1854 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1855 return NT_STATUS_INVALID_PARAMETER;
1857 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1858 return NT_STATUS_INVALID_PARAMETER;
1861 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1863 body_size = SVAL(inbody, 0x00);
1864 if (body_size != expected_body_size) {
1865 return NT_STATUS_INVALID_PARAMETER;
1868 return NT_STATUS_OK;
1871 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1873 struct smbXsrv_connection *conn = req->sconn->conn;
1874 const struct smbd_smb2_dispatch_table *call = NULL;
1875 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1876 const uint8_t *inhdr;
1881 NTSTATUS session_status;
1882 uint32_t allowed_flags;
1883 NTSTATUS return_value;
1884 struct smbXsrv_session *x = NULL;
1885 bool signing_required = false;
1886 bool encryption_required = false;
1888 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1890 /* TODO: verify more things */
1892 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1893 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1894 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1895 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1896 smb2_opcode_name(opcode),
1897 (unsigned long long)mid));
1899 if (conn->protocol >= PROTOCOL_SMB2_02) {
1901 * once the protocol is negotiated
1902 * SMB2_OP_NEGPROT is not allowed anymore
1904 if (opcode == SMB2_OP_NEGPROT) {
1905 /* drop the connection */
1906 return NT_STATUS_INVALID_PARAMETER;
1910 * if the protocol is not negotiated yet
1911 * only SMB2_OP_NEGPROT is allowed.
1913 if (opcode != SMB2_OP_NEGPROT) {
1914 /* drop the connection */
1915 return NT_STATUS_INVALID_PARAMETER;
1920 * Check if the client provided a valid session id,
1921 * if so smbd_smb2_request_check_session() calls
1922 * set_current_user_info().
1924 * As some command don't require a valid session id
1925 * we defer the check of the session_status
1927 session_status = smbd_smb2_request_check_session(req);
1930 signing_required = x->global->signing_required;
1931 encryption_required = x->global->encryption_required;
1933 if (opcode == SMB2_OP_SESSSETUP &&
1934 x->global->channels[0].signing_key.length) {
1935 signing_required = true;
1939 req->do_signing = false;
1940 req->do_encryption = false;
1941 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
1942 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
1943 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
1945 if (x != NULL && x->global->session_wire_id != tf_session_id) {
1946 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1947 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1948 (unsigned long long)x->global->session_wire_id,
1949 (unsigned long long)tf_session_id));
1951 * TODO: windows allows this...
1952 * should we drop the connection?
1954 * For now we just return ACCESS_DENIED
1955 * (Windows clients never trigger this)
1956 * and wait for an update of [MS-SMB2].
1958 return smbd_smb2_request_error(req,
1959 NT_STATUS_ACCESS_DENIED);
1962 req->do_encryption = true;
1965 if (encryption_required && !req->do_encryption) {
1966 return smbd_smb2_request_error(req,
1967 NT_STATUS_ACCESS_DENIED);
1970 call = smbd_smb2_call(opcode);
1972 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1975 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1976 SMB2_HDR_FLAG_SIGNED |
1978 if (opcode == SMB2_OP_CANCEL) {
1979 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1981 if ((flags & ~allowed_flags) != 0) {
1982 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1985 if (flags & SMB2_HDR_FLAG_CHAINED) {
1987 * This check is mostly for giving the correct error code
1988 * for compounded requests.
1990 if (!NT_STATUS_IS_OK(session_status)) {
1991 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1994 req->compat_chain_fsp = NULL;
1997 if (req->do_encryption) {
1998 signing_required = false;
1999 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2000 DATA_BLOB signing_key;
2003 return smbd_smb2_request_error(
2004 req, NT_STATUS_USER_SESSION_DELETED);
2007 signing_key = x->global->channels[0].signing_key;
2010 * If we have a signing key, we should
2013 if (signing_key.length > 0) {
2014 req->do_signing = true;
2017 status = smb2_signing_check_pdu(signing_key,
2019 SMBD_SMB2_IN_HDR_IOV(req),
2020 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2021 if (!NT_STATUS_IS_OK(status)) {
2022 return smbd_smb2_request_error(req, status);
2026 * Now that we know the request was correctly signed
2027 * we have to sign the response too.
2029 req->do_signing = true;
2031 if (!NT_STATUS_IS_OK(session_status)) {
2032 return smbd_smb2_request_error(req, session_status);
2034 } else if (opcode == SMB2_OP_CANCEL) {
2035 /* Cancel requests are allowed to skip the signing */
2036 } else if (signing_required) {
2038 * If signing is required we try to sign
2039 * a possible error response
2041 req->do_signing = true;
2042 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2045 if (flags & SMB2_HDR_FLAG_CHAINED) {
2046 req->compound_related = true;
2049 if (call->need_session) {
2050 if (!NT_STATUS_IS_OK(session_status)) {
2051 return smbd_smb2_request_error(req, session_status);
2055 if (call->need_tcon) {
2056 SMB_ASSERT(call->need_session);
2059 * This call needs to be run as user.
2061 * smbd_smb2_request_check_tcon()
2062 * calls change_to_user() on success.
2064 status = smbd_smb2_request_check_tcon(req);
2065 if (!NT_STATUS_IS_OK(status)) {
2066 return smbd_smb2_request_error(req, status);
2068 if (req->tcon->global->encryption_required) {
2069 encryption_required = true;
2071 if (encryption_required && !req->do_encryption) {
2072 return smbd_smb2_request_error(req,
2073 NT_STATUS_ACCESS_DENIED);
2077 if (call->fileid_ofs != 0) {
2078 size_t needed = call->fileid_ofs + 16;
2079 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2080 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2081 uint64_t file_id_persistent;
2082 uint64_t file_id_volatile;
2083 struct files_struct *fsp;
2085 SMB_ASSERT(call->need_tcon);
2087 if (needed > body_size) {
2088 return smbd_smb2_request_error(req,
2089 NT_STATUS_INVALID_PARAMETER);
2092 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2093 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2095 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2097 if (!call->allow_invalid_fileid) {
2098 return smbd_smb2_request_error(req,
2099 NT_STATUS_FILE_CLOSED);
2102 if (file_id_persistent != UINT64_MAX) {
2103 return smbd_smb2_request_error(req,
2104 NT_STATUS_FILE_CLOSED);
2106 if (file_id_volatile != UINT64_MAX) {
2107 return smbd_smb2_request_error(req,
2108 NT_STATUS_FILE_CLOSED);
2113 if (call->as_root) {
2114 SMB_ASSERT(call->fileid_ofs == 0);
2115 /* This call needs to be run as root */
2116 change_to_root_user();
2118 SMB_ASSERT(call->need_tcon);
2122 case SMB2_OP_NEGPROT:
2124 START_PROFILE(smb2_negprot);
2125 return_value = smbd_smb2_request_process_negprot(req);
2126 END_PROFILE(smb2_negprot);
2130 case SMB2_OP_SESSSETUP:
2132 START_PROFILE(smb2_sesssetup);
2133 return_value = smbd_smb2_request_process_sesssetup(req);
2134 END_PROFILE(smb2_sesssetup);
2138 case SMB2_OP_LOGOFF:
2140 START_PROFILE(smb2_logoff);
2141 return_value = smbd_smb2_request_process_logoff(req);
2142 END_PROFILE(smb2_logoff);
2148 START_PROFILE(smb2_tcon);
2149 return_value = smbd_smb2_request_process_tcon(req);
2150 END_PROFILE(smb2_tcon);
2156 START_PROFILE(smb2_tdis);
2157 return_value = smbd_smb2_request_process_tdis(req);
2158 END_PROFILE(smb2_tdis);
2162 case SMB2_OP_CREATE:
2164 START_PROFILE(smb2_create);
2165 return_value = smbd_smb2_request_process_create(req);
2166 END_PROFILE(smb2_create);
2172 START_PROFILE(smb2_close);
2173 return_value = smbd_smb2_request_process_close(req);
2174 END_PROFILE(smb2_close);
2180 START_PROFILE(smb2_flush);
2181 return_value = smbd_smb2_request_process_flush(req);
2182 END_PROFILE(smb2_flush);
2188 START_PROFILE(smb2_read);
2189 return_value = smbd_smb2_request_process_read(req);
2190 END_PROFILE(smb2_read);
2196 START_PROFILE(smb2_write);
2197 return_value = smbd_smb2_request_process_write(req);
2198 END_PROFILE(smb2_write);
2204 START_PROFILE(smb2_lock);
2205 return_value = smbd_smb2_request_process_lock(req);
2206 END_PROFILE(smb2_lock);
2212 START_PROFILE(smb2_ioctl);
2213 return_value = smbd_smb2_request_process_ioctl(req);
2214 END_PROFILE(smb2_ioctl);
2218 case SMB2_OP_CANCEL:
2220 START_PROFILE(smb2_cancel);
2221 return_value = smbd_smb2_request_process_cancel(req);
2222 END_PROFILE(smb2_cancel);
2226 case SMB2_OP_KEEPALIVE:
2228 START_PROFILE(smb2_keepalive);
2229 return_value = smbd_smb2_request_process_keepalive(req);
2230 END_PROFILE(smb2_keepalive);
2236 START_PROFILE(smb2_find);
2237 return_value = smbd_smb2_request_process_find(req);
2238 END_PROFILE(smb2_find);
2242 case SMB2_OP_NOTIFY:
2244 START_PROFILE(smb2_notify);
2245 return_value = smbd_smb2_request_process_notify(req);
2246 END_PROFILE(smb2_notify);
2250 case SMB2_OP_GETINFO:
2252 START_PROFILE(smb2_getinfo);
2253 return_value = smbd_smb2_request_process_getinfo(req);
2254 END_PROFILE(smb2_getinfo);
2258 case SMB2_OP_SETINFO:
2260 START_PROFILE(smb2_setinfo);
2261 return_value = smbd_smb2_request_process_setinfo(req);
2262 END_PROFILE(smb2_setinfo);
2268 START_PROFILE(smb2_break);
2269 return_value = smbd_smb2_request_process_break(req);
2270 END_PROFILE(smb2_break);
2275 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2278 return return_value;
2281 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2283 struct smbd_server_connection *sconn = req->sconn;
2284 struct smbXsrv_connection *conn = req->sconn->conn;
2286 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2287 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2288 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2292 TALLOC_FREE(req->async_te);
2294 if (req->do_encryption &&
2295 (firsttf->iov_len == 0) &&
2296 (req->first_key.length == 0) &&
2297 (req->session != NULL) &&
2298 (req->session->global->encryption_key.length != 0))
2300 DATA_BLOB encryption_key = req->session->global->encryption_key;
2302 uint64_t session_id = req->session->global->session_wire_id;
2303 struct smbXsrv_session *x = req->session;
2304 uint64_t nonce_high;
2307 nonce_high = x->nonce_high;
2308 nonce_low = x->nonce_low;
2311 if (x->nonce_low == 0) {
2317 * We need to place the SMB2_TRANSFORM header before the
2322 * we need to remember the encryption key
2323 * and defer the signing/encryption until
2324 * we are sure that we do not change
2327 req->first_key = data_blob_dup_talloc(req, encryption_key);
2328 if (req->first_key.data == NULL) {
2329 return NT_STATUS_NO_MEMORY;
2332 tf = talloc_zero_array(req->out.vector, uint8_t,
2335 return NT_STATUS_NO_MEMORY;
2338 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2339 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2340 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2341 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2343 firsttf->iov_base = (void *)tf;
2344 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2347 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2348 (req->last_key.length > 0) &&
2349 (firsttf->iov_len == 0))
2351 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2352 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2355 * As we are sure the header of the last request in the
2356 * compound chain will not change, we can to sign here
2357 * with the last signing key we remembered.
2359 status = smb2_signing_sign_pdu(req->last_key,
2362 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2363 if (!NT_STATUS_IS_OK(status)) {
2367 data_blob_clear_free(&req->last_key);
2369 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2371 if (req->current_idx < req->out.vector_count) {
2373 * We must process the remaining compound
2374 * SMB2 requests before any new incoming SMB2
2375 * requests. This is because incoming SMB2
2376 * requests may include a cancel for a
2377 * compound request we haven't processed
2380 struct tevent_immediate *im = tevent_create_immediate(req);
2382 return NT_STATUS_NO_MEMORY;
2385 if (req->do_signing && firsttf->iov_len == 0) {
2386 struct smbXsrv_session *x = req->session;
2387 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2390 * we need to remember the signing key
2391 * and defer the signing until
2392 * we are sure that we do not change
2395 req->last_key = data_blob_dup_talloc(req, signing_key);
2396 if (req->last_key.data == NULL) {
2397 return NT_STATUS_NO_MEMORY;
2401 tevent_schedule_immediate(im,
2403 smbd_smb2_request_dispatch_immediate,
2405 return NT_STATUS_OK;
2408 if (req->compound_related) {
2409 req->compound_related = false;
2412 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2414 /* Set credit for these operations (zero credits if this
2415 is a final reply for an async operation). */
2416 smb2_calculate_credits(req, req);
2419 * now check if we need to sign the current response
2421 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2422 status = smb2_signing_encrypt_pdu(req->first_key,
2425 req->out.vector_count - first_idx);
2426 if (!NT_STATUS_IS_OK(status)) {
2429 } else if (req->do_signing) {
2430 struct smbXsrv_session *x = req->session;
2431 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2433 status = smb2_signing_sign_pdu(signing_key,
2436 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2437 if (!NT_STATUS_IS_OK(status)) {
2441 data_blob_clear_free(&req->first_key);
2443 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2444 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2445 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2446 /* Dynamic part is NULL. Chop it off,
2447 We're going to send it via sendfile. */
2448 req->out.vector_count -= 1;
2452 * We're done with this request -
2453 * move it off the "being processed" queue.
2455 DLIST_REMOVE(req->sconn->smb2.requests, req);
2457 req->queue_entry.mem_ctx = req;
2458 req->queue_entry.vector = req->out.vector;
2459 req->queue_entry.count = req->out.vector_count;
2460 DLIST_ADD_END(req->sconn->smb2.send_queue, &req->queue_entry, NULL);
2461 req->sconn->smb2.send_queue_len++;
2463 status = smbd_smb2_io_handler(sconn, TEVENT_FD_WRITE);
2464 if (!NT_STATUS_IS_OK(status)) {
2468 return NT_STATUS_OK;
2471 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2473 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2474 struct tevent_immediate *im,
2477 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2478 struct smbd_smb2_request);
2479 struct smbd_server_connection *sconn = req->sconn;
2484 if (DEBUGLEVEL >= 10) {
2485 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2486 req->current_idx, req->in.vector_count));
2487 print_req_vectors(req);
2490 status = smbd_smb2_request_dispatch(req);
2491 if (!NT_STATUS_IS_OK(status)) {
2492 smbd_server_connection_terminate(sconn, nt_errstr(status));
2496 status = smbd_smb2_request_next_incoming(sconn);
2497 if (!NT_STATUS_IS_OK(status)) {
2498 smbd_server_connection_terminate(sconn, nt_errstr(status));
2503 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2505 DATA_BLOB body, DATA_BLOB *dyn,
2506 const char *location)
2509 struct iovec *outbody_v;
2510 struct iovec *outdyn_v;
2511 uint32_t next_command_ofs;
2513 DEBUG(10,("smbd_smb2_request_done_ex: "
2514 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2515 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2517 (unsigned int)(dyn ? dyn->length : 0),
2520 if (body.length < 2) {
2521 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2524 if ((body.length % 2) != 0) {
2525 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2528 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2529 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2530 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2532 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2533 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2535 outbody_v->iov_base = (void *)body.data;
2536 outbody_v->iov_len = body.length;
2539 outdyn_v->iov_base = (void *)dyn->data;
2540 outdyn_v->iov_len = dyn->length;
2542 outdyn_v->iov_base = NULL;
2543 outdyn_v->iov_len = 0;
2546 /* see if we need to recalculate the offset to the next response */
2547 if (next_command_ofs > 0) {
2548 next_command_ofs = SMB2_HDR_BODY;
2549 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2550 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2553 if ((next_command_ofs % 8) != 0) {
2554 size_t pad_size = 8 - (next_command_ofs % 8);
2555 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2557 * if the dyn buffer is empty
2558 * we can use it to add padding
2562 pad = talloc_zero_array(req->out.vector,
2565 return smbd_smb2_request_error(req,
2566 NT_STATUS_NO_MEMORY);
2569 outdyn_v->iov_base = (void *)pad;
2570 outdyn_v->iov_len = pad_size;
2573 * For now we copy the dynamic buffer
2574 * and add the padding to the new buffer
2581 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2582 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2584 new_size = old_size + pad_size;
2585 new_dyn = talloc_zero_array(req->out.vector,
2587 if (new_dyn == NULL) {
2588 return smbd_smb2_request_error(req,
2589 NT_STATUS_NO_MEMORY);
2592 memcpy(new_dyn, old_dyn, old_size);
2593 memset(new_dyn + old_size, 0, pad_size);
2595 outdyn_v->iov_base = (void *)new_dyn;
2596 outdyn_v->iov_len = new_size;
2598 next_command_ofs += pad_size;
2601 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2603 return smbd_smb2_request_reply(req);
2606 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2609 const char *location)
2612 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2613 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2615 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2616 req->current_idx, nt_errstr(status), info ? " +info" : "",
2620 /* Recvfile error. Drain incoming socket. */
2624 ret = drain_socket(req->sconn->sock, unread_bytes);
2625 if (ret != unread_bytes) {
2629 error = NT_STATUS_IO_DEVICE_ERROR;
2631 error = map_nt_error_from_unix_common(errno);
2634 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2635 "ret[%u] errno[%d] => %s\n",
2636 (unsigned)unread_bytes,
2637 (unsigned)ret, errno, nt_errstr(error)));
2642 body.data = outhdr + SMB2_HDR_BODY;
2644 SSVAL(body.data, 0, 9);
2647 SIVAL(body.data, 0x04, info->length);
2649 /* Allocated size of req->out.vector[i].iov_base
2650 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2651 * 1 byte without having to do an alloc.
2653 info = talloc_zero_array(req->out.vector,
2657 return NT_STATUS_NO_MEMORY;
2659 info->data = ((uint8_t *)outhdr) +
2660 OUTVEC_ALLOC_SIZE - 1;
2662 SCVAL(info->data, 0, 0);
2666 * Note: Even if there is an error, continue to process the request.
2670 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2674 struct smbd_smb2_send_oplock_break_state {
2675 struct smbd_server_connection *sconn;
2676 struct smbd_smb2_send_queue queue_entry;
2677 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x18];
2678 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2681 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2682 struct smbXsrv_session *session,
2683 struct smbXsrv_tcon *tcon,
2684 struct smbXsrv_open *op,
2685 uint8_t oplock_level)
2687 struct smbd_smb2_send_oplock_break_state *state;
2688 struct smbXsrv_connection *conn = sconn->conn;
2696 bool do_encryption = session->global->encryption_required;
2697 uint64_t nonce_high = 0;
2698 uint64_t nonce_low = 0;
2701 if (tcon->global->encryption_required) {
2702 do_encryption = true;
2705 state = talloc_zero(sconn, struct smbd_smb2_send_oplock_break_state);
2706 if (state == NULL) {
2707 return NT_STATUS_NO_MEMORY;
2709 state->sconn = sconn;
2711 tf = state->buf + NBT_HDR_SIZE;
2712 tf_len = SMB2_TF_HDR_SIZE;
2714 body = hdr + SMB2_HDR_BODY;
2716 dyn = body + body_len;
2719 if (do_encryption) {
2720 nonce_high = session->nonce_high;
2721 nonce_low = session->nonce_low;
2723 session->nonce_low += 1;
2724 if (session->nonce_low == 0) {
2725 session->nonce_low += 1;
2726 session->nonce_high += 1;
2730 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2731 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2732 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2733 SBVAL(tf, SMB2_TF_SESSION_ID, session->global->session_wire_id);
2735 SIVAL(hdr, 0, SMB2_MAGIC);
2736 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2737 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2738 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2739 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2740 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2741 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2742 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2743 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2744 SIVAL(hdr, SMB2_HDR_PID, 0);
2745 SIVAL(hdr, SMB2_HDR_TID, 0);
2746 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2747 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2749 SSVAL(body, 0x00, body_len);
2751 SCVAL(body, 0x02, oplock_level);
2752 SCVAL(body, 0x03, 0); /* reserved */
2753 SIVAL(body, 0x04, 0); /* reserved */
2754 SBVAL(body, 0x08, op->global->open_persistent_id);
2755 SBVAL(body, 0x10, op->global->open_volatile_id);
2757 state->vector[0].iov_base = (void *)state->buf;
2758 state->vector[0].iov_len = NBT_HDR_SIZE;
2760 if (do_encryption) {
2761 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
2762 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
2764 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
2765 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
2768 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
2769 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
2771 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
2772 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = body_len;
2774 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
2775 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_len;
2777 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2779 if (do_encryption) {
2780 DATA_BLOB encryption_key = session->global->encryption_key;
2782 status = smb2_signing_encrypt_pdu(encryption_key,
2784 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2785 SMBD_SMB2_NUM_IOV_PER_REQ);
2786 if (!NT_STATUS_IS_OK(status)) {
2791 state->queue_entry.mem_ctx = state;
2792 state->queue_entry.vector = state->vector;
2793 state->queue_entry.count = ARRAY_SIZE(state->vector);
2794 DLIST_ADD_END(state->sconn->smb2.send_queue, &state->queue_entry, NULL);
2795 state->sconn->smb2.send_queue_len++;
2797 status = smbd_smb2_io_handler(sconn, TEVENT_FD_WRITE);
2798 if (!NT_STATUS_IS_OK(status)) {
2802 return NT_STATUS_OK;
2805 static size_t get_min_receive_file_size(struct smbd_smb2_request *smb2_req)
2807 if (smb2_req->do_signing) {
2810 if (smb2_req->do_encryption) {
2813 return (size_t)lp_min_receive_file_size();
2816 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2820 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
2821 /* Transform header. Cannot recvfile. */
2824 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
2825 /* Not SMB2. Normal error path will cope. */
2828 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
2829 /* Not SMB2. Normal error path will cope. */
2832 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
2833 /* Needs to be a WRITE. */
2836 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
2837 /* Chained. Cannot recvfile. */
2840 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
2841 if (flags & SMB2_HDR_FLAG_CHAINED) {
2842 /* Chained. Cannot recvfile. */
2845 if (flags & SMB2_HDR_FLAG_SIGNED) {
2846 /* Signed. Cannot recvfile. */
2850 DEBUG(10,("Doing recvfile write len = %u\n",
2851 (unsigned int)(state->pktlen -
2852 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN)));
2857 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2859 struct smbd_smb2_request_read_state *state = &sconn->smb2.request_read_state;
2860 size_t max_send_queue_len;
2861 size_t cur_send_queue_len;
2863 if (!NT_STATUS_IS_OK(sconn->status)) {
2865 * we're not supposed to do any io
2867 return NT_STATUS_OK;
2870 if (state->req != NULL) {
2872 * if there is already a tstream_readv_pdu
2873 * pending, we are done.
2875 return NT_STATUS_OK;
2878 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2879 cur_send_queue_len = sconn->smb2.send_queue_len;
2881 if (cur_send_queue_len > max_send_queue_len) {
2883 * if we have a lot of requests to send,
2884 * we wait until they are on the wire until we
2885 * ask for the next request.
2887 return NT_STATUS_OK;
2890 /* ask for the next request */
2891 ZERO_STRUCTP(state);
2892 state->req = smbd_smb2_request_allocate(sconn);
2893 if (state->req == NULL) {
2894 return NT_STATUS_NO_MEMORY;
2896 state->req->sconn = sconn;
2897 state->min_recv_size = get_min_receive_file_size(state->req);
2899 TEVENT_FD_READABLE(sconn->smb2.fde);
2901 return NT_STATUS_OK;
2904 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2905 uint8_t *inbuf, size_t size)
2908 struct smbd_smb2_request *req = NULL;
2910 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2911 (unsigned int)size));
2913 status = smbd_initialize_smb2(sconn);
2914 if (!NT_STATUS_IS_OK(status)) {
2915 smbd_server_connection_terminate(sconn, nt_errstr(status));
2919 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2920 if (!NT_STATUS_IS_OK(status)) {
2921 smbd_server_connection_terminate(sconn, nt_errstr(status));
2925 status = smbd_smb2_request_validate(req);
2926 if (!NT_STATUS_IS_OK(status)) {
2927 smbd_server_connection_terminate(sconn, nt_errstr(status));
2931 status = smbd_smb2_request_setup_out(req);
2932 if (!NT_STATUS_IS_OK(status)) {
2933 smbd_server_connection_terminate(sconn, nt_errstr(status));
2937 status = smbd_smb2_request_dispatch(req);
2938 if (!NT_STATUS_IS_OK(status)) {
2939 smbd_server_connection_terminate(sconn, nt_errstr(status));
2943 status = smbd_smb2_request_next_incoming(sconn);
2944 if (!NT_STATUS_IS_OK(status)) {
2945 smbd_server_connection_terminate(sconn, nt_errstr(status));
2949 sconn->num_requests++;
2952 static int socket_error_from_errno(int ret,
2966 if (sys_errno == 0) {
2970 if (sys_errno == EINTR) {
2975 if (sys_errno == EINPROGRESS) {
2980 if (sys_errno == EAGAIN) {
2985 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
2986 if (sys_errno == ENOMEM) {
2992 #if EWOULDBLOCK != EAGAIN
2993 if (sys_errno == EWOULDBLOCK) {
3003 static NTSTATUS smbd_smb2_flush_send_queue(struct smbd_server_connection *sconn)
3009 if (sconn->smb2.send_queue == NULL) {
3010 TEVENT_FD_NOT_WRITEABLE(sconn->smb2.fde);
3011 return NT_STATUS_OK;
3014 while (sconn->smb2.send_queue != NULL) {
3015 struct smbd_smb2_send_queue *e = sconn->smb2.send_queue;
3017 if (e->sendfile_header != NULL) {
3022 for (i=0; i < e->count; i++) {
3023 size += e->vector[i].iov_len;
3026 buf = talloc_array(e->mem_ctx, uint8_t, size);
3028 return NT_STATUS_NO_MEMORY;
3032 for (i=0; i < e->count; i++) {
3034 e->vector[i].iov_base,
3035 e->vector[i].iov_len);
3036 size += e->vector[i].iov_len;
3039 e->sendfile_header->data = buf;
3040 e->sendfile_header->length = size;
3043 sconn->smb2.send_queue_len--;
3044 DLIST_REMOVE(sconn->smb2.send_queue, e);
3045 talloc_free(e->mem_ctx);
3049 ret = writev(sconn->sock, e->vector, e->count);
3051 /* propagate end of file */
3052 return NT_STATUS_INTERNAL_ERROR;
3054 err = socket_error_from_errno(ret, errno, &retry);
3057 TEVENT_FD_WRITEABLE(sconn->smb2.fde);
3058 return NT_STATUS_OK;
3061 return map_nt_error_from_unix_common(err);
3064 if (ret < e->vector[0].iov_len) {
3066 base = (uint8_t *)e->vector[0].iov_base;
3068 e->vector[0].iov_base = (void *)base;
3069 e->vector[0].iov_len -= ret;
3072 ret -= e->vector[0].iov_len;
3078 * there're maybe some empty vectors at the end
3079 * which we need to skip, otherwise we would get
3080 * ret == 0 from the readv() call and return EPIPE
3082 while (e->count > 0) {
3083 if (e->vector[0].iov_len > 0) {
3091 /* we have more to write */
3092 TEVENT_FD_WRITEABLE(sconn->smb2.fde);
3093 return NT_STATUS_OK;
3096 sconn->smb2.send_queue_len--;
3097 DLIST_REMOVE(sconn->smb2.send_queue, e);
3098 talloc_free(e->mem_ctx);
3101 return NT_STATUS_OK;
3104 static NTSTATUS smbd_smb2_io_handler(struct smbd_server_connection *sconn,
3107 struct smbd_smb2_request_read_state *state = &sconn->smb2.request_read_state;
3108 struct smbd_smb2_request *req = NULL;
3109 size_t min_recvfile_size = UINT32_MAX;
3116 if (!NT_STATUS_IS_OK(sconn->status)) {
3118 * we're not supposed to do any io
3120 TEVENT_FD_NOT_READABLE(sconn->smb2.fde);
3121 TEVENT_FD_NOT_WRITEABLE(sconn->smb2.fde);
3122 return NT_STATUS_OK;
3125 if (fde_flags & TEVENT_FD_WRITE) {
3126 status = smbd_smb2_flush_send_queue(sconn);
3127 if (!NT_STATUS_IS_OK(status)) {
3132 if (!(fde_flags & TEVENT_FD_READ)) {
3133 return NT_STATUS_OK;
3136 if (state->req == NULL) {
3137 TEVENT_FD_NOT_READABLE(sconn->smb2.fde);
3138 return NT_STATUS_OK;
3142 if (!state->hdr.done) {
3143 state->hdr.done = true;
3145 state->vector.iov_base = (void *)state->hdr.nbt;
3146 state->vector.iov_len = NBT_HDR_SIZE;
3149 ret = readv(sconn->sock, &state->vector, 1);
3151 /* propagate end of file */
3152 return NT_STATUS_END_OF_FILE;
3154 err = socket_error_from_errno(ret, errno, &retry);
3157 TEVENT_FD_READABLE(sconn->smb2.fde);
3158 return NT_STATUS_OK;
3161 return map_nt_error_from_unix_common(err);
3164 if (ret < state->vector.iov_len) {
3166 base = (uint8_t *)state->vector.iov_base;
3168 state->vector.iov_base = (void *)base;
3169 state->vector.iov_len -= ret;
3170 /* we have more to read */
3171 TEVENT_FD_READABLE(sconn->smb2.fde);
3172 return NT_STATUS_OK;
3175 if (state->pktlen > 0) {
3176 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3178 * Not a possible receivefile write.
3179 * Read the rest of the data.
3181 state->doing_receivefile = false;
3182 state->vector.iov_base = (void *)(state->pktbuf +
3183 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN);
3184 state->vector.iov_len = (state->pktlen -
3185 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN);
3190 * Either this is a receivefile write so we've
3191 * done a short read, or if not we have all the data.
3197 * Now we analyze the NBT header
3199 state->pktlen = smb2_len(state->hdr.nbt);
3200 if (state->pktlen == 0) {
3204 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3205 if (state->pktbuf == NULL) {
3206 return NT_STATUS_NO_MEMORY;
3209 state->vector.iov_base = (void *)state->pktbuf;
3211 if (state->min_recv_size != 0) {
3212 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3213 min_recvfile_size += state->min_recv_size;
3216 if (state->pktlen > min_recvfile_size) {
3218 * Might be a receivefile write. Read the SMB2 HEADER +
3219 * SMB2_WRITE header first. Set 'doing_receivefile'
3220 * as we're *attempting* receivefile write. If this
3221 * turns out not to be a SMB2_WRITE request or otherwise
3222 * not suitable then we'll just read the rest of the data
3223 * the next time this function is called.
3225 state->vector.iov_len = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3226 state->doing_receivefile = true;
3228 state->vector.iov_len = state->pktlen;
3235 if (state->hdr.nbt[0] != 0x00) {
3236 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3237 state->hdr.nbt[0]));
3240 ZERO_STRUCTP(state);
3242 state->min_recv_size = get_min_receive_file_size(state->req);
3250 req->request_time = timeval_current();
3251 now = timeval_to_nttime(&req->request_time);
3253 status = smbd_smb2_inbuf_parse_compound(req->sconn->conn,
3259 &req->in.vector_count);
3260 if (!NT_STATUS_IS_OK(status)) {
3264 if (state->doing_receivefile) {
3265 req->smb1req = talloc_zero(req, struct smb_request);
3266 if (req->smb1req == NULL) {
3267 return NT_STATUS_NO_MEMORY;
3269 req->smb1req->unread_bytes =
3270 state->pktlen - SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3273 ZERO_STRUCTP(state);
3275 req->current_idx = 1;
3277 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3278 req->current_idx, req->in.vector_count));
3280 status = smbd_smb2_request_validate(req);
3281 if (!NT_STATUS_IS_OK(status)) {
3285 status = smbd_smb2_request_setup_out(req);
3286 if (!NT_STATUS_IS_OK(status)) {
3290 status = smbd_smb2_request_dispatch(req);
3291 if (!NT_STATUS_IS_OK(status)) {
3295 sconn->num_requests++;
3297 /* The timeout_processing function isn't run nearly
3298 often enough to implement 'max log size' without
3299 overrunning the size of the file by many megabytes.
3300 This is especially true if we are running at debug
3301 level 10. Checking every 50 SMB2s is a nice
3302 tradeoff of performance vs log file size overrun. */
3304 if ((sconn->num_requests % 50) == 0 &&
3305 need_to_check_log_size()) {
3306 change_to_root_user();
3310 status = smbd_smb2_request_next_incoming(sconn);
3311 if (!NT_STATUS_IS_OK(status)) {
3315 return NT_STATUS_OK;
3318 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3319 struct tevent_fd *fde,
3323 struct smbd_server_connection *sconn =
3324 talloc_get_type_abort(private_data,
3325 struct smbd_server_connection);
3328 status = smbd_smb2_io_handler(sconn, flags);
3329 if (!NT_STATUS_IS_OK(status)) {
3330 smbd_server_connection_terminate(sconn, nt_errstr(status));