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 int smbd_smb2_request_parent_destructor(struct smbd_smb2_request **req)
157 (*req)->parent = NULL;
158 (*req)->mem_pool = NULL;
164 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
168 talloc_free(req->mem_pool);
174 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
176 TALLOC_CTX *mem_pool;
177 struct smbd_smb2_request **parent;
178 struct smbd_smb2_request *req;
181 /* Enable this to find subtle valgrind errors. */
182 mem_pool = talloc_init("smbd_smb2_request_allocate");
184 mem_pool = talloc_pool(mem_ctx, 8192);
186 if (mem_pool == NULL) {
190 parent = talloc(mem_pool, struct smbd_smb2_request *);
191 if (parent == NULL) {
192 talloc_free(mem_pool);
196 req = talloc_zero(parent, struct smbd_smb2_request);
198 talloc_free(mem_pool);
202 req->mem_pool = mem_pool;
203 req->parent = parent;
205 req->last_session_id = UINT64_MAX;
206 req->last_tid = UINT32_MAX;
208 talloc_set_destructor(parent, smbd_smb2_request_parent_destructor);
209 talloc_set_destructor(req, smbd_smb2_request_destructor);
214 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
215 const uint8_t *inbuf, size_t size,
216 struct smbd_smb2_request **_req)
218 struct smbd_smb2_request *req;
219 uint32_t protocol_version;
220 const uint8_t *inhdr = NULL;
223 uint32_t next_command_ofs;
225 if (size < (4 + SMB2_HDR_BODY + 2)) {
226 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
227 return NT_STATUS_INVALID_PARAMETER;
232 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
233 if (protocol_version != SMB2_MAGIC) {
234 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
236 return NT_STATUS_INVALID_PARAMETER;
239 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
240 if (cmd != SMB2_OP_NEGPROT) {
241 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
243 return NT_STATUS_INVALID_PARAMETER;
246 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
247 if (next_command_ofs != 0) {
248 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
250 return NT_STATUS_INVALID_PARAMETER;
253 req = smbd_smb2_request_allocate(sconn);
255 return NT_STATUS_NO_MEMORY;
259 talloc_steal(req, inbuf);
261 req->in.vector = talloc_array(req, struct iovec, 4);
262 if (req->in.vector == NULL) {
264 return NT_STATUS_NO_MEMORY;
266 req->in.vector_count = 4;
268 memcpy(req->in.nbt_hdr, inbuf, 4);
271 req->in.vector[0].iov_base = discard_const_p(void, req->in.nbt_hdr);
272 req->in.vector[0].iov_len = 4;
273 ofs += req->in.vector[0].iov_len;
275 req->in.vector[1].iov_base = discard_const_p(void, (inbuf + ofs));
276 req->in.vector[1].iov_len = SMB2_HDR_BODY;
277 ofs += req->in.vector[1].iov_len;
279 req->in.vector[2].iov_base = discard_const_p(void, (inbuf + ofs));
280 req->in.vector[2].iov_len = SVAL(inbuf, ofs) & 0xFFFE;
281 ofs += req->in.vector[2].iov_len;
284 return NT_STATUS_INVALID_PARAMETER;
287 req->in.vector[3].iov_base = discard_const_p(void, (inbuf + ofs));
288 req->in.vector[3].iov_len = size - ofs;
289 ofs += req->in.vector[3].iov_len;
291 req->current_idx = 1;
297 static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
298 uint64_t message_id, uint64_t seq_id)
300 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
303 if (seq_id < sconn->smb2.seqnum_low) {
304 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
305 "%llu (sequence id %llu) "
306 "(granted = %u, low = %llu, range = %u)\n",
307 (unsigned long long)message_id,
308 (unsigned long long)seq_id,
309 (unsigned int)sconn->smb2.credits_granted,
310 (unsigned long long)sconn->smb2.seqnum_low,
311 (unsigned int)sconn->smb2.seqnum_range));
315 if (seq_id >= sconn->smb2.seqnum_low + sconn->smb2.seqnum_range) {
316 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
317 "%llu (sequence id %llu) "
318 "(granted = %u, low = %llu, range = %u)\n",
319 (unsigned long long)message_id,
320 (unsigned long long)seq_id,
321 (unsigned int)sconn->smb2.credits_granted,
322 (unsigned long long)sconn->smb2.seqnum_low,
323 (unsigned int)sconn->smb2.seqnum_range));
327 offset = seq_id % sconn->smb2.max_credits;
329 if (bitmap_query(credits_bm, offset)) {
330 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
331 "%llu (sequence id %llu) "
332 "(granted = %u, low = %llu, range = %u) "
334 (unsigned long long)message_id,
335 (unsigned long long)seq_id,
336 (unsigned int)sconn->smb2.credits_granted,
337 (unsigned long long)sconn->smb2.seqnum_low,
338 (unsigned int)sconn->smb2.seqnum_range,
343 /* Mark the message_ids as seen in the bitmap. */
344 bitmap_set(credits_bm, offset);
346 if (seq_id != sconn->smb2.seqnum_low) {
351 * Move the window forward by all the message_id's
354 while (bitmap_query(credits_bm, offset)) {
355 DEBUG(10,("smb2_validate_sequence_number: clearing "
356 "id %llu (position %u) from bitmap\n",
357 (unsigned long long)(sconn->smb2.seqnum_low),
359 bitmap_clear(credits_bm, offset);
361 sconn->smb2.seqnum_low += 1;
362 sconn->smb2.seqnum_range -= 1;
363 offset = sconn->smb2.seqnum_low % sconn->smb2.max_credits;
369 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
370 const uint8_t *inhdr)
372 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
373 uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
374 uint16_t credit_charge = 1;
377 if (opcode == SMB2_OP_CANCEL) {
378 /* SMB2_CANCEL requests by definition resend messageids. */
382 if (sconn->smb2.supports_multicredit) {
383 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
384 credit_charge = MAX(credit_charge, 1);
387 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
388 "credits_granted %llu, "
389 "seqnum low/range: %llu/%llu\n",
390 (unsigned long long) message_id,
391 (unsigned long long) credit_charge,
392 (unsigned long long) sconn->smb2.credits_granted,
393 (unsigned long long) sconn->smb2.seqnum_low,
394 (unsigned long long) sconn->smb2.seqnum_range));
396 if (sconn->smb2.credits_granted < credit_charge) {
397 DEBUG(0, ("smb2_validate_message_id: client used more "
398 "credits than granted, mid %llu, charge %llu, "
399 "credits_granted %llu, "
400 "seqnum low/range: %llu/%llu\n",
401 (unsigned long long) message_id,
402 (unsigned long long) credit_charge,
403 (unsigned long long) sconn->smb2.credits_granted,
404 (unsigned long long) sconn->smb2.seqnum_low,
405 (unsigned long long) sconn->smb2.seqnum_range));
410 * now check the message ids
412 * for multi-credit requests we need to check all current mid plus
413 * the implicit mids caused by the credit charge
414 * e.g. current mid = 15, charge 5 => mark 15-19 as used
417 for (i = 0; i <= (credit_charge-1); i++) {
418 uint64_t id = message_id + i;
421 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
422 (unsigned long long)message_id,
424 (unsigned long long)id));
426 ok = smb2_validate_sequence_number(sconn, message_id, id);
432 /* substract used credits */
433 sconn->smb2.credits_granted -= credit_charge;
438 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
443 count = req->in.vector_count;
446 /* It's not a SMB2 request */
447 return NT_STATUS_INVALID_PARAMETER;
450 for (idx=1; idx < count; idx += 3) {
451 const uint8_t *inhdr = NULL;
454 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
455 return NT_STATUS_INVALID_PARAMETER;
458 if (req->in.vector[idx+1].iov_len < 2) {
459 return NT_STATUS_INVALID_PARAMETER;
462 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
464 /* Check the SMB2 header */
465 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
466 return NT_STATUS_INVALID_PARAMETER;
469 if (!smb2_validate_message_id(req->sconn, inhdr)) {
470 return NT_STATUS_INVALID_PARAMETER;
473 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
476 * the 1st request should never have the
477 * SMB2_HDR_FLAG_CHAINED flag set
479 if (flags & SMB2_HDR_FLAG_CHAINED) {
480 req->next_status = NT_STATUS_INVALID_PARAMETER;
483 } else if (idx == 4) {
485 * the 2nd request triggers related vs. unrelated
486 * compounded requests
488 if (flags & SMB2_HDR_FLAG_CHAINED) {
489 req->compound_related = true;
491 } else if (idx > 4) {
494 * It seems the this tests are wrong
495 * see the SMB2-COMPOUND test
499 * all other requests should match the 2nd one
501 if (flags & SMB2_HDR_FLAG_CHAINED) {
502 if (!req->compound_related) {
504 NT_STATUS_INVALID_PARAMETER;
508 if (req->compound_related) {
510 NT_STATUS_INVALID_PARAMETER;
521 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
522 const struct iovec *in_vector,
523 struct iovec *out_vector)
525 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
526 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
527 uint16_t credits_requested;
529 uint16_t credits_granted = 0;
530 uint64_t credits_possible;
532 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
533 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
535 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
537 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
539 * In case we already send an async interim
540 * response, we should not grant
541 * credits on the final response.
544 } else if (credits_requested > 0) {
545 uint16_t modified_credits_requested;
549 * Split up max_credits into 1/16ths, and then scale
550 * the requested credits by how many 16ths have been
551 * currently granted. Less than 1/16th == grant all
552 * requested (100%), scale down as more have been
553 * granted. Never ask for less than 1 as the client
554 * asked for at least 1. JRA.
557 multiplier = 16 - (((sconn->smb2.credits_granted * 16) / sconn->smb2.max_credits) % 16);
559 modified_credits_requested = (multiplier * credits_requested) / 16;
560 if (modified_credits_requested == 0) {
561 modified_credits_requested = 1;
564 credits_granted = modified_credits_requested;
565 } else if (sconn->smb2.credits_granted == 0) {
567 * Make sure the client has always at least one credit
573 * remove the range we'll already granted to the client
574 * this makes sure the client consumes the lowest sequence
575 * number, before we can grant additional credits.
577 credits_possible = sconn->smb2.max_credits;
578 credits_possible -= sconn->smb2.seqnum_range;
580 credits_granted = MIN(credits_granted, credits_possible);
582 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
583 sconn->smb2.credits_granted += credits_granted;
584 sconn->smb2.seqnum_range += credits_granted;
586 DEBUG(10,("smb2_set_operation_credit: requested %u, "
587 "granted %u, current possible %u, "
588 "total granted/max/low/range %u/%u/%llu/%u\n",
589 (unsigned int)credits_requested,
590 (unsigned int)credits_granted,
591 (unsigned int)credits_possible,
592 (unsigned int)sconn->smb2.credits_granted,
593 (unsigned int)sconn->smb2.max_credits,
594 (unsigned long long)sconn->smb2.seqnum_low,
595 (unsigned int)sconn->smb2.seqnum_range));
598 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
599 struct smbd_smb2_request *outreq)
602 uint16_t total_credits = 0;
604 count = outreq->out.vector_count;
606 for (idx=1; idx < count; idx += 3) {
607 uint8_t *outhdr = (uint8_t *)outreq->out.vector[idx].iov_base;
608 smb2_set_operation_credit(outreq->sconn,
609 &inreq->in.vector[idx],
610 &outreq->out.vector[idx]);
611 /* To match Windows, count up what we
613 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
614 /* Set to zero in all but the last reply. */
615 if (idx + 3 < count) {
616 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
618 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
623 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
625 struct iovec *vector;
629 req->request_time = timeval_current();
631 count = req->in.vector_count;
632 vector = talloc_zero_array(req, struct iovec, count);
633 if (vector == NULL) {
634 return NT_STATUS_NO_MEMORY;
637 vector[0].iov_base = req->out.nbt_hdr;
638 vector[0].iov_len = 4;
639 SIVAL(req->out.nbt_hdr, 0, 0);
641 for (idx=1; idx < count; idx += 3) {
642 const uint8_t *inhdr = NULL;
643 uint8_t *outhdr = NULL;
644 uint8_t *outbody = NULL;
645 uint32_t next_command_ofs = 0;
646 struct iovec *current = &vector[idx];
648 if ((idx + 3) < count) {
649 /* we have a next command -
650 * setup for the error case. */
651 next_command_ofs = SMB2_HDR_BODY + 9;
654 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
656 outhdr = talloc_zero_array(vector, uint8_t,
658 if (outhdr == NULL) {
659 return NT_STATUS_NO_MEMORY;
662 outbody = outhdr + SMB2_HDR_BODY;
664 current[0].iov_base = (void *)outhdr;
665 current[0].iov_len = SMB2_HDR_BODY;
667 current[1].iov_base = (void *)outbody;
668 current[1].iov_len = 8;
670 current[2].iov_base = NULL;
671 current[2].iov_len = 0;
673 /* setup the SMB2 header */
674 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
675 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
676 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
677 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
678 SIVAL(outhdr, SMB2_HDR_STATUS,
679 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
680 SSVAL(outhdr, SMB2_HDR_OPCODE,
681 SVAL(inhdr, SMB2_HDR_OPCODE));
682 SIVAL(outhdr, SMB2_HDR_FLAGS,
683 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
684 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
685 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
686 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
687 SIVAL(outhdr, SMB2_HDR_PID,
688 IVAL(inhdr, SMB2_HDR_PID));
689 SIVAL(outhdr, SMB2_HDR_TID,
690 IVAL(inhdr, SMB2_HDR_TID));
691 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
692 BVAL(inhdr, SMB2_HDR_SESSION_ID));
693 memcpy(outhdr + SMB2_HDR_SIGNATURE,
694 inhdr + SMB2_HDR_SIGNATURE, 16);
696 /* setup error body header */
697 SSVAL(outbody, 0x00, 0x08 + 1);
698 SSVAL(outbody, 0x02, 0);
699 SIVAL(outbody, 0x04, 0);
702 req->out.vector = vector;
703 req->out.vector_count = count;
705 /* setup the length of the NBT packet */
706 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
708 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
713 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
715 const char *location)
717 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
719 exit_server_cleanly(reason);
722 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
723 struct iovec *outvec,
724 const struct iovec *srcvec)
726 /* vec[0] is always boilerplate and must
727 * be allocated with size OUTVEC_ALLOC_SIZE. */
729 outvec[0].iov_base = talloc_memdup(ctx,
732 if (!outvec[0].iov_base) {
735 outvec[0].iov_len = SMB2_HDR_BODY;
738 * If this is a "standard" vec[1] of length 8,
739 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
740 * then duplicate this. Else use talloc_memdup().
743 if (srcvec[1].iov_len == 8 &&
744 srcvec[1].iov_base ==
745 ((uint8_t *)srcvec[0].iov_base) +
747 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
749 outvec[1].iov_len = 8;
751 outvec[1].iov_base = talloc_memdup(ctx,
754 if (!outvec[1].iov_base) {
757 outvec[1].iov_len = srcvec[1].iov_len;
761 * If this is a "standard" vec[2] of length 1,
762 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
763 * then duplicate this. Else use talloc_memdup().
766 if (srcvec[2].iov_base &&
768 if (srcvec[2].iov_base ==
769 ((uint8_t *)srcvec[0].iov_base) +
770 (OUTVEC_ALLOC_SIZE - 1) &&
771 srcvec[2].iov_len == 1) {
772 /* Common SMB2 error packet case. */
773 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
774 (OUTVEC_ALLOC_SIZE - 1);
776 outvec[2].iov_base = talloc_memdup(ctx,
779 if (!outvec[2].iov_base) {
783 outvec[2].iov_len = srcvec[2].iov_len;
785 outvec[2].iov_base = NULL;
786 outvec[2].iov_len = 0;
791 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
793 struct smbd_smb2_request *newreq = NULL;
794 struct iovec *outvec = NULL;
795 int count = req->out.vector_count;
798 newreq = smbd_smb2_request_allocate(req->sconn);
803 newreq->sconn = req->sconn;
804 newreq->session = req->session;
805 newreq->do_signing = req->do_signing;
806 newreq->current_idx = req->current_idx;
808 outvec = talloc_zero_array(newreq, struct iovec, count);
813 newreq->out.vector = outvec;
814 newreq->out.vector_count = count;
816 /* Setup the outvec's identically to req. */
817 outvec[0].iov_base = newreq->out.nbt_hdr;
818 outvec[0].iov_len = 4;
819 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
821 /* Setup the vectors identically to the ones in req. */
822 for (i = 1; i < count; i += 3) {
823 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
834 smb2_setup_nbt_length(newreq->out.vector,
835 newreq->out.vector_count);
840 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
842 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
845 uint8_t *outhdr = NULL;
846 struct smbd_smb2_request *nreq = NULL;
848 /* Create a new smb2 request we'll use
849 for the interim return. */
850 nreq = dup_smb2_req(req);
852 return NT_STATUS_NO_MEMORY;
855 /* Lose the last 3 out vectors. They're the
856 ones we'll be using for the async reply. */
857 nreq->out.vector_count -= 3;
859 smb2_setup_nbt_length(nreq->out.vector,
860 nreq->out.vector_count);
862 /* Step back to the previous reply. */
863 i = nreq->current_idx - 3;
864 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
865 /* And end the chain. */
866 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
868 /* Calculate outgoing credits */
869 smb2_calculate_credits(req, nreq);
871 /* Re-sign if needed. */
872 if (nreq->do_signing) {
874 struct smbXsrv_session *x = nreq->session;
875 struct smbXsrv_connection *conn = x->connection;
876 DATA_BLOB signing_key = x->global->channels[0].signing_key;
878 status = smb2_signing_sign_pdu(signing_key,
880 &nreq->out.vector[i], 3);
881 if (!NT_STATUS_IS_OK(status)) {
885 if (DEBUGLEVEL >= 10) {
886 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
887 (unsigned int)nreq->current_idx );
888 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
889 (unsigned int)nreq->out.vector_count );
890 print_req_vectors(nreq);
892 nreq->subreq = tstream_writev_queue_send(nreq,
894 nreq->sconn->smb2.stream,
895 nreq->sconn->smb2.send_queue,
897 nreq->out.vector_count);
899 if (nreq->subreq == NULL) {
900 return NT_STATUS_NO_MEMORY;
903 tevent_req_set_callback(nreq->subreq,
904 smbd_smb2_request_writev_done,
910 struct smbd_smb2_request_pending_state {
911 struct smbd_server_connection *sconn;
912 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
913 struct iovec vector[3];
916 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
918 struct smbd_smb2_request_pending_state *state =
919 tevent_req_callback_data(subreq,
920 struct smbd_smb2_request_pending_state);
921 struct smbd_server_connection *sconn = state->sconn;
925 ret = tstream_writev_queue_recv(subreq, &sys_errno);
928 NTSTATUS status = map_nt_error_from_unix(sys_errno);
929 smbd_server_connection_terminate(sconn, nt_errstr(status));
936 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
937 struct tevent_timer *te,
938 struct timeval current_time,
941 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
942 struct tevent_req *subreq,
946 int i = req->current_idx;
947 struct timeval defer_endtime;
948 uint8_t *outhdr = NULL;
951 if (!tevent_req_is_in_progress(subreq)) {
955 req->subreq = subreq;
959 /* We're already async. */
963 outhdr = (uint8_t *)req->out.vector[i].iov_base;
964 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
965 if (flags & SMB2_HDR_FLAG_ASYNC) {
966 /* We're already async. */
970 if (req->in.vector_count > i + 3) {
972 * We're trying to go async in a compound
973 * request chain. This is not allowed.
974 * Cancel the outstanding request.
976 tevent_req_cancel(req->subreq);
977 return smbd_smb2_request_error(req,
978 NT_STATUS_INSUFFICIENT_RESOURCES);
981 if (DEBUGLEVEL >= 10) {
982 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
983 (unsigned int)req->current_idx );
984 print_req_vectors(req);
987 if (req->out.vector_count > 4) {
988 struct iovec *outvec = NULL;
990 /* This is a compound reply. We
991 * must do an interim response
992 * followed by the async response
995 status = smb2_send_async_interim_response(req);
996 if (!NT_STATUS_IS_OK(status)) {
1001 * We're splitting off the last SMB2
1002 * request in a compound set, and the
1003 * smb2_send_async_interim_response()
1004 * call above just sent all the replies
1005 * for the previous SMB2 requests in
1006 * this compound set. So we're no longer
1007 * in the "compound_related_in_progress"
1008 * state, and this is no longer a compound
1011 req->compound_related = false;
1012 req->sconn->smb2.compound_related_in_progress = false;
1014 /* Re-arrange the in.vectors. */
1015 req->in.vector[1] = req->in.vector[i];
1016 req->in.vector[2] = req->in.vector[i+1];
1017 req->in.vector[3] = req->in.vector[i+2];
1018 req->in.vector_count = 4;
1020 /* Reset the new in size. */
1021 smb2_setup_nbt_length(req->in.vector, 4);
1023 /* Now recreate the out.vectors. */
1024 outvec = talloc_zero_array(req, struct iovec, 4);
1026 return NT_STATUS_NO_MEMORY;
1029 /* 0 is always boilerplate and must
1030 * be of size 4 for the length field. */
1032 outvec[0].iov_base = req->out.nbt_hdr;
1033 outvec[0].iov_len = 4;
1034 SIVAL(req->out.nbt_hdr, 0, 0);
1036 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
1037 return NT_STATUS_NO_MEMORY;
1040 TALLOC_FREE(req->out.vector);
1042 req->out.vector = outvec;
1044 req->current_idx = 1;
1045 req->out.vector_count = 4;
1047 outhdr = (uint8_t *)req->out.vector[1].iov_base;
1048 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1049 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1052 defer_endtime = timeval_current_ofs_usec(defer_time);
1053 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1055 smbd_smb2_request_pending_timer,
1057 if (req->async_te == NULL) {
1058 return NT_STATUS_NO_MEMORY;
1061 return NT_STATUS_OK;
1064 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1065 struct tevent_timer *te,
1066 struct timeval current_time,
1069 struct smbd_smb2_request *req =
1070 talloc_get_type_abort(private_data,
1071 struct smbd_smb2_request);
1072 struct smbd_smb2_request_pending_state *state = NULL;
1073 int i = req->current_idx;
1074 uint8_t *outhdr = NULL;
1075 const uint8_t *inhdr = NULL;
1076 uint8_t *hdr = NULL;
1077 uint8_t *body = NULL;
1079 uint64_t message_id = 0;
1080 uint64_t async_id = 0;
1081 struct tevent_req *subreq = NULL;
1083 TALLOC_FREE(req->async_te);
1085 /* Ensure our final reply matches the interim one. */
1086 inhdr = (const uint8_t *)req->in.vector[1].iov_base;
1087 outhdr = (uint8_t *)req->out.vector[1].iov_base;
1088 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1089 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1091 async_id = message_id; /* keep it simple for now... */
1093 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1094 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1096 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1098 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1099 (unsigned long long)async_id ));
1102 * What we send is identical to a smbd_smb2_request_error
1103 * packet with an error status of STATUS_PENDING. Make use
1104 * of this fact sometime when refactoring. JRA.
1107 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1108 if (state == NULL) {
1109 smbd_server_connection_terminate(req->sconn,
1110 nt_errstr(NT_STATUS_NO_MEMORY));
1113 state->sconn = req->sconn;
1115 state->vector[0].iov_base = (void *)state->buf;
1116 state->vector[0].iov_len = 4;
1118 state->vector[1].iov_base = state->buf + 4;
1119 state->vector[1].iov_len = SMB2_HDR_BODY;
1121 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
1122 state->vector[2].iov_len = 9;
1124 smb2_setup_nbt_length(state->vector, 3);
1126 hdr = (uint8_t *)state->vector[1].iov_base;
1127 body = (uint8_t *)state->vector[2].iov_base;
1129 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1130 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1131 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1132 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1133 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1135 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1136 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1137 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1138 SBVAL(hdr, SMB2_HDR_PID, async_id);
1139 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1140 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1141 memcpy(hdr+SMB2_HDR_SIGNATURE,
1142 outhdr+SMB2_HDR_SIGNATURE, 16);
1144 SSVAL(body, 0x00, 0x08 + 1);
1146 SCVAL(body, 0x02, 0);
1147 SCVAL(body, 0x03, 0);
1148 SIVAL(body, 0x04, 0);
1149 /* Match W2K8R2... */
1150 SCVAL(body, 0x08, 0x21);
1152 /* Ensure we correctly go through crediting. Grant
1153 the credits now, and zero credits on the final
1155 smb2_set_operation_credit(req->sconn,
1159 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1161 if (req->do_signing) {
1163 struct smbXsrv_session *x = req->session;
1164 struct smbXsrv_connection *conn = x->connection;
1165 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1167 status = smb2_signing_sign_pdu(signing_key,
1169 &state->vector[1], 2);
1170 if (!NT_STATUS_IS_OK(status)) {
1171 smbd_server_connection_terminate(req->sconn,
1177 subreq = tstream_writev_queue_send(state,
1178 state->sconn->ev_ctx,
1179 state->sconn->smb2.stream,
1180 state->sconn->smb2.send_queue,
1183 if (subreq == NULL) {
1184 smbd_server_connection_terminate(state->sconn,
1185 nt_errstr(NT_STATUS_NO_MEMORY));
1188 tevent_req_set_callback(subreq,
1189 smbd_smb2_request_pending_writev_done,
1193 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1195 struct smbd_server_connection *sconn = req->sconn;
1196 struct smbd_smb2_request *cur;
1197 const uint8_t *inhdr;
1198 int i = req->current_idx;
1200 uint64_t search_message_id;
1201 uint64_t search_async_id;
1204 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1206 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1207 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1208 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1211 * we don't need the request anymore
1212 * cancel requests never have a response
1214 DLIST_REMOVE(req->sconn->smb2.requests, req);
1217 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1218 const uint8_t *outhdr;
1219 uint64_t message_id;
1222 i = cur->current_idx;
1224 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1226 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1227 async_id = BVAL(outhdr, SMB2_HDR_PID);
1229 if (flags & SMB2_HDR_FLAG_ASYNC) {
1230 if (search_async_id == async_id) {
1231 found_id = async_id;
1235 if (search_message_id == message_id) {
1236 found_id = message_id;
1242 if (cur && cur->subreq) {
1243 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1244 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1245 "cancel opcode[%s] mid %llu\n",
1246 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1247 (unsigned long long)found_id ));
1248 tevent_req_cancel(cur->subreq);
1251 return NT_STATUS_OK;
1254 /*************************************************************
1255 Ensure an incoming tid is a valid one for us to access.
1256 Change to the associated uid credentials and chdir to the
1257 valid tid directory.
1258 *************************************************************/
1260 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1262 const uint8_t *inhdr;
1263 int i = req->current_idx;
1266 struct smbXsrv_tcon0 *tcon;
1268 NTTIME now = timeval_to_nttime(&req->request_time);
1272 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1274 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1275 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1277 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1278 in_tid = req->last_tid;
1281 status = smb2srv_tcon_lookup(req->session,
1282 in_tid, now, &tcon);
1283 if (!NT_STATUS_IS_OK(status)) {
1287 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1288 return NT_STATUS_ACCESS_DENIED;
1291 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1292 if (!set_current_service(tcon->compat, 0, true)) {
1293 return NT_STATUS_ACCESS_DENIED;
1297 req->last_tid = in_tid;
1299 return NT_STATUS_OK;
1302 /*************************************************************
1303 Ensure an incoming session_id is a valid one for us to access.
1304 *************************************************************/
1306 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1308 const uint8_t *inhdr;
1309 int i = req->current_idx;
1312 uint64_t in_session_id;
1313 struct smbXsrv_session *session = NULL;
1314 struct auth_session_info *session_info;
1316 NTTIME now = timeval_to_nttime(&req->request_time);
1318 req->session = NULL;
1321 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1323 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1324 in_opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1325 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1327 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1328 in_session_id = req->last_session_id;
1331 /* lookup an existing session */
1332 status = smb2srv_session_lookup(req->sconn->conn,
1336 req->session = session;
1337 req->last_session_id = in_session_id;
1339 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1340 switch (in_opcode) {
1341 case SMB2_OP_SESSSETUP:
1342 status = NT_STATUS_OK;
1348 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1349 switch (in_opcode) {
1351 case SMB2_OP_CREATE:
1352 case SMB2_OP_GETINFO:
1353 case SMB2_OP_SETINFO:
1354 return NT_STATUS_INVALID_HANDLE;
1357 * Notice the check for
1358 * (session_info == NULL)
1361 status = NT_STATUS_OK;
1365 if (!NT_STATUS_IS_OK(status)) {
1369 session_info = session->global->auth_session_info;
1370 if (session_info == NULL) {
1371 return NT_STATUS_INVALID_HANDLE;
1374 set_current_user_info(session_info->unix_info->sanitized_username,
1375 session_info->unix_info->unix_name,
1376 session_info->info->domain_name);
1378 return NT_STATUS_OK;
1381 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1382 uint32_t data_length)
1384 uint16_t needed_charge;
1385 uint16_t credit_charge;
1386 const uint8_t *inhdr;
1387 int i = req->current_idx;
1389 if (!req->sconn->smb2.supports_multicredit) {
1390 if (data_length > 65536) {
1391 return NT_STATUS_INVALID_PARAMETER;
1393 return NT_STATUS_OK;
1396 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1397 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1399 /* requests larger than 64 KB need credit charge */
1400 if (credit_charge == 0 && data_length > 65536) {
1401 DEBUG(2, ("Request larger than 64KB w/o creditcharge\n"));
1402 return NT_STATUS_INVALID_PARAMETER;
1405 needed_charge = (data_length - 1)/ 65536 + 1;
1407 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1408 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1409 credit_charge, needed_charge));
1411 if (needed_charge > credit_charge) {
1412 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1413 credit_charge, needed_charge));
1414 return NT_STATUS_INVALID_PARAMETER;
1417 return NT_STATUS_OK;
1420 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1421 size_t expected_body_size)
1423 const uint8_t *inhdr;
1425 const uint8_t *inbody;
1426 int i = req->current_idx;
1428 size_t min_dyn_size = expected_body_size & 0x00000001;
1431 * The following should be checked already.
1433 if ((i+2) > req->in.vector_count) {
1434 return NT_STATUS_INTERNAL_ERROR;
1436 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1437 return NT_STATUS_INTERNAL_ERROR;
1439 if (req->in.vector[i+1].iov_len < 2) {
1440 return NT_STATUS_INTERNAL_ERROR;
1443 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1444 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1448 case SMB2_OP_GETINFO:
1454 * Now check the expected body size,
1455 * where the last byte might be in the
1458 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1459 return NT_STATUS_INVALID_PARAMETER;
1461 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1462 return NT_STATUS_INVALID_PARAMETER;
1465 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1467 body_size = SVAL(inbody, 0x00);
1468 if (body_size != expected_body_size) {
1469 return NT_STATUS_INVALID_PARAMETER;
1472 return NT_STATUS_OK;
1475 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1477 const uint8_t *inhdr;
1478 int i = req->current_idx;
1483 NTSTATUS session_status;
1484 uint32_t allowed_flags;
1485 NTSTATUS return_value;
1486 struct smbXsrv_session *x = NULL;
1487 bool signing_required = false;
1489 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1491 /* TODO: verify more things */
1493 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1494 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1495 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1496 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1497 smb2_opcode_name(opcode),
1498 (unsigned long long)mid));
1500 if (get_Protocol() >= PROTOCOL_SMB2_02) {
1502 * once the protocol is negotiated
1503 * SMB2_OP_NEGPROT is not allowed anymore
1505 if (opcode == SMB2_OP_NEGPROT) {
1506 /* drop the connection */
1507 return NT_STATUS_INVALID_PARAMETER;
1511 * if the protocol is not negotiated yet
1512 * only SMB2_OP_NEGPROT is allowed.
1514 if (opcode != SMB2_OP_NEGPROT) {
1515 /* drop the connection */
1516 return NT_STATUS_INVALID_PARAMETER;
1520 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1521 SMB2_HDR_FLAG_SIGNED |
1523 if (opcode == SMB2_OP_CANCEL) {
1524 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1526 if ((flags & ~allowed_flags) != 0) {
1527 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1531 * Check if the client provided a valid session id,
1532 * if so smbd_smb2_request_check_session() calls
1533 * set_current_user_info().
1535 * As some command don't require a valid session id
1536 * we defer the check of the session_status
1538 session_status = smbd_smb2_request_check_session(req);
1542 signing_required = x->global->signing_required;
1544 if (opcode == SMB2_OP_SESSSETUP &&
1545 x->global->channels[0].signing_key.length) {
1546 signing_required = true;
1550 req->do_signing = false;
1551 if (flags & SMB2_HDR_FLAG_SIGNED) {
1552 struct smbXsrv_connection *conn = x->connection;
1553 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1555 if (!NT_STATUS_IS_OK(session_status)) {
1556 return smbd_smb2_request_error(req, session_status);
1559 req->do_signing = true;
1560 status = smb2_signing_check_pdu(signing_key,
1562 &req->in.vector[i], 3);
1563 if (!NT_STATUS_IS_OK(status)) {
1564 return smbd_smb2_request_error(req, status);
1566 } else if (opcode == SMB2_OP_CANCEL) {
1567 /* Cancel requests are allowed to skip the signing */
1568 } else if (signing_required) {
1569 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1572 if (flags & SMB2_HDR_FLAG_CHAINED) {
1574 * This check is mostly for giving the correct error code
1575 * for compounded requests.
1577 * TODO: we may need to move this after the session
1580 if (!NT_STATUS_IS_OK(req->next_status)) {
1581 return smbd_smb2_request_error(req, req->next_status);
1584 req->compat_chain_fsp = NULL;
1587 if (req->compound_related) {
1588 req->sconn->smb2.compound_related_in_progress = true;
1592 case SMB2_OP_NEGPROT:
1593 /* This call needs to be run as root */
1594 change_to_root_user();
1597 START_PROFILE(smb2_negprot);
1598 return_value = smbd_smb2_request_process_negprot(req);
1599 END_PROFILE(smb2_negprot);
1603 case SMB2_OP_SESSSETUP:
1604 /* This call needs to be run as root */
1605 change_to_root_user();
1608 START_PROFILE(smb2_sesssetup);
1609 return_value = smbd_smb2_request_process_sesssetup(req);
1610 END_PROFILE(smb2_sesssetup);
1614 case SMB2_OP_LOGOFF:
1615 if (!NT_STATUS_IS_OK(session_status)) {
1616 return_value = smbd_smb2_request_error(req, session_status);
1620 /* This call needs to be run as root */
1621 change_to_root_user();
1624 START_PROFILE(smb2_logoff);
1625 return_value = smbd_smb2_request_process_logoff(req);
1626 END_PROFILE(smb2_logoff);
1631 if (!NT_STATUS_IS_OK(session_status)) {
1632 return_value = smbd_smb2_request_error(req, session_status);
1637 * This call needs to be run as root.
1639 * smbd_smb2_request_process_tcon()
1640 * calls make_connection_snum(), which will call
1641 * change_to_user(), when needed.
1643 change_to_root_user();
1646 START_PROFILE(smb2_tcon);
1647 return_value = smbd_smb2_request_process_tcon(req);
1648 END_PROFILE(smb2_tcon);
1653 if (!NT_STATUS_IS_OK(session_status)) {
1654 return_value = smbd_smb2_request_error(req, session_status);
1658 * This call needs to be run as user.
1660 * smbd_smb2_request_check_tcon()
1661 * calls change_to_user() on success.
1663 status = smbd_smb2_request_check_tcon(req);
1664 if (!NT_STATUS_IS_OK(status)) {
1665 return_value = smbd_smb2_request_error(req, status);
1668 /* This call needs to be run as root */
1669 change_to_root_user();
1673 START_PROFILE(smb2_tdis);
1674 return_value = smbd_smb2_request_process_tdis(req);
1675 END_PROFILE(smb2_tdis);
1679 case SMB2_OP_CREATE:
1680 if (!NT_STATUS_IS_OK(session_status)) {
1681 return_value = smbd_smb2_request_error(req, session_status);
1685 * This call needs to be run as user.
1687 * smbd_smb2_request_check_tcon()
1688 * calls change_to_user() on success.
1690 status = smbd_smb2_request_check_tcon(req);
1691 if (!NT_STATUS_IS_OK(status)) {
1692 return_value = smbd_smb2_request_error(req, status);
1697 START_PROFILE(smb2_create);
1698 return_value = smbd_smb2_request_process_create(req);
1699 END_PROFILE(smb2_create);
1704 if (!NT_STATUS_IS_OK(session_status)) {
1705 return_value = smbd_smb2_request_error(req, session_status);
1709 * This call needs to be run as user.
1711 * smbd_smb2_request_check_tcon()
1712 * calls change_to_user() on success.
1714 status = smbd_smb2_request_check_tcon(req);
1715 if (!NT_STATUS_IS_OK(status)) {
1716 return_value = smbd_smb2_request_error(req, status);
1721 START_PROFILE(smb2_close);
1722 return_value = smbd_smb2_request_process_close(req);
1723 END_PROFILE(smb2_close);
1728 if (!NT_STATUS_IS_OK(session_status)) {
1729 return_value = smbd_smb2_request_error(req, session_status);
1733 * This call needs to be run as user.
1735 * smbd_smb2_request_check_tcon()
1736 * calls change_to_user() on success.
1738 status = smbd_smb2_request_check_tcon(req);
1739 if (!NT_STATUS_IS_OK(status)) {
1740 return_value = smbd_smb2_request_error(req, status);
1745 START_PROFILE(smb2_flush);
1746 return_value = smbd_smb2_request_process_flush(req);
1747 END_PROFILE(smb2_flush);
1752 if (!NT_STATUS_IS_OK(session_status)) {
1753 return_value = smbd_smb2_request_error(req, session_status);
1757 * This call needs to be run as user.
1759 * smbd_smb2_request_check_tcon()
1760 * calls change_to_user() on success.
1762 status = smbd_smb2_request_check_tcon(req);
1763 if (!NT_STATUS_IS_OK(status)) {
1764 return_value = smbd_smb2_request_error(req, status);
1769 START_PROFILE(smb2_read);
1770 return_value = smbd_smb2_request_process_read(req);
1771 END_PROFILE(smb2_read);
1776 if (!NT_STATUS_IS_OK(session_status)) {
1777 return_value = smbd_smb2_request_error(req, session_status);
1781 * This call needs to be run as user.
1783 * smbd_smb2_request_check_tcon()
1784 * calls change_to_user() on success.
1786 status = smbd_smb2_request_check_tcon(req);
1787 if (!NT_STATUS_IS_OK(status)) {
1788 return_value = smbd_smb2_request_error(req, status);
1793 START_PROFILE(smb2_write);
1794 return_value = smbd_smb2_request_process_write(req);
1795 END_PROFILE(smb2_write);
1800 if (!NT_STATUS_IS_OK(session_status)) {
1801 /* Too ugly to live ? JRA. */
1802 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1803 session_status = NT_STATUS_FILE_CLOSED;
1805 return_value = smbd_smb2_request_error(req, session_status);
1809 * This call needs to be run as user.
1811 * smbd_smb2_request_check_tcon()
1812 * calls change_to_user() on success.
1814 status = smbd_smb2_request_check_tcon(req);
1815 if (!NT_STATUS_IS_OK(status)) {
1816 /* Too ugly to live ? JRA. */
1817 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1818 status = NT_STATUS_FILE_CLOSED;
1820 return_value = smbd_smb2_request_error(req, status);
1825 START_PROFILE(smb2_lock);
1826 return_value = smbd_smb2_request_process_lock(req);
1827 END_PROFILE(smb2_lock);
1832 if (!NT_STATUS_IS_OK(session_status)) {
1833 return_value = smbd_smb2_request_error(req, session_status);
1837 * This call needs to be run as user.
1839 * smbd_smb2_request_check_tcon()
1840 * calls change_to_user() on success.
1842 status = smbd_smb2_request_check_tcon(req);
1843 if (!NT_STATUS_IS_OK(status)) {
1844 return_value = smbd_smb2_request_error(req, status);
1849 START_PROFILE(smb2_ioctl);
1850 return_value = smbd_smb2_request_process_ioctl(req);
1851 END_PROFILE(smb2_ioctl);
1855 case SMB2_OP_CANCEL:
1857 * This call needs to be run as root
1859 * That is what we also do in the SMB1 case.
1861 change_to_root_user();
1864 START_PROFILE(smb2_cancel);
1865 return_value = smbd_smb2_request_process_cancel(req);
1866 END_PROFILE(smb2_cancel);
1870 case SMB2_OP_KEEPALIVE:
1871 /* This call needs to be run as root */
1872 change_to_root_user();
1875 START_PROFILE(smb2_keepalive);
1876 return_value = smbd_smb2_request_process_keepalive(req);
1877 END_PROFILE(smb2_keepalive);
1882 if (!NT_STATUS_IS_OK(session_status)) {
1883 return_value = smbd_smb2_request_error(req, session_status);
1887 * This call needs to be run as user.
1889 * smbd_smb2_request_check_tcon()
1890 * calls change_to_user() on success.
1892 status = smbd_smb2_request_check_tcon(req);
1893 if (!NT_STATUS_IS_OK(status)) {
1894 return_value = smbd_smb2_request_error(req, status);
1899 START_PROFILE(smb2_find);
1900 return_value = smbd_smb2_request_process_find(req);
1901 END_PROFILE(smb2_find);
1905 case SMB2_OP_NOTIFY:
1906 if (!NT_STATUS_IS_OK(session_status)) {
1907 return_value = smbd_smb2_request_error(req, session_status);
1911 * This call needs to be run as user.
1913 * smbd_smb2_request_check_tcon()
1914 * calls change_to_user() on success.
1916 status = smbd_smb2_request_check_tcon(req);
1917 if (!NT_STATUS_IS_OK(status)) {
1918 return_value = smbd_smb2_request_error(req, status);
1923 START_PROFILE(smb2_notify);
1924 return_value = smbd_smb2_request_process_notify(req);
1925 END_PROFILE(smb2_notify);
1929 case SMB2_OP_GETINFO:
1930 if (!NT_STATUS_IS_OK(session_status)) {
1931 return_value = smbd_smb2_request_error(req, session_status);
1935 * This call needs to be run as user.
1937 * smbd_smb2_request_check_tcon()
1938 * calls change_to_user() on success.
1940 status = smbd_smb2_request_check_tcon(req);
1941 if (!NT_STATUS_IS_OK(status)) {
1942 return_value = smbd_smb2_request_error(req, status);
1947 START_PROFILE(smb2_getinfo);
1948 return_value = smbd_smb2_request_process_getinfo(req);
1949 END_PROFILE(smb2_getinfo);
1953 case SMB2_OP_SETINFO:
1954 if (!NT_STATUS_IS_OK(session_status)) {
1955 return_value = smbd_smb2_request_error(req, session_status);
1959 * This call needs to be run as user.
1961 * smbd_smb2_request_check_tcon()
1962 * calls change_to_user() on success.
1964 status = smbd_smb2_request_check_tcon(req);
1965 if (!NT_STATUS_IS_OK(status)) {
1966 return_value = smbd_smb2_request_error(req, status);
1971 START_PROFILE(smb2_setinfo);
1972 return_value = smbd_smb2_request_process_setinfo(req);
1973 END_PROFILE(smb2_setinfo);
1978 if (!NT_STATUS_IS_OK(session_status)) {
1979 return_value = smbd_smb2_request_error(req, session_status);
1983 * This call needs to be run as user.
1985 * smbd_smb2_request_check_tcon()
1986 * calls change_to_user() on success.
1988 status = smbd_smb2_request_check_tcon(req);
1989 if (!NT_STATUS_IS_OK(status)) {
1990 return_value = smbd_smb2_request_error(req, status);
1995 START_PROFILE(smb2_break);
1996 return_value = smbd_smb2_request_process_break(req);
1997 END_PROFILE(smb2_break);
2002 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2005 return return_value;
2008 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2010 struct tevent_req *subreq;
2011 int i = req->current_idx;
2014 TALLOC_FREE(req->async_te);
2016 req->current_idx += 3;
2018 if (req->current_idx < req->out.vector_count) {
2020 * We must process the remaining compound
2021 * SMB2 requests before any new incoming SMB2
2022 * requests. This is because incoming SMB2
2023 * requests may include a cancel for a
2024 * compound request we haven't processed
2027 struct tevent_immediate *im = tevent_create_immediate(req);
2029 return NT_STATUS_NO_MEMORY;
2031 tevent_schedule_immediate(im,
2033 smbd_smb2_request_dispatch_immediate,
2035 return NT_STATUS_OK;
2038 if (req->compound_related) {
2039 req->sconn->smb2.compound_related_in_progress = false;
2042 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2044 /* Set credit for these operations (zero credits if this
2045 is a final reply for an async operation). */
2046 smb2_calculate_credits(req, req);
2048 if (req->do_signing) {
2050 struct smbXsrv_session *x = req->session;
2051 struct smbXsrv_connection *conn = x->connection;
2052 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2054 status = smb2_signing_sign_pdu(signing_key,
2056 &req->out.vector[i], 3);
2057 if (!NT_STATUS_IS_OK(status)) {
2062 if (DEBUGLEVEL >= 10) {
2063 dbgtext("smbd_smb2_request_reply: sending...\n");
2064 print_req_vectors(req);
2067 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2068 if (req->out.vector_count == 4 &&
2069 req->out.vector[3].iov_base == NULL &&
2070 req->out.vector[3].iov_len != 0) {
2071 /* Dynamic part is NULL. Chop it off,
2072 We're going to send it via sendfile. */
2073 req->out.vector_count -= 1;
2076 subreq = tstream_writev_queue_send(req,
2078 req->sconn->smb2.stream,
2079 req->sconn->smb2.send_queue,
2081 req->out.vector_count);
2082 if (subreq == NULL) {
2083 return NT_STATUS_NO_MEMORY;
2085 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
2087 * We're done with this request -
2088 * move it off the "being processed" queue.
2090 DLIST_REMOVE(req->sconn->smb2.requests, req);
2092 return NT_STATUS_OK;
2095 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2097 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2098 struct tevent_immediate *im,
2101 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2102 struct smbd_smb2_request);
2103 struct smbd_server_connection *sconn = req->sconn;
2108 if (DEBUGLEVEL >= 10) {
2109 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2110 req->current_idx, req->in.vector_count));
2111 print_req_vectors(req);
2114 status = smbd_smb2_request_dispatch(req);
2115 if (!NT_STATUS_IS_OK(status)) {
2116 smbd_server_connection_terminate(sconn, nt_errstr(status));
2120 status = smbd_smb2_request_next_incoming(sconn);
2121 if (!NT_STATUS_IS_OK(status)) {
2122 smbd_server_connection_terminate(sconn, nt_errstr(status));
2127 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
2129 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
2130 struct smbd_smb2_request);
2131 struct smbd_server_connection *sconn = req->sconn;
2136 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2137 TALLOC_FREE(subreq);
2140 status = map_nt_error_from_unix(sys_errno);
2141 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2142 nt_errstr(status)));
2143 smbd_server_connection_terminate(sconn, nt_errstr(status));
2147 status = smbd_smb2_request_next_incoming(sconn);
2148 if (!NT_STATUS_IS_OK(status)) {
2149 smbd_server_connection_terminate(sconn, nt_errstr(status));
2154 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2156 DATA_BLOB body, DATA_BLOB *dyn,
2157 const char *location)
2160 int i = req->current_idx;
2161 uint32_t next_command_ofs;
2163 DEBUG(10,("smbd_smb2_request_done_ex: "
2164 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2165 i, nt_errstr(status), (unsigned int)body.length,
2167 (unsigned int)(dyn ? dyn->length : 0),
2170 if (body.length < 2) {
2171 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2174 if ((body.length % 2) != 0) {
2175 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2178 outhdr = (uint8_t *)req->out.vector[i].iov_base;
2180 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2181 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2183 req->out.vector[i+1].iov_base = (void *)body.data;
2184 req->out.vector[i+1].iov_len = body.length;
2187 req->out.vector[i+2].iov_base = (void *)dyn->data;
2188 req->out.vector[i+2].iov_len = dyn->length;
2190 req->out.vector[i+2].iov_base = NULL;
2191 req->out.vector[i+2].iov_len = 0;
2194 /* see if we need to recalculate the offset to the next response */
2195 if (next_command_ofs > 0) {
2196 next_command_ofs = SMB2_HDR_BODY;
2197 next_command_ofs += req->out.vector[i+1].iov_len;
2198 next_command_ofs += req->out.vector[i+2].iov_len;
2201 if ((next_command_ofs % 8) != 0) {
2202 size_t pad_size = 8 - (next_command_ofs % 8);
2203 if (req->out.vector[i+2].iov_len == 0) {
2205 * if the dyn buffer is empty
2206 * we can use it to add padding
2210 pad = talloc_zero_array(req->out.vector,
2213 return smbd_smb2_request_error(req,
2214 NT_STATUS_NO_MEMORY);
2217 req->out.vector[i+2].iov_base = (void *)pad;
2218 req->out.vector[i+2].iov_len = pad_size;
2221 * For now we copy the dynamic buffer
2222 * and add the padding to the new buffer
2229 old_size = req->out.vector[i+2].iov_len;
2230 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2232 new_size = old_size + pad_size;
2233 new_dyn = talloc_zero_array(req->out.vector,
2235 if (new_dyn == NULL) {
2236 return smbd_smb2_request_error(req,
2237 NT_STATUS_NO_MEMORY);
2240 memcpy(new_dyn, old_dyn, old_size);
2241 memset(new_dyn + old_size, 0, pad_size);
2243 req->out.vector[i+2].iov_base = (void *)new_dyn;
2244 req->out.vector[i+2].iov_len = new_size;
2246 next_command_ofs += pad_size;
2249 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2251 return smbd_smb2_request_reply(req);
2254 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2257 const char *location)
2260 int i = req->current_idx;
2261 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
2263 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2264 i, nt_errstr(status), info ? " +info" : "",
2267 body.data = outhdr + SMB2_HDR_BODY;
2269 SSVAL(body.data, 0, 9);
2272 SIVAL(body.data, 0x04, info->length);
2274 /* Allocated size of req->out.vector[i].iov_base
2275 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2276 * 1 byte without having to do an alloc.
2278 info = talloc_zero_array(req->out.vector,
2282 return NT_STATUS_NO_MEMORY;
2284 info->data = ((uint8_t *)outhdr) +
2285 OUTVEC_ALLOC_SIZE - 1;
2287 SCVAL(info->data, 0, 0);
2291 * if a request fails, all other remaining
2292 * compounded requests should fail too
2294 req->next_status = NT_STATUS_INVALID_PARAMETER;
2296 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2300 struct smbd_smb2_send_oplock_break_state {
2301 struct smbd_server_connection *sconn;
2302 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2303 struct iovec vector;
2306 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2308 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2309 uint64_t file_id_persistent,
2310 uint64_t file_id_volatile,
2311 uint8_t oplock_level)
2313 struct smbd_smb2_send_oplock_break_state *state;
2314 struct tevent_req *subreq;
2318 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2319 if (state == NULL) {
2320 return NT_STATUS_NO_MEMORY;
2322 state->sconn = sconn;
2324 state->vector.iov_base = (void *)state->buf;
2325 state->vector.iov_len = sizeof(state->buf);
2327 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2328 hdr = state->buf + 4;
2329 body = hdr + SMB2_HDR_BODY;
2331 SIVAL(hdr, 0, SMB2_MAGIC);
2332 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2333 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2334 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2335 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2336 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2337 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2338 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2339 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2340 SIVAL(hdr, SMB2_HDR_PID, 0);
2341 SIVAL(hdr, SMB2_HDR_TID, 0);
2342 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2343 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2345 SSVAL(body, 0x00, 0x18);
2347 SCVAL(body, 0x02, oplock_level);
2348 SCVAL(body, 0x03, 0); /* reserved */
2349 SIVAL(body, 0x04, 0); /* reserved */
2350 SBVAL(body, 0x08, file_id_persistent);
2351 SBVAL(body, 0x10, file_id_volatile);
2353 subreq = tstream_writev_queue_send(state,
2356 sconn->smb2.send_queue,
2358 if (subreq == NULL) {
2359 return NT_STATUS_NO_MEMORY;
2361 tevent_req_set_callback(subreq,
2362 smbd_smb2_oplock_break_writev_done,
2365 return NT_STATUS_OK;
2368 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2370 struct smbd_smb2_send_oplock_break_state *state =
2371 tevent_req_callback_data(subreq,
2372 struct smbd_smb2_send_oplock_break_state);
2373 struct smbd_server_connection *sconn = state->sconn;
2377 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2378 TALLOC_FREE(subreq);
2380 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2381 smbd_server_connection_terminate(sconn, nt_errstr(status));
2388 struct smbd_smb2_request_read_state {
2390 bool asked_for_header;
2391 struct smbd_smb2_request *smb2_req;
2394 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2396 TALLOC_CTX *mem_ctx,
2397 struct iovec **_vector,
2399 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2401 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2402 struct tevent_context *ev,
2403 struct smbd_server_connection *sconn)
2405 struct tevent_req *req;
2406 struct smbd_smb2_request_read_state *state;
2407 struct tevent_req *subreq;
2409 req = tevent_req_create(mem_ctx, &state,
2410 struct smbd_smb2_request_read_state);
2415 state->asked_for_header = false;
2417 state->smb2_req = smbd_smb2_request_allocate(state);
2418 if (tevent_req_nomem(state->smb2_req, req)) {
2419 return tevent_req_post(req, ev);
2421 state->smb2_req->sconn = sconn;
2423 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2424 sconn->smb2.recv_queue,
2425 smbd_smb2_request_next_vector,
2427 if (tevent_req_nomem(subreq, req)) {
2428 return tevent_req_post(req, ev);
2430 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2435 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2437 TALLOC_CTX *mem_ctx,
2438 struct iovec **_vector,
2441 struct smbd_smb2_request_read_state *state =
2442 talloc_get_type_abort(private_data,
2443 struct smbd_smb2_request_read_state);
2444 struct smbd_smb2_request *req = state->smb2_req;
2445 struct iovec *vector;
2446 int idx = req->in.vector_count;
2448 uint8_t *buf = NULL;
2450 if (req->in.vector_count == 0) {
2452 * first we need to get the NBT header
2454 req->in.vector = talloc_array(req, struct iovec,
2455 req->in.vector_count + 1);
2456 if (req->in.vector == NULL) {
2459 req->in.vector_count += 1;
2461 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2462 req->in.vector[idx].iov_len = 4;
2464 vector = talloc_array(mem_ctx, struct iovec, 1);
2465 if (vector == NULL) {
2469 vector[0] = req->in.vector[idx];
2476 if (req->in.vector_count == 1) {
2478 * Now we analyze the NBT header
2480 state->missing = smb2_len(req->in.vector[0].iov_base);
2482 if (state->missing == 0) {
2483 /* if there're no remaining bytes, we're done */
2489 req->in.vector = talloc_realloc(req, req->in.vector,
2491 req->in.vector_count + 1);
2492 if (req->in.vector == NULL) {
2495 req->in.vector_count += 1;
2497 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2499 * it's a special NBT message,
2500 * so get all remaining bytes
2502 len = state->missing;
2503 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2505 * it's an invalid message, just read what we can get
2506 * and let the caller handle the error
2508 len = state->missing;
2511 * We assume it's a SMB2 request,
2512 * and we first get the header and the
2513 * first 2 bytes (the struct size) of the body
2515 len = SMB2_HDR_BODY + 2;
2517 state->asked_for_header = true;
2520 state->missing -= len;
2522 buf = talloc_array(req->in.vector, uint8_t, len);
2527 req->in.vector[idx].iov_base = (void *)buf;
2528 req->in.vector[idx].iov_len = len;
2530 vector = talloc_array(mem_ctx, struct iovec, 1);
2531 if (vector == NULL) {
2535 vector[0] = req->in.vector[idx];
2542 if (state->missing == 0) {
2543 /* if there're no remaining bytes, we're done */
2549 if (state->asked_for_header) {
2552 size_t next_command_ofs;
2557 bool invalid = false;
2559 state->asked_for_header = false;
2562 * We got the SMB2 header and the first 2 bytes
2563 * of the body. We fix the size to just the header
2564 * and manually copy the 2 first bytes to the body section
2566 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2567 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2569 /* allocate vectors for body and dynamic areas */
2570 req->in.vector = talloc_realloc(req, req->in.vector,
2572 req->in.vector_count + 2);
2573 if (req->in.vector == NULL) {
2576 req->in.vector_count += 2;
2578 full_size = state->missing + SMB2_HDR_BODY + 2;
2579 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2580 body_size = SVAL(hdr, SMB2_HDR_BODY);
2582 if (next_command_ofs != 0) {
2583 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2585 * this is invalid, just return a zero
2586 * body and let the caller deal with the error
2589 } else if (next_command_ofs > full_size) {
2591 * this is invalid, just return a zero
2592 * body and let the caller deal with the error
2596 full_size = next_command_ofs;
2601 if (body_size < 2) {
2603 * this is invalid, just return a zero
2604 * body and let the caller deal with the error
2610 * Mask out the lowest bit, the "dynamic" part
2615 if (body_size > (full_size - SMB2_HDR_BODY)) {
2617 * this is invalid, just return a zero
2618 * body and let the caller deal with the error
2625 /* the caller should check this */
2629 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2631 state->missing -= (body_size - 2) + dyn_size;
2633 body = talloc_array(req->in.vector, uint8_t, body_size);
2638 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2643 req->in.vector[idx].iov_base = (void *)body;
2644 req->in.vector[idx].iov_len = body_size;
2645 req->in.vector[idx+1].iov_base = (void *)dyn;
2646 req->in.vector[idx+1].iov_len = dyn_size;
2648 vector = talloc_array(mem_ctx, struct iovec, 2);
2649 if (vector == NULL) {
2654 * the first 2 bytes of the body were already fetched
2655 * together with the header
2657 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2658 vector[0].iov_base = body + 2;
2659 vector[0].iov_len = body_size - 2;
2661 vector[1] = req->in.vector[idx+1];
2669 * when we endup here, we're looking for a new SMB2 request
2670 * next. And we ask for its header and the first 2 bytes of
2671 * the body (like we did for the first SMB2 request).
2674 req->in.vector = talloc_realloc(req, req->in.vector,
2676 req->in.vector_count + 1);
2677 if (req->in.vector == NULL) {
2680 req->in.vector_count += 1;
2683 * We assume it's a SMB2 request,
2684 * and we first get the header and the
2685 * first 2 bytes (the struct size) of the body
2687 len = SMB2_HDR_BODY + 2;
2689 if (len > state->missing) {
2690 /* let the caller handle the error */
2691 len = state->missing;
2694 state->missing -= len;
2695 state->asked_for_header = true;
2697 buf = talloc_array(req->in.vector, uint8_t, len);
2702 req->in.vector[idx].iov_base = (void *)buf;
2703 req->in.vector[idx].iov_len = len;
2705 vector = talloc_array(mem_ctx, struct iovec, 1);
2706 if (vector == NULL) {
2710 vector[0] = req->in.vector[idx];
2717 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2719 struct tevent_req *req =
2720 tevent_req_callback_data(subreq,
2726 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2728 status = map_nt_error_from_unix(sys_errno);
2729 tevent_req_nterror(req, status);
2733 tevent_req_done(req);
2736 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2737 TALLOC_CTX *mem_ctx,
2738 struct smbd_smb2_request **_smb2_req)
2740 struct smbd_smb2_request_read_state *state =
2741 tevent_req_data(req,
2742 struct smbd_smb2_request_read_state);
2745 if (tevent_req_is_nterror(req, &status)) {
2746 tevent_req_received(req);
2750 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2751 *_smb2_req = state->smb2_req;
2752 tevent_req_received(req);
2753 return NT_STATUS_OK;
2756 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2758 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2760 size_t max_send_queue_len;
2761 size_t cur_send_queue_len;
2762 struct tevent_req *subreq;
2764 if (sconn->smb2.compound_related_in_progress) {
2766 * Can't read another until the related
2769 return NT_STATUS_OK;
2772 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2774 * if there is already a smbd_smb2_request_read
2775 * pending, we are done.
2777 return NT_STATUS_OK;
2780 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2781 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2783 if (cur_send_queue_len > max_send_queue_len) {
2785 * if we have a lot of requests to send,
2786 * we wait until they are on the wire until we
2787 * ask for the next request.
2789 return NT_STATUS_OK;
2792 /* ask for the next request */
2793 subreq = smbd_smb2_request_read_send(sconn, sconn->ev_ctx, sconn);
2794 if (subreq == NULL) {
2795 return NT_STATUS_NO_MEMORY;
2797 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2799 return NT_STATUS_OK;
2802 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2803 const uint8_t *inbuf, size_t size)
2806 struct smbd_smb2_request *req = NULL;
2808 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2809 (unsigned int)size));
2811 status = smbd_initialize_smb2(sconn);
2812 if (!NT_STATUS_IS_OK(status)) {
2813 smbd_server_connection_terminate(sconn, nt_errstr(status));
2817 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2818 if (!NT_STATUS_IS_OK(status)) {
2819 smbd_server_connection_terminate(sconn, nt_errstr(status));
2823 status = smbd_smb2_request_validate(req);
2824 if (!NT_STATUS_IS_OK(status)) {
2825 smbd_server_connection_terminate(sconn, nt_errstr(status));
2829 status = smbd_smb2_request_setup_out(req);
2830 if (!NT_STATUS_IS_OK(status)) {
2831 smbd_server_connection_terminate(sconn, nt_errstr(status));
2835 status = smbd_smb2_request_dispatch(req);
2836 if (!NT_STATUS_IS_OK(status)) {
2837 smbd_server_connection_terminate(sconn, nt_errstr(status));
2841 status = smbd_smb2_request_next_incoming(sconn);
2842 if (!NT_STATUS_IS_OK(status)) {
2843 smbd_server_connection_terminate(sconn, nt_errstr(status));
2847 sconn->num_requests++;
2850 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2852 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2853 struct smbd_server_connection);
2855 struct smbd_smb2_request *req = NULL;
2857 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2858 TALLOC_FREE(subreq);
2859 if (!NT_STATUS_IS_OK(status)) {
2860 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2861 nt_errstr(status)));
2862 smbd_server_connection_terminate(sconn, nt_errstr(status));
2866 if (req->in.nbt_hdr[0] != 0x00) {
2867 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2868 req->in.nbt_hdr[0]));
2873 req->current_idx = 1;
2875 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2876 req->current_idx, req->in.vector_count));
2878 status = smbd_smb2_request_validate(req);
2879 if (!NT_STATUS_IS_OK(status)) {
2880 smbd_server_connection_terminate(sconn, nt_errstr(status));
2884 status = smbd_smb2_request_setup_out(req);
2885 if (!NT_STATUS_IS_OK(status)) {
2886 smbd_server_connection_terminate(sconn, nt_errstr(status));
2890 status = smbd_smb2_request_dispatch(req);
2891 if (!NT_STATUS_IS_OK(status)) {
2892 smbd_server_connection_terminate(sconn, nt_errstr(status));
2897 status = smbd_smb2_request_next_incoming(sconn);
2898 if (!NT_STATUS_IS_OK(status)) {
2899 smbd_server_connection_terminate(sconn, nt_errstr(status));
2903 sconn->num_requests++;
2905 /* The timeout_processing function isn't run nearly
2906 often enough to implement 'max log size' without
2907 overrunning the size of the file by many megabytes.
2908 This is especially true if we are running at debug
2909 level 10. Checking every 50 SMB2s is a nice
2910 tradeoff of performance vs log file size overrun. */
2912 if ((sconn->num_requests % 50) == 0 &&
2913 need_to_check_log_size()) {
2914 change_to_root_user();