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 req->last_session_id = UINT64_MAX;
213 req->last_tid = UINT32_MAX;
215 talloc_set_destructor(parent, smbd_smb2_request_parent_destructor);
216 talloc_set_destructor(req, smbd_smb2_request_destructor);
221 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
222 const uint8_t *inbuf, size_t size,
223 struct smbd_smb2_request **_req)
225 struct smbd_smb2_request *req;
226 uint32_t protocol_version;
227 const uint8_t *inhdr = NULL;
230 uint32_t next_command_ofs;
232 if (size < (4 + SMB2_HDR_BODY + 2)) {
233 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
234 return NT_STATUS_INVALID_PARAMETER;
239 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
240 if (protocol_version != SMB2_MAGIC) {
241 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
243 return NT_STATUS_INVALID_PARAMETER;
246 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
247 if (cmd != SMB2_OP_NEGPROT) {
248 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
250 return NT_STATUS_INVALID_PARAMETER;
253 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
254 if (next_command_ofs != 0) {
255 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
257 return NT_STATUS_INVALID_PARAMETER;
260 req = smbd_smb2_request_allocate(sconn);
262 return NT_STATUS_NO_MEMORY;
266 talloc_steal(req, inbuf);
268 req->in.vector = talloc_array(req, struct iovec, 4);
269 if (req->in.vector == NULL) {
271 return NT_STATUS_NO_MEMORY;
273 req->in.vector_count = 4;
275 memcpy(req->in.nbt_hdr, inbuf, 4);
278 req->in.vector[0].iov_base = discard_const_p(void, req->in.nbt_hdr);
279 req->in.vector[0].iov_len = 4;
280 ofs += req->in.vector[0].iov_len;
282 req->in.vector[1].iov_base = discard_const_p(void, (inbuf + ofs));
283 req->in.vector[1].iov_len = SMB2_HDR_BODY;
284 ofs += req->in.vector[1].iov_len;
286 req->in.vector[2].iov_base = discard_const_p(void, (inbuf + ofs));
287 req->in.vector[2].iov_len = SVAL(inbuf, ofs) & 0xFFFE;
288 ofs += req->in.vector[2].iov_len;
291 return NT_STATUS_INVALID_PARAMETER;
294 req->in.vector[3].iov_base = discard_const_p(void, (inbuf + ofs));
295 req->in.vector[3].iov_len = size - ofs;
296 ofs += req->in.vector[3].iov_len;
298 req->current_idx = 1;
304 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
305 const uint8_t *inhdr)
307 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
308 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
309 uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
310 unsigned int bitmap_offset;
312 if (opcode == SMB2_OP_CANCEL) {
313 /* SMB2_CANCEL requests by definition resend messageids. */
317 if (message_id < sconn->smb2.seqnum_low ||
318 message_id > (sconn->smb2.seqnum_low +
319 (sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR))) {
320 DEBUG(0,("smb2_validate_message_id: bad message_id "
321 "%llu (low = %llu, max = %lu)\n",
322 (unsigned long long)message_id,
323 (unsigned long long)sconn->smb2.seqnum_low,
324 (unsigned long)sconn->smb2.max_credits ));
328 if (sconn->smb2.credits_granted == 0) {
329 DEBUG(0,("smb2_validate_message_id: client used more "
330 "credits than granted message_id (%llu)\n",
331 (unsigned long long)message_id));
335 /* client just used a credit. */
336 sconn->smb2.credits_granted -= 1;
338 /* Mark the message_id as seen in the bitmap. */
339 bitmap_offset = (unsigned int)(message_id %
340 (uint64_t)(sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR));
341 if (bitmap_query(credits_bm, bitmap_offset)) {
342 DEBUG(0,("smb2_validate_message_id: duplicate message_id "
343 "%llu (bm offset %u)\n",
344 (unsigned long long)message_id,
348 bitmap_set(credits_bm, bitmap_offset);
350 if (message_id == sconn->smb2.seqnum_low + 1) {
351 /* Move the window forward by all the message_id's
353 while (bitmap_query(credits_bm, bitmap_offset)) {
354 DEBUG(10,("smb2_validate_message_id: clearing "
355 "id %llu (position %u) from bitmap\n",
356 (unsigned long long)(sconn->smb2.seqnum_low + 1),
358 bitmap_clear(credits_bm, bitmap_offset);
359 sconn->smb2.seqnum_low += 1;
360 bitmap_offset = (bitmap_offset + 1) %
361 (sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR);
368 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
373 count = req->in.vector_count;
376 /* It's not a SMB2 request */
377 return NT_STATUS_INVALID_PARAMETER;
380 for (idx=1; idx < count; idx += 3) {
381 const uint8_t *inhdr = NULL;
384 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
385 return NT_STATUS_INVALID_PARAMETER;
388 if (req->in.vector[idx+1].iov_len < 2) {
389 return NT_STATUS_INVALID_PARAMETER;
392 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
394 /* Check the SMB2 header */
395 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
396 return NT_STATUS_INVALID_PARAMETER;
399 if (!smb2_validate_message_id(req->sconn, inhdr)) {
400 return NT_STATUS_INVALID_PARAMETER;
403 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
406 * the 1st request should never have the
407 * SMB2_HDR_FLAG_CHAINED flag set
409 if (flags & SMB2_HDR_FLAG_CHAINED) {
410 req->next_status = NT_STATUS_INVALID_PARAMETER;
413 } else if (idx == 4) {
415 * the 2nd request triggers related vs. unrelated
416 * compounded requests
418 if (flags & SMB2_HDR_FLAG_CHAINED) {
419 req->compound_related = true;
421 } else if (idx > 4) {
424 * It seems the this tests are wrong
425 * see the SMB2-COMPOUND test
429 * all other requests should match the 2nd one
431 if (flags & SMB2_HDR_FLAG_CHAINED) {
432 if (!req->compound_related) {
434 NT_STATUS_INVALID_PARAMETER;
438 if (req->compound_related) {
440 NT_STATUS_INVALID_PARAMETER;
451 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
452 const struct iovec *in_vector,
453 struct iovec *out_vector)
455 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
456 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
457 uint16_t credits_requested;
459 uint16_t credits_granted = 0;
461 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
462 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
464 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
466 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
468 * In case we already send an async interim
469 * response, we should not grant
470 * credits on the final response.
472 credits_requested = 0;
475 if (credits_requested) {
476 uint16_t modified_credits_requested;
480 * Split up max_credits into 1/16ths, and then scale
481 * the requested credits by how many 16ths have been
482 * currently granted. Less than 1/16th == grant all
483 * requested (100%), scale down as more have been
484 * granted. Never ask for less than 1 as the client
485 * asked for at least 1. JRA.
488 multiplier = 16 - (((sconn->smb2.credits_granted * 16) / sconn->smb2.max_credits) % 16);
490 modified_credits_requested = (multiplier * credits_requested) / 16;
491 if (modified_credits_requested == 0) {
492 modified_credits_requested = 1;
495 /* Remember what we gave out. */
496 credits_granted = MIN(modified_credits_requested,
497 (sconn->smb2.max_credits - sconn->smb2.credits_granted));
500 if (credits_granted == 0 && sconn->smb2.credits_granted == 0) {
501 /* First negprot packet, or ensure the client credits can
502 never drop to zero. */
506 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
507 sconn->smb2.credits_granted += credits_granted;
509 DEBUG(10,("smb2_set_operation_credit: requested %u, "
510 "granted %u, total granted %u\n",
511 (unsigned int)credits_requested,
512 (unsigned int)credits_granted,
513 (unsigned int)sconn->smb2.credits_granted ));
516 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
517 struct smbd_smb2_request *outreq)
521 count = outreq->out.vector_count;
523 for (idx=1; idx < count; idx += 3) {
524 smb2_set_operation_credit(outreq->sconn,
525 &inreq->in.vector[idx],
526 &outreq->out.vector[idx]);
530 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
532 struct iovec *vector;
536 count = req->in.vector_count;
537 vector = talloc_zero_array(req, struct iovec, count);
538 if (vector == NULL) {
539 return NT_STATUS_NO_MEMORY;
542 vector[0].iov_base = req->out.nbt_hdr;
543 vector[0].iov_len = 4;
544 SIVAL(req->out.nbt_hdr, 0, 0);
546 for (idx=1; idx < count; idx += 3) {
547 const uint8_t *inhdr = NULL;
549 uint8_t *outhdr = NULL;
550 uint8_t *outbody = NULL;
551 uint32_t next_command_ofs = 0;
552 struct iovec *current = &vector[idx];
554 if ((idx + 3) < count) {
555 /* we have a next command -
556 * setup for the error case. */
557 next_command_ofs = SMB2_HDR_BODY + 9;
560 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
561 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
563 outhdr = talloc_zero_array(vector, uint8_t,
565 if (outhdr == NULL) {
566 return NT_STATUS_NO_MEMORY;
569 outbody = outhdr + SMB2_HDR_BODY;
571 current[0].iov_base = (void *)outhdr;
572 current[0].iov_len = SMB2_HDR_BODY;
574 current[1].iov_base = (void *)outbody;
575 current[1].iov_len = 8;
577 current[2].iov_base = NULL;
578 current[2].iov_len = 0;
580 /* setup the SMB2 header */
581 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
582 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
583 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
584 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
585 SIVAL(outhdr, SMB2_HDR_STATUS,
586 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
587 SSVAL(outhdr, SMB2_HDR_OPCODE,
588 SVAL(inhdr, SMB2_HDR_OPCODE));
589 SIVAL(outhdr, SMB2_HDR_FLAGS,
590 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
591 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
592 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
593 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
594 SIVAL(outhdr, SMB2_HDR_PID,
595 IVAL(inhdr, SMB2_HDR_PID));
596 SIVAL(outhdr, SMB2_HDR_TID,
597 IVAL(inhdr, SMB2_HDR_TID));
598 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
599 BVAL(inhdr, SMB2_HDR_SESSION_ID));
600 memcpy(outhdr + SMB2_HDR_SIGNATURE,
601 inhdr + SMB2_HDR_SIGNATURE, 16);
603 /* setup error body header */
604 SSVAL(outbody, 0x00, 0x08 + 1);
605 SSVAL(outbody, 0x02, 0);
606 SIVAL(outbody, 0x04, 0);
609 req->out.vector = vector;
610 req->out.vector_count = count;
612 /* setup the length of the NBT packet */
613 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
615 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
620 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
622 const char *location)
624 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
626 exit_server_cleanly(reason);
629 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
630 struct iovec *outvec,
631 const struct iovec *srcvec)
633 /* vec[0] is always boilerplate and must
634 * be allocated with size OUTVEC_ALLOC_SIZE. */
636 outvec[0].iov_base = talloc_memdup(ctx,
639 if (!outvec[0].iov_base) {
642 outvec[0].iov_len = SMB2_HDR_BODY;
645 * If this is a "standard" vec[1] of length 8,
646 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
647 * then duplicate this. Else use talloc_memdup().
650 if (srcvec[1].iov_len == 8 &&
651 srcvec[1].iov_base ==
652 ((uint8_t *)srcvec[0].iov_base) +
654 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
656 outvec[1].iov_len = 8;
658 outvec[1].iov_base = talloc_memdup(ctx,
661 if (!outvec[1].iov_base) {
664 outvec[1].iov_len = srcvec[1].iov_len;
668 * If this is a "standard" vec[2] of length 1,
669 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
670 * then duplicate this. Else use talloc_memdup().
673 if (srcvec[2].iov_base &&
675 if (srcvec[2].iov_base ==
676 ((uint8_t *)srcvec[0].iov_base) +
677 (OUTVEC_ALLOC_SIZE - 1) &&
678 srcvec[2].iov_len == 1) {
679 /* Common SMB2 error packet case. */
680 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
681 (OUTVEC_ALLOC_SIZE - 1);
683 outvec[2].iov_base = talloc_memdup(ctx,
686 if (!outvec[2].iov_base) {
690 outvec[2].iov_len = srcvec[2].iov_len;
692 outvec[2].iov_base = NULL;
693 outvec[2].iov_len = 0;
698 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
700 struct smbd_smb2_request *newreq = NULL;
701 struct iovec *outvec = NULL;
702 int count = req->out.vector_count;
705 newreq = smbd_smb2_request_allocate(req->sconn);
710 newreq->sconn = req->sconn;
711 newreq->session = req->session;
712 newreq->do_signing = req->do_signing;
713 newreq->current_idx = req->current_idx;
715 outvec = talloc_zero_array(newreq, struct iovec, count);
720 newreq->out.vector = outvec;
721 newreq->out.vector_count = count;
723 /* Setup the outvec's identically to req. */
724 outvec[0].iov_base = newreq->out.nbt_hdr;
725 outvec[0].iov_len = 4;
726 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
728 /* Setup the vectors identically to the ones in req. */
729 for (i = 1; i < count; i += 3) {
730 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
741 smb2_setup_nbt_length(newreq->out.vector,
742 newreq->out.vector_count);
747 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
749 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
752 uint8_t *outhdr = NULL;
753 struct smbd_smb2_request *nreq = NULL;
755 /* Create a new smb2 request we'll use
756 for the interim return. */
757 nreq = dup_smb2_req(req);
759 return NT_STATUS_NO_MEMORY;
762 /* Lose the last 3 out vectors. They're the
763 ones we'll be using for the async reply. */
764 nreq->out.vector_count -= 3;
766 smb2_setup_nbt_length(nreq->out.vector,
767 nreq->out.vector_count);
769 /* Step back to the previous reply. */
770 i = nreq->current_idx - 3;
771 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
772 /* And end the chain. */
773 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
775 /* Calculate outgoing credits */
776 smb2_calculate_credits(req, nreq);
778 /* Re-sign if needed. */
779 if (nreq->do_signing) {
781 status = smb2_signing_sign_pdu(nreq->session->session_key,
782 &nreq->out.vector[i], 3);
783 if (!NT_STATUS_IS_OK(status)) {
787 if (DEBUGLEVEL >= 10) {
788 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
789 (unsigned int)nreq->current_idx );
790 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
791 (unsigned int)nreq->out.vector_count );
792 print_req_vectors(nreq);
794 nreq->subreq = tstream_writev_queue_send(nreq,
795 nreq->sconn->smb2.event_ctx,
796 nreq->sconn->smb2.stream,
797 nreq->sconn->smb2.send_queue,
799 nreq->out.vector_count);
801 if (nreq->subreq == NULL) {
802 return NT_STATUS_NO_MEMORY;
805 tevent_req_set_callback(nreq->subreq,
806 smbd_smb2_request_writev_done,
812 struct smbd_smb2_request_pending_state {
813 struct smbd_server_connection *sconn;
814 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
815 struct iovec vector[3];
818 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
820 struct smbd_smb2_request_pending_state *state =
821 tevent_req_callback_data(subreq,
822 struct smbd_smb2_request_pending_state);
823 struct smbd_server_connection *sconn = state->sconn;
827 ret = tstream_writev_queue_recv(subreq, &sys_errno);
830 NTSTATUS status = map_nt_error_from_unix(sys_errno);
831 smbd_server_connection_terminate(sconn, nt_errstr(status));
838 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
839 struct tevent_timer *te,
840 struct timeval current_time,
843 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
844 struct tevent_req *subreq)
847 int i = req->current_idx;
848 uint32_t defer_time = 500;
849 struct timeval defer_endtime;
850 uint8_t *outhdr = NULL;
853 if (!tevent_req_is_in_progress(subreq)) {
857 req->subreq = subreq;
861 /* We're already async. */
865 outhdr = (uint8_t *)req->out.vector[i].iov_base;
866 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
867 if (flags & SMB2_HDR_FLAG_ASYNC) {
868 /* We're already async. */
872 if (req->in.vector_count > i + 3) {
874 * We're trying to go async in a compound
875 * request chain. This is not allowed.
876 * Cancel the outstanding request.
878 tevent_req_cancel(req->subreq);
879 return smbd_smb2_request_error(req,
880 NT_STATUS_INSUFFICIENT_RESOURCES);
883 if (DEBUGLEVEL >= 10) {
884 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
885 (unsigned int)req->current_idx );
886 print_req_vectors(req);
889 if (req->out.vector_count > 4) {
890 struct iovec *outvec = NULL;
892 /* This is a compound reply. We
893 * must do an interim response
894 * followed by the async response
897 status = smb2_send_async_interim_response(req);
898 if (!NT_STATUS_IS_OK(status)) {
903 * We're splitting off the last SMB2
904 * request in a compound set, and the
905 * smb2_send_async_interim_response()
906 * call above just sent all the replies
907 * for the previous SMB2 requests in
908 * this compound set. So we're no longer
909 * in the "compound_related_in_progress"
910 * state, and this is no longer a compound
913 req->compound_related = false;
914 req->sconn->smb2.compound_related_in_progress = false;
916 /* Re-arrange the in.vectors. */
917 req->in.vector[1] = req->in.vector[i];
918 req->in.vector[2] = req->in.vector[i+1];
919 req->in.vector[3] = req->in.vector[i+2];
920 req->in.vector_count = 4;
922 /* Reset the new in size. */
923 smb2_setup_nbt_length(req->in.vector, 4);
925 /* Now recreate the out.vectors. */
926 outvec = talloc_zero_array(req, struct iovec, 4);
928 return NT_STATUS_NO_MEMORY;
931 /* 0 is always boilerplate and must
932 * be of size 4 for the length field. */
934 outvec[0].iov_base = req->out.nbt_hdr;
935 outvec[0].iov_len = 4;
936 SIVAL(req->out.nbt_hdr, 0, 0);
938 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
939 return NT_STATUS_NO_MEMORY;
942 TALLOC_FREE(req->out.vector);
944 req->out.vector = outvec;
946 req->current_idx = 1;
947 req->out.vector_count = 4;
949 outhdr = (uint8_t *)req->out.vector[1].iov_base;
950 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
951 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
954 defer_endtime = timeval_current_ofs_usec(defer_time);
955 req->async_te = tevent_add_timer(req->sconn->smb2.event_ctx,
957 smbd_smb2_request_pending_timer,
959 if (req->async_te == NULL) {
960 return NT_STATUS_NO_MEMORY;
966 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
967 struct tevent_timer *te,
968 struct timeval current_time,
971 struct smbd_smb2_request *req =
972 talloc_get_type_abort(private_data,
973 struct smbd_smb2_request);
974 struct smbd_smb2_request_pending_state *state = NULL;
975 int i = req->current_idx;
976 uint8_t *outhdr = NULL;
977 const uint8_t *inhdr = NULL;
979 uint8_t *body = NULL;
981 uint64_t message_id = 0;
982 uint64_t async_id = 0;
983 struct tevent_req *subreq = NULL;
985 TALLOC_FREE(req->async_te);
987 /* Ensure our final reply matches the interim one. */
988 inhdr = (const uint8_t *)req->in.vector[1].iov_base;
989 outhdr = (uint8_t *)req->out.vector[1].iov_base;
990 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
991 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
993 async_id = message_id; /* keep it simple for now... */
995 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
996 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
998 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1000 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1001 (unsigned long long)async_id ));
1004 * What we send is identical to a smbd_smb2_request_error
1005 * packet with an error status of STATUS_PENDING. Make use
1006 * of this fact sometime when refactoring. JRA.
1009 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1010 if (state == NULL) {
1011 smbd_server_connection_terminate(req->sconn,
1012 nt_errstr(NT_STATUS_NO_MEMORY));
1015 state->sconn = req->sconn;
1017 state->vector[0].iov_base = (void *)state->buf;
1018 state->vector[0].iov_len = 4;
1020 state->vector[1].iov_base = state->buf + 4;
1021 state->vector[1].iov_len = SMB2_HDR_BODY;
1023 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
1024 state->vector[2].iov_len = 9;
1026 smb2_setup_nbt_length(state->vector, 3);
1028 hdr = (uint8_t *)state->vector[1].iov_base;
1029 body = (uint8_t *)state->vector[2].iov_base;
1031 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1032 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1033 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1034 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1035 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1037 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1038 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1039 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1040 SBVAL(hdr, SMB2_HDR_PID, async_id);
1041 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1042 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1043 memcpy(hdr+SMB2_HDR_SIGNATURE,
1044 outhdr+SMB2_HDR_SIGNATURE, 16);
1046 SSVAL(body, 0x00, 0x08 + 1);
1048 SCVAL(body, 0x02, 0);
1049 SCVAL(body, 0x03, 0);
1050 SIVAL(body, 0x04, 0);
1051 /* Match W2K8R2... */
1052 SCVAL(body, 0x08, 0x21);
1054 /* Ensure we correctly go through crediting. Grant
1055 the credits now, and zero credits on the final
1057 smb2_set_operation_credit(req->sconn,
1061 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1063 if (req->do_signing) {
1066 status = smb2_signing_sign_pdu(req->session->session_key,
1067 &state->vector[1], 2);
1068 if (!NT_STATUS_IS_OK(status)) {
1069 smbd_server_connection_terminate(req->sconn,
1075 subreq = tstream_writev_queue_send(state,
1076 state->sconn->smb2.event_ctx,
1077 state->sconn->smb2.stream,
1078 state->sconn->smb2.send_queue,
1081 if (subreq == NULL) {
1082 smbd_server_connection_terminate(state->sconn,
1083 nt_errstr(NT_STATUS_NO_MEMORY));
1086 tevent_req_set_callback(subreq,
1087 smbd_smb2_request_pending_writev_done,
1091 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1093 struct smbd_server_connection *sconn = req->sconn;
1094 struct smbd_smb2_request *cur;
1095 const uint8_t *inhdr;
1096 int i = req->current_idx;
1098 uint64_t search_message_id;
1099 uint64_t search_async_id;
1102 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1104 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1105 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1106 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1109 * we don't need the request anymore
1110 * cancel requests never have a response
1112 DLIST_REMOVE(req->sconn->smb2.requests, req);
1115 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1116 const uint8_t *outhdr;
1117 uint64_t message_id;
1120 i = cur->current_idx;
1122 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1124 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1125 async_id = BVAL(outhdr, SMB2_HDR_PID);
1127 if (flags & SMB2_HDR_FLAG_ASYNC) {
1128 if (search_async_id == async_id) {
1129 found_id = async_id;
1133 if (search_message_id == message_id) {
1134 found_id = message_id;
1140 if (cur && cur->subreq) {
1141 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1142 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1143 "cancel opcode[%s] mid %llu\n",
1144 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1145 (unsigned long long)found_id ));
1146 tevent_req_cancel(cur->subreq);
1149 return NT_STATUS_OK;
1152 /*************************************************************
1153 Ensure an incoming tid is a valid one for us to access.
1154 Change to the associated uid credentials and chdir to the
1155 valid tid directory.
1156 *************************************************************/
1158 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1160 const uint8_t *inhdr;
1161 int i = req->current_idx;
1165 struct smbd_smb2_tcon *tcon;
1169 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1171 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1172 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1174 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1175 in_tid = req->last_tid;
1178 /* lookup an existing session */
1179 p = idr_find(req->session->tcons.idtree, in_tid);
1181 return NT_STATUS_NETWORK_NAME_DELETED;
1183 tcon = talloc_get_type_abort(p, struct smbd_smb2_tcon);
1185 if (!change_to_user(tcon->compat_conn,req->session->vuid)) {
1186 return NT_STATUS_ACCESS_DENIED;
1189 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1190 if (!set_current_service(tcon->compat_conn, 0, true)) {
1191 return NT_STATUS_ACCESS_DENIED;
1195 req->last_tid = in_tid;
1197 return NT_STATUS_OK;
1200 /*************************************************************
1201 Ensure an incoming session_id is a valid one for us to access.
1202 *************************************************************/
1204 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1206 const uint8_t *inhdr;
1207 int i = req->current_idx;
1209 uint64_t in_session_id;
1211 struct smbd_smb2_session *session;
1213 req->session = NULL;
1216 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1218 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1219 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1221 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1222 in_session_id = req->last_session_id;
1225 /* lookup an existing session */
1226 p = idr_find(req->sconn->smb2.sessions.idtree, in_session_id);
1228 return NT_STATUS_USER_SESSION_DELETED;
1230 session = talloc_get_type_abort(p, struct smbd_smb2_session);
1232 if (!NT_STATUS_IS_OK(session->status)) {
1233 return NT_STATUS_ACCESS_DENIED;
1236 set_current_user_info(session->session_info->unix_info->sanitized_username,
1237 session->session_info->unix_info->unix_name,
1238 session->session_info->info->domain_name);
1240 req->session = session;
1241 req->last_session_id = in_session_id;
1243 return NT_STATUS_OK;
1246 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1247 size_t expected_body_size)
1249 const uint8_t *inhdr;
1251 const uint8_t *inbody;
1252 int i = req->current_idx;
1254 size_t min_dyn_size = expected_body_size & 0x00000001;
1257 * The following should be checked already.
1259 if ((i+2) > req->in.vector_count) {
1260 return NT_STATUS_INTERNAL_ERROR;
1262 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1263 return NT_STATUS_INTERNAL_ERROR;
1265 if (req->in.vector[i+1].iov_len < 2) {
1266 return NT_STATUS_INTERNAL_ERROR;
1269 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1270 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1274 case SMB2_OP_GETINFO:
1280 * Now check the expected body size,
1281 * where the last byte might be in the
1282 * dynnamic section..
1284 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1285 return NT_STATUS_INVALID_PARAMETER;
1287 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1288 return NT_STATUS_INVALID_PARAMETER;
1291 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1293 body_size = SVAL(inbody, 0x00);
1294 if (body_size != expected_body_size) {
1295 return NT_STATUS_INVALID_PARAMETER;
1298 return NT_STATUS_OK;
1301 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1303 const uint8_t *inhdr;
1304 int i = req->current_idx;
1309 NTSTATUS session_status;
1310 uint32_t allowed_flags;
1311 NTSTATUS return_value;
1313 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1315 /* TODO: verify more things */
1317 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1318 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1319 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1320 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1321 smb2_opcode_name(opcode),
1322 (unsigned long long)mid));
1324 if (get_Protocol() >= PROTOCOL_SMB2_02) {
1326 * once the protocol is negotiated
1327 * SMB2_OP_NEGPROT is not allowed anymore
1329 if (opcode == SMB2_OP_NEGPROT) {
1330 /* drop the connection */
1331 return NT_STATUS_INVALID_PARAMETER;
1335 * if the protocol is not negotiated yet
1336 * only SMB2_OP_NEGPROT is allowed.
1338 if (opcode != SMB2_OP_NEGPROT) {
1339 /* drop the connection */
1340 return NT_STATUS_INVALID_PARAMETER;
1344 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1345 SMB2_HDR_FLAG_SIGNED |
1347 if (opcode == SMB2_OP_CANCEL) {
1348 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1350 if ((flags & ~allowed_flags) != 0) {
1351 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1355 * Check if the client provided a valid session id,
1356 * if so smbd_smb2_request_check_session() calls
1357 * set_current_user_info().
1359 * As some command don't require a valid session id
1360 * we defer the check of the session_status
1362 session_status = smbd_smb2_request_check_session(req);
1364 req->do_signing = false;
1365 if (flags & SMB2_HDR_FLAG_SIGNED) {
1366 if (!NT_STATUS_IS_OK(session_status)) {
1367 return smbd_smb2_request_error(req, session_status);
1370 req->do_signing = true;
1371 status = smb2_signing_check_pdu(req->session->session_key,
1372 &req->in.vector[i], 3);
1373 if (!NT_STATUS_IS_OK(status)) {
1374 return smbd_smb2_request_error(req, status);
1376 } else if (opcode == SMB2_OP_CANCEL) {
1377 /* Cancel requests are allowed to skip the signing */
1378 } else if (req->session && req->session->do_signing) {
1379 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1382 if (flags & SMB2_HDR_FLAG_CHAINED) {
1384 * This check is mostly for giving the correct error code
1385 * for compounded requests.
1387 * TODO: we may need to move this after the session
1390 if (!NT_STATUS_IS_OK(req->next_status)) {
1391 return smbd_smb2_request_error(req, req->next_status);
1394 req->compat_chain_fsp = NULL;
1397 if (req->compound_related) {
1398 req->sconn->smb2.compound_related_in_progress = true;
1402 case SMB2_OP_NEGPROT:
1403 /* This call needs to be run as root */
1404 change_to_root_user();
1407 START_PROFILE(smb2_negprot);
1408 return_value = smbd_smb2_request_process_negprot(req);
1409 END_PROFILE(smb2_negprot);
1413 case SMB2_OP_SESSSETUP:
1414 /* This call needs to be run as root */
1415 change_to_root_user();
1418 START_PROFILE(smb2_sesssetup);
1419 return_value = smbd_smb2_request_process_sesssetup(req);
1420 END_PROFILE(smb2_sesssetup);
1424 case SMB2_OP_LOGOFF:
1425 if (!NT_STATUS_IS_OK(session_status)) {
1426 return_value = smbd_smb2_request_error(req, session_status);
1430 /* This call needs to be run as root */
1431 change_to_root_user();
1434 START_PROFILE(smb2_logoff);
1435 return_value = smbd_smb2_request_process_logoff(req);
1436 END_PROFILE(smb2_logoff);
1441 if (!NT_STATUS_IS_OK(session_status)) {
1442 return_value = smbd_smb2_request_error(req, session_status);
1447 * This call needs to be run as root.
1449 * smbd_smb2_request_process_tcon()
1450 * calls make_connection_snum(), which will call
1451 * change_to_user(), when needed.
1453 change_to_root_user();
1456 START_PROFILE(smb2_tcon);
1457 return_value = smbd_smb2_request_process_tcon(req);
1458 END_PROFILE(smb2_tcon);
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);
1478 /* This call needs to be run as root */
1479 change_to_root_user();
1483 START_PROFILE(smb2_tdis);
1484 return_value = smbd_smb2_request_process_tdis(req);
1485 END_PROFILE(smb2_tdis);
1489 case SMB2_OP_CREATE:
1490 if (!NT_STATUS_IS_OK(session_status)) {
1491 return_value = smbd_smb2_request_error(req, session_status);
1495 * This call needs to be run as user.
1497 * smbd_smb2_request_check_tcon()
1498 * calls change_to_user() on success.
1500 status = smbd_smb2_request_check_tcon(req);
1501 if (!NT_STATUS_IS_OK(status)) {
1502 return_value = smbd_smb2_request_error(req, status);
1507 START_PROFILE(smb2_create);
1508 return_value = smbd_smb2_request_process_create(req);
1509 END_PROFILE(smb2_create);
1514 if (!NT_STATUS_IS_OK(session_status)) {
1515 return_value = smbd_smb2_request_error(req, session_status);
1519 * This call needs to be run as user.
1521 * smbd_smb2_request_check_tcon()
1522 * calls change_to_user() on success.
1524 status = smbd_smb2_request_check_tcon(req);
1525 if (!NT_STATUS_IS_OK(status)) {
1526 return_value = smbd_smb2_request_error(req, status);
1531 START_PROFILE(smb2_close);
1532 return_value = smbd_smb2_request_process_close(req);
1533 END_PROFILE(smb2_close);
1538 if (!NT_STATUS_IS_OK(session_status)) {
1539 return_value = smbd_smb2_request_error(req, session_status);
1543 * This call needs to be run as user.
1545 * smbd_smb2_request_check_tcon()
1546 * calls change_to_user() on success.
1548 status = smbd_smb2_request_check_tcon(req);
1549 if (!NT_STATUS_IS_OK(status)) {
1550 return_value = smbd_smb2_request_error(req, status);
1555 START_PROFILE(smb2_flush);
1556 return_value = smbd_smb2_request_process_flush(req);
1557 END_PROFILE(smb2_flush);
1562 if (!NT_STATUS_IS_OK(session_status)) {
1563 return_value = smbd_smb2_request_error(req, session_status);
1567 * This call needs to be run as user.
1569 * smbd_smb2_request_check_tcon()
1570 * calls change_to_user() on success.
1572 status = smbd_smb2_request_check_tcon(req);
1573 if (!NT_STATUS_IS_OK(status)) {
1574 return_value = smbd_smb2_request_error(req, status);
1579 START_PROFILE(smb2_read);
1580 return_value = smbd_smb2_request_process_read(req);
1581 END_PROFILE(smb2_read);
1586 if (!NT_STATUS_IS_OK(session_status)) {
1587 return_value = smbd_smb2_request_error(req, session_status);
1591 * This call needs to be run as user.
1593 * smbd_smb2_request_check_tcon()
1594 * calls change_to_user() on success.
1596 status = smbd_smb2_request_check_tcon(req);
1597 if (!NT_STATUS_IS_OK(status)) {
1598 return_value = smbd_smb2_request_error(req, status);
1603 START_PROFILE(smb2_write);
1604 return_value = smbd_smb2_request_process_write(req);
1605 END_PROFILE(smb2_write);
1610 if (!NT_STATUS_IS_OK(session_status)) {
1611 /* Too ugly to live ? JRA. */
1612 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1613 session_status = NT_STATUS_FILE_CLOSED;
1615 return_value = smbd_smb2_request_error(req, session_status);
1619 * This call needs to be run as user.
1621 * smbd_smb2_request_check_tcon()
1622 * calls change_to_user() on success.
1624 status = smbd_smb2_request_check_tcon(req);
1625 if (!NT_STATUS_IS_OK(status)) {
1626 /* Too ugly to live ? JRA. */
1627 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1628 status = NT_STATUS_FILE_CLOSED;
1630 return_value = smbd_smb2_request_error(req, status);
1635 START_PROFILE(smb2_lock);
1636 return_value = smbd_smb2_request_process_lock(req);
1637 END_PROFILE(smb2_lock);
1642 if (!NT_STATUS_IS_OK(session_status)) {
1643 return_value = smbd_smb2_request_error(req, session_status);
1647 * This call needs to be run as user.
1649 * smbd_smb2_request_check_tcon()
1650 * calls change_to_user() on success.
1652 status = smbd_smb2_request_check_tcon(req);
1653 if (!NT_STATUS_IS_OK(status)) {
1654 return_value = smbd_smb2_request_error(req, status);
1659 START_PROFILE(smb2_ioctl);
1660 return_value = smbd_smb2_request_process_ioctl(req);
1661 END_PROFILE(smb2_ioctl);
1665 case SMB2_OP_CANCEL:
1667 * This call needs to be run as root
1669 * That is what we also do in the SMB1 case.
1671 change_to_root_user();
1674 START_PROFILE(smb2_cancel);
1675 return_value = smbd_smb2_request_process_cancel(req);
1676 END_PROFILE(smb2_cancel);
1680 case SMB2_OP_KEEPALIVE:
1681 /* This call needs to be run as root */
1682 change_to_root_user();
1685 START_PROFILE(smb2_keepalive);
1686 return_value = smbd_smb2_request_process_keepalive(req);
1687 END_PROFILE(smb2_keepalive);
1692 if (!NT_STATUS_IS_OK(session_status)) {
1693 return_value = smbd_smb2_request_error(req, session_status);
1697 * This call needs to be run as user.
1699 * smbd_smb2_request_check_tcon()
1700 * calls change_to_user() on success.
1702 status = smbd_smb2_request_check_tcon(req);
1703 if (!NT_STATUS_IS_OK(status)) {
1704 return_value = smbd_smb2_request_error(req, status);
1709 START_PROFILE(smb2_find);
1710 return_value = smbd_smb2_request_process_find(req);
1711 END_PROFILE(smb2_find);
1715 case SMB2_OP_NOTIFY:
1716 if (!NT_STATUS_IS_OK(session_status)) {
1717 return_value = smbd_smb2_request_error(req, session_status);
1721 * This call needs to be run as user.
1723 * smbd_smb2_request_check_tcon()
1724 * calls change_to_user() on success.
1726 status = smbd_smb2_request_check_tcon(req);
1727 if (!NT_STATUS_IS_OK(status)) {
1728 return_value = smbd_smb2_request_error(req, status);
1733 START_PROFILE(smb2_notify);
1734 return_value = smbd_smb2_request_process_notify(req);
1735 END_PROFILE(smb2_notify);
1739 case SMB2_OP_GETINFO:
1740 if (!NT_STATUS_IS_OK(session_status)) {
1741 return_value = smbd_smb2_request_error(req, session_status);
1745 * This call needs to be run as user.
1747 * smbd_smb2_request_check_tcon()
1748 * calls change_to_user() on success.
1750 status = smbd_smb2_request_check_tcon(req);
1751 if (!NT_STATUS_IS_OK(status)) {
1752 return_value = smbd_smb2_request_error(req, status);
1757 START_PROFILE(smb2_getinfo);
1758 return_value = smbd_smb2_request_process_getinfo(req);
1759 END_PROFILE(smb2_getinfo);
1763 case SMB2_OP_SETINFO:
1764 if (!NT_STATUS_IS_OK(session_status)) {
1765 return_value = smbd_smb2_request_error(req, session_status);
1769 * This call needs to be run as user.
1771 * smbd_smb2_request_check_tcon()
1772 * calls change_to_user() on success.
1774 status = smbd_smb2_request_check_tcon(req);
1775 if (!NT_STATUS_IS_OK(status)) {
1776 return_value = smbd_smb2_request_error(req, status);
1781 START_PROFILE(smb2_setinfo);
1782 return_value = smbd_smb2_request_process_setinfo(req);
1783 END_PROFILE(smb2_setinfo);
1788 if (!NT_STATUS_IS_OK(session_status)) {
1789 return_value = smbd_smb2_request_error(req, session_status);
1793 * This call needs to be run as user.
1795 * smbd_smb2_request_check_tcon()
1796 * calls change_to_user() on success.
1798 status = smbd_smb2_request_check_tcon(req);
1799 if (!NT_STATUS_IS_OK(status)) {
1800 return_value = smbd_smb2_request_error(req, status);
1805 START_PROFILE(smb2_break);
1806 return_value = smbd_smb2_request_process_break(req);
1807 END_PROFILE(smb2_break);
1812 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1815 return return_value;
1818 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1820 struct tevent_req *subreq;
1821 int i = req->current_idx;
1824 TALLOC_FREE(req->async_te);
1826 req->current_idx += 3;
1828 if (req->current_idx < req->out.vector_count) {
1830 * We must process the remaining compound
1831 * SMB2 requests before any new incoming SMB2
1832 * requests. This is because incoming SMB2
1833 * requests may include a cancel for a
1834 * compound request we haven't processed
1837 struct tevent_immediate *im = tevent_create_immediate(req);
1839 return NT_STATUS_NO_MEMORY;
1841 tevent_schedule_immediate(im,
1842 req->sconn->smb2.event_ctx,
1843 smbd_smb2_request_dispatch_immediate,
1845 return NT_STATUS_OK;
1848 if (req->compound_related) {
1849 req->sconn->smb2.compound_related_in_progress = false;
1852 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1854 /* Set credit for this operation (zero credits if this
1855 is a final reply for an async operation). */
1856 smb2_set_operation_credit(req->sconn,
1858 &req->out.vector[i]);
1860 if (req->do_signing) {
1862 status = smb2_signing_sign_pdu(req->session->session_key,
1863 &req->out.vector[i], 3);
1864 if (!NT_STATUS_IS_OK(status)) {
1869 if (DEBUGLEVEL >= 10) {
1870 dbgtext("smbd_smb2_request_reply: sending...\n");
1871 print_req_vectors(req);
1874 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1875 if (req->out.vector_count == 4 &&
1876 req->out.vector[3].iov_base == NULL &&
1877 req->out.vector[3].iov_len != 0) {
1878 /* Dynamic part is NULL. Chop it off,
1879 We're going to send it via sendfile. */
1880 req->out.vector_count -= 1;
1883 subreq = tstream_writev_queue_send(req,
1884 req->sconn->smb2.event_ctx,
1885 req->sconn->smb2.stream,
1886 req->sconn->smb2.send_queue,
1888 req->out.vector_count);
1889 if (subreq == NULL) {
1890 return NT_STATUS_NO_MEMORY;
1892 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1894 * We're done with this request -
1895 * move it off the "being processed" queue.
1897 DLIST_REMOVE(req->sconn->smb2.requests, req);
1899 return NT_STATUS_OK;
1902 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
1904 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1905 struct tevent_immediate *im,
1908 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1909 struct smbd_smb2_request);
1910 struct smbd_server_connection *sconn = req->sconn;
1915 if (DEBUGLEVEL >= 10) {
1916 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1917 req->current_idx, req->in.vector_count));
1918 print_req_vectors(req);
1921 status = smbd_smb2_request_dispatch(req);
1922 if (!NT_STATUS_IS_OK(status)) {
1923 smbd_server_connection_terminate(sconn, nt_errstr(status));
1927 status = smbd_smb2_request_next_incoming(sconn);
1928 if (!NT_STATUS_IS_OK(status)) {
1929 smbd_server_connection_terminate(sconn, nt_errstr(status));
1934 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1936 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1937 struct smbd_smb2_request);
1938 struct smbd_server_connection *sconn = req->sconn;
1943 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1944 TALLOC_FREE(subreq);
1947 status = map_nt_error_from_unix(sys_errno);
1948 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1949 nt_errstr(status)));
1950 smbd_server_connection_terminate(sconn, nt_errstr(status));
1954 status = smbd_smb2_request_next_incoming(sconn);
1955 if (!NT_STATUS_IS_OK(status)) {
1956 smbd_server_connection_terminate(sconn, nt_errstr(status));
1961 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1963 DATA_BLOB body, DATA_BLOB *dyn,
1964 const char *location)
1967 int i = req->current_idx;
1968 uint32_t next_command_ofs;
1970 DEBUG(10,("smbd_smb2_request_done_ex: "
1971 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1972 i, nt_errstr(status), (unsigned int)body.length,
1974 (unsigned int)(dyn ? dyn->length : 0),
1977 if (body.length < 2) {
1978 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1981 if ((body.length % 2) != 0) {
1982 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1985 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1987 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1988 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1990 req->out.vector[i+1].iov_base = (void *)body.data;
1991 req->out.vector[i+1].iov_len = body.length;
1994 req->out.vector[i+2].iov_base = (void *)dyn->data;
1995 req->out.vector[i+2].iov_len = dyn->length;
1997 req->out.vector[i+2].iov_base = NULL;
1998 req->out.vector[i+2].iov_len = 0;
2001 /* see if we need to recalculate the offset to the next response */
2002 if (next_command_ofs > 0) {
2003 next_command_ofs = SMB2_HDR_BODY;
2004 next_command_ofs += req->out.vector[i+1].iov_len;
2005 next_command_ofs += req->out.vector[i+2].iov_len;
2008 if ((next_command_ofs % 8) != 0) {
2009 size_t pad_size = 8 - (next_command_ofs % 8);
2010 if (req->out.vector[i+2].iov_len == 0) {
2012 * if the dyn buffer is empty
2013 * we can use it to add padding
2017 pad = talloc_zero_array(req->out.vector,
2020 return smbd_smb2_request_error(req,
2021 NT_STATUS_NO_MEMORY);
2024 req->out.vector[i+2].iov_base = (void *)pad;
2025 req->out.vector[i+2].iov_len = pad_size;
2028 * For now we copy the dynamic buffer
2029 * and add the padding to the new buffer
2036 old_size = req->out.vector[i+2].iov_len;
2037 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2039 new_size = old_size + pad_size;
2040 new_dyn = talloc_zero_array(req->out.vector,
2042 if (new_dyn == NULL) {
2043 return smbd_smb2_request_error(req,
2044 NT_STATUS_NO_MEMORY);
2047 memcpy(new_dyn, old_dyn, old_size);
2048 memset(new_dyn + old_size, 0, pad_size);
2050 req->out.vector[i+2].iov_base = (void *)new_dyn;
2051 req->out.vector[i+2].iov_len = new_size;
2053 next_command_ofs += pad_size;
2056 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2058 return smbd_smb2_request_reply(req);
2061 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2064 const char *location)
2067 int i = req->current_idx;
2068 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
2070 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2071 i, nt_errstr(status), info ? " +info" : "",
2074 body.data = outhdr + SMB2_HDR_BODY;
2076 SSVAL(body.data, 0, 9);
2079 SIVAL(body.data, 0x04, info->length);
2081 /* Allocated size of req->out.vector[i].iov_base
2082 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2083 * 1 byte without having to do an alloc.
2085 info = talloc_zero_array(req->out.vector,
2089 return NT_STATUS_NO_MEMORY;
2091 info->data = ((uint8_t *)outhdr) +
2092 OUTVEC_ALLOC_SIZE - 1;
2094 SCVAL(info->data, 0, 0);
2098 * if a request fails, all other remaining
2099 * compounded requests should fail too
2101 req->next_status = NT_STATUS_INVALID_PARAMETER;
2103 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2107 struct smbd_smb2_send_oplock_break_state {
2108 struct smbd_server_connection *sconn;
2109 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2110 struct iovec vector;
2113 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2115 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2116 uint64_t file_id_persistent,
2117 uint64_t file_id_volatile,
2118 uint8_t oplock_level)
2120 struct smbd_smb2_send_oplock_break_state *state;
2121 struct tevent_req *subreq;
2125 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2126 if (state == NULL) {
2127 return NT_STATUS_NO_MEMORY;
2129 state->sconn = sconn;
2131 state->vector.iov_base = (void *)state->buf;
2132 state->vector.iov_len = sizeof(state->buf);
2134 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2135 hdr = state->buf + 4;
2136 body = hdr + SMB2_HDR_BODY;
2138 SIVAL(hdr, 0, SMB2_MAGIC);
2139 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2140 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2141 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2142 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2143 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2144 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2145 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2146 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2147 SIVAL(hdr, SMB2_HDR_PID, 0);
2148 SIVAL(hdr, SMB2_HDR_TID, 0);
2149 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2150 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2152 SSVAL(body, 0x00, 0x18);
2154 SCVAL(body, 0x02, oplock_level);
2155 SCVAL(body, 0x03, 0); /* reserved */
2156 SIVAL(body, 0x04, 0); /* reserved */
2157 SBVAL(body, 0x08, file_id_persistent);
2158 SBVAL(body, 0x10, file_id_volatile);
2160 subreq = tstream_writev_queue_send(state,
2161 sconn->smb2.event_ctx,
2163 sconn->smb2.send_queue,
2165 if (subreq == NULL) {
2166 return NT_STATUS_NO_MEMORY;
2168 tevent_req_set_callback(subreq,
2169 smbd_smb2_oplock_break_writev_done,
2172 return NT_STATUS_OK;
2175 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2177 struct smbd_smb2_send_oplock_break_state *state =
2178 tevent_req_callback_data(subreq,
2179 struct smbd_smb2_send_oplock_break_state);
2180 struct smbd_server_connection *sconn = state->sconn;
2184 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2185 TALLOC_FREE(subreq);
2187 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2188 smbd_server_connection_terminate(sconn, nt_errstr(status));
2195 struct smbd_smb2_request_read_state {
2197 bool asked_for_header;
2198 struct smbd_smb2_request *smb2_req;
2201 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2203 TALLOC_CTX *mem_ctx,
2204 struct iovec **_vector,
2206 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2208 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2209 struct tevent_context *ev,
2210 struct smbd_server_connection *sconn)
2212 struct tevent_req *req;
2213 struct smbd_smb2_request_read_state *state;
2214 struct tevent_req *subreq;
2216 req = tevent_req_create(mem_ctx, &state,
2217 struct smbd_smb2_request_read_state);
2222 state->asked_for_header = false;
2224 state->smb2_req = smbd_smb2_request_allocate(state);
2225 if (tevent_req_nomem(state->smb2_req, req)) {
2226 return tevent_req_post(req, ev);
2228 state->smb2_req->sconn = sconn;
2230 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2231 sconn->smb2.recv_queue,
2232 smbd_smb2_request_next_vector,
2234 if (tevent_req_nomem(subreq, req)) {
2235 return tevent_req_post(req, ev);
2237 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2242 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2244 TALLOC_CTX *mem_ctx,
2245 struct iovec **_vector,
2248 struct smbd_smb2_request_read_state *state =
2249 talloc_get_type_abort(private_data,
2250 struct smbd_smb2_request_read_state);
2251 struct smbd_smb2_request *req = state->smb2_req;
2252 struct iovec *vector;
2253 int idx = req->in.vector_count;
2255 uint8_t *buf = NULL;
2257 if (req->in.vector_count == 0) {
2259 * first we need to get the NBT header
2261 req->in.vector = talloc_array(req, struct iovec,
2262 req->in.vector_count + 1);
2263 if (req->in.vector == NULL) {
2266 req->in.vector_count += 1;
2268 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2269 req->in.vector[idx].iov_len = 4;
2271 vector = talloc_array(mem_ctx, struct iovec, 1);
2272 if (vector == NULL) {
2276 vector[0] = req->in.vector[idx];
2283 if (req->in.vector_count == 1) {
2285 * Now we analyze the NBT header
2287 state->missing = smb2_len(req->in.vector[0].iov_base);
2289 if (state->missing == 0) {
2290 /* if there're no remaining bytes, we're done */
2296 req->in.vector = talloc_realloc(req, req->in.vector,
2298 req->in.vector_count + 1);
2299 if (req->in.vector == NULL) {
2302 req->in.vector_count += 1;
2304 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2306 * it's a special NBT message,
2307 * so get all remaining bytes
2309 len = state->missing;
2310 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2312 * it's an invalid message, just read what we can get
2313 * and let the caller handle the error
2315 len = state->missing;
2318 * We assume it's a SMB2 request,
2319 * and we first get the header and the
2320 * first 2 bytes (the struct size) of the body
2322 len = SMB2_HDR_BODY + 2;
2324 state->asked_for_header = true;
2327 state->missing -= len;
2329 buf = talloc_array(req->in.vector, uint8_t, len);
2334 req->in.vector[idx].iov_base = (void *)buf;
2335 req->in.vector[idx].iov_len = len;
2337 vector = talloc_array(mem_ctx, struct iovec, 1);
2338 if (vector == NULL) {
2342 vector[0] = req->in.vector[idx];
2349 if (state->missing == 0) {
2350 /* if there're no remaining bytes, we're done */
2356 if (state->asked_for_header) {
2359 size_t next_command_ofs;
2364 bool invalid = false;
2366 state->asked_for_header = false;
2369 * We got the SMB2 header and the first 2 bytes
2370 * of the body. We fix the size to just the header
2371 * and manually copy the 2 first bytes to the body section
2373 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2374 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2376 /* allocate vectors for body and dynamic areas */
2377 req->in.vector = talloc_realloc(req, req->in.vector,
2379 req->in.vector_count + 2);
2380 if (req->in.vector == NULL) {
2383 req->in.vector_count += 2;
2385 full_size = state->missing + SMB2_HDR_BODY + 2;
2386 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2387 body_size = SVAL(hdr, SMB2_HDR_BODY);
2389 if (next_command_ofs != 0) {
2390 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2392 * this is invalid, just return a zero
2393 * body and let the caller deal with the error
2396 } else if (next_command_ofs > full_size) {
2398 * this is invalid, just return a zero
2399 * body and let the caller deal with the error
2403 full_size = next_command_ofs;
2408 if (body_size < 2) {
2410 * this is invalid, just return a zero
2411 * body and let the caller deal with the error
2417 * Mask out the lowest bit, the "dynamic" part
2422 if (body_size > (full_size - SMB2_HDR_BODY)) {
2424 * this is invalid, just return a zero
2425 * body and let the caller deal with the error
2432 /* the caller should check this */
2436 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2438 state->missing -= (body_size - 2) + dyn_size;
2440 body = talloc_array(req->in.vector, uint8_t, body_size);
2445 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2450 req->in.vector[idx].iov_base = (void *)body;
2451 req->in.vector[idx].iov_len = body_size;
2452 req->in.vector[idx+1].iov_base = (void *)dyn;
2453 req->in.vector[idx+1].iov_len = dyn_size;
2455 vector = talloc_array(mem_ctx, struct iovec, 2);
2456 if (vector == NULL) {
2461 * the first 2 bytes of the body were already fetched
2462 * together with the header
2464 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2465 vector[0].iov_base = body + 2;
2466 vector[0].iov_len = body_size - 2;
2468 vector[1] = req->in.vector[idx+1];
2476 * when we endup here, we're looking for a new SMB2 request
2477 * next. And we ask for its header and the first 2 bytes of
2478 * the body (like we did for the first SMB2 request).
2481 req->in.vector = talloc_realloc(req, req->in.vector,
2483 req->in.vector_count + 1);
2484 if (req->in.vector == NULL) {
2487 req->in.vector_count += 1;
2490 * We assume it's a SMB2 request,
2491 * and we first get the header and the
2492 * first 2 bytes (the struct size) of the body
2494 len = SMB2_HDR_BODY + 2;
2496 if (len > state->missing) {
2497 /* let the caller handle the error */
2498 len = state->missing;
2501 state->missing -= len;
2502 state->asked_for_header = true;
2504 buf = talloc_array(req->in.vector, uint8_t, len);
2509 req->in.vector[idx].iov_base = (void *)buf;
2510 req->in.vector[idx].iov_len = len;
2512 vector = talloc_array(mem_ctx, struct iovec, 1);
2513 if (vector == NULL) {
2517 vector[0] = req->in.vector[idx];
2524 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2526 struct tevent_req *req =
2527 tevent_req_callback_data(subreq,
2533 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2535 status = map_nt_error_from_unix(sys_errno);
2536 tevent_req_nterror(req, status);
2540 tevent_req_done(req);
2543 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2544 TALLOC_CTX *mem_ctx,
2545 struct smbd_smb2_request **_smb2_req)
2547 struct smbd_smb2_request_read_state *state =
2548 tevent_req_data(req,
2549 struct smbd_smb2_request_read_state);
2552 if (tevent_req_is_nterror(req, &status)) {
2553 tevent_req_received(req);
2557 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2558 *_smb2_req = state->smb2_req;
2559 tevent_req_received(req);
2560 return NT_STATUS_OK;
2563 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2565 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2567 size_t max_send_queue_len;
2568 size_t cur_send_queue_len;
2569 struct tevent_req *subreq;
2571 if (sconn->smb2.compound_related_in_progress) {
2573 * Can't read another until the related
2576 return NT_STATUS_OK;
2579 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2581 * if there is already a smbd_smb2_request_read
2582 * pending, we are done.
2584 return NT_STATUS_OK;
2587 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2588 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2590 if (cur_send_queue_len > max_send_queue_len) {
2592 * if we have a lot of requests to send,
2593 * we wait until they are on the wire until we
2594 * ask for the next request.
2596 return NT_STATUS_OK;
2599 /* ask for the next request */
2600 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2601 if (subreq == NULL) {
2602 return NT_STATUS_NO_MEMORY;
2604 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2606 return NT_STATUS_OK;
2609 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2610 const uint8_t *inbuf, size_t size)
2613 struct smbd_smb2_request *req = NULL;
2615 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2616 (unsigned int)size));
2618 status = smbd_initialize_smb2(sconn);
2619 if (!NT_STATUS_IS_OK(status)) {
2620 smbd_server_connection_terminate(sconn, nt_errstr(status));
2624 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2625 if (!NT_STATUS_IS_OK(status)) {
2626 smbd_server_connection_terminate(sconn, nt_errstr(status));
2630 status = smbd_smb2_request_setup_out(req);
2631 if (!NT_STATUS_IS_OK(status)) {
2632 smbd_server_connection_terminate(sconn, nt_errstr(status));
2636 status = smbd_smb2_request_dispatch(req);
2637 if (!NT_STATUS_IS_OK(status)) {
2638 smbd_server_connection_terminate(sconn, nt_errstr(status));
2642 status = smbd_smb2_request_next_incoming(sconn);
2643 if (!NT_STATUS_IS_OK(status)) {
2644 smbd_server_connection_terminate(sconn, nt_errstr(status));
2648 sconn->num_requests++;
2651 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2653 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2654 struct smbd_server_connection);
2656 struct smbd_smb2_request *req = NULL;
2658 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2659 TALLOC_FREE(subreq);
2660 if (!NT_STATUS_IS_OK(status)) {
2661 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2662 nt_errstr(status)));
2663 smbd_server_connection_terminate(sconn, nt_errstr(status));
2667 if (req->in.nbt_hdr[0] != 0x00) {
2668 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2669 req->in.nbt_hdr[0]));
2674 req->current_idx = 1;
2676 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2677 req->current_idx, req->in.vector_count));
2679 status = smbd_smb2_request_validate(req);
2680 if (!NT_STATUS_IS_OK(status)) {
2681 smbd_server_connection_terminate(sconn, nt_errstr(status));
2685 status = smbd_smb2_request_setup_out(req);
2686 if (!NT_STATUS_IS_OK(status)) {
2687 smbd_server_connection_terminate(sconn, nt_errstr(status));
2691 status = smbd_smb2_request_dispatch(req);
2692 if (!NT_STATUS_IS_OK(status)) {
2693 smbd_server_connection_terminate(sconn, nt_errstr(status));
2698 status = smbd_smb2_request_next_incoming(sconn);
2699 if (!NT_STATUS_IS_OK(status)) {
2700 smbd_server_connection_terminate(sconn, nt_errstr(status));
2704 sconn->num_requests++;
2706 /* The timeout_processing function isn't run nearly
2707 often enough to implement 'max log size' without
2708 overrunning the size of the file by many megabytes.
2709 This is especially true if we are running at debug
2710 level 10. Checking every 50 SMB2s is a nice
2711 tradeoff of performance vs log file size overrun. */
2713 if ((sconn->num_requests % 50) == 0 &&
2714 need_to_check_log_size()) {
2715 change_to_root_user();