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 uint8_t *body = NULL;
298 struct iovec *iov_tmp;
301 * We need the header plus the body length field
304 if (len < SMB2_HDR_BODY + 2) {
305 DEBUG(10, ("%d bytes left, expected at least %d\n",
306 (int)len, SMB2_HDR_BODY));
309 if (IVAL(hdr, 0) != SMB2_MAGIC) {
310 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
314 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
315 DEBUG(10, ("Got HDR len %d, expected %d\n",
316 SVAL(hdr, 4), SMB2_HDR_BODY));
321 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
322 body_size = SVAL(hdr, SMB2_HDR_BODY);
324 if (next_command_ofs != 0) {
325 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
328 if (next_command_ofs > full_size) {
331 full_size = next_command_ofs;
338 if (body_size > (full_size - SMB2_HDR_BODY)) {
340 * let the caller handle the error
342 body_size = full_size - SMB2_HDR_BODY;
344 body = hdr + SMB2_HDR_BODY;
345 dyn = body + body_size;
346 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
348 iov_tmp = talloc_realloc(mem_ctx, iov, struct iovec,
349 num_iov + SMBD_SMB2_NUM_IOV_PER_REQ);
350 if (iov_tmp == NULL) {
352 return NT_STATUS_NO_MEMORY;
356 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
358 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
359 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
360 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
361 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
362 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
363 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
374 return NT_STATUS_INVALID_PARAMETER;
377 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
378 uint8_t *inbuf, size_t size,
379 struct smbd_smb2_request **_req)
381 struct smbd_smb2_request *req;
382 uint32_t protocol_version;
383 const uint8_t *inhdr = NULL;
385 uint32_t next_command_ofs;
389 if (size < (4 + SMB2_HDR_BODY + 2)) {
390 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
391 return NT_STATUS_INVALID_PARAMETER;
396 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
397 if (protocol_version != SMB2_MAGIC) {
398 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
400 return NT_STATUS_INVALID_PARAMETER;
403 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
404 if (cmd != SMB2_OP_NEGPROT) {
405 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
407 return NT_STATUS_INVALID_PARAMETER;
410 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
411 if (next_command_ofs != 0) {
412 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
414 return NT_STATUS_INVALID_PARAMETER;
417 req = smbd_smb2_request_allocate(sconn);
419 return NT_STATUS_NO_MEMORY;
423 talloc_steal(req, inbuf);
425 req->request_time = timeval_current();
426 now = timeval_to_nttime(&req->request_time);
428 status = smbd_smb2_inbuf_parse_compound(sconn->conn,
430 inbuf + NBT_HDR_SIZE,
432 req, &req->in.vector,
433 &req->in.vector_count);
434 if (!NT_STATUS_IS_OK(status)) {
439 req->current_idx = 1;
445 static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
446 uint64_t message_id, uint64_t seq_id)
448 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
451 if (seq_id < sconn->smb2.seqnum_low) {
452 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
453 "%llu (sequence id %llu) "
454 "(granted = %u, low = %llu, range = %u)\n",
455 (unsigned long long)message_id,
456 (unsigned long long)seq_id,
457 (unsigned int)sconn->smb2.credits_granted,
458 (unsigned long long)sconn->smb2.seqnum_low,
459 (unsigned int)sconn->smb2.seqnum_range));
463 if (seq_id >= sconn->smb2.seqnum_low + sconn->smb2.seqnum_range) {
464 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
465 "%llu (sequence id %llu) "
466 "(granted = %u, low = %llu, range = %u)\n",
467 (unsigned long long)message_id,
468 (unsigned long long)seq_id,
469 (unsigned int)sconn->smb2.credits_granted,
470 (unsigned long long)sconn->smb2.seqnum_low,
471 (unsigned int)sconn->smb2.seqnum_range));
475 offset = seq_id % sconn->smb2.max_credits;
477 if (bitmap_query(credits_bm, offset)) {
478 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
479 "%llu (sequence id %llu) "
480 "(granted = %u, low = %llu, range = %u) "
482 (unsigned long long)message_id,
483 (unsigned long long)seq_id,
484 (unsigned int)sconn->smb2.credits_granted,
485 (unsigned long long)sconn->smb2.seqnum_low,
486 (unsigned int)sconn->smb2.seqnum_range,
491 /* Mark the message_ids as seen in the bitmap. */
492 bitmap_set(credits_bm, offset);
494 if (seq_id != sconn->smb2.seqnum_low) {
499 * Move the window forward by all the message_id's
502 while (bitmap_query(credits_bm, offset)) {
503 DEBUG(10,("smb2_validate_sequence_number: clearing "
504 "id %llu (position %u) from bitmap\n",
505 (unsigned long long)(sconn->smb2.seqnum_low),
507 bitmap_clear(credits_bm, offset);
509 sconn->smb2.seqnum_low += 1;
510 sconn->smb2.seqnum_range -= 1;
511 offset = sconn->smb2.seqnum_low % sconn->smb2.max_credits;
517 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
518 const uint8_t *inhdr)
520 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
521 uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
522 uint16_t credit_charge = 1;
525 if (opcode == SMB2_OP_CANCEL) {
526 /* SMB2_CANCEL requests by definition resend messageids. */
530 if (sconn->smb2.supports_multicredit) {
531 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
532 credit_charge = MAX(credit_charge, 1);
535 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
536 "credits_granted %llu, "
537 "seqnum low/range: %llu/%llu\n",
538 (unsigned long long) message_id,
539 (unsigned long long) credit_charge,
540 (unsigned long long) sconn->smb2.credits_granted,
541 (unsigned long long) sconn->smb2.seqnum_low,
542 (unsigned long long) sconn->smb2.seqnum_range));
544 if (sconn->smb2.credits_granted < credit_charge) {
545 DEBUG(0, ("smb2_validate_message_id: client used more "
546 "credits than granted, mid %llu, charge %llu, "
547 "credits_granted %llu, "
548 "seqnum low/range: %llu/%llu\n",
549 (unsigned long long) message_id,
550 (unsigned long long) credit_charge,
551 (unsigned long long) sconn->smb2.credits_granted,
552 (unsigned long long) sconn->smb2.seqnum_low,
553 (unsigned long long) sconn->smb2.seqnum_range));
558 * now check the message ids
560 * for multi-credit requests we need to check all current mid plus
561 * the implicit mids caused by the credit charge
562 * e.g. current mid = 15, charge 5 => mark 15-19 as used
565 for (i = 0; i <= (credit_charge-1); i++) {
566 uint64_t id = message_id + i;
569 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
570 (unsigned long long)message_id,
572 (unsigned long long)id));
574 ok = smb2_validate_sequence_number(sconn, message_id, id);
580 /* substract used credits */
581 sconn->smb2.credits_granted -= credit_charge;
586 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
591 count = req->in.vector_count;
593 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
594 /* It's not a SMB2 request */
595 return NT_STATUS_INVALID_PARAMETER;
598 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
599 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
600 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
601 const uint8_t *inhdr = NULL;
604 if (hdr->iov_len != SMB2_HDR_BODY) {
605 return NT_STATUS_INVALID_PARAMETER;
608 if (body->iov_len < 2) {
609 return NT_STATUS_INVALID_PARAMETER;
612 inhdr = (const uint8_t *)hdr->iov_base;
614 /* Check the SMB2 header */
615 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
616 return NT_STATUS_INVALID_PARAMETER;
619 if (!smb2_validate_message_id(req->sconn, inhdr)) {
620 return NT_STATUS_INVALID_PARAMETER;
623 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
626 * the 1st request should never have the
627 * SMB2_HDR_FLAG_CHAINED flag set
629 if (flags & SMB2_HDR_FLAG_CHAINED) {
630 req->next_status = NT_STATUS_INVALID_PARAMETER;
633 } else if (idx == 4) {
635 * the 2nd request triggers related vs. unrelated
636 * compounded requests
638 if (flags & SMB2_HDR_FLAG_CHAINED) {
639 req->compound_related = true;
641 } else if (idx > 4) {
644 * It seems the this tests are wrong
645 * see the SMB2-COMPOUND test
649 * all other requests should match the 2nd one
651 if (flags & SMB2_HDR_FLAG_CHAINED) {
652 if (!req->compound_related) {
654 NT_STATUS_INVALID_PARAMETER;
658 if (req->compound_related) {
660 NT_STATUS_INVALID_PARAMETER;
671 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
672 const struct iovec *in_vector,
673 struct iovec *out_vector)
675 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
676 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
677 uint16_t credit_charge = 1;
678 uint16_t credits_requested;
682 uint16_t credits_granted = 0;
683 uint64_t credits_possible;
684 uint16_t current_max_credits;
687 * first we grant only 1/16th of the max range.
689 * Windows also starts with the 1/16th and then grants
690 * more later. I was only able to trigger higher
691 * values, when using a verify high credit charge.
693 * TODO: scale up depending one load, free memory
695 * Maybe also on the relationship between number
696 * of requests and the used sequence number.
697 * Which means we would grant more credits
698 * for client which use multi credit requests.
700 current_max_credits = sconn->smb2.max_credits / 16;
701 current_max_credits = MAX(current_max_credits, 1);
703 if (sconn->smb2.supports_multicredit) {
704 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
705 credit_charge = MAX(credit_charge, 1);
708 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
709 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
710 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
711 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
713 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
714 SMB_ASSERT(sconn->smb2.max_credits >= credit_charge);
716 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
718 * In case we already send an async interim
719 * response, we should not grant
720 * credits on the final response.
723 } else if (credits_requested > 0) {
724 uint16_t additional_max = 0;
725 uint16_t additional_credits = credits_requested - 1;
728 case SMB2_OP_NEGPROT:
730 case SMB2_OP_SESSSETUP:
732 * Windows 2012 RC1 starts to grant
734 * with a successful session setup
736 if (NT_STATUS_IS_OK(out_status)) {
742 * We match windows and only grant additional credits
749 additional_credits = MIN(additional_credits, additional_max);
751 credits_granted = credit_charge + additional_credits;
752 } else if (sconn->smb2.credits_granted == 0) {
754 * Make sure the client has always at least one credit
760 * sequence numbers should not wrap
762 * 1. calculate the possible credits until
763 * the sequence numbers start to wrap on 64-bit.
765 * 2. UINT64_MAX is used for Break Notifications.
767 * 2. truncate the possible credits to the maximum
768 * credits we want to grant to the client in total.
770 * 3. remove the range we'll already granted to the client
771 * this makes sure the client consumes the lowest sequence
772 * number, before we can grant additional credits.
774 credits_possible = UINT64_MAX - sconn->smb2.seqnum_low;
775 if (credits_possible > 0) {
776 /* remove UINT64_MAX */
777 credits_possible -= 1;
779 credits_possible = MIN(credits_possible, current_max_credits);
780 credits_possible -= sconn->smb2.seqnum_range;
782 credits_granted = MIN(credits_granted, credits_possible);
784 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
785 sconn->smb2.credits_granted += credits_granted;
786 sconn->smb2.seqnum_range += credits_granted;
788 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
789 "granted %u, current possible/max %u/%u, "
790 "total granted/max/low/range %u/%u/%llu/%u\n",
791 (unsigned int)credits_requested,
792 (unsigned int)credit_charge,
793 (unsigned int)credits_granted,
794 (unsigned int)credits_possible,
795 (unsigned int)current_max_credits,
796 (unsigned int)sconn->smb2.credits_granted,
797 (unsigned int)sconn->smb2.max_credits,
798 (unsigned long long)sconn->smb2.seqnum_low,
799 (unsigned int)sconn->smb2.seqnum_range));
802 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
803 struct smbd_smb2_request *outreq)
806 uint16_t total_credits = 0;
808 count = outreq->out.vector_count;
810 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
811 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
812 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
813 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
815 smb2_set_operation_credit(outreq->sconn, inhdr_v, outhdr_v);
817 /* To match Windows, count up what we
819 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
820 /* Set to zero in all but the last reply. */
821 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
822 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
824 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
829 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
831 struct iovec *vector;
835 count = req->in.vector_count;
836 vector = talloc_zero_array(req, struct iovec, count);
837 if (vector == NULL) {
838 return NT_STATUS_NO_MEMORY;
841 vector[0].iov_base = req->out.nbt_hdr;
842 vector[0].iov_len = 4;
843 SIVAL(req->out.nbt_hdr, 0, 0);
845 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
846 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
847 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
848 uint8_t *outhdr = NULL;
849 uint8_t *outbody = NULL;
850 uint32_t next_command_ofs = 0;
851 struct iovec *current = &vector[idx];
853 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
854 /* we have a next command -
855 * setup for the error case. */
856 next_command_ofs = SMB2_HDR_BODY + 9;
859 outhdr = talloc_zero_array(vector, uint8_t,
861 if (outhdr == NULL) {
862 return NT_STATUS_NO_MEMORY;
865 outbody = outhdr + SMB2_HDR_BODY;
867 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
868 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
870 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
871 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
873 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
874 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
876 /* setup the SMB2 header */
877 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
878 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
879 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
880 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
881 SIVAL(outhdr, SMB2_HDR_STATUS,
882 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
883 SSVAL(outhdr, SMB2_HDR_OPCODE,
884 SVAL(inhdr, SMB2_HDR_OPCODE));
885 SIVAL(outhdr, SMB2_HDR_FLAGS,
886 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
887 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
888 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
889 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
890 SIVAL(outhdr, SMB2_HDR_PID,
891 IVAL(inhdr, SMB2_HDR_PID));
892 SIVAL(outhdr, SMB2_HDR_TID,
893 IVAL(inhdr, SMB2_HDR_TID));
894 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
895 BVAL(inhdr, SMB2_HDR_SESSION_ID));
896 memcpy(outhdr + SMB2_HDR_SIGNATURE,
897 inhdr + SMB2_HDR_SIGNATURE, 16);
899 /* setup error body header */
900 SSVAL(outbody, 0x00, 0x08 + 1);
901 SSVAL(outbody, 0x02, 0);
902 SIVAL(outbody, 0x04, 0);
905 req->out.vector = vector;
906 req->out.vector_count = count;
908 /* setup the length of the NBT packet */
909 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
911 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
916 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
918 const char *location)
920 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
922 exit_server_cleanly(reason);
925 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
926 struct iovec *outvec,
927 const struct iovec *srcvec)
929 /* vec[0] is always boilerplate and must
930 * be allocated with size OUTVEC_ALLOC_SIZE. */
932 outvec[0].iov_base = talloc_memdup(ctx,
935 if (!outvec[0].iov_base) {
938 outvec[0].iov_len = SMB2_HDR_BODY;
941 * If this is a "standard" vec[1] of length 8,
942 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
943 * then duplicate this. Else use talloc_memdup().
946 if (srcvec[1].iov_len == 8 &&
947 srcvec[1].iov_base ==
948 ((uint8_t *)srcvec[0].iov_base) +
950 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
952 outvec[1].iov_len = 8;
954 outvec[1].iov_base = talloc_memdup(ctx,
957 if (!outvec[1].iov_base) {
960 outvec[1].iov_len = srcvec[1].iov_len;
964 * If this is a "standard" vec[2] of length 1,
965 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
966 * then duplicate this. Else use talloc_memdup().
969 if (srcvec[2].iov_base &&
971 if (srcvec[2].iov_base ==
972 ((uint8_t *)srcvec[0].iov_base) +
973 (OUTVEC_ALLOC_SIZE - 1) &&
974 srcvec[2].iov_len == 1) {
975 /* Common SMB2 error packet case. */
976 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
977 (OUTVEC_ALLOC_SIZE - 1);
979 outvec[2].iov_base = talloc_memdup(ctx,
982 if (!outvec[2].iov_base) {
986 outvec[2].iov_len = srcvec[2].iov_len;
988 outvec[2].iov_base = NULL;
989 outvec[2].iov_len = 0;
994 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
996 struct smbd_smb2_request *newreq = NULL;
997 struct iovec *outvec = NULL;
998 int count = req->out.vector_count;
1001 newreq = smbd_smb2_request_allocate(req->sconn);
1006 newreq->sconn = req->sconn;
1007 newreq->session = req->session;
1008 newreq->do_signing = req->do_signing;
1009 newreq->current_idx = req->current_idx;
1011 outvec = talloc_zero_array(newreq, struct iovec, count);
1013 TALLOC_FREE(newreq);
1016 newreq->out.vector = outvec;
1017 newreq->out.vector_count = count;
1019 /* Setup the outvec's identically to req. */
1020 outvec[0].iov_base = newreq->out.nbt_hdr;
1021 outvec[0].iov_len = 4;
1022 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1024 /* Setup the vectors identically to the ones in req. */
1025 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1026 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
1033 TALLOC_FREE(newreq);
1037 smb2_setup_nbt_length(newreq->out.vector,
1038 newreq->out.vector_count);
1043 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
1045 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1048 uint8_t *outhdr = NULL;
1049 struct smbd_smb2_request *nreq = NULL;
1051 /* Create a new smb2 request we'll use
1052 for the interim return. */
1053 nreq = dup_smb2_req(req);
1055 return NT_STATUS_NO_MEMORY;
1058 /* Lose the last X out vectors. They're the
1059 ones we'll be using for the async reply. */
1060 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1062 smb2_setup_nbt_length(nreq->out.vector,
1063 nreq->out.vector_count);
1065 /* Step back to the previous reply. */
1066 i = nreq->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
1067 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
1068 /* And end the chain. */
1069 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1071 /* Calculate outgoing credits */
1072 smb2_calculate_credits(req, nreq);
1074 /* Re-sign if needed. */
1075 if (nreq->do_signing) {
1077 struct smbXsrv_session *x = nreq->session;
1078 struct smbXsrv_connection *conn = x->connection;
1079 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1081 status = smb2_signing_sign_pdu(signing_key,
1083 &nreq->out.vector[i],
1084 SMBD_SMB2_NUM_IOV_PER_REQ);
1085 if (!NT_STATUS_IS_OK(status)) {
1089 if (DEBUGLEVEL >= 10) {
1090 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1091 (unsigned int)nreq->current_idx );
1092 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1093 (unsigned int)nreq->out.vector_count );
1094 print_req_vectors(nreq);
1096 nreq->subreq = tstream_writev_queue_send(nreq,
1097 nreq->sconn->ev_ctx,
1098 nreq->sconn->smb2.stream,
1099 nreq->sconn->smb2.send_queue,
1101 nreq->out.vector_count);
1103 if (nreq->subreq == NULL) {
1104 return NT_STATUS_NO_MEMORY;
1107 tevent_req_set_callback(nreq->subreq,
1108 smbd_smb2_request_writev_done,
1111 return NT_STATUS_OK;
1114 struct smbd_smb2_request_pending_state {
1115 struct smbd_server_connection *sconn;
1116 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
1117 struct iovec vector[3];
1120 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
1122 struct smbd_smb2_request_pending_state *state =
1123 tevent_req_callback_data(subreq,
1124 struct smbd_smb2_request_pending_state);
1125 struct smbd_server_connection *sconn = state->sconn;
1129 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1130 TALLOC_FREE(subreq);
1132 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1133 smbd_server_connection_terminate(sconn, nt_errstr(status));
1140 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1141 struct tevent_timer *te,
1142 struct timeval current_time,
1143 void *private_data);
1145 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1146 struct tevent_req *subreq,
1147 uint32_t defer_time)
1150 int i = req->current_idx;
1151 struct timeval defer_endtime;
1152 uint8_t *outhdr = NULL;
1155 if (!tevent_req_is_in_progress(subreq)) {
1156 return NT_STATUS_OK;
1159 req->subreq = subreq;
1162 if (req->async_te) {
1163 /* We're already async. */
1164 return NT_STATUS_OK;
1167 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1168 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1169 if (flags & SMB2_HDR_FLAG_ASYNC) {
1170 /* We're already async. */
1171 return NT_STATUS_OK;
1174 if (req->in.vector_count > i + SMBD_SMB2_NUM_IOV_PER_REQ) {
1176 * We're trying to go async in a compound
1177 * request chain. This is not allowed.
1178 * Cancel the outstanding request.
1180 tevent_req_cancel(req->subreq);
1181 return smbd_smb2_request_error(req,
1182 NT_STATUS_INSUFFICIENT_RESOURCES);
1185 if (DEBUGLEVEL >= 10) {
1186 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1187 (unsigned int)req->current_idx );
1188 print_req_vectors(req);
1191 if (req->out.vector_count > 4) {
1192 struct iovec *outvec = NULL;
1194 /* This is a compound reply. We
1195 * must do an interim response
1196 * followed by the async response
1199 status = smb2_send_async_interim_response(req);
1200 if (!NT_STATUS_IS_OK(status)) {
1205 * We're splitting off the last SMB2
1206 * request in a compound set, and the
1207 * smb2_send_async_interim_response()
1208 * call above just sent all the replies
1209 * for the previous SMB2 requests in
1210 * this compound set. So we're no longer
1211 * in the "compound_related_in_progress"
1212 * state, and this is no longer a compound
1215 req->compound_related = false;
1216 req->sconn->smb2.compound_related_in_progress = false;
1218 /* Re-arrange the in.vectors. */
1219 req->in.vector[1] = req->in.vector[i];
1220 req->in.vector[2] = req->in.vector[i+1];
1221 req->in.vector[3] = req->in.vector[i+2];
1222 req->in.vector_count = 4;
1224 /* Reset the new in size. */
1225 smb2_setup_nbt_length(req->in.vector, 4);
1227 /* Now recreate the out.vectors. */
1228 outvec = talloc_zero_array(req, struct iovec, 4);
1230 return NT_STATUS_NO_MEMORY;
1233 /* 0 is always boilerplate and must
1234 * be of size 4 for the length field. */
1236 outvec[0].iov_base = req->out.nbt_hdr;
1237 outvec[0].iov_len = 4;
1238 SIVAL(req->out.nbt_hdr, 0, 0);
1240 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
1241 return NT_STATUS_NO_MEMORY;
1244 TALLOC_FREE(req->out.vector);
1246 req->out.vector = outvec;
1248 req->current_idx = 1;
1249 req->out.vector_count = 4;
1251 outhdr = (uint8_t *)req->out.vector[1].iov_base;
1252 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1253 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1256 defer_endtime = timeval_current_ofs_usec(defer_time);
1257 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1259 smbd_smb2_request_pending_timer,
1261 if (req->async_te == NULL) {
1262 return NT_STATUS_NO_MEMORY;
1265 return NT_STATUS_OK;
1268 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1269 struct tevent_timer *te,
1270 struct timeval current_time,
1273 struct smbd_smb2_request *req =
1274 talloc_get_type_abort(private_data,
1275 struct smbd_smb2_request);
1276 struct smbd_smb2_request_pending_state *state = NULL;
1277 uint8_t *outhdr = NULL;
1278 const uint8_t *inhdr = NULL;
1279 uint8_t *hdr = NULL;
1280 uint8_t *body = NULL;
1282 uint64_t message_id = 0;
1283 uint64_t async_id = 0;
1284 struct tevent_req *subreq = NULL;
1286 TALLOC_FREE(req->async_te);
1288 /* Ensure our final reply matches the interim one. */
1289 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1290 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1291 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1292 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1294 async_id = message_id; /* keep it simple for now... */
1296 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1297 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1299 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1301 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1302 (unsigned long long)async_id ));
1305 * What we send is identical to a smbd_smb2_request_error
1306 * packet with an error status of STATUS_PENDING. Make use
1307 * of this fact sometime when refactoring. JRA.
1310 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1311 if (state == NULL) {
1312 smbd_server_connection_terminate(req->sconn,
1313 nt_errstr(NT_STATUS_NO_MEMORY));
1316 state->sconn = req->sconn;
1318 state->vector[0].iov_base = (void *)state->buf;
1319 state->vector[0].iov_len = 4;
1321 state->vector[1].iov_base = state->buf + 4;
1322 state->vector[1].iov_len = SMB2_HDR_BODY;
1324 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
1325 state->vector[2].iov_len = 9;
1327 smb2_setup_nbt_length(state->vector, 3);
1329 hdr = (uint8_t *)state->vector[1].iov_base;
1330 body = (uint8_t *)state->vector[2].iov_base;
1332 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1333 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1334 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1335 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1336 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1338 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1339 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1340 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1341 SBVAL(hdr, SMB2_HDR_PID, async_id);
1342 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1343 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1344 memcpy(hdr+SMB2_HDR_SIGNATURE,
1345 outhdr+SMB2_HDR_SIGNATURE, 16);
1347 SSVAL(body, 0x00, 0x08 + 1);
1349 SCVAL(body, 0x02, 0);
1350 SCVAL(body, 0x03, 0);
1351 SIVAL(body, 0x04, 0);
1352 /* Match W2K8R2... */
1353 SCVAL(body, 0x08, 0x21);
1355 /* Ensure we correctly go through crediting. Grant
1356 the credits now, and zero credits on the final
1358 smb2_set_operation_credit(req->sconn,
1359 SMBD_SMB2_IN_HDR_IOV(req),
1362 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1364 if (req->do_signing) {
1366 struct smbXsrv_session *x = req->session;
1367 struct smbXsrv_connection *conn = x->connection;
1368 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1370 status = smb2_signing_sign_pdu(signing_key,
1372 &state->vector[1], 2);
1373 if (!NT_STATUS_IS_OK(status)) {
1374 smbd_server_connection_terminate(req->sconn,
1380 subreq = tstream_writev_queue_send(state,
1381 state->sconn->ev_ctx,
1382 state->sconn->smb2.stream,
1383 state->sconn->smb2.send_queue,
1386 if (subreq == NULL) {
1387 smbd_server_connection_terminate(state->sconn,
1388 nt_errstr(NT_STATUS_NO_MEMORY));
1391 tevent_req_set_callback(subreq,
1392 smbd_smb2_request_pending_writev_done,
1396 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1398 struct smbd_server_connection *sconn = req->sconn;
1399 struct smbd_smb2_request *cur;
1400 const uint8_t *inhdr;
1402 uint64_t search_message_id;
1403 uint64_t search_async_id;
1406 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1408 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1409 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1410 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1413 * we don't need the request anymore
1414 * cancel requests never have a response
1416 DLIST_REMOVE(req->sconn->smb2.requests, req);
1419 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1420 const uint8_t *outhdr;
1421 uint64_t message_id;
1424 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1426 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1427 async_id = BVAL(outhdr, SMB2_HDR_PID);
1429 if (flags & SMB2_HDR_FLAG_ASYNC) {
1430 if (search_async_id == async_id) {
1431 found_id = async_id;
1435 if (search_message_id == message_id) {
1436 found_id = message_id;
1442 if (cur && cur->subreq) {
1443 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1444 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1445 "cancel opcode[%s] mid %llu\n",
1446 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1447 (unsigned long long)found_id ));
1448 tevent_req_cancel(cur->subreq);
1451 return NT_STATUS_OK;
1454 /*************************************************************
1455 Ensure an incoming tid is a valid one for us to access.
1456 Change to the associated uid credentials and chdir to the
1457 valid tid directory.
1458 *************************************************************/
1460 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1462 const uint8_t *inhdr;
1465 struct smbXsrv_tcon *tcon;
1467 NTTIME now = timeval_to_nttime(&req->request_time);
1471 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1473 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1474 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1476 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1477 in_tid = req->last_tid;
1480 status = smb2srv_tcon_lookup(req->session,
1481 in_tid, now, &tcon);
1482 if (!NT_STATUS_IS_OK(status)) {
1486 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1487 return NT_STATUS_ACCESS_DENIED;
1490 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1491 if (!set_current_service(tcon->compat, 0, true)) {
1492 return NT_STATUS_ACCESS_DENIED;
1496 req->last_tid = in_tid;
1498 return NT_STATUS_OK;
1501 /*************************************************************
1502 Ensure an incoming session_id is a valid one for us to access.
1503 *************************************************************/
1505 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1507 const uint8_t *inhdr;
1510 uint64_t in_session_id;
1511 struct smbXsrv_session *session = NULL;
1512 struct auth_session_info *session_info;
1514 NTTIME now = timeval_to_nttime(&req->request_time);
1516 req->session = NULL;
1519 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1521 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1522 in_opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1523 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1525 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1526 in_session_id = req->last_session_id;
1529 /* lookup an existing session */
1530 status = smb2srv_session_lookup(req->sconn->conn,
1534 req->session = session;
1535 req->last_session_id = in_session_id;
1537 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1538 switch (in_opcode) {
1539 case SMB2_OP_SESSSETUP:
1540 status = NT_STATUS_OK;
1546 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1547 switch (in_opcode) {
1549 case SMB2_OP_CREATE:
1550 case SMB2_OP_GETINFO:
1551 case SMB2_OP_SETINFO:
1552 return NT_STATUS_INVALID_HANDLE;
1555 * Notice the check for
1556 * (session_info == NULL)
1559 status = NT_STATUS_OK;
1563 if (!NT_STATUS_IS_OK(status)) {
1567 session_info = session->global->auth_session_info;
1568 if (session_info == NULL) {
1569 return NT_STATUS_INVALID_HANDLE;
1572 set_current_user_info(session_info->unix_info->sanitized_username,
1573 session_info->unix_info->unix_name,
1574 session_info->info->domain_name);
1576 return NT_STATUS_OK;
1579 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1580 uint32_t data_length)
1582 uint16_t needed_charge;
1583 uint16_t credit_charge = 1;
1584 const uint8_t *inhdr;
1586 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1588 if (req->sconn->smb2.supports_multicredit) {
1589 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1590 credit_charge = MAX(credit_charge, 1);
1593 needed_charge = (data_length - 1)/ 65536 + 1;
1595 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1596 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1597 credit_charge, needed_charge));
1599 if (needed_charge > credit_charge) {
1600 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1601 credit_charge, needed_charge));
1602 return NT_STATUS_INVALID_PARAMETER;
1605 return NT_STATUS_OK;
1608 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1609 size_t expected_body_size)
1611 const uint8_t *inhdr;
1613 const uint8_t *inbody;
1614 int i = req->current_idx;
1616 size_t min_dyn_size = expected_body_size & 0x00000001;
1619 * The following should be checked already.
1621 if ((i+2) > req->in.vector_count) {
1622 return NT_STATUS_INTERNAL_ERROR;
1624 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1625 return NT_STATUS_INTERNAL_ERROR;
1627 if (req->in.vector[i+1].iov_len < 2) {
1628 return NT_STATUS_INTERNAL_ERROR;
1631 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1632 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1636 case SMB2_OP_GETINFO:
1642 * Now check the expected body size,
1643 * where the last byte might be in the
1646 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1647 return NT_STATUS_INVALID_PARAMETER;
1649 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1650 return NT_STATUS_INVALID_PARAMETER;
1653 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1655 body_size = SVAL(inbody, 0x00);
1656 if (body_size != expected_body_size) {
1657 return NT_STATUS_INVALID_PARAMETER;
1660 return NT_STATUS_OK;
1663 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1665 struct smbXsrv_connection *conn = req->sconn->conn;
1666 const struct smbd_smb2_dispatch_table *call = NULL;
1667 const uint8_t *inhdr;
1672 NTSTATUS session_status;
1673 uint32_t allowed_flags;
1674 NTSTATUS return_value;
1675 struct smbXsrv_session *x = NULL;
1676 bool signing_required = false;
1678 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1680 /* TODO: verify more things */
1682 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1683 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1684 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1685 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1686 smb2_opcode_name(opcode),
1687 (unsigned long long)mid));
1689 if (conn->protocol >= PROTOCOL_SMB2_02) {
1691 * once the protocol is negotiated
1692 * SMB2_OP_NEGPROT is not allowed anymore
1694 if (opcode == SMB2_OP_NEGPROT) {
1695 /* drop the connection */
1696 return NT_STATUS_INVALID_PARAMETER;
1700 * if the protocol is not negotiated yet
1701 * only SMB2_OP_NEGPROT is allowed.
1703 if (opcode != SMB2_OP_NEGPROT) {
1704 /* drop the connection */
1705 return NT_STATUS_INVALID_PARAMETER;
1709 call = smbd_smb2_call(opcode);
1711 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1714 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1715 SMB2_HDR_FLAG_SIGNED |
1717 if (opcode == SMB2_OP_CANCEL) {
1718 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1720 if ((flags & ~allowed_flags) != 0) {
1721 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1725 * Check if the client provided a valid session id,
1726 * if so smbd_smb2_request_check_session() calls
1727 * set_current_user_info().
1729 * As some command don't require a valid session id
1730 * we defer the check of the session_status
1732 session_status = smbd_smb2_request_check_session(req);
1736 signing_required = x->global->signing_required;
1738 if (opcode == SMB2_OP_SESSSETUP &&
1739 x->global->channels[0].signing_key.length) {
1740 signing_required = true;
1744 req->do_signing = false;
1745 if (flags & SMB2_HDR_FLAG_SIGNED) {
1746 DATA_BLOB signing_key;
1749 return smbd_smb2_request_error(
1750 req, NT_STATUS_ACCESS_DENIED);
1753 signing_key = x->global->channels[0].signing_key;
1755 if (!NT_STATUS_IS_OK(session_status)) {
1756 return smbd_smb2_request_error(req, session_status);
1759 req->do_signing = true;
1760 status = smb2_signing_check_pdu(signing_key,
1762 SMBD_SMB2_IN_HDR_IOV(req),
1763 SMBD_SMB2_NUM_IOV_PER_REQ);
1764 if (!NT_STATUS_IS_OK(status)) {
1765 return smbd_smb2_request_error(req, status);
1767 } else if (opcode == SMB2_OP_CANCEL) {
1768 /* Cancel requests are allowed to skip the signing */
1769 } else if (signing_required) {
1770 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1773 if (flags & SMB2_HDR_FLAG_CHAINED) {
1775 * This check is mostly for giving the correct error code
1776 * for compounded requests.
1778 * TODO: we may need to move this after the session
1781 if (!NT_STATUS_IS_OK(req->next_status)) {
1782 return smbd_smb2_request_error(req, req->next_status);
1785 req->compat_chain_fsp = NULL;
1788 if (req->compound_related) {
1789 req->sconn->smb2.compound_related_in_progress = true;
1792 if (call->need_session) {
1793 if (!NT_STATUS_IS_OK(session_status)) {
1794 return smbd_smb2_request_error(req, session_status);
1798 if (call->need_tcon) {
1799 SMB_ASSERT(call->need_session);
1802 * This call needs to be run as user.
1804 * smbd_smb2_request_check_tcon()
1805 * calls change_to_user() on success.
1807 status = smbd_smb2_request_check_tcon(req);
1808 if (!NT_STATUS_IS_OK(status)) {
1809 return smbd_smb2_request_error(req, status);
1813 if (call->as_root) {
1814 /* This call needs to be run as root */
1815 change_to_root_user();
1817 SMB_ASSERT(call->need_tcon);
1821 case SMB2_OP_NEGPROT:
1823 START_PROFILE(smb2_negprot);
1824 return_value = smbd_smb2_request_process_negprot(req);
1825 END_PROFILE(smb2_negprot);
1829 case SMB2_OP_SESSSETUP:
1831 START_PROFILE(smb2_sesssetup);
1832 return_value = smbd_smb2_request_process_sesssetup(req);
1833 END_PROFILE(smb2_sesssetup);
1837 case SMB2_OP_LOGOFF:
1839 START_PROFILE(smb2_logoff);
1840 return_value = smbd_smb2_request_process_logoff(req);
1841 END_PROFILE(smb2_logoff);
1847 START_PROFILE(smb2_tcon);
1848 return_value = smbd_smb2_request_process_tcon(req);
1849 END_PROFILE(smb2_tcon);
1855 START_PROFILE(smb2_tdis);
1856 return_value = smbd_smb2_request_process_tdis(req);
1857 END_PROFILE(smb2_tdis);
1861 case SMB2_OP_CREATE:
1863 START_PROFILE(smb2_create);
1864 return_value = smbd_smb2_request_process_create(req);
1865 END_PROFILE(smb2_create);
1871 START_PROFILE(smb2_close);
1872 return_value = smbd_smb2_request_process_close(req);
1873 END_PROFILE(smb2_close);
1879 START_PROFILE(smb2_flush);
1880 return_value = smbd_smb2_request_process_flush(req);
1881 END_PROFILE(smb2_flush);
1887 START_PROFILE(smb2_read);
1888 return_value = smbd_smb2_request_process_read(req);
1889 END_PROFILE(smb2_read);
1895 START_PROFILE(smb2_write);
1896 return_value = smbd_smb2_request_process_write(req);
1897 END_PROFILE(smb2_write);
1903 START_PROFILE(smb2_lock);
1904 return_value = smbd_smb2_request_process_lock(req);
1905 END_PROFILE(smb2_lock);
1911 START_PROFILE(smb2_ioctl);
1912 return_value = smbd_smb2_request_process_ioctl(req);
1913 END_PROFILE(smb2_ioctl);
1917 case SMB2_OP_CANCEL:
1919 START_PROFILE(smb2_cancel);
1920 return_value = smbd_smb2_request_process_cancel(req);
1921 END_PROFILE(smb2_cancel);
1925 case SMB2_OP_KEEPALIVE:
1927 START_PROFILE(smb2_keepalive);
1928 return_value = smbd_smb2_request_process_keepalive(req);
1929 END_PROFILE(smb2_keepalive);
1935 START_PROFILE(smb2_find);
1936 return_value = smbd_smb2_request_process_find(req);
1937 END_PROFILE(smb2_find);
1941 case SMB2_OP_NOTIFY:
1943 START_PROFILE(smb2_notify);
1944 return_value = smbd_smb2_request_process_notify(req);
1945 END_PROFILE(smb2_notify);
1949 case SMB2_OP_GETINFO:
1951 START_PROFILE(smb2_getinfo);
1952 return_value = smbd_smb2_request_process_getinfo(req);
1953 END_PROFILE(smb2_getinfo);
1957 case SMB2_OP_SETINFO:
1959 START_PROFILE(smb2_setinfo);
1960 return_value = smbd_smb2_request_process_setinfo(req);
1961 END_PROFILE(smb2_setinfo);
1967 START_PROFILE(smb2_break);
1968 return_value = smbd_smb2_request_process_break(req);
1969 END_PROFILE(smb2_break);
1974 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1977 return return_value;
1980 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1982 struct tevent_req *subreq;
1983 int i = req->current_idx;
1986 TALLOC_FREE(req->async_te);
1988 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
1990 if (req->current_idx < req->out.vector_count) {
1992 * We must process the remaining compound
1993 * SMB2 requests before any new incoming SMB2
1994 * requests. This is because incoming SMB2
1995 * requests may include a cancel for a
1996 * compound request we haven't processed
1999 struct tevent_immediate *im = tevent_create_immediate(req);
2001 return NT_STATUS_NO_MEMORY;
2003 tevent_schedule_immediate(im,
2005 smbd_smb2_request_dispatch_immediate,
2007 return NT_STATUS_OK;
2010 if (req->compound_related) {
2011 req->sconn->smb2.compound_related_in_progress = false;
2014 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2016 /* Set credit for these operations (zero credits if this
2017 is a final reply for an async operation). */
2018 smb2_calculate_credits(req, req);
2020 if (req->do_signing) {
2022 struct smbXsrv_session *x = req->session;
2023 struct smbXsrv_connection *conn = x->connection;
2024 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2026 status = smb2_signing_sign_pdu(signing_key,
2028 &req->out.vector[i],
2029 SMBD_SMB2_NUM_IOV_PER_REQ);
2030 if (!NT_STATUS_IS_OK(status)) {
2035 if (DEBUGLEVEL >= 10) {
2036 dbgtext("smbd_smb2_request_reply: sending...\n");
2037 print_req_vectors(req);
2040 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2041 if (req->out.vector_count == 4 &&
2042 req->out.vector[3].iov_base == NULL &&
2043 req->out.vector[3].iov_len != 0) {
2044 /* Dynamic part is NULL. Chop it off,
2045 We're going to send it via sendfile. */
2046 req->out.vector_count -= 1;
2049 subreq = tstream_writev_queue_send(req,
2051 req->sconn->smb2.stream,
2052 req->sconn->smb2.send_queue,
2054 req->out.vector_count);
2055 if (subreq == NULL) {
2056 return NT_STATUS_NO_MEMORY;
2058 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
2060 * We're done with this request -
2061 * move it off the "being processed" queue.
2063 DLIST_REMOVE(req->sconn->smb2.requests, req);
2065 return NT_STATUS_OK;
2068 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2070 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2071 struct tevent_immediate *im,
2074 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2075 struct smbd_smb2_request);
2076 struct smbd_server_connection *sconn = req->sconn;
2081 if (DEBUGLEVEL >= 10) {
2082 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2083 req->current_idx, req->in.vector_count));
2084 print_req_vectors(req);
2087 status = smbd_smb2_request_dispatch(req);
2088 if (!NT_STATUS_IS_OK(status)) {
2089 smbd_server_connection_terminate(sconn, nt_errstr(status));
2093 status = smbd_smb2_request_next_incoming(sconn);
2094 if (!NT_STATUS_IS_OK(status)) {
2095 smbd_server_connection_terminate(sconn, nt_errstr(status));
2100 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
2102 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
2103 struct smbd_smb2_request);
2104 struct smbd_server_connection *sconn = req->sconn;
2109 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2110 TALLOC_FREE(subreq);
2113 status = map_nt_error_from_unix(sys_errno);
2114 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2115 nt_errstr(status)));
2116 smbd_server_connection_terminate(sconn, nt_errstr(status));
2120 status = smbd_smb2_request_next_incoming(sconn);
2121 if (!NT_STATUS_IS_OK(status)) {
2122 smbd_server_connection_terminate(sconn, nt_errstr(status));
2127 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2129 DATA_BLOB body, DATA_BLOB *dyn,
2130 const char *location)
2133 int i = req->current_idx;
2134 uint32_t next_command_ofs;
2136 DEBUG(10,("smbd_smb2_request_done_ex: "
2137 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2138 i, nt_errstr(status), (unsigned int)body.length,
2140 (unsigned int)(dyn ? dyn->length : 0),
2143 if (body.length < 2) {
2144 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2147 if ((body.length % 2) != 0) {
2148 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2151 outhdr = (uint8_t *)req->out.vector[i].iov_base;
2153 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2154 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2156 req->out.vector[i+1].iov_base = (void *)body.data;
2157 req->out.vector[i+1].iov_len = body.length;
2160 req->out.vector[i+2].iov_base = (void *)dyn->data;
2161 req->out.vector[i+2].iov_len = dyn->length;
2163 req->out.vector[i+2].iov_base = NULL;
2164 req->out.vector[i+2].iov_len = 0;
2167 /* see if we need to recalculate the offset to the next response */
2168 if (next_command_ofs > 0) {
2169 next_command_ofs = SMB2_HDR_BODY;
2170 next_command_ofs += req->out.vector[i+1].iov_len;
2171 next_command_ofs += req->out.vector[i+2].iov_len;
2174 if ((next_command_ofs % 8) != 0) {
2175 size_t pad_size = 8 - (next_command_ofs % 8);
2176 if (req->out.vector[i+2].iov_len == 0) {
2178 * if the dyn buffer is empty
2179 * we can use it to add padding
2183 pad = talloc_zero_array(req->out.vector,
2186 return smbd_smb2_request_error(req,
2187 NT_STATUS_NO_MEMORY);
2190 req->out.vector[i+2].iov_base = (void *)pad;
2191 req->out.vector[i+2].iov_len = pad_size;
2194 * For now we copy the dynamic buffer
2195 * and add the padding to the new buffer
2202 old_size = req->out.vector[i+2].iov_len;
2203 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2205 new_size = old_size + pad_size;
2206 new_dyn = talloc_zero_array(req->out.vector,
2208 if (new_dyn == NULL) {
2209 return smbd_smb2_request_error(req,
2210 NT_STATUS_NO_MEMORY);
2213 memcpy(new_dyn, old_dyn, old_size);
2214 memset(new_dyn + old_size, 0, pad_size);
2216 req->out.vector[i+2].iov_base = (void *)new_dyn;
2217 req->out.vector[i+2].iov_len = new_size;
2219 next_command_ofs += pad_size;
2222 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2224 return smbd_smb2_request_reply(req);
2227 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2230 const char *location)
2233 int i = req->current_idx;
2234 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2236 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2237 i, nt_errstr(status), info ? " +info" : "",
2240 body.data = outhdr + SMB2_HDR_BODY;
2242 SSVAL(body.data, 0, 9);
2245 SIVAL(body.data, 0x04, info->length);
2247 /* Allocated size of req->out.vector[i].iov_base
2248 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2249 * 1 byte without having to do an alloc.
2251 info = talloc_zero_array(req->out.vector,
2255 return NT_STATUS_NO_MEMORY;
2257 info->data = ((uint8_t *)outhdr) +
2258 OUTVEC_ALLOC_SIZE - 1;
2260 SCVAL(info->data, 0, 0);
2264 * if a request fails, all other remaining
2265 * compounded requests should fail too
2267 req->next_status = NT_STATUS_INVALID_PARAMETER;
2269 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2273 struct smbd_smb2_send_oplock_break_state {
2274 struct smbd_server_connection *sconn;
2275 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2276 struct iovec vector;
2279 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2281 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2282 uint64_t file_id_persistent,
2283 uint64_t file_id_volatile,
2284 uint8_t oplock_level)
2286 struct smbd_smb2_send_oplock_break_state *state;
2287 struct tevent_req *subreq;
2291 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2292 if (state == NULL) {
2293 return NT_STATUS_NO_MEMORY;
2295 state->sconn = sconn;
2297 state->vector.iov_base = (void *)state->buf;
2298 state->vector.iov_len = sizeof(state->buf);
2300 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2301 hdr = state->buf + 4;
2302 body = hdr + SMB2_HDR_BODY;
2304 SIVAL(hdr, 0, SMB2_MAGIC);
2305 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2306 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2307 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2308 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2309 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2310 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2311 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2312 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2313 SIVAL(hdr, SMB2_HDR_PID, 0);
2314 SIVAL(hdr, SMB2_HDR_TID, 0);
2315 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2316 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2318 SSVAL(body, 0x00, 0x18);
2320 SCVAL(body, 0x02, oplock_level);
2321 SCVAL(body, 0x03, 0); /* reserved */
2322 SIVAL(body, 0x04, 0); /* reserved */
2323 SBVAL(body, 0x08, file_id_persistent);
2324 SBVAL(body, 0x10, file_id_volatile);
2326 subreq = tstream_writev_queue_send(state,
2329 sconn->smb2.send_queue,
2331 if (subreq == NULL) {
2332 return NT_STATUS_NO_MEMORY;
2334 tevent_req_set_callback(subreq,
2335 smbd_smb2_oplock_break_writev_done,
2338 return NT_STATUS_OK;
2341 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2343 struct smbd_smb2_send_oplock_break_state *state =
2344 tevent_req_callback_data(subreq,
2345 struct smbd_smb2_send_oplock_break_state);
2346 struct smbd_server_connection *sconn = state->sconn;
2350 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2351 TALLOC_FREE(subreq);
2353 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2354 smbd_server_connection_terminate(sconn, nt_errstr(status));
2361 struct smbd_smb2_request_read_state {
2362 struct tevent_context *ev;
2363 struct smbd_server_connection *sconn;
2364 struct smbd_smb2_request *smb2_req;
2366 uint8_t nbt[NBT_HDR_SIZE];
2373 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2375 TALLOC_CTX *mem_ctx,
2376 struct iovec **_vector,
2378 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2380 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2381 struct tevent_context *ev,
2382 struct smbd_server_connection *sconn)
2384 struct tevent_req *req;
2385 struct smbd_smb2_request_read_state *state;
2386 struct tevent_req *subreq;
2388 req = tevent_req_create(mem_ctx, &state,
2389 struct smbd_smb2_request_read_state);
2394 state->sconn = sconn;
2396 state->smb2_req = smbd_smb2_request_allocate(state);
2397 if (tevent_req_nomem(state->smb2_req, req)) {
2398 return tevent_req_post(req, ev);
2400 state->smb2_req->sconn = sconn;
2402 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
2404 state->sconn->smb2.stream,
2405 state->sconn->smb2.recv_queue,
2406 smbd_smb2_request_next_vector,
2408 if (tevent_req_nomem(subreq, req)) {
2409 return tevent_req_post(req, ev);
2411 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2416 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2418 TALLOC_CTX *mem_ctx,
2419 struct iovec **_vector,
2422 struct smbd_smb2_request_read_state *state =
2423 talloc_get_type_abort(private_data,
2424 struct smbd_smb2_request_read_state);
2425 struct iovec *vector;
2427 if (state->pktlen > 0) {
2428 /* if there're no remaining bytes, we're done */
2434 if (!state->hdr.done) {
2436 * first we need to get the NBT header
2438 vector = talloc_array(mem_ctx, struct iovec, 1);
2439 if (vector == NULL) {
2443 vector[0].iov_base = (void *)state->hdr.nbt;
2444 vector[0].iov_len = NBT_HDR_SIZE;
2449 state->hdr.done = true;
2454 * Now we analyze the NBT header
2456 state->pktlen = smb2_len(state->hdr.nbt);
2458 if (state->pktlen == 0) {
2459 /* if there're no remaining bytes, we're done */
2465 state->pktbuf = talloc_array(state->smb2_req, uint8_t, state->pktlen);
2466 if (state->pktbuf == NULL) {
2470 vector = talloc_array(mem_ctx, struct iovec, 1);
2471 if (vector == NULL) {
2475 vector[0].iov_base = (void *)state->pktbuf;
2476 vector[0].iov_len = state->pktlen;
2483 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2485 struct tevent_req *req =
2486 tevent_req_callback_data(subreq,
2488 struct smbd_smb2_request_read_state *state =
2489 tevent_req_data(req,
2490 struct smbd_smb2_request_read_state);
2496 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2497 TALLOC_FREE(subreq);
2499 status = map_nt_error_from_unix(sys_errno);
2500 tevent_req_nterror(req, status);
2504 if (state->hdr.nbt[0] != 0x00) {
2505 DEBUG(1,("smbd_smb2_request_read_done: ignore NBT[0x%02X] msg\n",
2506 state->hdr.nbt[0]));
2508 ZERO_STRUCT(state->hdr);
2509 TALLOC_FREE(state->pktbuf);
2512 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
2514 state->sconn->smb2.stream,
2515 state->sconn->smb2.recv_queue,
2516 smbd_smb2_request_next_vector,
2518 if (tevent_req_nomem(subreq, req)) {
2521 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2525 state->smb2_req->request_time = timeval_current();
2526 now = timeval_to_nttime(&state->smb2_req->request_time);
2528 status = smbd_smb2_inbuf_parse_compound(state->smb2_req->sconn->conn,
2533 &state->smb2_req->in.vector,
2534 &state->smb2_req->in.vector_count);
2535 if (tevent_req_nterror(req, status)) {
2539 state->smb2_req->current_idx = 1;
2541 tevent_req_done(req);
2544 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2545 TALLOC_CTX *mem_ctx,
2546 struct smbd_smb2_request **_smb2_req)
2548 struct smbd_smb2_request_read_state *state =
2549 tevent_req_data(req,
2550 struct smbd_smb2_request_read_state);
2553 if (tevent_req_is_nterror(req, &status)) {
2554 tevent_req_received(req);
2558 *_smb2_req = talloc_move(mem_ctx, &state->smb2_req);
2559 tevent_req_received(req);
2560 return NT_STATUS_OK;
2563 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2565 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2567 size_t max_send_queue_len;
2568 size_t cur_send_queue_len;
2569 struct tevent_req *subreq;
2571 if (sconn->smb2.compound_related_in_progress) {
2573 * Can't read another until the related
2576 return NT_STATUS_OK;
2579 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2581 * if there is already a smbd_smb2_request_read
2582 * pending, we are done.
2584 return NT_STATUS_OK;
2587 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2588 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2590 if (cur_send_queue_len > max_send_queue_len) {
2592 * if we have a lot of requests to send,
2593 * we wait until they are on the wire until we
2594 * ask for the next request.
2596 return NT_STATUS_OK;
2599 /* ask for the next request */
2600 subreq = smbd_smb2_request_read_send(sconn, sconn->ev_ctx, sconn);
2601 if (subreq == NULL) {
2602 return NT_STATUS_NO_MEMORY;
2604 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2606 return NT_STATUS_OK;
2609 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2610 uint8_t *inbuf, size_t size)
2613 struct smbd_smb2_request *req = NULL;
2615 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2616 (unsigned int)size));
2618 status = smbd_initialize_smb2(sconn);
2619 if (!NT_STATUS_IS_OK(status)) {
2620 smbd_server_connection_terminate(sconn, nt_errstr(status));
2624 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2625 if (!NT_STATUS_IS_OK(status)) {
2626 smbd_server_connection_terminate(sconn, nt_errstr(status));
2630 status = smbd_smb2_request_validate(req);
2631 if (!NT_STATUS_IS_OK(status)) {
2632 smbd_server_connection_terminate(sconn, nt_errstr(status));
2636 status = smbd_smb2_request_setup_out(req);
2637 if (!NT_STATUS_IS_OK(status)) {
2638 smbd_server_connection_terminate(sconn, nt_errstr(status));
2642 status = smbd_smb2_request_dispatch(req);
2643 if (!NT_STATUS_IS_OK(status)) {
2644 smbd_server_connection_terminate(sconn, nt_errstr(status));
2648 status = smbd_smb2_request_next_incoming(sconn);
2649 if (!NT_STATUS_IS_OK(status)) {
2650 smbd_server_connection_terminate(sconn, nt_errstr(status));
2654 sconn->num_requests++;
2657 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2659 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2660 struct smbd_server_connection);
2662 struct smbd_smb2_request *req = NULL;
2664 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2665 TALLOC_FREE(subreq);
2666 if (!NT_STATUS_IS_OK(status)) {
2667 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2668 nt_errstr(status)));
2669 smbd_server_connection_terminate(sconn, nt_errstr(status));
2673 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2674 req->current_idx, req->in.vector_count));
2676 status = smbd_smb2_request_validate(req);
2677 if (!NT_STATUS_IS_OK(status)) {
2678 smbd_server_connection_terminate(sconn, nt_errstr(status));
2682 status = smbd_smb2_request_setup_out(req);
2683 if (!NT_STATUS_IS_OK(status)) {
2684 smbd_server_connection_terminate(sconn, nt_errstr(status));
2688 status = smbd_smb2_request_dispatch(req);
2689 if (!NT_STATUS_IS_OK(status)) {
2690 smbd_server_connection_terminate(sconn, nt_errstr(status));
2694 status = smbd_smb2_request_next_incoming(sconn);
2695 if (!NT_STATUS_IS_OK(status)) {
2696 smbd_server_connection_terminate(sconn, nt_errstr(status));
2700 sconn->num_requests++;
2702 /* The timeout_processing function isn't run nearly
2703 often enough to implement 'max log size' without
2704 overrunning the size of the file by many megabytes.
2705 This is especially true if we are running at debug
2706 level 10. Checking every 50 SMB2s is a nice
2707 tradeoff of performance vs log file size overrun. */
2709 if ((sconn->num_requests % 50) == 0 &&
2710 need_to_check_log_size()) {
2711 change_to_root_user();