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.event_ctx = server_event_context();
103 sconn->smb2.recv_queue = tevent_queue_create(sconn, "smb2 recv queue");
104 if (sconn->smb2.recv_queue == NULL) {
105 return NT_STATUS_NO_MEMORY;
108 sconn->smb2.send_queue = tevent_queue_create(sconn, "smb2 send queue");
109 if (sconn->smb2.send_queue == NULL) {
110 return NT_STATUS_NO_MEMORY;
113 sconn->smb2.sessions.idtree = idr_init(sconn);
114 if (sconn->smb2.sessions.idtree == NULL) {
115 return NT_STATUS_NO_MEMORY;
117 sconn->smb2.sessions.limit = 0x0000FFFE;
118 sconn->smb2.sessions.list = NULL;
119 sconn->smb2.seqnum_low = 0;
120 sconn->smb2.credits_granted = 0;
121 sconn->smb2.max_credits = lp_smb2_max_credits();
122 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
123 DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR*sconn->smb2.max_credits);
124 if (sconn->smb2.credits_bitmap == NULL) {
125 return NT_STATUS_NO_MEMORY;
128 ret = tstream_bsd_existing_socket(sconn, sconn->sock,
129 &sconn->smb2.stream);
131 status = map_nt_error_from_unix(errno);
135 /* Ensure child is set to non-blocking mode */
136 set_blocking(sconn->sock, false);
140 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
141 #define _smb2_setlen(_buf,len) do { \
142 uint8_t *buf = (uint8_t *)_buf; \
144 buf[1] = ((len)&0xFF0000)>>16; \
145 buf[2] = ((len)&0xFF00)>>8; \
146 buf[3] = (len)&0xFF; \
149 static void smb2_setup_nbt_length(struct iovec *vector, int count)
154 for (i=1; i < count; i++) {
155 len += vector[i].iov_len;
158 _smb2_setlen(vector[0].iov_base, len);
161 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request **req)
164 (*req)->parent = NULL;
165 (*req)->mem_pool = NULL;
171 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
175 talloc_free(req->mem_pool);
181 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
183 TALLOC_CTX *mem_pool;
184 struct smbd_smb2_request **parent;
185 struct smbd_smb2_request *req;
188 /* Enable this to find subtle valgrind errors. */
189 mem_pool = talloc_init("smbd_smb2_request_allocate");
191 mem_pool = talloc_pool(mem_ctx, 8192);
193 if (mem_pool == NULL) {
197 parent = talloc(mem_pool, struct smbd_smb2_request *);
198 if (parent == NULL) {
199 talloc_free(mem_pool);
203 req = talloc_zero(parent, struct smbd_smb2_request);
205 talloc_free(mem_pool);
209 req->mem_pool = mem_pool;
210 req->parent = parent;
212 talloc_set_destructor(parent, smbd_smb2_request_parent_destructor);
213 talloc_set_destructor(req, smbd_smb2_request_destructor);
218 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
219 const uint8_t *inbuf, size_t size,
220 struct smbd_smb2_request **_req)
222 struct smbd_smb2_request *req;
223 uint32_t protocol_version;
224 const uint8_t *inhdr = NULL;
227 uint32_t next_command_ofs;
229 if (size < (4 + SMB2_HDR_BODY + 2)) {
230 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
231 return NT_STATUS_INVALID_PARAMETER;
236 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
237 if (protocol_version != SMB2_MAGIC) {
238 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
240 return NT_STATUS_INVALID_PARAMETER;
243 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
244 if (cmd != SMB2_OP_NEGPROT) {
245 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
247 return NT_STATUS_INVALID_PARAMETER;
250 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
251 if (next_command_ofs != 0) {
252 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
254 return NT_STATUS_INVALID_PARAMETER;
257 req = smbd_smb2_request_allocate(sconn);
259 return NT_STATUS_NO_MEMORY;
263 talloc_steal(req, inbuf);
265 req->in.vector = talloc_array(req, struct iovec, 4);
266 if (req->in.vector == NULL) {
268 return NT_STATUS_NO_MEMORY;
270 req->in.vector_count = 4;
272 memcpy(req->in.nbt_hdr, inbuf, 4);
275 req->in.vector[0].iov_base = discard_const_p(void, req->in.nbt_hdr);
276 req->in.vector[0].iov_len = 4;
277 ofs += req->in.vector[0].iov_len;
279 req->in.vector[1].iov_base = discard_const_p(void, (inbuf + ofs));
280 req->in.vector[1].iov_len = SMB2_HDR_BODY;
281 ofs += req->in.vector[1].iov_len;
283 req->in.vector[2].iov_base = discard_const_p(void, (inbuf + ofs));
284 req->in.vector[2].iov_len = SVAL(inbuf, ofs) & 0xFFFE;
285 ofs += req->in.vector[2].iov_len;
288 return NT_STATUS_INVALID_PARAMETER;
291 req->in.vector[3].iov_base = discard_const_p(void, (inbuf + ofs));
292 req->in.vector[3].iov_len = size - ofs;
293 ofs += req->in.vector[3].iov_len;
295 req->current_idx = 1;
301 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
302 const uint8_t *inhdr)
304 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
305 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
306 uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
307 unsigned int bitmap_offset;
309 if (opcode == SMB2_OP_CANCEL) {
310 /* SMB2_CANCEL requests by definition resend messageids. */
314 if (message_id < sconn->smb2.seqnum_low ||
315 message_id > (sconn->smb2.seqnum_low +
316 (sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR))) {
317 DEBUG(0,("smb2_validate_message_id: bad message_id "
318 "%llu (low = %llu, max = %lu)\n",
319 (unsigned long long)message_id,
320 (unsigned long long)sconn->smb2.seqnum_low,
321 (unsigned long)sconn->smb2.max_credits ));
325 /* client just used a credit. */
326 SMB_ASSERT(sconn->smb2.credits_granted > 0);
327 sconn->smb2.credits_granted -= 1;
329 /* Mark the message_id as seen in the bitmap. */
330 bitmap_offset = (unsigned int)(message_id %
331 (uint64_t)(sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR));
332 if (bitmap_query(credits_bm, bitmap_offset)) {
333 DEBUG(0,("smb2_validate_message_id: duplicate message_id "
334 "%llu (bm offset %u)\n",
335 (unsigned long long)message_id,
339 bitmap_set(credits_bm, bitmap_offset);
341 if (message_id == sconn->smb2.seqnum_low + 1) {
342 /* Move the window forward by all the message_id's
344 while (bitmap_query(credits_bm, bitmap_offset)) {
345 DEBUG(10,("smb2_validate_message_id: clearing "
346 "id %llu (position %u) from bitmap\n",
347 (unsigned long long)(sconn->smb2.seqnum_low + 1),
349 bitmap_clear(credits_bm, bitmap_offset);
350 sconn->smb2.seqnum_low += 1;
351 bitmap_offset = (bitmap_offset + 1) %
352 (sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR);
359 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
363 bool compound_related = false;
365 count = req->in.vector_count;
368 /* It's not a SMB2 request */
369 return NT_STATUS_INVALID_PARAMETER;
372 for (idx=1; idx < count; idx += 3) {
373 const uint8_t *inhdr = NULL;
376 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
377 return NT_STATUS_INVALID_PARAMETER;
380 if (req->in.vector[idx+1].iov_len < 2) {
381 return NT_STATUS_INVALID_PARAMETER;
384 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
386 /* Check the SMB2 header */
387 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
388 return NT_STATUS_INVALID_PARAMETER;
391 if (!smb2_validate_message_id(req->sconn, inhdr)) {
392 return NT_STATUS_INVALID_PARAMETER;
395 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
398 * the 1st request should never have the
399 * SMB2_HDR_FLAG_CHAINED flag set
401 if (flags & SMB2_HDR_FLAG_CHAINED) {
402 req->next_status = NT_STATUS_INVALID_PARAMETER;
405 } else if (idx == 4) {
407 * the 2nd request triggers related vs. unrelated
408 * compounded requests
410 if (flags & SMB2_HDR_FLAG_CHAINED) {
411 compound_related = true;
413 } else if (idx > 4) {
416 * It seems the this tests are wrong
417 * see the SMB2-COMPOUND test
421 * all other requests should match the 2nd one
423 if (flags & SMB2_HDR_FLAG_CHAINED) {
424 if (!compound_related) {
426 NT_STATUS_INVALID_PARAMETER;
430 if (compound_related) {
432 NT_STATUS_INVALID_PARAMETER;
443 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
444 const struct iovec *in_vector,
445 struct iovec *out_vector)
447 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
448 uint16_t credits_requested = 0;
449 uint16_t credits_granted = 0;
451 if (in_vector != NULL) {
452 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
453 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
456 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
458 if (credits_requested) {
459 uint16_t modified_credits_requested;
463 * Split up max_credits into 1/16ths, and then scale
464 * the requested credits by how many 16ths have been
465 * currently granted. Less than 1/16th == grant all
466 * requested (100%), scale down as more have been
467 * granted. Never ask for less than 1 as the client
468 * asked for at least 1. JRA.
471 multiplier = 16 - (((sconn->smb2.credits_granted * 16) / sconn->smb2.max_credits) % 16);
473 modified_credits_requested = (multiplier * credits_requested) / 16;
474 if (modified_credits_requested == 0) {
475 modified_credits_requested = 1;
478 /* Remember what we gave out. */
479 credits_granted = MIN(modified_credits_requested,
480 (sconn->smb2.max_credits - sconn->smb2.credits_granted));
483 if (credits_granted == 0 && sconn->smb2.credits_granted == 0) {
484 /* First negprot packet, or ensure the client credits can
485 never drop to zero. */
489 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
490 sconn->smb2.credits_granted += credits_granted;
492 DEBUG(10,("smb2_set_operation_credit: requested %u, "
493 "granted %u, total granted %u\n",
494 (unsigned int)credits_requested,
495 (unsigned int)credits_granted,
496 (unsigned int)sconn->smb2.credits_granted ));
499 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
500 struct smbd_smb2_request *outreq)
504 count = outreq->out.vector_count;
506 for (idx=1; idx < count; idx += 3) {
507 smb2_set_operation_credit(outreq->sconn,
508 &inreq->in.vector[idx],
509 &outreq->out.vector[idx]);
513 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
515 struct iovec *vector;
519 count = req->in.vector_count;
520 vector = talloc_zero_array(req, struct iovec, count);
521 if (vector == NULL) {
522 return NT_STATUS_NO_MEMORY;
525 vector[0].iov_base = req->out.nbt_hdr;
526 vector[0].iov_len = 4;
527 SIVAL(req->out.nbt_hdr, 0, 0);
529 for (idx=1; idx < count; idx += 3) {
530 const uint8_t *inhdr = NULL;
532 uint8_t *outhdr = NULL;
533 uint8_t *outbody = NULL;
534 uint32_t next_command_ofs = 0;
535 struct iovec *current = &vector[idx];
537 if ((idx + 3) < count) {
538 /* we have a next command -
539 * setup for the error case. */
540 next_command_ofs = SMB2_HDR_BODY + 9;
543 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
544 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
546 outhdr = talloc_zero_array(vector, uint8_t,
548 if (outhdr == NULL) {
549 return NT_STATUS_NO_MEMORY;
552 outbody = outhdr + SMB2_HDR_BODY;
554 current[0].iov_base = (void *)outhdr;
555 current[0].iov_len = SMB2_HDR_BODY;
557 current[1].iov_base = (void *)outbody;
558 current[1].iov_len = 8;
560 current[2].iov_base = NULL;
561 current[2].iov_len = 0;
563 /* setup the SMB2 header */
564 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
565 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
566 SSVAL(outhdr, SMB2_HDR_EPOCH, 0);
567 SIVAL(outhdr, SMB2_HDR_STATUS,
568 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
569 SSVAL(outhdr, SMB2_HDR_OPCODE,
570 SVAL(inhdr, SMB2_HDR_OPCODE));
571 SIVAL(outhdr, SMB2_HDR_FLAGS,
572 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
573 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
574 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
575 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
576 SIVAL(outhdr, SMB2_HDR_PID,
577 IVAL(inhdr, SMB2_HDR_PID));
578 SIVAL(outhdr, SMB2_HDR_TID,
579 IVAL(inhdr, SMB2_HDR_TID));
580 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
581 BVAL(inhdr, SMB2_HDR_SESSION_ID));
582 memset(outhdr + SMB2_HDR_SIGNATURE, 0, 16);
584 /* setup error body header */
585 SSVAL(outbody, 0x00, 0x08 + 1);
586 SSVAL(outbody, 0x02, 0);
587 SIVAL(outbody, 0x04, 0);
590 req->out.vector = vector;
591 req->out.vector_count = count;
593 /* setup the length of the NBT packet */
594 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
596 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
601 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
603 const char *location)
605 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
607 exit_server_cleanly(reason);
610 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
611 struct iovec *outvec,
612 const struct iovec *srcvec)
614 /* vec[0] is always boilerplate and must
615 * be allocated with size OUTVEC_ALLOC_SIZE. */
617 outvec[0].iov_base = talloc_memdup(ctx,
620 if (!outvec[0].iov_base) {
623 outvec[0].iov_len = SMB2_HDR_BODY;
626 * If this is a "standard" vec[1] of length 8,
627 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
628 * then duplicate this. Else use talloc_memdup().
631 if (srcvec[1].iov_len == 8 &&
632 srcvec[1].iov_base ==
633 ((uint8_t *)srcvec[0].iov_base) +
635 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
637 outvec[1].iov_len = 8;
639 outvec[1].iov_base = talloc_memdup(ctx,
642 if (!outvec[1].iov_base) {
645 outvec[1].iov_len = srcvec[1].iov_len;
649 * If this is a "standard" vec[2] of length 1,
650 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
651 * then duplicate this. Else use talloc_memdup().
654 if (srcvec[2].iov_base &&
656 if (srcvec[2].iov_base ==
657 ((uint8_t *)srcvec[0].iov_base) +
658 (OUTVEC_ALLOC_SIZE - 1) &&
659 srcvec[2].iov_len == 1) {
660 /* Common SMB2 error packet case. */
661 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
662 (OUTVEC_ALLOC_SIZE - 1);
664 outvec[2].iov_base = talloc_memdup(ctx,
667 if (!outvec[2].iov_base) {
671 outvec[2].iov_len = srcvec[2].iov_len;
673 outvec[2].iov_base = NULL;
674 outvec[2].iov_len = 0;
679 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
681 struct smbd_smb2_request *newreq = NULL;
682 struct iovec *outvec = NULL;
683 int count = req->out.vector_count;
686 newreq = smbd_smb2_request_allocate(req->sconn);
691 newreq->sconn = req->sconn;
692 newreq->session = req->session;
693 newreq->do_signing = req->do_signing;
694 newreq->current_idx = req->current_idx;
695 newreq->async = false;
696 newreq->cancelled = false;
697 /* Note we are leaving:
701 uninitialized as NULL here as
702 they're not used in the interim
703 response code. JRA. */
705 outvec = talloc_zero_array(newreq, struct iovec, count);
710 newreq->out.vector = outvec;
711 newreq->out.vector_count = count;
713 /* Setup the outvec's identically to req. */
714 outvec[0].iov_base = newreq->out.nbt_hdr;
715 outvec[0].iov_len = 4;
716 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
718 /* Setup the vectors identically to the ones in req. */
719 for (i = 1; i < count; i += 3) {
720 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
731 smb2_setup_nbt_length(newreq->out.vector,
732 newreq->out.vector_count);
737 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
739 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
742 uint8_t *outhdr = NULL;
743 struct smbd_smb2_request *nreq = NULL;
745 /* Create a new smb2 request we'll use
746 for the interim return. */
747 nreq = dup_smb2_req(req);
749 return NT_STATUS_NO_MEMORY;
752 /* Lose the last 3 out vectors. They're the
753 ones we'll be using for the async reply. */
754 nreq->out.vector_count -= 3;
756 smb2_setup_nbt_length(nreq->out.vector,
757 nreq->out.vector_count);
759 /* Step back to the previous reply. */
760 i = nreq->current_idx - 3;
761 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
762 /* And end the chain. */
763 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
765 /* Calculate outgoing credits */
766 smb2_calculate_credits(req, nreq);
768 /* Re-sign if needed. */
769 if (nreq->do_signing) {
771 status = smb2_signing_sign_pdu(nreq->session->session_key,
772 &nreq->out.vector[i], 3);
773 if (!NT_STATUS_IS_OK(status)) {
777 if (DEBUGLEVEL >= 10) {
778 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
779 (unsigned int)nreq->current_idx );
780 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
781 (unsigned int)nreq->out.vector_count );
782 print_req_vectors(nreq);
784 nreq->subreq = tstream_writev_queue_send(nreq,
785 nreq->sconn->smb2.event_ctx,
786 nreq->sconn->smb2.stream,
787 nreq->sconn->smb2.send_queue,
789 nreq->out.vector_count);
791 if (nreq->subreq == NULL) {
792 return NT_STATUS_NO_MEMORY;
795 tevent_req_set_callback(nreq->subreq,
796 smbd_smb2_request_writev_done,
802 struct smbd_smb2_request_pending_state {
803 struct smbd_server_connection *sconn;
804 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
805 struct iovec vector[3];
808 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
810 struct smbd_smb2_request_pending_state *state =
811 tevent_req_callback_data(subreq,
812 struct smbd_smb2_request_pending_state);
813 struct smbd_server_connection *sconn = state->sconn;
817 ret = tstream_writev_queue_recv(subreq, &sys_errno);
820 NTSTATUS status = map_nt_error_from_unix(sys_errno);
821 smbd_server_connection_terminate(sconn, nt_errstr(status));
828 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
829 struct tevent_req *subreq)
832 struct smbd_smb2_request_pending_state *state = NULL;
833 int i = req->current_idx;
834 uint8_t *reqhdr = NULL;
836 uint8_t *body = NULL;
838 uint64_t message_id = 0;
839 uint64_t async_id = 0;
840 struct iovec *outvec = NULL;
842 if (!tevent_req_is_in_progress(subreq)) {
846 req->subreq = subreq;
850 /* We're already async. */
854 if (req->in.vector_count > i + 3) {
856 * We're trying to go async in a compound
857 * request chain. This is not allowed.
858 * Cancel the outstanding request.
860 tevent_req_cancel(req->subreq);
861 return smbd_smb2_request_error(req,
862 NT_STATUS_INSUFFICIENT_RESOURCES);
865 if (DEBUGLEVEL >= 10) {
866 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
867 (unsigned int)req->current_idx );
868 print_req_vectors(req);
871 if (req->out.vector_count > 4) {
872 /* This is a compound reply. We
873 * must do an interim response
874 * followed by the async response
877 status = smb2_send_async_interim_response(req);
878 if (!NT_STATUS_IS_OK(status)) {
883 /* Don't return an intermediate packet on a pipe read/write. */
884 if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
888 reqhdr = (uint8_t *)req->out.vector[i].iov_base;
889 flags = (IVAL(reqhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
890 message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
891 async_id = message_id; /* keep it simple for now... */
894 * What we send is identical to a smbd_smb2_request_error
895 * packet with an error status of STATUS_PENDING. Make use
896 * of this fact sometime when refactoring. JRA.
899 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
901 return NT_STATUS_NO_MEMORY;
903 state->sconn = req->sconn;
905 state->vector[0].iov_base = (void *)state->buf;
906 state->vector[0].iov_len = 4;
908 state->vector[1].iov_base = state->buf + 4;
909 state->vector[1].iov_len = SMB2_HDR_BODY;
911 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
912 state->vector[2].iov_len = 9;
914 smb2_setup_nbt_length(state->vector, 3);
916 hdr = (uint8_t *)state->vector[1].iov_base;
917 body = (uint8_t *)state->vector[2].iov_base;
919 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
920 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
921 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
922 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
923 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(reqhdr, SMB2_HDR_OPCODE));
925 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
926 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
927 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
928 SBVAL(hdr, SMB2_HDR_PID, async_id);
929 SBVAL(hdr, SMB2_HDR_SESSION_ID,
930 BVAL(reqhdr, SMB2_HDR_SESSION_ID));
931 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
933 SSVAL(body, 0x00, 0x08 + 1);
935 SCVAL(body, 0x02, 0);
936 SCVAL(body, 0x03, 0);
937 SIVAL(body, 0x04, 0);
938 /* Match W2K8R2... */
939 SCVAL(body, 0x08, 0x21);
941 /* Ensure we correctly go through crediting. Grant
942 the credits now, and zero credits on the final
944 smb2_set_operation_credit(req->sconn,
948 if (req->do_signing) {
949 status = smb2_signing_sign_pdu(req->session->session_key,
950 &state->vector[1], 2);
951 if (!NT_STATUS_IS_OK(status)) {
956 subreq = tstream_writev_queue_send(state,
957 req->sconn->smb2.event_ctx,
958 req->sconn->smb2.stream,
959 req->sconn->smb2.send_queue,
963 if (subreq == NULL) {
964 return NT_STATUS_NO_MEMORY;
967 tevent_req_set_callback(subreq,
968 smbd_smb2_request_pending_writev_done,
971 /* Note we're going async with this request. */
975 * Now manipulate req so that the outstanding async request
976 * is the only one left in the struct smbd_smb2_request.
979 if (req->current_idx == 1) {
980 /* There was only one. */
984 /* Re-arrange the in.vectors. */
985 req->in.vector[1] = req->in.vector[i];
986 req->in.vector[2] = req->in.vector[i+1];
987 req->in.vector[3] = req->in.vector[i+2];
988 req->in.vector_count = 4;
989 /* Reset the new in size. */
990 smb2_setup_nbt_length(req->in.vector, 4);
992 /* Now recreate the out.vectors. */
993 outvec = talloc_zero_array(req, struct iovec, 4);
995 return NT_STATUS_NO_MEMORY;
998 /* 0 is always boilerplate and must
999 * be of size 4 for the length field. */
1001 outvec[0].iov_base = req->out.nbt_hdr;
1002 outvec[0].iov_len = 4;
1003 SIVAL(req->out.nbt_hdr, 0, 0);
1005 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
1006 return NT_STATUS_NO_MEMORY;
1009 TALLOC_FREE(req->out.vector);
1011 req->out.vector = outvec;
1013 req->current_idx = 1;
1014 req->out.vector_count = 4;
1018 smb2_setup_nbt_length(req->out.vector,
1019 req->out.vector_count);
1021 /* Ensure our final reply matches the interim one. */
1022 reqhdr = (uint8_t *)req->out.vector[1].iov_base;
1023 SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1024 SBVAL(reqhdr, SMB2_HDR_PID, async_id);
1027 const uint8_t *inhdr =
1028 (const uint8_t *)req->in.vector[1].iov_base;
1029 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1031 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1032 (unsigned long long)async_id ));
1034 return NT_STATUS_OK;
1037 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1039 struct smbd_server_connection *sconn = req->sconn;
1040 struct smbd_smb2_request *cur;
1041 const uint8_t *inhdr;
1042 int i = req->current_idx;
1044 uint64_t search_message_id;
1045 uint64_t search_async_id;
1048 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1050 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1051 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1052 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1055 * we don't need the request anymore
1056 * cancel requests never have a response
1058 DLIST_REMOVE(req->sconn->smb2.requests, req);
1061 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1062 const uint8_t *outhdr;
1063 uint64_t message_id;
1066 i = cur->current_idx;
1068 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1070 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1071 async_id = BVAL(outhdr, SMB2_HDR_PID);
1073 if (flags & SMB2_HDR_FLAG_ASYNC) {
1074 if (search_async_id == async_id) {
1075 found_id = async_id;
1079 if (search_message_id == message_id) {
1080 found_id = message_id;
1086 if (cur && cur->subreq) {
1087 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1088 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1089 "cancel opcode[%s] mid %llu\n",
1090 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1091 (unsigned long long)found_id ));
1092 tevent_req_cancel(cur->subreq);
1095 return NT_STATUS_OK;
1098 /*************************************************************
1099 Ensure an incoming tid is a valid one for us to access.
1100 Change to the associated uid credentials and chdir to the
1101 valid tid directory.
1102 *************************************************************/
1104 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1106 const uint8_t *inhdr;
1107 const uint8_t *outhdr;
1108 int i = req->current_idx;
1111 struct smbd_smb2_tcon *tcon;
1112 bool chained_fixup = false;
1114 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1116 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1118 if (in_tid == (0xFFFFFFFF)) {
1121 * async request - fill in tid from
1122 * already setup out.vector[].iov_base.
1124 outhdr = (const uint8_t *)req->out.vector[i].iov_base;
1125 in_tid = IVAL(outhdr, SMB2_HDR_TID);
1128 * Chained request - fill in tid from
1129 * the previous request out.vector[].iov_base.
1131 outhdr = (const uint8_t *)req->out.vector[i-3].iov_base;
1132 in_tid = IVAL(outhdr, SMB2_HDR_TID);
1133 chained_fixup = true;
1137 /* lookup an existing session */
1138 p = idr_find(req->session->tcons.idtree, in_tid);
1140 return NT_STATUS_NETWORK_NAME_DELETED;
1142 tcon = talloc_get_type_abort(p, struct smbd_smb2_tcon);
1144 if (!change_to_user(tcon->compat_conn,req->session->vuid)) {
1145 return NT_STATUS_ACCESS_DENIED;
1148 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1149 if (!set_current_service(tcon->compat_conn, 0, true)) {
1150 return NT_STATUS_ACCESS_DENIED;
1155 if (chained_fixup) {
1156 /* Fix up our own outhdr. */
1157 outhdr = (const uint8_t *)req->out.vector[i].iov_base;
1158 SIVAL(discard_const_p(uint8_t, outhdr), SMB2_HDR_TID, in_tid);
1161 return NT_STATUS_OK;
1164 /*************************************************************
1165 Ensure an incoming session_id is a valid one for us to access.
1166 *************************************************************/
1168 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1170 const uint8_t *inhdr;
1171 const uint8_t *outhdr;
1172 int i = req->current_idx;
1173 uint64_t in_session_id;
1175 struct smbd_smb2_session *session;
1176 bool chained_fixup = false;
1178 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1180 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1182 if (in_session_id == (0xFFFFFFFFFFFFFFFFLL)) {
1185 * async request - fill in session_id from
1186 * already setup request out.vector[].iov_base.
1188 outhdr = (const uint8_t *)req->out.vector[i].iov_base;
1189 in_session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1192 * Chained request - fill in session_id from
1193 * the previous request out.vector[].iov_base.
1195 outhdr = (const uint8_t *)req->out.vector[i-3].iov_base;
1196 in_session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1197 chained_fixup = true;
1201 /* lookup an existing session */
1202 p = idr_find(req->sconn->smb2.sessions.idtree, in_session_id);
1204 return NT_STATUS_USER_SESSION_DELETED;
1206 session = talloc_get_type_abort(p, struct smbd_smb2_session);
1208 if (!NT_STATUS_IS_OK(session->status)) {
1209 return NT_STATUS_ACCESS_DENIED;
1212 set_current_user_info(session->session_info->unix_info->sanitized_username,
1213 session->session_info->unix_info->unix_name,
1214 session->session_info->info->domain_name);
1216 req->session = session;
1218 if (chained_fixup) {
1219 /* Fix up our own outhdr. */
1220 outhdr = (const uint8_t *)req->out.vector[i].iov_base;
1221 SBVAL(discard_const_p(uint8_t, outhdr), SMB2_HDR_SESSION_ID, in_session_id);
1223 return NT_STATUS_OK;
1226 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1228 const uint8_t *inhdr;
1229 int i = req->current_idx;
1234 NTSTATUS session_status;
1235 uint32_t allowed_flags;
1236 NTSTATUS return_value;
1238 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1240 /* TODO: verify more things */
1242 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1243 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1244 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1245 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1246 smb2_opcode_name(opcode),
1247 (unsigned long long)mid));
1249 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1250 SMB2_HDR_FLAG_SIGNED |
1252 if (opcode == SMB2_OP_CANCEL) {
1253 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1255 if ((flags & ~allowed_flags) != 0) {
1256 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1260 * Check if the client provided a valid session id,
1261 * if so smbd_smb2_request_check_session() calls
1262 * set_current_user_info().
1264 * As some command don't require a valid session id
1265 * we defer the check of the session_status
1267 session_status = smbd_smb2_request_check_session(req);
1269 req->do_signing = false;
1270 if (flags & SMB2_HDR_FLAG_SIGNED) {
1271 if (!NT_STATUS_IS_OK(session_status)) {
1272 return smbd_smb2_request_error(req, session_status);
1275 req->do_signing = true;
1276 status = smb2_signing_check_pdu(req->session->session_key,
1277 &req->in.vector[i], 3);
1278 if (!NT_STATUS_IS_OK(status)) {
1279 return smbd_smb2_request_error(req, status);
1281 } else if (req->session && req->session->do_signing) {
1282 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1285 if (flags & SMB2_HDR_FLAG_CHAINED) {
1287 * This check is mostly for giving the correct error code
1288 * for compounded requests.
1290 * TODO: we may need to move this after the session
1293 if (!NT_STATUS_IS_OK(req->next_status)) {
1294 return smbd_smb2_request_error(req, req->next_status);
1297 req->compat_chain_fsp = NULL;
1301 case SMB2_OP_NEGPROT:
1302 /* This call needs to be run as root */
1303 change_to_root_user();
1306 START_PROFILE(smb2_negprot);
1307 return_value = smbd_smb2_request_process_negprot(req);
1308 END_PROFILE(smb2_negprot);
1312 case SMB2_OP_SESSSETUP:
1313 /* This call needs to be run as root */
1314 change_to_root_user();
1317 START_PROFILE(smb2_sesssetup);
1318 return_value = smbd_smb2_request_process_sesssetup(req);
1319 END_PROFILE(smb2_sesssetup);
1323 case SMB2_OP_LOGOFF:
1324 if (!NT_STATUS_IS_OK(session_status)) {
1325 return_value = smbd_smb2_request_error(req, session_status);
1329 /* This call needs to be run as root */
1330 change_to_root_user();
1333 START_PROFILE(smb2_logoff);
1334 return_value = smbd_smb2_request_process_logoff(req);
1335 END_PROFILE(smb2_logoff);
1340 if (!NT_STATUS_IS_OK(session_status)) {
1341 return_value = smbd_smb2_request_error(req, session_status);
1346 * This call needs to be run as root.
1348 * smbd_smb2_request_process_tcon()
1349 * calls make_connection_snum(), which will call
1350 * change_to_user(), when needed.
1352 change_to_root_user();
1355 START_PROFILE(smb2_tcon);
1356 return_value = smbd_smb2_request_process_tcon(req);
1357 END_PROFILE(smb2_tcon);
1362 if (!NT_STATUS_IS_OK(session_status)) {
1363 return_value = smbd_smb2_request_error(req, session_status);
1367 * This call needs to be run as user.
1369 * smbd_smb2_request_check_tcon()
1370 * calls change_to_user() on success.
1372 status = smbd_smb2_request_check_tcon(req);
1373 if (!NT_STATUS_IS_OK(status)) {
1374 return_value = smbd_smb2_request_error(req, status);
1377 /* This call needs to be run as root */
1378 change_to_root_user();
1382 START_PROFILE(smb2_tdis);
1383 return_value = smbd_smb2_request_process_tdis(req);
1384 END_PROFILE(smb2_tdis);
1388 case SMB2_OP_CREATE:
1389 if (!NT_STATUS_IS_OK(session_status)) {
1390 return_value = smbd_smb2_request_error(req, session_status);
1394 * This call needs to be run as user.
1396 * smbd_smb2_request_check_tcon()
1397 * calls change_to_user() on success.
1399 status = smbd_smb2_request_check_tcon(req);
1400 if (!NT_STATUS_IS_OK(status)) {
1401 return_value = smbd_smb2_request_error(req, status);
1406 START_PROFILE(smb2_create);
1407 return_value = smbd_smb2_request_process_create(req);
1408 END_PROFILE(smb2_create);
1413 if (!NT_STATUS_IS_OK(session_status)) {
1414 return_value = smbd_smb2_request_error(req, session_status);
1418 * This call needs to be run as user.
1420 * smbd_smb2_request_check_tcon()
1421 * calls change_to_user() on success.
1423 status = smbd_smb2_request_check_tcon(req);
1424 if (!NT_STATUS_IS_OK(status)) {
1425 return_value = smbd_smb2_request_error(req, status);
1430 START_PROFILE(smb2_close);
1431 return_value = smbd_smb2_request_process_close(req);
1432 END_PROFILE(smb2_close);
1437 if (!NT_STATUS_IS_OK(session_status)) {
1438 return_value = smbd_smb2_request_error(req, session_status);
1442 * This call needs to be run as user.
1444 * smbd_smb2_request_check_tcon()
1445 * calls change_to_user() on success.
1447 status = smbd_smb2_request_check_tcon(req);
1448 if (!NT_STATUS_IS_OK(status)) {
1449 return_value = smbd_smb2_request_error(req, status);
1454 START_PROFILE(smb2_flush);
1455 return_value = smbd_smb2_request_process_flush(req);
1456 END_PROFILE(smb2_flush);
1461 if (!NT_STATUS_IS_OK(session_status)) {
1462 return_value = smbd_smb2_request_error(req, session_status);
1466 * This call needs to be run as user.
1468 * smbd_smb2_request_check_tcon()
1469 * calls change_to_user() on success.
1471 status = smbd_smb2_request_check_tcon(req);
1472 if (!NT_STATUS_IS_OK(status)) {
1473 return_value = smbd_smb2_request_error(req, status);
1478 START_PROFILE(smb2_read);
1479 return_value = smbd_smb2_request_process_read(req);
1480 END_PROFILE(smb2_read);
1485 if (!NT_STATUS_IS_OK(session_status)) {
1486 return_value = smbd_smb2_request_error(req, session_status);
1490 * This call needs to be run as user.
1492 * smbd_smb2_request_check_tcon()
1493 * calls change_to_user() on success.
1495 status = smbd_smb2_request_check_tcon(req);
1496 if (!NT_STATUS_IS_OK(status)) {
1497 return_value = smbd_smb2_request_error(req, status);
1502 START_PROFILE(smb2_write);
1503 return_value = smbd_smb2_request_process_write(req);
1504 END_PROFILE(smb2_write);
1509 if (!NT_STATUS_IS_OK(session_status)) {
1510 /* Too ugly to live ? JRA. */
1511 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1512 session_status = NT_STATUS_FILE_CLOSED;
1514 return_value = smbd_smb2_request_error(req, session_status);
1518 * This call needs to be run as user.
1520 * smbd_smb2_request_check_tcon()
1521 * calls change_to_user() on success.
1523 status = smbd_smb2_request_check_tcon(req);
1524 if (!NT_STATUS_IS_OK(status)) {
1525 /* Too ugly to live ? JRA. */
1526 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1527 status = NT_STATUS_FILE_CLOSED;
1529 return_value = smbd_smb2_request_error(req, status);
1534 START_PROFILE(smb2_lock);
1535 return_value = smbd_smb2_request_process_lock(req);
1536 END_PROFILE(smb2_lock);
1541 if (!NT_STATUS_IS_OK(session_status)) {
1542 return_value = smbd_smb2_request_error(req, session_status);
1546 * This call needs to be run as user.
1548 * smbd_smb2_request_check_tcon()
1549 * calls change_to_user() on success.
1551 status = smbd_smb2_request_check_tcon(req);
1552 if (!NT_STATUS_IS_OK(status)) {
1553 return_value = smbd_smb2_request_error(req, status);
1558 START_PROFILE(smb2_ioctl);
1559 return_value = smbd_smb2_request_process_ioctl(req);
1560 END_PROFILE(smb2_ioctl);
1564 case SMB2_OP_CANCEL:
1566 * This call needs to be run as root
1568 * That is what we also do in the SMB1 case.
1570 change_to_root_user();
1573 START_PROFILE(smb2_cancel);
1574 return_value = smbd_smb2_request_process_cancel(req);
1575 END_PROFILE(smb2_cancel);
1579 case SMB2_OP_KEEPALIVE:
1580 /* This call needs to be run as root */
1581 change_to_root_user();
1584 START_PROFILE(smb2_keepalive);
1585 return_value = smbd_smb2_request_process_keepalive(req);
1586 END_PROFILE(smb2_keepalive);
1591 if (!NT_STATUS_IS_OK(session_status)) {
1592 return_value = smbd_smb2_request_error(req, session_status);
1596 * This call needs to be run as user.
1598 * smbd_smb2_request_check_tcon()
1599 * calls change_to_user() on success.
1601 status = smbd_smb2_request_check_tcon(req);
1602 if (!NT_STATUS_IS_OK(status)) {
1603 return_value = smbd_smb2_request_error(req, status);
1608 START_PROFILE(smb2_find);
1609 return_value = smbd_smb2_request_process_find(req);
1610 END_PROFILE(smb2_find);
1614 case SMB2_OP_NOTIFY:
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 user.
1622 * smbd_smb2_request_check_tcon()
1623 * calls change_to_user() on success.
1625 status = smbd_smb2_request_check_tcon(req);
1626 if (!NT_STATUS_IS_OK(status)) {
1627 return_value = smbd_smb2_request_error(req, status);
1632 START_PROFILE(smb2_notify);
1633 return_value = smbd_smb2_request_process_notify(req);
1634 END_PROFILE(smb2_notify);
1638 case SMB2_OP_GETINFO:
1639 if (!NT_STATUS_IS_OK(session_status)) {
1640 return_value = smbd_smb2_request_error(req, session_status);
1644 * This call needs to be run as user.
1646 * smbd_smb2_request_check_tcon()
1647 * calls change_to_user() on success.
1649 status = smbd_smb2_request_check_tcon(req);
1650 if (!NT_STATUS_IS_OK(status)) {
1651 return_value = smbd_smb2_request_error(req, status);
1656 START_PROFILE(smb2_getinfo);
1657 return_value = smbd_smb2_request_process_getinfo(req);
1658 END_PROFILE(smb2_getinfo);
1662 case SMB2_OP_SETINFO:
1663 if (!NT_STATUS_IS_OK(session_status)) {
1664 return_value = smbd_smb2_request_error(req, session_status);
1668 * This call needs to be run as user.
1670 * smbd_smb2_request_check_tcon()
1671 * calls change_to_user() on success.
1673 status = smbd_smb2_request_check_tcon(req);
1674 if (!NT_STATUS_IS_OK(status)) {
1675 return_value = smbd_smb2_request_error(req, status);
1680 START_PROFILE(smb2_setinfo);
1681 return_value = smbd_smb2_request_process_setinfo(req);
1682 END_PROFILE(smb2_setinfo);
1687 if (!NT_STATUS_IS_OK(session_status)) {
1688 return_value = smbd_smb2_request_error(req, session_status);
1692 * This call needs to be run as user.
1694 * smbd_smb2_request_check_tcon()
1695 * calls change_to_user() on success.
1697 status = smbd_smb2_request_check_tcon(req);
1698 if (!NT_STATUS_IS_OK(status)) {
1699 return_value = smbd_smb2_request_error(req, status);
1704 START_PROFILE(smb2_break);
1705 return_value = smbd_smb2_request_process_break(req);
1706 END_PROFILE(smb2_break);
1711 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1714 return return_value;
1717 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1719 struct tevent_req *subreq;
1720 int i = req->current_idx;
1724 req->current_idx += 3;
1726 if (req->current_idx < req->out.vector_count) {
1728 * We must process the remaining compound
1729 * SMB2 requests before any new incoming SMB2
1730 * requests. This is because incoming SMB2
1731 * requests may include a cancel for a
1732 * compound request we haven't processed
1735 struct tevent_immediate *im = tevent_create_immediate(req);
1737 return NT_STATUS_NO_MEMORY;
1739 tevent_schedule_immediate(im,
1740 req->sconn->smb2.event_ctx,
1741 smbd_smb2_request_dispatch_immediate,
1743 return NT_STATUS_OK;
1746 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1748 /* Set credit for this operation (zero credits if this
1749 is a final reply for an async operation). */
1750 smb2_set_operation_credit(req->sconn,
1751 req->async ? NULL : &req->in.vector[i],
1752 &req->out.vector[i]);
1754 if (req->do_signing) {
1756 status = smb2_signing_sign_pdu(req->session->session_key,
1757 &req->out.vector[i], 3);
1758 if (!NT_STATUS_IS_OK(status)) {
1763 if (DEBUGLEVEL >= 10) {
1764 dbgtext("smbd_smb2_request_reply: sending...\n");
1765 print_req_vectors(req);
1768 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1769 if (req->out.vector_count == 4 &&
1770 req->out.vector[3].iov_base == NULL &&
1771 req->out.vector[3].iov_len != 0) {
1772 /* Dynamic part is NULL. Chop it off,
1773 We're going to send it via sendfile. */
1774 req->out.vector_count -= 1;
1777 subreq = tstream_writev_queue_send(req,
1778 req->sconn->smb2.event_ctx,
1779 req->sconn->smb2.stream,
1780 req->sconn->smb2.send_queue,
1782 req->out.vector_count);
1783 if (subreq == NULL) {
1784 return NT_STATUS_NO_MEMORY;
1786 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1788 * We're done with this request -
1789 * move it off the "being processed" queue.
1791 DLIST_REMOVE(req->sconn->smb2.requests, req);
1793 return NT_STATUS_OK;
1796 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1797 struct tevent_immediate *im,
1800 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1801 struct smbd_smb2_request);
1802 struct smbd_server_connection *sconn = req->sconn;
1807 if (DEBUGLEVEL >= 10) {
1808 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1809 req->current_idx, req->in.vector_count));
1810 print_req_vectors(req);
1813 status = smbd_smb2_request_dispatch(req);
1814 if (!NT_STATUS_IS_OK(status)) {
1815 smbd_server_connection_terminate(sconn, nt_errstr(status));
1820 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
1822 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1824 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1825 struct smbd_smb2_request);
1826 struct smbd_server_connection *sconn = req->sconn;
1831 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1832 TALLOC_FREE(subreq);
1835 status = map_nt_error_from_unix(sys_errno);
1836 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1837 nt_errstr(status)));
1838 smbd_server_connection_terminate(sconn, nt_errstr(status));
1842 status = smbd_smb2_request_next_incoming(sconn);
1843 if (!NT_STATUS_IS_OK(status)) {
1844 smbd_server_connection_terminate(sconn, nt_errstr(status));
1849 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1851 DATA_BLOB body, DATA_BLOB *dyn,
1852 const char *location)
1855 int i = req->current_idx;
1856 uint32_t next_command_ofs;
1858 DEBUG(10,("smbd_smb2_request_done_ex: "
1859 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1860 i, nt_errstr(status), (unsigned int)body.length,
1862 (unsigned int)(dyn ? dyn->length : 0),
1865 if (body.length < 2) {
1866 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1869 if ((body.length % 2) != 0) {
1870 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1873 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1875 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1876 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1878 req->out.vector[i+1].iov_base = (void *)body.data;
1879 req->out.vector[i+1].iov_len = body.length;
1882 req->out.vector[i+2].iov_base = (void *)dyn->data;
1883 req->out.vector[i+2].iov_len = dyn->length;
1885 req->out.vector[i+2].iov_base = NULL;
1886 req->out.vector[i+2].iov_len = 0;
1889 /* see if we need to recalculate the offset to the next response */
1890 if (next_command_ofs > 0) {
1891 next_command_ofs = SMB2_HDR_BODY;
1892 next_command_ofs += req->out.vector[i+1].iov_len;
1893 next_command_ofs += req->out.vector[i+2].iov_len;
1896 if ((next_command_ofs % 8) != 0) {
1897 size_t pad_size = 8 - (next_command_ofs % 8);
1898 if (req->out.vector[i+2].iov_len == 0) {
1900 * if the dyn buffer is empty
1901 * we can use it to add padding
1905 pad = talloc_zero_array(req->out.vector,
1908 return smbd_smb2_request_error(req,
1909 NT_STATUS_NO_MEMORY);
1912 req->out.vector[i+2].iov_base = (void *)pad;
1913 req->out.vector[i+2].iov_len = pad_size;
1916 * For now we copy the dynamic buffer
1917 * and add the padding to the new buffer
1924 old_size = req->out.vector[i+2].iov_len;
1925 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
1927 new_size = old_size + pad_size;
1928 new_dyn = talloc_zero_array(req->out.vector,
1930 if (new_dyn == NULL) {
1931 return smbd_smb2_request_error(req,
1932 NT_STATUS_NO_MEMORY);
1935 memcpy(new_dyn, old_dyn, old_size);
1936 memset(new_dyn + old_size, 0, pad_size);
1938 req->out.vector[i+2].iov_base = (void *)new_dyn;
1939 req->out.vector[i+2].iov_len = new_size;
1941 next_command_ofs += pad_size;
1944 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1946 return smbd_smb2_request_reply(req);
1949 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
1952 const char *location)
1955 int i = req->current_idx;
1956 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
1958 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1959 i, nt_errstr(status), info ? " +info" : "",
1962 body.data = outhdr + SMB2_HDR_BODY;
1964 SSVAL(body.data, 0, 9);
1967 SIVAL(body.data, 0x04, info->length);
1969 /* Allocated size of req->out.vector[i].iov_base
1970 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
1971 * 1 byte without having to do an alloc.
1973 info = talloc_zero_array(req->out.vector,
1977 return NT_STATUS_NO_MEMORY;
1979 info->data = ((uint8_t *)outhdr) +
1980 OUTVEC_ALLOC_SIZE - 1;
1982 SCVAL(info->data, 0, 0);
1986 * if a request fails, all other remaining
1987 * compounded requests should fail too
1989 req->next_status = NT_STATUS_INVALID_PARAMETER;
1991 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
1995 struct smbd_smb2_send_oplock_break_state {
1996 struct smbd_server_connection *sconn;
1997 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
1998 struct iovec vector;
2001 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2003 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2004 uint64_t file_id_persistent,
2005 uint64_t file_id_volatile,
2006 uint8_t oplock_level)
2008 struct smbd_smb2_send_oplock_break_state *state;
2009 struct tevent_req *subreq;
2013 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2014 if (state == NULL) {
2015 return NT_STATUS_NO_MEMORY;
2017 state->sconn = sconn;
2019 state->vector.iov_base = (void *)state->buf;
2020 state->vector.iov_len = sizeof(state->buf);
2022 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2023 hdr = state->buf + 4;
2024 body = hdr + SMB2_HDR_BODY;
2026 SIVAL(hdr, 0, SMB2_MAGIC);
2027 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2028 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2029 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2030 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2031 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2032 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2033 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2034 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2035 SIVAL(hdr, SMB2_HDR_PID, 0);
2036 SIVAL(hdr, SMB2_HDR_TID, 0);
2037 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2038 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2040 SSVAL(body, 0x00, 0x18);
2042 SCVAL(body, 0x02, oplock_level);
2043 SCVAL(body, 0x03, 0); /* reserved */
2044 SIVAL(body, 0x04, 0); /* reserved */
2045 SBVAL(body, 0x08, file_id_persistent);
2046 SBVAL(body, 0x10, file_id_volatile);
2048 subreq = tstream_writev_queue_send(state,
2049 sconn->smb2.event_ctx,
2051 sconn->smb2.send_queue,
2053 if (subreq == NULL) {
2054 return NT_STATUS_NO_MEMORY;
2056 tevent_req_set_callback(subreq,
2057 smbd_smb2_oplock_break_writev_done,
2060 return NT_STATUS_OK;
2063 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2065 struct smbd_smb2_send_oplock_break_state *state =
2066 tevent_req_callback_data(subreq,
2067 struct smbd_smb2_send_oplock_break_state);
2068 struct smbd_server_connection *sconn = state->sconn;
2072 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2073 TALLOC_FREE(subreq);
2075 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2076 smbd_server_connection_terminate(sconn, nt_errstr(status));
2083 struct smbd_smb2_request_read_state {
2085 bool asked_for_header;
2086 struct smbd_smb2_request *smb2_req;
2089 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2091 TALLOC_CTX *mem_ctx,
2092 struct iovec **_vector,
2094 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2096 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2097 struct tevent_context *ev,
2098 struct smbd_server_connection *sconn)
2100 struct tevent_req *req;
2101 struct smbd_smb2_request_read_state *state;
2102 struct tevent_req *subreq;
2104 req = tevent_req_create(mem_ctx, &state,
2105 struct smbd_smb2_request_read_state);
2110 state->asked_for_header = false;
2112 state->smb2_req = smbd_smb2_request_allocate(state);
2113 if (tevent_req_nomem(state->smb2_req, req)) {
2114 return tevent_req_post(req, ev);
2116 state->smb2_req->sconn = sconn;
2118 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2119 sconn->smb2.recv_queue,
2120 smbd_smb2_request_next_vector,
2122 if (tevent_req_nomem(subreq, req)) {
2123 return tevent_req_post(req, ev);
2125 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2130 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2132 TALLOC_CTX *mem_ctx,
2133 struct iovec **_vector,
2136 struct smbd_smb2_request_read_state *state =
2137 talloc_get_type_abort(private_data,
2138 struct smbd_smb2_request_read_state);
2139 struct smbd_smb2_request *req = state->smb2_req;
2140 struct iovec *vector;
2141 int idx = req->in.vector_count;
2143 uint8_t *buf = NULL;
2145 if (req->in.vector_count == 0) {
2147 * first we need to get the NBT header
2149 req->in.vector = talloc_array(req, struct iovec,
2150 req->in.vector_count + 1);
2151 if (req->in.vector == NULL) {
2154 req->in.vector_count += 1;
2156 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2157 req->in.vector[idx].iov_len = 4;
2159 vector = talloc_array(mem_ctx, struct iovec, 1);
2160 if (vector == NULL) {
2164 vector[0] = req->in.vector[idx];
2171 if (req->in.vector_count == 1) {
2173 * Now we analyze the NBT header
2175 state->missing = smb2_len(req->in.vector[0].iov_base);
2177 if (state->missing == 0) {
2178 /* if there're no remaining bytes, we're done */
2184 req->in.vector = talloc_realloc(req, req->in.vector,
2186 req->in.vector_count + 1);
2187 if (req->in.vector == NULL) {
2190 req->in.vector_count += 1;
2192 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2194 * it's a special NBT message,
2195 * so get all remaining bytes
2197 len = state->missing;
2198 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2200 * it's an invalid message, just read what we can get
2201 * and let the caller handle the error
2203 len = state->missing;
2206 * We assume it's a SMB2 request,
2207 * and we first get the header and the
2208 * first 2 bytes (the struct size) of the body
2210 len = SMB2_HDR_BODY + 2;
2212 state->asked_for_header = true;
2215 state->missing -= len;
2217 buf = talloc_array(req->in.vector, uint8_t, len);
2222 req->in.vector[idx].iov_base = (void *)buf;
2223 req->in.vector[idx].iov_len = len;
2225 vector = talloc_array(mem_ctx, struct iovec, 1);
2226 if (vector == NULL) {
2230 vector[0] = req->in.vector[idx];
2237 if (state->missing == 0) {
2238 /* if there're no remaining bytes, we're done */
2244 if (state->asked_for_header) {
2247 size_t next_command_ofs;
2252 bool invalid = false;
2254 state->asked_for_header = false;
2257 * We got the SMB2 header and the first 2 bytes
2258 * of the body. We fix the size to just the header
2259 * and manually copy the 2 first bytes to the body section
2261 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2262 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2264 /* allocate vectors for body and dynamic areas */
2265 req->in.vector = talloc_realloc(req, req->in.vector,
2267 req->in.vector_count + 2);
2268 if (req->in.vector == NULL) {
2271 req->in.vector_count += 2;
2273 full_size = state->missing + SMB2_HDR_BODY + 2;
2274 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2275 body_size = SVAL(hdr, SMB2_HDR_BODY);
2277 if (next_command_ofs != 0) {
2278 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2280 * this is invalid, just return a zero
2281 * body and let the caller deal with the error
2284 } else if (next_command_ofs > full_size) {
2286 * this is invalid, just return a zero
2287 * body and let the caller deal with the error
2291 full_size = next_command_ofs;
2296 if (body_size < 2) {
2298 * this is invalid, just return a zero
2299 * body and let the caller deal with the error
2305 * Mask out the lowest bit, the "dynamic" part
2310 if (body_size > (full_size - SMB2_HDR_BODY)) {
2312 * this is invalid, just return a zero
2313 * body and let the caller deal with the error
2320 /* the caller should check this */
2324 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2326 state->missing -= (body_size - 2) + dyn_size;
2328 body = talloc_array(req->in.vector, uint8_t, body_size);
2333 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2338 req->in.vector[idx].iov_base = (void *)body;
2339 req->in.vector[idx].iov_len = body_size;
2340 req->in.vector[idx+1].iov_base = (void *)dyn;
2341 req->in.vector[idx+1].iov_len = dyn_size;
2343 vector = talloc_array(mem_ctx, struct iovec, 2);
2344 if (vector == NULL) {
2349 * the first 2 bytes of the body were already fetched
2350 * together with the header
2352 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2353 vector[0].iov_base = body + 2;
2354 vector[0].iov_len = body_size - 2;
2356 vector[1] = req->in.vector[idx+1];
2364 * when we endup here, we're looking for a new SMB2 request
2365 * next. And we ask for its header and the first 2 bytes of
2366 * the body (like we did for the first SMB2 request).
2369 req->in.vector = talloc_realloc(req, req->in.vector,
2371 req->in.vector_count + 1);
2372 if (req->in.vector == NULL) {
2375 req->in.vector_count += 1;
2378 * We assume it's a SMB2 request,
2379 * and we first get the header and the
2380 * first 2 bytes (the struct size) of the body
2382 len = SMB2_HDR_BODY + 2;
2384 if (len > state->missing) {
2385 /* let the caller handle the error */
2386 len = state->missing;
2389 state->missing -= len;
2390 state->asked_for_header = true;
2392 buf = talloc_array(req->in.vector, uint8_t, len);
2397 req->in.vector[idx].iov_base = (void *)buf;
2398 req->in.vector[idx].iov_len = len;
2400 vector = talloc_array(mem_ctx, struct iovec, 1);
2401 if (vector == NULL) {
2405 vector[0] = req->in.vector[idx];
2412 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2414 struct tevent_req *req =
2415 tevent_req_callback_data(subreq,
2421 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2423 status = map_nt_error_from_unix(sys_errno);
2424 tevent_req_nterror(req, status);
2428 tevent_req_done(req);
2431 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2432 TALLOC_CTX *mem_ctx,
2433 struct smbd_smb2_request **_smb2_req)
2435 struct smbd_smb2_request_read_state *state =
2436 tevent_req_data(req,
2437 struct smbd_smb2_request_read_state);
2440 if (tevent_req_is_nterror(req, &status)) {
2441 tevent_req_received(req);
2445 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2446 *_smb2_req = state->smb2_req;
2447 tevent_req_received(req);
2448 return NT_STATUS_OK;
2451 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2453 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2455 size_t max_send_queue_len;
2456 size_t cur_send_queue_len;
2457 struct tevent_req *subreq;
2459 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2461 * if there is already a smbd_smb2_request_read
2462 * pending, we are done.
2464 return NT_STATUS_OK;
2467 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2468 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2470 if (cur_send_queue_len > max_send_queue_len) {
2472 * if we have a lot of requests to send,
2473 * we wait until they are on the wire until we
2474 * ask for the next request.
2476 return NT_STATUS_OK;
2479 /* ask for the next request */
2480 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2481 if (subreq == NULL) {
2482 return NT_STATUS_NO_MEMORY;
2484 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2486 return NT_STATUS_OK;
2489 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2490 const uint8_t *inbuf, size_t size)
2493 struct smbd_smb2_request *req = NULL;
2495 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2496 (unsigned int)size));
2498 status = smbd_initialize_smb2(sconn);
2499 if (!NT_STATUS_IS_OK(status)) {
2500 smbd_server_connection_terminate(sconn, nt_errstr(status));
2504 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2505 if (!NT_STATUS_IS_OK(status)) {
2506 smbd_server_connection_terminate(sconn, nt_errstr(status));
2510 status = smbd_smb2_request_setup_out(req);
2511 if (!NT_STATUS_IS_OK(status)) {
2512 smbd_server_connection_terminate(sconn, nt_errstr(status));
2516 status = smbd_smb2_request_dispatch(req);
2517 if (!NT_STATUS_IS_OK(status)) {
2518 smbd_server_connection_terminate(sconn, nt_errstr(status));
2522 status = smbd_smb2_request_next_incoming(sconn);
2523 if (!NT_STATUS_IS_OK(status)) {
2524 smbd_server_connection_terminate(sconn, nt_errstr(status));
2528 sconn->num_requests++;
2531 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2533 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2534 struct smbd_server_connection);
2536 struct smbd_smb2_request *req = NULL;
2538 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2539 TALLOC_FREE(subreq);
2540 if (!NT_STATUS_IS_OK(status)) {
2541 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2542 nt_errstr(status)));
2543 smbd_server_connection_terminate(sconn, nt_errstr(status));
2547 if (req->in.nbt_hdr[0] != 0x00) {
2548 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2549 req->in.nbt_hdr[0]));
2554 req->current_idx = 1;
2556 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2557 req->current_idx, req->in.vector_count));
2559 status = smbd_smb2_request_validate(req);
2560 if (!NT_STATUS_IS_OK(status)) {
2561 smbd_server_connection_terminate(sconn, nt_errstr(status));
2565 status = smbd_smb2_request_setup_out(req);
2566 if (!NT_STATUS_IS_OK(status)) {
2567 smbd_server_connection_terminate(sconn, nt_errstr(status));
2571 status = smbd_smb2_request_dispatch(req);
2572 if (!NT_STATUS_IS_OK(status)) {
2573 smbd_server_connection_terminate(sconn, nt_errstr(status));
2578 status = smbd_smb2_request_next_incoming(sconn);
2579 if (!NT_STATUS_IS_OK(status)) {
2580 smbd_server_connection_terminate(sconn, nt_errstr(status));
2584 sconn->num_requests++;
2586 /* The timeout_processing function isn't run nearly
2587 often enough to implement 'max log size' without
2588 overrunning the size of the file by many megabytes.
2589 This is especially true if we are running at debug
2590 level 10. Checking every 50 SMB2s is a nice
2591 tradeoff of performance vs log file size overrun. */
2593 if ((sconn->num_requests % 50) == 0 &&
2594 need_to_check_log_size()) {
2595 change_to_root_user();