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 >= (2*SMBD_SMB2_NUM_IOV_PER_REQ)) {
1193 * This is a compound reply. We
1194 * must do an interim response
1195 * followed by the async response
1198 status = smb2_send_async_interim_response(req);
1199 if (!NT_STATUS_IS_OK(status)) {
1204 * We're splitting off the last SMB2
1205 * request in a compound set, and the
1206 * smb2_send_async_interim_response()
1207 * call above just sent all the replies
1208 * for the previous SMB2 requests in
1209 * this compound set. So we're no longer
1210 * in the "compound_related_in_progress"
1211 * state, and this is no longer a compound
1214 req->compound_related = false;
1215 req->sconn->smb2.compound_related_in_progress = false;
1217 req->current_idx = 1;
1219 /* Re-arrange the in.vectors. */
1220 memmove(&req->in.vector[req->current_idx],
1222 sizeof(req->in.vector[0])*SMBD_SMB2_NUM_IOV_PER_REQ);
1223 req->in.vector_count = req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ;
1225 /* Reset the new in size. */
1226 smb2_setup_nbt_length(req->in.vector, req->in.vector_count);
1228 /* Re-arrange the out.vectors. */
1229 memmove(&req->out.vector[req->current_idx],
1230 &req->out.vector[i],
1231 sizeof(req->out.vector[0])*SMBD_SMB2_NUM_IOV_PER_REQ);
1232 req->out.vector_count = req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ;
1234 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1235 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1236 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1239 defer_endtime = timeval_current_ofs_usec(defer_time);
1240 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1242 smbd_smb2_request_pending_timer,
1244 if (req->async_te == NULL) {
1245 return NT_STATUS_NO_MEMORY;
1248 return NT_STATUS_OK;
1251 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1252 struct tevent_timer *te,
1253 struct timeval current_time,
1256 struct smbd_smb2_request *req =
1257 talloc_get_type_abort(private_data,
1258 struct smbd_smb2_request);
1259 struct smbd_smb2_request_pending_state *state = NULL;
1260 uint8_t *outhdr = NULL;
1261 const uint8_t *inhdr = NULL;
1262 uint8_t *hdr = NULL;
1263 uint8_t *body = NULL;
1265 uint64_t message_id = 0;
1266 uint64_t async_id = 0;
1267 struct tevent_req *subreq = NULL;
1269 TALLOC_FREE(req->async_te);
1271 /* Ensure our final reply matches the interim one. */
1272 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1273 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1274 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1275 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1277 async_id = message_id; /* keep it simple for now... */
1279 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1280 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1282 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1284 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1285 (unsigned long long)async_id ));
1288 * What we send is identical to a smbd_smb2_request_error
1289 * packet with an error status of STATUS_PENDING. Make use
1290 * of this fact sometime when refactoring. JRA.
1293 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1294 if (state == NULL) {
1295 smbd_server_connection_terminate(req->sconn,
1296 nt_errstr(NT_STATUS_NO_MEMORY));
1299 state->sconn = req->sconn;
1301 state->vector[0].iov_base = (void *)state->buf;
1302 state->vector[0].iov_len = 4;
1304 state->vector[1].iov_base = state->buf + 4;
1305 state->vector[1].iov_len = SMB2_HDR_BODY;
1307 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
1308 state->vector[2].iov_len = 9;
1310 smb2_setup_nbt_length(state->vector, 3);
1312 hdr = (uint8_t *)state->vector[1].iov_base;
1313 body = (uint8_t *)state->vector[2].iov_base;
1315 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1316 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1317 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1318 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1319 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1321 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1322 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1323 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1324 SBVAL(hdr, SMB2_HDR_PID, async_id);
1325 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1326 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1327 memcpy(hdr+SMB2_HDR_SIGNATURE,
1328 outhdr+SMB2_HDR_SIGNATURE, 16);
1330 SSVAL(body, 0x00, 0x08 + 1);
1332 SCVAL(body, 0x02, 0);
1333 SCVAL(body, 0x03, 0);
1334 SIVAL(body, 0x04, 0);
1335 /* Match W2K8R2... */
1336 SCVAL(body, 0x08, 0x21);
1338 /* Ensure we correctly go through crediting. Grant
1339 the credits now, and zero credits on the final
1341 smb2_set_operation_credit(req->sconn,
1342 SMBD_SMB2_IN_HDR_IOV(req),
1345 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1347 if (req->do_signing) {
1349 struct smbXsrv_session *x = req->session;
1350 struct smbXsrv_connection *conn = x->connection;
1351 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1353 status = smb2_signing_sign_pdu(signing_key,
1355 &state->vector[1], 2);
1356 if (!NT_STATUS_IS_OK(status)) {
1357 smbd_server_connection_terminate(req->sconn,
1363 subreq = tstream_writev_queue_send(state,
1364 state->sconn->ev_ctx,
1365 state->sconn->smb2.stream,
1366 state->sconn->smb2.send_queue,
1369 if (subreq == NULL) {
1370 smbd_server_connection_terminate(state->sconn,
1371 nt_errstr(NT_STATUS_NO_MEMORY));
1374 tevent_req_set_callback(subreq,
1375 smbd_smb2_request_pending_writev_done,
1379 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1381 struct smbd_server_connection *sconn = req->sconn;
1382 struct smbd_smb2_request *cur;
1383 const uint8_t *inhdr;
1385 uint64_t search_message_id;
1386 uint64_t search_async_id;
1389 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1391 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1392 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1393 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1396 * we don't need the request anymore
1397 * cancel requests never have a response
1399 DLIST_REMOVE(req->sconn->smb2.requests, req);
1402 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1403 const uint8_t *outhdr;
1404 uint64_t message_id;
1407 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1409 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1410 async_id = BVAL(outhdr, SMB2_HDR_PID);
1412 if (flags & SMB2_HDR_FLAG_ASYNC) {
1413 if (search_async_id == async_id) {
1414 found_id = async_id;
1418 if (search_message_id == message_id) {
1419 found_id = message_id;
1425 if (cur && cur->subreq) {
1426 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1427 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1428 "cancel opcode[%s] mid %llu\n",
1429 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1430 (unsigned long long)found_id ));
1431 tevent_req_cancel(cur->subreq);
1434 return NT_STATUS_OK;
1437 /*************************************************************
1438 Ensure an incoming tid is a valid one for us to access.
1439 Change to the associated uid credentials and chdir to the
1440 valid tid directory.
1441 *************************************************************/
1443 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1445 const uint8_t *inhdr;
1448 struct smbXsrv_tcon *tcon;
1450 NTTIME now = timeval_to_nttime(&req->request_time);
1454 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1456 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1457 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1459 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1460 in_tid = req->last_tid;
1463 status = smb2srv_tcon_lookup(req->session,
1464 in_tid, now, &tcon);
1465 if (!NT_STATUS_IS_OK(status)) {
1469 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1470 return NT_STATUS_ACCESS_DENIED;
1473 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1474 if (!set_current_service(tcon->compat, 0, true)) {
1475 return NT_STATUS_ACCESS_DENIED;
1479 req->last_tid = in_tid;
1481 return NT_STATUS_OK;
1484 /*************************************************************
1485 Ensure an incoming session_id is a valid one for us to access.
1486 *************************************************************/
1488 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1490 const uint8_t *inhdr;
1493 uint64_t in_session_id;
1494 struct smbXsrv_session *session = NULL;
1495 struct auth_session_info *session_info;
1497 NTTIME now = timeval_to_nttime(&req->request_time);
1499 req->session = NULL;
1502 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1504 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1505 in_opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1506 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1508 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1509 in_session_id = req->last_session_id;
1512 /* lookup an existing session */
1513 status = smb2srv_session_lookup(req->sconn->conn,
1517 req->session = session;
1518 req->last_session_id = in_session_id;
1520 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1521 switch (in_opcode) {
1522 case SMB2_OP_SESSSETUP:
1523 status = NT_STATUS_OK;
1529 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1530 switch (in_opcode) {
1532 case SMB2_OP_CREATE:
1533 case SMB2_OP_GETINFO:
1534 case SMB2_OP_SETINFO:
1535 return NT_STATUS_INVALID_HANDLE;
1538 * Notice the check for
1539 * (session_info == NULL)
1542 status = NT_STATUS_OK;
1546 if (!NT_STATUS_IS_OK(status)) {
1550 session_info = session->global->auth_session_info;
1551 if (session_info == NULL) {
1552 return NT_STATUS_INVALID_HANDLE;
1555 set_current_user_info(session_info->unix_info->sanitized_username,
1556 session_info->unix_info->unix_name,
1557 session_info->info->domain_name);
1559 return NT_STATUS_OK;
1562 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1563 uint32_t data_length)
1565 uint16_t needed_charge;
1566 uint16_t credit_charge = 1;
1567 const uint8_t *inhdr;
1569 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1571 if (req->sconn->smb2.supports_multicredit) {
1572 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1573 credit_charge = MAX(credit_charge, 1);
1576 needed_charge = (data_length - 1)/ 65536 + 1;
1578 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1579 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1580 credit_charge, needed_charge));
1582 if (needed_charge > credit_charge) {
1583 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1584 credit_charge, needed_charge));
1585 return NT_STATUS_INVALID_PARAMETER;
1588 return NT_STATUS_OK;
1591 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1592 size_t expected_body_size)
1594 const uint8_t *inhdr;
1596 const uint8_t *inbody;
1597 int i = req->current_idx;
1599 size_t min_dyn_size = expected_body_size & 0x00000001;
1602 * The following should be checked already.
1604 if ((i+2) > req->in.vector_count) {
1605 return NT_STATUS_INTERNAL_ERROR;
1607 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1608 return NT_STATUS_INTERNAL_ERROR;
1610 if (req->in.vector[i+1].iov_len < 2) {
1611 return NT_STATUS_INTERNAL_ERROR;
1614 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1615 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1619 case SMB2_OP_GETINFO:
1625 * Now check the expected body size,
1626 * where the last byte might be in the
1629 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1630 return NT_STATUS_INVALID_PARAMETER;
1632 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1633 return NT_STATUS_INVALID_PARAMETER;
1636 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1638 body_size = SVAL(inbody, 0x00);
1639 if (body_size != expected_body_size) {
1640 return NT_STATUS_INVALID_PARAMETER;
1643 return NT_STATUS_OK;
1646 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1648 struct smbXsrv_connection *conn = req->sconn->conn;
1649 const struct smbd_smb2_dispatch_table *call = NULL;
1650 const uint8_t *inhdr;
1655 NTSTATUS session_status;
1656 uint32_t allowed_flags;
1657 NTSTATUS return_value;
1658 struct smbXsrv_session *x = NULL;
1659 bool signing_required = false;
1661 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1663 /* TODO: verify more things */
1665 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1666 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1667 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1668 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1669 smb2_opcode_name(opcode),
1670 (unsigned long long)mid));
1672 if (conn->protocol >= PROTOCOL_SMB2_02) {
1674 * once the protocol is negotiated
1675 * SMB2_OP_NEGPROT is not allowed anymore
1677 if (opcode == SMB2_OP_NEGPROT) {
1678 /* drop the connection */
1679 return NT_STATUS_INVALID_PARAMETER;
1683 * if the protocol is not negotiated yet
1684 * only SMB2_OP_NEGPROT is allowed.
1686 if (opcode != SMB2_OP_NEGPROT) {
1687 /* drop the connection */
1688 return NT_STATUS_INVALID_PARAMETER;
1692 call = smbd_smb2_call(opcode);
1694 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1697 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1698 SMB2_HDR_FLAG_SIGNED |
1700 if (opcode == SMB2_OP_CANCEL) {
1701 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1703 if ((flags & ~allowed_flags) != 0) {
1704 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1708 * Check if the client provided a valid session id,
1709 * if so smbd_smb2_request_check_session() calls
1710 * set_current_user_info().
1712 * As some command don't require a valid session id
1713 * we defer the check of the session_status
1715 session_status = smbd_smb2_request_check_session(req);
1719 signing_required = x->global->signing_required;
1721 if (opcode == SMB2_OP_SESSSETUP &&
1722 x->global->channels[0].signing_key.length) {
1723 signing_required = true;
1727 req->do_signing = false;
1728 if (flags & SMB2_HDR_FLAG_SIGNED) {
1729 DATA_BLOB signing_key;
1732 return smbd_smb2_request_error(
1733 req, NT_STATUS_ACCESS_DENIED);
1736 signing_key = x->global->channels[0].signing_key;
1738 if (!NT_STATUS_IS_OK(session_status)) {
1739 return smbd_smb2_request_error(req, session_status);
1742 req->do_signing = true;
1743 status = smb2_signing_check_pdu(signing_key,
1745 SMBD_SMB2_IN_HDR_IOV(req),
1746 SMBD_SMB2_NUM_IOV_PER_REQ);
1747 if (!NT_STATUS_IS_OK(status)) {
1748 return smbd_smb2_request_error(req, status);
1750 } else if (opcode == SMB2_OP_CANCEL) {
1751 /* Cancel requests are allowed to skip the signing */
1752 } else if (signing_required) {
1753 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1756 if (flags & SMB2_HDR_FLAG_CHAINED) {
1758 * This check is mostly for giving the correct error code
1759 * for compounded requests.
1761 * TODO: we may need to move this after the session
1764 if (!NT_STATUS_IS_OK(req->next_status)) {
1765 return smbd_smb2_request_error(req, req->next_status);
1768 req->compat_chain_fsp = NULL;
1771 if (req->compound_related) {
1772 req->sconn->smb2.compound_related_in_progress = true;
1775 if (call->need_session) {
1776 if (!NT_STATUS_IS_OK(session_status)) {
1777 return smbd_smb2_request_error(req, session_status);
1781 if (call->need_tcon) {
1782 SMB_ASSERT(call->need_session);
1785 * This call needs to be run as user.
1787 * smbd_smb2_request_check_tcon()
1788 * calls change_to_user() on success.
1790 status = smbd_smb2_request_check_tcon(req);
1791 if (!NT_STATUS_IS_OK(status)) {
1792 return smbd_smb2_request_error(req, status);
1796 if (call->as_root) {
1797 /* This call needs to be run as root */
1798 change_to_root_user();
1800 SMB_ASSERT(call->need_tcon);
1804 case SMB2_OP_NEGPROT:
1806 START_PROFILE(smb2_negprot);
1807 return_value = smbd_smb2_request_process_negprot(req);
1808 END_PROFILE(smb2_negprot);
1812 case SMB2_OP_SESSSETUP:
1814 START_PROFILE(smb2_sesssetup);
1815 return_value = smbd_smb2_request_process_sesssetup(req);
1816 END_PROFILE(smb2_sesssetup);
1820 case SMB2_OP_LOGOFF:
1822 START_PROFILE(smb2_logoff);
1823 return_value = smbd_smb2_request_process_logoff(req);
1824 END_PROFILE(smb2_logoff);
1830 START_PROFILE(smb2_tcon);
1831 return_value = smbd_smb2_request_process_tcon(req);
1832 END_PROFILE(smb2_tcon);
1838 START_PROFILE(smb2_tdis);
1839 return_value = smbd_smb2_request_process_tdis(req);
1840 END_PROFILE(smb2_tdis);
1844 case SMB2_OP_CREATE:
1846 START_PROFILE(smb2_create);
1847 return_value = smbd_smb2_request_process_create(req);
1848 END_PROFILE(smb2_create);
1854 START_PROFILE(smb2_close);
1855 return_value = smbd_smb2_request_process_close(req);
1856 END_PROFILE(smb2_close);
1862 START_PROFILE(smb2_flush);
1863 return_value = smbd_smb2_request_process_flush(req);
1864 END_PROFILE(smb2_flush);
1870 START_PROFILE(smb2_read);
1871 return_value = smbd_smb2_request_process_read(req);
1872 END_PROFILE(smb2_read);
1878 START_PROFILE(smb2_write);
1879 return_value = smbd_smb2_request_process_write(req);
1880 END_PROFILE(smb2_write);
1886 START_PROFILE(smb2_lock);
1887 return_value = smbd_smb2_request_process_lock(req);
1888 END_PROFILE(smb2_lock);
1894 START_PROFILE(smb2_ioctl);
1895 return_value = smbd_smb2_request_process_ioctl(req);
1896 END_PROFILE(smb2_ioctl);
1900 case SMB2_OP_CANCEL:
1902 START_PROFILE(smb2_cancel);
1903 return_value = smbd_smb2_request_process_cancel(req);
1904 END_PROFILE(smb2_cancel);
1908 case SMB2_OP_KEEPALIVE:
1910 START_PROFILE(smb2_keepalive);
1911 return_value = smbd_smb2_request_process_keepalive(req);
1912 END_PROFILE(smb2_keepalive);
1918 START_PROFILE(smb2_find);
1919 return_value = smbd_smb2_request_process_find(req);
1920 END_PROFILE(smb2_find);
1924 case SMB2_OP_NOTIFY:
1926 START_PROFILE(smb2_notify);
1927 return_value = smbd_smb2_request_process_notify(req);
1928 END_PROFILE(smb2_notify);
1932 case SMB2_OP_GETINFO:
1934 START_PROFILE(smb2_getinfo);
1935 return_value = smbd_smb2_request_process_getinfo(req);
1936 END_PROFILE(smb2_getinfo);
1940 case SMB2_OP_SETINFO:
1942 START_PROFILE(smb2_setinfo);
1943 return_value = smbd_smb2_request_process_setinfo(req);
1944 END_PROFILE(smb2_setinfo);
1950 START_PROFILE(smb2_break);
1951 return_value = smbd_smb2_request_process_break(req);
1952 END_PROFILE(smb2_break);
1957 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1960 return return_value;
1963 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1965 struct tevent_req *subreq;
1966 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
1967 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
1970 TALLOC_FREE(req->async_te);
1972 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
1974 if (req->current_idx < req->out.vector_count) {
1976 * We must process the remaining compound
1977 * SMB2 requests before any new incoming SMB2
1978 * requests. This is because incoming SMB2
1979 * requests may include a cancel for a
1980 * compound request we haven't processed
1983 struct tevent_immediate *im = tevent_create_immediate(req);
1985 return NT_STATUS_NO_MEMORY;
1987 tevent_schedule_immediate(im,
1989 smbd_smb2_request_dispatch_immediate,
1991 return NT_STATUS_OK;
1994 if (req->compound_related) {
1995 req->sconn->smb2.compound_related_in_progress = false;
1998 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2000 /* Set credit for these operations (zero credits if this
2001 is a final reply for an async operation). */
2002 smb2_calculate_credits(req, req);
2004 if (req->do_signing) {
2006 struct smbXsrv_session *x = req->session;
2007 struct smbXsrv_connection *conn = x->connection;
2008 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2010 status = smb2_signing_sign_pdu(signing_key,
2013 SMBD_SMB2_NUM_IOV_PER_REQ);
2014 if (!NT_STATUS_IS_OK(status)) {
2019 if (DEBUGLEVEL >= 10) {
2020 dbgtext("smbd_smb2_request_reply: sending...\n");
2021 print_req_vectors(req);
2024 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2025 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2026 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2027 /* Dynamic part is NULL. Chop it off,
2028 We're going to send it via sendfile. */
2029 req->out.vector_count -= 1;
2032 subreq = tstream_writev_queue_send(req,
2034 req->sconn->smb2.stream,
2035 req->sconn->smb2.send_queue,
2037 req->out.vector_count);
2038 if (subreq == NULL) {
2039 return NT_STATUS_NO_MEMORY;
2041 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
2043 * We're done with this request -
2044 * move it off the "being processed" queue.
2046 DLIST_REMOVE(req->sconn->smb2.requests, req);
2048 return NT_STATUS_OK;
2051 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2053 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2054 struct tevent_immediate *im,
2057 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2058 struct smbd_smb2_request);
2059 struct smbd_server_connection *sconn = req->sconn;
2064 if (DEBUGLEVEL >= 10) {
2065 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2066 req->current_idx, req->in.vector_count));
2067 print_req_vectors(req);
2070 status = smbd_smb2_request_dispatch(req);
2071 if (!NT_STATUS_IS_OK(status)) {
2072 smbd_server_connection_terminate(sconn, nt_errstr(status));
2076 status = smbd_smb2_request_next_incoming(sconn);
2077 if (!NT_STATUS_IS_OK(status)) {
2078 smbd_server_connection_terminate(sconn, nt_errstr(status));
2083 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
2085 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
2086 struct smbd_smb2_request);
2087 struct smbd_server_connection *sconn = req->sconn;
2092 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2093 TALLOC_FREE(subreq);
2096 status = map_nt_error_from_unix(sys_errno);
2097 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2098 nt_errstr(status)));
2099 smbd_server_connection_terminate(sconn, nt_errstr(status));
2103 status = smbd_smb2_request_next_incoming(sconn);
2104 if (!NT_STATUS_IS_OK(status)) {
2105 smbd_server_connection_terminate(sconn, nt_errstr(status));
2110 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2112 DATA_BLOB body, DATA_BLOB *dyn,
2113 const char *location)
2116 int i = req->current_idx;
2117 uint32_t next_command_ofs;
2119 DEBUG(10,("smbd_smb2_request_done_ex: "
2120 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2121 i, nt_errstr(status), (unsigned int)body.length,
2123 (unsigned int)(dyn ? dyn->length : 0),
2126 if (body.length < 2) {
2127 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2130 if ((body.length % 2) != 0) {
2131 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2134 outhdr = (uint8_t *)req->out.vector[i].iov_base;
2136 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2137 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2139 req->out.vector[i+1].iov_base = (void *)body.data;
2140 req->out.vector[i+1].iov_len = body.length;
2143 req->out.vector[i+2].iov_base = (void *)dyn->data;
2144 req->out.vector[i+2].iov_len = dyn->length;
2146 req->out.vector[i+2].iov_base = NULL;
2147 req->out.vector[i+2].iov_len = 0;
2150 /* see if we need to recalculate the offset to the next response */
2151 if (next_command_ofs > 0) {
2152 next_command_ofs = SMB2_HDR_BODY;
2153 next_command_ofs += req->out.vector[i+1].iov_len;
2154 next_command_ofs += req->out.vector[i+2].iov_len;
2157 if ((next_command_ofs % 8) != 0) {
2158 size_t pad_size = 8 - (next_command_ofs % 8);
2159 if (req->out.vector[i+2].iov_len == 0) {
2161 * if the dyn buffer is empty
2162 * we can use it to add padding
2166 pad = talloc_zero_array(req->out.vector,
2169 return smbd_smb2_request_error(req,
2170 NT_STATUS_NO_MEMORY);
2173 req->out.vector[i+2].iov_base = (void *)pad;
2174 req->out.vector[i+2].iov_len = pad_size;
2177 * For now we copy the dynamic buffer
2178 * and add the padding to the new buffer
2185 old_size = req->out.vector[i+2].iov_len;
2186 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2188 new_size = old_size + pad_size;
2189 new_dyn = talloc_zero_array(req->out.vector,
2191 if (new_dyn == NULL) {
2192 return smbd_smb2_request_error(req,
2193 NT_STATUS_NO_MEMORY);
2196 memcpy(new_dyn, old_dyn, old_size);
2197 memset(new_dyn + old_size, 0, pad_size);
2199 req->out.vector[i+2].iov_base = (void *)new_dyn;
2200 req->out.vector[i+2].iov_len = new_size;
2202 next_command_ofs += pad_size;
2205 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2207 return smbd_smb2_request_reply(req);
2210 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2213 const char *location)
2216 int i = req->current_idx;
2217 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2219 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2220 i, nt_errstr(status), info ? " +info" : "",
2223 body.data = outhdr + SMB2_HDR_BODY;
2225 SSVAL(body.data, 0, 9);
2228 SIVAL(body.data, 0x04, info->length);
2230 /* Allocated size of req->out.vector[i].iov_base
2231 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2232 * 1 byte without having to do an alloc.
2234 info = talloc_zero_array(req->out.vector,
2238 return NT_STATUS_NO_MEMORY;
2240 info->data = ((uint8_t *)outhdr) +
2241 OUTVEC_ALLOC_SIZE - 1;
2243 SCVAL(info->data, 0, 0);
2247 * if a request fails, all other remaining
2248 * compounded requests should fail too
2250 req->next_status = NT_STATUS_INVALID_PARAMETER;
2252 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2256 struct smbd_smb2_send_oplock_break_state {
2257 struct smbd_server_connection *sconn;
2258 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2259 struct iovec vector;
2262 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2264 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2265 uint64_t file_id_persistent,
2266 uint64_t file_id_volatile,
2267 uint8_t oplock_level)
2269 struct smbd_smb2_send_oplock_break_state *state;
2270 struct tevent_req *subreq;
2274 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2275 if (state == NULL) {
2276 return NT_STATUS_NO_MEMORY;
2278 state->sconn = sconn;
2280 state->vector.iov_base = (void *)state->buf;
2281 state->vector.iov_len = sizeof(state->buf);
2283 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2284 hdr = state->buf + 4;
2285 body = hdr + SMB2_HDR_BODY;
2287 SIVAL(hdr, 0, SMB2_MAGIC);
2288 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2289 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2290 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2291 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2292 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2293 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2294 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2295 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2296 SIVAL(hdr, SMB2_HDR_PID, 0);
2297 SIVAL(hdr, SMB2_HDR_TID, 0);
2298 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2299 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2301 SSVAL(body, 0x00, 0x18);
2303 SCVAL(body, 0x02, oplock_level);
2304 SCVAL(body, 0x03, 0); /* reserved */
2305 SIVAL(body, 0x04, 0); /* reserved */
2306 SBVAL(body, 0x08, file_id_persistent);
2307 SBVAL(body, 0x10, file_id_volatile);
2309 subreq = tstream_writev_queue_send(state,
2312 sconn->smb2.send_queue,
2314 if (subreq == NULL) {
2315 return NT_STATUS_NO_MEMORY;
2317 tevent_req_set_callback(subreq,
2318 smbd_smb2_oplock_break_writev_done,
2321 return NT_STATUS_OK;
2324 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2326 struct smbd_smb2_send_oplock_break_state *state =
2327 tevent_req_callback_data(subreq,
2328 struct smbd_smb2_send_oplock_break_state);
2329 struct smbd_server_connection *sconn = state->sconn;
2333 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2334 TALLOC_FREE(subreq);
2336 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2337 smbd_server_connection_terminate(sconn, nt_errstr(status));
2344 struct smbd_smb2_request_read_state {
2345 struct tevent_context *ev;
2346 struct smbd_server_connection *sconn;
2347 struct smbd_smb2_request *smb2_req;
2349 uint8_t nbt[NBT_HDR_SIZE];
2356 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2358 TALLOC_CTX *mem_ctx,
2359 struct iovec **_vector,
2361 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2363 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2364 struct tevent_context *ev,
2365 struct smbd_server_connection *sconn)
2367 struct tevent_req *req;
2368 struct smbd_smb2_request_read_state *state;
2369 struct tevent_req *subreq;
2371 req = tevent_req_create(mem_ctx, &state,
2372 struct smbd_smb2_request_read_state);
2377 state->sconn = sconn;
2379 state->smb2_req = smbd_smb2_request_allocate(state);
2380 if (tevent_req_nomem(state->smb2_req, req)) {
2381 return tevent_req_post(req, ev);
2383 state->smb2_req->sconn = sconn;
2385 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
2387 state->sconn->smb2.stream,
2388 state->sconn->smb2.recv_queue,
2389 smbd_smb2_request_next_vector,
2391 if (tevent_req_nomem(subreq, req)) {
2392 return tevent_req_post(req, ev);
2394 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2399 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2401 TALLOC_CTX *mem_ctx,
2402 struct iovec **_vector,
2405 struct smbd_smb2_request_read_state *state =
2406 talloc_get_type_abort(private_data,
2407 struct smbd_smb2_request_read_state);
2408 struct iovec *vector;
2410 if (state->pktlen > 0) {
2411 /* if there're no remaining bytes, we're done */
2417 if (!state->hdr.done) {
2419 * first we need to get the NBT header
2421 vector = talloc_array(mem_ctx, struct iovec, 1);
2422 if (vector == NULL) {
2426 vector[0].iov_base = (void *)state->hdr.nbt;
2427 vector[0].iov_len = NBT_HDR_SIZE;
2432 state->hdr.done = true;
2437 * Now we analyze the NBT header
2439 state->pktlen = smb2_len(state->hdr.nbt);
2441 if (state->pktlen == 0) {
2442 /* if there're no remaining bytes, we're done */
2448 state->pktbuf = talloc_array(state->smb2_req, uint8_t, state->pktlen);
2449 if (state->pktbuf == NULL) {
2453 vector = talloc_array(mem_ctx, struct iovec, 1);
2454 if (vector == NULL) {
2458 vector[0].iov_base = (void *)state->pktbuf;
2459 vector[0].iov_len = state->pktlen;
2466 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2468 struct tevent_req *req =
2469 tevent_req_callback_data(subreq,
2471 struct smbd_smb2_request_read_state *state =
2472 tevent_req_data(req,
2473 struct smbd_smb2_request_read_state);
2479 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2480 TALLOC_FREE(subreq);
2482 status = map_nt_error_from_unix(sys_errno);
2483 tevent_req_nterror(req, status);
2487 if (state->hdr.nbt[0] != 0x00) {
2488 DEBUG(1,("smbd_smb2_request_read_done: ignore NBT[0x%02X] msg\n",
2489 state->hdr.nbt[0]));
2491 ZERO_STRUCT(state->hdr);
2492 TALLOC_FREE(state->pktbuf);
2495 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
2497 state->sconn->smb2.stream,
2498 state->sconn->smb2.recv_queue,
2499 smbd_smb2_request_next_vector,
2501 if (tevent_req_nomem(subreq, req)) {
2504 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2508 state->smb2_req->request_time = timeval_current();
2509 now = timeval_to_nttime(&state->smb2_req->request_time);
2511 status = smbd_smb2_inbuf_parse_compound(state->smb2_req->sconn->conn,
2516 &state->smb2_req->in.vector,
2517 &state->smb2_req->in.vector_count);
2518 if (tevent_req_nterror(req, status)) {
2522 state->smb2_req->current_idx = 1;
2524 tevent_req_done(req);
2527 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2528 TALLOC_CTX *mem_ctx,
2529 struct smbd_smb2_request **_smb2_req)
2531 struct smbd_smb2_request_read_state *state =
2532 tevent_req_data(req,
2533 struct smbd_smb2_request_read_state);
2536 if (tevent_req_is_nterror(req, &status)) {
2537 tevent_req_received(req);
2541 *_smb2_req = talloc_move(mem_ctx, &state->smb2_req);
2542 tevent_req_received(req);
2543 return NT_STATUS_OK;
2546 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2548 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2550 size_t max_send_queue_len;
2551 size_t cur_send_queue_len;
2552 struct tevent_req *subreq;
2554 if (sconn->smb2.compound_related_in_progress) {
2556 * Can't read another until the related
2559 return NT_STATUS_OK;
2562 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2564 * if there is already a smbd_smb2_request_read
2565 * pending, we are done.
2567 return NT_STATUS_OK;
2570 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2571 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2573 if (cur_send_queue_len > max_send_queue_len) {
2575 * if we have a lot of requests to send,
2576 * we wait until they are on the wire until we
2577 * ask for the next request.
2579 return NT_STATUS_OK;
2582 /* ask for the next request */
2583 subreq = smbd_smb2_request_read_send(sconn, sconn->ev_ctx, sconn);
2584 if (subreq == NULL) {
2585 return NT_STATUS_NO_MEMORY;
2587 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2589 return NT_STATUS_OK;
2592 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2593 uint8_t *inbuf, size_t size)
2596 struct smbd_smb2_request *req = NULL;
2598 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2599 (unsigned int)size));
2601 status = smbd_initialize_smb2(sconn);
2602 if (!NT_STATUS_IS_OK(status)) {
2603 smbd_server_connection_terminate(sconn, nt_errstr(status));
2607 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2608 if (!NT_STATUS_IS_OK(status)) {
2609 smbd_server_connection_terminate(sconn, nt_errstr(status));
2613 status = smbd_smb2_request_validate(req);
2614 if (!NT_STATUS_IS_OK(status)) {
2615 smbd_server_connection_terminate(sconn, nt_errstr(status));
2619 status = smbd_smb2_request_setup_out(req);
2620 if (!NT_STATUS_IS_OK(status)) {
2621 smbd_server_connection_terminate(sconn, nt_errstr(status));
2625 status = smbd_smb2_request_dispatch(req);
2626 if (!NT_STATUS_IS_OK(status)) {
2627 smbd_server_connection_terminate(sconn, nt_errstr(status));
2631 status = smbd_smb2_request_next_incoming(sconn);
2632 if (!NT_STATUS_IS_OK(status)) {
2633 smbd_server_connection_terminate(sconn, nt_errstr(status));
2637 sconn->num_requests++;
2640 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2642 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2643 struct smbd_server_connection);
2645 struct smbd_smb2_request *req = NULL;
2647 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2648 TALLOC_FREE(subreq);
2649 if (!NT_STATUS_IS_OK(status)) {
2650 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2651 nt_errstr(status)));
2652 smbd_server_connection_terminate(sconn, nt_errstr(status));
2656 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2657 req->current_idx, req->in.vector_count));
2659 status = smbd_smb2_request_validate(req);
2660 if (!NT_STATUS_IS_OK(status)) {
2661 smbd_server_connection_terminate(sconn, nt_errstr(status));
2665 status = smbd_smb2_request_setup_out(req);
2666 if (!NT_STATUS_IS_OK(status)) {
2667 smbd_server_connection_terminate(sconn, nt_errstr(status));
2671 status = smbd_smb2_request_dispatch(req);
2672 if (!NT_STATUS_IS_OK(status)) {
2673 smbd_server_connection_terminate(sconn, nt_errstr(status));
2677 status = smbd_smb2_request_next_incoming(sconn);
2678 if (!NT_STATUS_IS_OK(status)) {
2679 smbd_server_connection_terminate(sconn, nt_errstr(status));
2683 sconn->num_requests++;
2685 /* The timeout_processing function isn't run nearly
2686 often enough to implement 'max log size' without
2687 overrunning the size of the file by many megabytes.
2688 This is especially true if we are running at debug
2689 level 10. Checking every 50 SMB2s is a nice
2690 tradeoff of performance vs log file size overrun. */
2692 if ((sconn->num_requests % 50) == 0 &&
2693 need_to_check_log_size()) {
2694 change_to_root_user();