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;
714 newreq->async = false;
715 newreq->cancelled = false;
716 /* Note we are leaving:
720 uninitialized as NULL here as
721 they're not used in the interim
722 response code. JRA. */
724 outvec = talloc_zero_array(newreq, struct iovec, count);
729 newreq->out.vector = outvec;
730 newreq->out.vector_count = count;
732 /* Setup the outvec's identically to req. */
733 outvec[0].iov_base = newreq->out.nbt_hdr;
734 outvec[0].iov_len = 4;
735 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
737 /* Setup the vectors identically to the ones in req. */
738 for (i = 1; i < count; i += 3) {
739 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
750 smb2_setup_nbt_length(newreq->out.vector,
751 newreq->out.vector_count);
756 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
758 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
761 uint8_t *outhdr = NULL;
762 struct smbd_smb2_request *nreq = NULL;
764 /* Create a new smb2 request we'll use
765 for the interim return. */
766 nreq = dup_smb2_req(req);
768 return NT_STATUS_NO_MEMORY;
771 /* Lose the last 3 out vectors. They're the
772 ones we'll be using for the async reply. */
773 nreq->out.vector_count -= 3;
775 smb2_setup_nbt_length(nreq->out.vector,
776 nreq->out.vector_count);
778 /* Step back to the previous reply. */
779 i = nreq->current_idx - 3;
780 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
781 /* And end the chain. */
782 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
784 /* Calculate outgoing credits */
785 smb2_calculate_credits(req, nreq);
787 /* Re-sign if needed. */
788 if (nreq->do_signing) {
790 status = smb2_signing_sign_pdu(nreq->session->session_key,
791 &nreq->out.vector[i], 3);
792 if (!NT_STATUS_IS_OK(status)) {
796 if (DEBUGLEVEL >= 10) {
797 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
798 (unsigned int)nreq->current_idx );
799 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
800 (unsigned int)nreq->out.vector_count );
801 print_req_vectors(nreq);
803 nreq->subreq = tstream_writev_queue_send(nreq,
804 nreq->sconn->smb2.event_ctx,
805 nreq->sconn->smb2.stream,
806 nreq->sconn->smb2.send_queue,
808 nreq->out.vector_count);
810 if (nreq->subreq == NULL) {
811 return NT_STATUS_NO_MEMORY;
814 tevent_req_set_callback(nreq->subreq,
815 smbd_smb2_request_writev_done,
821 struct smbd_smb2_request_pending_state {
822 struct smbd_server_connection *sconn;
823 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
824 struct iovec vector[3];
827 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
829 struct smbd_smb2_request_pending_state *state =
830 tevent_req_callback_data(subreq,
831 struct smbd_smb2_request_pending_state);
832 struct smbd_server_connection *sconn = state->sconn;
836 ret = tstream_writev_queue_recv(subreq, &sys_errno);
839 NTSTATUS status = map_nt_error_from_unix(sys_errno);
840 smbd_server_connection_terminate(sconn, nt_errstr(status));
847 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
848 struct tevent_req *subreq)
851 struct smbd_smb2_request_pending_state *state = NULL;
852 int i = req->current_idx;
853 uint8_t *reqhdr = NULL;
855 uint8_t *body = NULL;
857 uint64_t message_id = 0;
858 uint64_t async_id = 0;
859 struct iovec *outvec = NULL;
861 if (!tevent_req_is_in_progress(subreq)) {
865 req->subreq = subreq;
869 /* We're already async. */
873 if (req->in.vector_count > i + 3) {
875 * We're trying to go async in a compound
876 * request chain. This is not allowed.
877 * Cancel the outstanding request.
879 tevent_req_cancel(req->subreq);
880 return smbd_smb2_request_error(req,
881 NT_STATUS_INSUFFICIENT_RESOURCES);
884 if (DEBUGLEVEL >= 10) {
885 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
886 (unsigned int)req->current_idx );
887 print_req_vectors(req);
890 if (req->out.vector_count > 4) {
891 /* This is a compound reply. We
892 * must do an interim response
893 * followed by the async response
896 status = smb2_send_async_interim_response(req);
897 if (!NT_STATUS_IS_OK(status)) {
902 * We're splitting off the last SMB2
903 * request in a compound set, and the
904 * smb2_send_async_interim_response()
905 * call above just sent all the replies
906 * for the previous SMB2 requests in
907 * this compound set. So we're no longer
908 * in the "compound_related_in_progress"
909 * state, and this is no longer a compound
912 req->compound_related = false;
913 req->sconn->smb2.compound_related_in_progress = false;
916 /* Don't return an intermediate packet on a pipe read/write. */
917 if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
921 reqhdr = (uint8_t *)req->out.vector[i].iov_base;
922 flags = (IVAL(reqhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
923 message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
924 async_id = message_id; /* keep it simple for now... */
927 * What we send is identical to a smbd_smb2_request_error
928 * packet with an error status of STATUS_PENDING. Make use
929 * of this fact sometime when refactoring. JRA.
932 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
934 return NT_STATUS_NO_MEMORY;
936 state->sconn = req->sconn;
938 state->vector[0].iov_base = (void *)state->buf;
939 state->vector[0].iov_len = 4;
941 state->vector[1].iov_base = state->buf + 4;
942 state->vector[1].iov_len = SMB2_HDR_BODY;
944 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
945 state->vector[2].iov_len = 9;
947 smb2_setup_nbt_length(state->vector, 3);
949 hdr = (uint8_t *)state->vector[1].iov_base;
950 body = (uint8_t *)state->vector[2].iov_base;
952 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
953 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
954 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
955 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
956 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(reqhdr, SMB2_HDR_OPCODE));
958 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
959 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
960 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
961 SBVAL(hdr, SMB2_HDR_PID, async_id);
962 SBVAL(hdr, SMB2_HDR_SESSION_ID,
963 BVAL(reqhdr, SMB2_HDR_SESSION_ID));
964 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
966 SSVAL(body, 0x00, 0x08 + 1);
968 SCVAL(body, 0x02, 0);
969 SCVAL(body, 0x03, 0);
970 SIVAL(body, 0x04, 0);
971 /* Match W2K8R2... */
972 SCVAL(body, 0x08, 0x21);
974 /* Ensure we correctly go through crediting. Grant
975 the credits now, and zero credits on the final
977 smb2_set_operation_credit(req->sconn,
981 if (req->do_signing) {
982 status = smb2_signing_sign_pdu(req->session->session_key,
983 &state->vector[1], 2);
984 if (!NT_STATUS_IS_OK(status)) {
989 subreq = tstream_writev_queue_send(state,
990 req->sconn->smb2.event_ctx,
991 req->sconn->smb2.stream,
992 req->sconn->smb2.send_queue,
996 if (subreq == NULL) {
997 return NT_STATUS_NO_MEMORY;
1000 tevent_req_set_callback(subreq,
1001 smbd_smb2_request_pending_writev_done,
1004 /* Note we're going async with this request. */
1010 * Now manipulate req so that the outstanding async request
1011 * is the only one left in the struct smbd_smb2_request.
1014 if (req->current_idx == 1) {
1015 /* There was only one. */
1019 /* Re-arrange the in.vectors. */
1020 req->in.vector[1] = req->in.vector[i];
1021 req->in.vector[2] = req->in.vector[i+1];
1022 req->in.vector[3] = req->in.vector[i+2];
1023 req->in.vector_count = 4;
1024 /* Reset the new in size. */
1025 smb2_setup_nbt_length(req->in.vector, 4);
1027 /* Now recreate the out.vectors. */
1028 outvec = talloc_zero_array(req, struct iovec, 4);
1030 return NT_STATUS_NO_MEMORY;
1033 /* 0 is always boilerplate and must
1034 * be of size 4 for the length field. */
1036 outvec[0].iov_base = req->out.nbt_hdr;
1037 outvec[0].iov_len = 4;
1038 SIVAL(req->out.nbt_hdr, 0, 0);
1040 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
1041 return NT_STATUS_NO_MEMORY;
1044 TALLOC_FREE(req->out.vector);
1046 req->out.vector = outvec;
1048 req->current_idx = 1;
1049 req->out.vector_count = 4;
1053 smb2_setup_nbt_length(req->out.vector,
1054 req->out.vector_count);
1057 /* Ensure our final reply matches the interim one. */
1058 reqhdr = (uint8_t *)req->out.vector[1].iov_base;
1059 SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1060 SBVAL(reqhdr, SMB2_HDR_PID, async_id);
1063 const uint8_t *inhdr =
1064 (const uint8_t *)req->in.vector[1].iov_base;
1065 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1067 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1068 (unsigned long long)async_id ));
1072 return NT_STATUS_OK;
1075 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1077 struct smbd_server_connection *sconn = req->sconn;
1078 struct smbd_smb2_request *cur;
1079 const uint8_t *inhdr;
1080 int i = req->current_idx;
1082 uint64_t search_message_id;
1083 uint64_t search_async_id;
1086 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1088 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1089 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1090 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1093 * we don't need the request anymore
1094 * cancel requests never have a response
1096 DLIST_REMOVE(req->sconn->smb2.requests, req);
1099 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1100 const uint8_t *outhdr;
1101 uint64_t message_id;
1104 i = cur->current_idx;
1106 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1108 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1109 async_id = BVAL(outhdr, SMB2_HDR_PID);
1111 if (flags & SMB2_HDR_FLAG_ASYNC) {
1112 if (search_async_id == async_id) {
1113 found_id = async_id;
1117 if (search_message_id == message_id) {
1118 found_id = message_id;
1124 if (cur && cur->subreq) {
1125 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1126 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1127 "cancel opcode[%s] mid %llu\n",
1128 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1129 (unsigned long long)found_id ));
1130 tevent_req_cancel(cur->subreq);
1133 return NT_STATUS_OK;
1136 /*************************************************************
1137 Ensure an incoming tid is a valid one for us to access.
1138 Change to the associated uid credentials and chdir to the
1139 valid tid directory.
1140 *************************************************************/
1142 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1144 const uint8_t *inhdr;
1145 int i = req->current_idx;
1149 struct smbd_smb2_tcon *tcon;
1153 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1155 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1156 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1158 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1159 in_tid = req->last_tid;
1162 /* lookup an existing session */
1163 p = idr_find(req->session->tcons.idtree, in_tid);
1165 return NT_STATUS_NETWORK_NAME_DELETED;
1167 tcon = talloc_get_type_abort(p, struct smbd_smb2_tcon);
1169 if (!change_to_user(tcon->compat_conn,req->session->vuid)) {
1170 return NT_STATUS_ACCESS_DENIED;
1173 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1174 if (!set_current_service(tcon->compat_conn, 0, true)) {
1175 return NT_STATUS_ACCESS_DENIED;
1179 req->last_tid = in_tid;
1181 return NT_STATUS_OK;
1184 /*************************************************************
1185 Ensure an incoming session_id is a valid one for us to access.
1186 *************************************************************/
1188 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1190 const uint8_t *inhdr;
1191 int i = req->current_idx;
1193 uint64_t in_session_id;
1195 struct smbd_smb2_session *session;
1197 req->session = NULL;
1200 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1202 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1203 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1205 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1206 in_session_id = req->last_session_id;
1209 /* lookup an existing session */
1210 p = idr_find(req->sconn->smb2.sessions.idtree, in_session_id);
1212 return NT_STATUS_USER_SESSION_DELETED;
1214 session = talloc_get_type_abort(p, struct smbd_smb2_session);
1216 if (!NT_STATUS_IS_OK(session->status)) {
1217 return NT_STATUS_ACCESS_DENIED;
1220 set_current_user_info(session->session_info->unix_info->sanitized_username,
1221 session->session_info->unix_info->unix_name,
1222 session->session_info->info->domain_name);
1224 req->session = session;
1225 req->last_session_id = in_session_id;
1227 return NT_STATUS_OK;
1230 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1231 size_t expected_body_size)
1233 const uint8_t *inhdr;
1235 const uint8_t *inbody;
1236 int i = req->current_idx;
1238 size_t min_dyn_size = expected_body_size & 0x00000001;
1241 * The following should be checked already.
1243 if ((i+2) > req->in.vector_count) {
1244 return NT_STATUS_INTERNAL_ERROR;
1246 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1247 return NT_STATUS_INTERNAL_ERROR;
1249 if (req->in.vector[i+1].iov_len < 2) {
1250 return NT_STATUS_INTERNAL_ERROR;
1253 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1254 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1258 case SMB2_OP_GETINFO:
1264 * Now check the expected body size,
1265 * where the last byte might be in the
1266 * dynnamic section..
1268 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1269 return NT_STATUS_INVALID_PARAMETER;
1271 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1272 return NT_STATUS_INVALID_PARAMETER;
1275 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1277 body_size = SVAL(inbody, 0x00);
1278 if (body_size != expected_body_size) {
1279 return NT_STATUS_INVALID_PARAMETER;
1282 return NT_STATUS_OK;
1285 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1287 const uint8_t *inhdr;
1288 int i = req->current_idx;
1293 NTSTATUS session_status;
1294 uint32_t allowed_flags;
1295 NTSTATUS return_value;
1297 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1299 /* TODO: verify more things */
1301 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1302 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1303 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1304 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1305 smb2_opcode_name(opcode),
1306 (unsigned long long)mid));
1308 if (get_Protocol() >= PROTOCOL_SMB2_02) {
1310 * once the protocol is negotiated
1311 * SMB2_OP_NEGPROT is not allowed anymore
1313 if (opcode == SMB2_OP_NEGPROT) {
1314 /* drop the connection */
1315 return NT_STATUS_INVALID_PARAMETER;
1319 * if the protocol is not negotiated yet
1320 * only SMB2_OP_NEGPROT is allowed.
1322 if (opcode != SMB2_OP_NEGPROT) {
1323 /* drop the connection */
1324 return NT_STATUS_INVALID_PARAMETER;
1328 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1329 SMB2_HDR_FLAG_SIGNED |
1331 if (opcode == SMB2_OP_CANCEL) {
1332 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1334 if ((flags & ~allowed_flags) != 0) {
1335 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1339 * Check if the client provided a valid session id,
1340 * if so smbd_smb2_request_check_session() calls
1341 * set_current_user_info().
1343 * As some command don't require a valid session id
1344 * we defer the check of the session_status
1346 session_status = smbd_smb2_request_check_session(req);
1348 req->do_signing = false;
1349 if (flags & SMB2_HDR_FLAG_SIGNED) {
1350 if (!NT_STATUS_IS_OK(session_status)) {
1351 return smbd_smb2_request_error(req, session_status);
1354 req->do_signing = true;
1355 status = smb2_signing_check_pdu(req->session->session_key,
1356 &req->in.vector[i], 3);
1357 if (!NT_STATUS_IS_OK(status)) {
1358 return smbd_smb2_request_error(req, status);
1360 } else if (opcode == SMB2_OP_CANCEL) {
1361 /* Cancel requests are allowed to skip the signing */
1362 } else if (req->session && req->session->do_signing) {
1363 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1366 if (flags & SMB2_HDR_FLAG_CHAINED) {
1368 * This check is mostly for giving the correct error code
1369 * for compounded requests.
1371 * TODO: we may need to move this after the session
1374 if (!NT_STATUS_IS_OK(req->next_status)) {
1375 return smbd_smb2_request_error(req, req->next_status);
1378 req->compat_chain_fsp = NULL;
1381 if (req->compound_related) {
1382 req->sconn->smb2.compound_related_in_progress = true;
1386 case SMB2_OP_NEGPROT:
1387 /* This call needs to be run as root */
1388 change_to_root_user();
1391 START_PROFILE(smb2_negprot);
1392 return_value = smbd_smb2_request_process_negprot(req);
1393 END_PROFILE(smb2_negprot);
1397 case SMB2_OP_SESSSETUP:
1398 /* This call needs to be run as root */
1399 change_to_root_user();
1402 START_PROFILE(smb2_sesssetup);
1403 return_value = smbd_smb2_request_process_sesssetup(req);
1404 END_PROFILE(smb2_sesssetup);
1408 case SMB2_OP_LOGOFF:
1409 if (!NT_STATUS_IS_OK(session_status)) {
1410 return_value = smbd_smb2_request_error(req, session_status);
1414 /* This call needs to be run as root */
1415 change_to_root_user();
1418 START_PROFILE(smb2_logoff);
1419 return_value = smbd_smb2_request_process_logoff(req);
1420 END_PROFILE(smb2_logoff);
1425 if (!NT_STATUS_IS_OK(session_status)) {
1426 return_value = smbd_smb2_request_error(req, session_status);
1431 * This call needs to be run as root.
1433 * smbd_smb2_request_process_tcon()
1434 * calls make_connection_snum(), which will call
1435 * change_to_user(), when needed.
1437 change_to_root_user();
1440 START_PROFILE(smb2_tcon);
1441 return_value = smbd_smb2_request_process_tcon(req);
1442 END_PROFILE(smb2_tcon);
1447 if (!NT_STATUS_IS_OK(session_status)) {
1448 return_value = smbd_smb2_request_error(req, session_status);
1452 * This call needs to be run as user.
1454 * smbd_smb2_request_check_tcon()
1455 * calls change_to_user() on success.
1457 status = smbd_smb2_request_check_tcon(req);
1458 if (!NT_STATUS_IS_OK(status)) {
1459 return_value = smbd_smb2_request_error(req, status);
1462 /* This call needs to be run as root */
1463 change_to_root_user();
1467 START_PROFILE(smb2_tdis);
1468 return_value = smbd_smb2_request_process_tdis(req);
1469 END_PROFILE(smb2_tdis);
1473 case SMB2_OP_CREATE:
1474 if (!NT_STATUS_IS_OK(session_status)) {
1475 return_value = smbd_smb2_request_error(req, session_status);
1479 * This call needs to be run as user.
1481 * smbd_smb2_request_check_tcon()
1482 * calls change_to_user() on success.
1484 status = smbd_smb2_request_check_tcon(req);
1485 if (!NT_STATUS_IS_OK(status)) {
1486 return_value = smbd_smb2_request_error(req, status);
1491 START_PROFILE(smb2_create);
1492 return_value = smbd_smb2_request_process_create(req);
1493 END_PROFILE(smb2_create);
1498 if (!NT_STATUS_IS_OK(session_status)) {
1499 return_value = smbd_smb2_request_error(req, session_status);
1503 * This call needs to be run as user.
1505 * smbd_smb2_request_check_tcon()
1506 * calls change_to_user() on success.
1508 status = smbd_smb2_request_check_tcon(req);
1509 if (!NT_STATUS_IS_OK(status)) {
1510 return_value = smbd_smb2_request_error(req, status);
1515 START_PROFILE(smb2_close);
1516 return_value = smbd_smb2_request_process_close(req);
1517 END_PROFILE(smb2_close);
1522 if (!NT_STATUS_IS_OK(session_status)) {
1523 return_value = smbd_smb2_request_error(req, session_status);
1527 * This call needs to be run as user.
1529 * smbd_smb2_request_check_tcon()
1530 * calls change_to_user() on success.
1532 status = smbd_smb2_request_check_tcon(req);
1533 if (!NT_STATUS_IS_OK(status)) {
1534 return_value = smbd_smb2_request_error(req, status);
1539 START_PROFILE(smb2_flush);
1540 return_value = smbd_smb2_request_process_flush(req);
1541 END_PROFILE(smb2_flush);
1546 if (!NT_STATUS_IS_OK(session_status)) {
1547 return_value = smbd_smb2_request_error(req, session_status);
1551 * This call needs to be run as user.
1553 * smbd_smb2_request_check_tcon()
1554 * calls change_to_user() on success.
1556 status = smbd_smb2_request_check_tcon(req);
1557 if (!NT_STATUS_IS_OK(status)) {
1558 return_value = smbd_smb2_request_error(req, status);
1563 START_PROFILE(smb2_read);
1564 return_value = smbd_smb2_request_process_read(req);
1565 END_PROFILE(smb2_read);
1570 if (!NT_STATUS_IS_OK(session_status)) {
1571 return_value = smbd_smb2_request_error(req, session_status);
1575 * This call needs to be run as user.
1577 * smbd_smb2_request_check_tcon()
1578 * calls change_to_user() on success.
1580 status = smbd_smb2_request_check_tcon(req);
1581 if (!NT_STATUS_IS_OK(status)) {
1582 return_value = smbd_smb2_request_error(req, status);
1587 START_PROFILE(smb2_write);
1588 return_value = smbd_smb2_request_process_write(req);
1589 END_PROFILE(smb2_write);
1594 if (!NT_STATUS_IS_OK(session_status)) {
1595 /* Too ugly to live ? JRA. */
1596 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1597 session_status = NT_STATUS_FILE_CLOSED;
1599 return_value = smbd_smb2_request_error(req, session_status);
1603 * This call needs to be run as user.
1605 * smbd_smb2_request_check_tcon()
1606 * calls change_to_user() on success.
1608 status = smbd_smb2_request_check_tcon(req);
1609 if (!NT_STATUS_IS_OK(status)) {
1610 /* Too ugly to live ? JRA. */
1611 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1612 status = NT_STATUS_FILE_CLOSED;
1614 return_value = smbd_smb2_request_error(req, status);
1619 START_PROFILE(smb2_lock);
1620 return_value = smbd_smb2_request_process_lock(req);
1621 END_PROFILE(smb2_lock);
1626 if (!NT_STATUS_IS_OK(session_status)) {
1627 return_value = smbd_smb2_request_error(req, session_status);
1631 * This call needs to be run as user.
1633 * smbd_smb2_request_check_tcon()
1634 * calls change_to_user() on success.
1636 status = smbd_smb2_request_check_tcon(req);
1637 if (!NT_STATUS_IS_OK(status)) {
1638 return_value = smbd_smb2_request_error(req, status);
1643 START_PROFILE(smb2_ioctl);
1644 return_value = smbd_smb2_request_process_ioctl(req);
1645 END_PROFILE(smb2_ioctl);
1649 case SMB2_OP_CANCEL:
1651 * This call needs to be run as root
1653 * That is what we also do in the SMB1 case.
1655 change_to_root_user();
1658 START_PROFILE(smb2_cancel);
1659 return_value = smbd_smb2_request_process_cancel(req);
1660 END_PROFILE(smb2_cancel);
1664 case SMB2_OP_KEEPALIVE:
1665 /* This call needs to be run as root */
1666 change_to_root_user();
1669 START_PROFILE(smb2_keepalive);
1670 return_value = smbd_smb2_request_process_keepalive(req);
1671 END_PROFILE(smb2_keepalive);
1676 if (!NT_STATUS_IS_OK(session_status)) {
1677 return_value = smbd_smb2_request_error(req, session_status);
1681 * This call needs to be run as user.
1683 * smbd_smb2_request_check_tcon()
1684 * calls change_to_user() on success.
1686 status = smbd_smb2_request_check_tcon(req);
1687 if (!NT_STATUS_IS_OK(status)) {
1688 return_value = smbd_smb2_request_error(req, status);
1693 START_PROFILE(smb2_find);
1694 return_value = smbd_smb2_request_process_find(req);
1695 END_PROFILE(smb2_find);
1699 case SMB2_OP_NOTIFY:
1700 if (!NT_STATUS_IS_OK(session_status)) {
1701 return_value = smbd_smb2_request_error(req, session_status);
1705 * This call needs to be run as user.
1707 * smbd_smb2_request_check_tcon()
1708 * calls change_to_user() on success.
1710 status = smbd_smb2_request_check_tcon(req);
1711 if (!NT_STATUS_IS_OK(status)) {
1712 return_value = smbd_smb2_request_error(req, status);
1717 START_PROFILE(smb2_notify);
1718 return_value = smbd_smb2_request_process_notify(req);
1719 END_PROFILE(smb2_notify);
1723 case SMB2_OP_GETINFO:
1724 if (!NT_STATUS_IS_OK(session_status)) {
1725 return_value = smbd_smb2_request_error(req, session_status);
1729 * This call needs to be run as user.
1731 * smbd_smb2_request_check_tcon()
1732 * calls change_to_user() on success.
1734 status = smbd_smb2_request_check_tcon(req);
1735 if (!NT_STATUS_IS_OK(status)) {
1736 return_value = smbd_smb2_request_error(req, status);
1741 START_PROFILE(smb2_getinfo);
1742 return_value = smbd_smb2_request_process_getinfo(req);
1743 END_PROFILE(smb2_getinfo);
1747 case SMB2_OP_SETINFO:
1748 if (!NT_STATUS_IS_OK(session_status)) {
1749 return_value = smbd_smb2_request_error(req, session_status);
1753 * This call needs to be run as user.
1755 * smbd_smb2_request_check_tcon()
1756 * calls change_to_user() on success.
1758 status = smbd_smb2_request_check_tcon(req);
1759 if (!NT_STATUS_IS_OK(status)) {
1760 return_value = smbd_smb2_request_error(req, status);
1765 START_PROFILE(smb2_setinfo);
1766 return_value = smbd_smb2_request_process_setinfo(req);
1767 END_PROFILE(smb2_setinfo);
1772 if (!NT_STATUS_IS_OK(session_status)) {
1773 return_value = smbd_smb2_request_error(req, session_status);
1777 * This call needs to be run as user.
1779 * smbd_smb2_request_check_tcon()
1780 * calls change_to_user() on success.
1782 status = smbd_smb2_request_check_tcon(req);
1783 if (!NT_STATUS_IS_OK(status)) {
1784 return_value = smbd_smb2_request_error(req, status);
1789 START_PROFILE(smb2_break);
1790 return_value = smbd_smb2_request_process_break(req);
1791 END_PROFILE(smb2_break);
1796 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1799 return return_value;
1802 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1804 struct tevent_req *subreq;
1805 int i = req->current_idx;
1809 req->current_idx += 3;
1811 if (req->current_idx < req->out.vector_count) {
1813 * We must process the remaining compound
1814 * SMB2 requests before any new incoming SMB2
1815 * requests. This is because incoming SMB2
1816 * requests may include a cancel for a
1817 * compound request we haven't processed
1820 struct tevent_immediate *im = tevent_create_immediate(req);
1822 return NT_STATUS_NO_MEMORY;
1824 tevent_schedule_immediate(im,
1825 req->sconn->smb2.event_ctx,
1826 smbd_smb2_request_dispatch_immediate,
1828 return NT_STATUS_OK;
1831 if (req->compound_related) {
1832 req->sconn->smb2.compound_related_in_progress = false;
1835 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1837 /* Set credit for this operation (zero credits if this
1838 is a final reply for an async operation). */
1839 smb2_set_operation_credit(req->sconn,
1841 &req->out.vector[i]);
1843 if (req->do_signing) {
1845 status = smb2_signing_sign_pdu(req->session->session_key,
1846 &req->out.vector[i], 3);
1847 if (!NT_STATUS_IS_OK(status)) {
1852 if (DEBUGLEVEL >= 10) {
1853 dbgtext("smbd_smb2_request_reply: sending...\n");
1854 print_req_vectors(req);
1857 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1858 if (req->out.vector_count == 4 &&
1859 req->out.vector[3].iov_base == NULL &&
1860 req->out.vector[3].iov_len != 0) {
1861 /* Dynamic part is NULL. Chop it off,
1862 We're going to send it via sendfile. */
1863 req->out.vector_count -= 1;
1866 subreq = tstream_writev_queue_send(req,
1867 req->sconn->smb2.event_ctx,
1868 req->sconn->smb2.stream,
1869 req->sconn->smb2.send_queue,
1871 req->out.vector_count);
1872 if (subreq == NULL) {
1873 return NT_STATUS_NO_MEMORY;
1875 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1877 * We're done with this request -
1878 * move it off the "being processed" queue.
1880 DLIST_REMOVE(req->sconn->smb2.requests, req);
1882 return NT_STATUS_OK;
1885 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
1887 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1888 struct tevent_immediate *im,
1891 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1892 struct smbd_smb2_request);
1893 struct smbd_server_connection *sconn = req->sconn;
1898 if (DEBUGLEVEL >= 10) {
1899 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1900 req->current_idx, req->in.vector_count));
1901 print_req_vectors(req);
1904 status = smbd_smb2_request_dispatch(req);
1905 if (!NT_STATUS_IS_OK(status)) {
1906 smbd_server_connection_terminate(sconn, nt_errstr(status));
1910 status = smbd_smb2_request_next_incoming(sconn);
1911 if (!NT_STATUS_IS_OK(status)) {
1912 smbd_server_connection_terminate(sconn, nt_errstr(status));
1917 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1919 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1920 struct smbd_smb2_request);
1921 struct smbd_server_connection *sconn = req->sconn;
1926 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1927 TALLOC_FREE(subreq);
1930 status = map_nt_error_from_unix(sys_errno);
1931 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1932 nt_errstr(status)));
1933 smbd_server_connection_terminate(sconn, nt_errstr(status));
1937 status = smbd_smb2_request_next_incoming(sconn);
1938 if (!NT_STATUS_IS_OK(status)) {
1939 smbd_server_connection_terminate(sconn, nt_errstr(status));
1944 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1946 DATA_BLOB body, DATA_BLOB *dyn,
1947 const char *location)
1950 int i = req->current_idx;
1951 uint32_t next_command_ofs;
1953 DEBUG(10,("smbd_smb2_request_done_ex: "
1954 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1955 i, nt_errstr(status), (unsigned int)body.length,
1957 (unsigned int)(dyn ? dyn->length : 0),
1960 if (body.length < 2) {
1961 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1964 if ((body.length % 2) != 0) {
1965 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1968 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1970 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1971 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1973 req->out.vector[i+1].iov_base = (void *)body.data;
1974 req->out.vector[i+1].iov_len = body.length;
1977 req->out.vector[i+2].iov_base = (void *)dyn->data;
1978 req->out.vector[i+2].iov_len = dyn->length;
1980 req->out.vector[i+2].iov_base = NULL;
1981 req->out.vector[i+2].iov_len = 0;
1984 /* see if we need to recalculate the offset to the next response */
1985 if (next_command_ofs > 0) {
1986 next_command_ofs = SMB2_HDR_BODY;
1987 next_command_ofs += req->out.vector[i+1].iov_len;
1988 next_command_ofs += req->out.vector[i+2].iov_len;
1991 if ((next_command_ofs % 8) != 0) {
1992 size_t pad_size = 8 - (next_command_ofs % 8);
1993 if (req->out.vector[i+2].iov_len == 0) {
1995 * if the dyn buffer is empty
1996 * we can use it to add padding
2000 pad = talloc_zero_array(req->out.vector,
2003 return smbd_smb2_request_error(req,
2004 NT_STATUS_NO_MEMORY);
2007 req->out.vector[i+2].iov_base = (void *)pad;
2008 req->out.vector[i+2].iov_len = pad_size;
2011 * For now we copy the dynamic buffer
2012 * and add the padding to the new buffer
2019 old_size = req->out.vector[i+2].iov_len;
2020 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2022 new_size = old_size + pad_size;
2023 new_dyn = talloc_zero_array(req->out.vector,
2025 if (new_dyn == NULL) {
2026 return smbd_smb2_request_error(req,
2027 NT_STATUS_NO_MEMORY);
2030 memcpy(new_dyn, old_dyn, old_size);
2031 memset(new_dyn + old_size, 0, pad_size);
2033 req->out.vector[i+2].iov_base = (void *)new_dyn;
2034 req->out.vector[i+2].iov_len = new_size;
2036 next_command_ofs += pad_size;
2039 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2041 return smbd_smb2_request_reply(req);
2044 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2047 const char *location)
2050 int i = req->current_idx;
2051 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
2053 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2054 i, nt_errstr(status), info ? " +info" : "",
2057 body.data = outhdr + SMB2_HDR_BODY;
2059 SSVAL(body.data, 0, 9);
2062 SIVAL(body.data, 0x04, info->length);
2064 /* Allocated size of req->out.vector[i].iov_base
2065 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2066 * 1 byte without having to do an alloc.
2068 info = talloc_zero_array(req->out.vector,
2072 return NT_STATUS_NO_MEMORY;
2074 info->data = ((uint8_t *)outhdr) +
2075 OUTVEC_ALLOC_SIZE - 1;
2077 SCVAL(info->data, 0, 0);
2081 * if a request fails, all other remaining
2082 * compounded requests should fail too
2084 req->next_status = NT_STATUS_INVALID_PARAMETER;
2086 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2090 struct smbd_smb2_send_oplock_break_state {
2091 struct smbd_server_connection *sconn;
2092 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2093 struct iovec vector;
2096 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2098 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2099 uint64_t file_id_persistent,
2100 uint64_t file_id_volatile,
2101 uint8_t oplock_level)
2103 struct smbd_smb2_send_oplock_break_state *state;
2104 struct tevent_req *subreq;
2108 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2109 if (state == NULL) {
2110 return NT_STATUS_NO_MEMORY;
2112 state->sconn = sconn;
2114 state->vector.iov_base = (void *)state->buf;
2115 state->vector.iov_len = sizeof(state->buf);
2117 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2118 hdr = state->buf + 4;
2119 body = hdr + SMB2_HDR_BODY;
2121 SIVAL(hdr, 0, SMB2_MAGIC);
2122 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2123 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2124 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2125 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2126 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2127 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2128 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2129 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2130 SIVAL(hdr, SMB2_HDR_PID, 0);
2131 SIVAL(hdr, SMB2_HDR_TID, 0);
2132 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2133 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2135 SSVAL(body, 0x00, 0x18);
2137 SCVAL(body, 0x02, oplock_level);
2138 SCVAL(body, 0x03, 0); /* reserved */
2139 SIVAL(body, 0x04, 0); /* reserved */
2140 SBVAL(body, 0x08, file_id_persistent);
2141 SBVAL(body, 0x10, file_id_volatile);
2143 subreq = tstream_writev_queue_send(state,
2144 sconn->smb2.event_ctx,
2146 sconn->smb2.send_queue,
2148 if (subreq == NULL) {
2149 return NT_STATUS_NO_MEMORY;
2151 tevent_req_set_callback(subreq,
2152 smbd_smb2_oplock_break_writev_done,
2155 return NT_STATUS_OK;
2158 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2160 struct smbd_smb2_send_oplock_break_state *state =
2161 tevent_req_callback_data(subreq,
2162 struct smbd_smb2_send_oplock_break_state);
2163 struct smbd_server_connection *sconn = state->sconn;
2167 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2168 TALLOC_FREE(subreq);
2170 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2171 smbd_server_connection_terminate(sconn, nt_errstr(status));
2178 struct smbd_smb2_request_read_state {
2180 bool asked_for_header;
2181 struct smbd_smb2_request *smb2_req;
2184 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2186 TALLOC_CTX *mem_ctx,
2187 struct iovec **_vector,
2189 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2191 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2192 struct tevent_context *ev,
2193 struct smbd_server_connection *sconn)
2195 struct tevent_req *req;
2196 struct smbd_smb2_request_read_state *state;
2197 struct tevent_req *subreq;
2199 req = tevent_req_create(mem_ctx, &state,
2200 struct smbd_smb2_request_read_state);
2205 state->asked_for_header = false;
2207 state->smb2_req = smbd_smb2_request_allocate(state);
2208 if (tevent_req_nomem(state->smb2_req, req)) {
2209 return tevent_req_post(req, ev);
2211 state->smb2_req->sconn = sconn;
2213 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2214 sconn->smb2.recv_queue,
2215 smbd_smb2_request_next_vector,
2217 if (tevent_req_nomem(subreq, req)) {
2218 return tevent_req_post(req, ev);
2220 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2225 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2227 TALLOC_CTX *mem_ctx,
2228 struct iovec **_vector,
2231 struct smbd_smb2_request_read_state *state =
2232 talloc_get_type_abort(private_data,
2233 struct smbd_smb2_request_read_state);
2234 struct smbd_smb2_request *req = state->smb2_req;
2235 struct iovec *vector;
2236 int idx = req->in.vector_count;
2238 uint8_t *buf = NULL;
2240 if (req->in.vector_count == 0) {
2242 * first we need to get the NBT header
2244 req->in.vector = talloc_array(req, struct iovec,
2245 req->in.vector_count + 1);
2246 if (req->in.vector == NULL) {
2249 req->in.vector_count += 1;
2251 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2252 req->in.vector[idx].iov_len = 4;
2254 vector = talloc_array(mem_ctx, struct iovec, 1);
2255 if (vector == NULL) {
2259 vector[0] = req->in.vector[idx];
2266 if (req->in.vector_count == 1) {
2268 * Now we analyze the NBT header
2270 state->missing = smb2_len(req->in.vector[0].iov_base);
2272 if (state->missing == 0) {
2273 /* if there're no remaining bytes, we're done */
2279 req->in.vector = talloc_realloc(req, req->in.vector,
2281 req->in.vector_count + 1);
2282 if (req->in.vector == NULL) {
2285 req->in.vector_count += 1;
2287 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2289 * it's a special NBT message,
2290 * so get all remaining bytes
2292 len = state->missing;
2293 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2295 * it's an invalid message, just read what we can get
2296 * and let the caller handle the error
2298 len = state->missing;
2301 * We assume it's a SMB2 request,
2302 * and we first get the header and the
2303 * first 2 bytes (the struct size) of the body
2305 len = SMB2_HDR_BODY + 2;
2307 state->asked_for_header = true;
2310 state->missing -= len;
2312 buf = talloc_array(req->in.vector, uint8_t, len);
2317 req->in.vector[idx].iov_base = (void *)buf;
2318 req->in.vector[idx].iov_len = len;
2320 vector = talloc_array(mem_ctx, struct iovec, 1);
2321 if (vector == NULL) {
2325 vector[0] = req->in.vector[idx];
2332 if (state->missing == 0) {
2333 /* if there're no remaining bytes, we're done */
2339 if (state->asked_for_header) {
2342 size_t next_command_ofs;
2347 bool invalid = false;
2349 state->asked_for_header = false;
2352 * We got the SMB2 header and the first 2 bytes
2353 * of the body. We fix the size to just the header
2354 * and manually copy the 2 first bytes to the body section
2356 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2357 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2359 /* allocate vectors for body and dynamic areas */
2360 req->in.vector = talloc_realloc(req, req->in.vector,
2362 req->in.vector_count + 2);
2363 if (req->in.vector == NULL) {
2366 req->in.vector_count += 2;
2368 full_size = state->missing + SMB2_HDR_BODY + 2;
2369 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2370 body_size = SVAL(hdr, SMB2_HDR_BODY);
2372 if (next_command_ofs != 0) {
2373 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2375 * this is invalid, just return a zero
2376 * body and let the caller deal with the error
2379 } else if (next_command_ofs > full_size) {
2381 * this is invalid, just return a zero
2382 * body and let the caller deal with the error
2386 full_size = next_command_ofs;
2391 if (body_size < 2) {
2393 * this is invalid, just return a zero
2394 * body and let the caller deal with the error
2400 * Mask out the lowest bit, the "dynamic" part
2405 if (body_size > (full_size - SMB2_HDR_BODY)) {
2407 * this is invalid, just return a zero
2408 * body and let the caller deal with the error
2415 /* the caller should check this */
2419 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2421 state->missing -= (body_size - 2) + dyn_size;
2423 body = talloc_array(req->in.vector, uint8_t, body_size);
2428 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2433 req->in.vector[idx].iov_base = (void *)body;
2434 req->in.vector[idx].iov_len = body_size;
2435 req->in.vector[idx+1].iov_base = (void *)dyn;
2436 req->in.vector[idx+1].iov_len = dyn_size;
2438 vector = talloc_array(mem_ctx, struct iovec, 2);
2439 if (vector == NULL) {
2444 * the first 2 bytes of the body were already fetched
2445 * together with the header
2447 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2448 vector[0].iov_base = body + 2;
2449 vector[0].iov_len = body_size - 2;
2451 vector[1] = req->in.vector[idx+1];
2459 * when we endup here, we're looking for a new SMB2 request
2460 * next. And we ask for its header and the first 2 bytes of
2461 * the body (like we did for the first SMB2 request).
2464 req->in.vector = talloc_realloc(req, req->in.vector,
2466 req->in.vector_count + 1);
2467 if (req->in.vector == NULL) {
2470 req->in.vector_count += 1;
2473 * We assume it's a SMB2 request,
2474 * and we first get the header and the
2475 * first 2 bytes (the struct size) of the body
2477 len = SMB2_HDR_BODY + 2;
2479 if (len > state->missing) {
2480 /* let the caller handle the error */
2481 len = state->missing;
2484 state->missing -= len;
2485 state->asked_for_header = true;
2487 buf = talloc_array(req->in.vector, uint8_t, len);
2492 req->in.vector[idx].iov_base = (void *)buf;
2493 req->in.vector[idx].iov_len = len;
2495 vector = talloc_array(mem_ctx, struct iovec, 1);
2496 if (vector == NULL) {
2500 vector[0] = req->in.vector[idx];
2507 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2509 struct tevent_req *req =
2510 tevent_req_callback_data(subreq,
2516 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2518 status = map_nt_error_from_unix(sys_errno);
2519 tevent_req_nterror(req, status);
2523 tevent_req_done(req);
2526 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2527 TALLOC_CTX *mem_ctx,
2528 struct smbd_smb2_request **_smb2_req)
2530 struct smbd_smb2_request_read_state *state =
2531 tevent_req_data(req,
2532 struct smbd_smb2_request_read_state);
2535 if (tevent_req_is_nterror(req, &status)) {
2536 tevent_req_received(req);
2540 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2541 *_smb2_req = state->smb2_req;
2542 tevent_req_received(req);
2543 return NT_STATUS_OK;
2546 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2548 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2550 size_t max_send_queue_len;
2551 size_t cur_send_queue_len;
2552 struct tevent_req *subreq;
2554 if (sconn->smb2.compound_related_in_progress) {
2556 * Can't read another until the related
2559 return NT_STATUS_OK;
2562 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2564 * if there is already a smbd_smb2_request_read
2565 * pending, we are done.
2567 return NT_STATUS_OK;
2570 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2571 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2573 if (cur_send_queue_len > max_send_queue_len) {
2575 * if we have a lot of requests to send,
2576 * we wait until they are on the wire until we
2577 * ask for the next request.
2579 return NT_STATUS_OK;
2582 /* ask for the next request */
2583 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2584 if (subreq == NULL) {
2585 return NT_STATUS_NO_MEMORY;
2587 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2589 return NT_STATUS_OK;
2592 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2593 const uint8_t *inbuf, size_t size)
2596 struct smbd_smb2_request *req = NULL;
2598 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2599 (unsigned int)size));
2601 status = smbd_initialize_smb2(sconn);
2602 if (!NT_STATUS_IS_OK(status)) {
2603 smbd_server_connection_terminate(sconn, nt_errstr(status));
2607 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2608 if (!NT_STATUS_IS_OK(status)) {
2609 smbd_server_connection_terminate(sconn, nt_errstr(status));
2613 status = smbd_smb2_request_setup_out(req);
2614 if (!NT_STATUS_IS_OK(status)) {
2615 smbd_server_connection_terminate(sconn, nt_errstr(status));
2619 status = smbd_smb2_request_dispatch(req);
2620 if (!NT_STATUS_IS_OK(status)) {
2621 smbd_server_connection_terminate(sconn, nt_errstr(status));
2625 status = smbd_smb2_request_next_incoming(sconn);
2626 if (!NT_STATUS_IS_OK(status)) {
2627 smbd_server_connection_terminate(sconn, nt_errstr(status));
2631 sconn->num_requests++;
2634 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2636 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2637 struct smbd_server_connection);
2639 struct smbd_smb2_request *req = NULL;
2641 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2642 TALLOC_FREE(subreq);
2643 if (!NT_STATUS_IS_OK(status)) {
2644 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2645 nt_errstr(status)));
2646 smbd_server_connection_terminate(sconn, nt_errstr(status));
2650 if (req->in.nbt_hdr[0] != 0x00) {
2651 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2652 req->in.nbt_hdr[0]));
2657 req->current_idx = 1;
2659 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2660 req->current_idx, req->in.vector_count));
2662 status = smbd_smb2_request_validate(req);
2663 if (!NT_STATUS_IS_OK(status)) {
2664 smbd_server_connection_terminate(sconn, nt_errstr(status));
2668 status = smbd_smb2_request_setup_out(req);
2669 if (!NT_STATUS_IS_OK(status)) {
2670 smbd_server_connection_terminate(sconn, nt_errstr(status));
2674 status = smbd_smb2_request_dispatch(req);
2675 if (!NT_STATUS_IS_OK(status)) {
2676 smbd_server_connection_terminate(sconn, nt_errstr(status));
2681 status = smbd_smb2_request_next_incoming(sconn);
2682 if (!NT_STATUS_IS_OK(status)) {
2683 smbd_server_connection_terminate(sconn, nt_errstr(status));
2687 sconn->num_requests++;
2689 /* The timeout_processing function isn't run nearly
2690 often enough to implement 'max log size' without
2691 overrunning the size of the file by many megabytes.
2692 This is especially true if we are running at debug
2693 level 10. Checking every 50 SMB2s is a nice
2694 tradeoff of performance vs log file size overrun. */
2696 if ((sconn->num_requests % 50) == 0 &&
2697 need_to_check_log_size()) {
2698 change_to_root_user();