2 Unix SMB/CIFS implementation.
5 Copyright (C) Stefan Metzmacher 2009
6 Copyright (C) Jeremy Allison 2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../libcli/smb/smb_common.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "../lib/util/tevent_ntstatus.h"
28 #include "smbprofile.h"
29 #include "../lib/util/bitmap.h"
30 #include "../librpc/gen_ndr/krb5pac.h"
33 #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9)
35 static const struct smbd_smb2_dispatch_table {
41 } smbd_smb2_table[] = {
42 #define _OP(o) .opcode = o, .name = #o
47 _OP(SMB2_OP_SESSSETUP),
57 * This call needs to be run as root.
59 * smbd_smb2_request_process_tcon()
60 * calls make_connection_snum(), which will call
61 * change_to_user(), when needed.
101 _OP(SMB2_OP_KEEPALIVE),
105 .need_session = true,
109 .need_session = true,
112 _OP(SMB2_OP_GETINFO),
113 .need_session = true,
116 _OP(SMB2_OP_SETINFO),
117 .need_session = true,
121 .need_session = true,
126 const char *smb2_opcode_name(uint16_t opcode)
128 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
129 return "Bad SMB2 opcode";
131 return smbd_smb2_table[opcode].name;
134 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
136 const struct smbd_smb2_dispatch_table *ret = NULL;
138 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
142 ret = &smbd_smb2_table[opcode];
144 SMB_ASSERT(ret->opcode == opcode);
149 static void print_req_vectors(struct smbd_smb2_request *req)
153 for (i = 0; i < req->in.vector_count; i++) {
154 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
156 (unsigned int)req->in.vector[i].iov_len);
158 for (i = 0; i < req->out.vector_count; i++) {
159 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
161 (unsigned int)req->out.vector[i].iov_len);
165 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
167 if (size < (4 + SMB2_HDR_BODY)) {
171 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
178 static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
183 TALLOC_FREE(sconn->smb1.fde);
185 sconn->smb2.recv_queue = tevent_queue_create(sconn, "smb2 recv queue");
186 if (sconn->smb2.recv_queue == NULL) {
187 return NT_STATUS_NO_MEMORY;
190 sconn->smb2.send_queue = tevent_queue_create(sconn, "smb2 send queue");
191 if (sconn->smb2.send_queue == NULL) {
192 return NT_STATUS_NO_MEMORY;
195 sconn->smb2.seqnum_low = 0;
196 sconn->smb2.seqnum_range = 1;
197 sconn->smb2.credits_granted = 1;
198 sconn->smb2.max_credits = lp_smb2_max_credits();
199 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
200 sconn->smb2.max_credits);
201 if (sconn->smb2.credits_bitmap == NULL) {
202 return NT_STATUS_NO_MEMORY;
205 ret = tstream_bsd_existing_socket(sconn, sconn->sock,
206 &sconn->smb2.stream);
208 status = map_nt_error_from_unix(errno);
212 /* Ensure child is set to non-blocking mode */
213 set_blocking(sconn->sock, false);
217 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
218 #define _smb2_setlen(_buf,len) do { \
219 uint8_t *buf = (uint8_t *)_buf; \
221 buf[1] = ((len)&0xFF0000)>>16; \
222 buf[2] = ((len)&0xFF00)>>8; \
223 buf[3] = (len)&0xFF; \
226 static void smb2_setup_nbt_length(struct iovec *vector, int count)
231 for (i=1; i < count; i++) {
232 len += vector[i].iov_len;
235 _smb2_setlen(vector[0].iov_base, len);
238 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
240 data_blob_clear_free(&req->last_key);
244 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
246 TALLOC_CTX *mem_pool;
247 struct smbd_smb2_request *req;
250 /* Enable this to find subtle valgrind errors. */
251 mem_pool = talloc_init("smbd_smb2_request_allocate");
253 mem_pool = talloc_pool(mem_ctx, 8192);
255 if (mem_pool == NULL) {
259 req = talloc_zero(mem_pool, struct smbd_smb2_request);
261 talloc_free(mem_pool);
264 talloc_reparent(mem_pool, mem_ctx, req);
265 TALLOC_FREE(mem_pool);
267 req->last_session_id = UINT64_MAX;
268 req->last_tid = UINT32_MAX;
270 talloc_set_destructor(req, smbd_smb2_request_destructor);
275 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn,
286 uint8_t *first_hdr = buf;
289 * Note: index '0' is reserved for the transport protocol
291 iov = talloc_zero_array(mem_ctx, struct iovec, num_iov);
293 return NT_STATUS_NO_MEMORY;
296 while (taken < buflen) {
297 size_t len = buflen - taken;
298 uint8_t *hdr = first_hdr + taken;
301 size_t next_command_ofs;
303 uint8_t *body = NULL;
306 struct iovec *iov_tmp;
309 * We need the header plus the body length field
312 if (len < SMB2_HDR_BODY + 2) {
313 DEBUG(10, ("%d bytes left, expected at least %d\n",
314 (int)len, SMB2_HDR_BODY));
317 if (IVAL(hdr, 0) != SMB2_MAGIC) {
318 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
322 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
323 DEBUG(10, ("Got HDR len %d, expected %d\n",
324 SVAL(hdr, 4), SMB2_HDR_BODY));
329 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
330 body_size = SVAL(hdr, SMB2_HDR_BODY);
332 if (next_command_ofs != 0) {
333 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
336 if (next_command_ofs > full_size) {
339 full_size = next_command_ofs;
346 if (body_size > (full_size - SMB2_HDR_BODY)) {
348 * let the caller handle the error
350 body_size = full_size - SMB2_HDR_BODY;
352 body = hdr + SMB2_HDR_BODY;
353 dyn = body + body_size;
354 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
356 iov_tmp = talloc_realloc(mem_ctx, iov, struct iovec,
357 num_iov + SMBD_SMB2_NUM_IOV_PER_REQ);
358 if (iov_tmp == NULL) {
360 return NT_STATUS_NO_MEMORY;
364 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
366 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
367 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
368 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
369 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
370 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
371 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
382 return NT_STATUS_INVALID_PARAMETER;
385 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
386 uint8_t *inbuf, size_t size,
387 struct smbd_smb2_request **_req)
389 struct smbd_smb2_request *req;
390 uint32_t protocol_version;
391 const uint8_t *inhdr = NULL;
393 uint32_t next_command_ofs;
397 if (size < (4 + SMB2_HDR_BODY + 2)) {
398 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
399 return NT_STATUS_INVALID_PARAMETER;
404 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
405 if (protocol_version != SMB2_MAGIC) {
406 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
408 return NT_STATUS_INVALID_PARAMETER;
411 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
412 if (cmd != SMB2_OP_NEGPROT) {
413 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
415 return NT_STATUS_INVALID_PARAMETER;
418 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
419 if (next_command_ofs != 0) {
420 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
422 return NT_STATUS_INVALID_PARAMETER;
425 req = smbd_smb2_request_allocate(sconn);
427 return NT_STATUS_NO_MEMORY;
431 talloc_steal(req, inbuf);
433 req->request_time = timeval_current();
434 now = timeval_to_nttime(&req->request_time);
436 status = smbd_smb2_inbuf_parse_compound(sconn->conn,
438 inbuf + NBT_HDR_SIZE,
440 req, &req->in.vector,
441 &req->in.vector_count);
442 if (!NT_STATUS_IS_OK(status)) {
447 req->current_idx = 1;
453 static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
454 uint64_t message_id, uint64_t seq_id)
456 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
459 if (seq_id < sconn->smb2.seqnum_low) {
460 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
461 "%llu (sequence id %llu) "
462 "(granted = %u, low = %llu, range = %u)\n",
463 (unsigned long long)message_id,
464 (unsigned long long)seq_id,
465 (unsigned int)sconn->smb2.credits_granted,
466 (unsigned long long)sconn->smb2.seqnum_low,
467 (unsigned int)sconn->smb2.seqnum_range));
471 if (seq_id >= sconn->smb2.seqnum_low + sconn->smb2.seqnum_range) {
472 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
473 "%llu (sequence id %llu) "
474 "(granted = %u, low = %llu, range = %u)\n",
475 (unsigned long long)message_id,
476 (unsigned long long)seq_id,
477 (unsigned int)sconn->smb2.credits_granted,
478 (unsigned long long)sconn->smb2.seqnum_low,
479 (unsigned int)sconn->smb2.seqnum_range));
483 offset = seq_id % sconn->smb2.max_credits;
485 if (bitmap_query(credits_bm, offset)) {
486 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
487 "%llu (sequence id %llu) "
488 "(granted = %u, low = %llu, range = %u) "
490 (unsigned long long)message_id,
491 (unsigned long long)seq_id,
492 (unsigned int)sconn->smb2.credits_granted,
493 (unsigned long long)sconn->smb2.seqnum_low,
494 (unsigned int)sconn->smb2.seqnum_range,
499 /* Mark the message_ids as seen in the bitmap. */
500 bitmap_set(credits_bm, offset);
502 if (seq_id != sconn->smb2.seqnum_low) {
507 * Move the window forward by all the message_id's
510 while (bitmap_query(credits_bm, offset)) {
511 DEBUG(10,("smb2_validate_sequence_number: clearing "
512 "id %llu (position %u) from bitmap\n",
513 (unsigned long long)(sconn->smb2.seqnum_low),
515 bitmap_clear(credits_bm, offset);
517 sconn->smb2.seqnum_low += 1;
518 sconn->smb2.seqnum_range -= 1;
519 offset = sconn->smb2.seqnum_low % sconn->smb2.max_credits;
525 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
526 const uint8_t *inhdr)
528 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
529 uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
530 uint16_t credit_charge = 1;
533 if (opcode == SMB2_OP_CANCEL) {
534 /* SMB2_CANCEL requests by definition resend messageids. */
538 if (sconn->smb2.supports_multicredit) {
539 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
540 credit_charge = MAX(credit_charge, 1);
543 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
544 "credits_granted %llu, "
545 "seqnum low/range: %llu/%llu\n",
546 (unsigned long long) message_id,
547 (unsigned long long) credit_charge,
548 (unsigned long long) sconn->smb2.credits_granted,
549 (unsigned long long) sconn->smb2.seqnum_low,
550 (unsigned long long) sconn->smb2.seqnum_range));
552 if (sconn->smb2.credits_granted < credit_charge) {
553 DEBUG(0, ("smb2_validate_message_id: client used more "
554 "credits than granted, mid %llu, charge %llu, "
555 "credits_granted %llu, "
556 "seqnum low/range: %llu/%llu\n",
557 (unsigned long long) message_id,
558 (unsigned long long) credit_charge,
559 (unsigned long long) sconn->smb2.credits_granted,
560 (unsigned long long) sconn->smb2.seqnum_low,
561 (unsigned long long) sconn->smb2.seqnum_range));
566 * now check the message ids
568 * for multi-credit requests we need to check all current mid plus
569 * the implicit mids caused by the credit charge
570 * e.g. current mid = 15, charge 5 => mark 15-19 as used
573 for (i = 0; i <= (credit_charge-1); i++) {
574 uint64_t id = message_id + i;
577 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
578 (unsigned long long)message_id,
580 (unsigned long long)id));
582 ok = smb2_validate_sequence_number(sconn, message_id, id);
588 /* substract used credits */
589 sconn->smb2.credits_granted -= credit_charge;
594 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
599 count = req->in.vector_count;
601 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
602 /* It's not a SMB2 request */
603 return NT_STATUS_INVALID_PARAMETER;
606 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
607 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
608 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
609 const uint8_t *inhdr = NULL;
612 if (hdr->iov_len != SMB2_HDR_BODY) {
613 return NT_STATUS_INVALID_PARAMETER;
616 if (body->iov_len < 2) {
617 return NT_STATUS_INVALID_PARAMETER;
620 inhdr = (const uint8_t *)hdr->iov_base;
622 /* Check the SMB2 header */
623 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
624 return NT_STATUS_INVALID_PARAMETER;
627 if (!smb2_validate_message_id(req->sconn, inhdr)) {
628 return NT_STATUS_INVALID_PARAMETER;
631 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
634 * the 1st request should never have the
635 * SMB2_HDR_FLAG_CHAINED flag set
637 if (flags & SMB2_HDR_FLAG_CHAINED) {
638 req->next_status = NT_STATUS_INVALID_PARAMETER;
641 } else if (idx == 4) {
643 * the 2nd request triggers related vs. unrelated
644 * compounded requests
646 if (flags & SMB2_HDR_FLAG_CHAINED) {
647 req->compound_related = true;
649 } else if (idx > 4) {
652 * It seems the this tests are wrong
653 * see the SMB2-COMPOUND test
657 * all other requests should match the 2nd one
659 if (flags & SMB2_HDR_FLAG_CHAINED) {
660 if (!req->compound_related) {
662 NT_STATUS_INVALID_PARAMETER;
666 if (req->compound_related) {
668 NT_STATUS_INVALID_PARAMETER;
679 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
680 const struct iovec *in_vector,
681 struct iovec *out_vector)
683 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
684 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
685 uint16_t credit_charge = 1;
686 uint16_t credits_requested;
690 uint16_t credits_granted = 0;
691 uint64_t credits_possible;
692 uint16_t current_max_credits;
695 * first we grant only 1/16th of the max range.
697 * Windows also starts with the 1/16th and then grants
698 * more later. I was only able to trigger higher
699 * values, when using a verify high credit charge.
701 * TODO: scale up depending one load, free memory
703 * Maybe also on the relationship between number
704 * of requests and the used sequence number.
705 * Which means we would grant more credits
706 * for client which use multi credit requests.
708 current_max_credits = sconn->smb2.max_credits / 16;
709 current_max_credits = MAX(current_max_credits, 1);
711 if (sconn->smb2.supports_multicredit) {
712 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
713 credit_charge = MAX(credit_charge, 1);
716 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
717 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
718 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
719 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
721 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
722 SMB_ASSERT(sconn->smb2.max_credits >= credit_charge);
724 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
726 * In case we already send an async interim
727 * response, we should not grant
728 * credits on the final response.
731 } else if (credits_requested > 0) {
732 uint16_t additional_max = 0;
733 uint16_t additional_credits = credits_requested - 1;
736 case SMB2_OP_NEGPROT:
738 case SMB2_OP_SESSSETUP:
740 * Windows 2012 RC1 starts to grant
742 * with a successful session setup
744 if (NT_STATUS_IS_OK(out_status)) {
750 * We match windows and only grant additional credits
757 additional_credits = MIN(additional_credits, additional_max);
759 credits_granted = credit_charge + additional_credits;
760 } else if (sconn->smb2.credits_granted == 0) {
762 * Make sure the client has always at least one credit
768 * sequence numbers should not wrap
770 * 1. calculate the possible credits until
771 * the sequence numbers start to wrap on 64-bit.
773 * 2. UINT64_MAX is used for Break Notifications.
775 * 2. truncate the possible credits to the maximum
776 * credits we want to grant to the client in total.
778 * 3. remove the range we'll already granted to the client
779 * this makes sure the client consumes the lowest sequence
780 * number, before we can grant additional credits.
782 credits_possible = UINT64_MAX - sconn->smb2.seqnum_low;
783 if (credits_possible > 0) {
784 /* remove UINT64_MAX */
785 credits_possible -= 1;
787 credits_possible = MIN(credits_possible, current_max_credits);
788 credits_possible -= sconn->smb2.seqnum_range;
790 credits_granted = MIN(credits_granted, credits_possible);
792 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
793 sconn->smb2.credits_granted += credits_granted;
794 sconn->smb2.seqnum_range += credits_granted;
796 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
797 "granted %u, current possible/max %u/%u, "
798 "total granted/max/low/range %u/%u/%llu/%u\n",
799 (unsigned int)credits_requested,
800 (unsigned int)credit_charge,
801 (unsigned int)credits_granted,
802 (unsigned int)credits_possible,
803 (unsigned int)current_max_credits,
804 (unsigned int)sconn->smb2.credits_granted,
805 (unsigned int)sconn->smb2.max_credits,
806 (unsigned long long)sconn->smb2.seqnum_low,
807 (unsigned int)sconn->smb2.seqnum_range));
810 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
811 struct smbd_smb2_request *outreq)
814 uint16_t total_credits = 0;
816 count = outreq->out.vector_count;
818 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
819 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
820 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
821 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
823 smb2_set_operation_credit(outreq->sconn, inhdr_v, outhdr_v);
825 /* To match Windows, count up what we
827 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
828 /* Set to zero in all but the last reply. */
829 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
830 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
832 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
837 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
839 struct iovec *vector;
843 count = req->in.vector_count;
844 vector = talloc_zero_array(req, struct iovec, count);
845 if (vector == NULL) {
846 return NT_STATUS_NO_MEMORY;
849 vector[0].iov_base = req->out.nbt_hdr;
850 vector[0].iov_len = 4;
851 SIVAL(req->out.nbt_hdr, 0, 0);
853 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
854 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
855 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
856 uint8_t *outhdr = NULL;
857 uint8_t *outbody = NULL;
858 uint32_t next_command_ofs = 0;
859 struct iovec *current = &vector[idx];
861 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
862 /* we have a next command -
863 * setup for the error case. */
864 next_command_ofs = SMB2_HDR_BODY + 9;
867 outhdr = talloc_zero_array(vector, uint8_t,
869 if (outhdr == NULL) {
870 return NT_STATUS_NO_MEMORY;
873 outbody = outhdr + SMB2_HDR_BODY;
875 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
876 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
878 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
879 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
881 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
882 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
884 /* setup the SMB2 header */
885 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
886 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
887 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
888 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
889 SIVAL(outhdr, SMB2_HDR_STATUS,
890 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
891 SSVAL(outhdr, SMB2_HDR_OPCODE,
892 SVAL(inhdr, SMB2_HDR_OPCODE));
893 SIVAL(outhdr, SMB2_HDR_FLAGS,
894 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
895 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
896 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
897 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
898 SIVAL(outhdr, SMB2_HDR_PID,
899 IVAL(inhdr, SMB2_HDR_PID));
900 SIVAL(outhdr, SMB2_HDR_TID,
901 IVAL(inhdr, SMB2_HDR_TID));
902 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
903 BVAL(inhdr, SMB2_HDR_SESSION_ID));
904 memcpy(outhdr + SMB2_HDR_SIGNATURE,
905 inhdr + SMB2_HDR_SIGNATURE, 16);
907 /* setup error body header */
908 SSVAL(outbody, 0x00, 0x08 + 1);
909 SSVAL(outbody, 0x02, 0);
910 SIVAL(outbody, 0x04, 0);
913 req->out.vector = vector;
914 req->out.vector_count = count;
916 /* setup the length of the NBT packet */
917 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
919 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
924 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
926 const char *location)
928 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
930 exit_server_cleanly(reason);
933 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
934 struct iovec *outvec,
935 const struct iovec *srcvec)
937 const uint8_t *srchdr;
939 const uint8_t *srcbody;
941 const uint8_t *expected_srcbody;
942 const uint8_t *srcdyn;
944 const uint8_t *expected_srcdyn;
949 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
950 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
951 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
952 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
953 expected_srcbody = srchdr + SMB2_HDR_BODY;
954 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
955 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
956 expected_srcdyn = srcbody + 8;
958 if (srchdr_len != SMB2_HDR_BODY) {
962 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
963 * be allocated with size OUTVEC_ALLOC_SIZE. */
965 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
966 if (dsthdr == NULL) {
969 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
970 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
973 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
974 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
975 * then duplicate this. Else use talloc_memdup().
978 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
979 dstbody = dsthdr + SMB2_HDR_BODY;
981 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
982 if (dstbody == NULL) {
986 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
987 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
990 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
992 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
993 * then duplicate this. Else use talloc_memdup().
996 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
997 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
998 } else if (srcdyn == NULL) {
1001 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1002 if (dstdyn == NULL) {
1006 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1007 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1012 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1014 struct smbd_smb2_request *newreq = NULL;
1015 struct iovec *outvec = NULL;
1016 int count = req->out.vector_count;
1019 newreq = smbd_smb2_request_allocate(req->sconn);
1024 newreq->sconn = req->sconn;
1025 newreq->session = req->session;
1026 newreq->do_signing = req->do_signing;
1027 newreq->current_idx = req->current_idx;
1029 outvec = talloc_zero_array(newreq, struct iovec, count);
1031 TALLOC_FREE(newreq);
1034 newreq->out.vector = outvec;
1035 newreq->out.vector_count = count;
1037 /* Setup the outvec's identically to req. */
1038 outvec[0].iov_base = newreq->out.nbt_hdr;
1039 outvec[0].iov_len = 4;
1040 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1042 /* Setup the vectors identically to the ones in req. */
1043 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1044 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
1051 TALLOC_FREE(newreq);
1055 smb2_setup_nbt_length(newreq->out.vector,
1056 newreq->out.vector_count);
1061 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
1063 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1065 struct smbXsrv_connection *conn = req->sconn->conn;
1066 struct iovec *outhdr_v = NULL;
1067 uint8_t *outhdr = NULL;
1068 struct smbd_smb2_request *nreq = NULL;
1071 /* Create a new smb2 request we'll use
1072 for the interim return. */
1073 nreq = dup_smb2_req(req);
1075 return NT_STATUS_NO_MEMORY;
1078 /* Lose the last X out vectors. They're the
1079 ones we'll be using for the async reply. */
1080 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1082 smb2_setup_nbt_length(nreq->out.vector,
1083 nreq->out.vector_count);
1085 /* Step back to the previous reply. */
1086 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1087 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1088 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1089 /* And end the chain. */
1090 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1092 /* Calculate outgoing credits */
1093 smb2_calculate_credits(req, nreq);
1096 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1097 * we need to sign here with the last signing key we remembered
1099 if (req->last_key.length > 0) {
1100 status = smb2_signing_sign_pdu(req->last_key,
1103 SMBD_SMB2_NUM_IOV_PER_REQ);
1104 if (!NT_STATUS_IS_OK(status)) {
1109 if (DEBUGLEVEL >= 10) {
1110 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1111 (unsigned int)nreq->current_idx );
1112 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1113 (unsigned int)nreq->out.vector_count );
1114 print_req_vectors(nreq);
1116 nreq->subreq = tstream_writev_queue_send(nreq,
1117 nreq->sconn->ev_ctx,
1118 nreq->sconn->smb2.stream,
1119 nreq->sconn->smb2.send_queue,
1121 nreq->out.vector_count);
1123 if (nreq->subreq == NULL) {
1124 return NT_STATUS_NO_MEMORY;
1127 tevent_req_set_callback(nreq->subreq,
1128 smbd_smb2_request_writev_done,
1131 return NT_STATUS_OK;
1134 struct smbd_smb2_request_pending_state {
1135 struct smbd_server_connection *sconn;
1136 uint8_t buf[NBT_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1137 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1140 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
1142 struct smbd_smb2_request_pending_state *state =
1143 tevent_req_callback_data(subreq,
1144 struct smbd_smb2_request_pending_state);
1145 struct smbd_server_connection *sconn = state->sconn;
1149 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1150 TALLOC_FREE(subreq);
1152 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1153 smbd_server_connection_terminate(sconn, nt_errstr(status));
1160 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1161 struct tevent_timer *te,
1162 struct timeval current_time,
1163 void *private_data);
1165 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1166 struct tevent_req *subreq,
1167 uint32_t defer_time)
1170 int i = req->current_idx;
1171 struct timeval defer_endtime;
1172 uint8_t *outhdr = NULL;
1175 if (!tevent_req_is_in_progress(subreq)) {
1176 return NT_STATUS_OK;
1179 req->subreq = subreq;
1182 if (req->async_te) {
1183 /* We're already async. */
1184 return NT_STATUS_OK;
1187 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1188 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1189 if (flags & SMB2_HDR_FLAG_ASYNC) {
1190 /* We're already async. */
1191 return NT_STATUS_OK;
1194 if (req->in.vector_count > i + SMBD_SMB2_NUM_IOV_PER_REQ) {
1196 * We're trying to go async in a compound
1197 * request chain. This is not allowed.
1198 * Cancel the outstanding request.
1200 tevent_req_cancel(req->subreq);
1201 return smbd_smb2_request_error(req,
1202 NT_STATUS_INSUFFICIENT_RESOURCES);
1205 if (DEBUGLEVEL >= 10) {
1206 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1207 (unsigned int)req->current_idx );
1208 print_req_vectors(req);
1211 if (req->out.vector_count >= (2*SMBD_SMB2_NUM_IOV_PER_REQ)) {
1213 * This is a compound reply. We
1214 * must do an interim response
1215 * followed by the async response
1218 status = smb2_send_async_interim_response(req);
1219 if (!NT_STATUS_IS_OK(status)) {
1224 * We're splitting off the last SMB2
1225 * request in a compound set, and the
1226 * smb2_send_async_interim_response()
1227 * call above just sent all the replies
1228 * for the previous SMB2 requests in
1229 * this compound set. So we're no longer
1230 * in the "compound_related_in_progress"
1231 * state, and this is no longer a compound
1234 req->compound_related = false;
1235 req->sconn->smb2.compound_related_in_progress = false;
1237 req->current_idx = 1;
1239 /* Re-arrange the in.vectors. */
1240 memmove(&req->in.vector[req->current_idx],
1242 sizeof(req->in.vector[0])*SMBD_SMB2_NUM_IOV_PER_REQ);
1243 req->in.vector_count = req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ;
1245 /* Re-arrange the out.vectors. */
1246 memmove(&req->out.vector[req->current_idx],
1247 &req->out.vector[i],
1248 sizeof(req->out.vector[0])*SMBD_SMB2_NUM_IOV_PER_REQ);
1249 req->out.vector_count = req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ;
1251 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1252 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1253 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1255 data_blob_clear_free(&req->last_key);
1257 defer_endtime = timeval_current_ofs_usec(defer_time);
1258 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1260 smbd_smb2_request_pending_timer,
1262 if (req->async_te == NULL) {
1263 return NT_STATUS_NO_MEMORY;
1266 return NT_STATUS_OK;
1269 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1270 struct tevent_timer *te,
1271 struct timeval current_time,
1274 struct smbd_smb2_request *req =
1275 talloc_get_type_abort(private_data,
1276 struct smbd_smb2_request);
1277 struct smbd_smb2_request_pending_state *state = NULL;
1278 uint8_t *outhdr = NULL;
1279 const uint8_t *inhdr = NULL;
1280 uint8_t *hdr = NULL;
1281 uint8_t *body = NULL;
1282 uint8_t *dyn = NULL;
1284 uint64_t message_id = 0;
1285 uint64_t async_id = 0;
1286 struct tevent_req *subreq = NULL;
1288 TALLOC_FREE(req->async_te);
1290 /* Ensure our final reply matches the interim one. */
1291 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1292 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1293 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1294 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1296 async_id = message_id; /* keep it simple for now... */
1298 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1299 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1301 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1303 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1304 (unsigned long long)async_id ));
1307 * What we send is identical to a smbd_smb2_request_error
1308 * packet with an error status of STATUS_PENDING. Make use
1309 * of this fact sometime when refactoring. JRA.
1312 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1313 if (state == NULL) {
1314 smbd_server_connection_terminate(req->sconn,
1315 nt_errstr(NT_STATUS_NO_MEMORY));
1318 state->sconn = req->sconn;
1321 hdr = state->buf + NBT_HDR_SIZE;
1322 body = hdr + SMB2_HDR_BODY;
1328 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1329 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1330 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1331 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1332 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1334 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1335 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1336 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1337 SBVAL(hdr, SMB2_HDR_PID, async_id);
1338 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1339 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1340 memcpy(hdr+SMB2_HDR_SIGNATURE,
1341 outhdr+SMB2_HDR_SIGNATURE, 16);
1343 SSVAL(body, 0x00, 0x08 + 1);
1345 SCVAL(body, 0x02, 0);
1346 SCVAL(body, 0x03, 0);
1347 SIVAL(body, 0x04, 0);
1348 /* Match W2K8R2... */
1349 SCVAL(dyn, 0x00, 0x21);
1351 state->vector[0].iov_base = (void *)state->buf;
1352 state->vector[0].iov_len = NBT_HDR_SIZE;
1354 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1355 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1357 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1358 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1360 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1361 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1363 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1365 /* Ensure we correctly go through crediting. Grant
1366 the credits now, and zero credits on the final
1368 smb2_set_operation_credit(req->sconn,
1369 SMBD_SMB2_IN_HDR_IOV(req),
1370 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1372 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1374 if (req->do_signing) {
1376 struct smbXsrv_session *x = req->session;
1377 struct smbXsrv_connection *conn = x->connection;
1378 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1380 status = smb2_signing_sign_pdu(signing_key,
1382 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1383 SMBD_SMB2_NUM_IOV_PER_REQ);
1384 if (!NT_STATUS_IS_OK(status)) {
1385 smbd_server_connection_terminate(req->sconn,
1391 subreq = tstream_writev_queue_send(state,
1392 state->sconn->ev_ctx,
1393 state->sconn->smb2.stream,
1394 state->sconn->smb2.send_queue,
1396 ARRAY_SIZE(state->vector));
1397 if (subreq == NULL) {
1398 smbd_server_connection_terminate(state->sconn,
1399 nt_errstr(NT_STATUS_NO_MEMORY));
1402 tevent_req_set_callback(subreq,
1403 smbd_smb2_request_pending_writev_done,
1407 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1409 struct smbd_server_connection *sconn = req->sconn;
1410 struct smbd_smb2_request *cur;
1411 const uint8_t *inhdr;
1413 uint64_t search_message_id;
1414 uint64_t search_async_id;
1417 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1419 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1420 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1421 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1424 * we don't need the request anymore
1425 * cancel requests never have a response
1427 DLIST_REMOVE(req->sconn->smb2.requests, req);
1430 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1431 const uint8_t *outhdr;
1432 uint64_t message_id;
1435 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1437 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1438 async_id = BVAL(outhdr, SMB2_HDR_PID);
1440 if (flags & SMB2_HDR_FLAG_ASYNC) {
1441 if (search_async_id == async_id) {
1442 found_id = async_id;
1446 if (search_message_id == message_id) {
1447 found_id = message_id;
1453 if (cur && cur->subreq) {
1454 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1455 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1456 "cancel opcode[%s] mid %llu\n",
1457 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1458 (unsigned long long)found_id ));
1459 tevent_req_cancel(cur->subreq);
1462 return NT_STATUS_OK;
1465 /*************************************************************
1466 Ensure an incoming tid is a valid one for us to access.
1467 Change to the associated uid credentials and chdir to the
1468 valid tid directory.
1469 *************************************************************/
1471 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1473 const uint8_t *inhdr;
1476 struct smbXsrv_tcon *tcon;
1478 NTTIME now = timeval_to_nttime(&req->request_time);
1482 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1484 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1485 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1487 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1488 in_tid = req->last_tid;
1491 status = smb2srv_tcon_lookup(req->session,
1492 in_tid, now, &tcon);
1493 if (!NT_STATUS_IS_OK(status)) {
1497 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1498 return NT_STATUS_ACCESS_DENIED;
1501 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1502 if (!set_current_service(tcon->compat, 0, true)) {
1503 return NT_STATUS_ACCESS_DENIED;
1507 req->last_tid = in_tid;
1509 return NT_STATUS_OK;
1512 /*************************************************************
1513 Ensure an incoming session_id is a valid one for us to access.
1514 *************************************************************/
1516 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1518 const uint8_t *inhdr;
1521 uint64_t in_session_id;
1522 struct smbXsrv_session *session = NULL;
1523 struct auth_session_info *session_info;
1525 NTTIME now = timeval_to_nttime(&req->request_time);
1527 req->session = NULL;
1530 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1532 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1533 in_opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1534 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1536 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1537 in_session_id = req->last_session_id;
1540 /* lookup an existing session */
1541 status = smb2srv_session_lookup(req->sconn->conn,
1545 req->session = session;
1546 req->last_session_id = in_session_id;
1548 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1549 switch (in_opcode) {
1550 case SMB2_OP_SESSSETUP:
1551 status = NT_STATUS_OK;
1557 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1558 switch (in_opcode) {
1560 case SMB2_OP_CREATE:
1561 case SMB2_OP_GETINFO:
1562 case SMB2_OP_SETINFO:
1563 return NT_STATUS_INVALID_HANDLE;
1566 * Notice the check for
1567 * (session_info == NULL)
1570 status = NT_STATUS_OK;
1574 if (!NT_STATUS_IS_OK(status)) {
1578 session_info = session->global->auth_session_info;
1579 if (session_info == NULL) {
1580 return NT_STATUS_INVALID_HANDLE;
1583 set_current_user_info(session_info->unix_info->sanitized_username,
1584 session_info->unix_info->unix_name,
1585 session_info->info->domain_name);
1587 return NT_STATUS_OK;
1590 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1591 uint32_t data_length)
1593 uint16_t needed_charge;
1594 uint16_t credit_charge = 1;
1595 const uint8_t *inhdr;
1597 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1599 if (req->sconn->smb2.supports_multicredit) {
1600 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1601 credit_charge = MAX(credit_charge, 1);
1604 needed_charge = (data_length - 1)/ 65536 + 1;
1606 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1607 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1608 credit_charge, needed_charge));
1610 if (needed_charge > credit_charge) {
1611 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1612 credit_charge, needed_charge));
1613 return NT_STATUS_INVALID_PARAMETER;
1616 return NT_STATUS_OK;
1619 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1620 size_t expected_body_size)
1622 struct iovec *inhdr_v;
1623 const uint8_t *inhdr;
1625 const uint8_t *inbody;
1627 size_t min_dyn_size = expected_body_size & 0x00000001;
1628 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1631 * The following should be checked already.
1633 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1634 return NT_STATUS_INTERNAL_ERROR;
1636 if (req->current_idx > max_idx) {
1637 return NT_STATUS_INTERNAL_ERROR;
1640 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1641 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1642 return NT_STATUS_INTERNAL_ERROR;
1644 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1645 return NT_STATUS_INTERNAL_ERROR;
1648 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1649 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1653 case SMB2_OP_GETINFO:
1659 * Now check the expected body size,
1660 * where the last byte might be in the
1663 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1664 return NT_STATUS_INVALID_PARAMETER;
1666 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1667 return NT_STATUS_INVALID_PARAMETER;
1670 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1672 body_size = SVAL(inbody, 0x00);
1673 if (body_size != expected_body_size) {
1674 return NT_STATUS_INVALID_PARAMETER;
1677 return NT_STATUS_OK;
1680 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1682 struct smbXsrv_connection *conn = req->sconn->conn;
1683 const struct smbd_smb2_dispatch_table *call = NULL;
1684 const uint8_t *inhdr;
1689 NTSTATUS session_status;
1690 uint32_t allowed_flags;
1691 NTSTATUS return_value;
1692 struct smbXsrv_session *x = NULL;
1693 bool signing_required = false;
1695 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1697 /* TODO: verify more things */
1699 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1700 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1701 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1702 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1703 smb2_opcode_name(opcode),
1704 (unsigned long long)mid));
1706 if (conn->protocol >= PROTOCOL_SMB2_02) {
1708 * once the protocol is negotiated
1709 * SMB2_OP_NEGPROT is not allowed anymore
1711 if (opcode == SMB2_OP_NEGPROT) {
1712 /* drop the connection */
1713 return NT_STATUS_INVALID_PARAMETER;
1717 * if the protocol is not negotiated yet
1718 * only SMB2_OP_NEGPROT is allowed.
1720 if (opcode != SMB2_OP_NEGPROT) {
1721 /* drop the connection */
1722 return NT_STATUS_INVALID_PARAMETER;
1726 call = smbd_smb2_call(opcode);
1728 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1731 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1732 SMB2_HDR_FLAG_SIGNED |
1734 if (opcode == SMB2_OP_CANCEL) {
1735 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1737 if ((flags & ~allowed_flags) != 0) {
1738 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1742 * Check if the client provided a valid session id,
1743 * if so smbd_smb2_request_check_session() calls
1744 * set_current_user_info().
1746 * As some command don't require a valid session id
1747 * we defer the check of the session_status
1749 session_status = smbd_smb2_request_check_session(req);
1753 signing_required = x->global->signing_required;
1755 if (opcode == SMB2_OP_SESSSETUP &&
1756 x->global->channels[0].signing_key.length) {
1757 signing_required = true;
1761 req->do_signing = false;
1762 if (flags & SMB2_HDR_FLAG_SIGNED) {
1763 DATA_BLOB signing_key;
1766 return smbd_smb2_request_error(
1767 req, NT_STATUS_ACCESS_DENIED);
1770 signing_key = x->global->channels[0].signing_key;
1772 if (!NT_STATUS_IS_OK(session_status)) {
1773 return smbd_smb2_request_error(req, session_status);
1776 req->do_signing = true;
1777 status = smb2_signing_check_pdu(signing_key,
1779 SMBD_SMB2_IN_HDR_IOV(req),
1780 SMBD_SMB2_NUM_IOV_PER_REQ);
1781 if (!NT_STATUS_IS_OK(status)) {
1782 return smbd_smb2_request_error(req, status);
1784 } else if (opcode == SMB2_OP_CANCEL) {
1785 /* Cancel requests are allowed to skip the signing */
1786 } else if (signing_required) {
1787 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1790 if (flags & SMB2_HDR_FLAG_CHAINED) {
1792 * This check is mostly for giving the correct error code
1793 * for compounded requests.
1795 * TODO: we may need to move this after the session
1798 if (!NT_STATUS_IS_OK(req->next_status)) {
1799 return smbd_smb2_request_error(req, req->next_status);
1802 req->compat_chain_fsp = NULL;
1805 if (req->compound_related) {
1806 req->sconn->smb2.compound_related_in_progress = true;
1809 if (call->need_session) {
1810 if (!NT_STATUS_IS_OK(session_status)) {
1811 return smbd_smb2_request_error(req, session_status);
1815 if (call->need_tcon) {
1816 SMB_ASSERT(call->need_session);
1819 * This call needs to be run as user.
1821 * smbd_smb2_request_check_tcon()
1822 * calls change_to_user() on success.
1824 status = smbd_smb2_request_check_tcon(req);
1825 if (!NT_STATUS_IS_OK(status)) {
1826 return smbd_smb2_request_error(req, status);
1830 if (call->as_root) {
1831 /* This call needs to be run as root */
1832 change_to_root_user();
1834 SMB_ASSERT(call->need_tcon);
1838 case SMB2_OP_NEGPROT:
1840 START_PROFILE(smb2_negprot);
1841 return_value = smbd_smb2_request_process_negprot(req);
1842 END_PROFILE(smb2_negprot);
1846 case SMB2_OP_SESSSETUP:
1848 START_PROFILE(smb2_sesssetup);
1849 return_value = smbd_smb2_request_process_sesssetup(req);
1850 END_PROFILE(smb2_sesssetup);
1854 case SMB2_OP_LOGOFF:
1856 START_PROFILE(smb2_logoff);
1857 return_value = smbd_smb2_request_process_logoff(req);
1858 END_PROFILE(smb2_logoff);
1864 START_PROFILE(smb2_tcon);
1865 return_value = smbd_smb2_request_process_tcon(req);
1866 END_PROFILE(smb2_tcon);
1872 START_PROFILE(smb2_tdis);
1873 return_value = smbd_smb2_request_process_tdis(req);
1874 END_PROFILE(smb2_tdis);
1878 case SMB2_OP_CREATE:
1880 START_PROFILE(smb2_create);
1881 return_value = smbd_smb2_request_process_create(req);
1882 END_PROFILE(smb2_create);
1888 START_PROFILE(smb2_close);
1889 return_value = smbd_smb2_request_process_close(req);
1890 END_PROFILE(smb2_close);
1896 START_PROFILE(smb2_flush);
1897 return_value = smbd_smb2_request_process_flush(req);
1898 END_PROFILE(smb2_flush);
1904 START_PROFILE(smb2_read);
1905 return_value = smbd_smb2_request_process_read(req);
1906 END_PROFILE(smb2_read);
1912 START_PROFILE(smb2_write);
1913 return_value = smbd_smb2_request_process_write(req);
1914 END_PROFILE(smb2_write);
1920 START_PROFILE(smb2_lock);
1921 return_value = smbd_smb2_request_process_lock(req);
1922 END_PROFILE(smb2_lock);
1928 START_PROFILE(smb2_ioctl);
1929 return_value = smbd_smb2_request_process_ioctl(req);
1930 END_PROFILE(smb2_ioctl);
1934 case SMB2_OP_CANCEL:
1936 START_PROFILE(smb2_cancel);
1937 return_value = smbd_smb2_request_process_cancel(req);
1938 END_PROFILE(smb2_cancel);
1942 case SMB2_OP_KEEPALIVE:
1944 START_PROFILE(smb2_keepalive);
1945 return_value = smbd_smb2_request_process_keepalive(req);
1946 END_PROFILE(smb2_keepalive);
1952 START_PROFILE(smb2_find);
1953 return_value = smbd_smb2_request_process_find(req);
1954 END_PROFILE(smb2_find);
1958 case SMB2_OP_NOTIFY:
1960 START_PROFILE(smb2_notify);
1961 return_value = smbd_smb2_request_process_notify(req);
1962 END_PROFILE(smb2_notify);
1966 case SMB2_OP_GETINFO:
1968 START_PROFILE(smb2_getinfo);
1969 return_value = smbd_smb2_request_process_getinfo(req);
1970 END_PROFILE(smb2_getinfo);
1974 case SMB2_OP_SETINFO:
1976 START_PROFILE(smb2_setinfo);
1977 return_value = smbd_smb2_request_process_setinfo(req);
1978 END_PROFILE(smb2_setinfo);
1984 START_PROFILE(smb2_break);
1985 return_value = smbd_smb2_request_process_break(req);
1986 END_PROFILE(smb2_break);
1991 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1994 return return_value;
1997 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1999 struct smbXsrv_connection *conn = req->sconn->conn;
2000 struct tevent_req *subreq;
2001 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2002 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2005 TALLOC_FREE(req->async_te);
2007 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2008 (req->last_key.length > 0)) {
2009 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2010 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2014 * As we are sure the header of the last request in the
2015 * compound chain will not change, we can to sign here
2016 * with the last signing key we remembered.
2019 status = smb2_signing_sign_pdu(req->last_key,
2022 SMBD_SMB2_NUM_IOV_PER_REQ);
2023 if (!NT_STATUS_IS_OK(status)) {
2027 data_blob_clear_free(&req->last_key);
2029 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2031 if (req->current_idx < req->out.vector_count) {
2033 * We must process the remaining compound
2034 * SMB2 requests before any new incoming SMB2
2035 * requests. This is because incoming SMB2
2036 * requests may include a cancel for a
2037 * compound request we haven't processed
2040 struct tevent_immediate *im = tevent_create_immediate(req);
2042 return NT_STATUS_NO_MEMORY;
2045 if (req->do_signing) {
2046 struct smbXsrv_session *x = req->session;
2047 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2050 * we need to remember the signing key
2051 * and defer the signing until
2052 * we are sure that we do not change
2055 req->last_key = data_blob_dup_talloc(req, signing_key);
2056 if (req->last_key.data == NULL) {
2057 return NT_STATUS_NO_MEMORY;
2061 tevent_schedule_immediate(im,
2063 smbd_smb2_request_dispatch_immediate,
2065 return NT_STATUS_OK;
2068 if (req->compound_related) {
2069 req->sconn->smb2.compound_related_in_progress = false;
2072 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2074 /* Set credit for these operations (zero credits if this
2075 is a final reply for an async operation). */
2076 smb2_calculate_credits(req, req);
2079 * now check if we need to sign the current response
2081 if (req->do_signing) {
2083 struct smbXsrv_session *x = req->session;
2084 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2086 status = smb2_signing_sign_pdu(signing_key,
2089 SMBD_SMB2_NUM_IOV_PER_REQ);
2090 if (!NT_STATUS_IS_OK(status)) {
2095 if (DEBUGLEVEL >= 10) {
2096 dbgtext("smbd_smb2_request_reply: sending...\n");
2097 print_req_vectors(req);
2100 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2101 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2102 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2103 /* Dynamic part is NULL. Chop it off,
2104 We're going to send it via sendfile. */
2105 req->out.vector_count -= 1;
2108 subreq = tstream_writev_queue_send(req,
2110 req->sconn->smb2.stream,
2111 req->sconn->smb2.send_queue,
2113 req->out.vector_count);
2114 if (subreq == NULL) {
2115 return NT_STATUS_NO_MEMORY;
2117 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
2119 * We're done with this request -
2120 * move it off the "being processed" queue.
2122 DLIST_REMOVE(req->sconn->smb2.requests, req);
2124 return NT_STATUS_OK;
2127 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2129 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2130 struct tevent_immediate *im,
2133 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2134 struct smbd_smb2_request);
2135 struct smbd_server_connection *sconn = req->sconn;
2140 if (DEBUGLEVEL >= 10) {
2141 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2142 req->current_idx, req->in.vector_count));
2143 print_req_vectors(req);
2146 status = smbd_smb2_request_dispatch(req);
2147 if (!NT_STATUS_IS_OK(status)) {
2148 smbd_server_connection_terminate(sconn, nt_errstr(status));
2152 status = smbd_smb2_request_next_incoming(sconn);
2153 if (!NT_STATUS_IS_OK(status)) {
2154 smbd_server_connection_terminate(sconn, nt_errstr(status));
2159 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
2161 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
2162 struct smbd_smb2_request);
2163 struct smbd_server_connection *sconn = req->sconn;
2168 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2169 TALLOC_FREE(subreq);
2172 status = map_nt_error_from_unix(sys_errno);
2173 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2174 nt_errstr(status)));
2175 smbd_server_connection_terminate(sconn, nt_errstr(status));
2179 status = smbd_smb2_request_next_incoming(sconn);
2180 if (!NT_STATUS_IS_OK(status)) {
2181 smbd_server_connection_terminate(sconn, nt_errstr(status));
2186 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2188 DATA_BLOB body, DATA_BLOB *dyn,
2189 const char *location)
2192 struct iovec *outbody_v;
2193 struct iovec *outdyn_v;
2194 uint32_t next_command_ofs;
2196 DEBUG(10,("smbd_smb2_request_done_ex: "
2197 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2198 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2200 (unsigned int)(dyn ? dyn->length : 0),
2203 if (body.length < 2) {
2204 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2207 if ((body.length % 2) != 0) {
2208 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2211 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2212 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2213 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2215 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2216 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2218 outbody_v->iov_base = (void *)body.data;
2219 outbody_v->iov_len = body.length;
2222 outdyn_v->iov_base = (void *)dyn->data;
2223 outdyn_v->iov_len = dyn->length;
2225 outdyn_v->iov_base = NULL;
2226 outdyn_v->iov_len = 0;
2229 /* see if we need to recalculate the offset to the next response */
2230 if (next_command_ofs > 0) {
2231 next_command_ofs = SMB2_HDR_BODY;
2232 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2233 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2236 if ((next_command_ofs % 8) != 0) {
2237 size_t pad_size = 8 - (next_command_ofs % 8);
2238 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2240 * if the dyn buffer is empty
2241 * we can use it to add padding
2245 pad = talloc_zero_array(req->out.vector,
2248 return smbd_smb2_request_error(req,
2249 NT_STATUS_NO_MEMORY);
2252 outdyn_v->iov_base = (void *)pad;
2253 outdyn_v->iov_len = pad_size;
2256 * For now we copy the dynamic buffer
2257 * and add the padding to the new buffer
2264 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2265 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2267 new_size = old_size + pad_size;
2268 new_dyn = talloc_zero_array(req->out.vector,
2270 if (new_dyn == NULL) {
2271 return smbd_smb2_request_error(req,
2272 NT_STATUS_NO_MEMORY);
2275 memcpy(new_dyn, old_dyn, old_size);
2276 memset(new_dyn + old_size, 0, pad_size);
2278 outdyn_v->iov_base = (void *)new_dyn;
2279 outdyn_v->iov_len = new_size;
2281 next_command_ofs += pad_size;
2284 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2286 return smbd_smb2_request_reply(req);
2289 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2292 const char *location)
2295 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2297 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2298 req->current_idx, nt_errstr(status), info ? " +info" : "",
2301 body.data = outhdr + SMB2_HDR_BODY;
2303 SSVAL(body.data, 0, 9);
2306 SIVAL(body.data, 0x04, info->length);
2308 /* Allocated size of req->out.vector[i].iov_base
2309 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2310 * 1 byte without having to do an alloc.
2312 info = talloc_zero_array(req->out.vector,
2316 return NT_STATUS_NO_MEMORY;
2318 info->data = ((uint8_t *)outhdr) +
2319 OUTVEC_ALLOC_SIZE - 1;
2321 SCVAL(info->data, 0, 0);
2325 * if a request fails, all other remaining
2326 * compounded requests should fail too
2328 req->next_status = NT_STATUS_INVALID_PARAMETER;
2330 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2334 struct smbd_smb2_send_oplock_break_state {
2335 struct smbd_server_connection *sconn;
2336 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2337 struct iovec vector;
2340 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2342 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2343 uint64_t file_id_persistent,
2344 uint64_t file_id_volatile,
2345 uint8_t oplock_level)
2347 struct smbd_smb2_send_oplock_break_state *state;
2348 struct tevent_req *subreq;
2352 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2353 if (state == NULL) {
2354 return NT_STATUS_NO_MEMORY;
2356 state->sconn = sconn;
2358 state->vector.iov_base = (void *)state->buf;
2359 state->vector.iov_len = sizeof(state->buf);
2361 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2362 hdr = state->buf + 4;
2363 body = hdr + SMB2_HDR_BODY;
2365 SIVAL(hdr, 0, SMB2_MAGIC);
2366 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2367 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2368 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2369 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2370 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2371 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2372 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2373 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2374 SIVAL(hdr, SMB2_HDR_PID, 0);
2375 SIVAL(hdr, SMB2_HDR_TID, 0);
2376 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2377 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2379 SSVAL(body, 0x00, 0x18);
2381 SCVAL(body, 0x02, oplock_level);
2382 SCVAL(body, 0x03, 0); /* reserved */
2383 SIVAL(body, 0x04, 0); /* reserved */
2384 SBVAL(body, 0x08, file_id_persistent);
2385 SBVAL(body, 0x10, file_id_volatile);
2387 subreq = tstream_writev_queue_send(state,
2390 sconn->smb2.send_queue,
2392 if (subreq == NULL) {
2393 return NT_STATUS_NO_MEMORY;
2395 tevent_req_set_callback(subreq,
2396 smbd_smb2_oplock_break_writev_done,
2399 return NT_STATUS_OK;
2402 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2404 struct smbd_smb2_send_oplock_break_state *state =
2405 tevent_req_callback_data(subreq,
2406 struct smbd_smb2_send_oplock_break_state);
2407 struct smbd_server_connection *sconn = state->sconn;
2411 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2412 TALLOC_FREE(subreq);
2414 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2415 smbd_server_connection_terminate(sconn, nt_errstr(status));
2422 struct smbd_smb2_request_read_state {
2423 struct tevent_context *ev;
2424 struct smbd_server_connection *sconn;
2425 struct smbd_smb2_request *smb2_req;
2427 uint8_t nbt[NBT_HDR_SIZE];
2434 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2436 TALLOC_CTX *mem_ctx,
2437 struct iovec **_vector,
2439 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2441 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2442 struct tevent_context *ev,
2443 struct smbd_server_connection *sconn)
2445 struct tevent_req *req;
2446 struct smbd_smb2_request_read_state *state;
2447 struct tevent_req *subreq;
2449 req = tevent_req_create(mem_ctx, &state,
2450 struct smbd_smb2_request_read_state);
2455 state->sconn = sconn;
2457 state->smb2_req = smbd_smb2_request_allocate(state);
2458 if (tevent_req_nomem(state->smb2_req, req)) {
2459 return tevent_req_post(req, ev);
2461 state->smb2_req->sconn = sconn;
2463 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
2465 state->sconn->smb2.stream,
2466 state->sconn->smb2.recv_queue,
2467 smbd_smb2_request_next_vector,
2469 if (tevent_req_nomem(subreq, req)) {
2470 return tevent_req_post(req, ev);
2472 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2477 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2479 TALLOC_CTX *mem_ctx,
2480 struct iovec **_vector,
2483 struct smbd_smb2_request_read_state *state =
2484 talloc_get_type_abort(private_data,
2485 struct smbd_smb2_request_read_state);
2486 struct iovec *vector;
2488 if (state->pktlen > 0) {
2489 /* if there're no remaining bytes, we're done */
2495 if (!state->hdr.done) {
2497 * first we need to get the NBT header
2499 vector = talloc_array(mem_ctx, struct iovec, 1);
2500 if (vector == NULL) {
2504 vector[0].iov_base = (void *)state->hdr.nbt;
2505 vector[0].iov_len = NBT_HDR_SIZE;
2510 state->hdr.done = true;
2515 * Now we analyze the NBT header
2517 state->pktlen = smb2_len(state->hdr.nbt);
2519 if (state->pktlen == 0) {
2520 /* if there're no remaining bytes, we're done */
2526 state->pktbuf = talloc_array(state->smb2_req, uint8_t, state->pktlen);
2527 if (state->pktbuf == NULL) {
2531 vector = talloc_array(mem_ctx, struct iovec, 1);
2532 if (vector == NULL) {
2536 vector[0].iov_base = (void *)state->pktbuf;
2537 vector[0].iov_len = state->pktlen;
2544 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2546 struct tevent_req *req =
2547 tevent_req_callback_data(subreq,
2549 struct smbd_smb2_request_read_state *state =
2550 tevent_req_data(req,
2551 struct smbd_smb2_request_read_state);
2557 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2558 TALLOC_FREE(subreq);
2560 status = map_nt_error_from_unix(sys_errno);
2561 tevent_req_nterror(req, status);
2565 if (state->hdr.nbt[0] != 0x00) {
2566 DEBUG(1,("smbd_smb2_request_read_done: ignore NBT[0x%02X] msg\n",
2567 state->hdr.nbt[0]));
2569 ZERO_STRUCT(state->hdr);
2570 TALLOC_FREE(state->pktbuf);
2573 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
2575 state->sconn->smb2.stream,
2576 state->sconn->smb2.recv_queue,
2577 smbd_smb2_request_next_vector,
2579 if (tevent_req_nomem(subreq, req)) {
2582 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2586 state->smb2_req->request_time = timeval_current();
2587 now = timeval_to_nttime(&state->smb2_req->request_time);
2589 status = smbd_smb2_inbuf_parse_compound(state->smb2_req->sconn->conn,
2594 &state->smb2_req->in.vector,
2595 &state->smb2_req->in.vector_count);
2596 if (tevent_req_nterror(req, status)) {
2600 state->smb2_req->current_idx = 1;
2602 tevent_req_done(req);
2605 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2606 TALLOC_CTX *mem_ctx,
2607 struct smbd_smb2_request **_smb2_req)
2609 struct smbd_smb2_request_read_state *state =
2610 tevent_req_data(req,
2611 struct smbd_smb2_request_read_state);
2614 if (tevent_req_is_nterror(req, &status)) {
2615 tevent_req_received(req);
2619 *_smb2_req = talloc_move(mem_ctx, &state->smb2_req);
2620 tevent_req_received(req);
2621 return NT_STATUS_OK;
2624 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2626 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2628 size_t max_send_queue_len;
2629 size_t cur_send_queue_len;
2630 struct tevent_req *subreq;
2632 if (sconn->smb2.compound_related_in_progress) {
2634 * Can't read another until the related
2637 return NT_STATUS_OK;
2640 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2642 * if there is already a smbd_smb2_request_read
2643 * pending, we are done.
2645 return NT_STATUS_OK;
2648 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2649 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2651 if (cur_send_queue_len > max_send_queue_len) {
2653 * if we have a lot of requests to send,
2654 * we wait until they are on the wire until we
2655 * ask for the next request.
2657 return NT_STATUS_OK;
2660 /* ask for the next request */
2661 subreq = smbd_smb2_request_read_send(sconn, sconn->ev_ctx, sconn);
2662 if (subreq == NULL) {
2663 return NT_STATUS_NO_MEMORY;
2665 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2667 return NT_STATUS_OK;
2670 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2671 uint8_t *inbuf, size_t size)
2674 struct smbd_smb2_request *req = NULL;
2676 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2677 (unsigned int)size));
2679 status = smbd_initialize_smb2(sconn);
2680 if (!NT_STATUS_IS_OK(status)) {
2681 smbd_server_connection_terminate(sconn, nt_errstr(status));
2685 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2686 if (!NT_STATUS_IS_OK(status)) {
2687 smbd_server_connection_terminate(sconn, nt_errstr(status));
2691 status = smbd_smb2_request_validate(req);
2692 if (!NT_STATUS_IS_OK(status)) {
2693 smbd_server_connection_terminate(sconn, nt_errstr(status));
2697 status = smbd_smb2_request_setup_out(req);
2698 if (!NT_STATUS_IS_OK(status)) {
2699 smbd_server_connection_terminate(sconn, nt_errstr(status));
2703 status = smbd_smb2_request_dispatch(req);
2704 if (!NT_STATUS_IS_OK(status)) {
2705 smbd_server_connection_terminate(sconn, nt_errstr(status));
2709 status = smbd_smb2_request_next_incoming(sconn);
2710 if (!NT_STATUS_IS_OK(status)) {
2711 smbd_server_connection_terminate(sconn, nt_errstr(status));
2715 sconn->num_requests++;
2718 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2720 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2721 struct smbd_server_connection);
2723 struct smbd_smb2_request *req = NULL;
2725 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2726 TALLOC_FREE(subreq);
2727 if (!NT_STATUS_IS_OK(status)) {
2728 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2729 nt_errstr(status)));
2730 smbd_server_connection_terminate(sconn, nt_errstr(status));
2734 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2735 req->current_idx, req->in.vector_count));
2737 status = smbd_smb2_request_validate(req);
2738 if (!NT_STATUS_IS_OK(status)) {
2739 smbd_server_connection_terminate(sconn, nt_errstr(status));
2743 status = smbd_smb2_request_setup_out(req);
2744 if (!NT_STATUS_IS_OK(status)) {
2745 smbd_server_connection_terminate(sconn, nt_errstr(status));
2749 status = smbd_smb2_request_dispatch(req);
2750 if (!NT_STATUS_IS_OK(status)) {
2751 smbd_server_connection_terminate(sconn, nt_errstr(status));
2755 status = smbd_smb2_request_next_incoming(sconn);
2756 if (!NT_STATUS_IS_OK(status)) {
2757 smbd_server_connection_terminate(sconn, nt_errstr(status));
2761 sconn->num_requests++;
2763 /* The timeout_processing function isn't run nearly
2764 often enough to implement 'max log size' without
2765 overrunning the size of the file by many megabytes.
2766 This is especially true if we are running at debug
2767 level 10. Checking every 50 SMB2s is a nice
2768 tradeoff of performance vs log file size overrun. */
2770 if ((sconn->num_requests % 50) == 0 &&
2771 need_to_check_log_size()) {
2772 change_to_root_user();