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 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;
1828 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1829 TALLOC_FREE(subreq);
1832 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1833 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1834 nt_errstr(status)));
1835 smbd_server_connection_terminate(sconn, nt_errstr(status));
1840 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1842 DATA_BLOB body, DATA_BLOB *dyn,
1843 const char *location)
1846 int i = req->current_idx;
1847 uint32_t next_command_ofs;
1849 DEBUG(10,("smbd_smb2_request_done_ex: "
1850 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1851 i, nt_errstr(status), (unsigned int)body.length,
1853 (unsigned int)(dyn ? dyn->length : 0),
1856 if (body.length < 2) {
1857 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1860 if ((body.length % 2) != 0) {
1861 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1864 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1866 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1867 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1869 req->out.vector[i+1].iov_base = (void *)body.data;
1870 req->out.vector[i+1].iov_len = body.length;
1873 req->out.vector[i+2].iov_base = (void *)dyn->data;
1874 req->out.vector[i+2].iov_len = dyn->length;
1876 req->out.vector[i+2].iov_base = NULL;
1877 req->out.vector[i+2].iov_len = 0;
1880 /* see if we need to recalculate the offset to the next response */
1881 if (next_command_ofs > 0) {
1882 next_command_ofs = SMB2_HDR_BODY;
1883 next_command_ofs += req->out.vector[i+1].iov_len;
1884 next_command_ofs += req->out.vector[i+2].iov_len;
1887 if ((next_command_ofs % 8) != 0) {
1888 size_t pad_size = 8 - (next_command_ofs % 8);
1889 if (req->out.vector[i+2].iov_len == 0) {
1891 * if the dyn buffer is empty
1892 * we can use it to add padding
1896 pad = talloc_zero_array(req->out.vector,
1899 return smbd_smb2_request_error(req,
1900 NT_STATUS_NO_MEMORY);
1903 req->out.vector[i+2].iov_base = (void *)pad;
1904 req->out.vector[i+2].iov_len = pad_size;
1907 * For now we copy the dynamic buffer
1908 * and add the padding to the new buffer
1915 old_size = req->out.vector[i+2].iov_len;
1916 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
1918 new_size = old_size + pad_size;
1919 new_dyn = talloc_zero_array(req->out.vector,
1921 if (new_dyn == NULL) {
1922 return smbd_smb2_request_error(req,
1923 NT_STATUS_NO_MEMORY);
1926 memcpy(new_dyn, old_dyn, old_size);
1927 memset(new_dyn + old_size, 0, pad_size);
1929 req->out.vector[i+2].iov_base = (void *)new_dyn;
1930 req->out.vector[i+2].iov_len = new_size;
1932 next_command_ofs += pad_size;
1935 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1937 return smbd_smb2_request_reply(req);
1940 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
1943 const char *location)
1946 int i = req->current_idx;
1947 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
1949 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1950 i, nt_errstr(status), info ? " +info" : "",
1953 body.data = outhdr + SMB2_HDR_BODY;
1955 SSVAL(body.data, 0, 9);
1958 SIVAL(body.data, 0x04, info->length);
1960 /* Allocated size of req->out.vector[i].iov_base
1961 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
1962 * 1 byte without having to do an alloc.
1964 info = talloc_zero_array(req->out.vector,
1968 return NT_STATUS_NO_MEMORY;
1970 info->data = ((uint8_t *)outhdr) +
1971 OUTVEC_ALLOC_SIZE - 1;
1973 SCVAL(info->data, 0, 0);
1977 * if a request fails, all other remaining
1978 * compounded requests should fail too
1980 req->next_status = NT_STATUS_INVALID_PARAMETER;
1982 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
1986 struct smbd_smb2_send_oplock_break_state {
1987 struct smbd_server_connection *sconn;
1988 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
1989 struct iovec vector;
1992 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
1994 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
1995 uint64_t file_id_persistent,
1996 uint64_t file_id_volatile,
1997 uint8_t oplock_level)
1999 struct smbd_smb2_send_oplock_break_state *state;
2000 struct tevent_req *subreq;
2004 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2005 if (state == NULL) {
2006 return NT_STATUS_NO_MEMORY;
2008 state->sconn = sconn;
2010 state->vector.iov_base = (void *)state->buf;
2011 state->vector.iov_len = sizeof(state->buf);
2013 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2014 hdr = state->buf + 4;
2015 body = hdr + SMB2_HDR_BODY;
2017 SIVAL(hdr, 0, SMB2_MAGIC);
2018 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2019 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2020 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2021 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2022 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2023 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2024 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2025 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2026 SIVAL(hdr, SMB2_HDR_PID, 0);
2027 SIVAL(hdr, SMB2_HDR_TID, 0);
2028 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2029 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2031 SSVAL(body, 0x00, 0x18);
2033 SCVAL(body, 0x02, oplock_level);
2034 SCVAL(body, 0x03, 0); /* reserved */
2035 SIVAL(body, 0x04, 0); /* reserved */
2036 SBVAL(body, 0x08, file_id_persistent);
2037 SBVAL(body, 0x10, file_id_volatile);
2039 subreq = tstream_writev_queue_send(state,
2040 sconn->smb2.event_ctx,
2042 sconn->smb2.send_queue,
2044 if (subreq == NULL) {
2045 return NT_STATUS_NO_MEMORY;
2047 tevent_req_set_callback(subreq,
2048 smbd_smb2_oplock_break_writev_done,
2051 return NT_STATUS_OK;
2054 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2056 struct smbd_smb2_send_oplock_break_state *state =
2057 tevent_req_callback_data(subreq,
2058 struct smbd_smb2_send_oplock_break_state);
2059 struct smbd_server_connection *sconn = state->sconn;
2063 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2064 TALLOC_FREE(subreq);
2066 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2067 smbd_server_connection_terminate(sconn, nt_errstr(status));
2074 struct smbd_smb2_request_read_state {
2076 bool asked_for_header;
2077 struct smbd_smb2_request *smb2_req;
2080 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2082 TALLOC_CTX *mem_ctx,
2083 struct iovec **_vector,
2085 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2087 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2088 struct tevent_context *ev,
2089 struct smbd_server_connection *sconn)
2091 struct tevent_req *req;
2092 struct smbd_smb2_request_read_state *state;
2093 struct tevent_req *subreq;
2095 req = tevent_req_create(mem_ctx, &state,
2096 struct smbd_smb2_request_read_state);
2101 state->asked_for_header = false;
2103 state->smb2_req = smbd_smb2_request_allocate(state);
2104 if (tevent_req_nomem(state->smb2_req, req)) {
2105 return tevent_req_post(req, ev);
2107 state->smb2_req->sconn = sconn;
2109 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2110 sconn->smb2.recv_queue,
2111 smbd_smb2_request_next_vector,
2113 if (tevent_req_nomem(subreq, req)) {
2114 return tevent_req_post(req, ev);
2116 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2121 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2123 TALLOC_CTX *mem_ctx,
2124 struct iovec **_vector,
2127 struct smbd_smb2_request_read_state *state =
2128 talloc_get_type_abort(private_data,
2129 struct smbd_smb2_request_read_state);
2130 struct smbd_smb2_request *req = state->smb2_req;
2131 struct iovec *vector;
2132 int idx = req->in.vector_count;
2134 uint8_t *buf = NULL;
2136 if (req->in.vector_count == 0) {
2138 * first we need to get the NBT header
2140 req->in.vector = talloc_array(req, struct iovec,
2141 req->in.vector_count + 1);
2142 if (req->in.vector == NULL) {
2145 req->in.vector_count += 1;
2147 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2148 req->in.vector[idx].iov_len = 4;
2150 vector = talloc_array(mem_ctx, struct iovec, 1);
2151 if (vector == NULL) {
2155 vector[0] = req->in.vector[idx];
2162 if (req->in.vector_count == 1) {
2164 * Now we analyze the NBT header
2166 state->missing = smb2_len(req->in.vector[0].iov_base);
2168 if (state->missing == 0) {
2169 /* if there're no remaining bytes, we're done */
2175 req->in.vector = talloc_realloc(req, req->in.vector,
2177 req->in.vector_count + 1);
2178 if (req->in.vector == NULL) {
2181 req->in.vector_count += 1;
2183 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2185 * it's a special NBT message,
2186 * so get all remaining bytes
2188 len = state->missing;
2189 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2191 * it's an invalid message, just read what we can get
2192 * and let the caller handle the error
2194 len = state->missing;
2197 * We assume it's a SMB2 request,
2198 * and we first get the header and the
2199 * first 2 bytes (the struct size) of the body
2201 len = SMB2_HDR_BODY + 2;
2203 state->asked_for_header = true;
2206 state->missing -= len;
2208 buf = talloc_array(req->in.vector, uint8_t, len);
2213 req->in.vector[idx].iov_base = (void *)buf;
2214 req->in.vector[idx].iov_len = len;
2216 vector = talloc_array(mem_ctx, struct iovec, 1);
2217 if (vector == NULL) {
2221 vector[0] = req->in.vector[idx];
2228 if (state->missing == 0) {
2229 /* if there're no remaining bytes, we're done */
2235 if (state->asked_for_header) {
2238 size_t next_command_ofs;
2243 bool invalid = false;
2245 state->asked_for_header = false;
2248 * We got the SMB2 header and the first 2 bytes
2249 * of the body. We fix the size to just the header
2250 * and manually copy the 2 first bytes to the body section
2252 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2253 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2255 /* allocate vectors for body and dynamic areas */
2256 req->in.vector = talloc_realloc(req, req->in.vector,
2258 req->in.vector_count + 2);
2259 if (req->in.vector == NULL) {
2262 req->in.vector_count += 2;
2264 full_size = state->missing + SMB2_HDR_BODY + 2;
2265 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2266 body_size = SVAL(hdr, SMB2_HDR_BODY);
2268 if (next_command_ofs != 0) {
2269 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2271 * this is invalid, just return a zero
2272 * body and let the caller deal with the error
2275 } else if (next_command_ofs > full_size) {
2277 * this is invalid, just return a zero
2278 * body and let the caller deal with the error
2282 full_size = next_command_ofs;
2287 if (body_size < 2) {
2289 * this is invalid, just return a zero
2290 * body and let the caller deal with the error
2296 * Mask out the lowest bit, the "dynamic" part
2301 if (body_size > (full_size - SMB2_HDR_BODY)) {
2303 * this is invalid, just return a zero
2304 * body and let the caller deal with the error
2311 /* the caller should check this */
2315 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2317 state->missing -= (body_size - 2) + dyn_size;
2319 body = talloc_array(req->in.vector, uint8_t, body_size);
2324 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2329 req->in.vector[idx].iov_base = (void *)body;
2330 req->in.vector[idx].iov_len = body_size;
2331 req->in.vector[idx+1].iov_base = (void *)dyn;
2332 req->in.vector[idx+1].iov_len = dyn_size;
2334 vector = talloc_array(mem_ctx, struct iovec, 2);
2335 if (vector == NULL) {
2340 * the first 2 bytes of the body were already fetched
2341 * together with the header
2343 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2344 vector[0].iov_base = body + 2;
2345 vector[0].iov_len = body_size - 2;
2347 vector[1] = req->in.vector[idx+1];
2355 * when we endup here, we're looking for a new SMB2 request
2356 * next. And we ask for its header and the first 2 bytes of
2357 * the body (like we did for the first SMB2 request).
2360 req->in.vector = talloc_realloc(req, req->in.vector,
2362 req->in.vector_count + 1);
2363 if (req->in.vector == NULL) {
2366 req->in.vector_count += 1;
2369 * We assume it's a SMB2 request,
2370 * and we first get the header and the
2371 * first 2 bytes (the struct size) of the body
2373 len = SMB2_HDR_BODY + 2;
2375 if (len > state->missing) {
2376 /* let the caller handle the error */
2377 len = state->missing;
2380 state->missing -= len;
2381 state->asked_for_header = true;
2383 buf = talloc_array(req->in.vector, uint8_t, len);
2388 req->in.vector[idx].iov_base = (void *)buf;
2389 req->in.vector[idx].iov_len = len;
2391 vector = talloc_array(mem_ctx, struct iovec, 1);
2392 if (vector == NULL) {
2396 vector[0] = req->in.vector[idx];
2403 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2405 struct tevent_req *req =
2406 tevent_req_callback_data(subreq,
2412 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2414 status = map_nt_error_from_unix(sys_errno);
2415 tevent_req_nterror(req, status);
2419 tevent_req_done(req);
2422 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2423 TALLOC_CTX *mem_ctx,
2424 struct smbd_smb2_request **_smb2_req)
2426 struct smbd_smb2_request_read_state *state =
2427 tevent_req_data(req,
2428 struct smbd_smb2_request_read_state);
2431 if (tevent_req_is_nterror(req, &status)) {
2432 tevent_req_received(req);
2436 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2437 *_smb2_req = state->smb2_req;
2438 tevent_req_received(req);
2439 return NT_STATUS_OK;
2442 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2444 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2445 const uint8_t *inbuf, size_t size)
2448 struct smbd_smb2_request *req = NULL;
2449 struct tevent_req *subreq;
2451 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2452 (unsigned int)size));
2454 status = smbd_initialize_smb2(sconn);
2455 if (!NT_STATUS_IS_OK(status)) {
2456 smbd_server_connection_terminate(sconn, nt_errstr(status));
2460 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2461 if (!NT_STATUS_IS_OK(status)) {
2462 smbd_server_connection_terminate(sconn, nt_errstr(status));
2466 status = smbd_smb2_request_setup_out(req);
2467 if (!NT_STATUS_IS_OK(status)) {
2468 smbd_server_connection_terminate(sconn, nt_errstr(status));
2472 status = smbd_smb2_request_dispatch(req);
2473 if (!NT_STATUS_IS_OK(status)) {
2474 smbd_server_connection_terminate(sconn, nt_errstr(status));
2478 /* ask for the next request */
2479 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2480 if (subreq == NULL) {
2481 smbd_server_connection_terminate(sconn, "no memory for reading");
2484 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2486 sconn->num_requests++;
2489 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2491 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2492 struct smbd_server_connection);
2494 struct smbd_smb2_request *req = NULL;
2496 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2497 TALLOC_FREE(subreq);
2498 if (!NT_STATUS_IS_OK(status)) {
2499 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2500 nt_errstr(status)));
2501 smbd_server_connection_terminate(sconn, nt_errstr(status));
2505 if (req->in.nbt_hdr[0] != 0x00) {
2506 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2507 req->in.nbt_hdr[0]));
2512 req->current_idx = 1;
2514 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2515 req->current_idx, req->in.vector_count));
2517 status = smbd_smb2_request_validate(req);
2518 if (!NT_STATUS_IS_OK(status)) {
2519 smbd_server_connection_terminate(sconn, nt_errstr(status));
2523 status = smbd_smb2_request_setup_out(req);
2524 if (!NT_STATUS_IS_OK(status)) {
2525 smbd_server_connection_terminate(sconn, nt_errstr(status));
2529 status = smbd_smb2_request_dispatch(req);
2530 if (!NT_STATUS_IS_OK(status)) {
2531 smbd_server_connection_terminate(sconn, nt_errstr(status));
2536 /* ask for the next request (this constructs the main loop) */
2537 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2538 if (subreq == NULL) {
2539 smbd_server_connection_terminate(sconn, "no memory for reading");
2542 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2544 sconn->num_requests++;
2546 /* The timeout_processing function isn't run nearly
2547 often enough to implement 'max log size' without
2548 overrunning the size of the file by many megabytes.
2549 This is especially true if we are running at debug
2550 level 10. Checking every 50 SMB2s is a nice
2551 tradeoff of performance vs log file size overrun. */
2553 if ((sconn->num_requests % 50) == 0 &&
2554 need_to_check_log_size()) {
2555 change_to_root_user();