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)
364 count = req->in.vector_count;
367 /* It's not a SMB2 request */
368 return NT_STATUS_INVALID_PARAMETER;
371 for (idx=1; idx < count; idx += 3) {
372 const uint8_t *inhdr = NULL;
375 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
376 return NT_STATUS_INVALID_PARAMETER;
379 if (req->in.vector[idx+1].iov_len < 2) {
380 return NT_STATUS_INVALID_PARAMETER;
383 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
385 /* Check the SMB2 header */
386 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
387 return NT_STATUS_INVALID_PARAMETER;
390 if (!smb2_validate_message_id(req->sconn, inhdr)) {
391 return NT_STATUS_INVALID_PARAMETER;
394 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
397 * the 1st request should never have the
398 * SMB2_HDR_FLAG_CHAINED flag set
400 if (flags & SMB2_HDR_FLAG_CHAINED) {
401 req->next_status = NT_STATUS_INVALID_PARAMETER;
404 } else if (idx == 4) {
406 * the 2nd request triggers related vs. unrelated
407 * compounded requests
409 if (flags & SMB2_HDR_FLAG_CHAINED) {
410 req->compound_related = true;
412 } else if (idx > 4) {
415 * It seems the this tests are wrong
416 * see the SMB2-COMPOUND test
420 * all other requests should match the 2nd one
422 if (flags & SMB2_HDR_FLAG_CHAINED) {
423 if (!req->compound_related) {
425 NT_STATUS_INVALID_PARAMETER;
429 if (req->compound_related) {
431 NT_STATUS_INVALID_PARAMETER;
442 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
443 const struct iovec *in_vector,
444 struct iovec *out_vector)
446 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
447 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
448 uint16_t credits_requested;
450 uint16_t credits_granted = 0;
452 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
453 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
455 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
457 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
459 * In case we already send an async interim
460 * response, we should not grant
461 * credits on the final response.
463 credits_requested = 0;
466 if (credits_requested) {
467 uint16_t modified_credits_requested;
471 * Split up max_credits into 1/16ths, and then scale
472 * the requested credits by how many 16ths have been
473 * currently granted. Less than 1/16th == grant all
474 * requested (100%), scale down as more have been
475 * granted. Never ask for less than 1 as the client
476 * asked for at least 1. JRA.
479 multiplier = 16 - (((sconn->smb2.credits_granted * 16) / sconn->smb2.max_credits) % 16);
481 modified_credits_requested = (multiplier * credits_requested) / 16;
482 if (modified_credits_requested == 0) {
483 modified_credits_requested = 1;
486 /* Remember what we gave out. */
487 credits_granted = MIN(modified_credits_requested,
488 (sconn->smb2.max_credits - sconn->smb2.credits_granted));
491 if (credits_granted == 0 && sconn->smb2.credits_granted == 0) {
492 /* First negprot packet, or ensure the client credits can
493 never drop to zero. */
497 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
498 sconn->smb2.credits_granted += credits_granted;
500 DEBUG(10,("smb2_set_operation_credit: requested %u, "
501 "granted %u, total granted %u\n",
502 (unsigned int)credits_requested,
503 (unsigned int)credits_granted,
504 (unsigned int)sconn->smb2.credits_granted ));
507 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
508 struct smbd_smb2_request *outreq)
512 count = outreq->out.vector_count;
514 for (idx=1; idx < count; idx += 3) {
515 smb2_set_operation_credit(outreq->sconn,
516 &inreq->in.vector[idx],
517 &outreq->out.vector[idx]);
521 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
523 struct iovec *vector;
527 count = req->in.vector_count;
528 vector = talloc_zero_array(req, struct iovec, count);
529 if (vector == NULL) {
530 return NT_STATUS_NO_MEMORY;
533 vector[0].iov_base = req->out.nbt_hdr;
534 vector[0].iov_len = 4;
535 SIVAL(req->out.nbt_hdr, 0, 0);
537 for (idx=1; idx < count; idx += 3) {
538 const uint8_t *inhdr = NULL;
540 uint8_t *outhdr = NULL;
541 uint8_t *outbody = NULL;
542 uint32_t next_command_ofs = 0;
543 struct iovec *current = &vector[idx];
545 if ((idx + 3) < count) {
546 /* we have a next command -
547 * setup for the error case. */
548 next_command_ofs = SMB2_HDR_BODY + 9;
551 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
552 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
554 outhdr = talloc_zero_array(vector, uint8_t,
556 if (outhdr == NULL) {
557 return NT_STATUS_NO_MEMORY;
560 outbody = outhdr + SMB2_HDR_BODY;
562 current[0].iov_base = (void *)outhdr;
563 current[0].iov_len = SMB2_HDR_BODY;
565 current[1].iov_base = (void *)outbody;
566 current[1].iov_len = 8;
568 current[2].iov_base = NULL;
569 current[2].iov_len = 0;
571 /* setup the SMB2 header */
572 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
573 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
574 SSVAL(outhdr, SMB2_HDR_EPOCH, 0);
575 SIVAL(outhdr, SMB2_HDR_STATUS,
576 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
577 SSVAL(outhdr, SMB2_HDR_OPCODE,
578 SVAL(inhdr, SMB2_HDR_OPCODE));
579 SIVAL(outhdr, SMB2_HDR_FLAGS,
580 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
581 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
582 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
583 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
584 SIVAL(outhdr, SMB2_HDR_PID,
585 IVAL(inhdr, SMB2_HDR_PID));
586 SIVAL(outhdr, SMB2_HDR_TID,
587 IVAL(inhdr, SMB2_HDR_TID));
588 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
589 BVAL(inhdr, SMB2_HDR_SESSION_ID));
590 memset(outhdr + SMB2_HDR_SIGNATURE, 0, 16);
592 /* setup error body header */
593 SSVAL(outbody, 0x00, 0x08 + 1);
594 SSVAL(outbody, 0x02, 0);
595 SIVAL(outbody, 0x04, 0);
598 req->out.vector = vector;
599 req->out.vector_count = count;
601 /* setup the length of the NBT packet */
602 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
604 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
609 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
611 const char *location)
613 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
615 exit_server_cleanly(reason);
618 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
619 struct iovec *outvec,
620 const struct iovec *srcvec)
622 /* vec[0] is always boilerplate and must
623 * be allocated with size OUTVEC_ALLOC_SIZE. */
625 outvec[0].iov_base = talloc_memdup(ctx,
628 if (!outvec[0].iov_base) {
631 outvec[0].iov_len = SMB2_HDR_BODY;
634 * If this is a "standard" vec[1] of length 8,
635 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
636 * then duplicate this. Else use talloc_memdup().
639 if (srcvec[1].iov_len == 8 &&
640 srcvec[1].iov_base ==
641 ((uint8_t *)srcvec[0].iov_base) +
643 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
645 outvec[1].iov_len = 8;
647 outvec[1].iov_base = talloc_memdup(ctx,
650 if (!outvec[1].iov_base) {
653 outvec[1].iov_len = srcvec[1].iov_len;
657 * If this is a "standard" vec[2] of length 1,
658 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
659 * then duplicate this. Else use talloc_memdup().
662 if (srcvec[2].iov_base &&
664 if (srcvec[2].iov_base ==
665 ((uint8_t *)srcvec[0].iov_base) +
666 (OUTVEC_ALLOC_SIZE - 1) &&
667 srcvec[2].iov_len == 1) {
668 /* Common SMB2 error packet case. */
669 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
670 (OUTVEC_ALLOC_SIZE - 1);
672 outvec[2].iov_base = talloc_memdup(ctx,
675 if (!outvec[2].iov_base) {
679 outvec[2].iov_len = srcvec[2].iov_len;
681 outvec[2].iov_base = NULL;
682 outvec[2].iov_len = 0;
687 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
689 struct smbd_smb2_request *newreq = NULL;
690 struct iovec *outvec = NULL;
691 int count = req->out.vector_count;
694 newreq = smbd_smb2_request_allocate(req->sconn);
699 newreq->sconn = req->sconn;
700 newreq->session = req->session;
701 newreq->do_signing = req->do_signing;
702 newreq->current_idx = req->current_idx;
703 newreq->async = false;
704 newreq->cancelled = false;
705 /* Note we are leaving:
709 uninitialized as NULL here as
710 they're not used in the interim
711 response code. JRA. */
713 outvec = talloc_zero_array(newreq, struct iovec, count);
718 newreq->out.vector = outvec;
719 newreq->out.vector_count = count;
721 /* Setup the outvec's identically to req. */
722 outvec[0].iov_base = newreq->out.nbt_hdr;
723 outvec[0].iov_len = 4;
724 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
726 /* Setup the vectors identically to the ones in req. */
727 for (i = 1; i < count; i += 3) {
728 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
739 smb2_setup_nbt_length(newreq->out.vector,
740 newreq->out.vector_count);
745 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
747 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
750 uint8_t *outhdr = NULL;
751 struct smbd_smb2_request *nreq = NULL;
753 /* Create a new smb2 request we'll use
754 for the interim return. */
755 nreq = dup_smb2_req(req);
757 return NT_STATUS_NO_MEMORY;
760 /* Lose the last 3 out vectors. They're the
761 ones we'll be using for the async reply. */
762 nreq->out.vector_count -= 3;
764 smb2_setup_nbt_length(nreq->out.vector,
765 nreq->out.vector_count);
767 /* Step back to the previous reply. */
768 i = nreq->current_idx - 3;
769 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
770 /* And end the chain. */
771 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
773 /* Calculate outgoing credits */
774 smb2_calculate_credits(req, nreq);
776 /* Re-sign if needed. */
777 if (nreq->do_signing) {
779 status = smb2_signing_sign_pdu(nreq->session->session_key,
780 &nreq->out.vector[i], 3);
781 if (!NT_STATUS_IS_OK(status)) {
785 if (DEBUGLEVEL >= 10) {
786 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
787 (unsigned int)nreq->current_idx );
788 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
789 (unsigned int)nreq->out.vector_count );
790 print_req_vectors(nreq);
792 nreq->subreq = tstream_writev_queue_send(nreq,
793 nreq->sconn->smb2.event_ctx,
794 nreq->sconn->smb2.stream,
795 nreq->sconn->smb2.send_queue,
797 nreq->out.vector_count);
799 if (nreq->subreq == NULL) {
800 return NT_STATUS_NO_MEMORY;
803 tevent_req_set_callback(nreq->subreq,
804 smbd_smb2_request_writev_done,
810 struct smbd_smb2_request_pending_state {
811 struct smbd_server_connection *sconn;
812 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
813 struct iovec vector[3];
816 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
818 struct smbd_smb2_request_pending_state *state =
819 tevent_req_callback_data(subreq,
820 struct smbd_smb2_request_pending_state);
821 struct smbd_server_connection *sconn = state->sconn;
825 ret = tstream_writev_queue_recv(subreq, &sys_errno);
828 NTSTATUS status = map_nt_error_from_unix(sys_errno);
829 smbd_server_connection_terminate(sconn, nt_errstr(status));
836 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
837 struct tevent_req *subreq)
840 struct smbd_smb2_request_pending_state *state = NULL;
841 int i = req->current_idx;
842 uint8_t *reqhdr = NULL;
844 uint8_t *body = NULL;
846 uint64_t message_id = 0;
847 uint64_t async_id = 0;
848 struct iovec *outvec = NULL;
850 if (!tevent_req_is_in_progress(subreq)) {
854 req->subreq = subreq;
858 /* We're already async. */
862 if (req->in.vector_count > i + 3) {
864 * We're trying to go async in a compound
865 * request chain. This is not allowed.
866 * Cancel the outstanding request.
868 tevent_req_cancel(req->subreq);
869 return smbd_smb2_request_error(req,
870 NT_STATUS_INSUFFICIENT_RESOURCES);
873 if (DEBUGLEVEL >= 10) {
874 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
875 (unsigned int)req->current_idx );
876 print_req_vectors(req);
879 if (req->out.vector_count > 4) {
880 /* This is a compound reply. We
881 * must do an interim response
882 * followed by the async response
885 status = smb2_send_async_interim_response(req);
886 if (!NT_STATUS_IS_OK(status)) {
891 * We're splitting off the last SMB2
892 * request in a compound set, and the
893 * smb2_send_async_interim_response()
894 * call above just sent all the replies
895 * for the previous SMB2 requests in
896 * this compound set. So we're no longer
897 * in the "compound_related_in_progress"
898 * state, and this is no longer a compound
901 req->compound_related = false;
902 req->sconn->smb2.compound_related_in_progress = false;
905 /* Don't return an intermediate packet on a pipe read/write. */
906 if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
910 reqhdr = (uint8_t *)req->out.vector[i].iov_base;
911 flags = (IVAL(reqhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
912 message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
913 async_id = message_id; /* keep it simple for now... */
916 * What we send is identical to a smbd_smb2_request_error
917 * packet with an error status of STATUS_PENDING. Make use
918 * of this fact sometime when refactoring. JRA.
921 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
923 return NT_STATUS_NO_MEMORY;
925 state->sconn = req->sconn;
927 state->vector[0].iov_base = (void *)state->buf;
928 state->vector[0].iov_len = 4;
930 state->vector[1].iov_base = state->buf + 4;
931 state->vector[1].iov_len = SMB2_HDR_BODY;
933 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
934 state->vector[2].iov_len = 9;
936 smb2_setup_nbt_length(state->vector, 3);
938 hdr = (uint8_t *)state->vector[1].iov_base;
939 body = (uint8_t *)state->vector[2].iov_base;
941 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
942 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
943 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
944 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
945 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(reqhdr, SMB2_HDR_OPCODE));
947 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
948 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
949 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
950 SBVAL(hdr, SMB2_HDR_PID, async_id);
951 SBVAL(hdr, SMB2_HDR_SESSION_ID,
952 BVAL(reqhdr, SMB2_HDR_SESSION_ID));
953 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
955 SSVAL(body, 0x00, 0x08 + 1);
957 SCVAL(body, 0x02, 0);
958 SCVAL(body, 0x03, 0);
959 SIVAL(body, 0x04, 0);
960 /* Match W2K8R2... */
961 SCVAL(body, 0x08, 0x21);
963 /* Ensure we correctly go through crediting. Grant
964 the credits now, and zero credits on the final
966 smb2_set_operation_credit(req->sconn,
970 if (req->do_signing) {
971 status = smb2_signing_sign_pdu(req->session->session_key,
972 &state->vector[1], 2);
973 if (!NT_STATUS_IS_OK(status)) {
978 subreq = tstream_writev_queue_send(state,
979 req->sconn->smb2.event_ctx,
980 req->sconn->smb2.stream,
981 req->sconn->smb2.send_queue,
985 if (subreq == NULL) {
986 return NT_STATUS_NO_MEMORY;
989 tevent_req_set_callback(subreq,
990 smbd_smb2_request_pending_writev_done,
993 /* Note we're going async with this request. */
997 * Now manipulate req so that the outstanding async request
998 * is the only one left in the struct smbd_smb2_request.
1001 if (req->current_idx == 1) {
1002 /* There was only one. */
1006 /* Re-arrange the in.vectors. */
1007 req->in.vector[1] = req->in.vector[i];
1008 req->in.vector[2] = req->in.vector[i+1];
1009 req->in.vector[3] = req->in.vector[i+2];
1010 req->in.vector_count = 4;
1011 /* Reset the new in size. */
1012 smb2_setup_nbt_length(req->in.vector, 4);
1014 /* Now recreate the out.vectors. */
1015 outvec = talloc_zero_array(req, struct iovec, 4);
1017 return NT_STATUS_NO_MEMORY;
1020 /* 0 is always boilerplate and must
1021 * be of size 4 for the length field. */
1023 outvec[0].iov_base = req->out.nbt_hdr;
1024 outvec[0].iov_len = 4;
1025 SIVAL(req->out.nbt_hdr, 0, 0);
1027 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
1028 return NT_STATUS_NO_MEMORY;
1031 TALLOC_FREE(req->out.vector);
1033 req->out.vector = outvec;
1035 req->current_idx = 1;
1036 req->out.vector_count = 4;
1040 smb2_setup_nbt_length(req->out.vector,
1041 req->out.vector_count);
1043 /* Ensure our final reply matches the interim one. */
1044 reqhdr = (uint8_t *)req->out.vector[1].iov_base;
1045 SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1046 SBVAL(reqhdr, SMB2_HDR_PID, async_id);
1049 const uint8_t *inhdr =
1050 (const uint8_t *)req->in.vector[1].iov_base;
1051 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1053 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1054 (unsigned long long)async_id ));
1056 return NT_STATUS_OK;
1059 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1061 struct smbd_server_connection *sconn = req->sconn;
1062 struct smbd_smb2_request *cur;
1063 const uint8_t *inhdr;
1064 int i = req->current_idx;
1066 uint64_t search_message_id;
1067 uint64_t search_async_id;
1070 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1072 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1073 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1074 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1077 * we don't need the request anymore
1078 * cancel requests never have a response
1080 DLIST_REMOVE(req->sconn->smb2.requests, req);
1083 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1084 const uint8_t *outhdr;
1085 uint64_t message_id;
1088 i = cur->current_idx;
1090 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1092 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1093 async_id = BVAL(outhdr, SMB2_HDR_PID);
1095 if (flags & SMB2_HDR_FLAG_ASYNC) {
1096 if (search_async_id == async_id) {
1097 found_id = async_id;
1101 if (search_message_id == message_id) {
1102 found_id = message_id;
1108 if (cur && cur->subreq) {
1109 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1110 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1111 "cancel opcode[%s] mid %llu\n",
1112 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1113 (unsigned long long)found_id ));
1114 tevent_req_cancel(cur->subreq);
1117 return NT_STATUS_OK;
1120 /*************************************************************
1121 Ensure an incoming tid is a valid one for us to access.
1122 Change to the associated uid credentials and chdir to the
1123 valid tid directory.
1124 *************************************************************/
1126 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1128 const uint8_t *inhdr;
1129 const uint8_t *outhdr;
1130 int i = req->current_idx;
1133 struct smbd_smb2_tcon *tcon;
1134 bool chained_fixup = false;
1136 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1138 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1140 if (in_tid == (0xFFFFFFFF)) {
1143 * async request - fill in tid from
1144 * already setup out.vector[].iov_base.
1146 outhdr = (const uint8_t *)req->out.vector[i].iov_base;
1147 in_tid = IVAL(outhdr, SMB2_HDR_TID);
1150 * Chained request - fill in tid from
1151 * the previous request out.vector[].iov_base.
1153 outhdr = (const uint8_t *)req->out.vector[i-3].iov_base;
1154 in_tid = IVAL(outhdr, SMB2_HDR_TID);
1155 chained_fixup = true;
1159 /* lookup an existing session */
1160 p = idr_find(req->session->tcons.idtree, in_tid);
1162 return NT_STATUS_NETWORK_NAME_DELETED;
1164 tcon = talloc_get_type_abort(p, struct smbd_smb2_tcon);
1166 if (!change_to_user(tcon->compat_conn,req->session->vuid)) {
1167 return NT_STATUS_ACCESS_DENIED;
1170 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1171 if (!set_current_service(tcon->compat_conn, 0, true)) {
1172 return NT_STATUS_ACCESS_DENIED;
1177 if (chained_fixup) {
1178 /* Fix up our own outhdr. */
1179 outhdr = (const uint8_t *)req->out.vector[i].iov_base;
1180 SIVAL(discard_const_p(uint8_t, outhdr), SMB2_HDR_TID, in_tid);
1183 return NT_STATUS_OK;
1186 /*************************************************************
1187 Ensure an incoming session_id is a valid one for us to access.
1188 *************************************************************/
1190 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1192 const uint8_t *inhdr;
1193 const uint8_t *outhdr;
1194 int i = req->current_idx;
1195 uint64_t in_session_id;
1197 struct smbd_smb2_session *session;
1198 bool chained_fixup = false;
1200 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1202 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1204 if (in_session_id == (0xFFFFFFFFFFFFFFFFLL)) {
1207 * async request - fill in session_id from
1208 * already setup request out.vector[].iov_base.
1210 outhdr = (const uint8_t *)req->out.vector[i].iov_base;
1211 in_session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1214 * Chained request - fill in session_id from
1215 * the previous request out.vector[].iov_base.
1217 outhdr = (const uint8_t *)req->out.vector[i-3].iov_base;
1218 in_session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1219 chained_fixup = true;
1223 /* lookup an existing session */
1224 p = idr_find(req->sconn->smb2.sessions.idtree, in_session_id);
1226 return NT_STATUS_USER_SESSION_DELETED;
1228 session = talloc_get_type_abort(p, struct smbd_smb2_session);
1230 if (!NT_STATUS_IS_OK(session->status)) {
1231 return NT_STATUS_ACCESS_DENIED;
1234 set_current_user_info(session->session_info->unix_info->sanitized_username,
1235 session->session_info->unix_info->unix_name,
1236 session->session_info->info->domain_name);
1238 req->session = session;
1240 if (chained_fixup) {
1241 /* Fix up our own outhdr. */
1242 outhdr = (const uint8_t *)req->out.vector[i].iov_base;
1243 SBVAL(discard_const_p(uint8_t, outhdr), SMB2_HDR_SESSION_ID, in_session_id);
1245 return NT_STATUS_OK;
1248 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1250 const uint8_t *inhdr;
1251 int i = req->current_idx;
1256 NTSTATUS session_status;
1257 uint32_t allowed_flags;
1258 NTSTATUS return_value;
1260 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1262 /* TODO: verify more things */
1264 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1265 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1266 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1267 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1268 smb2_opcode_name(opcode),
1269 (unsigned long long)mid));
1271 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1272 SMB2_HDR_FLAG_SIGNED |
1274 if (opcode == SMB2_OP_CANCEL) {
1275 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1277 if ((flags & ~allowed_flags) != 0) {
1278 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1282 * Check if the client provided a valid session id,
1283 * if so smbd_smb2_request_check_session() calls
1284 * set_current_user_info().
1286 * As some command don't require a valid session id
1287 * we defer the check of the session_status
1289 session_status = smbd_smb2_request_check_session(req);
1291 req->do_signing = false;
1292 if (flags & SMB2_HDR_FLAG_SIGNED) {
1293 if (!NT_STATUS_IS_OK(session_status)) {
1294 return smbd_smb2_request_error(req, session_status);
1297 req->do_signing = true;
1298 status = smb2_signing_check_pdu(req->session->session_key,
1299 &req->in.vector[i], 3);
1300 if (!NT_STATUS_IS_OK(status)) {
1301 return smbd_smb2_request_error(req, status);
1303 } else if (req->session && req->session->do_signing) {
1304 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1307 if (flags & SMB2_HDR_FLAG_CHAINED) {
1309 * This check is mostly for giving the correct error code
1310 * for compounded requests.
1312 * TODO: we may need to move this after the session
1315 if (!NT_STATUS_IS_OK(req->next_status)) {
1316 return smbd_smb2_request_error(req, req->next_status);
1319 req->compat_chain_fsp = NULL;
1322 if (req->compound_related) {
1323 req->sconn->smb2.compound_related_in_progress = true;
1327 case SMB2_OP_NEGPROT:
1328 /* This call needs to be run as root */
1329 change_to_root_user();
1332 START_PROFILE(smb2_negprot);
1333 return_value = smbd_smb2_request_process_negprot(req);
1334 END_PROFILE(smb2_negprot);
1338 case SMB2_OP_SESSSETUP:
1339 /* This call needs to be run as root */
1340 change_to_root_user();
1343 START_PROFILE(smb2_sesssetup);
1344 return_value = smbd_smb2_request_process_sesssetup(req);
1345 END_PROFILE(smb2_sesssetup);
1349 case SMB2_OP_LOGOFF:
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 root */
1356 change_to_root_user();
1359 START_PROFILE(smb2_logoff);
1360 return_value = smbd_smb2_request_process_logoff(req);
1361 END_PROFILE(smb2_logoff);
1366 if (!NT_STATUS_IS_OK(session_status)) {
1367 return_value = smbd_smb2_request_error(req, session_status);
1372 * This call needs to be run as root.
1374 * smbd_smb2_request_process_tcon()
1375 * calls make_connection_snum(), which will call
1376 * change_to_user(), when needed.
1378 change_to_root_user();
1381 START_PROFILE(smb2_tcon);
1382 return_value = smbd_smb2_request_process_tcon(req);
1383 END_PROFILE(smb2_tcon);
1388 if (!NT_STATUS_IS_OK(session_status)) {
1389 return_value = smbd_smb2_request_error(req, session_status);
1393 * This call needs to be run as user.
1395 * smbd_smb2_request_check_tcon()
1396 * calls change_to_user() on success.
1398 status = smbd_smb2_request_check_tcon(req);
1399 if (!NT_STATUS_IS_OK(status)) {
1400 return_value = smbd_smb2_request_error(req, status);
1403 /* This call needs to be run as root */
1404 change_to_root_user();
1408 START_PROFILE(smb2_tdis);
1409 return_value = smbd_smb2_request_process_tdis(req);
1410 END_PROFILE(smb2_tdis);
1414 case SMB2_OP_CREATE:
1415 if (!NT_STATUS_IS_OK(session_status)) {
1416 return_value = smbd_smb2_request_error(req, session_status);
1420 * This call needs to be run as user.
1422 * smbd_smb2_request_check_tcon()
1423 * calls change_to_user() on success.
1425 status = smbd_smb2_request_check_tcon(req);
1426 if (!NT_STATUS_IS_OK(status)) {
1427 return_value = smbd_smb2_request_error(req, status);
1432 START_PROFILE(smb2_create);
1433 return_value = smbd_smb2_request_process_create(req);
1434 END_PROFILE(smb2_create);
1439 if (!NT_STATUS_IS_OK(session_status)) {
1440 return_value = smbd_smb2_request_error(req, session_status);
1444 * This call needs to be run as user.
1446 * smbd_smb2_request_check_tcon()
1447 * calls change_to_user() on success.
1449 status = smbd_smb2_request_check_tcon(req);
1450 if (!NT_STATUS_IS_OK(status)) {
1451 return_value = smbd_smb2_request_error(req, status);
1456 START_PROFILE(smb2_close);
1457 return_value = smbd_smb2_request_process_close(req);
1458 END_PROFILE(smb2_close);
1463 if (!NT_STATUS_IS_OK(session_status)) {
1464 return_value = smbd_smb2_request_error(req, session_status);
1468 * This call needs to be run as user.
1470 * smbd_smb2_request_check_tcon()
1471 * calls change_to_user() on success.
1473 status = smbd_smb2_request_check_tcon(req);
1474 if (!NT_STATUS_IS_OK(status)) {
1475 return_value = smbd_smb2_request_error(req, status);
1480 START_PROFILE(smb2_flush);
1481 return_value = smbd_smb2_request_process_flush(req);
1482 END_PROFILE(smb2_flush);
1487 if (!NT_STATUS_IS_OK(session_status)) {
1488 return_value = smbd_smb2_request_error(req, session_status);
1492 * This call needs to be run as user.
1494 * smbd_smb2_request_check_tcon()
1495 * calls change_to_user() on success.
1497 status = smbd_smb2_request_check_tcon(req);
1498 if (!NT_STATUS_IS_OK(status)) {
1499 return_value = smbd_smb2_request_error(req, status);
1504 START_PROFILE(smb2_read);
1505 return_value = smbd_smb2_request_process_read(req);
1506 END_PROFILE(smb2_read);
1511 if (!NT_STATUS_IS_OK(session_status)) {
1512 return_value = smbd_smb2_request_error(req, session_status);
1516 * This call needs to be run as user.
1518 * smbd_smb2_request_check_tcon()
1519 * calls change_to_user() on success.
1521 status = smbd_smb2_request_check_tcon(req);
1522 if (!NT_STATUS_IS_OK(status)) {
1523 return_value = smbd_smb2_request_error(req, status);
1528 START_PROFILE(smb2_write);
1529 return_value = smbd_smb2_request_process_write(req);
1530 END_PROFILE(smb2_write);
1535 if (!NT_STATUS_IS_OK(session_status)) {
1536 /* Too ugly to live ? JRA. */
1537 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1538 session_status = NT_STATUS_FILE_CLOSED;
1540 return_value = smbd_smb2_request_error(req, session_status);
1544 * This call needs to be run as user.
1546 * smbd_smb2_request_check_tcon()
1547 * calls change_to_user() on success.
1549 status = smbd_smb2_request_check_tcon(req);
1550 if (!NT_STATUS_IS_OK(status)) {
1551 /* Too ugly to live ? JRA. */
1552 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1553 status = NT_STATUS_FILE_CLOSED;
1555 return_value = smbd_smb2_request_error(req, status);
1560 START_PROFILE(smb2_lock);
1561 return_value = smbd_smb2_request_process_lock(req);
1562 END_PROFILE(smb2_lock);
1567 if (!NT_STATUS_IS_OK(session_status)) {
1568 return_value = smbd_smb2_request_error(req, session_status);
1572 * This call needs to be run as user.
1574 * smbd_smb2_request_check_tcon()
1575 * calls change_to_user() on success.
1577 status = smbd_smb2_request_check_tcon(req);
1578 if (!NT_STATUS_IS_OK(status)) {
1579 return_value = smbd_smb2_request_error(req, status);
1584 START_PROFILE(smb2_ioctl);
1585 return_value = smbd_smb2_request_process_ioctl(req);
1586 END_PROFILE(smb2_ioctl);
1590 case SMB2_OP_CANCEL:
1592 * This call needs to be run as root
1594 * That is what we also do in the SMB1 case.
1596 change_to_root_user();
1599 START_PROFILE(smb2_cancel);
1600 return_value = smbd_smb2_request_process_cancel(req);
1601 END_PROFILE(smb2_cancel);
1605 case SMB2_OP_KEEPALIVE:
1606 /* This call needs to be run as root */
1607 change_to_root_user();
1610 START_PROFILE(smb2_keepalive);
1611 return_value = smbd_smb2_request_process_keepalive(req);
1612 END_PROFILE(smb2_keepalive);
1617 if (!NT_STATUS_IS_OK(session_status)) {
1618 return_value = smbd_smb2_request_error(req, session_status);
1622 * This call needs to be run as user.
1624 * smbd_smb2_request_check_tcon()
1625 * calls change_to_user() on success.
1627 status = smbd_smb2_request_check_tcon(req);
1628 if (!NT_STATUS_IS_OK(status)) {
1629 return_value = smbd_smb2_request_error(req, status);
1634 START_PROFILE(smb2_find);
1635 return_value = smbd_smb2_request_process_find(req);
1636 END_PROFILE(smb2_find);
1640 case SMB2_OP_NOTIFY:
1641 if (!NT_STATUS_IS_OK(session_status)) {
1642 return_value = smbd_smb2_request_error(req, session_status);
1646 * This call needs to be run as user.
1648 * smbd_smb2_request_check_tcon()
1649 * calls change_to_user() on success.
1651 status = smbd_smb2_request_check_tcon(req);
1652 if (!NT_STATUS_IS_OK(status)) {
1653 return_value = smbd_smb2_request_error(req, status);
1658 START_PROFILE(smb2_notify);
1659 return_value = smbd_smb2_request_process_notify(req);
1660 END_PROFILE(smb2_notify);
1664 case SMB2_OP_GETINFO:
1665 if (!NT_STATUS_IS_OK(session_status)) {
1666 return_value = smbd_smb2_request_error(req, session_status);
1670 * This call needs to be run as user.
1672 * smbd_smb2_request_check_tcon()
1673 * calls change_to_user() on success.
1675 status = smbd_smb2_request_check_tcon(req);
1676 if (!NT_STATUS_IS_OK(status)) {
1677 return_value = smbd_smb2_request_error(req, status);
1682 START_PROFILE(smb2_getinfo);
1683 return_value = smbd_smb2_request_process_getinfo(req);
1684 END_PROFILE(smb2_getinfo);
1688 case SMB2_OP_SETINFO:
1689 if (!NT_STATUS_IS_OK(session_status)) {
1690 return_value = smbd_smb2_request_error(req, session_status);
1694 * This call needs to be run as user.
1696 * smbd_smb2_request_check_tcon()
1697 * calls change_to_user() on success.
1699 status = smbd_smb2_request_check_tcon(req);
1700 if (!NT_STATUS_IS_OK(status)) {
1701 return_value = smbd_smb2_request_error(req, status);
1706 START_PROFILE(smb2_setinfo);
1707 return_value = smbd_smb2_request_process_setinfo(req);
1708 END_PROFILE(smb2_setinfo);
1713 if (!NT_STATUS_IS_OK(session_status)) {
1714 return_value = smbd_smb2_request_error(req, session_status);
1718 * This call needs to be run as user.
1720 * smbd_smb2_request_check_tcon()
1721 * calls change_to_user() on success.
1723 status = smbd_smb2_request_check_tcon(req);
1724 if (!NT_STATUS_IS_OK(status)) {
1725 return_value = smbd_smb2_request_error(req, status);
1730 START_PROFILE(smb2_break);
1731 return_value = smbd_smb2_request_process_break(req);
1732 END_PROFILE(smb2_break);
1737 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1740 return return_value;
1743 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1745 struct tevent_req *subreq;
1746 int i = req->current_idx;
1750 req->current_idx += 3;
1752 if (req->current_idx < req->out.vector_count) {
1754 * We must process the remaining compound
1755 * SMB2 requests before any new incoming SMB2
1756 * requests. This is because incoming SMB2
1757 * requests may include a cancel for a
1758 * compound request we haven't processed
1761 struct tevent_immediate *im = tevent_create_immediate(req);
1763 return NT_STATUS_NO_MEMORY;
1765 tevent_schedule_immediate(im,
1766 req->sconn->smb2.event_ctx,
1767 smbd_smb2_request_dispatch_immediate,
1769 return NT_STATUS_OK;
1772 if (req->compound_related) {
1773 req->sconn->smb2.compound_related_in_progress = false;
1776 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1778 /* Set credit for this operation (zero credits if this
1779 is a final reply for an async operation). */
1780 smb2_set_operation_credit(req->sconn,
1782 &req->out.vector[i]);
1784 if (req->do_signing) {
1786 status = smb2_signing_sign_pdu(req->session->session_key,
1787 &req->out.vector[i], 3);
1788 if (!NT_STATUS_IS_OK(status)) {
1793 if (DEBUGLEVEL >= 10) {
1794 dbgtext("smbd_smb2_request_reply: sending...\n");
1795 print_req_vectors(req);
1798 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1799 if (req->out.vector_count == 4 &&
1800 req->out.vector[3].iov_base == NULL &&
1801 req->out.vector[3].iov_len != 0) {
1802 /* Dynamic part is NULL. Chop it off,
1803 We're going to send it via sendfile. */
1804 req->out.vector_count -= 1;
1807 subreq = tstream_writev_queue_send(req,
1808 req->sconn->smb2.event_ctx,
1809 req->sconn->smb2.stream,
1810 req->sconn->smb2.send_queue,
1812 req->out.vector_count);
1813 if (subreq == NULL) {
1814 return NT_STATUS_NO_MEMORY;
1816 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1818 * We're done with this request -
1819 * move it off the "being processed" queue.
1821 DLIST_REMOVE(req->sconn->smb2.requests, req);
1823 return NT_STATUS_OK;
1826 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
1828 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1829 struct tevent_immediate *im,
1832 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1833 struct smbd_smb2_request);
1834 struct smbd_server_connection *sconn = req->sconn;
1839 if (DEBUGLEVEL >= 10) {
1840 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1841 req->current_idx, req->in.vector_count));
1842 print_req_vectors(req);
1845 status = smbd_smb2_request_dispatch(req);
1846 if (!NT_STATUS_IS_OK(status)) {
1847 smbd_server_connection_terminate(sconn, nt_errstr(status));
1851 status = smbd_smb2_request_next_incoming(sconn);
1852 if (!NT_STATUS_IS_OK(status)) {
1853 smbd_server_connection_terminate(sconn, nt_errstr(status));
1858 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1860 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1861 struct smbd_smb2_request);
1862 struct smbd_server_connection *sconn = req->sconn;
1867 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1868 TALLOC_FREE(subreq);
1871 status = map_nt_error_from_unix(sys_errno);
1872 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1873 nt_errstr(status)));
1874 smbd_server_connection_terminate(sconn, nt_errstr(status));
1878 status = smbd_smb2_request_next_incoming(sconn);
1879 if (!NT_STATUS_IS_OK(status)) {
1880 smbd_server_connection_terminate(sconn, nt_errstr(status));
1885 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1887 DATA_BLOB body, DATA_BLOB *dyn,
1888 const char *location)
1891 int i = req->current_idx;
1892 uint32_t next_command_ofs;
1894 DEBUG(10,("smbd_smb2_request_done_ex: "
1895 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1896 i, nt_errstr(status), (unsigned int)body.length,
1898 (unsigned int)(dyn ? dyn->length : 0),
1901 if (body.length < 2) {
1902 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1905 if ((body.length % 2) != 0) {
1906 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1909 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1911 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1912 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1914 req->out.vector[i+1].iov_base = (void *)body.data;
1915 req->out.vector[i+1].iov_len = body.length;
1918 req->out.vector[i+2].iov_base = (void *)dyn->data;
1919 req->out.vector[i+2].iov_len = dyn->length;
1921 req->out.vector[i+2].iov_base = NULL;
1922 req->out.vector[i+2].iov_len = 0;
1925 /* see if we need to recalculate the offset to the next response */
1926 if (next_command_ofs > 0) {
1927 next_command_ofs = SMB2_HDR_BODY;
1928 next_command_ofs += req->out.vector[i+1].iov_len;
1929 next_command_ofs += req->out.vector[i+2].iov_len;
1932 if ((next_command_ofs % 8) != 0) {
1933 size_t pad_size = 8 - (next_command_ofs % 8);
1934 if (req->out.vector[i+2].iov_len == 0) {
1936 * if the dyn buffer is empty
1937 * we can use it to add padding
1941 pad = talloc_zero_array(req->out.vector,
1944 return smbd_smb2_request_error(req,
1945 NT_STATUS_NO_MEMORY);
1948 req->out.vector[i+2].iov_base = (void *)pad;
1949 req->out.vector[i+2].iov_len = pad_size;
1952 * For now we copy the dynamic buffer
1953 * and add the padding to the new buffer
1960 old_size = req->out.vector[i+2].iov_len;
1961 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
1963 new_size = old_size + pad_size;
1964 new_dyn = talloc_zero_array(req->out.vector,
1966 if (new_dyn == NULL) {
1967 return smbd_smb2_request_error(req,
1968 NT_STATUS_NO_MEMORY);
1971 memcpy(new_dyn, old_dyn, old_size);
1972 memset(new_dyn + old_size, 0, pad_size);
1974 req->out.vector[i+2].iov_base = (void *)new_dyn;
1975 req->out.vector[i+2].iov_len = new_size;
1977 next_command_ofs += pad_size;
1980 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1982 return smbd_smb2_request_reply(req);
1985 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
1988 const char *location)
1991 int i = req->current_idx;
1992 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
1994 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1995 i, nt_errstr(status), info ? " +info" : "",
1998 body.data = outhdr + SMB2_HDR_BODY;
2000 SSVAL(body.data, 0, 9);
2003 SIVAL(body.data, 0x04, info->length);
2005 /* Allocated size of req->out.vector[i].iov_base
2006 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2007 * 1 byte without having to do an alloc.
2009 info = talloc_zero_array(req->out.vector,
2013 return NT_STATUS_NO_MEMORY;
2015 info->data = ((uint8_t *)outhdr) +
2016 OUTVEC_ALLOC_SIZE - 1;
2018 SCVAL(info->data, 0, 0);
2022 * if a request fails, all other remaining
2023 * compounded requests should fail too
2025 req->next_status = NT_STATUS_INVALID_PARAMETER;
2027 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2031 struct smbd_smb2_send_oplock_break_state {
2032 struct smbd_server_connection *sconn;
2033 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2034 struct iovec vector;
2037 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2039 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2040 uint64_t file_id_persistent,
2041 uint64_t file_id_volatile,
2042 uint8_t oplock_level)
2044 struct smbd_smb2_send_oplock_break_state *state;
2045 struct tevent_req *subreq;
2049 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2050 if (state == NULL) {
2051 return NT_STATUS_NO_MEMORY;
2053 state->sconn = sconn;
2055 state->vector.iov_base = (void *)state->buf;
2056 state->vector.iov_len = sizeof(state->buf);
2058 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2059 hdr = state->buf + 4;
2060 body = hdr + SMB2_HDR_BODY;
2062 SIVAL(hdr, 0, SMB2_MAGIC);
2063 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2064 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2065 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2066 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2067 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2068 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2069 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2070 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2071 SIVAL(hdr, SMB2_HDR_PID, 0);
2072 SIVAL(hdr, SMB2_HDR_TID, 0);
2073 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2074 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2076 SSVAL(body, 0x00, 0x18);
2078 SCVAL(body, 0x02, oplock_level);
2079 SCVAL(body, 0x03, 0); /* reserved */
2080 SIVAL(body, 0x04, 0); /* reserved */
2081 SBVAL(body, 0x08, file_id_persistent);
2082 SBVAL(body, 0x10, file_id_volatile);
2084 subreq = tstream_writev_queue_send(state,
2085 sconn->smb2.event_ctx,
2087 sconn->smb2.send_queue,
2089 if (subreq == NULL) {
2090 return NT_STATUS_NO_MEMORY;
2092 tevent_req_set_callback(subreq,
2093 smbd_smb2_oplock_break_writev_done,
2096 return NT_STATUS_OK;
2099 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2101 struct smbd_smb2_send_oplock_break_state *state =
2102 tevent_req_callback_data(subreq,
2103 struct smbd_smb2_send_oplock_break_state);
2104 struct smbd_server_connection *sconn = state->sconn;
2108 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2109 TALLOC_FREE(subreq);
2111 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2112 smbd_server_connection_terminate(sconn, nt_errstr(status));
2119 struct smbd_smb2_request_read_state {
2121 bool asked_for_header;
2122 struct smbd_smb2_request *smb2_req;
2125 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2127 TALLOC_CTX *mem_ctx,
2128 struct iovec **_vector,
2130 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2132 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2133 struct tevent_context *ev,
2134 struct smbd_server_connection *sconn)
2136 struct tevent_req *req;
2137 struct smbd_smb2_request_read_state *state;
2138 struct tevent_req *subreq;
2140 req = tevent_req_create(mem_ctx, &state,
2141 struct smbd_smb2_request_read_state);
2146 state->asked_for_header = false;
2148 state->smb2_req = smbd_smb2_request_allocate(state);
2149 if (tevent_req_nomem(state->smb2_req, req)) {
2150 return tevent_req_post(req, ev);
2152 state->smb2_req->sconn = sconn;
2154 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2155 sconn->smb2.recv_queue,
2156 smbd_smb2_request_next_vector,
2158 if (tevent_req_nomem(subreq, req)) {
2159 return tevent_req_post(req, ev);
2161 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2166 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2168 TALLOC_CTX *mem_ctx,
2169 struct iovec **_vector,
2172 struct smbd_smb2_request_read_state *state =
2173 talloc_get_type_abort(private_data,
2174 struct smbd_smb2_request_read_state);
2175 struct smbd_smb2_request *req = state->smb2_req;
2176 struct iovec *vector;
2177 int idx = req->in.vector_count;
2179 uint8_t *buf = NULL;
2181 if (req->in.vector_count == 0) {
2183 * first we need to get the NBT header
2185 req->in.vector = talloc_array(req, struct iovec,
2186 req->in.vector_count + 1);
2187 if (req->in.vector == NULL) {
2190 req->in.vector_count += 1;
2192 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2193 req->in.vector[idx].iov_len = 4;
2195 vector = talloc_array(mem_ctx, struct iovec, 1);
2196 if (vector == NULL) {
2200 vector[0] = req->in.vector[idx];
2207 if (req->in.vector_count == 1) {
2209 * Now we analyze the NBT header
2211 state->missing = smb2_len(req->in.vector[0].iov_base);
2213 if (state->missing == 0) {
2214 /* if there're no remaining bytes, we're done */
2220 req->in.vector = talloc_realloc(req, req->in.vector,
2222 req->in.vector_count + 1);
2223 if (req->in.vector == NULL) {
2226 req->in.vector_count += 1;
2228 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2230 * it's a special NBT message,
2231 * so get all remaining bytes
2233 len = state->missing;
2234 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2236 * it's an invalid message, just read what we can get
2237 * and let the caller handle the error
2239 len = state->missing;
2242 * We assume it's a SMB2 request,
2243 * and we first get the header and the
2244 * first 2 bytes (the struct size) of the body
2246 len = SMB2_HDR_BODY + 2;
2248 state->asked_for_header = true;
2251 state->missing -= len;
2253 buf = talloc_array(req->in.vector, uint8_t, len);
2258 req->in.vector[idx].iov_base = (void *)buf;
2259 req->in.vector[idx].iov_len = len;
2261 vector = talloc_array(mem_ctx, struct iovec, 1);
2262 if (vector == NULL) {
2266 vector[0] = req->in.vector[idx];
2273 if (state->missing == 0) {
2274 /* if there're no remaining bytes, we're done */
2280 if (state->asked_for_header) {
2283 size_t next_command_ofs;
2288 bool invalid = false;
2290 state->asked_for_header = false;
2293 * We got the SMB2 header and the first 2 bytes
2294 * of the body. We fix the size to just the header
2295 * and manually copy the 2 first bytes to the body section
2297 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2298 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2300 /* allocate vectors for body and dynamic areas */
2301 req->in.vector = talloc_realloc(req, req->in.vector,
2303 req->in.vector_count + 2);
2304 if (req->in.vector == NULL) {
2307 req->in.vector_count += 2;
2309 full_size = state->missing + SMB2_HDR_BODY + 2;
2310 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2311 body_size = SVAL(hdr, SMB2_HDR_BODY);
2313 if (next_command_ofs != 0) {
2314 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2316 * this is invalid, just return a zero
2317 * body and let the caller deal with the error
2320 } else if (next_command_ofs > full_size) {
2322 * this is invalid, just return a zero
2323 * body and let the caller deal with the error
2327 full_size = next_command_ofs;
2332 if (body_size < 2) {
2334 * this is invalid, just return a zero
2335 * body and let the caller deal with the error
2341 * Mask out the lowest bit, the "dynamic" part
2346 if (body_size > (full_size - SMB2_HDR_BODY)) {
2348 * this is invalid, just return a zero
2349 * body and let the caller deal with the error
2356 /* the caller should check this */
2360 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2362 state->missing -= (body_size - 2) + dyn_size;
2364 body = talloc_array(req->in.vector, uint8_t, body_size);
2369 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2374 req->in.vector[idx].iov_base = (void *)body;
2375 req->in.vector[idx].iov_len = body_size;
2376 req->in.vector[idx+1].iov_base = (void *)dyn;
2377 req->in.vector[idx+1].iov_len = dyn_size;
2379 vector = talloc_array(mem_ctx, struct iovec, 2);
2380 if (vector == NULL) {
2385 * the first 2 bytes of the body were already fetched
2386 * together with the header
2388 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2389 vector[0].iov_base = body + 2;
2390 vector[0].iov_len = body_size - 2;
2392 vector[1] = req->in.vector[idx+1];
2400 * when we endup here, we're looking for a new SMB2 request
2401 * next. And we ask for its header and the first 2 bytes of
2402 * the body (like we did for the first SMB2 request).
2405 req->in.vector = talloc_realloc(req, req->in.vector,
2407 req->in.vector_count + 1);
2408 if (req->in.vector == NULL) {
2411 req->in.vector_count += 1;
2414 * We assume it's a SMB2 request,
2415 * and we first get the header and the
2416 * first 2 bytes (the struct size) of the body
2418 len = SMB2_HDR_BODY + 2;
2420 if (len > state->missing) {
2421 /* let the caller handle the error */
2422 len = state->missing;
2425 state->missing -= len;
2426 state->asked_for_header = true;
2428 buf = talloc_array(req->in.vector, uint8_t, len);
2433 req->in.vector[idx].iov_base = (void *)buf;
2434 req->in.vector[idx].iov_len = len;
2436 vector = talloc_array(mem_ctx, struct iovec, 1);
2437 if (vector == NULL) {
2441 vector[0] = req->in.vector[idx];
2448 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2450 struct tevent_req *req =
2451 tevent_req_callback_data(subreq,
2457 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2459 status = map_nt_error_from_unix(sys_errno);
2460 tevent_req_nterror(req, status);
2464 tevent_req_done(req);
2467 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2468 TALLOC_CTX *mem_ctx,
2469 struct smbd_smb2_request **_smb2_req)
2471 struct smbd_smb2_request_read_state *state =
2472 tevent_req_data(req,
2473 struct smbd_smb2_request_read_state);
2476 if (tevent_req_is_nterror(req, &status)) {
2477 tevent_req_received(req);
2481 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2482 *_smb2_req = state->smb2_req;
2483 tevent_req_received(req);
2484 return NT_STATUS_OK;
2487 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2489 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2491 size_t max_send_queue_len;
2492 size_t cur_send_queue_len;
2493 struct tevent_req *subreq;
2495 if (sconn->smb2.compound_related_in_progress) {
2497 * Can't read another until the related
2500 return NT_STATUS_OK;
2503 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2505 * if there is already a smbd_smb2_request_read
2506 * pending, we are done.
2508 return NT_STATUS_OK;
2511 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2512 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2514 if (cur_send_queue_len > max_send_queue_len) {
2516 * if we have a lot of requests to send,
2517 * we wait until they are on the wire until we
2518 * ask for the next request.
2520 return NT_STATUS_OK;
2523 /* ask for the next request */
2524 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2525 if (subreq == NULL) {
2526 return NT_STATUS_NO_MEMORY;
2528 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2530 return NT_STATUS_OK;
2533 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2534 const uint8_t *inbuf, size_t size)
2537 struct smbd_smb2_request *req = NULL;
2539 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2540 (unsigned int)size));
2542 status = smbd_initialize_smb2(sconn);
2543 if (!NT_STATUS_IS_OK(status)) {
2544 smbd_server_connection_terminate(sconn, nt_errstr(status));
2548 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2549 if (!NT_STATUS_IS_OK(status)) {
2550 smbd_server_connection_terminate(sconn, nt_errstr(status));
2554 status = smbd_smb2_request_setup_out(req);
2555 if (!NT_STATUS_IS_OK(status)) {
2556 smbd_server_connection_terminate(sconn, nt_errstr(status));
2560 status = smbd_smb2_request_dispatch(req);
2561 if (!NT_STATUS_IS_OK(status)) {
2562 smbd_server_connection_terminate(sconn, nt_errstr(status));
2566 status = smbd_smb2_request_next_incoming(sconn);
2567 if (!NT_STATUS_IS_OK(status)) {
2568 smbd_server_connection_terminate(sconn, nt_errstr(status));
2572 sconn->num_requests++;
2575 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2577 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2578 struct smbd_server_connection);
2580 struct smbd_smb2_request *req = NULL;
2582 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2583 TALLOC_FREE(subreq);
2584 if (!NT_STATUS_IS_OK(status)) {
2585 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2586 nt_errstr(status)));
2587 smbd_server_connection_terminate(sconn, nt_errstr(status));
2591 if (req->in.nbt_hdr[0] != 0x00) {
2592 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2593 req->in.nbt_hdr[0]));
2598 req->current_idx = 1;
2600 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2601 req->current_idx, req->in.vector_count));
2603 status = smbd_smb2_request_validate(req);
2604 if (!NT_STATUS_IS_OK(status)) {
2605 smbd_server_connection_terminate(sconn, nt_errstr(status));
2609 status = smbd_smb2_request_setup_out(req);
2610 if (!NT_STATUS_IS_OK(status)) {
2611 smbd_server_connection_terminate(sconn, nt_errstr(status));
2615 status = smbd_smb2_request_dispatch(req);
2616 if (!NT_STATUS_IS_OK(status)) {
2617 smbd_server_connection_terminate(sconn, nt_errstr(status));
2622 status = smbd_smb2_request_next_incoming(sconn);
2623 if (!NT_STATUS_IS_OK(status)) {
2624 smbd_server_connection_terminate(sconn, nt_errstr(status));
2628 sconn->num_requests++;
2630 /* The timeout_processing function isn't run nearly
2631 often enough to implement 'max log size' without
2632 overrunning the size of the file by many megabytes.
2633 This is especially true if we are running at debug
2634 level 10. Checking every 50 SMB2s is a nice
2635 tradeoff of performance vs log file size overrun. */
2637 if ((sconn->num_requests % 50) == 0 &&
2638 need_to_check_log_size()) {
2639 change_to_root_user();