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"
30 #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9)
32 static const char *smb2_names[] = {
54 const char *smb2_opcode_name(uint16_t opcode)
57 return "Bad SMB2 opcode";
59 return smb2_names[opcode];
62 static void print_req_vectors(struct smbd_smb2_request *req)
66 for (i = 0; i < req->in.vector_count; i++) {
67 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
69 (unsigned int)req->in.vector[i].iov_len);
71 for (i = 0; i < req->out.vector_count; i++) {
72 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
74 (unsigned int)req->out.vector[i].iov_len);
78 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
80 if (size < (4 + SMB2_HDR_BODY)) {
84 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
91 static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
96 TALLOC_FREE(sconn->smb1.fde);
98 sconn->smb2.event_ctx = smbd_event_context();
100 sconn->smb2.recv_queue = tevent_queue_create(sconn, "smb2 recv queue");
101 if (sconn->smb2.recv_queue == NULL) {
102 return NT_STATUS_NO_MEMORY;
105 sconn->smb2.send_queue = tevent_queue_create(sconn, "smb2 send queue");
106 if (sconn->smb2.send_queue == NULL) {
107 return NT_STATUS_NO_MEMORY;
110 sconn->smb2.sessions.idtree = idr_init(sconn);
111 if (sconn->smb2.sessions.idtree == NULL) {
112 return NT_STATUS_NO_MEMORY;
114 sconn->smb2.sessions.limit = 0x0000FFFE;
115 sconn->smb2.sessions.list = NULL;
116 sconn->smb2.seqnum_low = 0;
117 sconn->smb2.credits_granted = 0;
118 sconn->smb2.max_credits = lp_smb2_max_credits();
119 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
120 DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR*sconn->smb2.max_credits);
121 if (sconn->smb2.credits_bitmap == NULL) {
122 return NT_STATUS_NO_MEMORY;
125 ret = tstream_bsd_existing_socket(sconn, sconn->sock,
126 &sconn->smb2.stream);
128 status = map_nt_error_from_unix(errno);
132 /* Ensure child is set to non-blocking mode */
133 set_blocking(sconn->sock, false);
137 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
138 #define _smb2_setlen(_buf,len) do { \
139 uint8_t *buf = (uint8_t *)_buf; \
141 buf[1] = ((len)&0xFF0000)>>16; \
142 buf[2] = ((len)&0xFF00)>>8; \
143 buf[3] = (len)&0xFF; \
146 static void smb2_setup_nbt_length(struct iovec *vector, int count)
151 for (i=1; i < count; i++) {
152 len += vector[i].iov_len;
155 _smb2_setlen(vector[0].iov_base, len);
158 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request **req)
161 (*req)->parent = NULL;
162 (*req)->mem_pool = NULL;
168 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
172 talloc_free(req->mem_pool);
178 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
180 TALLOC_CTX *mem_pool;
181 struct smbd_smb2_request **parent;
182 struct smbd_smb2_request *req;
185 /* Enable this to find subtle valgrind errors. */
186 mem_pool = talloc_init("smbd_smb2_request_allocate");
188 mem_pool = talloc_pool(mem_ctx, 8192);
190 if (mem_pool == NULL) {
194 parent = talloc(mem_pool, struct smbd_smb2_request *);
195 if (parent == NULL) {
196 talloc_free(mem_pool);
200 req = talloc_zero(parent, struct smbd_smb2_request);
202 talloc_free(mem_pool);
206 req->mem_pool = mem_pool;
207 req->parent = parent;
209 req->last_session_id = UINT64_MAX;
210 req->last_tid = UINT32_MAX;
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 = (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 = (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 = (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 = (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 if (sconn->smb2.credits_granted == 0) {
326 DEBUG(0,("smb2_validate_message_id: client used more "
327 "credits than granted message_id (%llu)\n",
328 (unsigned long long)message_id));
332 /* client just used a credit. */
333 sconn->smb2.credits_granted -= 1;
335 /* Mark the message_id as seen in the bitmap. */
336 bitmap_offset = (unsigned int)(message_id %
337 (uint64_t)(sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR));
338 if (bitmap_query(credits_bm, bitmap_offset)) {
339 DEBUG(0,("smb2_validate_message_id: duplicate message_id "
340 "%llu (bm offset %u)\n",
341 (unsigned long long)message_id,
345 bitmap_set(credits_bm, bitmap_offset);
347 if (message_id == sconn->smb2.seqnum_low + 1) {
348 /* Move the window forward by all the message_id's
350 while (bitmap_query(credits_bm, bitmap_offset)) {
351 DEBUG(10,("smb2_validate_message_id: clearing "
352 "id %llu (position %u) from bitmap\n",
353 (unsigned long long)(sconn->smb2.seqnum_low + 1),
355 bitmap_clear(credits_bm, bitmap_offset);
356 sconn->smb2.seqnum_low += 1;
357 bitmap_offset = (bitmap_offset + 1) %
358 (sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR);
365 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
370 count = req->in.vector_count;
373 /* It's not a SMB2 request */
374 return NT_STATUS_INVALID_PARAMETER;
377 for (idx=1; idx < count; idx += 3) {
378 const uint8_t *inhdr = NULL;
381 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
382 return NT_STATUS_INVALID_PARAMETER;
385 if (req->in.vector[idx+1].iov_len < 2) {
386 return NT_STATUS_INVALID_PARAMETER;
389 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
391 /* Check the SMB2 header */
392 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
393 return NT_STATUS_INVALID_PARAMETER;
396 if (!smb2_validate_message_id(req->sconn, inhdr)) {
397 return NT_STATUS_INVALID_PARAMETER;
400 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
403 * the 1st request should never have the
404 * SMB2_HDR_FLAG_CHAINED flag set
406 if (flags & SMB2_HDR_FLAG_CHAINED) {
407 req->next_status = NT_STATUS_INVALID_PARAMETER;
410 } else if (idx == 4) {
412 * the 2nd request triggers related vs. unrelated
413 * compounded requests
415 if (flags & SMB2_HDR_FLAG_CHAINED) {
416 req->compound_related = true;
418 } else if (idx > 4) {
421 * It seems the this tests are wrong
422 * see the SMB2-COMPOUND test
426 * all other requests should match the 2nd one
428 if (flags & SMB2_HDR_FLAG_CHAINED) {
429 if (!req->compound_related) {
431 NT_STATUS_INVALID_PARAMETER;
435 if (req->compound_related) {
437 NT_STATUS_INVALID_PARAMETER;
448 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
449 const struct iovec *in_vector,
450 struct iovec *out_vector)
452 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
453 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
454 uint16_t credits_requested;
456 uint16_t credits_granted = 0;
458 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
459 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
461 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
463 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
465 * In case we already send an async interim
466 * response, we should not grant
467 * credits on the final response.
469 credits_requested = 0;
472 if (credits_requested) {
473 uint16_t modified_credits_requested;
477 * Split up max_credits into 1/16ths, and then scale
478 * the requested credits by how many 16ths have been
479 * currently granted. Less than 1/16th == grant all
480 * requested (100%), scale down as more have been
481 * granted. Never ask for less than 1 as the client
482 * asked for at least 1. JRA.
485 multiplier = 16 - (((sconn->smb2.credits_granted * 16) / sconn->smb2.max_credits) % 16);
487 modified_credits_requested = (multiplier * credits_requested) / 16;
488 if (modified_credits_requested == 0) {
489 modified_credits_requested = 1;
492 /* Remember what we gave out. */
493 credits_granted = MIN(modified_credits_requested,
494 (sconn->smb2.max_credits - sconn->smb2.credits_granted));
497 if (credits_granted == 0 && sconn->smb2.credits_granted == 0) {
498 /* First negprot packet, or ensure the client credits can
499 never drop to zero. */
503 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
504 sconn->smb2.credits_granted += credits_granted;
506 DEBUG(10,("smb2_set_operation_credit: requested %u, "
507 "granted %u, total granted %u\n",
508 (unsigned int)credits_requested,
509 (unsigned int)credits_granted,
510 (unsigned int)sconn->smb2.credits_granted ));
513 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
514 struct smbd_smb2_request *outreq)
518 count = outreq->out.vector_count;
520 for (idx=1; idx < count; idx += 3) {
521 smb2_set_operation_credit(outreq->sconn,
522 &inreq->in.vector[idx],
523 &outreq->out.vector[idx]);
527 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
529 struct iovec *vector;
533 count = req->in.vector_count;
534 vector = talloc_zero_array(req, struct iovec, count);
535 if (vector == NULL) {
536 return NT_STATUS_NO_MEMORY;
539 vector[0].iov_base = req->out.nbt_hdr;
540 vector[0].iov_len = 4;
541 SIVAL(req->out.nbt_hdr, 0, 0);
543 for (idx=1; idx < count; idx += 3) {
544 const uint8_t *inhdr = NULL;
546 uint8_t *outhdr = NULL;
547 uint8_t *outbody = NULL;
548 uint32_t next_command_ofs = 0;
549 struct iovec *current = &vector[idx];
551 if ((idx + 3) < count) {
552 /* we have a next command -
553 * setup for the error case. */
554 next_command_ofs = SMB2_HDR_BODY + 9;
557 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
558 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
560 outhdr = talloc_zero_array(vector, uint8_t,
562 if (outhdr == NULL) {
563 return NT_STATUS_NO_MEMORY;
566 outbody = outhdr + SMB2_HDR_BODY;
568 current[0].iov_base = (void *)outhdr;
569 current[0].iov_len = SMB2_HDR_BODY;
571 current[1].iov_base = (void *)outbody;
572 current[1].iov_len = 8;
574 current[2].iov_base = NULL;
575 current[2].iov_len = 0;
577 /* setup the SMB2 header */
578 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
579 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
580 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
581 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
582 SIVAL(outhdr, SMB2_HDR_STATUS,
583 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
584 SSVAL(outhdr, SMB2_HDR_OPCODE,
585 SVAL(inhdr, SMB2_HDR_OPCODE));
586 SIVAL(outhdr, SMB2_HDR_FLAGS,
587 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
588 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
589 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
590 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
591 SIVAL(outhdr, SMB2_HDR_PID,
592 IVAL(inhdr, SMB2_HDR_PID));
593 SIVAL(outhdr, SMB2_HDR_TID,
594 IVAL(inhdr, SMB2_HDR_TID));
595 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
596 BVAL(inhdr, SMB2_HDR_SESSION_ID));
597 memcpy(outhdr + SMB2_HDR_SIGNATURE,
598 inhdr + SMB2_HDR_SIGNATURE, 16);
600 /* setup error body header */
601 SSVAL(outbody, 0x00, 0x08 + 1);
602 SSVAL(outbody, 0x02, 0);
603 SIVAL(outbody, 0x04, 0);
606 req->out.vector = vector;
607 req->out.vector_count = count;
609 /* setup the length of the NBT packet */
610 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
612 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
617 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
619 const char *location)
621 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
623 exit_server_cleanly(reason);
626 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
627 struct iovec *outvec,
628 const struct iovec *srcvec)
630 /* vec[0] is always boilerplate and must
631 * be allocated with size OUTVEC_ALLOC_SIZE. */
633 outvec[0].iov_base = talloc_memdup(ctx,
636 if (!outvec[0].iov_base) {
639 outvec[0].iov_len = SMB2_HDR_BODY;
642 * If this is a "standard" vec[1] of length 8,
643 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
644 * then duplicate this. Else use talloc_memdup().
647 if (srcvec[1].iov_len == 8 &&
648 srcvec[1].iov_base ==
649 ((uint8_t *)srcvec[0].iov_base) +
651 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
653 outvec[1].iov_len = 8;
655 outvec[1].iov_base = talloc_memdup(ctx,
658 if (!outvec[1].iov_base) {
661 outvec[1].iov_len = srcvec[1].iov_len;
665 * If this is a "standard" vec[2] of length 1,
666 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
667 * then duplicate this. Else use talloc_memdup().
670 if (srcvec[2].iov_base &&
672 if (srcvec[2].iov_base ==
673 ((uint8_t *)srcvec[0].iov_base) +
674 (OUTVEC_ALLOC_SIZE - 1) &&
675 srcvec[2].iov_len == 1) {
676 /* Common SMB2 error packet case. */
677 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
678 (OUTVEC_ALLOC_SIZE - 1);
680 outvec[2].iov_base = talloc_memdup(ctx,
683 if (!outvec[2].iov_base) {
687 outvec[2].iov_len = srcvec[2].iov_len;
689 outvec[2].iov_base = NULL;
690 outvec[2].iov_len = 0;
695 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
697 struct smbd_smb2_request *newreq = NULL;
698 struct iovec *outvec = NULL;
699 int count = req->out.vector_count;
702 newreq = smbd_smb2_request_allocate(req->sconn);
707 newreq->sconn = req->sconn;
708 newreq->session = req->session;
709 newreq->do_signing = req->do_signing;
710 newreq->current_idx = req->current_idx;
711 newreq->async = false;
712 newreq->cancelled = false;
713 /* Note we are leaving:
717 uninitialized as NULL here as
718 they're not used in the interim
719 response code. JRA. */
721 outvec = talloc_zero_array(newreq, struct iovec, count);
726 newreq->out.vector = outvec;
727 newreq->out.vector_count = count;
729 /* Setup the outvec's identically to req. */
730 outvec[0].iov_base = newreq->out.nbt_hdr;
731 outvec[0].iov_len = 4;
732 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
734 /* Setup the vectors identically to the ones in req. */
735 for (i = 1; i < count; i += 3) {
736 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
747 smb2_setup_nbt_length(newreq->out.vector,
748 newreq->out.vector_count);
753 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
755 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
758 uint8_t *outhdr = NULL;
759 struct smbd_smb2_request *nreq = NULL;
761 /* Create a new smb2 request we'll use
762 for the interim return. */
763 nreq = dup_smb2_req(req);
765 return NT_STATUS_NO_MEMORY;
768 /* Lose the last 3 out vectors. They're the
769 ones we'll be using for the async reply. */
770 nreq->out.vector_count -= 3;
772 smb2_setup_nbt_length(nreq->out.vector,
773 nreq->out.vector_count);
775 /* Step back to the previous reply. */
776 i = nreq->current_idx - 3;
777 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
778 /* And end the chain. */
779 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
781 /* Calculate outgoing credits */
782 smb2_calculate_credits(req, nreq);
784 /* Re-sign if needed. */
785 if (nreq->do_signing) {
787 status = smb2_signing_sign_pdu(nreq->session->session_key,
788 &nreq->out.vector[i], 3);
789 if (!NT_STATUS_IS_OK(status)) {
793 if (DEBUGLEVEL >= 10) {
794 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
795 (unsigned int)nreq->current_idx );
796 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
797 (unsigned int)nreq->out.vector_count );
798 print_req_vectors(nreq);
800 nreq->subreq = tstream_writev_queue_send(nreq,
801 nreq->sconn->smb2.event_ctx,
802 nreq->sconn->smb2.stream,
803 nreq->sconn->smb2.send_queue,
805 nreq->out.vector_count);
807 if (nreq->subreq == NULL) {
808 return NT_STATUS_NO_MEMORY;
811 tevent_req_set_callback(nreq->subreq,
812 smbd_smb2_request_writev_done,
818 struct smbd_smb2_request_pending_state {
819 struct smbd_server_connection *sconn;
820 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
821 struct iovec vector[3];
824 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
826 struct smbd_smb2_request_pending_state *state =
827 tevent_req_callback_data(subreq,
828 struct smbd_smb2_request_pending_state);
829 struct smbd_server_connection *sconn = state->sconn;
833 ret = tstream_writev_queue_recv(subreq, &sys_errno);
836 NTSTATUS status = map_nt_error_from_unix(sys_errno);
837 smbd_server_connection_terminate(sconn, nt_errstr(status));
844 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
845 struct tevent_req *subreq)
848 struct smbd_smb2_request_pending_state *state = NULL;
849 int i = req->current_idx;
850 uint8_t *reqhdr = NULL;
852 uint8_t *body = NULL;
854 uint64_t message_id = 0;
855 uint64_t async_id = 0;
856 struct iovec *outvec = NULL;
858 if (!tevent_req_is_in_progress(subreq)) {
862 req->subreq = subreq;
866 /* We're already async. */
870 if (req->in.vector_count > i + 3) {
872 * We're trying to go async in a compound
873 * request chain. This is not allowed.
874 * Cancel the outstanding request.
876 tevent_req_cancel(req->subreq);
877 return smbd_smb2_request_error(req,
878 NT_STATUS_INSUFFICIENT_RESOURCES);
881 if (DEBUGLEVEL >= 10) {
882 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
883 (unsigned int)req->current_idx );
884 print_req_vectors(req);
887 if (req->out.vector_count > 4) {
888 /* This is a compound reply. We
889 * must do an interim response
890 * followed by the async response
893 status = smb2_send_async_interim_response(req);
894 if (!NT_STATUS_IS_OK(status)) {
899 * We're splitting off the last SMB2
900 * request in a compound set, and the
901 * smb2_send_async_interim_response()
902 * call above just sent all the replies
903 * for the previous SMB2 requests in
904 * this compound set. So we're no longer
905 * in the "compound_related_in_progress"
906 * state, and this is no longer a compound
909 req->compound_related = false;
910 req->sconn->smb2.compound_related_in_progress = false;
913 /* Don't return an intermediate packet on a pipe read/write. */
914 if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
918 reqhdr = (uint8_t *)req->out.vector[i].iov_base;
919 flags = (IVAL(reqhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
920 message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
921 async_id = message_id; /* keep it simple for now... */
924 * What we send is identical to a smbd_smb2_request_error
925 * packet with an error status of STATUS_PENDING. Make use
926 * of this fact sometime when refactoring. JRA.
929 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
931 return NT_STATUS_NO_MEMORY;
933 state->sconn = req->sconn;
935 state->vector[0].iov_base = (void *)state->buf;
936 state->vector[0].iov_len = 4;
938 state->vector[1].iov_base = state->buf + 4;
939 state->vector[1].iov_len = SMB2_HDR_BODY;
941 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
942 state->vector[2].iov_len = 9;
944 smb2_setup_nbt_length(state->vector, 3);
946 hdr = (uint8_t *)state->vector[1].iov_base;
947 body = (uint8_t *)state->vector[2].iov_base;
949 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
950 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
951 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
952 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
953 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(reqhdr, SMB2_HDR_OPCODE));
955 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
956 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
957 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
958 SBVAL(hdr, SMB2_HDR_PID, async_id);
959 SBVAL(hdr, SMB2_HDR_SESSION_ID,
960 BVAL(reqhdr, SMB2_HDR_SESSION_ID));
961 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
963 SSVAL(body, 0x00, 0x08 + 1);
965 SCVAL(body, 0x02, 0);
966 SCVAL(body, 0x03, 0);
967 SIVAL(body, 0x04, 0);
968 /* Match W2K8R2... */
969 SCVAL(body, 0x08, 0x21);
971 /* Ensure we correctly go through crediting. Grant
972 the credits now, and zero credits on the final
974 smb2_set_operation_credit(req->sconn,
978 if (req->do_signing) {
979 status = smb2_signing_sign_pdu(req->session->session_key,
980 &state->vector[1], 2);
981 if (!NT_STATUS_IS_OK(status)) {
986 subreq = tstream_writev_queue_send(state,
987 req->sconn->smb2.event_ctx,
988 req->sconn->smb2.stream,
989 req->sconn->smb2.send_queue,
993 if (subreq == NULL) {
994 return NT_STATUS_NO_MEMORY;
997 tevent_req_set_callback(subreq,
998 smbd_smb2_request_pending_writev_done,
1001 /* Note we're going async with this request. */
1007 * Now manipulate req so that the outstanding async request
1008 * is the only one left in the struct smbd_smb2_request.
1011 if (req->current_idx == 1) {
1012 /* There was only one. */
1016 /* Re-arrange the in.vectors. */
1017 req->in.vector[1] = req->in.vector[i];
1018 req->in.vector[2] = req->in.vector[i+1];
1019 req->in.vector[3] = req->in.vector[i+2];
1020 req->in.vector_count = 4;
1021 /* Reset the new in size. */
1022 smb2_setup_nbt_length(req->in.vector, 4);
1024 /* Now recreate the out.vectors. */
1025 outvec = talloc_zero_array(req, struct iovec, 4);
1027 return NT_STATUS_NO_MEMORY;
1030 /* 0 is always boilerplate and must
1031 * be of size 4 for the length field. */
1033 outvec[0].iov_base = req->out.nbt_hdr;
1034 outvec[0].iov_len = 4;
1035 SIVAL(req->out.nbt_hdr, 0, 0);
1037 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
1038 return NT_STATUS_NO_MEMORY;
1041 TALLOC_FREE(req->out.vector);
1043 req->out.vector = outvec;
1045 req->current_idx = 1;
1046 req->out.vector_count = 4;
1050 smb2_setup_nbt_length(req->out.vector,
1051 req->out.vector_count);
1054 /* Ensure our final reply matches the interim one. */
1055 reqhdr = (uint8_t *)req->out.vector[1].iov_base;
1056 SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1057 SBVAL(reqhdr, SMB2_HDR_PID, async_id);
1060 const uint8_t *inhdr =
1061 (const uint8_t *)req->in.vector[1].iov_base;
1062 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1064 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1065 (unsigned long long)async_id ));
1069 return NT_STATUS_OK;
1072 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1074 struct smbd_server_connection *sconn = req->sconn;
1075 struct smbd_smb2_request *cur;
1076 const uint8_t *inhdr;
1077 int i = req->current_idx;
1079 uint64_t search_message_id;
1080 uint64_t search_async_id;
1083 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1085 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1086 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1087 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1090 * we don't need the request anymore
1091 * cancel requests never have a response
1093 DLIST_REMOVE(req->sconn->smb2.requests, req);
1096 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1097 const uint8_t *outhdr;
1098 uint64_t message_id;
1101 i = cur->current_idx;
1103 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1105 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1106 async_id = BVAL(outhdr, SMB2_HDR_PID);
1108 if (flags & SMB2_HDR_FLAG_ASYNC) {
1109 if (search_async_id == async_id) {
1110 found_id = async_id;
1114 if (search_message_id == message_id) {
1115 found_id = message_id;
1121 if (cur && cur->subreq) {
1122 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1123 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1124 "cancel opcode[%s] mid %llu\n",
1125 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1126 (unsigned long long)found_id ));
1127 tevent_req_cancel(cur->subreq);
1130 return NT_STATUS_OK;
1133 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1134 size_t expected_body_size)
1136 const uint8_t *inhdr;
1138 const uint8_t *inbody;
1139 int i = req->current_idx;
1141 size_t min_dyn_size = expected_body_size & 0x00000001;
1144 * The following should be checked already.
1146 if ((i+2) > req->in.vector_count) {
1147 return NT_STATUS_INTERNAL_ERROR;
1149 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1150 return NT_STATUS_INTERNAL_ERROR;
1152 if (req->in.vector[i+1].iov_len < 2) {
1153 return NT_STATUS_INTERNAL_ERROR;
1156 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1157 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1161 case SMB2_OP_GETINFO:
1167 * Now check the expected body size,
1168 * where the last byte might be in the
1169 * dynnamic section..
1171 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1172 return NT_STATUS_INVALID_PARAMETER;
1174 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1175 return NT_STATUS_INVALID_PARAMETER;
1178 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1180 body_size = SVAL(inbody, 0x00);
1181 if (body_size != expected_body_size) {
1182 return NT_STATUS_INVALID_PARAMETER;
1185 return NT_STATUS_OK;
1188 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1190 const uint8_t *inhdr;
1191 int i = req->current_idx;
1196 NTSTATUS session_status;
1197 uint32_t allowed_flags;
1198 NTSTATUS return_value;
1200 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1202 /* TODO: verify more things */
1204 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1205 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1206 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1207 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1208 smb2_opcode_name(opcode),
1209 (unsigned long long)mid));
1211 if (get_Protocol() >= PROTOCOL_SMB2) {
1213 * once the protocol is negotiated
1214 * SMB2_OP_NEGPROT is not allowed anymore
1216 if (opcode == SMB2_OP_NEGPROT) {
1217 /* drop the connection */
1218 return NT_STATUS_INVALID_PARAMETER;
1222 * if the protocol is not negotiated yet
1223 * only SMB2_OP_NEGPROT is allowed.
1225 if (opcode != SMB2_OP_NEGPROT) {
1226 /* drop the connection */
1227 return NT_STATUS_INVALID_PARAMETER;
1231 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1232 SMB2_HDR_FLAG_SIGNED |
1234 if (opcode == SMB2_OP_CANCEL) {
1235 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1237 if ((flags & ~allowed_flags) != 0) {
1238 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1242 * Check if the client provided a valid session id,
1243 * if so smbd_smb2_request_check_session() calls
1244 * set_current_user_info().
1246 * As some command don't require a valid session id
1247 * we defer the check of the session_status
1249 session_status = smbd_smb2_request_check_session(req);
1251 req->do_signing = false;
1252 if (flags & SMB2_HDR_FLAG_SIGNED) {
1253 if (!NT_STATUS_IS_OK(session_status)) {
1254 return smbd_smb2_request_error(req, session_status);
1257 req->do_signing = true;
1258 status = smb2_signing_check_pdu(req->session->session_key,
1259 &req->in.vector[i], 3);
1260 if (!NT_STATUS_IS_OK(status)) {
1261 return smbd_smb2_request_error(req, status);
1263 } else if (opcode == SMB2_OP_CANCEL) {
1264 /* Cancel requests are allowed to skip the signing */
1265 } else if (req->session && req->session->do_signing) {
1266 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1269 if (flags & SMB2_HDR_FLAG_CHAINED) {
1271 * This check is mostly for giving the correct error code
1272 * for compounded requests.
1274 * TODO: we may need to move this after the session
1277 if (!NT_STATUS_IS_OK(req->next_status)) {
1278 return smbd_smb2_request_error(req, req->next_status);
1281 req->compat_chain_fsp = NULL;
1284 if (req->compound_related) {
1285 req->sconn->smb2.compound_related_in_progress = true;
1289 case SMB2_OP_NEGPROT:
1290 /* This call needs to be run as root */
1291 change_to_root_user();
1294 START_PROFILE(smb2_negprot);
1295 return_value = smbd_smb2_request_process_negprot(req);
1296 END_PROFILE(smb2_negprot);
1300 case SMB2_OP_SESSSETUP:
1301 /* This call needs to be run as root */
1302 change_to_root_user();
1305 START_PROFILE(smb2_sesssetup);
1306 return_value = smbd_smb2_request_process_sesssetup(req);
1307 END_PROFILE(smb2_sesssetup);
1311 case SMB2_OP_LOGOFF:
1312 if (!NT_STATUS_IS_OK(session_status)) {
1313 return_value = smbd_smb2_request_error(req, session_status);
1317 /* This call needs to be run as root */
1318 change_to_root_user();
1321 START_PROFILE(smb2_logoff);
1322 return_value = smbd_smb2_request_process_logoff(req);
1323 END_PROFILE(smb2_logoff);
1328 if (!NT_STATUS_IS_OK(session_status)) {
1329 return_value = smbd_smb2_request_error(req, session_status);
1334 * This call needs to be run as root.
1336 * smbd_smb2_request_process_tcon()
1337 * calls make_connection_snum(), which will call
1338 * change_to_user(), when needed.
1340 change_to_root_user();
1343 START_PROFILE(smb2_tcon);
1344 return_value = smbd_smb2_request_process_tcon(req);
1345 END_PROFILE(smb2_tcon);
1350 if (!NT_STATUS_IS_OK(session_status)) {
1351 return_value = smbd_smb2_request_error(req, session_status);
1355 * This call needs to be run as user.
1357 * smbd_smb2_request_check_tcon()
1358 * calls change_to_user() on success.
1360 status = smbd_smb2_request_check_tcon(req);
1361 if (!NT_STATUS_IS_OK(status)) {
1362 return_value = smbd_smb2_request_error(req, status);
1365 /* This call needs to be run as root */
1366 change_to_root_user();
1370 START_PROFILE(smb2_tdis);
1371 return_value = smbd_smb2_request_process_tdis(req);
1372 END_PROFILE(smb2_tdis);
1376 case SMB2_OP_CREATE:
1377 if (!NT_STATUS_IS_OK(session_status)) {
1378 return_value = smbd_smb2_request_error(req, session_status);
1382 * This call needs to be run as user.
1384 * smbd_smb2_request_check_tcon()
1385 * calls change_to_user() on success.
1387 status = smbd_smb2_request_check_tcon(req);
1388 if (!NT_STATUS_IS_OK(status)) {
1389 return_value = smbd_smb2_request_error(req, status);
1394 START_PROFILE(smb2_create);
1395 return_value = smbd_smb2_request_process_create(req);
1396 END_PROFILE(smb2_create);
1401 if (!NT_STATUS_IS_OK(session_status)) {
1402 return_value = smbd_smb2_request_error(req, session_status);
1406 * This call needs to be run as user.
1408 * smbd_smb2_request_check_tcon()
1409 * calls change_to_user() on success.
1411 status = smbd_smb2_request_check_tcon(req);
1412 if (!NT_STATUS_IS_OK(status)) {
1413 return_value = smbd_smb2_request_error(req, status);
1418 START_PROFILE(smb2_close);
1419 return_value = smbd_smb2_request_process_close(req);
1420 END_PROFILE(smb2_close);
1425 if (!NT_STATUS_IS_OK(session_status)) {
1426 return_value = smbd_smb2_request_error(req, session_status);
1430 * This call needs to be run as user.
1432 * smbd_smb2_request_check_tcon()
1433 * calls change_to_user() on success.
1435 status = smbd_smb2_request_check_tcon(req);
1436 if (!NT_STATUS_IS_OK(status)) {
1437 return_value = smbd_smb2_request_error(req, status);
1442 START_PROFILE(smb2_flush);
1443 return_value = smbd_smb2_request_process_flush(req);
1444 END_PROFILE(smb2_flush);
1449 if (!NT_STATUS_IS_OK(session_status)) {
1450 return_value = smbd_smb2_request_error(req, session_status);
1454 * This call needs to be run as user.
1456 * smbd_smb2_request_check_tcon()
1457 * calls change_to_user() on success.
1459 status = smbd_smb2_request_check_tcon(req);
1460 if (!NT_STATUS_IS_OK(status)) {
1461 return_value = smbd_smb2_request_error(req, status);
1466 START_PROFILE(smb2_read);
1467 return_value = smbd_smb2_request_process_read(req);
1468 END_PROFILE(smb2_read);
1473 if (!NT_STATUS_IS_OK(session_status)) {
1474 return_value = smbd_smb2_request_error(req, session_status);
1478 * This call needs to be run as user.
1480 * smbd_smb2_request_check_tcon()
1481 * calls change_to_user() on success.
1483 status = smbd_smb2_request_check_tcon(req);
1484 if (!NT_STATUS_IS_OK(status)) {
1485 return_value = smbd_smb2_request_error(req, status);
1490 START_PROFILE(smb2_write);
1491 return_value = smbd_smb2_request_process_write(req);
1492 END_PROFILE(smb2_write);
1497 if (!NT_STATUS_IS_OK(session_status)) {
1498 /* Too ugly to live ? JRA. */
1499 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1500 session_status = NT_STATUS_FILE_CLOSED;
1502 return_value = smbd_smb2_request_error(req, session_status);
1506 * This call needs to be run as user.
1508 * smbd_smb2_request_check_tcon()
1509 * calls change_to_user() on success.
1511 status = smbd_smb2_request_check_tcon(req);
1512 if (!NT_STATUS_IS_OK(status)) {
1513 /* Too ugly to live ? JRA. */
1514 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1515 status = NT_STATUS_FILE_CLOSED;
1517 return_value = smbd_smb2_request_error(req, status);
1522 START_PROFILE(smb2_lock);
1523 return_value = smbd_smb2_request_process_lock(req);
1524 END_PROFILE(smb2_lock);
1529 if (!NT_STATUS_IS_OK(session_status)) {
1530 return_value = smbd_smb2_request_error(req, session_status);
1534 * This call needs to be run as user.
1536 * smbd_smb2_request_check_tcon()
1537 * calls change_to_user() on success.
1539 status = smbd_smb2_request_check_tcon(req);
1540 if (!NT_STATUS_IS_OK(status)) {
1541 return_value = smbd_smb2_request_error(req, status);
1546 START_PROFILE(smb2_ioctl);
1547 return_value = smbd_smb2_request_process_ioctl(req);
1548 END_PROFILE(smb2_ioctl);
1552 case SMB2_OP_CANCEL:
1554 * This call needs to be run as root
1556 * That is what we also do in the SMB1 case.
1558 change_to_root_user();
1561 START_PROFILE(smb2_cancel);
1562 return_value = smbd_smb2_request_process_cancel(req);
1563 END_PROFILE(smb2_cancel);
1567 case SMB2_OP_KEEPALIVE:
1568 /* This call needs to be run as root */
1569 change_to_root_user();
1572 START_PROFILE(smb2_keepalive);
1573 return_value = smbd_smb2_request_process_keepalive(req);
1574 END_PROFILE(smb2_keepalive);
1579 if (!NT_STATUS_IS_OK(session_status)) {
1580 return_value = smbd_smb2_request_error(req, session_status);
1584 * This call needs to be run as user.
1586 * smbd_smb2_request_check_tcon()
1587 * calls change_to_user() on success.
1589 status = smbd_smb2_request_check_tcon(req);
1590 if (!NT_STATUS_IS_OK(status)) {
1591 return_value = smbd_smb2_request_error(req, status);
1596 START_PROFILE(smb2_find);
1597 return_value = smbd_smb2_request_process_find(req);
1598 END_PROFILE(smb2_find);
1602 case SMB2_OP_NOTIFY:
1603 if (!NT_STATUS_IS_OK(session_status)) {
1604 return_value = smbd_smb2_request_error(req, session_status);
1608 * This call needs to be run as user.
1610 * smbd_smb2_request_check_tcon()
1611 * calls change_to_user() on success.
1613 status = smbd_smb2_request_check_tcon(req);
1614 if (!NT_STATUS_IS_OK(status)) {
1615 return_value = smbd_smb2_request_error(req, status);
1620 START_PROFILE(smb2_notify);
1621 return_value = smbd_smb2_request_process_notify(req);
1622 END_PROFILE(smb2_notify);
1626 case SMB2_OP_GETINFO:
1627 if (!NT_STATUS_IS_OK(session_status)) {
1628 return_value = smbd_smb2_request_error(req, session_status);
1632 * This call needs to be run as user.
1634 * smbd_smb2_request_check_tcon()
1635 * calls change_to_user() on success.
1637 status = smbd_smb2_request_check_tcon(req);
1638 if (!NT_STATUS_IS_OK(status)) {
1639 return_value = smbd_smb2_request_error(req, status);
1644 START_PROFILE(smb2_getinfo);
1645 return_value = smbd_smb2_request_process_getinfo(req);
1646 END_PROFILE(smb2_getinfo);
1650 case SMB2_OP_SETINFO:
1651 if (!NT_STATUS_IS_OK(session_status)) {
1652 return_value = smbd_smb2_request_error(req, session_status);
1656 * This call needs to be run as user.
1658 * smbd_smb2_request_check_tcon()
1659 * calls change_to_user() on success.
1661 status = smbd_smb2_request_check_tcon(req);
1662 if (!NT_STATUS_IS_OK(status)) {
1663 return_value = smbd_smb2_request_error(req, status);
1668 START_PROFILE(smb2_setinfo);
1669 return_value = smbd_smb2_request_process_setinfo(req);
1670 END_PROFILE(smb2_setinfo);
1675 if (!NT_STATUS_IS_OK(session_status)) {
1676 return_value = smbd_smb2_request_error(req, session_status);
1680 * This call needs to be run as user.
1682 * smbd_smb2_request_check_tcon()
1683 * calls change_to_user() on success.
1685 status = smbd_smb2_request_check_tcon(req);
1686 if (!NT_STATUS_IS_OK(status)) {
1687 return_value = smbd_smb2_request_error(req, status);
1692 START_PROFILE(smb2_break);
1693 return_value = smbd_smb2_request_process_break(req);
1694 END_PROFILE(smb2_break);
1699 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1702 return return_value;
1705 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1707 struct tevent_req *subreq;
1708 int i = req->current_idx;
1712 req->current_idx += 3;
1714 if (req->current_idx < req->out.vector_count) {
1716 * We must process the remaining compound
1717 * SMB2 requests before any new incoming SMB2
1718 * requests. This is because incoming SMB2
1719 * requests may include a cancel for a
1720 * compound request we haven't processed
1723 struct tevent_immediate *im = tevent_create_immediate(req);
1725 return NT_STATUS_NO_MEMORY;
1727 tevent_schedule_immediate(im,
1728 req->sconn->smb2.event_ctx,
1729 smbd_smb2_request_dispatch_immediate,
1731 return NT_STATUS_OK;
1734 if (req->compound_related) {
1735 req->sconn->smb2.compound_related_in_progress = false;
1738 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1740 /* Set credit for this operation (zero credits if this
1741 is a final reply for an async operation). */
1742 smb2_set_operation_credit(req->sconn,
1744 &req->out.vector[i]);
1746 if (req->do_signing) {
1748 status = smb2_signing_sign_pdu(req->session->session_key,
1749 &req->out.vector[i], 3);
1750 if (!NT_STATUS_IS_OK(status)) {
1755 if (DEBUGLEVEL >= 10) {
1756 dbgtext("smbd_smb2_request_reply: sending...\n");
1757 print_req_vectors(req);
1760 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1761 if (req->out.vector_count == 4 &&
1762 req->out.vector[3].iov_base == NULL &&
1763 req->out.vector[3].iov_len != 0) {
1764 /* Dynamic part is NULL. Chop it off,
1765 We're going to send it via sendfile. */
1766 req->out.vector_count -= 1;
1769 subreq = tstream_writev_queue_send(req,
1770 req->sconn->smb2.event_ctx,
1771 req->sconn->smb2.stream,
1772 req->sconn->smb2.send_queue,
1774 req->out.vector_count);
1775 if (subreq == NULL) {
1776 return NT_STATUS_NO_MEMORY;
1778 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1780 * We're done with this request -
1781 * move it off the "being processed" queue.
1783 DLIST_REMOVE(req->sconn->smb2.requests, req);
1785 return NT_STATUS_OK;
1788 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
1790 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1791 struct tevent_immediate *im,
1794 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1795 struct smbd_smb2_request);
1796 struct smbd_server_connection *sconn = req->sconn;
1801 if (DEBUGLEVEL >= 10) {
1802 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1803 req->current_idx, req->in.vector_count));
1804 print_req_vectors(req);
1807 status = smbd_smb2_request_dispatch(req);
1808 if (!NT_STATUS_IS_OK(status)) {
1809 smbd_server_connection_terminate(sconn, nt_errstr(status));
1813 status = smbd_smb2_request_next_incoming(sconn);
1814 if (!NT_STATUS_IS_OK(status)) {
1815 smbd_server_connection_terminate(sconn, nt_errstr(status));
1820 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1822 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1823 struct smbd_smb2_request);
1824 struct smbd_server_connection *sconn = req->sconn;
1829 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1830 TALLOC_FREE(subreq);
1833 status = map_nt_error_from_unix(sys_errno);
1834 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1835 nt_errstr(status)));
1836 smbd_server_connection_terminate(sconn, nt_errstr(status));
1840 status = smbd_smb2_request_next_incoming(sconn);
1841 if (!NT_STATUS_IS_OK(status)) {
1842 smbd_server_connection_terminate(sconn, nt_errstr(status));
1847 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1849 DATA_BLOB body, DATA_BLOB *dyn,
1850 const char *location)
1853 int i = req->current_idx;
1854 uint32_t next_command_ofs;
1856 DEBUG(10,("smbd_smb2_request_done_ex: "
1857 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1858 i, nt_errstr(status), (unsigned int)body.length,
1860 (unsigned int)(dyn ? dyn->length : 0),
1863 if (body.length < 2) {
1864 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1867 if ((body.length % 2) != 0) {
1868 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1871 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1873 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1874 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1876 req->out.vector[i+1].iov_base = (void *)body.data;
1877 req->out.vector[i+1].iov_len = body.length;
1880 req->out.vector[i+2].iov_base = (void *)dyn->data;
1881 req->out.vector[i+2].iov_len = dyn->length;
1883 req->out.vector[i+2].iov_base = NULL;
1884 req->out.vector[i+2].iov_len = 0;
1887 /* see if we need to recalculate the offset to the next response */
1888 if (next_command_ofs > 0) {
1889 next_command_ofs = SMB2_HDR_BODY;
1890 next_command_ofs += req->out.vector[i+1].iov_len;
1891 next_command_ofs += req->out.vector[i+2].iov_len;
1894 if ((next_command_ofs % 8) != 0) {
1895 size_t pad_size = 8 - (next_command_ofs % 8);
1896 if (req->out.vector[i+2].iov_len == 0) {
1898 * if the dyn buffer is empty
1899 * we can use it to add padding
1903 pad = talloc_zero_array(req->out.vector,
1906 return smbd_smb2_request_error(req,
1907 NT_STATUS_NO_MEMORY);
1910 req->out.vector[i+2].iov_base = (void *)pad;
1911 req->out.vector[i+2].iov_len = pad_size;
1914 * For now we copy the dynamic buffer
1915 * and add the padding to the new buffer
1922 old_size = req->out.vector[i+2].iov_len;
1923 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
1925 new_size = old_size + pad_size;
1926 new_dyn = talloc_zero_array(req->out.vector,
1928 if (new_dyn == NULL) {
1929 return smbd_smb2_request_error(req,
1930 NT_STATUS_NO_MEMORY);
1933 memcpy(new_dyn, old_dyn, old_size);
1934 memset(new_dyn + old_size, 0, pad_size);
1936 req->out.vector[i+2].iov_base = (void *)new_dyn;
1937 req->out.vector[i+2].iov_len = new_size;
1939 next_command_ofs += pad_size;
1942 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1944 return smbd_smb2_request_reply(req);
1947 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
1950 const char *location)
1953 int i = req->current_idx;
1954 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
1956 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1957 i, nt_errstr(status), info ? " +info" : "",
1960 body.data = outhdr + SMB2_HDR_BODY;
1962 SSVAL(body.data, 0, 9);
1965 SIVAL(body.data, 0x04, info->length);
1967 /* Allocated size of req->out.vector[i].iov_base
1968 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
1969 * 1 byte without having to do an alloc.
1971 info = talloc_zero_array(req->out.vector,
1975 return NT_STATUS_NO_MEMORY;
1977 info->data = ((uint8_t *)outhdr) +
1978 OUTVEC_ALLOC_SIZE - 1;
1980 SCVAL(info->data, 0, 0);
1984 * if a request fails, all other remaining
1985 * compounded requests should fail too
1987 req->next_status = NT_STATUS_INVALID_PARAMETER;
1989 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
1993 struct smbd_smb2_send_oplock_break_state {
1994 struct smbd_server_connection *sconn;
1995 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
1996 struct iovec vector;
1999 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2001 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2002 uint64_t file_id_persistent,
2003 uint64_t file_id_volatile,
2004 uint8_t oplock_level)
2006 struct smbd_smb2_send_oplock_break_state *state;
2007 struct tevent_req *subreq;
2011 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2012 if (state == NULL) {
2013 return NT_STATUS_NO_MEMORY;
2015 state->sconn = sconn;
2017 state->vector.iov_base = (void *)state->buf;
2018 state->vector.iov_len = sizeof(state->buf);
2020 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2021 hdr = state->buf + 4;
2022 body = hdr + SMB2_HDR_BODY;
2024 SIVAL(hdr, 0, SMB2_MAGIC);
2025 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2026 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2027 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2028 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2029 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2030 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2031 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2032 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2033 SIVAL(hdr, SMB2_HDR_PID, 0);
2034 SIVAL(hdr, SMB2_HDR_TID, 0);
2035 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2036 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2038 SSVAL(body, 0x00, 0x18);
2040 SCVAL(body, 0x02, oplock_level);
2041 SCVAL(body, 0x03, 0); /* reserved */
2042 SIVAL(body, 0x04, 0); /* reserved */
2043 SBVAL(body, 0x08, file_id_persistent);
2044 SBVAL(body, 0x10, file_id_volatile);
2046 subreq = tstream_writev_queue_send(state,
2047 sconn->smb2.event_ctx,
2049 sconn->smb2.send_queue,
2051 if (subreq == NULL) {
2052 return NT_STATUS_NO_MEMORY;
2054 tevent_req_set_callback(subreq,
2055 smbd_smb2_oplock_break_writev_done,
2058 return NT_STATUS_OK;
2061 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2063 struct smbd_smb2_send_oplock_break_state *state =
2064 tevent_req_callback_data(subreq,
2065 struct smbd_smb2_send_oplock_break_state);
2066 struct smbd_server_connection *sconn = state->sconn;
2070 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2071 TALLOC_FREE(subreq);
2073 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2074 smbd_server_connection_terminate(sconn, nt_errstr(status));
2081 struct smbd_smb2_request_read_state {
2083 bool asked_for_header;
2084 struct smbd_smb2_request *smb2_req;
2087 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2089 TALLOC_CTX *mem_ctx,
2090 struct iovec **_vector,
2092 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2094 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2095 struct tevent_context *ev,
2096 struct smbd_server_connection *sconn)
2098 struct tevent_req *req;
2099 struct smbd_smb2_request_read_state *state;
2100 struct tevent_req *subreq;
2102 req = tevent_req_create(mem_ctx, &state,
2103 struct smbd_smb2_request_read_state);
2108 state->asked_for_header = false;
2110 state->smb2_req = smbd_smb2_request_allocate(state);
2111 if (tevent_req_nomem(state->smb2_req, req)) {
2112 return tevent_req_post(req, ev);
2114 state->smb2_req->sconn = sconn;
2116 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2117 sconn->smb2.recv_queue,
2118 smbd_smb2_request_next_vector,
2120 if (tevent_req_nomem(subreq, req)) {
2121 return tevent_req_post(req, ev);
2123 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2128 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2130 TALLOC_CTX *mem_ctx,
2131 struct iovec **_vector,
2134 struct smbd_smb2_request_read_state *state =
2135 talloc_get_type_abort(private_data,
2136 struct smbd_smb2_request_read_state);
2137 struct smbd_smb2_request *req = state->smb2_req;
2138 struct iovec *vector;
2139 int idx = req->in.vector_count;
2141 uint8_t *buf = NULL;
2143 if (req->in.vector_count == 0) {
2145 * first we need to get the NBT header
2147 req->in.vector = talloc_array(req, struct iovec,
2148 req->in.vector_count + 1);
2149 if (req->in.vector == NULL) {
2152 req->in.vector_count += 1;
2154 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2155 req->in.vector[idx].iov_len = 4;
2157 vector = talloc_array(mem_ctx, struct iovec, 1);
2158 if (vector == NULL) {
2162 vector[0] = req->in.vector[idx];
2169 if (req->in.vector_count == 1) {
2171 * Now we analyze the NBT header
2173 state->missing = smb2_len(req->in.vector[0].iov_base);
2175 if (state->missing == 0) {
2176 /* if there're no remaining bytes, we're done */
2182 req->in.vector = talloc_realloc(req, req->in.vector,
2184 req->in.vector_count + 1);
2185 if (req->in.vector == NULL) {
2188 req->in.vector_count += 1;
2190 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2192 * it's a special NBT message,
2193 * so get all remaining bytes
2195 len = state->missing;
2196 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2198 * it's an invalid message, just read what we can get
2199 * and let the caller handle the error
2201 len = state->missing;
2204 * We assume it's a SMB2 request,
2205 * and we first get the header and the
2206 * first 2 bytes (the struct size) of the body
2208 len = SMB2_HDR_BODY + 2;
2210 state->asked_for_header = true;
2213 state->missing -= len;
2215 buf = talloc_array(req->in.vector, uint8_t, len);
2220 req->in.vector[idx].iov_base = (void *)buf;
2221 req->in.vector[idx].iov_len = len;
2223 vector = talloc_array(mem_ctx, struct iovec, 1);
2224 if (vector == NULL) {
2228 vector[0] = req->in.vector[idx];
2235 if (state->missing == 0) {
2236 /* if there're no remaining bytes, we're done */
2242 if (state->asked_for_header) {
2245 size_t next_command_ofs;
2250 bool invalid = false;
2252 state->asked_for_header = false;
2255 * We got the SMB2 header and the first 2 bytes
2256 * of the body. We fix the size to just the header
2257 * and manually copy the 2 first bytes to the body section
2259 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2260 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2262 /* allocate vectors for body and dynamic areas */
2263 req->in.vector = talloc_realloc(req, req->in.vector,
2265 req->in.vector_count + 2);
2266 if (req->in.vector == NULL) {
2269 req->in.vector_count += 2;
2271 full_size = state->missing + SMB2_HDR_BODY + 2;
2272 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2273 body_size = SVAL(hdr, SMB2_HDR_BODY);
2275 if (next_command_ofs != 0) {
2276 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2278 * this is invalid, just return a zero
2279 * body and let the caller deal with the error
2282 } else if (next_command_ofs > full_size) {
2284 * this is invalid, just return a zero
2285 * body and let the caller deal with the error
2289 full_size = next_command_ofs;
2294 if (body_size < 2) {
2296 * this is invalid, just return a zero
2297 * body and let the caller deal with the error
2302 if ((body_size % 2) != 0) {
2306 if (body_size > (full_size - SMB2_HDR_BODY)) {
2308 * this is invalid, just return a zero
2309 * body and let the caller deal with the error
2316 /* the caller should check this */
2320 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2322 state->missing -= (body_size - 2) + dyn_size;
2324 body = talloc_array(req->in.vector, uint8_t, body_size);
2329 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2334 req->in.vector[idx].iov_base = (void *)body;
2335 req->in.vector[idx].iov_len = body_size;
2336 req->in.vector[idx+1].iov_base = (void *)dyn;
2337 req->in.vector[idx+1].iov_len = dyn_size;
2339 vector = talloc_array(mem_ctx, struct iovec, 2);
2340 if (vector == NULL) {
2345 * the first 2 bytes of the body were already fetched
2346 * together with the header
2348 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2349 vector[0].iov_base = body + 2;
2350 vector[0].iov_len = body_size - 2;
2352 vector[1] = req->in.vector[idx+1];
2360 * when we endup here, we're looking for a new SMB2 request
2361 * next. And we ask for its header and the first 2 bytes of
2362 * the body (like we did for the first SMB2 request).
2365 req->in.vector = talloc_realloc(req, req->in.vector,
2367 req->in.vector_count + 1);
2368 if (req->in.vector == NULL) {
2371 req->in.vector_count += 1;
2374 * We assume it's a SMB2 request,
2375 * and we first get the header and the
2376 * first 2 bytes (the struct size) of the body
2378 len = SMB2_HDR_BODY + 2;
2380 if (len > state->missing) {
2381 /* let the caller handle the error */
2382 len = state->missing;
2385 state->missing -= len;
2386 state->asked_for_header = true;
2388 buf = talloc_array(req->in.vector, uint8_t, len);
2393 req->in.vector[idx].iov_base = (void *)buf;
2394 req->in.vector[idx].iov_len = len;
2396 vector = talloc_array(mem_ctx, struct iovec, 1);
2397 if (vector == NULL) {
2401 vector[0] = req->in.vector[idx];
2408 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2410 struct tevent_req *req =
2411 tevent_req_callback_data(subreq,
2417 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2419 status = map_nt_error_from_unix(sys_errno);
2420 tevent_req_nterror(req, status);
2424 tevent_req_done(req);
2427 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2428 TALLOC_CTX *mem_ctx,
2429 struct smbd_smb2_request **_smb2_req)
2431 struct smbd_smb2_request_read_state *state =
2432 tevent_req_data(req,
2433 struct smbd_smb2_request_read_state);
2436 if (tevent_req_is_nterror(req, &status)) {
2437 tevent_req_received(req);
2441 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2442 *_smb2_req = state->smb2_req;
2443 tevent_req_received(req);
2444 return NT_STATUS_OK;
2447 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2449 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2451 size_t max_send_queue_len;
2452 size_t cur_send_queue_len;
2453 struct tevent_req *subreq;
2455 if (sconn->smb2.compound_related_in_progress) {
2457 * Can't read another until the related
2460 return NT_STATUS_OK;
2463 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2465 * if there is already a smbd_smb2_request_read
2466 * pending, we are done.
2468 return NT_STATUS_OK;
2471 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2472 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2474 if (cur_send_queue_len > max_send_queue_len) {
2476 * if we have a lot of requests to send,
2477 * we wait until they are on the wire until we
2478 * ask for the next request.
2480 return NT_STATUS_OK;
2483 /* ask for the next request */
2484 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2485 if (subreq == NULL) {
2486 return NT_STATUS_NO_MEMORY;
2488 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2490 return NT_STATUS_OK;
2493 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2494 const uint8_t *inbuf, size_t size)
2497 struct smbd_smb2_request *req = NULL;
2499 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2500 (unsigned int)size));
2502 status = smbd_initialize_smb2(sconn);
2503 if (!NT_STATUS_IS_OK(status)) {
2504 smbd_server_connection_terminate(sconn, nt_errstr(status));
2508 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2509 if (!NT_STATUS_IS_OK(status)) {
2510 smbd_server_connection_terminate(sconn, nt_errstr(status));
2514 status = smbd_smb2_request_setup_out(req);
2515 if (!NT_STATUS_IS_OK(status)) {
2516 smbd_server_connection_terminate(sconn, nt_errstr(status));
2520 status = smbd_smb2_request_dispatch(req);
2521 if (!NT_STATUS_IS_OK(status)) {
2522 smbd_server_connection_terminate(sconn, nt_errstr(status));
2526 status = smbd_smb2_request_next_incoming(sconn);
2527 if (!NT_STATUS_IS_OK(status)) {
2528 smbd_server_connection_terminate(sconn, nt_errstr(status));
2532 sconn->num_requests++;
2535 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2537 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2538 struct smbd_server_connection);
2540 struct smbd_smb2_request *req = NULL;
2542 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2543 TALLOC_FREE(subreq);
2544 if (!NT_STATUS_IS_OK(status)) {
2545 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2546 nt_errstr(status)));
2547 smbd_server_connection_terminate(sconn, nt_errstr(status));
2551 if (req->in.nbt_hdr[0] != 0x00) {
2552 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2553 req->in.nbt_hdr[0]));
2558 req->current_idx = 1;
2560 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2561 req->current_idx, req->in.vector_count));
2563 status = smbd_smb2_request_validate(req);
2564 if (!NT_STATUS_IS_OK(status)) {
2565 smbd_server_connection_terminate(sconn, nt_errstr(status));
2569 status = smbd_smb2_request_setup_out(req);
2570 if (!NT_STATUS_IS_OK(status)) {
2571 smbd_server_connection_terminate(sconn, nt_errstr(status));
2575 status = smbd_smb2_request_dispatch(req);
2576 if (!NT_STATUS_IS_OK(status)) {
2577 smbd_server_connection_terminate(sconn, nt_errstr(status));
2582 status = smbd_smb2_request_next_incoming(sconn);
2583 if (!NT_STATUS_IS_OK(status)) {
2584 smbd_server_connection_terminate(sconn, nt_errstr(status));
2588 sconn->num_requests++;
2590 /* The timeout_processing function isn't run nearly
2591 often enough to implement 'max log size' without
2592 overrunning the size of the file by many megabytes.
2593 This is especially true if we are running at debug
2594 level 10. Checking every 50 SMB2s is a nice
2595 tradeoff of performance vs log file size overrun. */
2597 if ((sconn->num_requests % 50) == 0 &&
2598 need_to_check_log_size()) {
2599 change_to_root_user();