2 Unix SMB/CIFS implementation.
5 Copyright (C) Stefan Metzmacher 2009
6 Copyright (C) Jeremy Allison 2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../libcli/smb/smb_common.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "../lib/util/tevent_ntstatus.h"
28 #include "smbprofile.h"
29 #include "../lib/util/bitmap.h"
30 #include "../librpc/gen_ndr/krb5pac.h"
33 #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9)
35 static const struct smbd_smb2_dispatch_table {
41 } smbd_smb2_table[] = {
42 #define _OP(o) .opcode = o, .name = #o
47 _OP(SMB2_OP_SESSSETUP),
57 * This call needs to be run as root.
59 * smbd_smb2_request_process_tcon()
60 * calls make_connection_snum(), which will call
61 * change_to_user(), when needed.
101 _OP(SMB2_OP_KEEPALIVE),
105 .need_session = true,
109 .need_session = true,
112 _OP(SMB2_OP_GETINFO),
113 .need_session = true,
116 _OP(SMB2_OP_SETINFO),
117 .need_session = true,
121 .need_session = true,
126 const char *smb2_opcode_name(uint16_t opcode)
128 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
129 return "Bad SMB2 opcode";
131 return smbd_smb2_table[opcode].name;
134 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
136 const struct smbd_smb2_dispatch_table *ret = NULL;
138 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
142 ret = &smbd_smb2_table[opcode];
144 SMB_ASSERT(ret->opcode == opcode);
149 static void print_req_vectors(struct smbd_smb2_request *req)
153 for (i = 0; i < req->in.vector_count; i++) {
154 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
156 (unsigned int)req->in.vector[i].iov_len);
158 for (i = 0; i < req->out.vector_count; i++) {
159 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
161 (unsigned int)req->out.vector[i].iov_len);
165 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
167 if (size < (4 + SMB2_HDR_BODY)) {
171 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
178 static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
183 TALLOC_FREE(sconn->smb1.fde);
185 sconn->smb2.recv_queue = tevent_queue_create(sconn, "smb2 recv queue");
186 if (sconn->smb2.recv_queue == NULL) {
187 return NT_STATUS_NO_MEMORY;
190 sconn->smb2.send_queue = tevent_queue_create(sconn, "smb2 send queue");
191 if (sconn->smb2.send_queue == NULL) {
192 return NT_STATUS_NO_MEMORY;
195 sconn->smb2.seqnum_low = 0;
196 sconn->smb2.seqnum_range = 1;
197 sconn->smb2.credits_granted = 1;
198 sconn->smb2.max_credits = lp_smb2_max_credits();
199 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
200 sconn->smb2.max_credits);
201 if (sconn->smb2.credits_bitmap == NULL) {
202 return NT_STATUS_NO_MEMORY;
205 ret = tstream_bsd_existing_socket(sconn, sconn->sock,
206 &sconn->smb2.stream);
208 status = map_nt_error_from_unix(errno);
212 /* Ensure child is set to non-blocking mode */
213 set_blocking(sconn->sock, false);
217 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
218 #define _smb2_setlen(_buf,len) do { \
219 uint8_t *buf = (uint8_t *)_buf; \
221 buf[1] = ((len)&0xFF0000)>>16; \
222 buf[2] = ((len)&0xFF00)>>8; \
223 buf[3] = (len)&0xFF; \
226 static void smb2_setup_nbt_length(struct iovec *vector, int count)
231 for (i=1; i < count; i++) {
232 len += vector[i].iov_len;
235 _smb2_setlen(vector[0].iov_base, len);
238 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
240 TALLOC_CTX *mem_pool;
241 struct smbd_smb2_request *req;
244 /* Enable this to find subtle valgrind errors. */
245 mem_pool = talloc_init("smbd_smb2_request_allocate");
247 mem_pool = talloc_pool(mem_ctx, 8192);
249 if (mem_pool == NULL) {
253 req = talloc_zero(mem_pool, struct smbd_smb2_request);
255 talloc_free(mem_pool);
258 talloc_reparent(mem_pool, mem_ctx, req);
259 TALLOC_FREE(mem_pool);
261 req->last_session_id = UINT64_MAX;
262 req->last_tid = UINT32_MAX;
267 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn,
278 uint8_t *first_hdr = buf;
281 * Note: index '0' is reserved for the transport protocol
283 iov = talloc_zero_array(mem_ctx, struct iovec, num_iov);
285 return NT_STATUS_NO_MEMORY;
288 while (taken < buflen) {
289 size_t len = buflen - taken;
290 uint8_t *hdr = first_hdr + taken;
293 size_t next_command_ofs;
295 struct iovec *iov_tmp;
298 * We need the header plus the body length field
301 if (len < SMB2_HDR_BODY + 2) {
302 DEBUG(10, ("%d bytes left, expected at least %d\n",
303 (int)len, SMB2_HDR_BODY));
306 if (IVAL(hdr, 0) != SMB2_MAGIC) {
307 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
311 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
312 DEBUG(10, ("Got HDR len %d, expected %d\n",
313 SVAL(hdr, 4), SMB2_HDR_BODY));
318 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
319 body_size = SVAL(hdr, SMB2_HDR_BODY);
321 if (next_command_ofs != 0) {
322 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
325 if (next_command_ofs > full_size) {
328 full_size = next_command_ofs;
335 if (body_size > (full_size - SMB2_HDR_BODY)) {
337 * let the caller handle the error
339 body_size = full_size - SMB2_HDR_BODY;
342 iov_tmp = talloc_realloc(mem_ctx, iov, struct iovec,
344 if (iov_tmp == NULL) {
346 return NT_STATUS_NO_MEMORY;
352 cur[0].iov_base = hdr;
353 cur[0].iov_len = SMB2_HDR_BODY;
354 cur[1].iov_base = hdr + SMB2_HDR_BODY;
355 cur[1].iov_len = body_size;
356 cur[2].iov_base = hdr + SMB2_HDR_BODY + body_size;
357 cur[2].iov_len = full_size - (SMB2_HDR_BODY + body_size);
368 return NT_STATUS_INVALID_PARAMETER;
371 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
372 uint8_t *inbuf, size_t size,
373 struct smbd_smb2_request **_req)
375 struct smbd_smb2_request *req;
376 uint32_t protocol_version;
377 const uint8_t *inhdr = NULL;
379 uint32_t next_command_ofs;
383 if (size < (4 + SMB2_HDR_BODY + 2)) {
384 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
385 return NT_STATUS_INVALID_PARAMETER;
390 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
391 if (protocol_version != SMB2_MAGIC) {
392 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
394 return NT_STATUS_INVALID_PARAMETER;
397 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
398 if (cmd != SMB2_OP_NEGPROT) {
399 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
401 return NT_STATUS_INVALID_PARAMETER;
404 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
405 if (next_command_ofs != 0) {
406 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
408 return NT_STATUS_INVALID_PARAMETER;
411 req = smbd_smb2_request_allocate(sconn);
413 return NT_STATUS_NO_MEMORY;
417 talloc_steal(req, inbuf);
419 req->request_time = timeval_current();
420 now = timeval_to_nttime(&req->request_time);
422 status = smbd_smb2_inbuf_parse_compound(sconn->conn,
424 inbuf + NBT_HDR_SIZE,
426 req, &req->in.vector,
427 &req->in.vector_count);
428 if (!NT_STATUS_IS_OK(status)) {
433 req->current_idx = 1;
439 static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
440 uint64_t message_id, uint64_t seq_id)
442 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
445 if (seq_id < sconn->smb2.seqnum_low) {
446 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
447 "%llu (sequence id %llu) "
448 "(granted = %u, low = %llu, range = %u)\n",
449 (unsigned long long)message_id,
450 (unsigned long long)seq_id,
451 (unsigned int)sconn->smb2.credits_granted,
452 (unsigned long long)sconn->smb2.seqnum_low,
453 (unsigned int)sconn->smb2.seqnum_range));
457 if (seq_id >= sconn->smb2.seqnum_low + sconn->smb2.seqnum_range) {
458 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
459 "%llu (sequence id %llu) "
460 "(granted = %u, low = %llu, range = %u)\n",
461 (unsigned long long)message_id,
462 (unsigned long long)seq_id,
463 (unsigned int)sconn->smb2.credits_granted,
464 (unsigned long long)sconn->smb2.seqnum_low,
465 (unsigned int)sconn->smb2.seqnum_range));
469 offset = seq_id % sconn->smb2.max_credits;
471 if (bitmap_query(credits_bm, offset)) {
472 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
473 "%llu (sequence id %llu) "
474 "(granted = %u, low = %llu, range = %u) "
476 (unsigned long long)message_id,
477 (unsigned long long)seq_id,
478 (unsigned int)sconn->smb2.credits_granted,
479 (unsigned long long)sconn->smb2.seqnum_low,
480 (unsigned int)sconn->smb2.seqnum_range,
485 /* Mark the message_ids as seen in the bitmap. */
486 bitmap_set(credits_bm, offset);
488 if (seq_id != sconn->smb2.seqnum_low) {
493 * Move the window forward by all the message_id's
496 while (bitmap_query(credits_bm, offset)) {
497 DEBUG(10,("smb2_validate_sequence_number: clearing "
498 "id %llu (position %u) from bitmap\n",
499 (unsigned long long)(sconn->smb2.seqnum_low),
501 bitmap_clear(credits_bm, offset);
503 sconn->smb2.seqnum_low += 1;
504 sconn->smb2.seqnum_range -= 1;
505 offset = sconn->smb2.seqnum_low % sconn->smb2.max_credits;
511 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
512 const uint8_t *inhdr)
514 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
515 uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
516 uint16_t credit_charge = 1;
519 if (opcode == SMB2_OP_CANCEL) {
520 /* SMB2_CANCEL requests by definition resend messageids. */
524 if (sconn->smb2.supports_multicredit) {
525 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
526 credit_charge = MAX(credit_charge, 1);
529 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
530 "credits_granted %llu, "
531 "seqnum low/range: %llu/%llu\n",
532 (unsigned long long) message_id,
533 (unsigned long long) credit_charge,
534 (unsigned long long) sconn->smb2.credits_granted,
535 (unsigned long long) sconn->smb2.seqnum_low,
536 (unsigned long long) sconn->smb2.seqnum_range));
538 if (sconn->smb2.credits_granted < credit_charge) {
539 DEBUG(0, ("smb2_validate_message_id: client used more "
540 "credits than granted, mid %llu, charge %llu, "
541 "credits_granted %llu, "
542 "seqnum low/range: %llu/%llu\n",
543 (unsigned long long) message_id,
544 (unsigned long long) credit_charge,
545 (unsigned long long) sconn->smb2.credits_granted,
546 (unsigned long long) sconn->smb2.seqnum_low,
547 (unsigned long long) sconn->smb2.seqnum_range));
552 * now check the message ids
554 * for multi-credit requests we need to check all current mid plus
555 * the implicit mids caused by the credit charge
556 * e.g. current mid = 15, charge 5 => mark 15-19 as used
559 for (i = 0; i <= (credit_charge-1); i++) {
560 uint64_t id = message_id + i;
563 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
564 (unsigned long long)message_id,
566 (unsigned long long)id));
568 ok = smb2_validate_sequence_number(sconn, message_id, id);
574 /* substract used credits */
575 sconn->smb2.credits_granted -= credit_charge;
580 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
585 count = req->in.vector_count;
588 /* It's not a SMB2 request */
589 return NT_STATUS_INVALID_PARAMETER;
592 for (idx=1; idx < count; idx += 3) {
593 const uint8_t *inhdr = NULL;
596 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
597 return NT_STATUS_INVALID_PARAMETER;
600 if (req->in.vector[idx+1].iov_len < 2) {
601 return NT_STATUS_INVALID_PARAMETER;
604 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
606 /* Check the SMB2 header */
607 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
608 return NT_STATUS_INVALID_PARAMETER;
611 if (!smb2_validate_message_id(req->sconn, inhdr)) {
612 return NT_STATUS_INVALID_PARAMETER;
615 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
618 * the 1st request should never have the
619 * SMB2_HDR_FLAG_CHAINED flag set
621 if (flags & SMB2_HDR_FLAG_CHAINED) {
622 req->next_status = NT_STATUS_INVALID_PARAMETER;
625 } else if (idx == 4) {
627 * the 2nd request triggers related vs. unrelated
628 * compounded requests
630 if (flags & SMB2_HDR_FLAG_CHAINED) {
631 req->compound_related = true;
633 } else if (idx > 4) {
636 * It seems the this tests are wrong
637 * see the SMB2-COMPOUND test
641 * all other requests should match the 2nd one
643 if (flags & SMB2_HDR_FLAG_CHAINED) {
644 if (!req->compound_related) {
646 NT_STATUS_INVALID_PARAMETER;
650 if (req->compound_related) {
652 NT_STATUS_INVALID_PARAMETER;
663 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
664 const struct iovec *in_vector,
665 struct iovec *out_vector)
667 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
668 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
669 uint16_t credit_charge = 1;
670 uint16_t credits_requested;
674 uint16_t credits_granted = 0;
675 uint64_t credits_possible;
676 uint16_t current_max_credits;
679 * first we grant only 1/16th of the max range.
681 * Windows also starts with the 1/16th and then grants
682 * more later. I was only able to trigger higher
683 * values, when using a verify high credit charge.
685 * TODO: scale up depending one load, free memory
687 * Maybe also on the relationship between number
688 * of requests and the used sequence number.
689 * Which means we would grant more credits
690 * for client which use multi credit requests.
692 current_max_credits = sconn->smb2.max_credits / 16;
693 current_max_credits = MAX(current_max_credits, 1);
695 if (sconn->smb2.supports_multicredit) {
696 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
697 credit_charge = MAX(credit_charge, 1);
700 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
701 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
702 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
703 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
705 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
706 SMB_ASSERT(sconn->smb2.max_credits >= credit_charge);
708 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
710 * In case we already send an async interim
711 * response, we should not grant
712 * credits on the final response.
715 } else if (credits_requested > 0) {
716 uint16_t additional_max = 0;
717 uint16_t additional_credits = credits_requested - 1;
720 case SMB2_OP_NEGPROT:
722 case SMB2_OP_SESSSETUP:
724 * Windows 2012 RC1 starts to grant
726 * with a successful session setup
728 if (NT_STATUS_IS_OK(out_status)) {
734 * We match windows and only grant additional credits
741 additional_credits = MIN(additional_credits, additional_max);
743 credits_granted = credit_charge + additional_credits;
744 } else if (sconn->smb2.credits_granted == 0) {
746 * Make sure the client has always at least one credit
752 * sequence numbers should not wrap
754 * 1. calculate the possible credits until
755 * the sequence numbers start to wrap on 64-bit.
757 * 2. UINT64_MAX is used for Break Notifications.
759 * 2. truncate the possible credits to the maximum
760 * credits we want to grant to the client in total.
762 * 3. remove the range we'll already granted to the client
763 * this makes sure the client consumes the lowest sequence
764 * number, before we can grant additional credits.
766 credits_possible = UINT64_MAX - sconn->smb2.seqnum_low;
767 if (credits_possible > 0) {
768 /* remove UINT64_MAX */
769 credits_possible -= 1;
771 credits_possible = MIN(credits_possible, current_max_credits);
772 credits_possible -= sconn->smb2.seqnum_range;
774 credits_granted = MIN(credits_granted, credits_possible);
776 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
777 sconn->smb2.credits_granted += credits_granted;
778 sconn->smb2.seqnum_range += credits_granted;
780 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
781 "granted %u, current possible/max %u/%u, "
782 "total granted/max/low/range %u/%u/%llu/%u\n",
783 (unsigned int)credits_requested,
784 (unsigned int)credit_charge,
785 (unsigned int)credits_granted,
786 (unsigned int)credits_possible,
787 (unsigned int)current_max_credits,
788 (unsigned int)sconn->smb2.credits_granted,
789 (unsigned int)sconn->smb2.max_credits,
790 (unsigned long long)sconn->smb2.seqnum_low,
791 (unsigned int)sconn->smb2.seqnum_range));
794 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
795 struct smbd_smb2_request *outreq)
798 uint16_t total_credits = 0;
800 count = outreq->out.vector_count;
802 for (idx=1; idx < count; idx += 3) {
803 uint8_t *outhdr = (uint8_t *)outreq->out.vector[idx].iov_base;
804 smb2_set_operation_credit(outreq->sconn,
805 &inreq->in.vector[idx],
806 &outreq->out.vector[idx]);
807 /* To match Windows, count up what we
809 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
810 /* Set to zero in all but the last reply. */
811 if (idx + 3 < count) {
812 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
814 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
819 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
821 struct iovec *vector;
825 count = req->in.vector_count;
826 vector = talloc_zero_array(req, struct iovec, count);
827 if (vector == NULL) {
828 return NT_STATUS_NO_MEMORY;
831 vector[0].iov_base = req->out.nbt_hdr;
832 vector[0].iov_len = 4;
833 SIVAL(req->out.nbt_hdr, 0, 0);
835 for (idx=1; idx < count; idx += 3) {
836 const uint8_t *inhdr = NULL;
837 uint8_t *outhdr = NULL;
838 uint8_t *outbody = NULL;
839 uint32_t next_command_ofs = 0;
840 struct iovec *current = &vector[idx];
842 if ((idx + 3) < count) {
843 /* we have a next command -
844 * setup for the error case. */
845 next_command_ofs = SMB2_HDR_BODY + 9;
848 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
850 outhdr = talloc_zero_array(vector, uint8_t,
852 if (outhdr == NULL) {
853 return NT_STATUS_NO_MEMORY;
856 outbody = outhdr + SMB2_HDR_BODY;
858 current[0].iov_base = (void *)outhdr;
859 current[0].iov_len = SMB2_HDR_BODY;
861 current[1].iov_base = (void *)outbody;
862 current[1].iov_len = 8;
864 current[2].iov_base = NULL;
865 current[2].iov_len = 0;
867 /* setup the SMB2 header */
868 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
869 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
870 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
871 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
872 SIVAL(outhdr, SMB2_HDR_STATUS,
873 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
874 SSVAL(outhdr, SMB2_HDR_OPCODE,
875 SVAL(inhdr, SMB2_HDR_OPCODE));
876 SIVAL(outhdr, SMB2_HDR_FLAGS,
877 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
878 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
879 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
880 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
881 SIVAL(outhdr, SMB2_HDR_PID,
882 IVAL(inhdr, SMB2_HDR_PID));
883 SIVAL(outhdr, SMB2_HDR_TID,
884 IVAL(inhdr, SMB2_HDR_TID));
885 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
886 BVAL(inhdr, SMB2_HDR_SESSION_ID));
887 memcpy(outhdr + SMB2_HDR_SIGNATURE,
888 inhdr + SMB2_HDR_SIGNATURE, 16);
890 /* setup error body header */
891 SSVAL(outbody, 0x00, 0x08 + 1);
892 SSVAL(outbody, 0x02, 0);
893 SIVAL(outbody, 0x04, 0);
896 req->out.vector = vector;
897 req->out.vector_count = count;
899 /* setup the length of the NBT packet */
900 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
902 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
907 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
909 const char *location)
911 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
913 exit_server_cleanly(reason);
916 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
917 struct iovec *outvec,
918 const struct iovec *srcvec)
920 /* vec[0] is always boilerplate and must
921 * be allocated with size OUTVEC_ALLOC_SIZE. */
923 outvec[0].iov_base = talloc_memdup(ctx,
926 if (!outvec[0].iov_base) {
929 outvec[0].iov_len = SMB2_HDR_BODY;
932 * If this is a "standard" vec[1] of length 8,
933 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
934 * then duplicate this. Else use talloc_memdup().
937 if (srcvec[1].iov_len == 8 &&
938 srcvec[1].iov_base ==
939 ((uint8_t *)srcvec[0].iov_base) +
941 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
943 outvec[1].iov_len = 8;
945 outvec[1].iov_base = talloc_memdup(ctx,
948 if (!outvec[1].iov_base) {
951 outvec[1].iov_len = srcvec[1].iov_len;
955 * If this is a "standard" vec[2] of length 1,
956 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
957 * then duplicate this. Else use talloc_memdup().
960 if (srcvec[2].iov_base &&
962 if (srcvec[2].iov_base ==
963 ((uint8_t *)srcvec[0].iov_base) +
964 (OUTVEC_ALLOC_SIZE - 1) &&
965 srcvec[2].iov_len == 1) {
966 /* Common SMB2 error packet case. */
967 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
968 (OUTVEC_ALLOC_SIZE - 1);
970 outvec[2].iov_base = talloc_memdup(ctx,
973 if (!outvec[2].iov_base) {
977 outvec[2].iov_len = srcvec[2].iov_len;
979 outvec[2].iov_base = NULL;
980 outvec[2].iov_len = 0;
985 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
987 struct smbd_smb2_request *newreq = NULL;
988 struct iovec *outvec = NULL;
989 int count = req->out.vector_count;
992 newreq = smbd_smb2_request_allocate(req->sconn);
997 newreq->sconn = req->sconn;
998 newreq->session = req->session;
999 newreq->do_signing = req->do_signing;
1000 newreq->current_idx = req->current_idx;
1002 outvec = talloc_zero_array(newreq, struct iovec, count);
1004 TALLOC_FREE(newreq);
1007 newreq->out.vector = outvec;
1008 newreq->out.vector_count = count;
1010 /* Setup the outvec's identically to req. */
1011 outvec[0].iov_base = newreq->out.nbt_hdr;
1012 outvec[0].iov_len = 4;
1013 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1015 /* Setup the vectors identically to the ones in req. */
1016 for (i = 1; i < count; i += 3) {
1017 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
1024 TALLOC_FREE(newreq);
1028 smb2_setup_nbt_length(newreq->out.vector,
1029 newreq->out.vector_count);
1034 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
1036 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1039 uint8_t *outhdr = NULL;
1040 struct smbd_smb2_request *nreq = NULL;
1042 /* Create a new smb2 request we'll use
1043 for the interim return. */
1044 nreq = dup_smb2_req(req);
1046 return NT_STATUS_NO_MEMORY;
1049 /* Lose the last 3 out vectors. They're the
1050 ones we'll be using for the async reply. */
1051 nreq->out.vector_count -= 3;
1053 smb2_setup_nbt_length(nreq->out.vector,
1054 nreq->out.vector_count);
1056 /* Step back to the previous reply. */
1057 i = nreq->current_idx - 3;
1058 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
1059 /* And end the chain. */
1060 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1062 /* Calculate outgoing credits */
1063 smb2_calculate_credits(req, nreq);
1065 /* Re-sign if needed. */
1066 if (nreq->do_signing) {
1068 struct smbXsrv_session *x = nreq->session;
1069 struct smbXsrv_connection *conn = x->connection;
1070 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1072 status = smb2_signing_sign_pdu(signing_key,
1074 &nreq->out.vector[i], 3);
1075 if (!NT_STATUS_IS_OK(status)) {
1079 if (DEBUGLEVEL >= 10) {
1080 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1081 (unsigned int)nreq->current_idx );
1082 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1083 (unsigned int)nreq->out.vector_count );
1084 print_req_vectors(nreq);
1086 nreq->subreq = tstream_writev_queue_send(nreq,
1087 nreq->sconn->ev_ctx,
1088 nreq->sconn->smb2.stream,
1089 nreq->sconn->smb2.send_queue,
1091 nreq->out.vector_count);
1093 if (nreq->subreq == NULL) {
1094 return NT_STATUS_NO_MEMORY;
1097 tevent_req_set_callback(nreq->subreq,
1098 smbd_smb2_request_writev_done,
1101 return NT_STATUS_OK;
1104 struct smbd_smb2_request_pending_state {
1105 struct smbd_server_connection *sconn;
1106 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
1107 struct iovec vector[3];
1110 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
1112 struct smbd_smb2_request_pending_state *state =
1113 tevent_req_callback_data(subreq,
1114 struct smbd_smb2_request_pending_state);
1115 struct smbd_server_connection *sconn = state->sconn;
1119 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1120 TALLOC_FREE(subreq);
1122 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1123 smbd_server_connection_terminate(sconn, nt_errstr(status));
1130 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1131 struct tevent_timer *te,
1132 struct timeval current_time,
1133 void *private_data);
1135 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1136 struct tevent_req *subreq,
1137 uint32_t defer_time)
1140 int i = req->current_idx;
1141 struct timeval defer_endtime;
1142 uint8_t *outhdr = NULL;
1145 if (!tevent_req_is_in_progress(subreq)) {
1146 return NT_STATUS_OK;
1149 req->subreq = subreq;
1152 if (req->async_te) {
1153 /* We're already async. */
1154 return NT_STATUS_OK;
1157 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1158 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1159 if (flags & SMB2_HDR_FLAG_ASYNC) {
1160 /* We're already async. */
1161 return NT_STATUS_OK;
1164 if (req->in.vector_count > i + 3) {
1166 * We're trying to go async in a compound
1167 * request chain. This is not allowed.
1168 * Cancel the outstanding request.
1170 tevent_req_cancel(req->subreq);
1171 return smbd_smb2_request_error(req,
1172 NT_STATUS_INSUFFICIENT_RESOURCES);
1175 if (DEBUGLEVEL >= 10) {
1176 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1177 (unsigned int)req->current_idx );
1178 print_req_vectors(req);
1181 if (req->out.vector_count > 4) {
1182 struct iovec *outvec = NULL;
1184 /* This is a compound reply. We
1185 * must do an interim response
1186 * followed by the async response
1189 status = smb2_send_async_interim_response(req);
1190 if (!NT_STATUS_IS_OK(status)) {
1195 * We're splitting off the last SMB2
1196 * request in a compound set, and the
1197 * smb2_send_async_interim_response()
1198 * call above just sent all the replies
1199 * for the previous SMB2 requests in
1200 * this compound set. So we're no longer
1201 * in the "compound_related_in_progress"
1202 * state, and this is no longer a compound
1205 req->compound_related = false;
1206 req->sconn->smb2.compound_related_in_progress = false;
1208 /* Re-arrange the in.vectors. */
1209 req->in.vector[1] = req->in.vector[i];
1210 req->in.vector[2] = req->in.vector[i+1];
1211 req->in.vector[3] = req->in.vector[i+2];
1212 req->in.vector_count = 4;
1214 /* Reset the new in size. */
1215 smb2_setup_nbt_length(req->in.vector, 4);
1217 /* Now recreate the out.vectors. */
1218 outvec = talloc_zero_array(req, struct iovec, 4);
1220 return NT_STATUS_NO_MEMORY;
1223 /* 0 is always boilerplate and must
1224 * be of size 4 for the length field. */
1226 outvec[0].iov_base = req->out.nbt_hdr;
1227 outvec[0].iov_len = 4;
1228 SIVAL(req->out.nbt_hdr, 0, 0);
1230 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
1231 return NT_STATUS_NO_MEMORY;
1234 TALLOC_FREE(req->out.vector);
1236 req->out.vector = outvec;
1238 req->current_idx = 1;
1239 req->out.vector_count = 4;
1241 outhdr = (uint8_t *)req->out.vector[1].iov_base;
1242 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1243 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1246 defer_endtime = timeval_current_ofs_usec(defer_time);
1247 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1249 smbd_smb2_request_pending_timer,
1251 if (req->async_te == NULL) {
1252 return NT_STATUS_NO_MEMORY;
1255 return NT_STATUS_OK;
1258 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1259 struct tevent_timer *te,
1260 struct timeval current_time,
1263 struct smbd_smb2_request *req =
1264 talloc_get_type_abort(private_data,
1265 struct smbd_smb2_request);
1266 struct smbd_smb2_request_pending_state *state = NULL;
1267 uint8_t *outhdr = NULL;
1268 const uint8_t *inhdr = NULL;
1269 uint8_t *hdr = NULL;
1270 uint8_t *body = NULL;
1272 uint64_t message_id = 0;
1273 uint64_t async_id = 0;
1274 struct tevent_req *subreq = NULL;
1276 TALLOC_FREE(req->async_te);
1278 /* Ensure our final reply matches the interim one. */
1279 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1280 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1281 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1282 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1284 async_id = message_id; /* keep it simple for now... */
1286 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1287 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1289 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1291 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1292 (unsigned long long)async_id ));
1295 * What we send is identical to a smbd_smb2_request_error
1296 * packet with an error status of STATUS_PENDING. Make use
1297 * of this fact sometime when refactoring. JRA.
1300 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1301 if (state == NULL) {
1302 smbd_server_connection_terminate(req->sconn,
1303 nt_errstr(NT_STATUS_NO_MEMORY));
1306 state->sconn = req->sconn;
1308 state->vector[0].iov_base = (void *)state->buf;
1309 state->vector[0].iov_len = 4;
1311 state->vector[1].iov_base = state->buf + 4;
1312 state->vector[1].iov_len = SMB2_HDR_BODY;
1314 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
1315 state->vector[2].iov_len = 9;
1317 smb2_setup_nbt_length(state->vector, 3);
1319 hdr = (uint8_t *)state->vector[1].iov_base;
1320 body = (uint8_t *)state->vector[2].iov_base;
1322 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1323 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1324 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1325 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1326 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1328 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1329 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1330 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1331 SBVAL(hdr, SMB2_HDR_PID, async_id);
1332 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1333 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1334 memcpy(hdr+SMB2_HDR_SIGNATURE,
1335 outhdr+SMB2_HDR_SIGNATURE, 16);
1337 SSVAL(body, 0x00, 0x08 + 1);
1339 SCVAL(body, 0x02, 0);
1340 SCVAL(body, 0x03, 0);
1341 SIVAL(body, 0x04, 0);
1342 /* Match W2K8R2... */
1343 SCVAL(body, 0x08, 0x21);
1345 /* Ensure we correctly go through crediting. Grant
1346 the credits now, and zero credits on the final
1348 smb2_set_operation_credit(req->sconn,
1349 SMBD_SMB2_IN_HDR_IOV(req),
1352 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1354 if (req->do_signing) {
1356 struct smbXsrv_session *x = req->session;
1357 struct smbXsrv_connection *conn = x->connection;
1358 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1360 status = smb2_signing_sign_pdu(signing_key,
1362 &state->vector[1], 2);
1363 if (!NT_STATUS_IS_OK(status)) {
1364 smbd_server_connection_terminate(req->sconn,
1370 subreq = tstream_writev_queue_send(state,
1371 state->sconn->ev_ctx,
1372 state->sconn->smb2.stream,
1373 state->sconn->smb2.send_queue,
1376 if (subreq == NULL) {
1377 smbd_server_connection_terminate(state->sconn,
1378 nt_errstr(NT_STATUS_NO_MEMORY));
1381 tevent_req_set_callback(subreq,
1382 smbd_smb2_request_pending_writev_done,
1386 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1388 struct smbd_server_connection *sconn = req->sconn;
1389 struct smbd_smb2_request *cur;
1390 const uint8_t *inhdr;
1392 uint64_t search_message_id;
1393 uint64_t search_async_id;
1396 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1398 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1399 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1400 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1403 * we don't need the request anymore
1404 * cancel requests never have a response
1406 DLIST_REMOVE(req->sconn->smb2.requests, req);
1409 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1410 const uint8_t *outhdr;
1411 uint64_t message_id;
1414 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1416 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1417 async_id = BVAL(outhdr, SMB2_HDR_PID);
1419 if (flags & SMB2_HDR_FLAG_ASYNC) {
1420 if (search_async_id == async_id) {
1421 found_id = async_id;
1425 if (search_message_id == message_id) {
1426 found_id = message_id;
1432 if (cur && cur->subreq) {
1433 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1434 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1435 "cancel opcode[%s] mid %llu\n",
1436 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1437 (unsigned long long)found_id ));
1438 tevent_req_cancel(cur->subreq);
1441 return NT_STATUS_OK;
1444 /*************************************************************
1445 Ensure an incoming tid is a valid one for us to access.
1446 Change to the associated uid credentials and chdir to the
1447 valid tid directory.
1448 *************************************************************/
1450 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1452 const uint8_t *inhdr;
1455 struct smbXsrv_tcon *tcon;
1457 NTTIME now = timeval_to_nttime(&req->request_time);
1461 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1463 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1464 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1466 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1467 in_tid = req->last_tid;
1470 status = smb2srv_tcon_lookup(req->session,
1471 in_tid, now, &tcon);
1472 if (!NT_STATUS_IS_OK(status)) {
1476 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1477 return NT_STATUS_ACCESS_DENIED;
1480 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1481 if (!set_current_service(tcon->compat, 0, true)) {
1482 return NT_STATUS_ACCESS_DENIED;
1486 req->last_tid = in_tid;
1488 return NT_STATUS_OK;
1491 /*************************************************************
1492 Ensure an incoming session_id is a valid one for us to access.
1493 *************************************************************/
1495 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1497 const uint8_t *inhdr;
1500 uint64_t in_session_id;
1501 struct smbXsrv_session *session = NULL;
1502 struct auth_session_info *session_info;
1504 NTTIME now = timeval_to_nttime(&req->request_time);
1506 req->session = NULL;
1509 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1511 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1512 in_opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1513 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1515 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1516 in_session_id = req->last_session_id;
1519 /* lookup an existing session */
1520 status = smb2srv_session_lookup(req->sconn->conn,
1524 req->session = session;
1525 req->last_session_id = in_session_id;
1527 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1528 switch (in_opcode) {
1529 case SMB2_OP_SESSSETUP:
1530 status = NT_STATUS_OK;
1536 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1537 switch (in_opcode) {
1539 case SMB2_OP_CREATE:
1540 case SMB2_OP_GETINFO:
1541 case SMB2_OP_SETINFO:
1542 return NT_STATUS_INVALID_HANDLE;
1545 * Notice the check for
1546 * (session_info == NULL)
1549 status = NT_STATUS_OK;
1553 if (!NT_STATUS_IS_OK(status)) {
1557 session_info = session->global->auth_session_info;
1558 if (session_info == NULL) {
1559 return NT_STATUS_INVALID_HANDLE;
1562 set_current_user_info(session_info->unix_info->sanitized_username,
1563 session_info->unix_info->unix_name,
1564 session_info->info->domain_name);
1566 return NT_STATUS_OK;
1569 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1570 uint32_t data_length)
1572 uint16_t needed_charge;
1573 uint16_t credit_charge = 1;
1574 const uint8_t *inhdr;
1576 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1578 if (req->sconn->smb2.supports_multicredit) {
1579 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1580 credit_charge = MAX(credit_charge, 1);
1583 needed_charge = (data_length - 1)/ 65536 + 1;
1585 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1586 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1587 credit_charge, needed_charge));
1589 if (needed_charge > credit_charge) {
1590 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1591 credit_charge, needed_charge));
1592 return NT_STATUS_INVALID_PARAMETER;
1595 return NT_STATUS_OK;
1598 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1599 size_t expected_body_size)
1601 const uint8_t *inhdr;
1603 const uint8_t *inbody;
1604 int i = req->current_idx;
1606 size_t min_dyn_size = expected_body_size & 0x00000001;
1609 * The following should be checked already.
1611 if ((i+2) > req->in.vector_count) {
1612 return NT_STATUS_INTERNAL_ERROR;
1614 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1615 return NT_STATUS_INTERNAL_ERROR;
1617 if (req->in.vector[i+1].iov_len < 2) {
1618 return NT_STATUS_INTERNAL_ERROR;
1621 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1622 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1626 case SMB2_OP_GETINFO:
1632 * Now check the expected body size,
1633 * where the last byte might be in the
1636 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1637 return NT_STATUS_INVALID_PARAMETER;
1639 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1640 return NT_STATUS_INVALID_PARAMETER;
1643 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1645 body_size = SVAL(inbody, 0x00);
1646 if (body_size != expected_body_size) {
1647 return NT_STATUS_INVALID_PARAMETER;
1650 return NT_STATUS_OK;
1653 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1655 struct smbXsrv_connection *conn = req->sconn->conn;
1656 const struct smbd_smb2_dispatch_table *call = NULL;
1657 const uint8_t *inhdr;
1662 NTSTATUS session_status;
1663 uint32_t allowed_flags;
1664 NTSTATUS return_value;
1665 struct smbXsrv_session *x = NULL;
1666 bool signing_required = false;
1668 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1670 /* TODO: verify more things */
1672 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1673 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1674 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1675 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1676 smb2_opcode_name(opcode),
1677 (unsigned long long)mid));
1679 if (conn->protocol >= PROTOCOL_SMB2_02) {
1681 * once the protocol is negotiated
1682 * SMB2_OP_NEGPROT is not allowed anymore
1684 if (opcode == SMB2_OP_NEGPROT) {
1685 /* drop the connection */
1686 return NT_STATUS_INVALID_PARAMETER;
1690 * if the protocol is not negotiated yet
1691 * only SMB2_OP_NEGPROT is allowed.
1693 if (opcode != SMB2_OP_NEGPROT) {
1694 /* drop the connection */
1695 return NT_STATUS_INVALID_PARAMETER;
1699 call = smbd_smb2_call(opcode);
1701 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1704 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1705 SMB2_HDR_FLAG_SIGNED |
1707 if (opcode == SMB2_OP_CANCEL) {
1708 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1710 if ((flags & ~allowed_flags) != 0) {
1711 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1715 * Check if the client provided a valid session id,
1716 * if so smbd_smb2_request_check_session() calls
1717 * set_current_user_info().
1719 * As some command don't require a valid session id
1720 * we defer the check of the session_status
1722 session_status = smbd_smb2_request_check_session(req);
1726 signing_required = x->global->signing_required;
1728 if (opcode == SMB2_OP_SESSSETUP &&
1729 x->global->channels[0].signing_key.length) {
1730 signing_required = true;
1734 req->do_signing = false;
1735 if (flags & SMB2_HDR_FLAG_SIGNED) {
1736 DATA_BLOB signing_key;
1739 return smbd_smb2_request_error(
1740 req, NT_STATUS_ACCESS_DENIED);
1743 signing_key = x->global->channels[0].signing_key;
1745 if (!NT_STATUS_IS_OK(session_status)) {
1746 return smbd_smb2_request_error(req, session_status);
1749 req->do_signing = true;
1750 status = smb2_signing_check_pdu(signing_key,
1752 SMBD_SMB2_IN_HDR_IOV(req), 3);
1753 if (!NT_STATUS_IS_OK(status)) {
1754 return smbd_smb2_request_error(req, status);
1756 } else if (opcode == SMB2_OP_CANCEL) {
1757 /* Cancel requests are allowed to skip the signing */
1758 } else if (signing_required) {
1759 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1762 if (flags & SMB2_HDR_FLAG_CHAINED) {
1764 * This check is mostly for giving the correct error code
1765 * for compounded requests.
1767 * TODO: we may need to move this after the session
1770 if (!NT_STATUS_IS_OK(req->next_status)) {
1771 return smbd_smb2_request_error(req, req->next_status);
1774 req->compat_chain_fsp = NULL;
1777 if (req->compound_related) {
1778 req->sconn->smb2.compound_related_in_progress = true;
1781 if (call->need_session) {
1782 if (!NT_STATUS_IS_OK(session_status)) {
1783 return smbd_smb2_request_error(req, session_status);
1787 if (call->need_tcon) {
1788 SMB_ASSERT(call->need_session);
1791 * This call needs to be run as user.
1793 * smbd_smb2_request_check_tcon()
1794 * calls change_to_user() on success.
1796 status = smbd_smb2_request_check_tcon(req);
1797 if (!NT_STATUS_IS_OK(status)) {
1798 return smbd_smb2_request_error(req, status);
1803 case SMB2_OP_NEGPROT:
1804 /* This call needs to be run as root */
1805 change_to_root_user();
1808 START_PROFILE(smb2_negprot);
1809 return_value = smbd_smb2_request_process_negprot(req);
1810 END_PROFILE(smb2_negprot);
1814 case SMB2_OP_SESSSETUP:
1815 /* This call needs to be run as root */
1816 change_to_root_user();
1819 START_PROFILE(smb2_sesssetup);
1820 return_value = smbd_smb2_request_process_sesssetup(req);
1821 END_PROFILE(smb2_sesssetup);
1825 case SMB2_OP_LOGOFF:
1826 /* This call needs to be run as root */
1827 change_to_root_user();
1830 START_PROFILE(smb2_logoff);
1831 return_value = smbd_smb2_request_process_logoff(req);
1832 END_PROFILE(smb2_logoff);
1838 * This call needs to be run as root.
1840 * smbd_smb2_request_process_tcon()
1841 * calls make_connection_snum(), which will call
1842 * change_to_user(), when needed.
1844 change_to_root_user();
1847 START_PROFILE(smb2_tcon);
1848 return_value = smbd_smb2_request_process_tcon(req);
1849 END_PROFILE(smb2_tcon);
1854 /* This call needs to be run as root */
1855 change_to_root_user();
1858 START_PROFILE(smb2_tdis);
1859 return_value = smbd_smb2_request_process_tdis(req);
1860 END_PROFILE(smb2_tdis);
1864 case SMB2_OP_CREATE:
1866 START_PROFILE(smb2_create);
1867 return_value = smbd_smb2_request_process_create(req);
1868 END_PROFILE(smb2_create);
1874 START_PROFILE(smb2_close);
1875 return_value = smbd_smb2_request_process_close(req);
1876 END_PROFILE(smb2_close);
1882 START_PROFILE(smb2_flush);
1883 return_value = smbd_smb2_request_process_flush(req);
1884 END_PROFILE(smb2_flush);
1890 START_PROFILE(smb2_read);
1891 return_value = smbd_smb2_request_process_read(req);
1892 END_PROFILE(smb2_read);
1898 START_PROFILE(smb2_write);
1899 return_value = smbd_smb2_request_process_write(req);
1900 END_PROFILE(smb2_write);
1906 START_PROFILE(smb2_lock);
1907 return_value = smbd_smb2_request_process_lock(req);
1908 END_PROFILE(smb2_lock);
1914 START_PROFILE(smb2_ioctl);
1915 return_value = smbd_smb2_request_process_ioctl(req);
1916 END_PROFILE(smb2_ioctl);
1920 case SMB2_OP_CANCEL:
1922 * This call needs to be run as root
1924 * That is what we also do in the SMB1 case.
1926 change_to_root_user();
1929 START_PROFILE(smb2_cancel);
1930 return_value = smbd_smb2_request_process_cancel(req);
1931 END_PROFILE(smb2_cancel);
1935 case SMB2_OP_KEEPALIVE:
1936 /* This call needs to be run as root */
1937 change_to_root_user();
1940 START_PROFILE(smb2_keepalive);
1941 return_value = smbd_smb2_request_process_keepalive(req);
1942 END_PROFILE(smb2_keepalive);
1948 START_PROFILE(smb2_find);
1949 return_value = smbd_smb2_request_process_find(req);
1950 END_PROFILE(smb2_find);
1954 case SMB2_OP_NOTIFY:
1956 START_PROFILE(smb2_notify);
1957 return_value = smbd_smb2_request_process_notify(req);
1958 END_PROFILE(smb2_notify);
1962 case SMB2_OP_GETINFO:
1964 START_PROFILE(smb2_getinfo);
1965 return_value = smbd_smb2_request_process_getinfo(req);
1966 END_PROFILE(smb2_getinfo);
1970 case SMB2_OP_SETINFO:
1972 START_PROFILE(smb2_setinfo);
1973 return_value = smbd_smb2_request_process_setinfo(req);
1974 END_PROFILE(smb2_setinfo);
1980 START_PROFILE(smb2_break);
1981 return_value = smbd_smb2_request_process_break(req);
1982 END_PROFILE(smb2_break);
1987 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1990 return return_value;
1993 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1995 struct tevent_req *subreq;
1996 int i = req->current_idx;
1999 TALLOC_FREE(req->async_te);
2001 req->current_idx += 3;
2003 if (req->current_idx < req->out.vector_count) {
2005 * We must process the remaining compound
2006 * SMB2 requests before any new incoming SMB2
2007 * requests. This is because incoming SMB2
2008 * requests may include a cancel for a
2009 * compound request we haven't processed
2012 struct tevent_immediate *im = tevent_create_immediate(req);
2014 return NT_STATUS_NO_MEMORY;
2016 tevent_schedule_immediate(im,
2018 smbd_smb2_request_dispatch_immediate,
2020 return NT_STATUS_OK;
2023 if (req->compound_related) {
2024 req->sconn->smb2.compound_related_in_progress = false;
2027 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2029 /* Set credit for these operations (zero credits if this
2030 is a final reply for an async operation). */
2031 smb2_calculate_credits(req, req);
2033 if (req->do_signing) {
2035 struct smbXsrv_session *x = req->session;
2036 struct smbXsrv_connection *conn = x->connection;
2037 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2039 status = smb2_signing_sign_pdu(signing_key,
2041 &req->out.vector[i], 3);
2042 if (!NT_STATUS_IS_OK(status)) {
2047 if (DEBUGLEVEL >= 10) {
2048 dbgtext("smbd_smb2_request_reply: sending...\n");
2049 print_req_vectors(req);
2052 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2053 if (req->out.vector_count == 4 &&
2054 req->out.vector[3].iov_base == NULL &&
2055 req->out.vector[3].iov_len != 0) {
2056 /* Dynamic part is NULL. Chop it off,
2057 We're going to send it via sendfile. */
2058 req->out.vector_count -= 1;
2061 subreq = tstream_writev_queue_send(req,
2063 req->sconn->smb2.stream,
2064 req->sconn->smb2.send_queue,
2066 req->out.vector_count);
2067 if (subreq == NULL) {
2068 return NT_STATUS_NO_MEMORY;
2070 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
2072 * We're done with this request -
2073 * move it off the "being processed" queue.
2075 DLIST_REMOVE(req->sconn->smb2.requests, req);
2077 return NT_STATUS_OK;
2080 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2082 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2083 struct tevent_immediate *im,
2086 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2087 struct smbd_smb2_request);
2088 struct smbd_server_connection *sconn = req->sconn;
2093 if (DEBUGLEVEL >= 10) {
2094 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2095 req->current_idx, req->in.vector_count));
2096 print_req_vectors(req);
2099 status = smbd_smb2_request_dispatch(req);
2100 if (!NT_STATUS_IS_OK(status)) {
2101 smbd_server_connection_terminate(sconn, nt_errstr(status));
2105 status = smbd_smb2_request_next_incoming(sconn);
2106 if (!NT_STATUS_IS_OK(status)) {
2107 smbd_server_connection_terminate(sconn, nt_errstr(status));
2112 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
2114 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
2115 struct smbd_smb2_request);
2116 struct smbd_server_connection *sconn = req->sconn;
2121 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2122 TALLOC_FREE(subreq);
2125 status = map_nt_error_from_unix(sys_errno);
2126 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2127 nt_errstr(status)));
2128 smbd_server_connection_terminate(sconn, nt_errstr(status));
2132 status = smbd_smb2_request_next_incoming(sconn);
2133 if (!NT_STATUS_IS_OK(status)) {
2134 smbd_server_connection_terminate(sconn, nt_errstr(status));
2139 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2141 DATA_BLOB body, DATA_BLOB *dyn,
2142 const char *location)
2145 int i = req->current_idx;
2146 uint32_t next_command_ofs;
2148 DEBUG(10,("smbd_smb2_request_done_ex: "
2149 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2150 i, nt_errstr(status), (unsigned int)body.length,
2152 (unsigned int)(dyn ? dyn->length : 0),
2155 if (body.length < 2) {
2156 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2159 if ((body.length % 2) != 0) {
2160 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2163 outhdr = (uint8_t *)req->out.vector[i].iov_base;
2165 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2166 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2168 req->out.vector[i+1].iov_base = (void *)body.data;
2169 req->out.vector[i+1].iov_len = body.length;
2172 req->out.vector[i+2].iov_base = (void *)dyn->data;
2173 req->out.vector[i+2].iov_len = dyn->length;
2175 req->out.vector[i+2].iov_base = NULL;
2176 req->out.vector[i+2].iov_len = 0;
2179 /* see if we need to recalculate the offset to the next response */
2180 if (next_command_ofs > 0) {
2181 next_command_ofs = SMB2_HDR_BODY;
2182 next_command_ofs += req->out.vector[i+1].iov_len;
2183 next_command_ofs += req->out.vector[i+2].iov_len;
2186 if ((next_command_ofs % 8) != 0) {
2187 size_t pad_size = 8 - (next_command_ofs % 8);
2188 if (req->out.vector[i+2].iov_len == 0) {
2190 * if the dyn buffer is empty
2191 * we can use it to add padding
2195 pad = talloc_zero_array(req->out.vector,
2198 return smbd_smb2_request_error(req,
2199 NT_STATUS_NO_MEMORY);
2202 req->out.vector[i+2].iov_base = (void *)pad;
2203 req->out.vector[i+2].iov_len = pad_size;
2206 * For now we copy the dynamic buffer
2207 * and add the padding to the new buffer
2214 old_size = req->out.vector[i+2].iov_len;
2215 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2217 new_size = old_size + pad_size;
2218 new_dyn = talloc_zero_array(req->out.vector,
2220 if (new_dyn == NULL) {
2221 return smbd_smb2_request_error(req,
2222 NT_STATUS_NO_MEMORY);
2225 memcpy(new_dyn, old_dyn, old_size);
2226 memset(new_dyn + old_size, 0, pad_size);
2228 req->out.vector[i+2].iov_base = (void *)new_dyn;
2229 req->out.vector[i+2].iov_len = new_size;
2231 next_command_ofs += pad_size;
2234 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2236 return smbd_smb2_request_reply(req);
2239 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2242 const char *location)
2245 int i = req->current_idx;
2246 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2248 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2249 i, nt_errstr(status), info ? " +info" : "",
2252 body.data = outhdr + SMB2_HDR_BODY;
2254 SSVAL(body.data, 0, 9);
2257 SIVAL(body.data, 0x04, info->length);
2259 /* Allocated size of req->out.vector[i].iov_base
2260 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2261 * 1 byte without having to do an alloc.
2263 info = talloc_zero_array(req->out.vector,
2267 return NT_STATUS_NO_MEMORY;
2269 info->data = ((uint8_t *)outhdr) +
2270 OUTVEC_ALLOC_SIZE - 1;
2272 SCVAL(info->data, 0, 0);
2276 * if a request fails, all other remaining
2277 * compounded requests should fail too
2279 req->next_status = NT_STATUS_INVALID_PARAMETER;
2281 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2285 struct smbd_smb2_send_oplock_break_state {
2286 struct smbd_server_connection *sconn;
2287 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2288 struct iovec vector;
2291 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2293 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2294 uint64_t file_id_persistent,
2295 uint64_t file_id_volatile,
2296 uint8_t oplock_level)
2298 struct smbd_smb2_send_oplock_break_state *state;
2299 struct tevent_req *subreq;
2303 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2304 if (state == NULL) {
2305 return NT_STATUS_NO_MEMORY;
2307 state->sconn = sconn;
2309 state->vector.iov_base = (void *)state->buf;
2310 state->vector.iov_len = sizeof(state->buf);
2312 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2313 hdr = state->buf + 4;
2314 body = hdr + SMB2_HDR_BODY;
2316 SIVAL(hdr, 0, SMB2_MAGIC);
2317 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2318 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2319 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2320 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2321 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2322 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2323 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2324 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2325 SIVAL(hdr, SMB2_HDR_PID, 0);
2326 SIVAL(hdr, SMB2_HDR_TID, 0);
2327 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2328 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2330 SSVAL(body, 0x00, 0x18);
2332 SCVAL(body, 0x02, oplock_level);
2333 SCVAL(body, 0x03, 0); /* reserved */
2334 SIVAL(body, 0x04, 0); /* reserved */
2335 SBVAL(body, 0x08, file_id_persistent);
2336 SBVAL(body, 0x10, file_id_volatile);
2338 subreq = tstream_writev_queue_send(state,
2341 sconn->smb2.send_queue,
2343 if (subreq == NULL) {
2344 return NT_STATUS_NO_MEMORY;
2346 tevent_req_set_callback(subreq,
2347 smbd_smb2_oplock_break_writev_done,
2350 return NT_STATUS_OK;
2353 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2355 struct smbd_smb2_send_oplock_break_state *state =
2356 tevent_req_callback_data(subreq,
2357 struct smbd_smb2_send_oplock_break_state);
2358 struct smbd_server_connection *sconn = state->sconn;
2362 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2363 TALLOC_FREE(subreq);
2365 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2366 smbd_server_connection_terminate(sconn, nt_errstr(status));
2373 struct smbd_smb2_request_read_state {
2374 struct tevent_context *ev;
2375 struct smbd_server_connection *sconn;
2376 struct smbd_smb2_request *smb2_req;
2378 uint8_t nbt[NBT_HDR_SIZE];
2385 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2387 TALLOC_CTX *mem_ctx,
2388 struct iovec **_vector,
2390 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2392 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2393 struct tevent_context *ev,
2394 struct smbd_server_connection *sconn)
2396 struct tevent_req *req;
2397 struct smbd_smb2_request_read_state *state;
2398 struct tevent_req *subreq;
2400 req = tevent_req_create(mem_ctx, &state,
2401 struct smbd_smb2_request_read_state);
2406 state->sconn = sconn;
2408 state->smb2_req = smbd_smb2_request_allocate(state);
2409 if (tevent_req_nomem(state->smb2_req, req)) {
2410 return tevent_req_post(req, ev);
2412 state->smb2_req->sconn = sconn;
2414 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
2416 state->sconn->smb2.stream,
2417 state->sconn->smb2.recv_queue,
2418 smbd_smb2_request_next_vector,
2420 if (tevent_req_nomem(subreq, req)) {
2421 return tevent_req_post(req, ev);
2423 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2428 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2430 TALLOC_CTX *mem_ctx,
2431 struct iovec **_vector,
2434 struct smbd_smb2_request_read_state *state =
2435 talloc_get_type_abort(private_data,
2436 struct smbd_smb2_request_read_state);
2437 struct iovec *vector;
2439 if (state->pktlen > 0) {
2440 /* if there're no remaining bytes, we're done */
2446 if (!state->hdr.done) {
2448 * first we need to get the NBT header
2450 vector = talloc_array(mem_ctx, struct iovec, 1);
2451 if (vector == NULL) {
2455 vector[0].iov_base = (void *)state->hdr.nbt;
2456 vector[0].iov_len = NBT_HDR_SIZE;
2461 state->hdr.done = true;
2466 * Now we analyze the NBT header
2468 state->pktlen = smb2_len(state->hdr.nbt);
2470 if (state->pktlen == 0) {
2471 /* if there're no remaining bytes, we're done */
2477 state->pktbuf = talloc_array(state->smb2_req, uint8_t, state->pktlen);
2478 if (state->pktbuf == NULL) {
2482 vector = talloc_array(mem_ctx, struct iovec, 1);
2483 if (vector == NULL) {
2487 vector[0].iov_base = (void *)state->pktbuf;
2488 vector[0].iov_len = state->pktlen;
2495 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2497 struct tevent_req *req =
2498 tevent_req_callback_data(subreq,
2500 struct smbd_smb2_request_read_state *state =
2501 tevent_req_data(req,
2502 struct smbd_smb2_request_read_state);
2508 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2509 TALLOC_FREE(subreq);
2511 status = map_nt_error_from_unix(sys_errno);
2512 tevent_req_nterror(req, status);
2516 if (state->hdr.nbt[0] != 0x00) {
2517 DEBUG(1,("smbd_smb2_request_read_done: ignore NBT[0x%02X] msg\n",
2518 state->hdr.nbt[0]));
2520 ZERO_STRUCT(state->hdr);
2521 TALLOC_FREE(state->pktbuf);
2524 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
2526 state->sconn->smb2.stream,
2527 state->sconn->smb2.recv_queue,
2528 smbd_smb2_request_next_vector,
2530 if (tevent_req_nomem(subreq, req)) {
2533 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2537 state->smb2_req->request_time = timeval_current();
2538 now = timeval_to_nttime(&state->smb2_req->request_time);
2540 status = smbd_smb2_inbuf_parse_compound(state->smb2_req->sconn->conn,
2545 &state->smb2_req->in.vector,
2546 &state->smb2_req->in.vector_count);
2547 if (tevent_req_nterror(req, status)) {
2551 state->smb2_req->current_idx = 1;
2553 tevent_req_done(req);
2556 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2557 TALLOC_CTX *mem_ctx,
2558 struct smbd_smb2_request **_smb2_req)
2560 struct smbd_smb2_request_read_state *state =
2561 tevent_req_data(req,
2562 struct smbd_smb2_request_read_state);
2565 if (tevent_req_is_nterror(req, &status)) {
2566 tevent_req_received(req);
2570 *_smb2_req = talloc_move(mem_ctx, &state->smb2_req);
2571 tevent_req_received(req);
2572 return NT_STATUS_OK;
2575 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2577 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2579 size_t max_send_queue_len;
2580 size_t cur_send_queue_len;
2581 struct tevent_req *subreq;
2583 if (sconn->smb2.compound_related_in_progress) {
2585 * Can't read another until the related
2588 return NT_STATUS_OK;
2591 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2593 * if there is already a smbd_smb2_request_read
2594 * pending, we are done.
2596 return NT_STATUS_OK;
2599 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2600 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2602 if (cur_send_queue_len > max_send_queue_len) {
2604 * if we have a lot of requests to send,
2605 * we wait until they are on the wire until we
2606 * ask for the next request.
2608 return NT_STATUS_OK;
2611 /* ask for the next request */
2612 subreq = smbd_smb2_request_read_send(sconn, sconn->ev_ctx, sconn);
2613 if (subreq == NULL) {
2614 return NT_STATUS_NO_MEMORY;
2616 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2618 return NT_STATUS_OK;
2621 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2622 uint8_t *inbuf, size_t size)
2625 struct smbd_smb2_request *req = NULL;
2627 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2628 (unsigned int)size));
2630 status = smbd_initialize_smb2(sconn);
2631 if (!NT_STATUS_IS_OK(status)) {
2632 smbd_server_connection_terminate(sconn, nt_errstr(status));
2636 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2637 if (!NT_STATUS_IS_OK(status)) {
2638 smbd_server_connection_terminate(sconn, nt_errstr(status));
2642 status = smbd_smb2_request_validate(req);
2643 if (!NT_STATUS_IS_OK(status)) {
2644 smbd_server_connection_terminate(sconn, nt_errstr(status));
2648 status = smbd_smb2_request_setup_out(req);
2649 if (!NT_STATUS_IS_OK(status)) {
2650 smbd_server_connection_terminate(sconn, nt_errstr(status));
2654 status = smbd_smb2_request_dispatch(req);
2655 if (!NT_STATUS_IS_OK(status)) {
2656 smbd_server_connection_terminate(sconn, nt_errstr(status));
2660 status = smbd_smb2_request_next_incoming(sconn);
2661 if (!NT_STATUS_IS_OK(status)) {
2662 smbd_server_connection_terminate(sconn, nt_errstr(status));
2666 sconn->num_requests++;
2669 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2671 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2672 struct smbd_server_connection);
2674 struct smbd_smb2_request *req = NULL;
2676 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2677 TALLOC_FREE(subreq);
2678 if (!NT_STATUS_IS_OK(status)) {
2679 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2680 nt_errstr(status)));
2681 smbd_server_connection_terminate(sconn, nt_errstr(status));
2685 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2686 req->current_idx, req->in.vector_count));
2688 status = smbd_smb2_request_validate(req);
2689 if (!NT_STATUS_IS_OK(status)) {
2690 smbd_server_connection_terminate(sconn, nt_errstr(status));
2694 status = smbd_smb2_request_setup_out(req);
2695 if (!NT_STATUS_IS_OK(status)) {
2696 smbd_server_connection_terminate(sconn, nt_errstr(status));
2700 status = smbd_smb2_request_dispatch(req);
2701 if (!NT_STATUS_IS_OK(status)) {
2702 smbd_server_connection_terminate(sconn, nt_errstr(status));
2706 status = smbd_smb2_request_next_incoming(sconn);
2707 if (!NT_STATUS_IS_OK(status)) {
2708 smbd_server_connection_terminate(sconn, nt_errstr(status));
2712 sconn->num_requests++;
2714 /* The timeout_processing function isn't run nearly
2715 often enough to implement 'max log size' without
2716 overrunning the size of the file by many megabytes.
2717 This is especially true if we are running at debug
2718 level 10. Checking every 50 SMB2s is a nice
2719 tradeoff of performance vs log file size overrun. */
2721 if ((sconn->num_requests % 50) == 0 &&
2722 need_to_check_log_size()) {
2723 change_to_root_user();