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 char *smb2_names[] = {
57 const char *smb2_opcode_name(uint16_t opcode)
60 return "Bad SMB2 opcode";
62 return smb2_names[opcode];
65 static void print_req_vectors(struct smbd_smb2_request *req)
69 for (i = 0; i < req->in.vector_count; i++) {
70 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
72 (unsigned int)req->in.vector[i].iov_len);
74 for (i = 0; i < req->out.vector_count; i++) {
75 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
77 (unsigned int)req->out.vector[i].iov_len);
81 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
83 if (size < (4 + SMB2_HDR_BODY)) {
87 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
94 static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
99 TALLOC_FREE(sconn->smb1.fde);
101 sconn->smb2.recv_queue = tevent_queue_create(sconn, "smb2 recv queue");
102 if (sconn->smb2.recv_queue == NULL) {
103 return NT_STATUS_NO_MEMORY;
106 sconn->smb2.send_queue = tevent_queue_create(sconn, "smb2 send queue");
107 if (sconn->smb2.send_queue == NULL) {
108 return NT_STATUS_NO_MEMORY;
111 sconn->smb2.seqnum_low = 0;
112 sconn->smb2.seqnum_range = 1;
113 sconn->smb2.credits_granted = 1;
114 sconn->smb2.max_credits = lp_smb2_max_credits();
115 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
116 sconn->smb2.max_credits);
117 if (sconn->smb2.credits_bitmap == NULL) {
118 return NT_STATUS_NO_MEMORY;
121 ret = tstream_bsd_existing_socket(sconn, sconn->sock,
122 &sconn->smb2.stream);
124 status = map_nt_error_from_unix(errno);
128 /* Ensure child is set to non-blocking mode */
129 set_blocking(sconn->sock, false);
133 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
134 #define _smb2_setlen(_buf,len) do { \
135 uint8_t *buf = (uint8_t *)_buf; \
137 buf[1] = ((len)&0xFF0000)>>16; \
138 buf[2] = ((len)&0xFF00)>>8; \
139 buf[3] = (len)&0xFF; \
142 static void smb2_setup_nbt_length(struct iovec *vector, int count)
147 for (i=1; i < count; i++) {
148 len += vector[i].iov_len;
151 _smb2_setlen(vector[0].iov_base, len);
154 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
156 TALLOC_CTX *mem_pool;
157 struct smbd_smb2_request *req;
160 /* Enable this to find subtle valgrind errors. */
161 mem_pool = talloc_init("smbd_smb2_request_allocate");
163 mem_pool = talloc_pool(mem_ctx, 8192);
165 if (mem_pool == NULL) {
169 req = talloc_zero(mem_pool, struct smbd_smb2_request);
171 talloc_free(mem_pool);
174 talloc_reparent(mem_pool, mem_ctx, req);
175 TALLOC_FREE(mem_pool);
177 req->last_session_id = UINT64_MAX;
178 req->last_tid = UINT32_MAX;
183 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn,
194 uint8_t *first_hdr = buf;
197 * Note: index '0' is reserved for the transport protocol
199 iov = talloc_zero_array(mem_ctx, struct iovec, num_iov);
201 return NT_STATUS_NO_MEMORY;
204 while (taken < buflen) {
205 size_t len = buflen - taken;
206 uint8_t *hdr = first_hdr + taken;
209 size_t next_command_ofs;
211 struct iovec *iov_tmp;
214 * We need the header plus the body length field
217 if (len < SMB2_HDR_BODY + 2) {
218 DEBUG(10, ("%d bytes left, expected at least %d\n",
219 (int)len, SMB2_HDR_BODY));
222 if (IVAL(hdr, 0) != SMB2_MAGIC) {
223 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
227 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
228 DEBUG(10, ("Got HDR len %d, expected %d\n",
229 SVAL(hdr, 4), SMB2_HDR_BODY));
234 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
235 body_size = SVAL(hdr, SMB2_HDR_BODY);
237 if (next_command_ofs != 0) {
238 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
241 if (next_command_ofs > full_size) {
244 full_size = next_command_ofs;
251 if (body_size > (full_size - SMB2_HDR_BODY)) {
253 * let the caller handle the error
255 body_size = full_size - SMB2_HDR_BODY;
258 iov_tmp = talloc_realloc(mem_ctx, iov, struct iovec,
260 if (iov_tmp == NULL) {
262 return NT_STATUS_NO_MEMORY;
268 cur[0].iov_base = hdr;
269 cur[0].iov_len = SMB2_HDR_BODY;
270 cur[1].iov_base = hdr + SMB2_HDR_BODY;
271 cur[1].iov_len = body_size;
272 cur[2].iov_base = hdr + SMB2_HDR_BODY + body_size;
273 cur[2].iov_len = full_size - (SMB2_HDR_BODY + body_size);
284 return NT_STATUS_INVALID_PARAMETER;
287 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
288 const uint8_t *inbuf, size_t size,
289 struct smbd_smb2_request **_req)
291 struct smbd_smb2_request *req;
292 uint32_t protocol_version;
293 const uint8_t *inhdr = NULL;
296 uint32_t next_command_ofs;
298 if (size < (4 + SMB2_HDR_BODY + 2)) {
299 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
300 return NT_STATUS_INVALID_PARAMETER;
305 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
306 if (protocol_version != SMB2_MAGIC) {
307 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
309 return NT_STATUS_INVALID_PARAMETER;
312 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
313 if (cmd != SMB2_OP_NEGPROT) {
314 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
316 return NT_STATUS_INVALID_PARAMETER;
319 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
320 if (next_command_ofs != 0) {
321 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
323 return NT_STATUS_INVALID_PARAMETER;
326 req = smbd_smb2_request_allocate(sconn);
328 return NT_STATUS_NO_MEMORY;
332 talloc_steal(req, inbuf);
334 req->in.vector = talloc_array(req, struct iovec, 4);
335 if (req->in.vector == NULL) {
337 return NT_STATUS_NO_MEMORY;
339 req->in.vector_count = 4;
341 memcpy(req->in.nbt_hdr, inbuf, 4);
344 req->in.vector[0].iov_base = discard_const_p(void, req->in.nbt_hdr);
345 req->in.vector[0].iov_len = 4;
346 ofs += req->in.vector[0].iov_len;
348 req->in.vector[1].iov_base = discard_const_p(void, (inbuf + ofs));
349 req->in.vector[1].iov_len = SMB2_HDR_BODY;
350 ofs += req->in.vector[1].iov_len;
352 req->in.vector[2].iov_base = discard_const_p(void, (inbuf + ofs));
353 req->in.vector[2].iov_len = SVAL(inbuf, ofs) & 0xFFFE;
354 ofs += req->in.vector[2].iov_len;
357 return NT_STATUS_INVALID_PARAMETER;
360 req->in.vector[3].iov_base = discard_const_p(void, (inbuf + ofs));
361 req->in.vector[3].iov_len = size - ofs;
362 ofs += req->in.vector[3].iov_len;
364 req->current_idx = 1;
370 static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
371 uint64_t message_id, uint64_t seq_id)
373 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
376 if (seq_id < sconn->smb2.seqnum_low) {
377 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
378 "%llu (sequence id %llu) "
379 "(granted = %u, low = %llu, range = %u)\n",
380 (unsigned long long)message_id,
381 (unsigned long long)seq_id,
382 (unsigned int)sconn->smb2.credits_granted,
383 (unsigned long long)sconn->smb2.seqnum_low,
384 (unsigned int)sconn->smb2.seqnum_range));
388 if (seq_id >= sconn->smb2.seqnum_low + sconn->smb2.seqnum_range) {
389 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
390 "%llu (sequence id %llu) "
391 "(granted = %u, low = %llu, range = %u)\n",
392 (unsigned long long)message_id,
393 (unsigned long long)seq_id,
394 (unsigned int)sconn->smb2.credits_granted,
395 (unsigned long long)sconn->smb2.seqnum_low,
396 (unsigned int)sconn->smb2.seqnum_range));
400 offset = seq_id % sconn->smb2.max_credits;
402 if (bitmap_query(credits_bm, offset)) {
403 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
404 "%llu (sequence id %llu) "
405 "(granted = %u, low = %llu, range = %u) "
407 (unsigned long long)message_id,
408 (unsigned long long)seq_id,
409 (unsigned int)sconn->smb2.credits_granted,
410 (unsigned long long)sconn->smb2.seqnum_low,
411 (unsigned int)sconn->smb2.seqnum_range,
416 /* Mark the message_ids as seen in the bitmap. */
417 bitmap_set(credits_bm, offset);
419 if (seq_id != sconn->smb2.seqnum_low) {
424 * Move the window forward by all the message_id's
427 while (bitmap_query(credits_bm, offset)) {
428 DEBUG(10,("smb2_validate_sequence_number: clearing "
429 "id %llu (position %u) from bitmap\n",
430 (unsigned long long)(sconn->smb2.seqnum_low),
432 bitmap_clear(credits_bm, offset);
434 sconn->smb2.seqnum_low += 1;
435 sconn->smb2.seqnum_range -= 1;
436 offset = sconn->smb2.seqnum_low % sconn->smb2.max_credits;
442 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
443 const uint8_t *inhdr)
445 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
446 uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
447 uint16_t credit_charge = 1;
450 if (opcode == SMB2_OP_CANCEL) {
451 /* SMB2_CANCEL requests by definition resend messageids. */
455 if (sconn->smb2.supports_multicredit) {
456 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
457 credit_charge = MAX(credit_charge, 1);
460 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
461 "credits_granted %llu, "
462 "seqnum low/range: %llu/%llu\n",
463 (unsigned long long) message_id,
464 (unsigned long long) credit_charge,
465 (unsigned long long) sconn->smb2.credits_granted,
466 (unsigned long long) sconn->smb2.seqnum_low,
467 (unsigned long long) sconn->smb2.seqnum_range));
469 if (sconn->smb2.credits_granted < credit_charge) {
470 DEBUG(0, ("smb2_validate_message_id: client used more "
471 "credits than granted, mid %llu, charge %llu, "
472 "credits_granted %llu, "
473 "seqnum low/range: %llu/%llu\n",
474 (unsigned long long) message_id,
475 (unsigned long long) credit_charge,
476 (unsigned long long) sconn->smb2.credits_granted,
477 (unsigned long long) sconn->smb2.seqnum_low,
478 (unsigned long long) sconn->smb2.seqnum_range));
483 * now check the message ids
485 * for multi-credit requests we need to check all current mid plus
486 * the implicit mids caused by the credit charge
487 * e.g. current mid = 15, charge 5 => mark 15-19 as used
490 for (i = 0; i <= (credit_charge-1); i++) {
491 uint64_t id = message_id + i;
494 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
495 (unsigned long long)message_id,
497 (unsigned long long)id));
499 ok = smb2_validate_sequence_number(sconn, message_id, id);
505 /* substract used credits */
506 sconn->smb2.credits_granted -= credit_charge;
511 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
516 count = req->in.vector_count;
519 /* It's not a SMB2 request */
520 return NT_STATUS_INVALID_PARAMETER;
523 for (idx=1; idx < count; idx += 3) {
524 const uint8_t *inhdr = NULL;
527 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
528 return NT_STATUS_INVALID_PARAMETER;
531 if (req->in.vector[idx+1].iov_len < 2) {
532 return NT_STATUS_INVALID_PARAMETER;
535 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
537 /* Check the SMB2 header */
538 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
539 return NT_STATUS_INVALID_PARAMETER;
542 if (!smb2_validate_message_id(req->sconn, inhdr)) {
543 return NT_STATUS_INVALID_PARAMETER;
546 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
549 * the 1st request should never have the
550 * SMB2_HDR_FLAG_CHAINED flag set
552 if (flags & SMB2_HDR_FLAG_CHAINED) {
553 req->next_status = NT_STATUS_INVALID_PARAMETER;
556 } else if (idx == 4) {
558 * the 2nd request triggers related vs. unrelated
559 * compounded requests
561 if (flags & SMB2_HDR_FLAG_CHAINED) {
562 req->compound_related = true;
564 } else if (idx > 4) {
567 * It seems the this tests are wrong
568 * see the SMB2-COMPOUND test
572 * all other requests should match the 2nd one
574 if (flags & SMB2_HDR_FLAG_CHAINED) {
575 if (!req->compound_related) {
577 NT_STATUS_INVALID_PARAMETER;
581 if (req->compound_related) {
583 NT_STATUS_INVALID_PARAMETER;
594 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
595 const struct iovec *in_vector,
596 struct iovec *out_vector)
598 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
599 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
600 uint16_t credit_charge = 1;
601 uint16_t credits_requested;
605 uint16_t credits_granted = 0;
606 uint64_t credits_possible;
607 uint16_t current_max_credits;
610 * first we grant only 1/16th of the max range.
612 * Windows also starts with the 1/16th and then grants
613 * more later. I was only able to trigger higher
614 * values, when using a verify high credit charge.
616 * TODO: scale up depending one load, free memory
618 * Maybe also on the relationship between number
619 * of requests and the used sequence number.
620 * Which means we would grant more credits
621 * for client which use multi credit requests.
623 current_max_credits = sconn->smb2.max_credits / 16;
624 current_max_credits = MAX(current_max_credits, 1);
626 if (sconn->smb2.supports_multicredit) {
627 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
628 credit_charge = MAX(credit_charge, 1);
631 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
632 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
633 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
634 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
636 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
637 SMB_ASSERT(sconn->smb2.max_credits >= credit_charge);
639 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
641 * In case we already send an async interim
642 * response, we should not grant
643 * credits on the final response.
646 } else if (credits_requested > 0) {
647 uint16_t additional_max = 0;
648 uint16_t additional_credits = credits_requested - 1;
651 case SMB2_OP_NEGPROT:
653 case SMB2_OP_SESSSETUP:
655 * Windows 2012 RC1 starts to grant
657 * with a successful session setup
659 if (NT_STATUS_IS_OK(out_status)) {
665 * We match windows and only grant additional credits
672 additional_credits = MIN(additional_credits, additional_max);
674 credits_granted = credit_charge + additional_credits;
675 } else if (sconn->smb2.credits_granted == 0) {
677 * Make sure the client has always at least one credit
683 * sequence numbers should not wrap
685 * 1. calculate the possible credits until
686 * the sequence numbers start to wrap on 64-bit.
688 * 2. UINT64_MAX is used for Break Notifications.
690 * 2. truncate the possible credits to the maximum
691 * credits we want to grant to the client in total.
693 * 3. remove the range we'll already granted to the client
694 * this makes sure the client consumes the lowest sequence
695 * number, before we can grant additional credits.
697 credits_possible = UINT64_MAX - sconn->smb2.seqnum_low;
698 if (credits_possible > 0) {
699 /* remove UINT64_MAX */
700 credits_possible -= 1;
702 credits_possible = MIN(credits_possible, current_max_credits);
703 credits_possible -= sconn->smb2.seqnum_range;
705 credits_granted = MIN(credits_granted, credits_possible);
707 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
708 sconn->smb2.credits_granted += credits_granted;
709 sconn->smb2.seqnum_range += credits_granted;
711 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
712 "granted %u, current possible/max %u/%u, "
713 "total granted/max/low/range %u/%u/%llu/%u\n",
714 (unsigned int)credits_requested,
715 (unsigned int)credit_charge,
716 (unsigned int)credits_granted,
717 (unsigned int)credits_possible,
718 (unsigned int)current_max_credits,
719 (unsigned int)sconn->smb2.credits_granted,
720 (unsigned int)sconn->smb2.max_credits,
721 (unsigned long long)sconn->smb2.seqnum_low,
722 (unsigned int)sconn->smb2.seqnum_range));
725 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
726 struct smbd_smb2_request *outreq)
729 uint16_t total_credits = 0;
731 count = outreq->out.vector_count;
733 for (idx=1; idx < count; idx += 3) {
734 uint8_t *outhdr = (uint8_t *)outreq->out.vector[idx].iov_base;
735 smb2_set_operation_credit(outreq->sconn,
736 &inreq->in.vector[idx],
737 &outreq->out.vector[idx]);
738 /* To match Windows, count up what we
740 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
741 /* Set to zero in all but the last reply. */
742 if (idx + 3 < count) {
743 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
745 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
750 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
752 struct iovec *vector;
756 req->request_time = timeval_current();
758 count = req->in.vector_count;
759 vector = talloc_zero_array(req, struct iovec, count);
760 if (vector == NULL) {
761 return NT_STATUS_NO_MEMORY;
764 vector[0].iov_base = req->out.nbt_hdr;
765 vector[0].iov_len = 4;
766 SIVAL(req->out.nbt_hdr, 0, 0);
768 for (idx=1; idx < count; idx += 3) {
769 const uint8_t *inhdr = NULL;
770 uint8_t *outhdr = NULL;
771 uint8_t *outbody = NULL;
772 uint32_t next_command_ofs = 0;
773 struct iovec *current = &vector[idx];
775 if ((idx + 3) < count) {
776 /* we have a next command -
777 * setup for the error case. */
778 next_command_ofs = SMB2_HDR_BODY + 9;
781 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
783 outhdr = talloc_zero_array(vector, uint8_t,
785 if (outhdr == NULL) {
786 return NT_STATUS_NO_MEMORY;
789 outbody = outhdr + SMB2_HDR_BODY;
791 current[0].iov_base = (void *)outhdr;
792 current[0].iov_len = SMB2_HDR_BODY;
794 current[1].iov_base = (void *)outbody;
795 current[1].iov_len = 8;
797 current[2].iov_base = NULL;
798 current[2].iov_len = 0;
800 /* setup the SMB2 header */
801 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
802 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
803 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
804 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
805 SIVAL(outhdr, SMB2_HDR_STATUS,
806 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
807 SSVAL(outhdr, SMB2_HDR_OPCODE,
808 SVAL(inhdr, SMB2_HDR_OPCODE));
809 SIVAL(outhdr, SMB2_HDR_FLAGS,
810 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
811 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
812 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
813 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
814 SIVAL(outhdr, SMB2_HDR_PID,
815 IVAL(inhdr, SMB2_HDR_PID));
816 SIVAL(outhdr, SMB2_HDR_TID,
817 IVAL(inhdr, SMB2_HDR_TID));
818 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
819 BVAL(inhdr, SMB2_HDR_SESSION_ID));
820 memcpy(outhdr + SMB2_HDR_SIGNATURE,
821 inhdr + SMB2_HDR_SIGNATURE, 16);
823 /* setup error body header */
824 SSVAL(outbody, 0x00, 0x08 + 1);
825 SSVAL(outbody, 0x02, 0);
826 SIVAL(outbody, 0x04, 0);
829 req->out.vector = vector;
830 req->out.vector_count = count;
832 /* setup the length of the NBT packet */
833 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
835 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
840 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
842 const char *location)
844 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
846 exit_server_cleanly(reason);
849 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
850 struct iovec *outvec,
851 const struct iovec *srcvec)
853 /* vec[0] is always boilerplate and must
854 * be allocated with size OUTVEC_ALLOC_SIZE. */
856 outvec[0].iov_base = talloc_memdup(ctx,
859 if (!outvec[0].iov_base) {
862 outvec[0].iov_len = SMB2_HDR_BODY;
865 * If this is a "standard" vec[1] of length 8,
866 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
867 * then duplicate this. Else use talloc_memdup().
870 if (srcvec[1].iov_len == 8 &&
871 srcvec[1].iov_base ==
872 ((uint8_t *)srcvec[0].iov_base) +
874 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
876 outvec[1].iov_len = 8;
878 outvec[1].iov_base = talloc_memdup(ctx,
881 if (!outvec[1].iov_base) {
884 outvec[1].iov_len = srcvec[1].iov_len;
888 * If this is a "standard" vec[2] of length 1,
889 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
890 * then duplicate this. Else use talloc_memdup().
893 if (srcvec[2].iov_base &&
895 if (srcvec[2].iov_base ==
896 ((uint8_t *)srcvec[0].iov_base) +
897 (OUTVEC_ALLOC_SIZE - 1) &&
898 srcvec[2].iov_len == 1) {
899 /* Common SMB2 error packet case. */
900 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
901 (OUTVEC_ALLOC_SIZE - 1);
903 outvec[2].iov_base = talloc_memdup(ctx,
906 if (!outvec[2].iov_base) {
910 outvec[2].iov_len = srcvec[2].iov_len;
912 outvec[2].iov_base = NULL;
913 outvec[2].iov_len = 0;
918 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
920 struct smbd_smb2_request *newreq = NULL;
921 struct iovec *outvec = NULL;
922 int count = req->out.vector_count;
925 newreq = smbd_smb2_request_allocate(req->sconn);
930 newreq->sconn = req->sconn;
931 newreq->session = req->session;
932 newreq->do_signing = req->do_signing;
933 newreq->current_idx = req->current_idx;
935 outvec = talloc_zero_array(newreq, struct iovec, count);
940 newreq->out.vector = outvec;
941 newreq->out.vector_count = count;
943 /* Setup the outvec's identically to req. */
944 outvec[0].iov_base = newreq->out.nbt_hdr;
945 outvec[0].iov_len = 4;
946 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
948 /* Setup the vectors identically to the ones in req. */
949 for (i = 1; i < count; i += 3) {
950 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
961 smb2_setup_nbt_length(newreq->out.vector,
962 newreq->out.vector_count);
967 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
969 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
972 uint8_t *outhdr = NULL;
973 struct smbd_smb2_request *nreq = NULL;
975 /* Create a new smb2 request we'll use
976 for the interim return. */
977 nreq = dup_smb2_req(req);
979 return NT_STATUS_NO_MEMORY;
982 /* Lose the last 3 out vectors. They're the
983 ones we'll be using for the async reply. */
984 nreq->out.vector_count -= 3;
986 smb2_setup_nbt_length(nreq->out.vector,
987 nreq->out.vector_count);
989 /* Step back to the previous reply. */
990 i = nreq->current_idx - 3;
991 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
992 /* And end the chain. */
993 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
995 /* Calculate outgoing credits */
996 smb2_calculate_credits(req, nreq);
998 /* Re-sign if needed. */
999 if (nreq->do_signing) {
1001 struct smbXsrv_session *x = nreq->session;
1002 struct smbXsrv_connection *conn = x->connection;
1003 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1005 status = smb2_signing_sign_pdu(signing_key,
1007 &nreq->out.vector[i], 3);
1008 if (!NT_STATUS_IS_OK(status)) {
1012 if (DEBUGLEVEL >= 10) {
1013 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1014 (unsigned int)nreq->current_idx );
1015 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1016 (unsigned int)nreq->out.vector_count );
1017 print_req_vectors(nreq);
1019 nreq->subreq = tstream_writev_queue_send(nreq,
1020 nreq->sconn->ev_ctx,
1021 nreq->sconn->smb2.stream,
1022 nreq->sconn->smb2.send_queue,
1024 nreq->out.vector_count);
1026 if (nreq->subreq == NULL) {
1027 return NT_STATUS_NO_MEMORY;
1030 tevent_req_set_callback(nreq->subreq,
1031 smbd_smb2_request_writev_done,
1034 return NT_STATUS_OK;
1037 struct smbd_smb2_request_pending_state {
1038 struct smbd_server_connection *sconn;
1039 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
1040 struct iovec vector[3];
1043 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
1045 struct smbd_smb2_request_pending_state *state =
1046 tevent_req_callback_data(subreq,
1047 struct smbd_smb2_request_pending_state);
1048 struct smbd_server_connection *sconn = state->sconn;
1052 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1053 TALLOC_FREE(subreq);
1055 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1056 smbd_server_connection_terminate(sconn, nt_errstr(status));
1063 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1064 struct tevent_timer *te,
1065 struct timeval current_time,
1066 void *private_data);
1068 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1069 struct tevent_req *subreq,
1070 uint32_t defer_time)
1073 int i = req->current_idx;
1074 struct timeval defer_endtime;
1075 uint8_t *outhdr = NULL;
1078 if (!tevent_req_is_in_progress(subreq)) {
1079 return NT_STATUS_OK;
1082 req->subreq = subreq;
1085 if (req->async_te) {
1086 /* We're already async. */
1087 return NT_STATUS_OK;
1090 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1091 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1092 if (flags & SMB2_HDR_FLAG_ASYNC) {
1093 /* We're already async. */
1094 return NT_STATUS_OK;
1097 if (req->in.vector_count > i + 3) {
1099 * We're trying to go async in a compound
1100 * request chain. This is not allowed.
1101 * Cancel the outstanding request.
1103 tevent_req_cancel(req->subreq);
1104 return smbd_smb2_request_error(req,
1105 NT_STATUS_INSUFFICIENT_RESOURCES);
1108 if (DEBUGLEVEL >= 10) {
1109 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1110 (unsigned int)req->current_idx );
1111 print_req_vectors(req);
1114 if (req->out.vector_count > 4) {
1115 struct iovec *outvec = NULL;
1117 /* This is a compound reply. We
1118 * must do an interim response
1119 * followed by the async response
1122 status = smb2_send_async_interim_response(req);
1123 if (!NT_STATUS_IS_OK(status)) {
1128 * We're splitting off the last SMB2
1129 * request in a compound set, and the
1130 * smb2_send_async_interim_response()
1131 * call above just sent all the replies
1132 * for the previous SMB2 requests in
1133 * this compound set. So we're no longer
1134 * in the "compound_related_in_progress"
1135 * state, and this is no longer a compound
1138 req->compound_related = false;
1139 req->sconn->smb2.compound_related_in_progress = false;
1141 /* Re-arrange the in.vectors. */
1142 req->in.vector[1] = req->in.vector[i];
1143 req->in.vector[2] = req->in.vector[i+1];
1144 req->in.vector[3] = req->in.vector[i+2];
1145 req->in.vector_count = 4;
1147 /* Reset the new in size. */
1148 smb2_setup_nbt_length(req->in.vector, 4);
1150 /* Now recreate the out.vectors. */
1151 outvec = talloc_zero_array(req, struct iovec, 4);
1153 return NT_STATUS_NO_MEMORY;
1156 /* 0 is always boilerplate and must
1157 * be of size 4 for the length field. */
1159 outvec[0].iov_base = req->out.nbt_hdr;
1160 outvec[0].iov_len = 4;
1161 SIVAL(req->out.nbt_hdr, 0, 0);
1163 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
1164 return NT_STATUS_NO_MEMORY;
1167 TALLOC_FREE(req->out.vector);
1169 req->out.vector = outvec;
1171 req->current_idx = 1;
1172 req->out.vector_count = 4;
1174 outhdr = (uint8_t *)req->out.vector[1].iov_base;
1175 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1176 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1179 defer_endtime = timeval_current_ofs_usec(defer_time);
1180 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1182 smbd_smb2_request_pending_timer,
1184 if (req->async_te == NULL) {
1185 return NT_STATUS_NO_MEMORY;
1188 return NT_STATUS_OK;
1191 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1192 struct tevent_timer *te,
1193 struct timeval current_time,
1196 struct smbd_smb2_request *req =
1197 talloc_get_type_abort(private_data,
1198 struct smbd_smb2_request);
1199 struct smbd_smb2_request_pending_state *state = NULL;
1200 uint8_t *outhdr = NULL;
1201 const uint8_t *inhdr = NULL;
1202 uint8_t *hdr = NULL;
1203 uint8_t *body = NULL;
1205 uint64_t message_id = 0;
1206 uint64_t async_id = 0;
1207 struct tevent_req *subreq = NULL;
1209 TALLOC_FREE(req->async_te);
1211 /* Ensure our final reply matches the interim one. */
1212 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1213 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1214 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1215 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1217 async_id = message_id; /* keep it simple for now... */
1219 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1220 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1222 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1224 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1225 (unsigned long long)async_id ));
1228 * What we send is identical to a smbd_smb2_request_error
1229 * packet with an error status of STATUS_PENDING. Make use
1230 * of this fact sometime when refactoring. JRA.
1233 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1234 if (state == NULL) {
1235 smbd_server_connection_terminate(req->sconn,
1236 nt_errstr(NT_STATUS_NO_MEMORY));
1239 state->sconn = req->sconn;
1241 state->vector[0].iov_base = (void *)state->buf;
1242 state->vector[0].iov_len = 4;
1244 state->vector[1].iov_base = state->buf + 4;
1245 state->vector[1].iov_len = SMB2_HDR_BODY;
1247 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
1248 state->vector[2].iov_len = 9;
1250 smb2_setup_nbt_length(state->vector, 3);
1252 hdr = (uint8_t *)state->vector[1].iov_base;
1253 body = (uint8_t *)state->vector[2].iov_base;
1255 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1256 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1257 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1258 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1259 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1261 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1262 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1263 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1264 SBVAL(hdr, SMB2_HDR_PID, async_id);
1265 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1266 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1267 memcpy(hdr+SMB2_HDR_SIGNATURE,
1268 outhdr+SMB2_HDR_SIGNATURE, 16);
1270 SSVAL(body, 0x00, 0x08 + 1);
1272 SCVAL(body, 0x02, 0);
1273 SCVAL(body, 0x03, 0);
1274 SIVAL(body, 0x04, 0);
1275 /* Match W2K8R2... */
1276 SCVAL(body, 0x08, 0x21);
1278 /* Ensure we correctly go through crediting. Grant
1279 the credits now, and zero credits on the final
1281 smb2_set_operation_credit(req->sconn,
1282 SMBD_SMB2_IN_HDR_IOV(req),
1285 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1287 if (req->do_signing) {
1289 struct smbXsrv_session *x = req->session;
1290 struct smbXsrv_connection *conn = x->connection;
1291 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1293 status = smb2_signing_sign_pdu(signing_key,
1295 &state->vector[1], 2);
1296 if (!NT_STATUS_IS_OK(status)) {
1297 smbd_server_connection_terminate(req->sconn,
1303 subreq = tstream_writev_queue_send(state,
1304 state->sconn->ev_ctx,
1305 state->sconn->smb2.stream,
1306 state->sconn->smb2.send_queue,
1309 if (subreq == NULL) {
1310 smbd_server_connection_terminate(state->sconn,
1311 nt_errstr(NT_STATUS_NO_MEMORY));
1314 tevent_req_set_callback(subreq,
1315 smbd_smb2_request_pending_writev_done,
1319 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1321 struct smbd_server_connection *sconn = req->sconn;
1322 struct smbd_smb2_request *cur;
1323 const uint8_t *inhdr;
1325 uint64_t search_message_id;
1326 uint64_t search_async_id;
1329 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1331 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1332 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1333 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1336 * we don't need the request anymore
1337 * cancel requests never have a response
1339 DLIST_REMOVE(req->sconn->smb2.requests, req);
1342 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1343 const uint8_t *outhdr;
1344 uint64_t message_id;
1347 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1349 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1350 async_id = BVAL(outhdr, SMB2_HDR_PID);
1352 if (flags & SMB2_HDR_FLAG_ASYNC) {
1353 if (search_async_id == async_id) {
1354 found_id = async_id;
1358 if (search_message_id == message_id) {
1359 found_id = message_id;
1365 if (cur && cur->subreq) {
1366 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1367 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1368 "cancel opcode[%s] mid %llu\n",
1369 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1370 (unsigned long long)found_id ));
1371 tevent_req_cancel(cur->subreq);
1374 return NT_STATUS_OK;
1377 /*************************************************************
1378 Ensure an incoming tid is a valid one for us to access.
1379 Change to the associated uid credentials and chdir to the
1380 valid tid directory.
1381 *************************************************************/
1383 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1385 const uint8_t *inhdr;
1388 struct smbXsrv_tcon *tcon;
1390 NTTIME now = timeval_to_nttime(&req->request_time);
1394 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1396 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1397 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1399 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1400 in_tid = req->last_tid;
1403 status = smb2srv_tcon_lookup(req->session,
1404 in_tid, now, &tcon);
1405 if (!NT_STATUS_IS_OK(status)) {
1409 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1410 return NT_STATUS_ACCESS_DENIED;
1413 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1414 if (!set_current_service(tcon->compat, 0, true)) {
1415 return NT_STATUS_ACCESS_DENIED;
1419 req->last_tid = in_tid;
1421 return NT_STATUS_OK;
1424 /*************************************************************
1425 Ensure an incoming session_id is a valid one for us to access.
1426 *************************************************************/
1428 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1430 const uint8_t *inhdr;
1433 uint64_t in_session_id;
1434 struct smbXsrv_session *session = NULL;
1435 struct auth_session_info *session_info;
1437 NTTIME now = timeval_to_nttime(&req->request_time);
1439 req->session = NULL;
1442 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1444 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1445 in_opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1446 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1448 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1449 in_session_id = req->last_session_id;
1452 /* lookup an existing session */
1453 status = smb2srv_session_lookup(req->sconn->conn,
1457 req->session = session;
1458 req->last_session_id = in_session_id;
1460 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1461 switch (in_opcode) {
1462 case SMB2_OP_SESSSETUP:
1463 status = NT_STATUS_OK;
1469 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1470 switch (in_opcode) {
1472 case SMB2_OP_CREATE:
1473 case SMB2_OP_GETINFO:
1474 case SMB2_OP_SETINFO:
1475 return NT_STATUS_INVALID_HANDLE;
1478 * Notice the check for
1479 * (session_info == NULL)
1482 status = NT_STATUS_OK;
1486 if (!NT_STATUS_IS_OK(status)) {
1490 session_info = session->global->auth_session_info;
1491 if (session_info == NULL) {
1492 return NT_STATUS_INVALID_HANDLE;
1495 set_current_user_info(session_info->unix_info->sanitized_username,
1496 session_info->unix_info->unix_name,
1497 session_info->info->domain_name);
1499 return NT_STATUS_OK;
1502 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1503 uint32_t data_length)
1505 uint16_t needed_charge;
1506 uint16_t credit_charge = 1;
1507 const uint8_t *inhdr;
1509 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1511 if (req->sconn->smb2.supports_multicredit) {
1512 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1513 credit_charge = MAX(credit_charge, 1);
1516 needed_charge = (data_length - 1)/ 65536 + 1;
1518 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1519 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1520 credit_charge, needed_charge));
1522 if (needed_charge > credit_charge) {
1523 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1524 credit_charge, needed_charge));
1525 return NT_STATUS_INVALID_PARAMETER;
1528 return NT_STATUS_OK;
1531 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1532 size_t expected_body_size)
1534 const uint8_t *inhdr;
1536 const uint8_t *inbody;
1537 int i = req->current_idx;
1539 size_t min_dyn_size = expected_body_size & 0x00000001;
1542 * The following should be checked already.
1544 if ((i+2) > req->in.vector_count) {
1545 return NT_STATUS_INTERNAL_ERROR;
1547 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1548 return NT_STATUS_INTERNAL_ERROR;
1550 if (req->in.vector[i+1].iov_len < 2) {
1551 return NT_STATUS_INTERNAL_ERROR;
1554 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1555 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1559 case SMB2_OP_GETINFO:
1565 * Now check the expected body size,
1566 * where the last byte might be in the
1569 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1570 return NT_STATUS_INVALID_PARAMETER;
1572 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1573 return NT_STATUS_INVALID_PARAMETER;
1576 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1578 body_size = SVAL(inbody, 0x00);
1579 if (body_size != expected_body_size) {
1580 return NT_STATUS_INVALID_PARAMETER;
1583 return NT_STATUS_OK;
1586 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1588 const uint8_t *inhdr;
1593 NTSTATUS session_status;
1594 uint32_t allowed_flags;
1595 NTSTATUS return_value;
1596 struct smbXsrv_session *x = NULL;
1597 bool signing_required = false;
1599 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1601 /* TODO: verify more things */
1603 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1604 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1605 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1606 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1607 smb2_opcode_name(opcode),
1608 (unsigned long long)mid));
1610 if (get_Protocol() >= PROTOCOL_SMB2_02) {
1612 * once the protocol is negotiated
1613 * SMB2_OP_NEGPROT is not allowed anymore
1615 if (opcode == SMB2_OP_NEGPROT) {
1616 /* drop the connection */
1617 return NT_STATUS_INVALID_PARAMETER;
1621 * if the protocol is not negotiated yet
1622 * only SMB2_OP_NEGPROT is allowed.
1624 if (opcode != SMB2_OP_NEGPROT) {
1625 /* drop the connection */
1626 return NT_STATUS_INVALID_PARAMETER;
1630 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1631 SMB2_HDR_FLAG_SIGNED |
1633 if (opcode == SMB2_OP_CANCEL) {
1634 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1636 if ((flags & ~allowed_flags) != 0) {
1637 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1641 * Check if the client provided a valid session id,
1642 * if so smbd_smb2_request_check_session() calls
1643 * set_current_user_info().
1645 * As some command don't require a valid session id
1646 * we defer the check of the session_status
1648 session_status = smbd_smb2_request_check_session(req);
1652 signing_required = x->global->signing_required;
1654 if (opcode == SMB2_OP_SESSSETUP &&
1655 x->global->channels[0].signing_key.length) {
1656 signing_required = true;
1660 req->do_signing = false;
1661 if (flags & SMB2_HDR_FLAG_SIGNED) {
1662 struct smbXsrv_connection *conn;
1663 DATA_BLOB signing_key;
1666 return smbd_smb2_request_error(
1667 req, NT_STATUS_ACCESS_DENIED);
1670 conn = x->connection;
1671 signing_key = x->global->channels[0].signing_key;
1673 if (!NT_STATUS_IS_OK(session_status)) {
1674 return smbd_smb2_request_error(req, session_status);
1677 req->do_signing = true;
1678 status = smb2_signing_check_pdu(signing_key,
1680 SMBD_SMB2_IN_HDR_IOV(req), 3);
1681 if (!NT_STATUS_IS_OK(status)) {
1682 return smbd_smb2_request_error(req, status);
1684 } else if (opcode == SMB2_OP_CANCEL) {
1685 /* Cancel requests are allowed to skip the signing */
1686 } else if (signing_required) {
1687 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1690 if (flags & SMB2_HDR_FLAG_CHAINED) {
1692 * This check is mostly for giving the correct error code
1693 * for compounded requests.
1695 * TODO: we may need to move this after the session
1698 if (!NT_STATUS_IS_OK(req->next_status)) {
1699 return smbd_smb2_request_error(req, req->next_status);
1702 req->compat_chain_fsp = NULL;
1705 if (req->compound_related) {
1706 req->sconn->smb2.compound_related_in_progress = true;
1710 case SMB2_OP_NEGPROT:
1711 /* This call needs to be run as root */
1712 change_to_root_user();
1715 START_PROFILE(smb2_negprot);
1716 return_value = smbd_smb2_request_process_negprot(req);
1717 END_PROFILE(smb2_negprot);
1721 case SMB2_OP_SESSSETUP:
1722 /* This call needs to be run as root */
1723 change_to_root_user();
1726 START_PROFILE(smb2_sesssetup);
1727 return_value = smbd_smb2_request_process_sesssetup(req);
1728 END_PROFILE(smb2_sesssetup);
1732 case SMB2_OP_LOGOFF:
1733 if (!NT_STATUS_IS_OK(session_status)) {
1734 return_value = smbd_smb2_request_error(req, session_status);
1738 /* This call needs to be run as root */
1739 change_to_root_user();
1742 START_PROFILE(smb2_logoff);
1743 return_value = smbd_smb2_request_process_logoff(req);
1744 END_PROFILE(smb2_logoff);
1749 if (!NT_STATUS_IS_OK(session_status)) {
1750 return_value = smbd_smb2_request_error(req, session_status);
1755 * This call needs to be run as root.
1757 * smbd_smb2_request_process_tcon()
1758 * calls make_connection_snum(), which will call
1759 * change_to_user(), when needed.
1761 change_to_root_user();
1764 START_PROFILE(smb2_tcon);
1765 return_value = smbd_smb2_request_process_tcon(req);
1766 END_PROFILE(smb2_tcon);
1771 if (!NT_STATUS_IS_OK(session_status)) {
1772 return_value = smbd_smb2_request_error(req, session_status);
1776 * This call needs to be run as user.
1778 * smbd_smb2_request_check_tcon()
1779 * calls change_to_user() on success.
1781 status = smbd_smb2_request_check_tcon(req);
1782 if (!NT_STATUS_IS_OK(status)) {
1783 return_value = smbd_smb2_request_error(req, status);
1786 /* This call needs to be run as root */
1787 change_to_root_user();
1791 START_PROFILE(smb2_tdis);
1792 return_value = smbd_smb2_request_process_tdis(req);
1793 END_PROFILE(smb2_tdis);
1797 case SMB2_OP_CREATE:
1798 if (!NT_STATUS_IS_OK(session_status)) {
1799 return_value = smbd_smb2_request_error(req, session_status);
1803 * This call needs to be run as user.
1805 * smbd_smb2_request_check_tcon()
1806 * calls change_to_user() on success.
1808 status = smbd_smb2_request_check_tcon(req);
1809 if (!NT_STATUS_IS_OK(status)) {
1810 return_value = smbd_smb2_request_error(req, status);
1815 START_PROFILE(smb2_create);
1816 return_value = smbd_smb2_request_process_create(req);
1817 END_PROFILE(smb2_create);
1822 if (!NT_STATUS_IS_OK(session_status)) {
1823 return_value = smbd_smb2_request_error(req, session_status);
1827 * This call needs to be run as user.
1829 * smbd_smb2_request_check_tcon()
1830 * calls change_to_user() on success.
1832 status = smbd_smb2_request_check_tcon(req);
1833 if (!NT_STATUS_IS_OK(status)) {
1834 return_value = smbd_smb2_request_error(req, status);
1839 START_PROFILE(smb2_close);
1840 return_value = smbd_smb2_request_process_close(req);
1841 END_PROFILE(smb2_close);
1846 if (!NT_STATUS_IS_OK(session_status)) {
1847 return_value = smbd_smb2_request_error(req, session_status);
1851 * This call needs to be run as user.
1853 * smbd_smb2_request_check_tcon()
1854 * calls change_to_user() on success.
1856 status = smbd_smb2_request_check_tcon(req);
1857 if (!NT_STATUS_IS_OK(status)) {
1858 return_value = smbd_smb2_request_error(req, status);
1863 START_PROFILE(smb2_flush);
1864 return_value = smbd_smb2_request_process_flush(req);
1865 END_PROFILE(smb2_flush);
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_read);
1888 return_value = smbd_smb2_request_process_read(req);
1889 END_PROFILE(smb2_read);
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_write);
1912 return_value = smbd_smb2_request_process_write(req);
1913 END_PROFILE(smb2_write);
1918 if (!NT_STATUS_IS_OK(session_status)) {
1919 /* Too ugly to live ? JRA. */
1920 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1921 session_status = NT_STATUS_FILE_CLOSED;
1923 return_value = smbd_smb2_request_error(req, session_status);
1927 * This call needs to be run as user.
1929 * smbd_smb2_request_check_tcon()
1930 * calls change_to_user() on success.
1932 status = smbd_smb2_request_check_tcon(req);
1933 if (!NT_STATUS_IS_OK(status)) {
1934 /* Too ugly to live ? JRA. */
1935 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1936 status = NT_STATUS_FILE_CLOSED;
1938 return_value = smbd_smb2_request_error(req, status);
1943 START_PROFILE(smb2_lock);
1944 return_value = smbd_smb2_request_process_lock(req);
1945 END_PROFILE(smb2_lock);
1950 if (!NT_STATUS_IS_OK(session_status)) {
1951 return_value = smbd_smb2_request_error(req, session_status);
1955 * This call needs to be run as user.
1957 * smbd_smb2_request_check_tcon()
1958 * calls change_to_user() on success.
1960 status = smbd_smb2_request_check_tcon(req);
1961 if (!NT_STATUS_IS_OK(status)) {
1962 return_value = smbd_smb2_request_error(req, status);
1967 START_PROFILE(smb2_ioctl);
1968 return_value = smbd_smb2_request_process_ioctl(req);
1969 END_PROFILE(smb2_ioctl);
1973 case SMB2_OP_CANCEL:
1975 * This call needs to be run as root
1977 * That is what we also do in the SMB1 case.
1979 change_to_root_user();
1982 START_PROFILE(smb2_cancel);
1983 return_value = smbd_smb2_request_process_cancel(req);
1984 END_PROFILE(smb2_cancel);
1988 case SMB2_OP_KEEPALIVE:
1989 /* This call needs to be run as root */
1990 change_to_root_user();
1993 START_PROFILE(smb2_keepalive);
1994 return_value = smbd_smb2_request_process_keepalive(req);
1995 END_PROFILE(smb2_keepalive);
2000 if (!NT_STATUS_IS_OK(session_status)) {
2001 return_value = smbd_smb2_request_error(req, session_status);
2005 * This call needs to be run as user.
2007 * smbd_smb2_request_check_tcon()
2008 * calls change_to_user() on success.
2010 status = smbd_smb2_request_check_tcon(req);
2011 if (!NT_STATUS_IS_OK(status)) {
2012 return_value = smbd_smb2_request_error(req, status);
2017 START_PROFILE(smb2_find);
2018 return_value = smbd_smb2_request_process_find(req);
2019 END_PROFILE(smb2_find);
2023 case SMB2_OP_NOTIFY:
2024 if (!NT_STATUS_IS_OK(session_status)) {
2025 return_value = smbd_smb2_request_error(req, session_status);
2029 * This call needs to be run as user.
2031 * smbd_smb2_request_check_tcon()
2032 * calls change_to_user() on success.
2034 status = smbd_smb2_request_check_tcon(req);
2035 if (!NT_STATUS_IS_OK(status)) {
2036 return_value = smbd_smb2_request_error(req, status);
2041 START_PROFILE(smb2_notify);
2042 return_value = smbd_smb2_request_process_notify(req);
2043 END_PROFILE(smb2_notify);
2047 case SMB2_OP_GETINFO:
2048 if (!NT_STATUS_IS_OK(session_status)) {
2049 return_value = smbd_smb2_request_error(req, session_status);
2053 * This call needs to be run as user.
2055 * smbd_smb2_request_check_tcon()
2056 * calls change_to_user() on success.
2058 status = smbd_smb2_request_check_tcon(req);
2059 if (!NT_STATUS_IS_OK(status)) {
2060 return_value = smbd_smb2_request_error(req, status);
2065 START_PROFILE(smb2_getinfo);
2066 return_value = smbd_smb2_request_process_getinfo(req);
2067 END_PROFILE(smb2_getinfo);
2071 case SMB2_OP_SETINFO:
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_setinfo);
2090 return_value = smbd_smb2_request_process_setinfo(req);
2091 END_PROFILE(smb2_setinfo);
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_break);
2114 return_value = smbd_smb2_request_process_break(req);
2115 END_PROFILE(smb2_break);
2120 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2123 return return_value;
2126 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2128 struct tevent_req *subreq;
2129 int i = req->current_idx;
2132 TALLOC_FREE(req->async_te);
2134 req->current_idx += 3;
2136 if (req->current_idx < req->out.vector_count) {
2138 * We must process the remaining compound
2139 * SMB2 requests before any new incoming SMB2
2140 * requests. This is because incoming SMB2
2141 * requests may include a cancel for a
2142 * compound request we haven't processed
2145 struct tevent_immediate *im = tevent_create_immediate(req);
2147 return NT_STATUS_NO_MEMORY;
2149 tevent_schedule_immediate(im,
2151 smbd_smb2_request_dispatch_immediate,
2153 return NT_STATUS_OK;
2156 if (req->compound_related) {
2157 req->sconn->smb2.compound_related_in_progress = false;
2160 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2162 /* Set credit for these operations (zero credits if this
2163 is a final reply for an async operation). */
2164 smb2_calculate_credits(req, req);
2166 if (req->do_signing) {
2168 struct smbXsrv_session *x = req->session;
2169 struct smbXsrv_connection *conn = x->connection;
2170 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2172 status = smb2_signing_sign_pdu(signing_key,
2174 &req->out.vector[i], 3);
2175 if (!NT_STATUS_IS_OK(status)) {
2180 if (DEBUGLEVEL >= 10) {
2181 dbgtext("smbd_smb2_request_reply: sending...\n");
2182 print_req_vectors(req);
2185 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2186 if (req->out.vector_count == 4 &&
2187 req->out.vector[3].iov_base == NULL &&
2188 req->out.vector[3].iov_len != 0) {
2189 /* Dynamic part is NULL. Chop it off,
2190 We're going to send it via sendfile. */
2191 req->out.vector_count -= 1;
2194 subreq = tstream_writev_queue_send(req,
2196 req->sconn->smb2.stream,
2197 req->sconn->smb2.send_queue,
2199 req->out.vector_count);
2200 if (subreq == NULL) {
2201 return NT_STATUS_NO_MEMORY;
2203 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
2205 * We're done with this request -
2206 * move it off the "being processed" queue.
2208 DLIST_REMOVE(req->sconn->smb2.requests, req);
2210 return NT_STATUS_OK;
2213 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2215 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2216 struct tevent_immediate *im,
2219 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2220 struct smbd_smb2_request);
2221 struct smbd_server_connection *sconn = req->sconn;
2226 if (DEBUGLEVEL >= 10) {
2227 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2228 req->current_idx, req->in.vector_count));
2229 print_req_vectors(req);
2232 status = smbd_smb2_request_dispatch(req);
2233 if (!NT_STATUS_IS_OK(status)) {
2234 smbd_server_connection_terminate(sconn, nt_errstr(status));
2238 status = smbd_smb2_request_next_incoming(sconn);
2239 if (!NT_STATUS_IS_OK(status)) {
2240 smbd_server_connection_terminate(sconn, nt_errstr(status));
2245 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
2247 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
2248 struct smbd_smb2_request);
2249 struct smbd_server_connection *sconn = req->sconn;
2254 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2255 TALLOC_FREE(subreq);
2258 status = map_nt_error_from_unix(sys_errno);
2259 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2260 nt_errstr(status)));
2261 smbd_server_connection_terminate(sconn, nt_errstr(status));
2265 status = smbd_smb2_request_next_incoming(sconn);
2266 if (!NT_STATUS_IS_OK(status)) {
2267 smbd_server_connection_terminate(sconn, nt_errstr(status));
2272 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2274 DATA_BLOB body, DATA_BLOB *dyn,
2275 const char *location)
2278 int i = req->current_idx;
2279 uint32_t next_command_ofs;
2281 DEBUG(10,("smbd_smb2_request_done_ex: "
2282 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2283 i, nt_errstr(status), (unsigned int)body.length,
2285 (unsigned int)(dyn ? dyn->length : 0),
2288 if (body.length < 2) {
2289 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2292 if ((body.length % 2) != 0) {
2293 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2296 outhdr = (uint8_t *)req->out.vector[i].iov_base;
2298 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2299 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2301 req->out.vector[i+1].iov_base = (void *)body.data;
2302 req->out.vector[i+1].iov_len = body.length;
2305 req->out.vector[i+2].iov_base = (void *)dyn->data;
2306 req->out.vector[i+2].iov_len = dyn->length;
2308 req->out.vector[i+2].iov_base = NULL;
2309 req->out.vector[i+2].iov_len = 0;
2312 /* see if we need to recalculate the offset to the next response */
2313 if (next_command_ofs > 0) {
2314 next_command_ofs = SMB2_HDR_BODY;
2315 next_command_ofs += req->out.vector[i+1].iov_len;
2316 next_command_ofs += req->out.vector[i+2].iov_len;
2319 if ((next_command_ofs % 8) != 0) {
2320 size_t pad_size = 8 - (next_command_ofs % 8);
2321 if (req->out.vector[i+2].iov_len == 0) {
2323 * if the dyn buffer is empty
2324 * we can use it to add padding
2328 pad = talloc_zero_array(req->out.vector,
2331 return smbd_smb2_request_error(req,
2332 NT_STATUS_NO_MEMORY);
2335 req->out.vector[i+2].iov_base = (void *)pad;
2336 req->out.vector[i+2].iov_len = pad_size;
2339 * For now we copy the dynamic buffer
2340 * and add the padding to the new buffer
2347 old_size = req->out.vector[i+2].iov_len;
2348 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2350 new_size = old_size + pad_size;
2351 new_dyn = talloc_zero_array(req->out.vector,
2353 if (new_dyn == NULL) {
2354 return smbd_smb2_request_error(req,
2355 NT_STATUS_NO_MEMORY);
2358 memcpy(new_dyn, old_dyn, old_size);
2359 memset(new_dyn + old_size, 0, pad_size);
2361 req->out.vector[i+2].iov_base = (void *)new_dyn;
2362 req->out.vector[i+2].iov_len = new_size;
2364 next_command_ofs += pad_size;
2367 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2369 return smbd_smb2_request_reply(req);
2372 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2375 const char *location)
2378 int i = req->current_idx;
2379 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2381 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2382 i, nt_errstr(status), info ? " +info" : "",
2385 body.data = outhdr + SMB2_HDR_BODY;
2387 SSVAL(body.data, 0, 9);
2390 SIVAL(body.data, 0x04, info->length);
2392 /* Allocated size of req->out.vector[i].iov_base
2393 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2394 * 1 byte without having to do an alloc.
2396 info = talloc_zero_array(req->out.vector,
2400 return NT_STATUS_NO_MEMORY;
2402 info->data = ((uint8_t *)outhdr) +
2403 OUTVEC_ALLOC_SIZE - 1;
2405 SCVAL(info->data, 0, 0);
2409 * if a request fails, all other remaining
2410 * compounded requests should fail too
2412 req->next_status = NT_STATUS_INVALID_PARAMETER;
2414 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2418 struct smbd_smb2_send_oplock_break_state {
2419 struct smbd_server_connection *sconn;
2420 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2421 struct iovec vector;
2424 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2426 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2427 uint64_t file_id_persistent,
2428 uint64_t file_id_volatile,
2429 uint8_t oplock_level)
2431 struct smbd_smb2_send_oplock_break_state *state;
2432 struct tevent_req *subreq;
2436 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2437 if (state == NULL) {
2438 return NT_STATUS_NO_MEMORY;
2440 state->sconn = sconn;
2442 state->vector.iov_base = (void *)state->buf;
2443 state->vector.iov_len = sizeof(state->buf);
2445 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2446 hdr = state->buf + 4;
2447 body = hdr + SMB2_HDR_BODY;
2449 SIVAL(hdr, 0, SMB2_MAGIC);
2450 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2451 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2452 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2453 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2454 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2455 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2456 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2457 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2458 SIVAL(hdr, SMB2_HDR_PID, 0);
2459 SIVAL(hdr, SMB2_HDR_TID, 0);
2460 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2461 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2463 SSVAL(body, 0x00, 0x18);
2465 SCVAL(body, 0x02, oplock_level);
2466 SCVAL(body, 0x03, 0); /* reserved */
2467 SIVAL(body, 0x04, 0); /* reserved */
2468 SBVAL(body, 0x08, file_id_persistent);
2469 SBVAL(body, 0x10, file_id_volatile);
2471 subreq = tstream_writev_queue_send(state,
2474 sconn->smb2.send_queue,
2476 if (subreq == NULL) {
2477 return NT_STATUS_NO_MEMORY;
2479 tevent_req_set_callback(subreq,
2480 smbd_smb2_oplock_break_writev_done,
2483 return NT_STATUS_OK;
2486 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2488 struct smbd_smb2_send_oplock_break_state *state =
2489 tevent_req_callback_data(subreq,
2490 struct smbd_smb2_send_oplock_break_state);
2491 struct smbd_server_connection *sconn = state->sconn;
2495 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2496 TALLOC_FREE(subreq);
2498 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2499 smbd_server_connection_terminate(sconn, nt_errstr(status));
2506 struct smbd_smb2_request_read_state {
2508 bool asked_for_header;
2509 struct smbd_smb2_request *smb2_req;
2512 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2514 TALLOC_CTX *mem_ctx,
2515 struct iovec **_vector,
2517 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2519 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2520 struct tevent_context *ev,
2521 struct smbd_server_connection *sconn)
2523 struct tevent_req *req;
2524 struct smbd_smb2_request_read_state *state;
2525 struct tevent_req *subreq;
2527 req = tevent_req_create(mem_ctx, &state,
2528 struct smbd_smb2_request_read_state);
2533 state->asked_for_header = false;
2535 state->smb2_req = smbd_smb2_request_allocate(state);
2536 if (tevent_req_nomem(state->smb2_req, req)) {
2537 return tevent_req_post(req, ev);
2539 state->smb2_req->sconn = sconn;
2541 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2542 sconn->smb2.recv_queue,
2543 smbd_smb2_request_next_vector,
2545 if (tevent_req_nomem(subreq, req)) {
2546 return tevent_req_post(req, ev);
2548 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2553 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2555 TALLOC_CTX *mem_ctx,
2556 struct iovec **_vector,
2559 struct smbd_smb2_request_read_state *state =
2560 talloc_get_type_abort(private_data,
2561 struct smbd_smb2_request_read_state);
2562 struct smbd_smb2_request *req = state->smb2_req;
2563 struct iovec *vector;
2564 int idx = req->in.vector_count;
2566 uint8_t *buf = NULL;
2568 if (req->in.vector_count == 0) {
2570 * first we need to get the NBT header
2572 req->in.vector = talloc_array(req, struct iovec,
2573 req->in.vector_count + 1);
2574 if (req->in.vector == NULL) {
2577 req->in.vector_count += 1;
2579 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2580 req->in.vector[idx].iov_len = 4;
2582 vector = talloc_array(mem_ctx, struct iovec, 1);
2583 if (vector == NULL) {
2587 vector[0] = req->in.vector[idx];
2594 if (req->in.vector_count == 1) {
2596 * Now we analyze the NBT header
2598 state->missing = smb2_len(req->in.vector[0].iov_base);
2600 if (state->missing == 0) {
2601 /* if there're no remaining bytes, we're done */
2607 req->in.vector = talloc_realloc(req, req->in.vector,
2609 req->in.vector_count + 1);
2610 if (req->in.vector == NULL) {
2613 req->in.vector_count += 1;
2615 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2617 * it's a special NBT message,
2618 * so get all remaining bytes
2620 len = state->missing;
2621 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2623 * it's an invalid message, just read what we can get
2624 * and let the caller handle the error
2626 len = state->missing;
2629 * We assume it's a SMB2 request,
2630 * and we first get the header and the
2631 * first 2 bytes (the struct size) of the body
2633 len = SMB2_HDR_BODY + 2;
2635 state->asked_for_header = true;
2638 state->missing -= len;
2640 buf = talloc_array(req->in.vector, uint8_t, len);
2645 req->in.vector[idx].iov_base = (void *)buf;
2646 req->in.vector[idx].iov_len = len;
2648 vector = talloc_array(mem_ctx, struct iovec, 1);
2649 if (vector == NULL) {
2653 vector[0] = req->in.vector[idx];
2660 if (state->missing == 0) {
2661 /* if there're no remaining bytes, we're done */
2667 if (state->asked_for_header) {
2670 size_t next_command_ofs;
2675 bool invalid = false;
2677 state->asked_for_header = false;
2680 * We got the SMB2 header and the first 2 bytes
2681 * of the body. We fix the size to just the header
2682 * and manually copy the 2 first bytes to the body section
2684 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2685 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2687 /* allocate vectors for body and dynamic areas */
2688 req->in.vector = talloc_realloc(req, req->in.vector,
2690 req->in.vector_count + 2);
2691 if (req->in.vector == NULL) {
2694 req->in.vector_count += 2;
2696 full_size = state->missing + SMB2_HDR_BODY + 2;
2697 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2698 body_size = SVAL(hdr, SMB2_HDR_BODY);
2700 if (next_command_ofs != 0) {
2701 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2703 * this is invalid, just return a zero
2704 * body and let the caller deal with the error
2707 } else if (next_command_ofs > full_size) {
2709 * this is invalid, just return a zero
2710 * body and let the caller deal with the error
2714 full_size = next_command_ofs;
2719 if (body_size < 2) {
2721 * this is invalid, just return a zero
2722 * body and let the caller deal with the error
2728 * Mask out the lowest bit, the "dynamic" part
2733 if (body_size > (full_size - SMB2_HDR_BODY)) {
2735 * this is invalid, just return a zero
2736 * body and let the caller deal with the error
2743 /* the caller should check this */
2747 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2749 state->missing -= (body_size - 2) + dyn_size;
2751 body = talloc_array(req->in.vector, uint8_t, body_size);
2756 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2761 req->in.vector[idx].iov_base = (void *)body;
2762 req->in.vector[idx].iov_len = body_size;
2763 req->in.vector[idx+1].iov_base = (void *)dyn;
2764 req->in.vector[idx+1].iov_len = dyn_size;
2766 vector = talloc_array(mem_ctx, struct iovec, 2);
2767 if (vector == NULL) {
2772 * the first 2 bytes of the body were already fetched
2773 * together with the header
2775 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2776 vector[0].iov_base = body + 2;
2777 vector[0].iov_len = body_size - 2;
2779 vector[1] = req->in.vector[idx+1];
2787 * when we endup here, we're looking for a new SMB2 request
2788 * next. And we ask for its header and the first 2 bytes of
2789 * the body (like we did for the first SMB2 request).
2792 req->in.vector = talloc_realloc(req, req->in.vector,
2794 req->in.vector_count + 1);
2795 if (req->in.vector == NULL) {
2798 req->in.vector_count += 1;
2801 * We assume it's a SMB2 request,
2802 * and we first get the header and the
2803 * first 2 bytes (the struct size) of the body
2805 len = SMB2_HDR_BODY + 2;
2807 if (len > state->missing) {
2808 /* let the caller handle the error */
2809 len = state->missing;
2812 state->missing -= len;
2813 state->asked_for_header = true;
2815 buf = talloc_array(req->in.vector, uint8_t, len);
2820 req->in.vector[idx].iov_base = (void *)buf;
2821 req->in.vector[idx].iov_len = len;
2823 vector = talloc_array(mem_ctx, struct iovec, 1);
2824 if (vector == NULL) {
2828 vector[0] = req->in.vector[idx];
2835 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2837 struct tevent_req *req =
2838 tevent_req_callback_data(subreq,
2844 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2846 status = map_nt_error_from_unix(sys_errno);
2847 tevent_req_nterror(req, status);
2851 tevent_req_done(req);
2854 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2855 TALLOC_CTX *mem_ctx,
2856 struct smbd_smb2_request **_smb2_req)
2858 struct smbd_smb2_request_read_state *state =
2859 tevent_req_data(req,
2860 struct smbd_smb2_request_read_state);
2863 if (tevent_req_is_nterror(req, &status)) {
2864 tevent_req_received(req);
2868 *_smb2_req = talloc_move(mem_ctx, &state->smb2_req);
2869 tevent_req_received(req);
2870 return NT_STATUS_OK;
2873 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2875 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2877 size_t max_send_queue_len;
2878 size_t cur_send_queue_len;
2879 struct tevent_req *subreq;
2881 if (sconn->smb2.compound_related_in_progress) {
2883 * Can't read another until the related
2886 return NT_STATUS_OK;
2889 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2891 * if there is already a smbd_smb2_request_read
2892 * pending, we are done.
2894 return NT_STATUS_OK;
2897 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2898 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2900 if (cur_send_queue_len > max_send_queue_len) {
2902 * if we have a lot of requests to send,
2903 * we wait until they are on the wire until we
2904 * ask for the next request.
2906 return NT_STATUS_OK;
2909 /* ask for the next request */
2910 subreq = smbd_smb2_request_read_send(sconn, sconn->ev_ctx, sconn);
2911 if (subreq == NULL) {
2912 return NT_STATUS_NO_MEMORY;
2914 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2916 return NT_STATUS_OK;
2919 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2920 const uint8_t *inbuf, size_t size)
2923 struct smbd_smb2_request *req = NULL;
2925 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2926 (unsigned int)size));
2928 status = smbd_initialize_smb2(sconn);
2929 if (!NT_STATUS_IS_OK(status)) {
2930 smbd_server_connection_terminate(sconn, nt_errstr(status));
2934 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2935 if (!NT_STATUS_IS_OK(status)) {
2936 smbd_server_connection_terminate(sconn, nt_errstr(status));
2940 status = smbd_smb2_request_validate(req);
2941 if (!NT_STATUS_IS_OK(status)) {
2942 smbd_server_connection_terminate(sconn, nt_errstr(status));
2946 status = smbd_smb2_request_setup_out(req);
2947 if (!NT_STATUS_IS_OK(status)) {
2948 smbd_server_connection_terminate(sconn, nt_errstr(status));
2952 status = smbd_smb2_request_dispatch(req);
2953 if (!NT_STATUS_IS_OK(status)) {
2954 smbd_server_connection_terminate(sconn, nt_errstr(status));
2958 status = smbd_smb2_request_next_incoming(sconn);
2959 if (!NT_STATUS_IS_OK(status)) {
2960 smbd_server_connection_terminate(sconn, nt_errstr(status));
2964 sconn->num_requests++;
2967 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2969 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2970 struct smbd_server_connection);
2972 struct smbd_smb2_request *req = NULL;
2974 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2975 TALLOC_FREE(subreq);
2976 if (!NT_STATUS_IS_OK(status)) {
2977 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2978 nt_errstr(status)));
2979 smbd_server_connection_terminate(sconn, nt_errstr(status));
2983 if (req->in.nbt_hdr[0] != 0x00) {
2984 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2985 req->in.nbt_hdr[0]));
2990 req->current_idx = 1;
2992 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2993 req->current_idx, req->in.vector_count));
2995 status = smbd_smb2_request_validate(req);
2996 if (!NT_STATUS_IS_OK(status)) {
2997 smbd_server_connection_terminate(sconn, nt_errstr(status));
3001 status = smbd_smb2_request_setup_out(req);
3002 if (!NT_STATUS_IS_OK(status)) {
3003 smbd_server_connection_terminate(sconn, nt_errstr(status));
3007 status = smbd_smb2_request_dispatch(req);
3008 if (!NT_STATUS_IS_OK(status)) {
3009 smbd_server_connection_terminate(sconn, nt_errstr(status));
3014 status = smbd_smb2_request_next_incoming(sconn);
3015 if (!NT_STATUS_IS_OK(status)) {
3016 smbd_server_connection_terminate(sconn, nt_errstr(status));
3020 sconn->num_requests++;
3022 /* The timeout_processing function isn't run nearly
3023 often enough to implement 'max log size' without
3024 overrunning the size of the file by many megabytes.
3025 This is especially true if we are running at debug
3026 level 10. Checking every 50 SMB2s is a nice
3027 tradeoff of performance vs log file size overrun. */
3029 if ((sconn->num_requests % 50) == 0 &&
3030 need_to_check_log_size()) {
3031 change_to_root_user();