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 struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
240 TALLOC_CTX *mem_pool;
241 struct smbd_smb2_request *req;
244 /* Enable this to find subtle valgrind errors. */
245 mem_pool = talloc_init("smbd_smb2_request_allocate");
247 mem_pool = talloc_pool(mem_ctx, 8192);
249 if (mem_pool == NULL) {
253 req = talloc_zero(mem_pool, struct smbd_smb2_request);
255 talloc_free(mem_pool);
258 talloc_reparent(mem_pool, mem_ctx, req);
259 TALLOC_FREE(mem_pool);
261 req->last_session_id = UINT64_MAX;
262 req->last_tid = UINT32_MAX;
267 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn,
278 uint8_t *first_hdr = buf;
281 * Note: index '0' is reserved for the transport protocol
283 iov = talloc_zero_array(mem_ctx, struct iovec, num_iov);
285 return NT_STATUS_NO_MEMORY;
288 while (taken < buflen) {
289 size_t len = buflen - taken;
290 uint8_t *hdr = first_hdr + taken;
293 size_t next_command_ofs;
295 struct iovec *iov_tmp;
298 * We need the header plus the body length field
301 if (len < SMB2_HDR_BODY + 2) {
302 DEBUG(10, ("%d bytes left, expected at least %d\n",
303 (int)len, SMB2_HDR_BODY));
306 if (IVAL(hdr, 0) != SMB2_MAGIC) {
307 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
311 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
312 DEBUG(10, ("Got HDR len %d, expected %d\n",
313 SVAL(hdr, 4), SMB2_HDR_BODY));
318 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
319 body_size = SVAL(hdr, SMB2_HDR_BODY);
321 if (next_command_ofs != 0) {
322 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
325 if (next_command_ofs > full_size) {
328 full_size = next_command_ofs;
335 if (body_size > (full_size - SMB2_HDR_BODY)) {
337 * let the caller handle the error
339 body_size = full_size - SMB2_HDR_BODY;
342 iov_tmp = talloc_realloc(mem_ctx, iov, struct iovec,
343 num_iov + SMBD_SMB2_NUM_IOV_PER_REQ);
344 if (iov_tmp == NULL) {
346 return NT_STATUS_NO_MEMORY;
350 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
352 cur[0].iov_base = hdr;
353 cur[0].iov_len = SMB2_HDR_BODY;
354 cur[1].iov_base = hdr + SMB2_HDR_BODY;
355 cur[1].iov_len = body_size;
356 cur[2].iov_base = hdr + SMB2_HDR_BODY + body_size;
357 cur[2].iov_len = full_size - (SMB2_HDR_BODY + body_size);
368 return NT_STATUS_INVALID_PARAMETER;
371 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
372 uint8_t *inbuf, size_t size,
373 struct smbd_smb2_request **_req)
375 struct smbd_smb2_request *req;
376 uint32_t protocol_version;
377 const uint8_t *inhdr = NULL;
379 uint32_t next_command_ofs;
383 if (size < (4 + SMB2_HDR_BODY + 2)) {
384 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
385 return NT_STATUS_INVALID_PARAMETER;
390 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
391 if (protocol_version != SMB2_MAGIC) {
392 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
394 return NT_STATUS_INVALID_PARAMETER;
397 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
398 if (cmd != SMB2_OP_NEGPROT) {
399 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
401 return NT_STATUS_INVALID_PARAMETER;
404 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
405 if (next_command_ofs != 0) {
406 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
408 return NT_STATUS_INVALID_PARAMETER;
411 req = smbd_smb2_request_allocate(sconn);
413 return NT_STATUS_NO_MEMORY;
417 talloc_steal(req, inbuf);
419 req->request_time = timeval_current();
420 now = timeval_to_nttime(&req->request_time);
422 status = smbd_smb2_inbuf_parse_compound(sconn->conn,
424 inbuf + NBT_HDR_SIZE,
426 req, &req->in.vector,
427 &req->in.vector_count);
428 if (!NT_STATUS_IS_OK(status)) {
433 req->current_idx = 1;
439 static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
440 uint64_t message_id, uint64_t seq_id)
442 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
445 if (seq_id < sconn->smb2.seqnum_low) {
446 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
447 "%llu (sequence id %llu) "
448 "(granted = %u, low = %llu, range = %u)\n",
449 (unsigned long long)message_id,
450 (unsigned long long)seq_id,
451 (unsigned int)sconn->smb2.credits_granted,
452 (unsigned long long)sconn->smb2.seqnum_low,
453 (unsigned int)sconn->smb2.seqnum_range));
457 if (seq_id >= sconn->smb2.seqnum_low + sconn->smb2.seqnum_range) {
458 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
459 "%llu (sequence id %llu) "
460 "(granted = %u, low = %llu, range = %u)\n",
461 (unsigned long long)message_id,
462 (unsigned long long)seq_id,
463 (unsigned int)sconn->smb2.credits_granted,
464 (unsigned long long)sconn->smb2.seqnum_low,
465 (unsigned int)sconn->smb2.seqnum_range));
469 offset = seq_id % sconn->smb2.max_credits;
471 if (bitmap_query(credits_bm, offset)) {
472 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
473 "%llu (sequence id %llu) "
474 "(granted = %u, low = %llu, range = %u) "
476 (unsigned long long)message_id,
477 (unsigned long long)seq_id,
478 (unsigned int)sconn->smb2.credits_granted,
479 (unsigned long long)sconn->smb2.seqnum_low,
480 (unsigned int)sconn->smb2.seqnum_range,
485 /* Mark the message_ids as seen in the bitmap. */
486 bitmap_set(credits_bm, offset);
488 if (seq_id != sconn->smb2.seqnum_low) {
493 * Move the window forward by all the message_id's
496 while (bitmap_query(credits_bm, offset)) {
497 DEBUG(10,("smb2_validate_sequence_number: clearing "
498 "id %llu (position %u) from bitmap\n",
499 (unsigned long long)(sconn->smb2.seqnum_low),
501 bitmap_clear(credits_bm, offset);
503 sconn->smb2.seqnum_low += 1;
504 sconn->smb2.seqnum_range -= 1;
505 offset = sconn->smb2.seqnum_low % sconn->smb2.max_credits;
511 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
512 const uint8_t *inhdr)
514 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
515 uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
516 uint16_t credit_charge = 1;
519 if (opcode == SMB2_OP_CANCEL) {
520 /* SMB2_CANCEL requests by definition resend messageids. */
524 if (sconn->smb2.supports_multicredit) {
525 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
526 credit_charge = MAX(credit_charge, 1);
529 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
530 "credits_granted %llu, "
531 "seqnum low/range: %llu/%llu\n",
532 (unsigned long long) message_id,
533 (unsigned long long) credit_charge,
534 (unsigned long long) sconn->smb2.credits_granted,
535 (unsigned long long) sconn->smb2.seqnum_low,
536 (unsigned long long) sconn->smb2.seqnum_range));
538 if (sconn->smb2.credits_granted < credit_charge) {
539 DEBUG(0, ("smb2_validate_message_id: client used more "
540 "credits than granted, mid %llu, charge %llu, "
541 "credits_granted %llu, "
542 "seqnum low/range: %llu/%llu\n",
543 (unsigned long long) message_id,
544 (unsigned long long) credit_charge,
545 (unsigned long long) sconn->smb2.credits_granted,
546 (unsigned long long) sconn->smb2.seqnum_low,
547 (unsigned long long) sconn->smb2.seqnum_range));
552 * now check the message ids
554 * for multi-credit requests we need to check all current mid plus
555 * the implicit mids caused by the credit charge
556 * e.g. current mid = 15, charge 5 => mark 15-19 as used
559 for (i = 0; i <= (credit_charge-1); i++) {
560 uint64_t id = message_id + i;
563 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
564 (unsigned long long)message_id,
566 (unsigned long long)id));
568 ok = smb2_validate_sequence_number(sconn, message_id, id);
574 /* substract used credits */
575 sconn->smb2.credits_granted -= credit_charge;
580 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
585 count = req->in.vector_count;
587 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
588 /* It's not a SMB2 request */
589 return NT_STATUS_INVALID_PARAMETER;
592 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
593 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
594 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
595 const uint8_t *inhdr = NULL;
598 if (hdr->iov_len != SMB2_HDR_BODY) {
599 return NT_STATUS_INVALID_PARAMETER;
602 if (body->iov_len < 2) {
603 return NT_STATUS_INVALID_PARAMETER;
606 inhdr = (const uint8_t *)hdr->iov_base;
608 /* Check the SMB2 header */
609 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
610 return NT_STATUS_INVALID_PARAMETER;
613 if (!smb2_validate_message_id(req->sconn, inhdr)) {
614 return NT_STATUS_INVALID_PARAMETER;
617 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
620 * the 1st request should never have the
621 * SMB2_HDR_FLAG_CHAINED flag set
623 if (flags & SMB2_HDR_FLAG_CHAINED) {
624 req->next_status = NT_STATUS_INVALID_PARAMETER;
627 } else if (idx == 4) {
629 * the 2nd request triggers related vs. unrelated
630 * compounded requests
632 if (flags & SMB2_HDR_FLAG_CHAINED) {
633 req->compound_related = true;
635 } else if (idx > 4) {
638 * It seems the this tests are wrong
639 * see the SMB2-COMPOUND test
643 * all other requests should match the 2nd one
645 if (flags & SMB2_HDR_FLAG_CHAINED) {
646 if (!req->compound_related) {
648 NT_STATUS_INVALID_PARAMETER;
652 if (req->compound_related) {
654 NT_STATUS_INVALID_PARAMETER;
665 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
666 const struct iovec *in_vector,
667 struct iovec *out_vector)
669 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
670 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
671 uint16_t credit_charge = 1;
672 uint16_t credits_requested;
676 uint16_t credits_granted = 0;
677 uint64_t credits_possible;
678 uint16_t current_max_credits;
681 * first we grant only 1/16th of the max range.
683 * Windows also starts with the 1/16th and then grants
684 * more later. I was only able to trigger higher
685 * values, when using a verify high credit charge.
687 * TODO: scale up depending one load, free memory
689 * Maybe also on the relationship between number
690 * of requests and the used sequence number.
691 * Which means we would grant more credits
692 * for client which use multi credit requests.
694 current_max_credits = sconn->smb2.max_credits / 16;
695 current_max_credits = MAX(current_max_credits, 1);
697 if (sconn->smb2.supports_multicredit) {
698 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
699 credit_charge = MAX(credit_charge, 1);
702 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
703 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
704 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
705 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
707 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
708 SMB_ASSERT(sconn->smb2.max_credits >= credit_charge);
710 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
712 * In case we already send an async interim
713 * response, we should not grant
714 * credits on the final response.
717 } else if (credits_requested > 0) {
718 uint16_t additional_max = 0;
719 uint16_t additional_credits = credits_requested - 1;
722 case SMB2_OP_NEGPROT:
724 case SMB2_OP_SESSSETUP:
726 * Windows 2012 RC1 starts to grant
728 * with a successful session setup
730 if (NT_STATUS_IS_OK(out_status)) {
736 * We match windows and only grant additional credits
743 additional_credits = MIN(additional_credits, additional_max);
745 credits_granted = credit_charge + additional_credits;
746 } else if (sconn->smb2.credits_granted == 0) {
748 * Make sure the client has always at least one credit
754 * sequence numbers should not wrap
756 * 1. calculate the possible credits until
757 * the sequence numbers start to wrap on 64-bit.
759 * 2. UINT64_MAX is used for Break Notifications.
761 * 2. truncate the possible credits to the maximum
762 * credits we want to grant to the client in total.
764 * 3. remove the range we'll already granted to the client
765 * this makes sure the client consumes the lowest sequence
766 * number, before we can grant additional credits.
768 credits_possible = UINT64_MAX - sconn->smb2.seqnum_low;
769 if (credits_possible > 0) {
770 /* remove UINT64_MAX */
771 credits_possible -= 1;
773 credits_possible = MIN(credits_possible, current_max_credits);
774 credits_possible -= sconn->smb2.seqnum_range;
776 credits_granted = MIN(credits_granted, credits_possible);
778 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
779 sconn->smb2.credits_granted += credits_granted;
780 sconn->smb2.seqnum_range += credits_granted;
782 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
783 "granted %u, current possible/max %u/%u, "
784 "total granted/max/low/range %u/%u/%llu/%u\n",
785 (unsigned int)credits_requested,
786 (unsigned int)credit_charge,
787 (unsigned int)credits_granted,
788 (unsigned int)credits_possible,
789 (unsigned int)current_max_credits,
790 (unsigned int)sconn->smb2.credits_granted,
791 (unsigned int)sconn->smb2.max_credits,
792 (unsigned long long)sconn->smb2.seqnum_low,
793 (unsigned int)sconn->smb2.seqnum_range));
796 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
797 struct smbd_smb2_request *outreq)
800 uint16_t total_credits = 0;
802 count = outreq->out.vector_count;
804 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
805 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
806 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
807 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
809 smb2_set_operation_credit(outreq->sconn, inhdr_v, outhdr_v);
811 /* To match Windows, count up what we
813 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
814 /* Set to zero in all but the last reply. */
815 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
816 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
818 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
823 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
825 struct iovec *vector;
829 count = req->in.vector_count;
830 vector = talloc_zero_array(req, struct iovec, count);
831 if (vector == NULL) {
832 return NT_STATUS_NO_MEMORY;
835 vector[0].iov_base = req->out.nbt_hdr;
836 vector[0].iov_len = 4;
837 SIVAL(req->out.nbt_hdr, 0, 0);
839 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
840 const uint8_t *inhdr = NULL;
841 uint8_t *outhdr = NULL;
842 uint8_t *outbody = NULL;
843 uint32_t next_command_ofs = 0;
844 struct iovec *current = &vector[idx];
846 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
847 /* we have a next command -
848 * setup for the error case. */
849 next_command_ofs = SMB2_HDR_BODY + 9;
852 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
854 outhdr = talloc_zero_array(vector, uint8_t,
856 if (outhdr == NULL) {
857 return NT_STATUS_NO_MEMORY;
860 outbody = outhdr + SMB2_HDR_BODY;
862 current[0].iov_base = (void *)outhdr;
863 current[0].iov_len = SMB2_HDR_BODY;
865 current[1].iov_base = (void *)outbody;
866 current[1].iov_len = 8;
868 current[2].iov_base = NULL;
869 current[2].iov_len = 0;
871 /* setup the SMB2 header */
872 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
873 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
874 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
875 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
876 SIVAL(outhdr, SMB2_HDR_STATUS,
877 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
878 SSVAL(outhdr, SMB2_HDR_OPCODE,
879 SVAL(inhdr, SMB2_HDR_OPCODE));
880 SIVAL(outhdr, SMB2_HDR_FLAGS,
881 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
882 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
883 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
884 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
885 SIVAL(outhdr, SMB2_HDR_PID,
886 IVAL(inhdr, SMB2_HDR_PID));
887 SIVAL(outhdr, SMB2_HDR_TID,
888 IVAL(inhdr, SMB2_HDR_TID));
889 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
890 BVAL(inhdr, SMB2_HDR_SESSION_ID));
891 memcpy(outhdr + SMB2_HDR_SIGNATURE,
892 inhdr + SMB2_HDR_SIGNATURE, 16);
894 /* setup error body header */
895 SSVAL(outbody, 0x00, 0x08 + 1);
896 SSVAL(outbody, 0x02, 0);
897 SIVAL(outbody, 0x04, 0);
900 req->out.vector = vector;
901 req->out.vector_count = count;
903 /* setup the length of the NBT packet */
904 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
906 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
911 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
913 const char *location)
915 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
917 exit_server_cleanly(reason);
920 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
921 struct iovec *outvec,
922 const struct iovec *srcvec)
924 /* vec[0] is always boilerplate and must
925 * be allocated with size OUTVEC_ALLOC_SIZE. */
927 outvec[0].iov_base = talloc_memdup(ctx,
930 if (!outvec[0].iov_base) {
933 outvec[0].iov_len = SMB2_HDR_BODY;
936 * If this is a "standard" vec[1] of length 8,
937 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
938 * then duplicate this. Else use talloc_memdup().
941 if (srcvec[1].iov_len == 8 &&
942 srcvec[1].iov_base ==
943 ((uint8_t *)srcvec[0].iov_base) +
945 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
947 outvec[1].iov_len = 8;
949 outvec[1].iov_base = talloc_memdup(ctx,
952 if (!outvec[1].iov_base) {
955 outvec[1].iov_len = srcvec[1].iov_len;
959 * If this is a "standard" vec[2] of length 1,
960 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
961 * then duplicate this. Else use talloc_memdup().
964 if (srcvec[2].iov_base &&
966 if (srcvec[2].iov_base ==
967 ((uint8_t *)srcvec[0].iov_base) +
968 (OUTVEC_ALLOC_SIZE - 1) &&
969 srcvec[2].iov_len == 1) {
970 /* Common SMB2 error packet case. */
971 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
972 (OUTVEC_ALLOC_SIZE - 1);
974 outvec[2].iov_base = talloc_memdup(ctx,
977 if (!outvec[2].iov_base) {
981 outvec[2].iov_len = srcvec[2].iov_len;
983 outvec[2].iov_base = NULL;
984 outvec[2].iov_len = 0;
989 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
991 struct smbd_smb2_request *newreq = NULL;
992 struct iovec *outvec = NULL;
993 int count = req->out.vector_count;
996 newreq = smbd_smb2_request_allocate(req->sconn);
1001 newreq->sconn = req->sconn;
1002 newreq->session = req->session;
1003 newreq->do_signing = req->do_signing;
1004 newreq->current_idx = req->current_idx;
1006 outvec = talloc_zero_array(newreq, struct iovec, count);
1008 TALLOC_FREE(newreq);
1011 newreq->out.vector = outvec;
1012 newreq->out.vector_count = count;
1014 /* Setup the outvec's identically to req. */
1015 outvec[0].iov_base = newreq->out.nbt_hdr;
1016 outvec[0].iov_len = 4;
1017 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1019 /* Setup the vectors identically to the ones in req. */
1020 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1021 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
1028 TALLOC_FREE(newreq);
1032 smb2_setup_nbt_length(newreq->out.vector,
1033 newreq->out.vector_count);
1038 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
1040 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1043 uint8_t *outhdr = NULL;
1044 struct smbd_smb2_request *nreq = NULL;
1046 /* Create a new smb2 request we'll use
1047 for the interim return. */
1048 nreq = dup_smb2_req(req);
1050 return NT_STATUS_NO_MEMORY;
1053 /* Lose the last X out vectors. They're the
1054 ones we'll be using for the async reply. */
1055 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1057 smb2_setup_nbt_length(nreq->out.vector,
1058 nreq->out.vector_count);
1060 /* Step back to the previous reply. */
1061 i = nreq->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
1062 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
1063 /* And end the chain. */
1064 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1066 /* Calculate outgoing credits */
1067 smb2_calculate_credits(req, nreq);
1069 /* Re-sign if needed. */
1070 if (nreq->do_signing) {
1072 struct smbXsrv_session *x = nreq->session;
1073 struct smbXsrv_connection *conn = x->connection;
1074 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1076 status = smb2_signing_sign_pdu(signing_key,
1078 &nreq->out.vector[i],
1079 SMBD_SMB2_NUM_IOV_PER_REQ);
1080 if (!NT_STATUS_IS_OK(status)) {
1084 if (DEBUGLEVEL >= 10) {
1085 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1086 (unsigned int)nreq->current_idx );
1087 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1088 (unsigned int)nreq->out.vector_count );
1089 print_req_vectors(nreq);
1091 nreq->subreq = tstream_writev_queue_send(nreq,
1092 nreq->sconn->ev_ctx,
1093 nreq->sconn->smb2.stream,
1094 nreq->sconn->smb2.send_queue,
1096 nreq->out.vector_count);
1098 if (nreq->subreq == NULL) {
1099 return NT_STATUS_NO_MEMORY;
1102 tevent_req_set_callback(nreq->subreq,
1103 smbd_smb2_request_writev_done,
1106 return NT_STATUS_OK;
1109 struct smbd_smb2_request_pending_state {
1110 struct smbd_server_connection *sconn;
1111 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
1112 struct iovec vector[3];
1115 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
1117 struct smbd_smb2_request_pending_state *state =
1118 tevent_req_callback_data(subreq,
1119 struct smbd_smb2_request_pending_state);
1120 struct smbd_server_connection *sconn = state->sconn;
1124 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1125 TALLOC_FREE(subreq);
1127 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1128 smbd_server_connection_terminate(sconn, nt_errstr(status));
1135 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1136 struct tevent_timer *te,
1137 struct timeval current_time,
1138 void *private_data);
1140 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1141 struct tevent_req *subreq,
1142 uint32_t defer_time)
1145 int i = req->current_idx;
1146 struct timeval defer_endtime;
1147 uint8_t *outhdr = NULL;
1150 if (!tevent_req_is_in_progress(subreq)) {
1151 return NT_STATUS_OK;
1154 req->subreq = subreq;
1157 if (req->async_te) {
1158 /* We're already async. */
1159 return NT_STATUS_OK;
1162 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1163 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1164 if (flags & SMB2_HDR_FLAG_ASYNC) {
1165 /* We're already async. */
1166 return NT_STATUS_OK;
1169 if (req->in.vector_count > i + SMBD_SMB2_NUM_IOV_PER_REQ) {
1171 * We're trying to go async in a compound
1172 * request chain. This is not allowed.
1173 * Cancel the outstanding request.
1175 tevent_req_cancel(req->subreq);
1176 return smbd_smb2_request_error(req,
1177 NT_STATUS_INSUFFICIENT_RESOURCES);
1180 if (DEBUGLEVEL >= 10) {
1181 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1182 (unsigned int)req->current_idx );
1183 print_req_vectors(req);
1186 if (req->out.vector_count > 4) {
1187 struct iovec *outvec = NULL;
1189 /* This is a compound reply. We
1190 * must do an interim response
1191 * followed by the async response
1194 status = smb2_send_async_interim_response(req);
1195 if (!NT_STATUS_IS_OK(status)) {
1200 * We're splitting off the last SMB2
1201 * request in a compound set, and the
1202 * smb2_send_async_interim_response()
1203 * call above just sent all the replies
1204 * for the previous SMB2 requests in
1205 * this compound set. So we're no longer
1206 * in the "compound_related_in_progress"
1207 * state, and this is no longer a compound
1210 req->compound_related = false;
1211 req->sconn->smb2.compound_related_in_progress = false;
1213 /* Re-arrange the in.vectors. */
1214 req->in.vector[1] = req->in.vector[i];
1215 req->in.vector[2] = req->in.vector[i+1];
1216 req->in.vector[3] = req->in.vector[i+2];
1217 req->in.vector_count = 4;
1219 /* Reset the new in size. */
1220 smb2_setup_nbt_length(req->in.vector, 4);
1222 /* Now recreate the out.vectors. */
1223 outvec = talloc_zero_array(req, struct iovec, 4);
1225 return NT_STATUS_NO_MEMORY;
1228 /* 0 is always boilerplate and must
1229 * be of size 4 for the length field. */
1231 outvec[0].iov_base = req->out.nbt_hdr;
1232 outvec[0].iov_len = 4;
1233 SIVAL(req->out.nbt_hdr, 0, 0);
1235 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
1236 return NT_STATUS_NO_MEMORY;
1239 TALLOC_FREE(req->out.vector);
1241 req->out.vector = outvec;
1243 req->current_idx = 1;
1244 req->out.vector_count = 4;
1246 outhdr = (uint8_t *)req->out.vector[1].iov_base;
1247 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1248 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1251 defer_endtime = timeval_current_ofs_usec(defer_time);
1252 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1254 smbd_smb2_request_pending_timer,
1256 if (req->async_te == NULL) {
1257 return NT_STATUS_NO_MEMORY;
1260 return NT_STATUS_OK;
1263 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1264 struct tevent_timer *te,
1265 struct timeval current_time,
1268 struct smbd_smb2_request *req =
1269 talloc_get_type_abort(private_data,
1270 struct smbd_smb2_request);
1271 struct smbd_smb2_request_pending_state *state = NULL;
1272 uint8_t *outhdr = NULL;
1273 const uint8_t *inhdr = NULL;
1274 uint8_t *hdr = NULL;
1275 uint8_t *body = NULL;
1277 uint64_t message_id = 0;
1278 uint64_t async_id = 0;
1279 struct tevent_req *subreq = NULL;
1281 TALLOC_FREE(req->async_te);
1283 /* Ensure our final reply matches the interim one. */
1284 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1285 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1286 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1287 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1289 async_id = message_id; /* keep it simple for now... */
1291 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1292 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1294 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1296 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1297 (unsigned long long)async_id ));
1300 * What we send is identical to a smbd_smb2_request_error
1301 * packet with an error status of STATUS_PENDING. Make use
1302 * of this fact sometime when refactoring. JRA.
1305 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1306 if (state == NULL) {
1307 smbd_server_connection_terminate(req->sconn,
1308 nt_errstr(NT_STATUS_NO_MEMORY));
1311 state->sconn = req->sconn;
1313 state->vector[0].iov_base = (void *)state->buf;
1314 state->vector[0].iov_len = 4;
1316 state->vector[1].iov_base = state->buf + 4;
1317 state->vector[1].iov_len = SMB2_HDR_BODY;
1319 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
1320 state->vector[2].iov_len = 9;
1322 smb2_setup_nbt_length(state->vector, 3);
1324 hdr = (uint8_t *)state->vector[1].iov_base;
1325 body = (uint8_t *)state->vector[2].iov_base;
1327 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1328 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1329 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1330 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1331 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1333 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1334 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1335 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1336 SBVAL(hdr, SMB2_HDR_PID, async_id);
1337 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1338 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1339 memcpy(hdr+SMB2_HDR_SIGNATURE,
1340 outhdr+SMB2_HDR_SIGNATURE, 16);
1342 SSVAL(body, 0x00, 0x08 + 1);
1344 SCVAL(body, 0x02, 0);
1345 SCVAL(body, 0x03, 0);
1346 SIVAL(body, 0x04, 0);
1347 /* Match W2K8R2... */
1348 SCVAL(body, 0x08, 0x21);
1350 /* Ensure we correctly go through crediting. Grant
1351 the credits now, and zero credits on the final
1353 smb2_set_operation_credit(req->sconn,
1354 SMBD_SMB2_IN_HDR_IOV(req),
1357 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1359 if (req->do_signing) {
1361 struct smbXsrv_session *x = req->session;
1362 struct smbXsrv_connection *conn = x->connection;
1363 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1365 status = smb2_signing_sign_pdu(signing_key,
1367 &state->vector[1], 2);
1368 if (!NT_STATUS_IS_OK(status)) {
1369 smbd_server_connection_terminate(req->sconn,
1375 subreq = tstream_writev_queue_send(state,
1376 state->sconn->ev_ctx,
1377 state->sconn->smb2.stream,
1378 state->sconn->smb2.send_queue,
1381 if (subreq == NULL) {
1382 smbd_server_connection_terminate(state->sconn,
1383 nt_errstr(NT_STATUS_NO_MEMORY));
1386 tevent_req_set_callback(subreq,
1387 smbd_smb2_request_pending_writev_done,
1391 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1393 struct smbd_server_connection *sconn = req->sconn;
1394 struct smbd_smb2_request *cur;
1395 const uint8_t *inhdr;
1397 uint64_t search_message_id;
1398 uint64_t search_async_id;
1401 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1403 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1404 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1405 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1408 * we don't need the request anymore
1409 * cancel requests never have a response
1411 DLIST_REMOVE(req->sconn->smb2.requests, req);
1414 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1415 const uint8_t *outhdr;
1416 uint64_t message_id;
1419 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1421 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1422 async_id = BVAL(outhdr, SMB2_HDR_PID);
1424 if (flags & SMB2_HDR_FLAG_ASYNC) {
1425 if (search_async_id == async_id) {
1426 found_id = async_id;
1430 if (search_message_id == message_id) {
1431 found_id = message_id;
1437 if (cur && cur->subreq) {
1438 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1439 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1440 "cancel opcode[%s] mid %llu\n",
1441 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1442 (unsigned long long)found_id ));
1443 tevent_req_cancel(cur->subreq);
1446 return NT_STATUS_OK;
1449 /*************************************************************
1450 Ensure an incoming tid is a valid one for us to access.
1451 Change to the associated uid credentials and chdir to the
1452 valid tid directory.
1453 *************************************************************/
1455 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1457 const uint8_t *inhdr;
1460 struct smbXsrv_tcon *tcon;
1462 NTTIME now = timeval_to_nttime(&req->request_time);
1466 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1468 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1469 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1471 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1472 in_tid = req->last_tid;
1475 status = smb2srv_tcon_lookup(req->session,
1476 in_tid, now, &tcon);
1477 if (!NT_STATUS_IS_OK(status)) {
1481 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1482 return NT_STATUS_ACCESS_DENIED;
1485 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1486 if (!set_current_service(tcon->compat, 0, true)) {
1487 return NT_STATUS_ACCESS_DENIED;
1491 req->last_tid = in_tid;
1493 return NT_STATUS_OK;
1496 /*************************************************************
1497 Ensure an incoming session_id is a valid one for us to access.
1498 *************************************************************/
1500 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1502 const uint8_t *inhdr;
1505 uint64_t in_session_id;
1506 struct smbXsrv_session *session = NULL;
1507 struct auth_session_info *session_info;
1509 NTTIME now = timeval_to_nttime(&req->request_time);
1511 req->session = NULL;
1514 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1516 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1517 in_opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1518 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1520 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1521 in_session_id = req->last_session_id;
1524 /* lookup an existing session */
1525 status = smb2srv_session_lookup(req->sconn->conn,
1529 req->session = session;
1530 req->last_session_id = in_session_id;
1532 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1533 switch (in_opcode) {
1534 case SMB2_OP_SESSSETUP:
1535 status = NT_STATUS_OK;
1541 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1542 switch (in_opcode) {
1544 case SMB2_OP_CREATE:
1545 case SMB2_OP_GETINFO:
1546 case SMB2_OP_SETINFO:
1547 return NT_STATUS_INVALID_HANDLE;
1550 * Notice the check for
1551 * (session_info == NULL)
1554 status = NT_STATUS_OK;
1558 if (!NT_STATUS_IS_OK(status)) {
1562 session_info = session->global->auth_session_info;
1563 if (session_info == NULL) {
1564 return NT_STATUS_INVALID_HANDLE;
1567 set_current_user_info(session_info->unix_info->sanitized_username,
1568 session_info->unix_info->unix_name,
1569 session_info->info->domain_name);
1571 return NT_STATUS_OK;
1574 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1575 uint32_t data_length)
1577 uint16_t needed_charge;
1578 uint16_t credit_charge = 1;
1579 const uint8_t *inhdr;
1581 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1583 if (req->sconn->smb2.supports_multicredit) {
1584 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1585 credit_charge = MAX(credit_charge, 1);
1588 needed_charge = (data_length - 1)/ 65536 + 1;
1590 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1591 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1592 credit_charge, needed_charge));
1594 if (needed_charge > credit_charge) {
1595 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1596 credit_charge, needed_charge));
1597 return NT_STATUS_INVALID_PARAMETER;
1600 return NT_STATUS_OK;
1603 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1604 size_t expected_body_size)
1606 const uint8_t *inhdr;
1608 const uint8_t *inbody;
1609 int i = req->current_idx;
1611 size_t min_dyn_size = expected_body_size & 0x00000001;
1614 * The following should be checked already.
1616 if ((i+2) > req->in.vector_count) {
1617 return NT_STATUS_INTERNAL_ERROR;
1619 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1620 return NT_STATUS_INTERNAL_ERROR;
1622 if (req->in.vector[i+1].iov_len < 2) {
1623 return NT_STATUS_INTERNAL_ERROR;
1626 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1627 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1631 case SMB2_OP_GETINFO:
1637 * Now check the expected body size,
1638 * where the last byte might be in the
1641 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1642 return NT_STATUS_INVALID_PARAMETER;
1644 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1645 return NT_STATUS_INVALID_PARAMETER;
1648 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1650 body_size = SVAL(inbody, 0x00);
1651 if (body_size != expected_body_size) {
1652 return NT_STATUS_INVALID_PARAMETER;
1655 return NT_STATUS_OK;
1658 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1660 struct smbXsrv_connection *conn = req->sconn->conn;
1661 const struct smbd_smb2_dispatch_table *call = NULL;
1662 const uint8_t *inhdr;
1667 NTSTATUS session_status;
1668 uint32_t allowed_flags;
1669 NTSTATUS return_value;
1670 struct smbXsrv_session *x = NULL;
1671 bool signing_required = false;
1673 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1675 /* TODO: verify more things */
1677 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1678 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1679 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1680 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1681 smb2_opcode_name(opcode),
1682 (unsigned long long)mid));
1684 if (conn->protocol >= PROTOCOL_SMB2_02) {
1686 * once the protocol is negotiated
1687 * SMB2_OP_NEGPROT is not allowed anymore
1689 if (opcode == SMB2_OP_NEGPROT) {
1690 /* drop the connection */
1691 return NT_STATUS_INVALID_PARAMETER;
1695 * if the protocol is not negotiated yet
1696 * only SMB2_OP_NEGPROT is allowed.
1698 if (opcode != SMB2_OP_NEGPROT) {
1699 /* drop the connection */
1700 return NT_STATUS_INVALID_PARAMETER;
1704 call = smbd_smb2_call(opcode);
1706 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1709 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1710 SMB2_HDR_FLAG_SIGNED |
1712 if (opcode == SMB2_OP_CANCEL) {
1713 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1715 if ((flags & ~allowed_flags) != 0) {
1716 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1720 * Check if the client provided a valid session id,
1721 * if so smbd_smb2_request_check_session() calls
1722 * set_current_user_info().
1724 * As some command don't require a valid session id
1725 * we defer the check of the session_status
1727 session_status = smbd_smb2_request_check_session(req);
1731 signing_required = x->global->signing_required;
1733 if (opcode == SMB2_OP_SESSSETUP &&
1734 x->global->channels[0].signing_key.length) {
1735 signing_required = true;
1739 req->do_signing = false;
1740 if (flags & SMB2_HDR_FLAG_SIGNED) {
1741 DATA_BLOB signing_key;
1744 return smbd_smb2_request_error(
1745 req, NT_STATUS_ACCESS_DENIED);
1748 signing_key = x->global->channels[0].signing_key;
1750 if (!NT_STATUS_IS_OK(session_status)) {
1751 return smbd_smb2_request_error(req, session_status);
1754 req->do_signing = true;
1755 status = smb2_signing_check_pdu(signing_key,
1757 SMBD_SMB2_IN_HDR_IOV(req),
1758 SMBD_SMB2_NUM_IOV_PER_REQ);
1759 if (!NT_STATUS_IS_OK(status)) {
1760 return smbd_smb2_request_error(req, status);
1762 } else if (opcode == SMB2_OP_CANCEL) {
1763 /* Cancel requests are allowed to skip the signing */
1764 } else if (signing_required) {
1765 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1768 if (flags & SMB2_HDR_FLAG_CHAINED) {
1770 * This check is mostly for giving the correct error code
1771 * for compounded requests.
1773 * TODO: we may need to move this after the session
1776 if (!NT_STATUS_IS_OK(req->next_status)) {
1777 return smbd_smb2_request_error(req, req->next_status);
1780 req->compat_chain_fsp = NULL;
1783 if (req->compound_related) {
1784 req->sconn->smb2.compound_related_in_progress = true;
1787 if (call->need_session) {
1788 if (!NT_STATUS_IS_OK(session_status)) {
1789 return smbd_smb2_request_error(req, session_status);
1793 if (call->need_tcon) {
1794 SMB_ASSERT(call->need_session);
1797 * This call needs to be run as user.
1799 * smbd_smb2_request_check_tcon()
1800 * calls change_to_user() on success.
1802 status = smbd_smb2_request_check_tcon(req);
1803 if (!NT_STATUS_IS_OK(status)) {
1804 return smbd_smb2_request_error(req, status);
1808 if (call->as_root) {
1809 /* This call needs to be run as root */
1810 change_to_root_user();
1812 SMB_ASSERT(call->need_tcon);
1816 case SMB2_OP_NEGPROT:
1818 START_PROFILE(smb2_negprot);
1819 return_value = smbd_smb2_request_process_negprot(req);
1820 END_PROFILE(smb2_negprot);
1824 case SMB2_OP_SESSSETUP:
1826 START_PROFILE(smb2_sesssetup);
1827 return_value = smbd_smb2_request_process_sesssetup(req);
1828 END_PROFILE(smb2_sesssetup);
1832 case SMB2_OP_LOGOFF:
1834 START_PROFILE(smb2_logoff);
1835 return_value = smbd_smb2_request_process_logoff(req);
1836 END_PROFILE(smb2_logoff);
1842 START_PROFILE(smb2_tcon);
1843 return_value = smbd_smb2_request_process_tcon(req);
1844 END_PROFILE(smb2_tcon);
1850 START_PROFILE(smb2_tdis);
1851 return_value = smbd_smb2_request_process_tdis(req);
1852 END_PROFILE(smb2_tdis);
1856 case SMB2_OP_CREATE:
1858 START_PROFILE(smb2_create);
1859 return_value = smbd_smb2_request_process_create(req);
1860 END_PROFILE(smb2_create);
1866 START_PROFILE(smb2_close);
1867 return_value = smbd_smb2_request_process_close(req);
1868 END_PROFILE(smb2_close);
1874 START_PROFILE(smb2_flush);
1875 return_value = smbd_smb2_request_process_flush(req);
1876 END_PROFILE(smb2_flush);
1882 START_PROFILE(smb2_read);
1883 return_value = smbd_smb2_request_process_read(req);
1884 END_PROFILE(smb2_read);
1890 START_PROFILE(smb2_write);
1891 return_value = smbd_smb2_request_process_write(req);
1892 END_PROFILE(smb2_write);
1898 START_PROFILE(smb2_lock);
1899 return_value = smbd_smb2_request_process_lock(req);
1900 END_PROFILE(smb2_lock);
1906 START_PROFILE(smb2_ioctl);
1907 return_value = smbd_smb2_request_process_ioctl(req);
1908 END_PROFILE(smb2_ioctl);
1912 case SMB2_OP_CANCEL:
1914 START_PROFILE(smb2_cancel);
1915 return_value = smbd_smb2_request_process_cancel(req);
1916 END_PROFILE(smb2_cancel);
1920 case SMB2_OP_KEEPALIVE:
1922 START_PROFILE(smb2_keepalive);
1923 return_value = smbd_smb2_request_process_keepalive(req);
1924 END_PROFILE(smb2_keepalive);
1930 START_PROFILE(smb2_find);
1931 return_value = smbd_smb2_request_process_find(req);
1932 END_PROFILE(smb2_find);
1936 case SMB2_OP_NOTIFY:
1938 START_PROFILE(smb2_notify);
1939 return_value = smbd_smb2_request_process_notify(req);
1940 END_PROFILE(smb2_notify);
1944 case SMB2_OP_GETINFO:
1946 START_PROFILE(smb2_getinfo);
1947 return_value = smbd_smb2_request_process_getinfo(req);
1948 END_PROFILE(smb2_getinfo);
1952 case SMB2_OP_SETINFO:
1954 START_PROFILE(smb2_setinfo);
1955 return_value = smbd_smb2_request_process_setinfo(req);
1956 END_PROFILE(smb2_setinfo);
1962 START_PROFILE(smb2_break);
1963 return_value = smbd_smb2_request_process_break(req);
1964 END_PROFILE(smb2_break);
1969 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1972 return return_value;
1975 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1977 struct tevent_req *subreq;
1978 int i = req->current_idx;
1981 TALLOC_FREE(req->async_te);
1983 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
1985 if (req->current_idx < req->out.vector_count) {
1987 * We must process the remaining compound
1988 * SMB2 requests before any new incoming SMB2
1989 * requests. This is because incoming SMB2
1990 * requests may include a cancel for a
1991 * compound request we haven't processed
1994 struct tevent_immediate *im = tevent_create_immediate(req);
1996 return NT_STATUS_NO_MEMORY;
1998 tevent_schedule_immediate(im,
2000 smbd_smb2_request_dispatch_immediate,
2002 return NT_STATUS_OK;
2005 if (req->compound_related) {
2006 req->sconn->smb2.compound_related_in_progress = false;
2009 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2011 /* Set credit for these operations (zero credits if this
2012 is a final reply for an async operation). */
2013 smb2_calculate_credits(req, req);
2015 if (req->do_signing) {
2017 struct smbXsrv_session *x = req->session;
2018 struct smbXsrv_connection *conn = x->connection;
2019 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2021 status = smb2_signing_sign_pdu(signing_key,
2023 &req->out.vector[i],
2024 SMBD_SMB2_NUM_IOV_PER_REQ);
2025 if (!NT_STATUS_IS_OK(status)) {
2030 if (DEBUGLEVEL >= 10) {
2031 dbgtext("smbd_smb2_request_reply: sending...\n");
2032 print_req_vectors(req);
2035 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2036 if (req->out.vector_count == 4 &&
2037 req->out.vector[3].iov_base == NULL &&
2038 req->out.vector[3].iov_len != 0) {
2039 /* Dynamic part is NULL. Chop it off,
2040 We're going to send it via sendfile. */
2041 req->out.vector_count -= 1;
2044 subreq = tstream_writev_queue_send(req,
2046 req->sconn->smb2.stream,
2047 req->sconn->smb2.send_queue,
2049 req->out.vector_count);
2050 if (subreq == NULL) {
2051 return NT_STATUS_NO_MEMORY;
2053 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
2055 * We're done with this request -
2056 * move it off the "being processed" queue.
2058 DLIST_REMOVE(req->sconn->smb2.requests, req);
2060 return NT_STATUS_OK;
2063 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2065 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2066 struct tevent_immediate *im,
2069 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2070 struct smbd_smb2_request);
2071 struct smbd_server_connection *sconn = req->sconn;
2076 if (DEBUGLEVEL >= 10) {
2077 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2078 req->current_idx, req->in.vector_count));
2079 print_req_vectors(req);
2082 status = smbd_smb2_request_dispatch(req);
2083 if (!NT_STATUS_IS_OK(status)) {
2084 smbd_server_connection_terminate(sconn, nt_errstr(status));
2088 status = smbd_smb2_request_next_incoming(sconn);
2089 if (!NT_STATUS_IS_OK(status)) {
2090 smbd_server_connection_terminate(sconn, nt_errstr(status));
2095 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
2097 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
2098 struct smbd_smb2_request);
2099 struct smbd_server_connection *sconn = req->sconn;
2104 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2105 TALLOC_FREE(subreq);
2108 status = map_nt_error_from_unix(sys_errno);
2109 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2110 nt_errstr(status)));
2111 smbd_server_connection_terminate(sconn, nt_errstr(status));
2115 status = smbd_smb2_request_next_incoming(sconn);
2116 if (!NT_STATUS_IS_OK(status)) {
2117 smbd_server_connection_terminate(sconn, nt_errstr(status));
2122 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2124 DATA_BLOB body, DATA_BLOB *dyn,
2125 const char *location)
2128 int i = req->current_idx;
2129 uint32_t next_command_ofs;
2131 DEBUG(10,("smbd_smb2_request_done_ex: "
2132 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2133 i, nt_errstr(status), (unsigned int)body.length,
2135 (unsigned int)(dyn ? dyn->length : 0),
2138 if (body.length < 2) {
2139 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2142 if ((body.length % 2) != 0) {
2143 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2146 outhdr = (uint8_t *)req->out.vector[i].iov_base;
2148 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2149 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2151 req->out.vector[i+1].iov_base = (void *)body.data;
2152 req->out.vector[i+1].iov_len = body.length;
2155 req->out.vector[i+2].iov_base = (void *)dyn->data;
2156 req->out.vector[i+2].iov_len = dyn->length;
2158 req->out.vector[i+2].iov_base = NULL;
2159 req->out.vector[i+2].iov_len = 0;
2162 /* see if we need to recalculate the offset to the next response */
2163 if (next_command_ofs > 0) {
2164 next_command_ofs = SMB2_HDR_BODY;
2165 next_command_ofs += req->out.vector[i+1].iov_len;
2166 next_command_ofs += req->out.vector[i+2].iov_len;
2169 if ((next_command_ofs % 8) != 0) {
2170 size_t pad_size = 8 - (next_command_ofs % 8);
2171 if (req->out.vector[i+2].iov_len == 0) {
2173 * if the dyn buffer is empty
2174 * we can use it to add padding
2178 pad = talloc_zero_array(req->out.vector,
2181 return smbd_smb2_request_error(req,
2182 NT_STATUS_NO_MEMORY);
2185 req->out.vector[i+2].iov_base = (void *)pad;
2186 req->out.vector[i+2].iov_len = pad_size;
2189 * For now we copy the dynamic buffer
2190 * and add the padding to the new buffer
2197 old_size = req->out.vector[i+2].iov_len;
2198 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2200 new_size = old_size + pad_size;
2201 new_dyn = talloc_zero_array(req->out.vector,
2203 if (new_dyn == NULL) {
2204 return smbd_smb2_request_error(req,
2205 NT_STATUS_NO_MEMORY);
2208 memcpy(new_dyn, old_dyn, old_size);
2209 memset(new_dyn + old_size, 0, pad_size);
2211 req->out.vector[i+2].iov_base = (void *)new_dyn;
2212 req->out.vector[i+2].iov_len = new_size;
2214 next_command_ofs += pad_size;
2217 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2219 return smbd_smb2_request_reply(req);
2222 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2225 const char *location)
2228 int i = req->current_idx;
2229 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2231 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2232 i, nt_errstr(status), info ? " +info" : "",
2235 body.data = outhdr + SMB2_HDR_BODY;
2237 SSVAL(body.data, 0, 9);
2240 SIVAL(body.data, 0x04, info->length);
2242 /* Allocated size of req->out.vector[i].iov_base
2243 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2244 * 1 byte without having to do an alloc.
2246 info = talloc_zero_array(req->out.vector,
2250 return NT_STATUS_NO_MEMORY;
2252 info->data = ((uint8_t *)outhdr) +
2253 OUTVEC_ALLOC_SIZE - 1;
2255 SCVAL(info->data, 0, 0);
2259 * if a request fails, all other remaining
2260 * compounded requests should fail too
2262 req->next_status = NT_STATUS_INVALID_PARAMETER;
2264 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2268 struct smbd_smb2_send_oplock_break_state {
2269 struct smbd_server_connection *sconn;
2270 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2271 struct iovec vector;
2274 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2276 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2277 uint64_t file_id_persistent,
2278 uint64_t file_id_volatile,
2279 uint8_t oplock_level)
2281 struct smbd_smb2_send_oplock_break_state *state;
2282 struct tevent_req *subreq;
2286 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2287 if (state == NULL) {
2288 return NT_STATUS_NO_MEMORY;
2290 state->sconn = sconn;
2292 state->vector.iov_base = (void *)state->buf;
2293 state->vector.iov_len = sizeof(state->buf);
2295 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2296 hdr = state->buf + 4;
2297 body = hdr + SMB2_HDR_BODY;
2299 SIVAL(hdr, 0, SMB2_MAGIC);
2300 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2301 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2302 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2303 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2304 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2305 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2306 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2307 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2308 SIVAL(hdr, SMB2_HDR_PID, 0);
2309 SIVAL(hdr, SMB2_HDR_TID, 0);
2310 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2311 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2313 SSVAL(body, 0x00, 0x18);
2315 SCVAL(body, 0x02, oplock_level);
2316 SCVAL(body, 0x03, 0); /* reserved */
2317 SIVAL(body, 0x04, 0); /* reserved */
2318 SBVAL(body, 0x08, file_id_persistent);
2319 SBVAL(body, 0x10, file_id_volatile);
2321 subreq = tstream_writev_queue_send(state,
2324 sconn->smb2.send_queue,
2326 if (subreq == NULL) {
2327 return NT_STATUS_NO_MEMORY;
2329 tevent_req_set_callback(subreq,
2330 smbd_smb2_oplock_break_writev_done,
2333 return NT_STATUS_OK;
2336 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2338 struct smbd_smb2_send_oplock_break_state *state =
2339 tevent_req_callback_data(subreq,
2340 struct smbd_smb2_send_oplock_break_state);
2341 struct smbd_server_connection *sconn = state->sconn;
2345 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2346 TALLOC_FREE(subreq);
2348 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2349 smbd_server_connection_terminate(sconn, nt_errstr(status));
2356 struct smbd_smb2_request_read_state {
2357 struct tevent_context *ev;
2358 struct smbd_server_connection *sconn;
2359 struct smbd_smb2_request *smb2_req;
2361 uint8_t nbt[NBT_HDR_SIZE];
2368 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2370 TALLOC_CTX *mem_ctx,
2371 struct iovec **_vector,
2373 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2375 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2376 struct tevent_context *ev,
2377 struct smbd_server_connection *sconn)
2379 struct tevent_req *req;
2380 struct smbd_smb2_request_read_state *state;
2381 struct tevent_req *subreq;
2383 req = tevent_req_create(mem_ctx, &state,
2384 struct smbd_smb2_request_read_state);
2389 state->sconn = sconn;
2391 state->smb2_req = smbd_smb2_request_allocate(state);
2392 if (tevent_req_nomem(state->smb2_req, req)) {
2393 return tevent_req_post(req, ev);
2395 state->smb2_req->sconn = sconn;
2397 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
2399 state->sconn->smb2.stream,
2400 state->sconn->smb2.recv_queue,
2401 smbd_smb2_request_next_vector,
2403 if (tevent_req_nomem(subreq, req)) {
2404 return tevent_req_post(req, ev);
2406 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2411 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2413 TALLOC_CTX *mem_ctx,
2414 struct iovec **_vector,
2417 struct smbd_smb2_request_read_state *state =
2418 talloc_get_type_abort(private_data,
2419 struct smbd_smb2_request_read_state);
2420 struct iovec *vector;
2422 if (state->pktlen > 0) {
2423 /* if there're no remaining bytes, we're done */
2429 if (!state->hdr.done) {
2431 * first we need to get the NBT header
2433 vector = talloc_array(mem_ctx, struct iovec, 1);
2434 if (vector == NULL) {
2438 vector[0].iov_base = (void *)state->hdr.nbt;
2439 vector[0].iov_len = NBT_HDR_SIZE;
2444 state->hdr.done = true;
2449 * Now we analyze the NBT header
2451 state->pktlen = smb2_len(state->hdr.nbt);
2453 if (state->pktlen == 0) {
2454 /* if there're no remaining bytes, we're done */
2460 state->pktbuf = talloc_array(state->smb2_req, uint8_t, state->pktlen);
2461 if (state->pktbuf == NULL) {
2465 vector = talloc_array(mem_ctx, struct iovec, 1);
2466 if (vector == NULL) {
2470 vector[0].iov_base = (void *)state->pktbuf;
2471 vector[0].iov_len = state->pktlen;
2478 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2480 struct tevent_req *req =
2481 tevent_req_callback_data(subreq,
2483 struct smbd_smb2_request_read_state *state =
2484 tevent_req_data(req,
2485 struct smbd_smb2_request_read_state);
2491 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2492 TALLOC_FREE(subreq);
2494 status = map_nt_error_from_unix(sys_errno);
2495 tevent_req_nterror(req, status);
2499 if (state->hdr.nbt[0] != 0x00) {
2500 DEBUG(1,("smbd_smb2_request_read_done: ignore NBT[0x%02X] msg\n",
2501 state->hdr.nbt[0]));
2503 ZERO_STRUCT(state->hdr);
2504 TALLOC_FREE(state->pktbuf);
2507 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
2509 state->sconn->smb2.stream,
2510 state->sconn->smb2.recv_queue,
2511 smbd_smb2_request_next_vector,
2513 if (tevent_req_nomem(subreq, req)) {
2516 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2520 state->smb2_req->request_time = timeval_current();
2521 now = timeval_to_nttime(&state->smb2_req->request_time);
2523 status = smbd_smb2_inbuf_parse_compound(state->smb2_req->sconn->conn,
2528 &state->smb2_req->in.vector,
2529 &state->smb2_req->in.vector_count);
2530 if (tevent_req_nterror(req, status)) {
2534 state->smb2_req->current_idx = 1;
2536 tevent_req_done(req);
2539 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2540 TALLOC_CTX *mem_ctx,
2541 struct smbd_smb2_request **_smb2_req)
2543 struct smbd_smb2_request_read_state *state =
2544 tevent_req_data(req,
2545 struct smbd_smb2_request_read_state);
2548 if (tevent_req_is_nterror(req, &status)) {
2549 tevent_req_received(req);
2553 *_smb2_req = talloc_move(mem_ctx, &state->smb2_req);
2554 tevent_req_received(req);
2555 return NT_STATUS_OK;
2558 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2560 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2562 size_t max_send_queue_len;
2563 size_t cur_send_queue_len;
2564 struct tevent_req *subreq;
2566 if (sconn->smb2.compound_related_in_progress) {
2568 * Can't read another until the related
2571 return NT_STATUS_OK;
2574 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2576 * if there is already a smbd_smb2_request_read
2577 * pending, we are done.
2579 return NT_STATUS_OK;
2582 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2583 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2585 if (cur_send_queue_len > max_send_queue_len) {
2587 * if we have a lot of requests to send,
2588 * we wait until they are on the wire until we
2589 * ask for the next request.
2591 return NT_STATUS_OK;
2594 /* ask for the next request */
2595 subreq = smbd_smb2_request_read_send(sconn, sconn->ev_ctx, sconn);
2596 if (subreq == NULL) {
2597 return NT_STATUS_NO_MEMORY;
2599 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2601 return NT_STATUS_OK;
2604 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2605 uint8_t *inbuf, size_t size)
2608 struct smbd_smb2_request *req = NULL;
2610 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2611 (unsigned int)size));
2613 status = smbd_initialize_smb2(sconn);
2614 if (!NT_STATUS_IS_OK(status)) {
2615 smbd_server_connection_terminate(sconn, nt_errstr(status));
2619 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2620 if (!NT_STATUS_IS_OK(status)) {
2621 smbd_server_connection_terminate(sconn, nt_errstr(status));
2625 status = smbd_smb2_request_validate(req);
2626 if (!NT_STATUS_IS_OK(status)) {
2627 smbd_server_connection_terminate(sconn, nt_errstr(status));
2631 status = smbd_smb2_request_setup_out(req);
2632 if (!NT_STATUS_IS_OK(status)) {
2633 smbd_server_connection_terminate(sconn, nt_errstr(status));
2637 status = smbd_smb2_request_dispatch(req);
2638 if (!NT_STATUS_IS_OK(status)) {
2639 smbd_server_connection_terminate(sconn, nt_errstr(status));
2643 status = smbd_smb2_request_next_incoming(sconn);
2644 if (!NT_STATUS_IS_OK(status)) {
2645 smbd_server_connection_terminate(sconn, nt_errstr(status));
2649 sconn->num_requests++;
2652 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2654 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2655 struct smbd_server_connection);
2657 struct smbd_smb2_request *req = NULL;
2659 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2660 TALLOC_FREE(subreq);
2661 if (!NT_STATUS_IS_OK(status)) {
2662 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2663 nt_errstr(status)));
2664 smbd_server_connection_terminate(sconn, nt_errstr(status));
2668 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2669 req->current_idx, req->in.vector_count));
2671 status = smbd_smb2_request_validate(req);
2672 if (!NT_STATUS_IS_OK(status)) {
2673 smbd_server_connection_terminate(sconn, nt_errstr(status));
2677 status = smbd_smb2_request_setup_out(req);
2678 if (!NT_STATUS_IS_OK(status)) {
2679 smbd_server_connection_terminate(sconn, nt_errstr(status));
2683 status = smbd_smb2_request_dispatch(req);
2684 if (!NT_STATUS_IS_OK(status)) {
2685 smbd_server_connection_terminate(sconn, nt_errstr(status));
2689 status = smbd_smb2_request_next_incoming(sconn);
2690 if (!NT_STATUS_IS_OK(status)) {
2691 smbd_server_connection_terminate(sconn, nt_errstr(status));
2695 sconn->num_requests++;
2697 /* The timeout_processing function isn't run nearly
2698 often enough to implement 'max log size' without
2699 overrunning the size of the file by many megabytes.
2700 This is especially true if we are running at debug
2701 level 10. Checking every 50 SMB2s is a nice
2702 tradeoff of performance vs log file size overrun. */
2704 if ((sconn->num_requests % 50) == 0 &&
2705 need_to_check_log_size()) {
2706 change_to_root_user();