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 {
40 } smbd_smb2_table[] = {
41 #define _OP(o) .opcode = o, .name = #o
45 _OP(SMB2_OP_SESSSETUP),
87 _OP(SMB2_OP_KEEPALIVE),
101 _OP(SMB2_OP_SETINFO),
102 .need_session = true,
106 .need_session = true,
111 const char *smb2_opcode_name(uint16_t opcode)
113 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
114 return "Bad SMB2 opcode";
116 return smbd_smb2_table[opcode].name;
119 static void print_req_vectors(struct smbd_smb2_request *req)
123 for (i = 0; i < req->in.vector_count; i++) {
124 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
126 (unsigned int)req->in.vector[i].iov_len);
128 for (i = 0; i < req->out.vector_count; i++) {
129 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
131 (unsigned int)req->out.vector[i].iov_len);
135 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
137 if (size < (4 + SMB2_HDR_BODY)) {
141 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
148 static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
153 TALLOC_FREE(sconn->smb1.fde);
155 sconn->smb2.recv_queue = tevent_queue_create(sconn, "smb2 recv queue");
156 if (sconn->smb2.recv_queue == NULL) {
157 return NT_STATUS_NO_MEMORY;
160 sconn->smb2.send_queue = tevent_queue_create(sconn, "smb2 send queue");
161 if (sconn->smb2.send_queue == NULL) {
162 return NT_STATUS_NO_MEMORY;
165 sconn->smb2.seqnum_low = 0;
166 sconn->smb2.seqnum_range = 1;
167 sconn->smb2.credits_granted = 1;
168 sconn->smb2.max_credits = lp_smb2_max_credits();
169 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
170 sconn->smb2.max_credits);
171 if (sconn->smb2.credits_bitmap == NULL) {
172 return NT_STATUS_NO_MEMORY;
175 ret = tstream_bsd_existing_socket(sconn, sconn->sock,
176 &sconn->smb2.stream);
178 status = map_nt_error_from_unix(errno);
182 /* Ensure child is set to non-blocking mode */
183 set_blocking(sconn->sock, false);
187 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
188 #define _smb2_setlen(_buf,len) do { \
189 uint8_t *buf = (uint8_t *)_buf; \
191 buf[1] = ((len)&0xFF0000)>>16; \
192 buf[2] = ((len)&0xFF00)>>8; \
193 buf[3] = (len)&0xFF; \
196 static void smb2_setup_nbt_length(struct iovec *vector, int count)
201 for (i=1; i < count; i++) {
202 len += vector[i].iov_len;
205 _smb2_setlen(vector[0].iov_base, len);
208 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
210 TALLOC_CTX *mem_pool;
211 struct smbd_smb2_request *req;
214 /* Enable this to find subtle valgrind errors. */
215 mem_pool = talloc_init("smbd_smb2_request_allocate");
217 mem_pool = talloc_pool(mem_ctx, 8192);
219 if (mem_pool == NULL) {
223 req = talloc_zero(mem_pool, struct smbd_smb2_request);
225 talloc_free(mem_pool);
228 talloc_reparent(mem_pool, mem_ctx, req);
229 TALLOC_FREE(mem_pool);
231 req->last_session_id = UINT64_MAX;
232 req->last_tid = UINT32_MAX;
237 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn,
248 uint8_t *first_hdr = buf;
251 * Note: index '0' is reserved for the transport protocol
253 iov = talloc_zero_array(mem_ctx, struct iovec, num_iov);
255 return NT_STATUS_NO_MEMORY;
258 while (taken < buflen) {
259 size_t len = buflen - taken;
260 uint8_t *hdr = first_hdr + taken;
263 size_t next_command_ofs;
265 struct iovec *iov_tmp;
268 * We need the header plus the body length field
271 if (len < SMB2_HDR_BODY + 2) {
272 DEBUG(10, ("%d bytes left, expected at least %d\n",
273 (int)len, SMB2_HDR_BODY));
276 if (IVAL(hdr, 0) != SMB2_MAGIC) {
277 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
281 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
282 DEBUG(10, ("Got HDR len %d, expected %d\n",
283 SVAL(hdr, 4), SMB2_HDR_BODY));
288 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
289 body_size = SVAL(hdr, SMB2_HDR_BODY);
291 if (next_command_ofs != 0) {
292 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
295 if (next_command_ofs > full_size) {
298 full_size = next_command_ofs;
305 if (body_size > (full_size - SMB2_HDR_BODY)) {
307 * let the caller handle the error
309 body_size = full_size - SMB2_HDR_BODY;
312 iov_tmp = talloc_realloc(mem_ctx, iov, struct iovec,
314 if (iov_tmp == NULL) {
316 return NT_STATUS_NO_MEMORY;
322 cur[0].iov_base = hdr;
323 cur[0].iov_len = SMB2_HDR_BODY;
324 cur[1].iov_base = hdr + SMB2_HDR_BODY;
325 cur[1].iov_len = body_size;
326 cur[2].iov_base = hdr + SMB2_HDR_BODY + body_size;
327 cur[2].iov_len = full_size - (SMB2_HDR_BODY + body_size);
338 return NT_STATUS_INVALID_PARAMETER;
341 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
342 uint8_t *inbuf, size_t size,
343 struct smbd_smb2_request **_req)
345 struct smbd_smb2_request *req;
346 uint32_t protocol_version;
347 const uint8_t *inhdr = NULL;
349 uint32_t next_command_ofs;
353 if (size < (4 + SMB2_HDR_BODY + 2)) {
354 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
355 return NT_STATUS_INVALID_PARAMETER;
360 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
361 if (protocol_version != SMB2_MAGIC) {
362 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
364 return NT_STATUS_INVALID_PARAMETER;
367 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
368 if (cmd != SMB2_OP_NEGPROT) {
369 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
371 return NT_STATUS_INVALID_PARAMETER;
374 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
375 if (next_command_ofs != 0) {
376 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
378 return NT_STATUS_INVALID_PARAMETER;
381 req = smbd_smb2_request_allocate(sconn);
383 return NT_STATUS_NO_MEMORY;
387 talloc_steal(req, inbuf);
389 req->request_time = timeval_current();
390 now = timeval_to_nttime(&req->request_time);
392 status = smbd_smb2_inbuf_parse_compound(sconn->conn,
394 inbuf + NBT_HDR_SIZE,
396 req, &req->in.vector,
397 &req->in.vector_count);
398 if (!NT_STATUS_IS_OK(status)) {
403 req->current_idx = 1;
409 static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
410 uint64_t message_id, uint64_t seq_id)
412 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
415 if (seq_id < sconn->smb2.seqnum_low) {
416 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
417 "%llu (sequence id %llu) "
418 "(granted = %u, low = %llu, range = %u)\n",
419 (unsigned long long)message_id,
420 (unsigned long long)seq_id,
421 (unsigned int)sconn->smb2.credits_granted,
422 (unsigned long long)sconn->smb2.seqnum_low,
423 (unsigned int)sconn->smb2.seqnum_range));
427 if (seq_id >= sconn->smb2.seqnum_low + sconn->smb2.seqnum_range) {
428 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
429 "%llu (sequence id %llu) "
430 "(granted = %u, low = %llu, range = %u)\n",
431 (unsigned long long)message_id,
432 (unsigned long long)seq_id,
433 (unsigned int)sconn->smb2.credits_granted,
434 (unsigned long long)sconn->smb2.seqnum_low,
435 (unsigned int)sconn->smb2.seqnum_range));
439 offset = seq_id % sconn->smb2.max_credits;
441 if (bitmap_query(credits_bm, offset)) {
442 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
443 "%llu (sequence id %llu) "
444 "(granted = %u, low = %llu, range = %u) "
446 (unsigned long long)message_id,
447 (unsigned long long)seq_id,
448 (unsigned int)sconn->smb2.credits_granted,
449 (unsigned long long)sconn->smb2.seqnum_low,
450 (unsigned int)sconn->smb2.seqnum_range,
455 /* Mark the message_ids as seen in the bitmap. */
456 bitmap_set(credits_bm, offset);
458 if (seq_id != sconn->smb2.seqnum_low) {
463 * Move the window forward by all the message_id's
466 while (bitmap_query(credits_bm, offset)) {
467 DEBUG(10,("smb2_validate_sequence_number: clearing "
468 "id %llu (position %u) from bitmap\n",
469 (unsigned long long)(sconn->smb2.seqnum_low),
471 bitmap_clear(credits_bm, offset);
473 sconn->smb2.seqnum_low += 1;
474 sconn->smb2.seqnum_range -= 1;
475 offset = sconn->smb2.seqnum_low % sconn->smb2.max_credits;
481 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
482 const uint8_t *inhdr)
484 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
485 uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
486 uint16_t credit_charge = 1;
489 if (opcode == SMB2_OP_CANCEL) {
490 /* SMB2_CANCEL requests by definition resend messageids. */
494 if (sconn->smb2.supports_multicredit) {
495 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
496 credit_charge = MAX(credit_charge, 1);
499 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
500 "credits_granted %llu, "
501 "seqnum low/range: %llu/%llu\n",
502 (unsigned long long) message_id,
503 (unsigned long long) credit_charge,
504 (unsigned long long) sconn->smb2.credits_granted,
505 (unsigned long long) sconn->smb2.seqnum_low,
506 (unsigned long long) sconn->smb2.seqnum_range));
508 if (sconn->smb2.credits_granted < credit_charge) {
509 DEBUG(0, ("smb2_validate_message_id: client used more "
510 "credits than granted, mid %llu, charge %llu, "
511 "credits_granted %llu, "
512 "seqnum low/range: %llu/%llu\n",
513 (unsigned long long) message_id,
514 (unsigned long long) credit_charge,
515 (unsigned long long) sconn->smb2.credits_granted,
516 (unsigned long long) sconn->smb2.seqnum_low,
517 (unsigned long long) sconn->smb2.seqnum_range));
522 * now check the message ids
524 * for multi-credit requests we need to check all current mid plus
525 * the implicit mids caused by the credit charge
526 * e.g. current mid = 15, charge 5 => mark 15-19 as used
529 for (i = 0; i <= (credit_charge-1); i++) {
530 uint64_t id = message_id + i;
533 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
534 (unsigned long long)message_id,
536 (unsigned long long)id));
538 ok = smb2_validate_sequence_number(sconn, message_id, id);
544 /* substract used credits */
545 sconn->smb2.credits_granted -= credit_charge;
550 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
555 count = req->in.vector_count;
558 /* It's not a SMB2 request */
559 return NT_STATUS_INVALID_PARAMETER;
562 for (idx=1; idx < count; idx += 3) {
563 const uint8_t *inhdr = NULL;
566 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
567 return NT_STATUS_INVALID_PARAMETER;
570 if (req->in.vector[idx+1].iov_len < 2) {
571 return NT_STATUS_INVALID_PARAMETER;
574 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
576 /* Check the SMB2 header */
577 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
578 return NT_STATUS_INVALID_PARAMETER;
581 if (!smb2_validate_message_id(req->sconn, inhdr)) {
582 return NT_STATUS_INVALID_PARAMETER;
585 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
588 * the 1st request should never have the
589 * SMB2_HDR_FLAG_CHAINED flag set
591 if (flags & SMB2_HDR_FLAG_CHAINED) {
592 req->next_status = NT_STATUS_INVALID_PARAMETER;
595 } else if (idx == 4) {
597 * the 2nd request triggers related vs. unrelated
598 * compounded requests
600 if (flags & SMB2_HDR_FLAG_CHAINED) {
601 req->compound_related = true;
603 } else if (idx > 4) {
606 * It seems the this tests are wrong
607 * see the SMB2-COMPOUND test
611 * all other requests should match the 2nd one
613 if (flags & SMB2_HDR_FLAG_CHAINED) {
614 if (!req->compound_related) {
616 NT_STATUS_INVALID_PARAMETER;
620 if (req->compound_related) {
622 NT_STATUS_INVALID_PARAMETER;
633 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
634 const struct iovec *in_vector,
635 struct iovec *out_vector)
637 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
638 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
639 uint16_t credit_charge = 1;
640 uint16_t credits_requested;
644 uint16_t credits_granted = 0;
645 uint64_t credits_possible;
646 uint16_t current_max_credits;
649 * first we grant only 1/16th of the max range.
651 * Windows also starts with the 1/16th and then grants
652 * more later. I was only able to trigger higher
653 * values, when using a verify high credit charge.
655 * TODO: scale up depending one load, free memory
657 * Maybe also on the relationship between number
658 * of requests and the used sequence number.
659 * Which means we would grant more credits
660 * for client which use multi credit requests.
662 current_max_credits = sconn->smb2.max_credits / 16;
663 current_max_credits = MAX(current_max_credits, 1);
665 if (sconn->smb2.supports_multicredit) {
666 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
667 credit_charge = MAX(credit_charge, 1);
670 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
671 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
672 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
673 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
675 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
676 SMB_ASSERT(sconn->smb2.max_credits >= credit_charge);
678 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
680 * In case we already send an async interim
681 * response, we should not grant
682 * credits on the final response.
685 } else if (credits_requested > 0) {
686 uint16_t additional_max = 0;
687 uint16_t additional_credits = credits_requested - 1;
690 case SMB2_OP_NEGPROT:
692 case SMB2_OP_SESSSETUP:
694 * Windows 2012 RC1 starts to grant
696 * with a successful session setup
698 if (NT_STATUS_IS_OK(out_status)) {
704 * We match windows and only grant additional credits
711 additional_credits = MIN(additional_credits, additional_max);
713 credits_granted = credit_charge + additional_credits;
714 } else if (sconn->smb2.credits_granted == 0) {
716 * Make sure the client has always at least one credit
722 * sequence numbers should not wrap
724 * 1. calculate the possible credits until
725 * the sequence numbers start to wrap on 64-bit.
727 * 2. UINT64_MAX is used for Break Notifications.
729 * 2. truncate the possible credits to the maximum
730 * credits we want to grant to the client in total.
732 * 3. remove the range we'll already granted to the client
733 * this makes sure the client consumes the lowest sequence
734 * number, before we can grant additional credits.
736 credits_possible = UINT64_MAX - sconn->smb2.seqnum_low;
737 if (credits_possible > 0) {
738 /* remove UINT64_MAX */
739 credits_possible -= 1;
741 credits_possible = MIN(credits_possible, current_max_credits);
742 credits_possible -= sconn->smb2.seqnum_range;
744 credits_granted = MIN(credits_granted, credits_possible);
746 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
747 sconn->smb2.credits_granted += credits_granted;
748 sconn->smb2.seqnum_range += credits_granted;
750 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
751 "granted %u, current possible/max %u/%u, "
752 "total granted/max/low/range %u/%u/%llu/%u\n",
753 (unsigned int)credits_requested,
754 (unsigned int)credit_charge,
755 (unsigned int)credits_granted,
756 (unsigned int)credits_possible,
757 (unsigned int)current_max_credits,
758 (unsigned int)sconn->smb2.credits_granted,
759 (unsigned int)sconn->smb2.max_credits,
760 (unsigned long long)sconn->smb2.seqnum_low,
761 (unsigned int)sconn->smb2.seqnum_range));
764 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
765 struct smbd_smb2_request *outreq)
768 uint16_t total_credits = 0;
770 count = outreq->out.vector_count;
772 for (idx=1; idx < count; idx += 3) {
773 uint8_t *outhdr = (uint8_t *)outreq->out.vector[idx].iov_base;
774 smb2_set_operation_credit(outreq->sconn,
775 &inreq->in.vector[idx],
776 &outreq->out.vector[idx]);
777 /* To match Windows, count up what we
779 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
780 /* Set to zero in all but the last reply. */
781 if (idx + 3 < count) {
782 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
784 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
789 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
791 struct iovec *vector;
795 count = req->in.vector_count;
796 vector = talloc_zero_array(req, struct iovec, count);
797 if (vector == NULL) {
798 return NT_STATUS_NO_MEMORY;
801 vector[0].iov_base = req->out.nbt_hdr;
802 vector[0].iov_len = 4;
803 SIVAL(req->out.nbt_hdr, 0, 0);
805 for (idx=1; idx < count; idx += 3) {
806 const uint8_t *inhdr = NULL;
807 uint8_t *outhdr = NULL;
808 uint8_t *outbody = NULL;
809 uint32_t next_command_ofs = 0;
810 struct iovec *current = &vector[idx];
812 if ((idx + 3) < count) {
813 /* we have a next command -
814 * setup for the error case. */
815 next_command_ofs = SMB2_HDR_BODY + 9;
818 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
820 outhdr = talloc_zero_array(vector, uint8_t,
822 if (outhdr == NULL) {
823 return NT_STATUS_NO_MEMORY;
826 outbody = outhdr + SMB2_HDR_BODY;
828 current[0].iov_base = (void *)outhdr;
829 current[0].iov_len = SMB2_HDR_BODY;
831 current[1].iov_base = (void *)outbody;
832 current[1].iov_len = 8;
834 current[2].iov_base = NULL;
835 current[2].iov_len = 0;
837 /* setup the SMB2 header */
838 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
839 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
840 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
841 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
842 SIVAL(outhdr, SMB2_HDR_STATUS,
843 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
844 SSVAL(outhdr, SMB2_HDR_OPCODE,
845 SVAL(inhdr, SMB2_HDR_OPCODE));
846 SIVAL(outhdr, SMB2_HDR_FLAGS,
847 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
848 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
849 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
850 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
851 SIVAL(outhdr, SMB2_HDR_PID,
852 IVAL(inhdr, SMB2_HDR_PID));
853 SIVAL(outhdr, SMB2_HDR_TID,
854 IVAL(inhdr, SMB2_HDR_TID));
855 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
856 BVAL(inhdr, SMB2_HDR_SESSION_ID));
857 memcpy(outhdr + SMB2_HDR_SIGNATURE,
858 inhdr + SMB2_HDR_SIGNATURE, 16);
860 /* setup error body header */
861 SSVAL(outbody, 0x00, 0x08 + 1);
862 SSVAL(outbody, 0x02, 0);
863 SIVAL(outbody, 0x04, 0);
866 req->out.vector = vector;
867 req->out.vector_count = count;
869 /* setup the length of the NBT packet */
870 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
872 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
877 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
879 const char *location)
881 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
883 exit_server_cleanly(reason);
886 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
887 struct iovec *outvec,
888 const struct iovec *srcvec)
890 /* vec[0] is always boilerplate and must
891 * be allocated with size OUTVEC_ALLOC_SIZE. */
893 outvec[0].iov_base = talloc_memdup(ctx,
896 if (!outvec[0].iov_base) {
899 outvec[0].iov_len = SMB2_HDR_BODY;
902 * If this is a "standard" vec[1] of length 8,
903 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
904 * then duplicate this. Else use talloc_memdup().
907 if (srcvec[1].iov_len == 8 &&
908 srcvec[1].iov_base ==
909 ((uint8_t *)srcvec[0].iov_base) +
911 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
913 outvec[1].iov_len = 8;
915 outvec[1].iov_base = talloc_memdup(ctx,
918 if (!outvec[1].iov_base) {
921 outvec[1].iov_len = srcvec[1].iov_len;
925 * If this is a "standard" vec[2] of length 1,
926 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
927 * then duplicate this. Else use talloc_memdup().
930 if (srcvec[2].iov_base &&
932 if (srcvec[2].iov_base ==
933 ((uint8_t *)srcvec[0].iov_base) +
934 (OUTVEC_ALLOC_SIZE - 1) &&
935 srcvec[2].iov_len == 1) {
936 /* Common SMB2 error packet case. */
937 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
938 (OUTVEC_ALLOC_SIZE - 1);
940 outvec[2].iov_base = talloc_memdup(ctx,
943 if (!outvec[2].iov_base) {
947 outvec[2].iov_len = srcvec[2].iov_len;
949 outvec[2].iov_base = NULL;
950 outvec[2].iov_len = 0;
955 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
957 struct smbd_smb2_request *newreq = NULL;
958 struct iovec *outvec = NULL;
959 int count = req->out.vector_count;
962 newreq = smbd_smb2_request_allocate(req->sconn);
967 newreq->sconn = req->sconn;
968 newreq->session = req->session;
969 newreq->do_signing = req->do_signing;
970 newreq->current_idx = req->current_idx;
972 outvec = talloc_zero_array(newreq, struct iovec, count);
977 newreq->out.vector = outvec;
978 newreq->out.vector_count = count;
980 /* Setup the outvec's identically to req. */
981 outvec[0].iov_base = newreq->out.nbt_hdr;
982 outvec[0].iov_len = 4;
983 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
985 /* Setup the vectors identically to the ones in req. */
986 for (i = 1; i < count; i += 3) {
987 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
998 smb2_setup_nbt_length(newreq->out.vector,
999 newreq->out.vector_count);
1004 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
1006 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1009 uint8_t *outhdr = NULL;
1010 struct smbd_smb2_request *nreq = NULL;
1012 /* Create a new smb2 request we'll use
1013 for the interim return. */
1014 nreq = dup_smb2_req(req);
1016 return NT_STATUS_NO_MEMORY;
1019 /* Lose the last 3 out vectors. They're the
1020 ones we'll be using for the async reply. */
1021 nreq->out.vector_count -= 3;
1023 smb2_setup_nbt_length(nreq->out.vector,
1024 nreq->out.vector_count);
1026 /* Step back to the previous reply. */
1027 i = nreq->current_idx - 3;
1028 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
1029 /* And end the chain. */
1030 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1032 /* Calculate outgoing credits */
1033 smb2_calculate_credits(req, nreq);
1035 /* Re-sign if needed. */
1036 if (nreq->do_signing) {
1038 struct smbXsrv_session *x = nreq->session;
1039 struct smbXsrv_connection *conn = x->connection;
1040 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1042 status = smb2_signing_sign_pdu(signing_key,
1044 &nreq->out.vector[i], 3);
1045 if (!NT_STATUS_IS_OK(status)) {
1049 if (DEBUGLEVEL >= 10) {
1050 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1051 (unsigned int)nreq->current_idx );
1052 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1053 (unsigned int)nreq->out.vector_count );
1054 print_req_vectors(nreq);
1056 nreq->subreq = tstream_writev_queue_send(nreq,
1057 nreq->sconn->ev_ctx,
1058 nreq->sconn->smb2.stream,
1059 nreq->sconn->smb2.send_queue,
1061 nreq->out.vector_count);
1063 if (nreq->subreq == NULL) {
1064 return NT_STATUS_NO_MEMORY;
1067 tevent_req_set_callback(nreq->subreq,
1068 smbd_smb2_request_writev_done,
1071 return NT_STATUS_OK;
1074 struct smbd_smb2_request_pending_state {
1075 struct smbd_server_connection *sconn;
1076 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
1077 struct iovec vector[3];
1080 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
1082 struct smbd_smb2_request_pending_state *state =
1083 tevent_req_callback_data(subreq,
1084 struct smbd_smb2_request_pending_state);
1085 struct smbd_server_connection *sconn = state->sconn;
1089 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1090 TALLOC_FREE(subreq);
1092 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1093 smbd_server_connection_terminate(sconn, nt_errstr(status));
1100 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1101 struct tevent_timer *te,
1102 struct timeval current_time,
1103 void *private_data);
1105 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1106 struct tevent_req *subreq,
1107 uint32_t defer_time)
1110 int i = req->current_idx;
1111 struct timeval defer_endtime;
1112 uint8_t *outhdr = NULL;
1115 if (!tevent_req_is_in_progress(subreq)) {
1116 return NT_STATUS_OK;
1119 req->subreq = subreq;
1122 if (req->async_te) {
1123 /* We're already async. */
1124 return NT_STATUS_OK;
1127 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1128 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1129 if (flags & SMB2_HDR_FLAG_ASYNC) {
1130 /* We're already async. */
1131 return NT_STATUS_OK;
1134 if (req->in.vector_count > i + 3) {
1136 * We're trying to go async in a compound
1137 * request chain. This is not allowed.
1138 * Cancel the outstanding request.
1140 tevent_req_cancel(req->subreq);
1141 return smbd_smb2_request_error(req,
1142 NT_STATUS_INSUFFICIENT_RESOURCES);
1145 if (DEBUGLEVEL >= 10) {
1146 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1147 (unsigned int)req->current_idx );
1148 print_req_vectors(req);
1151 if (req->out.vector_count > 4) {
1152 struct iovec *outvec = NULL;
1154 /* This is a compound reply. We
1155 * must do an interim response
1156 * followed by the async response
1159 status = smb2_send_async_interim_response(req);
1160 if (!NT_STATUS_IS_OK(status)) {
1165 * We're splitting off the last SMB2
1166 * request in a compound set, and the
1167 * smb2_send_async_interim_response()
1168 * call above just sent all the replies
1169 * for the previous SMB2 requests in
1170 * this compound set. So we're no longer
1171 * in the "compound_related_in_progress"
1172 * state, and this is no longer a compound
1175 req->compound_related = false;
1176 req->sconn->smb2.compound_related_in_progress = false;
1178 /* Re-arrange the in.vectors. */
1179 req->in.vector[1] = req->in.vector[i];
1180 req->in.vector[2] = req->in.vector[i+1];
1181 req->in.vector[3] = req->in.vector[i+2];
1182 req->in.vector_count = 4;
1184 /* Reset the new in size. */
1185 smb2_setup_nbt_length(req->in.vector, 4);
1187 /* Now recreate the out.vectors. */
1188 outvec = talloc_zero_array(req, struct iovec, 4);
1190 return NT_STATUS_NO_MEMORY;
1193 /* 0 is always boilerplate and must
1194 * be of size 4 for the length field. */
1196 outvec[0].iov_base = req->out.nbt_hdr;
1197 outvec[0].iov_len = 4;
1198 SIVAL(req->out.nbt_hdr, 0, 0);
1200 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
1201 return NT_STATUS_NO_MEMORY;
1204 TALLOC_FREE(req->out.vector);
1206 req->out.vector = outvec;
1208 req->current_idx = 1;
1209 req->out.vector_count = 4;
1211 outhdr = (uint8_t *)req->out.vector[1].iov_base;
1212 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1213 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1216 defer_endtime = timeval_current_ofs_usec(defer_time);
1217 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1219 smbd_smb2_request_pending_timer,
1221 if (req->async_te == NULL) {
1222 return NT_STATUS_NO_MEMORY;
1225 return NT_STATUS_OK;
1228 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1229 struct tevent_timer *te,
1230 struct timeval current_time,
1233 struct smbd_smb2_request *req =
1234 talloc_get_type_abort(private_data,
1235 struct smbd_smb2_request);
1236 struct smbd_smb2_request_pending_state *state = NULL;
1237 uint8_t *outhdr = NULL;
1238 const uint8_t *inhdr = NULL;
1239 uint8_t *hdr = NULL;
1240 uint8_t *body = NULL;
1242 uint64_t message_id = 0;
1243 uint64_t async_id = 0;
1244 struct tevent_req *subreq = NULL;
1246 TALLOC_FREE(req->async_te);
1248 /* Ensure our final reply matches the interim one. */
1249 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1250 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1251 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1252 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1254 async_id = message_id; /* keep it simple for now... */
1256 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1257 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1259 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1261 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1262 (unsigned long long)async_id ));
1265 * What we send is identical to a smbd_smb2_request_error
1266 * packet with an error status of STATUS_PENDING. Make use
1267 * of this fact sometime when refactoring. JRA.
1270 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1271 if (state == NULL) {
1272 smbd_server_connection_terminate(req->sconn,
1273 nt_errstr(NT_STATUS_NO_MEMORY));
1276 state->sconn = req->sconn;
1278 state->vector[0].iov_base = (void *)state->buf;
1279 state->vector[0].iov_len = 4;
1281 state->vector[1].iov_base = state->buf + 4;
1282 state->vector[1].iov_len = SMB2_HDR_BODY;
1284 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
1285 state->vector[2].iov_len = 9;
1287 smb2_setup_nbt_length(state->vector, 3);
1289 hdr = (uint8_t *)state->vector[1].iov_base;
1290 body = (uint8_t *)state->vector[2].iov_base;
1292 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1293 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1294 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1295 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1296 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1298 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1299 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1300 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1301 SBVAL(hdr, SMB2_HDR_PID, async_id);
1302 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1303 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1304 memcpy(hdr+SMB2_HDR_SIGNATURE,
1305 outhdr+SMB2_HDR_SIGNATURE, 16);
1307 SSVAL(body, 0x00, 0x08 + 1);
1309 SCVAL(body, 0x02, 0);
1310 SCVAL(body, 0x03, 0);
1311 SIVAL(body, 0x04, 0);
1312 /* Match W2K8R2... */
1313 SCVAL(body, 0x08, 0x21);
1315 /* Ensure we correctly go through crediting. Grant
1316 the credits now, and zero credits on the final
1318 smb2_set_operation_credit(req->sconn,
1319 SMBD_SMB2_IN_HDR_IOV(req),
1322 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1324 if (req->do_signing) {
1326 struct smbXsrv_session *x = req->session;
1327 struct smbXsrv_connection *conn = x->connection;
1328 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1330 status = smb2_signing_sign_pdu(signing_key,
1332 &state->vector[1], 2);
1333 if (!NT_STATUS_IS_OK(status)) {
1334 smbd_server_connection_terminate(req->sconn,
1340 subreq = tstream_writev_queue_send(state,
1341 state->sconn->ev_ctx,
1342 state->sconn->smb2.stream,
1343 state->sconn->smb2.send_queue,
1346 if (subreq == NULL) {
1347 smbd_server_connection_terminate(state->sconn,
1348 nt_errstr(NT_STATUS_NO_MEMORY));
1351 tevent_req_set_callback(subreq,
1352 smbd_smb2_request_pending_writev_done,
1356 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1358 struct smbd_server_connection *sconn = req->sconn;
1359 struct smbd_smb2_request *cur;
1360 const uint8_t *inhdr;
1362 uint64_t search_message_id;
1363 uint64_t search_async_id;
1366 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1368 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1369 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1370 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1373 * we don't need the request anymore
1374 * cancel requests never have a response
1376 DLIST_REMOVE(req->sconn->smb2.requests, req);
1379 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1380 const uint8_t *outhdr;
1381 uint64_t message_id;
1384 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1386 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1387 async_id = BVAL(outhdr, SMB2_HDR_PID);
1389 if (flags & SMB2_HDR_FLAG_ASYNC) {
1390 if (search_async_id == async_id) {
1391 found_id = async_id;
1395 if (search_message_id == message_id) {
1396 found_id = message_id;
1402 if (cur && cur->subreq) {
1403 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1404 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1405 "cancel opcode[%s] mid %llu\n",
1406 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1407 (unsigned long long)found_id ));
1408 tevent_req_cancel(cur->subreq);
1411 return NT_STATUS_OK;
1414 /*************************************************************
1415 Ensure an incoming tid is a valid one for us to access.
1416 Change to the associated uid credentials and chdir to the
1417 valid tid directory.
1418 *************************************************************/
1420 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1422 const uint8_t *inhdr;
1425 struct smbXsrv_tcon *tcon;
1427 NTTIME now = timeval_to_nttime(&req->request_time);
1431 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1433 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1434 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1436 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1437 in_tid = req->last_tid;
1440 status = smb2srv_tcon_lookup(req->session,
1441 in_tid, now, &tcon);
1442 if (!NT_STATUS_IS_OK(status)) {
1446 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1447 return NT_STATUS_ACCESS_DENIED;
1450 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1451 if (!set_current_service(tcon->compat, 0, true)) {
1452 return NT_STATUS_ACCESS_DENIED;
1456 req->last_tid = in_tid;
1458 return NT_STATUS_OK;
1461 /*************************************************************
1462 Ensure an incoming session_id is a valid one for us to access.
1463 *************************************************************/
1465 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1467 const uint8_t *inhdr;
1470 uint64_t in_session_id;
1471 struct smbXsrv_session *session = NULL;
1472 struct auth_session_info *session_info;
1474 NTTIME now = timeval_to_nttime(&req->request_time);
1476 req->session = NULL;
1479 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1481 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1482 in_opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1483 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1485 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1486 in_session_id = req->last_session_id;
1489 /* lookup an existing session */
1490 status = smb2srv_session_lookup(req->sconn->conn,
1494 req->session = session;
1495 req->last_session_id = in_session_id;
1497 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1498 switch (in_opcode) {
1499 case SMB2_OP_SESSSETUP:
1500 status = NT_STATUS_OK;
1506 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1507 switch (in_opcode) {
1509 case SMB2_OP_CREATE:
1510 case SMB2_OP_GETINFO:
1511 case SMB2_OP_SETINFO:
1512 return NT_STATUS_INVALID_HANDLE;
1515 * Notice the check for
1516 * (session_info == NULL)
1519 status = NT_STATUS_OK;
1523 if (!NT_STATUS_IS_OK(status)) {
1527 session_info = session->global->auth_session_info;
1528 if (session_info == NULL) {
1529 return NT_STATUS_INVALID_HANDLE;
1532 set_current_user_info(session_info->unix_info->sanitized_username,
1533 session_info->unix_info->unix_name,
1534 session_info->info->domain_name);
1536 return NT_STATUS_OK;
1539 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1540 uint32_t data_length)
1542 uint16_t needed_charge;
1543 uint16_t credit_charge = 1;
1544 const uint8_t *inhdr;
1546 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1548 if (req->sconn->smb2.supports_multicredit) {
1549 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1550 credit_charge = MAX(credit_charge, 1);
1553 needed_charge = (data_length - 1)/ 65536 + 1;
1555 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1556 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1557 credit_charge, needed_charge));
1559 if (needed_charge > credit_charge) {
1560 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1561 credit_charge, needed_charge));
1562 return NT_STATUS_INVALID_PARAMETER;
1565 return NT_STATUS_OK;
1568 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1569 size_t expected_body_size)
1571 const uint8_t *inhdr;
1573 const uint8_t *inbody;
1574 int i = req->current_idx;
1576 size_t min_dyn_size = expected_body_size & 0x00000001;
1579 * The following should be checked already.
1581 if ((i+2) > req->in.vector_count) {
1582 return NT_STATUS_INTERNAL_ERROR;
1584 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1585 return NT_STATUS_INTERNAL_ERROR;
1587 if (req->in.vector[i+1].iov_len < 2) {
1588 return NT_STATUS_INTERNAL_ERROR;
1591 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1592 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1596 case SMB2_OP_GETINFO:
1602 * Now check the expected body size,
1603 * where the last byte might be in the
1606 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1607 return NT_STATUS_INVALID_PARAMETER;
1609 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1610 return NT_STATUS_INVALID_PARAMETER;
1613 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1615 body_size = SVAL(inbody, 0x00);
1616 if (body_size != expected_body_size) {
1617 return NT_STATUS_INVALID_PARAMETER;
1620 return NT_STATUS_OK;
1623 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1625 struct smbXsrv_connection *conn = req->sconn->conn;
1626 const uint8_t *inhdr;
1631 NTSTATUS session_status;
1632 uint32_t allowed_flags;
1633 NTSTATUS return_value;
1634 struct smbXsrv_session *x = NULL;
1635 bool signing_required = false;
1637 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1639 /* TODO: verify more things */
1641 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1642 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1643 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1644 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1645 smb2_opcode_name(opcode),
1646 (unsigned long long)mid));
1648 if (conn->protocol >= PROTOCOL_SMB2_02) {
1650 * once the protocol is negotiated
1651 * SMB2_OP_NEGPROT is not allowed anymore
1653 if (opcode == SMB2_OP_NEGPROT) {
1654 /* drop the connection */
1655 return NT_STATUS_INVALID_PARAMETER;
1659 * if the protocol is not negotiated yet
1660 * only SMB2_OP_NEGPROT is allowed.
1662 if (opcode != SMB2_OP_NEGPROT) {
1663 /* drop the connection */
1664 return NT_STATUS_INVALID_PARAMETER;
1668 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1669 SMB2_HDR_FLAG_SIGNED |
1671 if (opcode == SMB2_OP_CANCEL) {
1672 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1674 if ((flags & ~allowed_flags) != 0) {
1675 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1679 * Check if the client provided a valid session id,
1680 * if so smbd_smb2_request_check_session() calls
1681 * set_current_user_info().
1683 * As some command don't require a valid session id
1684 * we defer the check of the session_status
1686 session_status = smbd_smb2_request_check_session(req);
1690 signing_required = x->global->signing_required;
1692 if (opcode == SMB2_OP_SESSSETUP &&
1693 x->global->channels[0].signing_key.length) {
1694 signing_required = true;
1698 req->do_signing = false;
1699 if (flags & SMB2_HDR_FLAG_SIGNED) {
1700 DATA_BLOB signing_key;
1703 return smbd_smb2_request_error(
1704 req, NT_STATUS_ACCESS_DENIED);
1707 signing_key = x->global->channels[0].signing_key;
1709 if (!NT_STATUS_IS_OK(session_status)) {
1710 return smbd_smb2_request_error(req, session_status);
1713 req->do_signing = true;
1714 status = smb2_signing_check_pdu(signing_key,
1716 SMBD_SMB2_IN_HDR_IOV(req), 3);
1717 if (!NT_STATUS_IS_OK(status)) {
1718 return smbd_smb2_request_error(req, status);
1720 } else if (opcode == SMB2_OP_CANCEL) {
1721 /* Cancel requests are allowed to skip the signing */
1722 } else if (signing_required) {
1723 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1726 if (flags & SMB2_HDR_FLAG_CHAINED) {
1728 * This check is mostly for giving the correct error code
1729 * for compounded requests.
1731 * TODO: we may need to move this after the session
1734 if (!NT_STATUS_IS_OK(req->next_status)) {
1735 return smbd_smb2_request_error(req, req->next_status);
1738 req->compat_chain_fsp = NULL;
1741 if (req->compound_related) {
1742 req->sconn->smb2.compound_related_in_progress = true;
1746 case SMB2_OP_NEGPROT:
1747 /* This call needs to be run as root */
1748 change_to_root_user();
1751 START_PROFILE(smb2_negprot);
1752 return_value = smbd_smb2_request_process_negprot(req);
1753 END_PROFILE(smb2_negprot);
1757 case SMB2_OP_SESSSETUP:
1758 /* This call needs to be run as root */
1759 change_to_root_user();
1762 START_PROFILE(smb2_sesssetup);
1763 return_value = smbd_smb2_request_process_sesssetup(req);
1764 END_PROFILE(smb2_sesssetup);
1768 case SMB2_OP_LOGOFF:
1769 if (!NT_STATUS_IS_OK(session_status)) {
1770 return_value = smbd_smb2_request_error(req, session_status);
1774 /* This call needs to be run as root */
1775 change_to_root_user();
1778 START_PROFILE(smb2_logoff);
1779 return_value = smbd_smb2_request_process_logoff(req);
1780 END_PROFILE(smb2_logoff);
1785 if (!NT_STATUS_IS_OK(session_status)) {
1786 return_value = smbd_smb2_request_error(req, session_status);
1791 * This call needs to be run as root.
1793 * smbd_smb2_request_process_tcon()
1794 * calls make_connection_snum(), which will call
1795 * change_to_user(), when needed.
1797 change_to_root_user();
1800 START_PROFILE(smb2_tcon);
1801 return_value = smbd_smb2_request_process_tcon(req);
1802 END_PROFILE(smb2_tcon);
1807 if (!NT_STATUS_IS_OK(session_status)) {
1808 return_value = smbd_smb2_request_error(req, session_status);
1812 * This call needs to be run as user.
1814 * smbd_smb2_request_check_tcon()
1815 * calls change_to_user() on success.
1817 status = smbd_smb2_request_check_tcon(req);
1818 if (!NT_STATUS_IS_OK(status)) {
1819 return_value = smbd_smb2_request_error(req, status);
1822 /* This call needs to be run as root */
1823 change_to_root_user();
1827 START_PROFILE(smb2_tdis);
1828 return_value = smbd_smb2_request_process_tdis(req);
1829 END_PROFILE(smb2_tdis);
1833 case SMB2_OP_CREATE:
1834 if (!NT_STATUS_IS_OK(session_status)) {
1835 return_value = smbd_smb2_request_error(req, session_status);
1839 * This call needs to be run as user.
1841 * smbd_smb2_request_check_tcon()
1842 * calls change_to_user() on success.
1844 status = smbd_smb2_request_check_tcon(req);
1845 if (!NT_STATUS_IS_OK(status)) {
1846 return_value = smbd_smb2_request_error(req, status);
1851 START_PROFILE(smb2_create);
1852 return_value = smbd_smb2_request_process_create(req);
1853 END_PROFILE(smb2_create);
1858 if (!NT_STATUS_IS_OK(session_status)) {
1859 return_value = smbd_smb2_request_error(req, session_status);
1863 * This call needs to be run as user.
1865 * smbd_smb2_request_check_tcon()
1866 * calls change_to_user() on success.
1868 status = smbd_smb2_request_check_tcon(req);
1869 if (!NT_STATUS_IS_OK(status)) {
1870 return_value = smbd_smb2_request_error(req, status);
1875 START_PROFILE(smb2_close);
1876 return_value = smbd_smb2_request_process_close(req);
1877 END_PROFILE(smb2_close);
1882 if (!NT_STATUS_IS_OK(session_status)) {
1883 return_value = smbd_smb2_request_error(req, session_status);
1887 * This call needs to be run as user.
1889 * smbd_smb2_request_check_tcon()
1890 * calls change_to_user() on success.
1892 status = smbd_smb2_request_check_tcon(req);
1893 if (!NT_STATUS_IS_OK(status)) {
1894 return_value = smbd_smb2_request_error(req, status);
1899 START_PROFILE(smb2_flush);
1900 return_value = smbd_smb2_request_process_flush(req);
1901 END_PROFILE(smb2_flush);
1906 if (!NT_STATUS_IS_OK(session_status)) {
1907 return_value = smbd_smb2_request_error(req, session_status);
1911 * This call needs to be run as user.
1913 * smbd_smb2_request_check_tcon()
1914 * calls change_to_user() on success.
1916 status = smbd_smb2_request_check_tcon(req);
1917 if (!NT_STATUS_IS_OK(status)) {
1918 return_value = smbd_smb2_request_error(req, status);
1923 START_PROFILE(smb2_read);
1924 return_value = smbd_smb2_request_process_read(req);
1925 END_PROFILE(smb2_read);
1930 if (!NT_STATUS_IS_OK(session_status)) {
1931 return_value = smbd_smb2_request_error(req, session_status);
1935 * This call needs to be run as user.
1937 * smbd_smb2_request_check_tcon()
1938 * calls change_to_user() on success.
1940 status = smbd_smb2_request_check_tcon(req);
1941 if (!NT_STATUS_IS_OK(status)) {
1942 return_value = smbd_smb2_request_error(req, status);
1947 START_PROFILE(smb2_write);
1948 return_value = smbd_smb2_request_process_write(req);
1949 END_PROFILE(smb2_write);
1954 if (!NT_STATUS_IS_OK(session_status)) {
1955 /* Too ugly to live ? JRA. */
1956 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1957 session_status = NT_STATUS_FILE_CLOSED;
1959 return_value = smbd_smb2_request_error(req, session_status);
1963 * This call needs to be run as user.
1965 * smbd_smb2_request_check_tcon()
1966 * calls change_to_user() on success.
1968 status = smbd_smb2_request_check_tcon(req);
1969 if (!NT_STATUS_IS_OK(status)) {
1970 /* Too ugly to live ? JRA. */
1971 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1972 status = NT_STATUS_FILE_CLOSED;
1974 return_value = smbd_smb2_request_error(req, status);
1979 START_PROFILE(smb2_lock);
1980 return_value = smbd_smb2_request_process_lock(req);
1981 END_PROFILE(smb2_lock);
1986 if (!NT_STATUS_IS_OK(session_status)) {
1987 return_value = smbd_smb2_request_error(req, session_status);
1991 * This call needs to be run as user.
1993 * smbd_smb2_request_check_tcon()
1994 * calls change_to_user() on success.
1996 status = smbd_smb2_request_check_tcon(req);
1997 if (!NT_STATUS_IS_OK(status)) {
1998 return_value = smbd_smb2_request_error(req, status);
2003 START_PROFILE(smb2_ioctl);
2004 return_value = smbd_smb2_request_process_ioctl(req);
2005 END_PROFILE(smb2_ioctl);
2009 case SMB2_OP_CANCEL:
2011 * This call needs to be run as root
2013 * That is what we also do in the SMB1 case.
2015 change_to_root_user();
2018 START_PROFILE(smb2_cancel);
2019 return_value = smbd_smb2_request_process_cancel(req);
2020 END_PROFILE(smb2_cancel);
2024 case SMB2_OP_KEEPALIVE:
2025 /* This call needs to be run as root */
2026 change_to_root_user();
2029 START_PROFILE(smb2_keepalive);
2030 return_value = smbd_smb2_request_process_keepalive(req);
2031 END_PROFILE(smb2_keepalive);
2036 if (!NT_STATUS_IS_OK(session_status)) {
2037 return_value = smbd_smb2_request_error(req, session_status);
2041 * This call needs to be run as user.
2043 * smbd_smb2_request_check_tcon()
2044 * calls change_to_user() on success.
2046 status = smbd_smb2_request_check_tcon(req);
2047 if (!NT_STATUS_IS_OK(status)) {
2048 return_value = smbd_smb2_request_error(req, status);
2053 START_PROFILE(smb2_find);
2054 return_value = smbd_smb2_request_process_find(req);
2055 END_PROFILE(smb2_find);
2059 case SMB2_OP_NOTIFY:
2060 if (!NT_STATUS_IS_OK(session_status)) {
2061 return_value = smbd_smb2_request_error(req, session_status);
2065 * This call needs to be run as user.
2067 * smbd_smb2_request_check_tcon()
2068 * calls change_to_user() on success.
2070 status = smbd_smb2_request_check_tcon(req);
2071 if (!NT_STATUS_IS_OK(status)) {
2072 return_value = smbd_smb2_request_error(req, status);
2077 START_PROFILE(smb2_notify);
2078 return_value = smbd_smb2_request_process_notify(req);
2079 END_PROFILE(smb2_notify);
2083 case SMB2_OP_GETINFO:
2084 if (!NT_STATUS_IS_OK(session_status)) {
2085 return_value = smbd_smb2_request_error(req, session_status);
2089 * This call needs to be run as user.
2091 * smbd_smb2_request_check_tcon()
2092 * calls change_to_user() on success.
2094 status = smbd_smb2_request_check_tcon(req);
2095 if (!NT_STATUS_IS_OK(status)) {
2096 return_value = smbd_smb2_request_error(req, status);
2101 START_PROFILE(smb2_getinfo);
2102 return_value = smbd_smb2_request_process_getinfo(req);
2103 END_PROFILE(smb2_getinfo);
2107 case SMB2_OP_SETINFO:
2108 if (!NT_STATUS_IS_OK(session_status)) {
2109 return_value = smbd_smb2_request_error(req, session_status);
2113 * This call needs to be run as user.
2115 * smbd_smb2_request_check_tcon()
2116 * calls change_to_user() on success.
2118 status = smbd_smb2_request_check_tcon(req);
2119 if (!NT_STATUS_IS_OK(status)) {
2120 return_value = smbd_smb2_request_error(req, status);
2125 START_PROFILE(smb2_setinfo);
2126 return_value = smbd_smb2_request_process_setinfo(req);
2127 END_PROFILE(smb2_setinfo);
2132 if (!NT_STATUS_IS_OK(session_status)) {
2133 return_value = smbd_smb2_request_error(req, session_status);
2137 * This call needs to be run as user.
2139 * smbd_smb2_request_check_tcon()
2140 * calls change_to_user() on success.
2142 status = smbd_smb2_request_check_tcon(req);
2143 if (!NT_STATUS_IS_OK(status)) {
2144 return_value = smbd_smb2_request_error(req, status);
2149 START_PROFILE(smb2_break);
2150 return_value = smbd_smb2_request_process_break(req);
2151 END_PROFILE(smb2_break);
2156 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2159 return return_value;
2162 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2164 struct tevent_req *subreq;
2165 int i = req->current_idx;
2168 TALLOC_FREE(req->async_te);
2170 req->current_idx += 3;
2172 if (req->current_idx < req->out.vector_count) {
2174 * We must process the remaining compound
2175 * SMB2 requests before any new incoming SMB2
2176 * requests. This is because incoming SMB2
2177 * requests may include a cancel for a
2178 * compound request we haven't processed
2181 struct tevent_immediate *im = tevent_create_immediate(req);
2183 return NT_STATUS_NO_MEMORY;
2185 tevent_schedule_immediate(im,
2187 smbd_smb2_request_dispatch_immediate,
2189 return NT_STATUS_OK;
2192 if (req->compound_related) {
2193 req->sconn->smb2.compound_related_in_progress = false;
2196 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2198 /* Set credit for these operations (zero credits if this
2199 is a final reply for an async operation). */
2200 smb2_calculate_credits(req, req);
2202 if (req->do_signing) {
2204 struct smbXsrv_session *x = req->session;
2205 struct smbXsrv_connection *conn = x->connection;
2206 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2208 status = smb2_signing_sign_pdu(signing_key,
2210 &req->out.vector[i], 3);
2211 if (!NT_STATUS_IS_OK(status)) {
2216 if (DEBUGLEVEL >= 10) {
2217 dbgtext("smbd_smb2_request_reply: sending...\n");
2218 print_req_vectors(req);
2221 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2222 if (req->out.vector_count == 4 &&
2223 req->out.vector[3].iov_base == NULL &&
2224 req->out.vector[3].iov_len != 0) {
2225 /* Dynamic part is NULL. Chop it off,
2226 We're going to send it via sendfile. */
2227 req->out.vector_count -= 1;
2230 subreq = tstream_writev_queue_send(req,
2232 req->sconn->smb2.stream,
2233 req->sconn->smb2.send_queue,
2235 req->out.vector_count);
2236 if (subreq == NULL) {
2237 return NT_STATUS_NO_MEMORY;
2239 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
2241 * We're done with this request -
2242 * move it off the "being processed" queue.
2244 DLIST_REMOVE(req->sconn->smb2.requests, req);
2246 return NT_STATUS_OK;
2249 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2251 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2252 struct tevent_immediate *im,
2255 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2256 struct smbd_smb2_request);
2257 struct smbd_server_connection *sconn = req->sconn;
2262 if (DEBUGLEVEL >= 10) {
2263 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2264 req->current_idx, req->in.vector_count));
2265 print_req_vectors(req);
2268 status = smbd_smb2_request_dispatch(req);
2269 if (!NT_STATUS_IS_OK(status)) {
2270 smbd_server_connection_terminate(sconn, nt_errstr(status));
2274 status = smbd_smb2_request_next_incoming(sconn);
2275 if (!NT_STATUS_IS_OK(status)) {
2276 smbd_server_connection_terminate(sconn, nt_errstr(status));
2281 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
2283 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
2284 struct smbd_smb2_request);
2285 struct smbd_server_connection *sconn = req->sconn;
2290 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2291 TALLOC_FREE(subreq);
2294 status = map_nt_error_from_unix(sys_errno);
2295 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2296 nt_errstr(status)));
2297 smbd_server_connection_terminate(sconn, nt_errstr(status));
2301 status = smbd_smb2_request_next_incoming(sconn);
2302 if (!NT_STATUS_IS_OK(status)) {
2303 smbd_server_connection_terminate(sconn, nt_errstr(status));
2308 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2310 DATA_BLOB body, DATA_BLOB *dyn,
2311 const char *location)
2314 int i = req->current_idx;
2315 uint32_t next_command_ofs;
2317 DEBUG(10,("smbd_smb2_request_done_ex: "
2318 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2319 i, nt_errstr(status), (unsigned int)body.length,
2321 (unsigned int)(dyn ? dyn->length : 0),
2324 if (body.length < 2) {
2325 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2328 if ((body.length % 2) != 0) {
2329 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2332 outhdr = (uint8_t *)req->out.vector[i].iov_base;
2334 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2335 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2337 req->out.vector[i+1].iov_base = (void *)body.data;
2338 req->out.vector[i+1].iov_len = body.length;
2341 req->out.vector[i+2].iov_base = (void *)dyn->data;
2342 req->out.vector[i+2].iov_len = dyn->length;
2344 req->out.vector[i+2].iov_base = NULL;
2345 req->out.vector[i+2].iov_len = 0;
2348 /* see if we need to recalculate the offset to the next response */
2349 if (next_command_ofs > 0) {
2350 next_command_ofs = SMB2_HDR_BODY;
2351 next_command_ofs += req->out.vector[i+1].iov_len;
2352 next_command_ofs += req->out.vector[i+2].iov_len;
2355 if ((next_command_ofs % 8) != 0) {
2356 size_t pad_size = 8 - (next_command_ofs % 8);
2357 if (req->out.vector[i+2].iov_len == 0) {
2359 * if the dyn buffer is empty
2360 * we can use it to add padding
2364 pad = talloc_zero_array(req->out.vector,
2367 return smbd_smb2_request_error(req,
2368 NT_STATUS_NO_MEMORY);
2371 req->out.vector[i+2].iov_base = (void *)pad;
2372 req->out.vector[i+2].iov_len = pad_size;
2375 * For now we copy the dynamic buffer
2376 * and add the padding to the new buffer
2383 old_size = req->out.vector[i+2].iov_len;
2384 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2386 new_size = old_size + pad_size;
2387 new_dyn = talloc_zero_array(req->out.vector,
2389 if (new_dyn == NULL) {
2390 return smbd_smb2_request_error(req,
2391 NT_STATUS_NO_MEMORY);
2394 memcpy(new_dyn, old_dyn, old_size);
2395 memset(new_dyn + old_size, 0, pad_size);
2397 req->out.vector[i+2].iov_base = (void *)new_dyn;
2398 req->out.vector[i+2].iov_len = new_size;
2400 next_command_ofs += pad_size;
2403 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2405 return smbd_smb2_request_reply(req);
2408 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2411 const char *location)
2414 int i = req->current_idx;
2415 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2417 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2418 i, nt_errstr(status), info ? " +info" : "",
2421 body.data = outhdr + SMB2_HDR_BODY;
2423 SSVAL(body.data, 0, 9);
2426 SIVAL(body.data, 0x04, info->length);
2428 /* Allocated size of req->out.vector[i].iov_base
2429 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2430 * 1 byte without having to do an alloc.
2432 info = talloc_zero_array(req->out.vector,
2436 return NT_STATUS_NO_MEMORY;
2438 info->data = ((uint8_t *)outhdr) +
2439 OUTVEC_ALLOC_SIZE - 1;
2441 SCVAL(info->data, 0, 0);
2445 * if a request fails, all other remaining
2446 * compounded requests should fail too
2448 req->next_status = NT_STATUS_INVALID_PARAMETER;
2450 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2454 struct smbd_smb2_send_oplock_break_state {
2455 struct smbd_server_connection *sconn;
2456 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2457 struct iovec vector;
2460 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2462 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2463 uint64_t file_id_persistent,
2464 uint64_t file_id_volatile,
2465 uint8_t oplock_level)
2467 struct smbd_smb2_send_oplock_break_state *state;
2468 struct tevent_req *subreq;
2472 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2473 if (state == NULL) {
2474 return NT_STATUS_NO_MEMORY;
2476 state->sconn = sconn;
2478 state->vector.iov_base = (void *)state->buf;
2479 state->vector.iov_len = sizeof(state->buf);
2481 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2482 hdr = state->buf + 4;
2483 body = hdr + SMB2_HDR_BODY;
2485 SIVAL(hdr, 0, SMB2_MAGIC);
2486 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2487 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2488 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2489 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2490 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2491 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2492 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2493 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2494 SIVAL(hdr, SMB2_HDR_PID, 0);
2495 SIVAL(hdr, SMB2_HDR_TID, 0);
2496 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2497 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2499 SSVAL(body, 0x00, 0x18);
2501 SCVAL(body, 0x02, oplock_level);
2502 SCVAL(body, 0x03, 0); /* reserved */
2503 SIVAL(body, 0x04, 0); /* reserved */
2504 SBVAL(body, 0x08, file_id_persistent);
2505 SBVAL(body, 0x10, file_id_volatile);
2507 subreq = tstream_writev_queue_send(state,
2510 sconn->smb2.send_queue,
2512 if (subreq == NULL) {
2513 return NT_STATUS_NO_MEMORY;
2515 tevent_req_set_callback(subreq,
2516 smbd_smb2_oplock_break_writev_done,
2519 return NT_STATUS_OK;
2522 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2524 struct smbd_smb2_send_oplock_break_state *state =
2525 tevent_req_callback_data(subreq,
2526 struct smbd_smb2_send_oplock_break_state);
2527 struct smbd_server_connection *sconn = state->sconn;
2531 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2532 TALLOC_FREE(subreq);
2534 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2535 smbd_server_connection_terminate(sconn, nt_errstr(status));
2542 struct smbd_smb2_request_read_state {
2543 struct tevent_context *ev;
2544 struct smbd_server_connection *sconn;
2545 struct smbd_smb2_request *smb2_req;
2547 uint8_t nbt[NBT_HDR_SIZE];
2554 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2556 TALLOC_CTX *mem_ctx,
2557 struct iovec **_vector,
2559 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2561 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2562 struct tevent_context *ev,
2563 struct smbd_server_connection *sconn)
2565 struct tevent_req *req;
2566 struct smbd_smb2_request_read_state *state;
2567 struct tevent_req *subreq;
2569 req = tevent_req_create(mem_ctx, &state,
2570 struct smbd_smb2_request_read_state);
2575 state->sconn = sconn;
2577 state->smb2_req = smbd_smb2_request_allocate(state);
2578 if (tevent_req_nomem(state->smb2_req, req)) {
2579 return tevent_req_post(req, ev);
2581 state->smb2_req->sconn = sconn;
2583 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
2585 state->sconn->smb2.stream,
2586 state->sconn->smb2.recv_queue,
2587 smbd_smb2_request_next_vector,
2589 if (tevent_req_nomem(subreq, req)) {
2590 return tevent_req_post(req, ev);
2592 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2597 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2599 TALLOC_CTX *mem_ctx,
2600 struct iovec **_vector,
2603 struct smbd_smb2_request_read_state *state =
2604 talloc_get_type_abort(private_data,
2605 struct smbd_smb2_request_read_state);
2606 struct iovec *vector;
2608 if (state->pktlen > 0) {
2609 /* if there're no remaining bytes, we're done */
2615 if (!state->hdr.done) {
2617 * first we need to get the NBT header
2619 vector = talloc_array(mem_ctx, struct iovec, 1);
2620 if (vector == NULL) {
2624 vector[0].iov_base = (void *)state->hdr.nbt;
2625 vector[0].iov_len = NBT_HDR_SIZE;
2630 state->hdr.done = true;
2635 * Now we analyze the NBT header
2637 state->pktlen = smb2_len(state->hdr.nbt);
2639 if (state->pktlen == 0) {
2640 /* if there're no remaining bytes, we're done */
2646 state->pktbuf = talloc_array(state->smb2_req, uint8_t, state->pktlen);
2647 if (state->pktbuf == NULL) {
2651 vector = talloc_array(mem_ctx, struct iovec, 1);
2652 if (vector == NULL) {
2656 vector[0].iov_base = (void *)state->pktbuf;
2657 vector[0].iov_len = state->pktlen;
2664 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2666 struct tevent_req *req =
2667 tevent_req_callback_data(subreq,
2669 struct smbd_smb2_request_read_state *state =
2670 tevent_req_data(req,
2671 struct smbd_smb2_request_read_state);
2677 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2678 TALLOC_FREE(subreq);
2680 status = map_nt_error_from_unix(sys_errno);
2681 tevent_req_nterror(req, status);
2685 if (state->hdr.nbt[0] != 0x00) {
2686 DEBUG(1,("smbd_smb2_request_read_done: ignore NBT[0x%02X] msg\n",
2687 state->hdr.nbt[0]));
2689 ZERO_STRUCT(state->hdr);
2690 TALLOC_FREE(state->pktbuf);
2693 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
2695 state->sconn->smb2.stream,
2696 state->sconn->smb2.recv_queue,
2697 smbd_smb2_request_next_vector,
2699 if (tevent_req_nomem(subreq, req)) {
2702 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2706 state->smb2_req->request_time = timeval_current();
2707 now = timeval_to_nttime(&state->smb2_req->request_time);
2709 status = smbd_smb2_inbuf_parse_compound(state->smb2_req->sconn->conn,
2714 &state->smb2_req->in.vector,
2715 &state->smb2_req->in.vector_count);
2716 if (tevent_req_nterror(req, status)) {
2720 state->smb2_req->current_idx = 1;
2722 tevent_req_done(req);
2725 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2726 TALLOC_CTX *mem_ctx,
2727 struct smbd_smb2_request **_smb2_req)
2729 struct smbd_smb2_request_read_state *state =
2730 tevent_req_data(req,
2731 struct smbd_smb2_request_read_state);
2734 if (tevent_req_is_nterror(req, &status)) {
2735 tevent_req_received(req);
2739 *_smb2_req = talloc_move(mem_ctx, &state->smb2_req);
2740 tevent_req_received(req);
2741 return NT_STATUS_OK;
2744 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2746 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2748 size_t max_send_queue_len;
2749 size_t cur_send_queue_len;
2750 struct tevent_req *subreq;
2752 if (sconn->smb2.compound_related_in_progress) {
2754 * Can't read another until the related
2757 return NT_STATUS_OK;
2760 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2762 * if there is already a smbd_smb2_request_read
2763 * pending, we are done.
2765 return NT_STATUS_OK;
2768 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2769 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2771 if (cur_send_queue_len > max_send_queue_len) {
2773 * if we have a lot of requests to send,
2774 * we wait until they are on the wire until we
2775 * ask for the next request.
2777 return NT_STATUS_OK;
2780 /* ask for the next request */
2781 subreq = smbd_smb2_request_read_send(sconn, sconn->ev_ctx, sconn);
2782 if (subreq == NULL) {
2783 return NT_STATUS_NO_MEMORY;
2785 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2787 return NT_STATUS_OK;
2790 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2791 uint8_t *inbuf, size_t size)
2794 struct smbd_smb2_request *req = NULL;
2796 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2797 (unsigned int)size));
2799 status = smbd_initialize_smb2(sconn);
2800 if (!NT_STATUS_IS_OK(status)) {
2801 smbd_server_connection_terminate(sconn, nt_errstr(status));
2805 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2806 if (!NT_STATUS_IS_OK(status)) {
2807 smbd_server_connection_terminate(sconn, nt_errstr(status));
2811 status = smbd_smb2_request_validate(req);
2812 if (!NT_STATUS_IS_OK(status)) {
2813 smbd_server_connection_terminate(sconn, nt_errstr(status));
2817 status = smbd_smb2_request_setup_out(req);
2818 if (!NT_STATUS_IS_OK(status)) {
2819 smbd_server_connection_terminate(sconn, nt_errstr(status));
2823 status = smbd_smb2_request_dispatch(req);
2824 if (!NT_STATUS_IS_OK(status)) {
2825 smbd_server_connection_terminate(sconn, nt_errstr(status));
2829 status = smbd_smb2_request_next_incoming(sconn);
2830 if (!NT_STATUS_IS_OK(status)) {
2831 smbd_server_connection_terminate(sconn, nt_errstr(status));
2835 sconn->num_requests++;
2838 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2840 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2841 struct smbd_server_connection);
2843 struct smbd_smb2_request *req = NULL;
2845 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2846 TALLOC_FREE(subreq);
2847 if (!NT_STATUS_IS_OK(status)) {
2848 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2849 nt_errstr(status)));
2850 smbd_server_connection_terminate(sconn, nt_errstr(status));
2854 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2855 req->current_idx, req->in.vector_count));
2857 status = smbd_smb2_request_validate(req);
2858 if (!NT_STATUS_IS_OK(status)) {
2859 smbd_server_connection_terminate(sconn, nt_errstr(status));
2863 status = smbd_smb2_request_setup_out(req);
2864 if (!NT_STATUS_IS_OK(status)) {
2865 smbd_server_connection_terminate(sconn, nt_errstr(status));
2869 status = smbd_smb2_request_dispatch(req);
2870 if (!NT_STATUS_IS_OK(status)) {
2871 smbd_server_connection_terminate(sconn, nt_errstr(status));
2875 status = smbd_smb2_request_next_incoming(sconn);
2876 if (!NT_STATUS_IS_OK(status)) {
2877 smbd_server_connection_terminate(sconn, nt_errstr(status));
2881 sconn->num_requests++;
2883 /* The timeout_processing function isn't run nearly
2884 often enough to implement 'max log size' without
2885 overrunning the size of the file by many megabytes.
2886 This is especially true if we are running at debug
2887 level 10. Checking every 50 SMB2s is a nice
2888 tradeoff of performance vs log file size overrun. */
2890 if ((sconn->num_requests % 50) == 0 &&
2891 need_to_check_log_size()) {
2892 change_to_root_user();