2 Unix SMB/CIFS implementation.
5 Copyright (C) Stefan Metzmacher 2009
6 Copyright (C) Jeremy Allison 2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../libcli/smb/smb_common.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "../lib/util/tevent_ntstatus.h"
28 #include "smbprofile.h"
29 #include "../lib/util/bitmap.h"
30 #include "../librpc/gen_ndr/krb5pac.h"
33 #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9)
35 static const struct smbd_smb2_dispatch_table {
41 } smbd_smb2_table[] = {
42 #define _OP(o) .opcode = o, .name = #o
47 _OP(SMB2_OP_SESSSETUP),
57 * This call needs to be run as root.
59 * smbd_smb2_request_process_tcon()
60 * calls make_connection_snum(), which will call
61 * change_to_user(), when needed.
101 _OP(SMB2_OP_KEEPALIVE),
105 .need_session = true,
109 .need_session = true,
112 _OP(SMB2_OP_GETINFO),
113 .need_session = true,
116 _OP(SMB2_OP_SETINFO),
117 .need_session = true,
121 .need_session = true,
126 const char *smb2_opcode_name(uint16_t opcode)
128 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
129 return "Bad SMB2 opcode";
131 return smbd_smb2_table[opcode].name;
134 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
136 const struct smbd_smb2_dispatch_table *ret = NULL;
138 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
142 ret = &smbd_smb2_table[opcode];
144 SMB_ASSERT(ret->opcode == opcode);
149 static void print_req_vectors(struct smbd_smb2_request *req)
153 for (i = 0; i < req->in.vector_count; i++) {
154 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
156 (unsigned int)req->in.vector[i].iov_len);
158 for (i = 0; i < req->out.vector_count; i++) {
159 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
161 (unsigned int)req->out.vector[i].iov_len);
165 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
167 if (size < (4 + SMB2_HDR_BODY)) {
171 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
178 static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
183 TALLOC_FREE(sconn->smb1.fde);
185 sconn->smb2.recv_queue = tevent_queue_create(sconn, "smb2 recv queue");
186 if (sconn->smb2.recv_queue == NULL) {
187 return NT_STATUS_NO_MEMORY;
190 sconn->smb2.send_queue = tevent_queue_create(sconn, "smb2 send queue");
191 if (sconn->smb2.send_queue == NULL) {
192 return NT_STATUS_NO_MEMORY;
195 sconn->smb2.seqnum_low = 0;
196 sconn->smb2.seqnum_range = 1;
197 sconn->smb2.credits_granted = 1;
198 sconn->smb2.max_credits = lp_smb2_max_credits();
199 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
200 sconn->smb2.max_credits);
201 if (sconn->smb2.credits_bitmap == NULL) {
202 return NT_STATUS_NO_MEMORY;
205 ret = tstream_bsd_existing_socket(sconn, sconn->sock,
206 &sconn->smb2.stream);
208 status = map_nt_error_from_unix(errno);
212 /* Ensure child is set to non-blocking mode */
213 set_blocking(sconn->sock, false);
217 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
218 #define _smb2_setlen(_buf,len) do { \
219 uint8_t *buf = (uint8_t *)_buf; \
221 buf[1] = ((len)&0xFF0000)>>16; \
222 buf[2] = ((len)&0xFF00)>>8; \
223 buf[3] = (len)&0xFF; \
226 static void smb2_setup_nbt_length(struct iovec *vector, int count)
231 for (i=1; i < count; i++) {
232 len += vector[i].iov_len;
235 _smb2_setlen(vector[0].iov_base, len);
238 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
240 data_blob_clear_free(&req->last_key);
244 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
246 TALLOC_CTX *mem_pool;
247 struct smbd_smb2_request *req;
250 /* Enable this to find subtle valgrind errors. */
251 mem_pool = talloc_init("smbd_smb2_request_allocate");
253 mem_pool = talloc_pool(mem_ctx, 8192);
255 if (mem_pool == NULL) {
259 req = talloc_zero(mem_pool, struct smbd_smb2_request);
261 talloc_free(mem_pool);
264 talloc_reparent(mem_pool, mem_ctx, req);
265 TALLOC_FREE(mem_pool);
267 req->last_session_id = UINT64_MAX;
268 req->last_tid = UINT32_MAX;
270 talloc_set_destructor(req, smbd_smb2_request_destructor);
275 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn,
286 uint8_t *first_hdr = buf;
289 * Note: index '0' is reserved for the transport protocol
291 iov = talloc_zero_array(mem_ctx, struct iovec, num_iov);
293 return NT_STATUS_NO_MEMORY;
296 while (taken < buflen) {
297 size_t len = buflen - taken;
298 uint8_t *hdr = first_hdr + taken;
301 size_t next_command_ofs;
303 uint8_t *body = NULL;
306 struct iovec *iov_tmp;
309 * We need the header plus the body length field
312 if (len < SMB2_HDR_BODY + 2) {
313 DEBUG(10, ("%d bytes left, expected at least %d\n",
314 (int)len, SMB2_HDR_BODY));
317 if (IVAL(hdr, 0) != SMB2_MAGIC) {
318 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
322 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
323 DEBUG(10, ("Got HDR len %d, expected %d\n",
324 SVAL(hdr, 4), SMB2_HDR_BODY));
329 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
330 body_size = SVAL(hdr, SMB2_HDR_BODY);
332 if (next_command_ofs != 0) {
333 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
336 if (next_command_ofs > full_size) {
339 full_size = next_command_ofs;
346 if (body_size > (full_size - SMB2_HDR_BODY)) {
348 * let the caller handle the error
350 body_size = full_size - SMB2_HDR_BODY;
352 body = hdr + SMB2_HDR_BODY;
353 dyn = body + body_size;
354 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
356 iov_tmp = talloc_realloc(mem_ctx, iov, struct iovec,
357 num_iov + SMBD_SMB2_NUM_IOV_PER_REQ);
358 if (iov_tmp == NULL) {
360 return NT_STATUS_NO_MEMORY;
364 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
366 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
367 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
368 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
369 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
370 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
371 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
382 return NT_STATUS_INVALID_PARAMETER;
385 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
386 uint8_t *inbuf, size_t size,
387 struct smbd_smb2_request **_req)
389 struct smbd_smb2_request *req;
390 uint32_t protocol_version;
391 const uint8_t *inhdr = NULL;
393 uint32_t next_command_ofs;
397 if (size < (4 + SMB2_HDR_BODY + 2)) {
398 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
399 return NT_STATUS_INVALID_PARAMETER;
404 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
405 if (protocol_version != SMB2_MAGIC) {
406 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
408 return NT_STATUS_INVALID_PARAMETER;
411 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
412 if (cmd != SMB2_OP_NEGPROT) {
413 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
415 return NT_STATUS_INVALID_PARAMETER;
418 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
419 if (next_command_ofs != 0) {
420 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
422 return NT_STATUS_INVALID_PARAMETER;
425 req = smbd_smb2_request_allocate(sconn);
427 return NT_STATUS_NO_MEMORY;
431 talloc_steal(req, inbuf);
433 req->request_time = timeval_current();
434 now = timeval_to_nttime(&req->request_time);
436 status = smbd_smb2_inbuf_parse_compound(sconn->conn,
438 inbuf + NBT_HDR_SIZE,
440 req, &req->in.vector,
441 &req->in.vector_count);
442 if (!NT_STATUS_IS_OK(status)) {
447 req->current_idx = 1;
453 static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
454 uint64_t message_id, uint64_t seq_id)
456 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
459 if (seq_id < sconn->smb2.seqnum_low) {
460 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
461 "%llu (sequence id %llu) "
462 "(granted = %u, low = %llu, range = %u)\n",
463 (unsigned long long)message_id,
464 (unsigned long long)seq_id,
465 (unsigned int)sconn->smb2.credits_granted,
466 (unsigned long long)sconn->smb2.seqnum_low,
467 (unsigned int)sconn->smb2.seqnum_range));
471 if (seq_id >= sconn->smb2.seqnum_low + sconn->smb2.seqnum_range) {
472 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
473 "%llu (sequence id %llu) "
474 "(granted = %u, low = %llu, range = %u)\n",
475 (unsigned long long)message_id,
476 (unsigned long long)seq_id,
477 (unsigned int)sconn->smb2.credits_granted,
478 (unsigned long long)sconn->smb2.seqnum_low,
479 (unsigned int)sconn->smb2.seqnum_range));
483 offset = seq_id % sconn->smb2.max_credits;
485 if (bitmap_query(credits_bm, offset)) {
486 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
487 "%llu (sequence id %llu) "
488 "(granted = %u, low = %llu, range = %u) "
490 (unsigned long long)message_id,
491 (unsigned long long)seq_id,
492 (unsigned int)sconn->smb2.credits_granted,
493 (unsigned long long)sconn->smb2.seqnum_low,
494 (unsigned int)sconn->smb2.seqnum_range,
499 /* Mark the message_ids as seen in the bitmap. */
500 bitmap_set(credits_bm, offset);
502 if (seq_id != sconn->smb2.seqnum_low) {
507 * Move the window forward by all the message_id's
510 while (bitmap_query(credits_bm, offset)) {
511 DEBUG(10,("smb2_validate_sequence_number: clearing "
512 "id %llu (position %u) from bitmap\n",
513 (unsigned long long)(sconn->smb2.seqnum_low),
515 bitmap_clear(credits_bm, offset);
517 sconn->smb2.seqnum_low += 1;
518 sconn->smb2.seqnum_range -= 1;
519 offset = sconn->smb2.seqnum_low % sconn->smb2.max_credits;
525 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
526 const uint8_t *inhdr)
528 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
529 uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
530 uint16_t credit_charge = 1;
533 if (opcode == SMB2_OP_CANCEL) {
534 /* SMB2_CANCEL requests by definition resend messageids. */
538 if (sconn->smb2.supports_multicredit) {
539 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
540 credit_charge = MAX(credit_charge, 1);
543 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
544 "credits_granted %llu, "
545 "seqnum low/range: %llu/%llu\n",
546 (unsigned long long) message_id,
547 (unsigned long long) credit_charge,
548 (unsigned long long) sconn->smb2.credits_granted,
549 (unsigned long long) sconn->smb2.seqnum_low,
550 (unsigned long long) sconn->smb2.seqnum_range));
552 if (sconn->smb2.credits_granted < credit_charge) {
553 DEBUG(0, ("smb2_validate_message_id: client used more "
554 "credits than granted, mid %llu, charge %llu, "
555 "credits_granted %llu, "
556 "seqnum low/range: %llu/%llu\n",
557 (unsigned long long) message_id,
558 (unsigned long long) credit_charge,
559 (unsigned long long) sconn->smb2.credits_granted,
560 (unsigned long long) sconn->smb2.seqnum_low,
561 (unsigned long long) sconn->smb2.seqnum_range));
566 * now check the message ids
568 * for multi-credit requests we need to check all current mid plus
569 * the implicit mids caused by the credit charge
570 * e.g. current mid = 15, charge 5 => mark 15-19 as used
573 for (i = 0; i <= (credit_charge-1); i++) {
574 uint64_t id = message_id + i;
577 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
578 (unsigned long long)message_id,
580 (unsigned long long)id));
582 ok = smb2_validate_sequence_number(sconn, message_id, id);
588 /* substract used credits */
589 sconn->smb2.credits_granted -= credit_charge;
594 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
599 count = req->in.vector_count;
601 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
602 /* It's not a SMB2 request */
603 return NT_STATUS_INVALID_PARAMETER;
606 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
607 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
608 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
609 const uint8_t *inhdr = NULL;
612 if (hdr->iov_len != SMB2_HDR_BODY) {
613 return NT_STATUS_INVALID_PARAMETER;
616 if (body->iov_len < 2) {
617 return NT_STATUS_INVALID_PARAMETER;
620 inhdr = (const uint8_t *)hdr->iov_base;
622 /* Check the SMB2 header */
623 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
624 return NT_STATUS_INVALID_PARAMETER;
627 if (!smb2_validate_message_id(req->sconn, inhdr)) {
628 return NT_STATUS_INVALID_PARAMETER;
631 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
634 * the 1st request should never have the
635 * SMB2_HDR_FLAG_CHAINED flag set
637 if (flags & SMB2_HDR_FLAG_CHAINED) {
638 req->next_status = NT_STATUS_INVALID_PARAMETER;
641 } else if (idx == 4) {
643 * the 2nd request triggers related vs. unrelated
644 * compounded requests
646 if (flags & SMB2_HDR_FLAG_CHAINED) {
647 req->compound_related = true;
649 } else if (idx > 4) {
652 * It seems the this tests are wrong
653 * see the SMB2-COMPOUND test
657 * all other requests should match the 2nd one
659 if (flags & SMB2_HDR_FLAG_CHAINED) {
660 if (!req->compound_related) {
662 NT_STATUS_INVALID_PARAMETER;
666 if (req->compound_related) {
668 NT_STATUS_INVALID_PARAMETER;
679 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
680 const struct iovec *in_vector,
681 struct iovec *out_vector)
683 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
684 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
685 uint16_t credit_charge = 1;
686 uint16_t credits_requested;
690 uint16_t credits_granted = 0;
691 uint64_t credits_possible;
692 uint16_t current_max_credits;
695 * first we grant only 1/16th of the max range.
697 * Windows also starts with the 1/16th and then grants
698 * more later. I was only able to trigger higher
699 * values, when using a verify high credit charge.
701 * TODO: scale up depending one load, free memory
703 * Maybe also on the relationship between number
704 * of requests and the used sequence number.
705 * Which means we would grant more credits
706 * for client which use multi credit requests.
708 current_max_credits = sconn->smb2.max_credits / 16;
709 current_max_credits = MAX(current_max_credits, 1);
711 if (sconn->smb2.supports_multicredit) {
712 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
713 credit_charge = MAX(credit_charge, 1);
716 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
717 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
718 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
719 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
721 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
722 SMB_ASSERT(sconn->smb2.max_credits >= credit_charge);
724 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
726 * In case we already send an async interim
727 * response, we should not grant
728 * credits on the final response.
731 } else if (credits_requested > 0) {
732 uint16_t additional_max = 0;
733 uint16_t additional_credits = credits_requested - 1;
736 case SMB2_OP_NEGPROT:
738 case SMB2_OP_SESSSETUP:
740 * Windows 2012 RC1 starts to grant
742 * with a successful session setup
744 if (NT_STATUS_IS_OK(out_status)) {
750 * We match windows and only grant additional credits
757 additional_credits = MIN(additional_credits, additional_max);
759 credits_granted = credit_charge + additional_credits;
760 } else if (sconn->smb2.credits_granted == 0) {
762 * Make sure the client has always at least one credit
768 * sequence numbers should not wrap
770 * 1. calculate the possible credits until
771 * the sequence numbers start to wrap on 64-bit.
773 * 2. UINT64_MAX is used for Break Notifications.
775 * 2. truncate the possible credits to the maximum
776 * credits we want to grant to the client in total.
778 * 3. remove the range we'll already granted to the client
779 * this makes sure the client consumes the lowest sequence
780 * number, before we can grant additional credits.
782 credits_possible = UINT64_MAX - sconn->smb2.seqnum_low;
783 if (credits_possible > 0) {
784 /* remove UINT64_MAX */
785 credits_possible -= 1;
787 credits_possible = MIN(credits_possible, current_max_credits);
788 credits_possible -= sconn->smb2.seqnum_range;
790 credits_granted = MIN(credits_granted, credits_possible);
792 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
793 sconn->smb2.credits_granted += credits_granted;
794 sconn->smb2.seqnum_range += credits_granted;
796 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
797 "granted %u, current possible/max %u/%u, "
798 "total granted/max/low/range %u/%u/%llu/%u\n",
799 (unsigned int)credits_requested,
800 (unsigned int)credit_charge,
801 (unsigned int)credits_granted,
802 (unsigned int)credits_possible,
803 (unsigned int)current_max_credits,
804 (unsigned int)sconn->smb2.credits_granted,
805 (unsigned int)sconn->smb2.max_credits,
806 (unsigned long long)sconn->smb2.seqnum_low,
807 (unsigned int)sconn->smb2.seqnum_range));
810 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
811 struct smbd_smb2_request *outreq)
814 uint16_t total_credits = 0;
816 count = outreq->out.vector_count;
818 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
819 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
820 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
821 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
823 smb2_set_operation_credit(outreq->sconn, inhdr_v, outhdr_v);
825 /* To match Windows, count up what we
827 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
828 /* Set to zero in all but the last reply. */
829 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
830 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
832 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
837 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
839 struct iovec *vector;
843 count = req->in.vector_count;
844 vector = talloc_zero_array(req, struct iovec, count);
845 if (vector == NULL) {
846 return NT_STATUS_NO_MEMORY;
849 vector[0].iov_base = req->out.nbt_hdr;
850 vector[0].iov_len = 4;
851 SIVAL(req->out.nbt_hdr, 0, 0);
853 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
854 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
855 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
856 uint8_t *outhdr = NULL;
857 uint8_t *outbody = NULL;
858 uint32_t next_command_ofs = 0;
859 struct iovec *current = &vector[idx];
861 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
862 /* we have a next command -
863 * setup for the error case. */
864 next_command_ofs = SMB2_HDR_BODY + 9;
867 outhdr = talloc_zero_array(vector, uint8_t,
869 if (outhdr == NULL) {
870 return NT_STATUS_NO_MEMORY;
873 outbody = outhdr + SMB2_HDR_BODY;
875 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
876 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
878 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
879 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
881 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
882 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
884 /* setup the SMB2 header */
885 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
886 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
887 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
888 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
889 SIVAL(outhdr, SMB2_HDR_STATUS,
890 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
891 SSVAL(outhdr, SMB2_HDR_OPCODE,
892 SVAL(inhdr, SMB2_HDR_OPCODE));
893 SIVAL(outhdr, SMB2_HDR_FLAGS,
894 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
895 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
896 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
897 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
898 SIVAL(outhdr, SMB2_HDR_PID,
899 IVAL(inhdr, SMB2_HDR_PID));
900 SIVAL(outhdr, SMB2_HDR_TID,
901 IVAL(inhdr, SMB2_HDR_TID));
902 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
903 BVAL(inhdr, SMB2_HDR_SESSION_ID));
904 memcpy(outhdr + SMB2_HDR_SIGNATURE,
905 inhdr + SMB2_HDR_SIGNATURE, 16);
907 /* setup error body header */
908 SSVAL(outbody, 0x00, 0x08 + 1);
909 SSVAL(outbody, 0x02, 0);
910 SIVAL(outbody, 0x04, 0);
913 req->out.vector = vector;
914 req->out.vector_count = count;
916 /* setup the length of the NBT packet */
917 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
919 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
924 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
926 const char *location)
928 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
930 exit_server_cleanly(reason);
933 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
934 struct iovec *outvec,
935 const struct iovec *srcvec)
937 /* vec[0] is always boilerplate and must
938 * be allocated with size OUTVEC_ALLOC_SIZE. */
940 outvec[0].iov_base = talloc_memdup(ctx,
943 if (!outvec[0].iov_base) {
946 outvec[0].iov_len = SMB2_HDR_BODY;
949 * If this is a "standard" vec[1] of length 8,
950 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
951 * then duplicate this. Else use talloc_memdup().
954 if (srcvec[1].iov_len == 8 &&
955 srcvec[1].iov_base ==
956 ((uint8_t *)srcvec[0].iov_base) +
958 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
960 outvec[1].iov_len = 8;
962 outvec[1].iov_base = talloc_memdup(ctx,
965 if (!outvec[1].iov_base) {
968 outvec[1].iov_len = srcvec[1].iov_len;
972 * If this is a "standard" vec[2] of length 1,
973 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
974 * then duplicate this. Else use talloc_memdup().
977 if (srcvec[2].iov_base &&
979 if (srcvec[2].iov_base ==
980 ((uint8_t *)srcvec[0].iov_base) +
981 (OUTVEC_ALLOC_SIZE - 1) &&
982 srcvec[2].iov_len == 1) {
983 /* Common SMB2 error packet case. */
984 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
985 (OUTVEC_ALLOC_SIZE - 1);
987 outvec[2].iov_base = talloc_memdup(ctx,
990 if (!outvec[2].iov_base) {
994 outvec[2].iov_len = srcvec[2].iov_len;
996 outvec[2].iov_base = NULL;
997 outvec[2].iov_len = 0;
1002 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1004 struct smbd_smb2_request *newreq = NULL;
1005 struct iovec *outvec = NULL;
1006 int count = req->out.vector_count;
1009 newreq = smbd_smb2_request_allocate(req->sconn);
1014 newreq->sconn = req->sconn;
1015 newreq->session = req->session;
1016 newreq->do_signing = req->do_signing;
1017 newreq->current_idx = req->current_idx;
1019 outvec = talloc_zero_array(newreq, struct iovec, count);
1021 TALLOC_FREE(newreq);
1024 newreq->out.vector = outvec;
1025 newreq->out.vector_count = count;
1027 /* Setup the outvec's identically to req. */
1028 outvec[0].iov_base = newreq->out.nbt_hdr;
1029 outvec[0].iov_len = 4;
1030 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1032 /* Setup the vectors identically to the ones in req. */
1033 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1034 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
1041 TALLOC_FREE(newreq);
1045 smb2_setup_nbt_length(newreq->out.vector,
1046 newreq->out.vector_count);
1051 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
1053 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1055 struct smbXsrv_connection *conn = req->sconn->conn;
1056 struct iovec *outhdr_v = NULL;
1057 uint8_t *outhdr = NULL;
1058 struct smbd_smb2_request *nreq = NULL;
1061 /* Create a new smb2 request we'll use
1062 for the interim return. */
1063 nreq = dup_smb2_req(req);
1065 return NT_STATUS_NO_MEMORY;
1068 /* Lose the last X out vectors. They're the
1069 ones we'll be using for the async reply. */
1070 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1072 smb2_setup_nbt_length(nreq->out.vector,
1073 nreq->out.vector_count);
1075 /* Step back to the previous reply. */
1076 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1077 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1078 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1079 /* And end the chain. */
1080 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1082 /* Calculate outgoing credits */
1083 smb2_calculate_credits(req, nreq);
1086 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1087 * we need to sign here with the last signing key we remembered
1089 if (req->last_key.length > 0) {
1090 status = smb2_signing_sign_pdu(req->last_key,
1093 SMBD_SMB2_NUM_IOV_PER_REQ);
1094 if (!NT_STATUS_IS_OK(status)) {
1099 if (DEBUGLEVEL >= 10) {
1100 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1101 (unsigned int)nreq->current_idx );
1102 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1103 (unsigned int)nreq->out.vector_count );
1104 print_req_vectors(nreq);
1106 nreq->subreq = tstream_writev_queue_send(nreq,
1107 nreq->sconn->ev_ctx,
1108 nreq->sconn->smb2.stream,
1109 nreq->sconn->smb2.send_queue,
1111 nreq->out.vector_count);
1113 if (nreq->subreq == NULL) {
1114 return NT_STATUS_NO_MEMORY;
1117 tevent_req_set_callback(nreq->subreq,
1118 smbd_smb2_request_writev_done,
1121 return NT_STATUS_OK;
1124 struct smbd_smb2_request_pending_state {
1125 struct smbd_server_connection *sconn;
1126 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
1127 struct iovec vector[3];
1130 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
1132 struct smbd_smb2_request_pending_state *state =
1133 tevent_req_callback_data(subreq,
1134 struct smbd_smb2_request_pending_state);
1135 struct smbd_server_connection *sconn = state->sconn;
1139 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1140 TALLOC_FREE(subreq);
1142 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1143 smbd_server_connection_terminate(sconn, nt_errstr(status));
1150 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1151 struct tevent_timer *te,
1152 struct timeval current_time,
1153 void *private_data);
1155 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1156 struct tevent_req *subreq,
1157 uint32_t defer_time)
1160 int i = req->current_idx;
1161 struct timeval defer_endtime;
1162 uint8_t *outhdr = NULL;
1165 if (!tevent_req_is_in_progress(subreq)) {
1166 return NT_STATUS_OK;
1169 req->subreq = subreq;
1172 if (req->async_te) {
1173 /* We're already async. */
1174 return NT_STATUS_OK;
1177 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1178 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1179 if (flags & SMB2_HDR_FLAG_ASYNC) {
1180 /* We're already async. */
1181 return NT_STATUS_OK;
1184 if (req->in.vector_count > i + SMBD_SMB2_NUM_IOV_PER_REQ) {
1186 * We're trying to go async in a compound
1187 * request chain. This is not allowed.
1188 * Cancel the outstanding request.
1190 tevent_req_cancel(req->subreq);
1191 return smbd_smb2_request_error(req,
1192 NT_STATUS_INSUFFICIENT_RESOURCES);
1195 if (DEBUGLEVEL >= 10) {
1196 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1197 (unsigned int)req->current_idx );
1198 print_req_vectors(req);
1201 if (req->out.vector_count >= (2*SMBD_SMB2_NUM_IOV_PER_REQ)) {
1203 * This is a compound reply. We
1204 * must do an interim response
1205 * followed by the async response
1208 status = smb2_send_async_interim_response(req);
1209 if (!NT_STATUS_IS_OK(status)) {
1214 * We're splitting off the last SMB2
1215 * request in a compound set, and the
1216 * smb2_send_async_interim_response()
1217 * call above just sent all the replies
1218 * for the previous SMB2 requests in
1219 * this compound set. So we're no longer
1220 * in the "compound_related_in_progress"
1221 * state, and this is no longer a compound
1224 req->compound_related = false;
1225 req->sconn->smb2.compound_related_in_progress = false;
1227 req->current_idx = 1;
1229 /* Re-arrange the in.vectors. */
1230 memmove(&req->in.vector[req->current_idx],
1232 sizeof(req->in.vector[0])*SMBD_SMB2_NUM_IOV_PER_REQ);
1233 req->in.vector_count = req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ;
1235 /* Re-arrange the out.vectors. */
1236 memmove(&req->out.vector[req->current_idx],
1237 &req->out.vector[i],
1238 sizeof(req->out.vector[0])*SMBD_SMB2_NUM_IOV_PER_REQ);
1239 req->out.vector_count = req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ;
1241 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1242 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1243 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1245 data_blob_clear_free(&req->last_key);
1247 defer_endtime = timeval_current_ofs_usec(defer_time);
1248 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1250 smbd_smb2_request_pending_timer,
1252 if (req->async_te == NULL) {
1253 return NT_STATUS_NO_MEMORY;
1256 return NT_STATUS_OK;
1259 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1260 struct tevent_timer *te,
1261 struct timeval current_time,
1264 struct smbd_smb2_request *req =
1265 talloc_get_type_abort(private_data,
1266 struct smbd_smb2_request);
1267 struct smbd_smb2_request_pending_state *state = NULL;
1268 uint8_t *outhdr = NULL;
1269 const uint8_t *inhdr = NULL;
1270 uint8_t *hdr = NULL;
1271 uint8_t *body = NULL;
1273 uint64_t message_id = 0;
1274 uint64_t async_id = 0;
1275 struct tevent_req *subreq = NULL;
1277 TALLOC_FREE(req->async_te);
1279 /* Ensure our final reply matches the interim one. */
1280 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1281 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1282 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1283 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1285 async_id = message_id; /* keep it simple for now... */
1287 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1288 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1290 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1292 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1293 (unsigned long long)async_id ));
1296 * What we send is identical to a smbd_smb2_request_error
1297 * packet with an error status of STATUS_PENDING. Make use
1298 * of this fact sometime when refactoring. JRA.
1301 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1302 if (state == NULL) {
1303 smbd_server_connection_terminate(req->sconn,
1304 nt_errstr(NT_STATUS_NO_MEMORY));
1307 state->sconn = req->sconn;
1309 state->vector[0].iov_base = (void *)state->buf;
1310 state->vector[0].iov_len = 4;
1312 state->vector[1].iov_base = state->buf + 4;
1313 state->vector[1].iov_len = SMB2_HDR_BODY;
1315 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
1316 state->vector[2].iov_len = 9;
1318 smb2_setup_nbt_length(state->vector, 3);
1320 hdr = (uint8_t *)state->vector[1].iov_base;
1321 body = (uint8_t *)state->vector[2].iov_base;
1323 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1324 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1325 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1326 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1327 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1329 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1330 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1331 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1332 SBVAL(hdr, SMB2_HDR_PID, async_id);
1333 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1334 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1335 memcpy(hdr+SMB2_HDR_SIGNATURE,
1336 outhdr+SMB2_HDR_SIGNATURE, 16);
1338 SSVAL(body, 0x00, 0x08 + 1);
1340 SCVAL(body, 0x02, 0);
1341 SCVAL(body, 0x03, 0);
1342 SIVAL(body, 0x04, 0);
1343 /* Match W2K8R2... */
1344 SCVAL(body, 0x08, 0x21);
1346 /* Ensure we correctly go through crediting. Grant
1347 the credits now, and zero credits on the final
1349 smb2_set_operation_credit(req->sconn,
1350 SMBD_SMB2_IN_HDR_IOV(req),
1353 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1355 if (req->do_signing) {
1357 struct smbXsrv_session *x = req->session;
1358 struct smbXsrv_connection *conn = x->connection;
1359 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1361 status = smb2_signing_sign_pdu(signing_key,
1363 &state->vector[1], 2);
1364 if (!NT_STATUS_IS_OK(status)) {
1365 smbd_server_connection_terminate(req->sconn,
1371 subreq = tstream_writev_queue_send(state,
1372 state->sconn->ev_ctx,
1373 state->sconn->smb2.stream,
1374 state->sconn->smb2.send_queue,
1377 if (subreq == NULL) {
1378 smbd_server_connection_terminate(state->sconn,
1379 nt_errstr(NT_STATUS_NO_MEMORY));
1382 tevent_req_set_callback(subreq,
1383 smbd_smb2_request_pending_writev_done,
1387 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1389 struct smbd_server_connection *sconn = req->sconn;
1390 struct smbd_smb2_request *cur;
1391 const uint8_t *inhdr;
1393 uint64_t search_message_id;
1394 uint64_t search_async_id;
1397 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1399 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1400 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1401 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1404 * we don't need the request anymore
1405 * cancel requests never have a response
1407 DLIST_REMOVE(req->sconn->smb2.requests, req);
1410 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1411 const uint8_t *outhdr;
1412 uint64_t message_id;
1415 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1417 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1418 async_id = BVAL(outhdr, SMB2_HDR_PID);
1420 if (flags & SMB2_HDR_FLAG_ASYNC) {
1421 if (search_async_id == async_id) {
1422 found_id = async_id;
1426 if (search_message_id == message_id) {
1427 found_id = message_id;
1433 if (cur && cur->subreq) {
1434 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1435 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1436 "cancel opcode[%s] mid %llu\n",
1437 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1438 (unsigned long long)found_id ));
1439 tevent_req_cancel(cur->subreq);
1442 return NT_STATUS_OK;
1445 /*************************************************************
1446 Ensure an incoming tid is a valid one for us to access.
1447 Change to the associated uid credentials and chdir to the
1448 valid tid directory.
1449 *************************************************************/
1451 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1453 const uint8_t *inhdr;
1456 struct smbXsrv_tcon *tcon;
1458 NTTIME now = timeval_to_nttime(&req->request_time);
1462 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1464 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1465 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1467 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1468 in_tid = req->last_tid;
1471 status = smb2srv_tcon_lookup(req->session,
1472 in_tid, now, &tcon);
1473 if (!NT_STATUS_IS_OK(status)) {
1477 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1478 return NT_STATUS_ACCESS_DENIED;
1481 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1482 if (!set_current_service(tcon->compat, 0, true)) {
1483 return NT_STATUS_ACCESS_DENIED;
1487 req->last_tid = in_tid;
1489 return NT_STATUS_OK;
1492 /*************************************************************
1493 Ensure an incoming session_id is a valid one for us to access.
1494 *************************************************************/
1496 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1498 const uint8_t *inhdr;
1501 uint64_t in_session_id;
1502 struct smbXsrv_session *session = NULL;
1503 struct auth_session_info *session_info;
1505 NTTIME now = timeval_to_nttime(&req->request_time);
1507 req->session = NULL;
1510 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1512 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1513 in_opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1514 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1516 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1517 in_session_id = req->last_session_id;
1520 /* lookup an existing session */
1521 status = smb2srv_session_lookup(req->sconn->conn,
1525 req->session = session;
1526 req->last_session_id = in_session_id;
1528 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1529 switch (in_opcode) {
1530 case SMB2_OP_SESSSETUP:
1531 status = NT_STATUS_OK;
1537 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1538 switch (in_opcode) {
1540 case SMB2_OP_CREATE:
1541 case SMB2_OP_GETINFO:
1542 case SMB2_OP_SETINFO:
1543 return NT_STATUS_INVALID_HANDLE;
1546 * Notice the check for
1547 * (session_info == NULL)
1550 status = NT_STATUS_OK;
1554 if (!NT_STATUS_IS_OK(status)) {
1558 session_info = session->global->auth_session_info;
1559 if (session_info == NULL) {
1560 return NT_STATUS_INVALID_HANDLE;
1563 set_current_user_info(session_info->unix_info->sanitized_username,
1564 session_info->unix_info->unix_name,
1565 session_info->info->domain_name);
1567 return NT_STATUS_OK;
1570 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1571 uint32_t data_length)
1573 uint16_t needed_charge;
1574 uint16_t credit_charge = 1;
1575 const uint8_t *inhdr;
1577 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1579 if (req->sconn->smb2.supports_multicredit) {
1580 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1581 credit_charge = MAX(credit_charge, 1);
1584 needed_charge = (data_length - 1)/ 65536 + 1;
1586 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1587 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1588 credit_charge, needed_charge));
1590 if (needed_charge > credit_charge) {
1591 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1592 credit_charge, needed_charge));
1593 return NT_STATUS_INVALID_PARAMETER;
1596 return NT_STATUS_OK;
1599 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1600 size_t expected_body_size)
1602 const uint8_t *inhdr;
1604 const uint8_t *inbody;
1605 int i = req->current_idx;
1607 size_t min_dyn_size = expected_body_size & 0x00000001;
1610 * The following should be checked already.
1612 if ((i+2) > req->in.vector_count) {
1613 return NT_STATUS_INTERNAL_ERROR;
1615 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1616 return NT_STATUS_INTERNAL_ERROR;
1618 if (req->in.vector[i+1].iov_len < 2) {
1619 return NT_STATUS_INTERNAL_ERROR;
1622 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1623 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1627 case SMB2_OP_GETINFO:
1633 * Now check the expected body size,
1634 * where the last byte might be in the
1637 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1638 return NT_STATUS_INVALID_PARAMETER;
1640 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1641 return NT_STATUS_INVALID_PARAMETER;
1644 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1646 body_size = SVAL(inbody, 0x00);
1647 if (body_size != expected_body_size) {
1648 return NT_STATUS_INVALID_PARAMETER;
1651 return NT_STATUS_OK;
1654 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1656 struct smbXsrv_connection *conn = req->sconn->conn;
1657 const struct smbd_smb2_dispatch_table *call = NULL;
1658 const uint8_t *inhdr;
1663 NTSTATUS session_status;
1664 uint32_t allowed_flags;
1665 NTSTATUS return_value;
1666 struct smbXsrv_session *x = NULL;
1667 bool signing_required = false;
1669 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1671 /* TODO: verify more things */
1673 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1674 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1675 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1676 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1677 smb2_opcode_name(opcode),
1678 (unsigned long long)mid));
1680 if (conn->protocol >= PROTOCOL_SMB2_02) {
1682 * once the protocol is negotiated
1683 * SMB2_OP_NEGPROT is not allowed anymore
1685 if (opcode == SMB2_OP_NEGPROT) {
1686 /* drop the connection */
1687 return NT_STATUS_INVALID_PARAMETER;
1691 * if the protocol is not negotiated yet
1692 * only SMB2_OP_NEGPROT is allowed.
1694 if (opcode != SMB2_OP_NEGPROT) {
1695 /* drop the connection */
1696 return NT_STATUS_INVALID_PARAMETER;
1700 call = smbd_smb2_call(opcode);
1702 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1705 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1706 SMB2_HDR_FLAG_SIGNED |
1708 if (opcode == SMB2_OP_CANCEL) {
1709 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1711 if ((flags & ~allowed_flags) != 0) {
1712 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1716 * Check if the client provided a valid session id,
1717 * if so smbd_smb2_request_check_session() calls
1718 * set_current_user_info().
1720 * As some command don't require a valid session id
1721 * we defer the check of the session_status
1723 session_status = smbd_smb2_request_check_session(req);
1727 signing_required = x->global->signing_required;
1729 if (opcode == SMB2_OP_SESSSETUP &&
1730 x->global->channels[0].signing_key.length) {
1731 signing_required = true;
1735 req->do_signing = false;
1736 if (flags & SMB2_HDR_FLAG_SIGNED) {
1737 DATA_BLOB signing_key;
1740 return smbd_smb2_request_error(
1741 req, NT_STATUS_ACCESS_DENIED);
1744 signing_key = x->global->channels[0].signing_key;
1746 if (!NT_STATUS_IS_OK(session_status)) {
1747 return smbd_smb2_request_error(req, session_status);
1750 req->do_signing = true;
1751 status = smb2_signing_check_pdu(signing_key,
1753 SMBD_SMB2_IN_HDR_IOV(req),
1754 SMBD_SMB2_NUM_IOV_PER_REQ);
1755 if (!NT_STATUS_IS_OK(status)) {
1756 return smbd_smb2_request_error(req, status);
1758 } else if (opcode == SMB2_OP_CANCEL) {
1759 /* Cancel requests are allowed to skip the signing */
1760 } else if (signing_required) {
1761 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1764 if (flags & SMB2_HDR_FLAG_CHAINED) {
1766 * This check is mostly for giving the correct error code
1767 * for compounded requests.
1769 * TODO: we may need to move this after the session
1772 if (!NT_STATUS_IS_OK(req->next_status)) {
1773 return smbd_smb2_request_error(req, req->next_status);
1776 req->compat_chain_fsp = NULL;
1779 if (req->compound_related) {
1780 req->sconn->smb2.compound_related_in_progress = true;
1783 if (call->need_session) {
1784 if (!NT_STATUS_IS_OK(session_status)) {
1785 return smbd_smb2_request_error(req, session_status);
1789 if (call->need_tcon) {
1790 SMB_ASSERT(call->need_session);
1793 * This call needs to be run as user.
1795 * smbd_smb2_request_check_tcon()
1796 * calls change_to_user() on success.
1798 status = smbd_smb2_request_check_tcon(req);
1799 if (!NT_STATUS_IS_OK(status)) {
1800 return smbd_smb2_request_error(req, status);
1804 if (call->as_root) {
1805 /* This call needs to be run as root */
1806 change_to_root_user();
1808 SMB_ASSERT(call->need_tcon);
1812 case SMB2_OP_NEGPROT:
1814 START_PROFILE(smb2_negprot);
1815 return_value = smbd_smb2_request_process_negprot(req);
1816 END_PROFILE(smb2_negprot);
1820 case SMB2_OP_SESSSETUP:
1822 START_PROFILE(smb2_sesssetup);
1823 return_value = smbd_smb2_request_process_sesssetup(req);
1824 END_PROFILE(smb2_sesssetup);
1828 case SMB2_OP_LOGOFF:
1830 START_PROFILE(smb2_logoff);
1831 return_value = smbd_smb2_request_process_logoff(req);
1832 END_PROFILE(smb2_logoff);
1838 START_PROFILE(smb2_tcon);
1839 return_value = smbd_smb2_request_process_tcon(req);
1840 END_PROFILE(smb2_tcon);
1846 START_PROFILE(smb2_tdis);
1847 return_value = smbd_smb2_request_process_tdis(req);
1848 END_PROFILE(smb2_tdis);
1852 case SMB2_OP_CREATE:
1854 START_PROFILE(smb2_create);
1855 return_value = smbd_smb2_request_process_create(req);
1856 END_PROFILE(smb2_create);
1862 START_PROFILE(smb2_close);
1863 return_value = smbd_smb2_request_process_close(req);
1864 END_PROFILE(smb2_close);
1870 START_PROFILE(smb2_flush);
1871 return_value = smbd_smb2_request_process_flush(req);
1872 END_PROFILE(smb2_flush);
1878 START_PROFILE(smb2_read);
1879 return_value = smbd_smb2_request_process_read(req);
1880 END_PROFILE(smb2_read);
1886 START_PROFILE(smb2_write);
1887 return_value = smbd_smb2_request_process_write(req);
1888 END_PROFILE(smb2_write);
1894 START_PROFILE(smb2_lock);
1895 return_value = smbd_smb2_request_process_lock(req);
1896 END_PROFILE(smb2_lock);
1902 START_PROFILE(smb2_ioctl);
1903 return_value = smbd_smb2_request_process_ioctl(req);
1904 END_PROFILE(smb2_ioctl);
1908 case SMB2_OP_CANCEL:
1910 START_PROFILE(smb2_cancel);
1911 return_value = smbd_smb2_request_process_cancel(req);
1912 END_PROFILE(smb2_cancel);
1916 case SMB2_OP_KEEPALIVE:
1918 START_PROFILE(smb2_keepalive);
1919 return_value = smbd_smb2_request_process_keepalive(req);
1920 END_PROFILE(smb2_keepalive);
1926 START_PROFILE(smb2_find);
1927 return_value = smbd_smb2_request_process_find(req);
1928 END_PROFILE(smb2_find);
1932 case SMB2_OP_NOTIFY:
1934 START_PROFILE(smb2_notify);
1935 return_value = smbd_smb2_request_process_notify(req);
1936 END_PROFILE(smb2_notify);
1940 case SMB2_OP_GETINFO:
1942 START_PROFILE(smb2_getinfo);
1943 return_value = smbd_smb2_request_process_getinfo(req);
1944 END_PROFILE(smb2_getinfo);
1948 case SMB2_OP_SETINFO:
1950 START_PROFILE(smb2_setinfo);
1951 return_value = smbd_smb2_request_process_setinfo(req);
1952 END_PROFILE(smb2_setinfo);
1958 START_PROFILE(smb2_break);
1959 return_value = smbd_smb2_request_process_break(req);
1960 END_PROFILE(smb2_break);
1965 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1968 return return_value;
1971 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1973 struct smbXsrv_connection *conn = req->sconn->conn;
1974 struct tevent_req *subreq;
1975 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
1976 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
1979 TALLOC_FREE(req->async_te);
1981 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
1982 (req->last_key.length > 0)) {
1983 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
1984 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
1988 * As we are sure the header of the last request in the
1989 * compound chain will not change, we can to sign here
1990 * with the last signing key we remembered.
1993 status = smb2_signing_sign_pdu(req->last_key,
1996 SMBD_SMB2_NUM_IOV_PER_REQ);
1997 if (!NT_STATUS_IS_OK(status)) {
2001 data_blob_clear_free(&req->last_key);
2003 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2005 if (req->current_idx < req->out.vector_count) {
2007 * We must process the remaining compound
2008 * SMB2 requests before any new incoming SMB2
2009 * requests. This is because incoming SMB2
2010 * requests may include a cancel for a
2011 * compound request we haven't processed
2014 struct tevent_immediate *im = tevent_create_immediate(req);
2016 return NT_STATUS_NO_MEMORY;
2019 if (req->do_signing) {
2020 struct smbXsrv_session *x = req->session;
2021 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2024 * we need to remember the signing key
2025 * and defer the signing until
2026 * we are sure that we do not change
2029 req->last_key = data_blob_dup_talloc(req, signing_key);
2030 if (req->last_key.data == NULL) {
2031 return NT_STATUS_NO_MEMORY;
2035 tevent_schedule_immediate(im,
2037 smbd_smb2_request_dispatch_immediate,
2039 return NT_STATUS_OK;
2042 if (req->compound_related) {
2043 req->sconn->smb2.compound_related_in_progress = false;
2046 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2048 /* Set credit for these operations (zero credits if this
2049 is a final reply for an async operation). */
2050 smb2_calculate_credits(req, req);
2053 * now check if we need to sign the current response
2055 if (req->do_signing) {
2057 struct smbXsrv_session *x = req->session;
2058 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2060 status = smb2_signing_sign_pdu(signing_key,
2063 SMBD_SMB2_NUM_IOV_PER_REQ);
2064 if (!NT_STATUS_IS_OK(status)) {
2069 if (DEBUGLEVEL >= 10) {
2070 dbgtext("smbd_smb2_request_reply: sending...\n");
2071 print_req_vectors(req);
2074 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2075 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2076 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2077 /* Dynamic part is NULL. Chop it off,
2078 We're going to send it via sendfile. */
2079 req->out.vector_count -= 1;
2082 subreq = tstream_writev_queue_send(req,
2084 req->sconn->smb2.stream,
2085 req->sconn->smb2.send_queue,
2087 req->out.vector_count);
2088 if (subreq == NULL) {
2089 return NT_STATUS_NO_MEMORY;
2091 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
2093 * We're done with this request -
2094 * move it off the "being processed" queue.
2096 DLIST_REMOVE(req->sconn->smb2.requests, req);
2098 return NT_STATUS_OK;
2101 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2103 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2104 struct tevent_immediate *im,
2107 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2108 struct smbd_smb2_request);
2109 struct smbd_server_connection *sconn = req->sconn;
2114 if (DEBUGLEVEL >= 10) {
2115 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2116 req->current_idx, req->in.vector_count));
2117 print_req_vectors(req);
2120 status = smbd_smb2_request_dispatch(req);
2121 if (!NT_STATUS_IS_OK(status)) {
2122 smbd_server_connection_terminate(sconn, nt_errstr(status));
2126 status = smbd_smb2_request_next_incoming(sconn);
2127 if (!NT_STATUS_IS_OK(status)) {
2128 smbd_server_connection_terminate(sconn, nt_errstr(status));
2133 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
2135 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
2136 struct smbd_smb2_request);
2137 struct smbd_server_connection *sconn = req->sconn;
2142 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2143 TALLOC_FREE(subreq);
2146 status = map_nt_error_from_unix(sys_errno);
2147 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2148 nt_errstr(status)));
2149 smbd_server_connection_terminate(sconn, nt_errstr(status));
2153 status = smbd_smb2_request_next_incoming(sconn);
2154 if (!NT_STATUS_IS_OK(status)) {
2155 smbd_server_connection_terminate(sconn, nt_errstr(status));
2160 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2162 DATA_BLOB body, DATA_BLOB *dyn,
2163 const char *location)
2166 int i = req->current_idx;
2167 uint32_t next_command_ofs;
2169 DEBUG(10,("smbd_smb2_request_done_ex: "
2170 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2171 i, nt_errstr(status), (unsigned int)body.length,
2173 (unsigned int)(dyn ? dyn->length : 0),
2176 if (body.length < 2) {
2177 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2180 if ((body.length % 2) != 0) {
2181 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2184 outhdr = (uint8_t *)req->out.vector[i].iov_base;
2186 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2187 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2189 req->out.vector[i+1].iov_base = (void *)body.data;
2190 req->out.vector[i+1].iov_len = body.length;
2193 req->out.vector[i+2].iov_base = (void *)dyn->data;
2194 req->out.vector[i+2].iov_len = dyn->length;
2196 req->out.vector[i+2].iov_base = NULL;
2197 req->out.vector[i+2].iov_len = 0;
2200 /* see if we need to recalculate the offset to the next response */
2201 if (next_command_ofs > 0) {
2202 next_command_ofs = SMB2_HDR_BODY;
2203 next_command_ofs += req->out.vector[i+1].iov_len;
2204 next_command_ofs += req->out.vector[i+2].iov_len;
2207 if ((next_command_ofs % 8) != 0) {
2208 size_t pad_size = 8 - (next_command_ofs % 8);
2209 if (req->out.vector[i+2].iov_len == 0) {
2211 * if the dyn buffer is empty
2212 * we can use it to add padding
2216 pad = talloc_zero_array(req->out.vector,
2219 return smbd_smb2_request_error(req,
2220 NT_STATUS_NO_MEMORY);
2223 req->out.vector[i+2].iov_base = (void *)pad;
2224 req->out.vector[i+2].iov_len = pad_size;
2227 * For now we copy the dynamic buffer
2228 * and add the padding to the new buffer
2235 old_size = req->out.vector[i+2].iov_len;
2236 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2238 new_size = old_size + pad_size;
2239 new_dyn = talloc_zero_array(req->out.vector,
2241 if (new_dyn == NULL) {
2242 return smbd_smb2_request_error(req,
2243 NT_STATUS_NO_MEMORY);
2246 memcpy(new_dyn, old_dyn, old_size);
2247 memset(new_dyn + old_size, 0, pad_size);
2249 req->out.vector[i+2].iov_base = (void *)new_dyn;
2250 req->out.vector[i+2].iov_len = new_size;
2252 next_command_ofs += pad_size;
2255 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2257 return smbd_smb2_request_reply(req);
2260 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2263 const char *location)
2266 int i = req->current_idx;
2267 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2269 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2270 i, nt_errstr(status), info ? " +info" : "",
2273 body.data = outhdr + SMB2_HDR_BODY;
2275 SSVAL(body.data, 0, 9);
2278 SIVAL(body.data, 0x04, info->length);
2280 /* Allocated size of req->out.vector[i].iov_base
2281 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2282 * 1 byte without having to do an alloc.
2284 info = talloc_zero_array(req->out.vector,
2288 return NT_STATUS_NO_MEMORY;
2290 info->data = ((uint8_t *)outhdr) +
2291 OUTVEC_ALLOC_SIZE - 1;
2293 SCVAL(info->data, 0, 0);
2297 * if a request fails, all other remaining
2298 * compounded requests should fail too
2300 req->next_status = NT_STATUS_INVALID_PARAMETER;
2302 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2306 struct smbd_smb2_send_oplock_break_state {
2307 struct smbd_server_connection *sconn;
2308 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2309 struct iovec vector;
2312 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2314 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2315 uint64_t file_id_persistent,
2316 uint64_t file_id_volatile,
2317 uint8_t oplock_level)
2319 struct smbd_smb2_send_oplock_break_state *state;
2320 struct tevent_req *subreq;
2324 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2325 if (state == NULL) {
2326 return NT_STATUS_NO_MEMORY;
2328 state->sconn = sconn;
2330 state->vector.iov_base = (void *)state->buf;
2331 state->vector.iov_len = sizeof(state->buf);
2333 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2334 hdr = state->buf + 4;
2335 body = hdr + SMB2_HDR_BODY;
2337 SIVAL(hdr, 0, SMB2_MAGIC);
2338 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2339 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2340 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2341 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2342 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2343 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2344 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2345 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2346 SIVAL(hdr, SMB2_HDR_PID, 0);
2347 SIVAL(hdr, SMB2_HDR_TID, 0);
2348 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2349 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2351 SSVAL(body, 0x00, 0x18);
2353 SCVAL(body, 0x02, oplock_level);
2354 SCVAL(body, 0x03, 0); /* reserved */
2355 SIVAL(body, 0x04, 0); /* reserved */
2356 SBVAL(body, 0x08, file_id_persistent);
2357 SBVAL(body, 0x10, file_id_volatile);
2359 subreq = tstream_writev_queue_send(state,
2362 sconn->smb2.send_queue,
2364 if (subreq == NULL) {
2365 return NT_STATUS_NO_MEMORY;
2367 tevent_req_set_callback(subreq,
2368 smbd_smb2_oplock_break_writev_done,
2371 return NT_STATUS_OK;
2374 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2376 struct smbd_smb2_send_oplock_break_state *state =
2377 tevent_req_callback_data(subreq,
2378 struct smbd_smb2_send_oplock_break_state);
2379 struct smbd_server_connection *sconn = state->sconn;
2383 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2384 TALLOC_FREE(subreq);
2386 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2387 smbd_server_connection_terminate(sconn, nt_errstr(status));
2394 struct smbd_smb2_request_read_state {
2395 struct tevent_context *ev;
2396 struct smbd_server_connection *sconn;
2397 struct smbd_smb2_request *smb2_req;
2399 uint8_t nbt[NBT_HDR_SIZE];
2406 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2408 TALLOC_CTX *mem_ctx,
2409 struct iovec **_vector,
2411 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2413 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2414 struct tevent_context *ev,
2415 struct smbd_server_connection *sconn)
2417 struct tevent_req *req;
2418 struct smbd_smb2_request_read_state *state;
2419 struct tevent_req *subreq;
2421 req = tevent_req_create(mem_ctx, &state,
2422 struct smbd_smb2_request_read_state);
2427 state->sconn = sconn;
2429 state->smb2_req = smbd_smb2_request_allocate(state);
2430 if (tevent_req_nomem(state->smb2_req, req)) {
2431 return tevent_req_post(req, ev);
2433 state->smb2_req->sconn = sconn;
2435 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
2437 state->sconn->smb2.stream,
2438 state->sconn->smb2.recv_queue,
2439 smbd_smb2_request_next_vector,
2441 if (tevent_req_nomem(subreq, req)) {
2442 return tevent_req_post(req, ev);
2444 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2449 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2451 TALLOC_CTX *mem_ctx,
2452 struct iovec **_vector,
2455 struct smbd_smb2_request_read_state *state =
2456 talloc_get_type_abort(private_data,
2457 struct smbd_smb2_request_read_state);
2458 struct iovec *vector;
2460 if (state->pktlen > 0) {
2461 /* if there're no remaining bytes, we're done */
2467 if (!state->hdr.done) {
2469 * first we need to get the NBT header
2471 vector = talloc_array(mem_ctx, struct iovec, 1);
2472 if (vector == NULL) {
2476 vector[0].iov_base = (void *)state->hdr.nbt;
2477 vector[0].iov_len = NBT_HDR_SIZE;
2482 state->hdr.done = true;
2487 * Now we analyze the NBT header
2489 state->pktlen = smb2_len(state->hdr.nbt);
2491 if (state->pktlen == 0) {
2492 /* if there're no remaining bytes, we're done */
2498 state->pktbuf = talloc_array(state->smb2_req, uint8_t, state->pktlen);
2499 if (state->pktbuf == NULL) {
2503 vector = talloc_array(mem_ctx, struct iovec, 1);
2504 if (vector == NULL) {
2508 vector[0].iov_base = (void *)state->pktbuf;
2509 vector[0].iov_len = state->pktlen;
2516 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2518 struct tevent_req *req =
2519 tevent_req_callback_data(subreq,
2521 struct smbd_smb2_request_read_state *state =
2522 tevent_req_data(req,
2523 struct smbd_smb2_request_read_state);
2529 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2530 TALLOC_FREE(subreq);
2532 status = map_nt_error_from_unix(sys_errno);
2533 tevent_req_nterror(req, status);
2537 if (state->hdr.nbt[0] != 0x00) {
2538 DEBUG(1,("smbd_smb2_request_read_done: ignore NBT[0x%02X] msg\n",
2539 state->hdr.nbt[0]));
2541 ZERO_STRUCT(state->hdr);
2542 TALLOC_FREE(state->pktbuf);
2545 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
2547 state->sconn->smb2.stream,
2548 state->sconn->smb2.recv_queue,
2549 smbd_smb2_request_next_vector,
2551 if (tevent_req_nomem(subreq, req)) {
2554 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2558 state->smb2_req->request_time = timeval_current();
2559 now = timeval_to_nttime(&state->smb2_req->request_time);
2561 status = smbd_smb2_inbuf_parse_compound(state->smb2_req->sconn->conn,
2566 &state->smb2_req->in.vector,
2567 &state->smb2_req->in.vector_count);
2568 if (tevent_req_nterror(req, status)) {
2572 state->smb2_req->current_idx = 1;
2574 tevent_req_done(req);
2577 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2578 TALLOC_CTX *mem_ctx,
2579 struct smbd_smb2_request **_smb2_req)
2581 struct smbd_smb2_request_read_state *state =
2582 tevent_req_data(req,
2583 struct smbd_smb2_request_read_state);
2586 if (tevent_req_is_nterror(req, &status)) {
2587 tevent_req_received(req);
2591 *_smb2_req = talloc_move(mem_ctx, &state->smb2_req);
2592 tevent_req_received(req);
2593 return NT_STATUS_OK;
2596 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2598 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2600 size_t max_send_queue_len;
2601 size_t cur_send_queue_len;
2602 struct tevent_req *subreq;
2604 if (sconn->smb2.compound_related_in_progress) {
2606 * Can't read another until the related
2609 return NT_STATUS_OK;
2612 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2614 * if there is already a smbd_smb2_request_read
2615 * pending, we are done.
2617 return NT_STATUS_OK;
2620 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2621 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2623 if (cur_send_queue_len > max_send_queue_len) {
2625 * if we have a lot of requests to send,
2626 * we wait until they are on the wire until we
2627 * ask for the next request.
2629 return NT_STATUS_OK;
2632 /* ask for the next request */
2633 subreq = smbd_smb2_request_read_send(sconn, sconn->ev_ctx, sconn);
2634 if (subreq == NULL) {
2635 return NT_STATUS_NO_MEMORY;
2637 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2639 return NT_STATUS_OK;
2642 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2643 uint8_t *inbuf, size_t size)
2646 struct smbd_smb2_request *req = NULL;
2648 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2649 (unsigned int)size));
2651 status = smbd_initialize_smb2(sconn);
2652 if (!NT_STATUS_IS_OK(status)) {
2653 smbd_server_connection_terminate(sconn, nt_errstr(status));
2657 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2658 if (!NT_STATUS_IS_OK(status)) {
2659 smbd_server_connection_terminate(sconn, nt_errstr(status));
2663 status = smbd_smb2_request_validate(req);
2664 if (!NT_STATUS_IS_OK(status)) {
2665 smbd_server_connection_terminate(sconn, nt_errstr(status));
2669 status = smbd_smb2_request_setup_out(req);
2670 if (!NT_STATUS_IS_OK(status)) {
2671 smbd_server_connection_terminate(sconn, nt_errstr(status));
2675 status = smbd_smb2_request_dispatch(req);
2676 if (!NT_STATUS_IS_OK(status)) {
2677 smbd_server_connection_terminate(sconn, nt_errstr(status));
2681 status = smbd_smb2_request_next_incoming(sconn);
2682 if (!NT_STATUS_IS_OK(status)) {
2683 smbd_server_connection_terminate(sconn, nt_errstr(status));
2687 sconn->num_requests++;
2690 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2692 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2693 struct smbd_server_connection);
2695 struct smbd_smb2_request *req = NULL;
2697 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2698 TALLOC_FREE(subreq);
2699 if (!NT_STATUS_IS_OK(status)) {
2700 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2701 nt_errstr(status)));
2702 smbd_server_connection_terminate(sconn, nt_errstr(status));
2706 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2707 req->current_idx, req->in.vector_count));
2709 status = smbd_smb2_request_validate(req);
2710 if (!NT_STATUS_IS_OK(status)) {
2711 smbd_server_connection_terminate(sconn, nt_errstr(status));
2715 status = smbd_smb2_request_setup_out(req);
2716 if (!NT_STATUS_IS_OK(status)) {
2717 smbd_server_connection_terminate(sconn, nt_errstr(status));
2721 status = smbd_smb2_request_dispatch(req);
2722 if (!NT_STATUS_IS_OK(status)) {
2723 smbd_server_connection_terminate(sconn, nt_errstr(status));
2727 status = smbd_smb2_request_next_incoming(sconn);
2728 if (!NT_STATUS_IS_OK(status)) {
2729 smbd_server_connection_terminate(sconn, nt_errstr(status));
2733 sconn->num_requests++;
2735 /* The timeout_processing function isn't run nearly
2736 often enough to implement 'max log size' without
2737 overrunning the size of the file by many megabytes.
2738 This is especially true if we are running at debug
2739 level 10. Checking every 50 SMB2s is a nice
2740 tradeoff of performance vs log file size overrun. */
2742 if ((sconn->num_requests % 50) == 0 &&
2743 need_to_check_log_size()) {
2744 change_to_root_user();