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;
1782 case SMB2_OP_NEGPROT:
1783 /* This call needs to be run as root */
1784 change_to_root_user();
1787 START_PROFILE(smb2_negprot);
1788 return_value = smbd_smb2_request_process_negprot(req);
1789 END_PROFILE(smb2_negprot);
1793 case SMB2_OP_SESSSETUP:
1794 /* This call needs to be run as root */
1795 change_to_root_user();
1798 START_PROFILE(smb2_sesssetup);
1799 return_value = smbd_smb2_request_process_sesssetup(req);
1800 END_PROFILE(smb2_sesssetup);
1804 case SMB2_OP_LOGOFF:
1805 if (!NT_STATUS_IS_OK(session_status)) {
1806 return_value = smbd_smb2_request_error(req, session_status);
1810 /* This call needs to be run as root */
1811 change_to_root_user();
1814 START_PROFILE(smb2_logoff);
1815 return_value = smbd_smb2_request_process_logoff(req);
1816 END_PROFILE(smb2_logoff);
1821 if (!NT_STATUS_IS_OK(session_status)) {
1822 return_value = smbd_smb2_request_error(req, session_status);
1827 * This call needs to be run as root.
1829 * smbd_smb2_request_process_tcon()
1830 * calls make_connection_snum(), which will call
1831 * change_to_user(), when needed.
1833 change_to_root_user();
1836 START_PROFILE(smb2_tcon);
1837 return_value = smbd_smb2_request_process_tcon(req);
1838 END_PROFILE(smb2_tcon);
1843 if (!NT_STATUS_IS_OK(session_status)) {
1844 return_value = smbd_smb2_request_error(req, session_status);
1848 * This call needs to be run as user.
1850 * smbd_smb2_request_check_tcon()
1851 * calls change_to_user() on success.
1853 status = smbd_smb2_request_check_tcon(req);
1854 if (!NT_STATUS_IS_OK(status)) {
1855 return_value = smbd_smb2_request_error(req, status);
1858 /* This call needs to be run as root */
1859 change_to_root_user();
1863 START_PROFILE(smb2_tdis);
1864 return_value = smbd_smb2_request_process_tdis(req);
1865 END_PROFILE(smb2_tdis);
1869 case SMB2_OP_CREATE:
1870 if (!NT_STATUS_IS_OK(session_status)) {
1871 return_value = smbd_smb2_request_error(req, session_status);
1875 * This call needs to be run as user.
1877 * smbd_smb2_request_check_tcon()
1878 * calls change_to_user() on success.
1880 status = smbd_smb2_request_check_tcon(req);
1881 if (!NT_STATUS_IS_OK(status)) {
1882 return_value = smbd_smb2_request_error(req, status);
1887 START_PROFILE(smb2_create);
1888 return_value = smbd_smb2_request_process_create(req);
1889 END_PROFILE(smb2_create);
1894 if (!NT_STATUS_IS_OK(session_status)) {
1895 return_value = smbd_smb2_request_error(req, session_status);
1899 * This call needs to be run as user.
1901 * smbd_smb2_request_check_tcon()
1902 * calls change_to_user() on success.
1904 status = smbd_smb2_request_check_tcon(req);
1905 if (!NT_STATUS_IS_OK(status)) {
1906 return_value = smbd_smb2_request_error(req, status);
1911 START_PROFILE(smb2_close);
1912 return_value = smbd_smb2_request_process_close(req);
1913 END_PROFILE(smb2_close);
1918 if (!NT_STATUS_IS_OK(session_status)) {
1919 return_value = smbd_smb2_request_error(req, session_status);
1923 * This call needs to be run as user.
1925 * smbd_smb2_request_check_tcon()
1926 * calls change_to_user() on success.
1928 status = smbd_smb2_request_check_tcon(req);
1929 if (!NT_STATUS_IS_OK(status)) {
1930 return_value = smbd_smb2_request_error(req, status);
1935 START_PROFILE(smb2_flush);
1936 return_value = smbd_smb2_request_process_flush(req);
1937 END_PROFILE(smb2_flush);
1942 if (!NT_STATUS_IS_OK(session_status)) {
1943 return_value = smbd_smb2_request_error(req, session_status);
1947 * This call needs to be run as user.
1949 * smbd_smb2_request_check_tcon()
1950 * calls change_to_user() on success.
1952 status = smbd_smb2_request_check_tcon(req);
1953 if (!NT_STATUS_IS_OK(status)) {
1954 return_value = smbd_smb2_request_error(req, status);
1959 START_PROFILE(smb2_read);
1960 return_value = smbd_smb2_request_process_read(req);
1961 END_PROFILE(smb2_read);
1966 if (!NT_STATUS_IS_OK(session_status)) {
1967 return_value = smbd_smb2_request_error(req, session_status);
1971 * This call needs to be run as user.
1973 * smbd_smb2_request_check_tcon()
1974 * calls change_to_user() on success.
1976 status = smbd_smb2_request_check_tcon(req);
1977 if (!NT_STATUS_IS_OK(status)) {
1978 return_value = smbd_smb2_request_error(req, status);
1983 START_PROFILE(smb2_write);
1984 return_value = smbd_smb2_request_process_write(req);
1985 END_PROFILE(smb2_write);
1990 if (!NT_STATUS_IS_OK(session_status)) {
1991 /* Too ugly to live ? JRA. */
1992 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1993 session_status = NT_STATUS_FILE_CLOSED;
1995 return_value = smbd_smb2_request_error(req, session_status);
1999 * This call needs to be run as user.
2001 * smbd_smb2_request_check_tcon()
2002 * calls change_to_user() on success.
2004 status = smbd_smb2_request_check_tcon(req);
2005 if (!NT_STATUS_IS_OK(status)) {
2006 /* Too ugly to live ? JRA. */
2007 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
2008 status = NT_STATUS_FILE_CLOSED;
2010 return_value = smbd_smb2_request_error(req, status);
2015 START_PROFILE(smb2_lock);
2016 return_value = smbd_smb2_request_process_lock(req);
2017 END_PROFILE(smb2_lock);
2022 if (!NT_STATUS_IS_OK(session_status)) {
2023 return_value = smbd_smb2_request_error(req, session_status);
2027 * This call needs to be run as user.
2029 * smbd_smb2_request_check_tcon()
2030 * calls change_to_user() on success.
2032 status = smbd_smb2_request_check_tcon(req);
2033 if (!NT_STATUS_IS_OK(status)) {
2034 return_value = smbd_smb2_request_error(req, status);
2039 START_PROFILE(smb2_ioctl);
2040 return_value = smbd_smb2_request_process_ioctl(req);
2041 END_PROFILE(smb2_ioctl);
2045 case SMB2_OP_CANCEL:
2047 * This call needs to be run as root
2049 * That is what we also do in the SMB1 case.
2051 change_to_root_user();
2054 START_PROFILE(smb2_cancel);
2055 return_value = smbd_smb2_request_process_cancel(req);
2056 END_PROFILE(smb2_cancel);
2060 case SMB2_OP_KEEPALIVE:
2061 /* This call needs to be run as root */
2062 change_to_root_user();
2065 START_PROFILE(smb2_keepalive);
2066 return_value = smbd_smb2_request_process_keepalive(req);
2067 END_PROFILE(smb2_keepalive);
2072 if (!NT_STATUS_IS_OK(session_status)) {
2073 return_value = smbd_smb2_request_error(req, session_status);
2077 * This call needs to be run as user.
2079 * smbd_smb2_request_check_tcon()
2080 * calls change_to_user() on success.
2082 status = smbd_smb2_request_check_tcon(req);
2083 if (!NT_STATUS_IS_OK(status)) {
2084 return_value = smbd_smb2_request_error(req, status);
2089 START_PROFILE(smb2_find);
2090 return_value = smbd_smb2_request_process_find(req);
2091 END_PROFILE(smb2_find);
2095 case SMB2_OP_NOTIFY:
2096 if (!NT_STATUS_IS_OK(session_status)) {
2097 return_value = smbd_smb2_request_error(req, session_status);
2101 * This call needs to be run as user.
2103 * smbd_smb2_request_check_tcon()
2104 * calls change_to_user() on success.
2106 status = smbd_smb2_request_check_tcon(req);
2107 if (!NT_STATUS_IS_OK(status)) {
2108 return_value = smbd_smb2_request_error(req, status);
2113 START_PROFILE(smb2_notify);
2114 return_value = smbd_smb2_request_process_notify(req);
2115 END_PROFILE(smb2_notify);
2119 case SMB2_OP_GETINFO:
2120 if (!NT_STATUS_IS_OK(session_status)) {
2121 return_value = smbd_smb2_request_error(req, session_status);
2125 * This call needs to be run as user.
2127 * smbd_smb2_request_check_tcon()
2128 * calls change_to_user() on success.
2130 status = smbd_smb2_request_check_tcon(req);
2131 if (!NT_STATUS_IS_OK(status)) {
2132 return_value = smbd_smb2_request_error(req, status);
2137 START_PROFILE(smb2_getinfo);
2138 return_value = smbd_smb2_request_process_getinfo(req);
2139 END_PROFILE(smb2_getinfo);
2143 case SMB2_OP_SETINFO:
2144 if (!NT_STATUS_IS_OK(session_status)) {
2145 return_value = smbd_smb2_request_error(req, session_status);
2149 * This call needs to be run as user.
2151 * smbd_smb2_request_check_tcon()
2152 * calls change_to_user() on success.
2154 status = smbd_smb2_request_check_tcon(req);
2155 if (!NT_STATUS_IS_OK(status)) {
2156 return_value = smbd_smb2_request_error(req, status);
2161 START_PROFILE(smb2_setinfo);
2162 return_value = smbd_smb2_request_process_setinfo(req);
2163 END_PROFILE(smb2_setinfo);
2168 if (!NT_STATUS_IS_OK(session_status)) {
2169 return_value = smbd_smb2_request_error(req, session_status);
2173 * This call needs to be run as user.
2175 * smbd_smb2_request_check_tcon()
2176 * calls change_to_user() on success.
2178 status = smbd_smb2_request_check_tcon(req);
2179 if (!NT_STATUS_IS_OK(status)) {
2180 return_value = smbd_smb2_request_error(req, status);
2185 START_PROFILE(smb2_break);
2186 return_value = smbd_smb2_request_process_break(req);
2187 END_PROFILE(smb2_break);
2192 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2195 return return_value;
2198 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2200 struct tevent_req *subreq;
2201 int i = req->current_idx;
2204 TALLOC_FREE(req->async_te);
2206 req->current_idx += 3;
2208 if (req->current_idx < req->out.vector_count) {
2210 * We must process the remaining compound
2211 * SMB2 requests before any new incoming SMB2
2212 * requests. This is because incoming SMB2
2213 * requests may include a cancel for a
2214 * compound request we haven't processed
2217 struct tevent_immediate *im = tevent_create_immediate(req);
2219 return NT_STATUS_NO_MEMORY;
2221 tevent_schedule_immediate(im,
2223 smbd_smb2_request_dispatch_immediate,
2225 return NT_STATUS_OK;
2228 if (req->compound_related) {
2229 req->sconn->smb2.compound_related_in_progress = false;
2232 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2234 /* Set credit for these operations (zero credits if this
2235 is a final reply for an async operation). */
2236 smb2_calculate_credits(req, req);
2238 if (req->do_signing) {
2240 struct smbXsrv_session *x = req->session;
2241 struct smbXsrv_connection *conn = x->connection;
2242 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2244 status = smb2_signing_sign_pdu(signing_key,
2246 &req->out.vector[i], 3);
2247 if (!NT_STATUS_IS_OK(status)) {
2252 if (DEBUGLEVEL >= 10) {
2253 dbgtext("smbd_smb2_request_reply: sending...\n");
2254 print_req_vectors(req);
2257 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2258 if (req->out.vector_count == 4 &&
2259 req->out.vector[3].iov_base == NULL &&
2260 req->out.vector[3].iov_len != 0) {
2261 /* Dynamic part is NULL. Chop it off,
2262 We're going to send it via sendfile. */
2263 req->out.vector_count -= 1;
2266 subreq = tstream_writev_queue_send(req,
2268 req->sconn->smb2.stream,
2269 req->sconn->smb2.send_queue,
2271 req->out.vector_count);
2272 if (subreq == NULL) {
2273 return NT_STATUS_NO_MEMORY;
2275 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
2277 * We're done with this request -
2278 * move it off the "being processed" queue.
2280 DLIST_REMOVE(req->sconn->smb2.requests, req);
2282 return NT_STATUS_OK;
2285 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2287 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2288 struct tevent_immediate *im,
2291 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2292 struct smbd_smb2_request);
2293 struct smbd_server_connection *sconn = req->sconn;
2298 if (DEBUGLEVEL >= 10) {
2299 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2300 req->current_idx, req->in.vector_count));
2301 print_req_vectors(req);
2304 status = smbd_smb2_request_dispatch(req);
2305 if (!NT_STATUS_IS_OK(status)) {
2306 smbd_server_connection_terminate(sconn, nt_errstr(status));
2310 status = smbd_smb2_request_next_incoming(sconn);
2311 if (!NT_STATUS_IS_OK(status)) {
2312 smbd_server_connection_terminate(sconn, nt_errstr(status));
2317 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
2319 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
2320 struct smbd_smb2_request);
2321 struct smbd_server_connection *sconn = req->sconn;
2326 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2327 TALLOC_FREE(subreq);
2330 status = map_nt_error_from_unix(sys_errno);
2331 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2332 nt_errstr(status)));
2333 smbd_server_connection_terminate(sconn, nt_errstr(status));
2337 status = smbd_smb2_request_next_incoming(sconn);
2338 if (!NT_STATUS_IS_OK(status)) {
2339 smbd_server_connection_terminate(sconn, nt_errstr(status));
2344 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2346 DATA_BLOB body, DATA_BLOB *dyn,
2347 const char *location)
2350 int i = req->current_idx;
2351 uint32_t next_command_ofs;
2353 DEBUG(10,("smbd_smb2_request_done_ex: "
2354 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2355 i, nt_errstr(status), (unsigned int)body.length,
2357 (unsigned int)(dyn ? dyn->length : 0),
2360 if (body.length < 2) {
2361 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2364 if ((body.length % 2) != 0) {
2365 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2368 outhdr = (uint8_t *)req->out.vector[i].iov_base;
2370 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2371 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2373 req->out.vector[i+1].iov_base = (void *)body.data;
2374 req->out.vector[i+1].iov_len = body.length;
2377 req->out.vector[i+2].iov_base = (void *)dyn->data;
2378 req->out.vector[i+2].iov_len = dyn->length;
2380 req->out.vector[i+2].iov_base = NULL;
2381 req->out.vector[i+2].iov_len = 0;
2384 /* see if we need to recalculate the offset to the next response */
2385 if (next_command_ofs > 0) {
2386 next_command_ofs = SMB2_HDR_BODY;
2387 next_command_ofs += req->out.vector[i+1].iov_len;
2388 next_command_ofs += req->out.vector[i+2].iov_len;
2391 if ((next_command_ofs % 8) != 0) {
2392 size_t pad_size = 8 - (next_command_ofs % 8);
2393 if (req->out.vector[i+2].iov_len == 0) {
2395 * if the dyn buffer is empty
2396 * we can use it to add padding
2400 pad = talloc_zero_array(req->out.vector,
2403 return smbd_smb2_request_error(req,
2404 NT_STATUS_NO_MEMORY);
2407 req->out.vector[i+2].iov_base = (void *)pad;
2408 req->out.vector[i+2].iov_len = pad_size;
2411 * For now we copy the dynamic buffer
2412 * and add the padding to the new buffer
2419 old_size = req->out.vector[i+2].iov_len;
2420 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2422 new_size = old_size + pad_size;
2423 new_dyn = talloc_zero_array(req->out.vector,
2425 if (new_dyn == NULL) {
2426 return smbd_smb2_request_error(req,
2427 NT_STATUS_NO_MEMORY);
2430 memcpy(new_dyn, old_dyn, old_size);
2431 memset(new_dyn + old_size, 0, pad_size);
2433 req->out.vector[i+2].iov_base = (void *)new_dyn;
2434 req->out.vector[i+2].iov_len = new_size;
2436 next_command_ofs += pad_size;
2439 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2441 return smbd_smb2_request_reply(req);
2444 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2447 const char *location)
2450 int i = req->current_idx;
2451 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2453 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2454 i, nt_errstr(status), info ? " +info" : "",
2457 body.data = outhdr + SMB2_HDR_BODY;
2459 SSVAL(body.data, 0, 9);
2462 SIVAL(body.data, 0x04, info->length);
2464 /* Allocated size of req->out.vector[i].iov_base
2465 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2466 * 1 byte without having to do an alloc.
2468 info = talloc_zero_array(req->out.vector,
2472 return NT_STATUS_NO_MEMORY;
2474 info->data = ((uint8_t *)outhdr) +
2475 OUTVEC_ALLOC_SIZE - 1;
2477 SCVAL(info->data, 0, 0);
2481 * if a request fails, all other remaining
2482 * compounded requests should fail too
2484 req->next_status = NT_STATUS_INVALID_PARAMETER;
2486 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2490 struct smbd_smb2_send_oplock_break_state {
2491 struct smbd_server_connection *sconn;
2492 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2493 struct iovec vector;
2496 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2498 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2499 uint64_t file_id_persistent,
2500 uint64_t file_id_volatile,
2501 uint8_t oplock_level)
2503 struct smbd_smb2_send_oplock_break_state *state;
2504 struct tevent_req *subreq;
2508 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2509 if (state == NULL) {
2510 return NT_STATUS_NO_MEMORY;
2512 state->sconn = sconn;
2514 state->vector.iov_base = (void *)state->buf;
2515 state->vector.iov_len = sizeof(state->buf);
2517 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2518 hdr = state->buf + 4;
2519 body = hdr + SMB2_HDR_BODY;
2521 SIVAL(hdr, 0, SMB2_MAGIC);
2522 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2523 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2524 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2525 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2526 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2527 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2528 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2529 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2530 SIVAL(hdr, SMB2_HDR_PID, 0);
2531 SIVAL(hdr, SMB2_HDR_TID, 0);
2532 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2533 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2535 SSVAL(body, 0x00, 0x18);
2537 SCVAL(body, 0x02, oplock_level);
2538 SCVAL(body, 0x03, 0); /* reserved */
2539 SIVAL(body, 0x04, 0); /* reserved */
2540 SBVAL(body, 0x08, file_id_persistent);
2541 SBVAL(body, 0x10, file_id_volatile);
2543 subreq = tstream_writev_queue_send(state,
2546 sconn->smb2.send_queue,
2548 if (subreq == NULL) {
2549 return NT_STATUS_NO_MEMORY;
2551 tevent_req_set_callback(subreq,
2552 smbd_smb2_oplock_break_writev_done,
2555 return NT_STATUS_OK;
2558 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2560 struct smbd_smb2_send_oplock_break_state *state =
2561 tevent_req_callback_data(subreq,
2562 struct smbd_smb2_send_oplock_break_state);
2563 struct smbd_server_connection *sconn = state->sconn;
2567 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2568 TALLOC_FREE(subreq);
2570 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2571 smbd_server_connection_terminate(sconn, nt_errstr(status));
2578 struct smbd_smb2_request_read_state {
2579 struct tevent_context *ev;
2580 struct smbd_server_connection *sconn;
2581 struct smbd_smb2_request *smb2_req;
2583 uint8_t nbt[NBT_HDR_SIZE];
2590 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2592 TALLOC_CTX *mem_ctx,
2593 struct iovec **_vector,
2595 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2597 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2598 struct tevent_context *ev,
2599 struct smbd_server_connection *sconn)
2601 struct tevent_req *req;
2602 struct smbd_smb2_request_read_state *state;
2603 struct tevent_req *subreq;
2605 req = tevent_req_create(mem_ctx, &state,
2606 struct smbd_smb2_request_read_state);
2611 state->sconn = sconn;
2613 state->smb2_req = smbd_smb2_request_allocate(state);
2614 if (tevent_req_nomem(state->smb2_req, req)) {
2615 return tevent_req_post(req, ev);
2617 state->smb2_req->sconn = sconn;
2619 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
2621 state->sconn->smb2.stream,
2622 state->sconn->smb2.recv_queue,
2623 smbd_smb2_request_next_vector,
2625 if (tevent_req_nomem(subreq, req)) {
2626 return tevent_req_post(req, ev);
2628 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2633 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2635 TALLOC_CTX *mem_ctx,
2636 struct iovec **_vector,
2639 struct smbd_smb2_request_read_state *state =
2640 talloc_get_type_abort(private_data,
2641 struct smbd_smb2_request_read_state);
2642 struct iovec *vector;
2644 if (state->pktlen > 0) {
2645 /* if there're no remaining bytes, we're done */
2651 if (!state->hdr.done) {
2653 * first we need to get the NBT header
2655 vector = talloc_array(mem_ctx, struct iovec, 1);
2656 if (vector == NULL) {
2660 vector[0].iov_base = (void *)state->hdr.nbt;
2661 vector[0].iov_len = NBT_HDR_SIZE;
2666 state->hdr.done = true;
2671 * Now we analyze the NBT header
2673 state->pktlen = smb2_len(state->hdr.nbt);
2675 if (state->pktlen == 0) {
2676 /* if there're no remaining bytes, we're done */
2682 state->pktbuf = talloc_array(state->smb2_req, uint8_t, state->pktlen);
2683 if (state->pktbuf == NULL) {
2687 vector = talloc_array(mem_ctx, struct iovec, 1);
2688 if (vector == NULL) {
2692 vector[0].iov_base = (void *)state->pktbuf;
2693 vector[0].iov_len = state->pktlen;
2700 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2702 struct tevent_req *req =
2703 tevent_req_callback_data(subreq,
2705 struct smbd_smb2_request_read_state *state =
2706 tevent_req_data(req,
2707 struct smbd_smb2_request_read_state);
2713 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2714 TALLOC_FREE(subreq);
2716 status = map_nt_error_from_unix(sys_errno);
2717 tevent_req_nterror(req, status);
2721 if (state->hdr.nbt[0] != 0x00) {
2722 DEBUG(1,("smbd_smb2_request_read_done: ignore NBT[0x%02X] msg\n",
2723 state->hdr.nbt[0]));
2725 ZERO_STRUCT(state->hdr);
2726 TALLOC_FREE(state->pktbuf);
2729 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
2731 state->sconn->smb2.stream,
2732 state->sconn->smb2.recv_queue,
2733 smbd_smb2_request_next_vector,
2735 if (tevent_req_nomem(subreq, req)) {
2738 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2742 state->smb2_req->request_time = timeval_current();
2743 now = timeval_to_nttime(&state->smb2_req->request_time);
2745 status = smbd_smb2_inbuf_parse_compound(state->smb2_req->sconn->conn,
2750 &state->smb2_req->in.vector,
2751 &state->smb2_req->in.vector_count);
2752 if (tevent_req_nterror(req, status)) {
2756 state->smb2_req->current_idx = 1;
2758 tevent_req_done(req);
2761 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2762 TALLOC_CTX *mem_ctx,
2763 struct smbd_smb2_request **_smb2_req)
2765 struct smbd_smb2_request_read_state *state =
2766 tevent_req_data(req,
2767 struct smbd_smb2_request_read_state);
2770 if (tevent_req_is_nterror(req, &status)) {
2771 tevent_req_received(req);
2775 *_smb2_req = talloc_move(mem_ctx, &state->smb2_req);
2776 tevent_req_received(req);
2777 return NT_STATUS_OK;
2780 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2782 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2784 size_t max_send_queue_len;
2785 size_t cur_send_queue_len;
2786 struct tevent_req *subreq;
2788 if (sconn->smb2.compound_related_in_progress) {
2790 * Can't read another until the related
2793 return NT_STATUS_OK;
2796 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2798 * if there is already a smbd_smb2_request_read
2799 * pending, we are done.
2801 return NT_STATUS_OK;
2804 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2805 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2807 if (cur_send_queue_len > max_send_queue_len) {
2809 * if we have a lot of requests to send,
2810 * we wait until they are on the wire until we
2811 * ask for the next request.
2813 return NT_STATUS_OK;
2816 /* ask for the next request */
2817 subreq = smbd_smb2_request_read_send(sconn, sconn->ev_ctx, sconn);
2818 if (subreq == NULL) {
2819 return NT_STATUS_NO_MEMORY;
2821 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2823 return NT_STATUS_OK;
2826 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2827 uint8_t *inbuf, size_t size)
2830 struct smbd_smb2_request *req = NULL;
2832 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2833 (unsigned int)size));
2835 status = smbd_initialize_smb2(sconn);
2836 if (!NT_STATUS_IS_OK(status)) {
2837 smbd_server_connection_terminate(sconn, nt_errstr(status));
2841 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2842 if (!NT_STATUS_IS_OK(status)) {
2843 smbd_server_connection_terminate(sconn, nt_errstr(status));
2847 status = smbd_smb2_request_validate(req);
2848 if (!NT_STATUS_IS_OK(status)) {
2849 smbd_server_connection_terminate(sconn, nt_errstr(status));
2853 status = smbd_smb2_request_setup_out(req);
2854 if (!NT_STATUS_IS_OK(status)) {
2855 smbd_server_connection_terminate(sconn, nt_errstr(status));
2859 status = smbd_smb2_request_dispatch(req);
2860 if (!NT_STATUS_IS_OK(status)) {
2861 smbd_server_connection_terminate(sconn, nt_errstr(status));
2865 status = smbd_smb2_request_next_incoming(sconn);
2866 if (!NT_STATUS_IS_OK(status)) {
2867 smbd_server_connection_terminate(sconn, nt_errstr(status));
2871 sconn->num_requests++;
2874 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2876 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2877 struct smbd_server_connection);
2879 struct smbd_smb2_request *req = NULL;
2881 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2882 TALLOC_FREE(subreq);
2883 if (!NT_STATUS_IS_OK(status)) {
2884 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2885 nt_errstr(status)));
2886 smbd_server_connection_terminate(sconn, nt_errstr(status));
2890 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2891 req->current_idx, req->in.vector_count));
2893 status = smbd_smb2_request_validate(req);
2894 if (!NT_STATUS_IS_OK(status)) {
2895 smbd_server_connection_terminate(sconn, nt_errstr(status));
2899 status = smbd_smb2_request_setup_out(req);
2900 if (!NT_STATUS_IS_OK(status)) {
2901 smbd_server_connection_terminate(sconn, nt_errstr(status));
2905 status = smbd_smb2_request_dispatch(req);
2906 if (!NT_STATUS_IS_OK(status)) {
2907 smbd_server_connection_terminate(sconn, nt_errstr(status));
2911 status = smbd_smb2_request_next_incoming(sconn);
2912 if (!NT_STATUS_IS_OK(status)) {
2913 smbd_server_connection_terminate(sconn, nt_errstr(status));
2917 sconn->num_requests++;
2919 /* The timeout_processing function isn't run nearly
2920 often enough to implement 'max log size' without
2921 overrunning the size of the file by many megabytes.
2922 This is especially true if we are running at debug
2923 level 10. Checking every 50 SMB2s is a nice
2924 tradeoff of performance vs log file size overrun. */
2926 if ((sconn->num_requests % 50) == 0 &&
2927 need_to_check_log_size()) {
2928 change_to_root_user();