2 Unix SMB/CIFS implementation.
5 Copyright (C) Stefan Metzmacher 2009
6 Copyright (C) Jeremy Allison 2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../libcli/smb/smb_common.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "../lib/util/tevent_ntstatus.h"
28 #include "smbprofile.h"
30 #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9)
32 static const char *smb2_names[] = {
54 const char *smb2_opcode_name(uint16_t opcode)
57 return "Bad SMB2 opcode";
59 return smb2_names[opcode];
62 static void print_req_vectors(struct smbd_smb2_request *req)
66 for (i = 0; i < req->in.vector_count; i++) {
67 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
69 (unsigned int)req->in.vector[i].iov_len);
71 for (i = 0; i < req->out.vector_count; i++) {
72 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
74 (unsigned int)req->out.vector[i].iov_len);
78 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
80 if (size < (4 + SMB2_HDR_BODY)) {
84 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
91 static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
96 TALLOC_FREE(sconn->smb1.fde);
98 sconn->smb2.event_ctx = smbd_event_context();
100 sconn->smb2.recv_queue = tevent_queue_create(sconn, "smb2 recv queue");
101 if (sconn->smb2.recv_queue == NULL) {
102 return NT_STATUS_NO_MEMORY;
105 sconn->smb2.send_queue = tevent_queue_create(sconn, "smb2 send queue");
106 if (sconn->smb2.send_queue == NULL) {
107 return NT_STATUS_NO_MEMORY;
110 sconn->smb2.sessions.idtree = idr_init(sconn);
111 if (sconn->smb2.sessions.idtree == NULL) {
112 return NT_STATUS_NO_MEMORY;
114 sconn->smb2.sessions.limit = 0x0000FFFE;
115 sconn->smb2.sessions.list = NULL;
116 sconn->smb2.seqnum_low = 0;
117 sconn->smb2.seqnum_range = 1;
118 sconn->smb2.credits_granted = 1;
119 sconn->smb2.max_credits = lp_smb2_max_credits();
120 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
121 sconn->smb2.max_credits);
122 if (sconn->smb2.credits_bitmap == NULL) {
123 return NT_STATUS_NO_MEMORY;
126 ret = tstream_bsd_existing_socket(sconn, sconn->sock,
127 &sconn->smb2.stream);
129 status = map_nt_error_from_unix(errno);
133 /* Ensure child is set to non-blocking mode */
134 set_blocking(sconn->sock, false);
138 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
139 #define _smb2_setlen(_buf,len) do { \
140 uint8_t *buf = (uint8_t *)_buf; \
142 buf[1] = ((len)&0xFF0000)>>16; \
143 buf[2] = ((len)&0xFF00)>>8; \
144 buf[3] = (len)&0xFF; \
147 static void smb2_setup_nbt_length(struct iovec *vector, int count)
152 for (i=1; i < count; i++) {
153 len += vector[i].iov_len;
156 _smb2_setlen(vector[0].iov_base, len);
159 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request **req)
162 (*req)->parent = NULL;
163 (*req)->mem_pool = NULL;
169 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
173 talloc_free(req->mem_pool);
179 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
181 TALLOC_CTX *mem_pool;
182 struct smbd_smb2_request **parent;
183 struct smbd_smb2_request *req;
186 /* Enable this to find subtle valgrind errors. */
187 mem_pool = talloc_init("smbd_smb2_request_allocate");
189 mem_pool = talloc_pool(mem_ctx, 8192);
191 if (mem_pool == NULL) {
195 parent = talloc(mem_pool, struct smbd_smb2_request *);
196 if (parent == NULL) {
197 talloc_free(mem_pool);
201 req = talloc_zero(parent, struct smbd_smb2_request);
203 talloc_free(mem_pool);
207 req->mem_pool = mem_pool;
208 req->parent = parent;
210 req->last_session_id = UINT64_MAX;
211 req->last_tid = UINT32_MAX;
213 talloc_set_destructor(parent, smbd_smb2_request_parent_destructor);
214 talloc_set_destructor(req, smbd_smb2_request_destructor);
219 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
220 const uint8_t *inbuf, size_t size,
221 struct smbd_smb2_request **_req)
223 struct smbd_smb2_request *req;
224 uint32_t protocol_version;
225 const uint8_t *inhdr = NULL;
228 uint32_t next_command_ofs;
230 if (size < (4 + SMB2_HDR_BODY + 2)) {
231 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
232 return NT_STATUS_INVALID_PARAMETER;
237 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
238 if (protocol_version != SMB2_MAGIC) {
239 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
241 return NT_STATUS_INVALID_PARAMETER;
244 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
245 if (cmd != SMB2_OP_NEGPROT) {
246 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
248 return NT_STATUS_INVALID_PARAMETER;
251 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
252 if (next_command_ofs != 0) {
253 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
255 return NT_STATUS_INVALID_PARAMETER;
258 req = smbd_smb2_request_allocate(sconn);
260 return NT_STATUS_NO_MEMORY;
264 talloc_steal(req, inbuf);
266 req->in.vector = talloc_array(req, struct iovec, 4);
267 if (req->in.vector == NULL) {
269 return NT_STATUS_NO_MEMORY;
271 req->in.vector_count = 4;
273 memcpy(req->in.nbt_hdr, inbuf, 4);
276 req->in.vector[0].iov_base = (void *)req->in.nbt_hdr;
277 req->in.vector[0].iov_len = 4;
278 ofs += req->in.vector[0].iov_len;
280 req->in.vector[1].iov_base = (void *)(inbuf + ofs);
281 req->in.vector[1].iov_len = SMB2_HDR_BODY;
282 ofs += req->in.vector[1].iov_len;
284 req->in.vector[2].iov_base = (void *)(inbuf + ofs);
285 req->in.vector[2].iov_len = SVAL(inbuf, ofs) & 0xFFFE;
286 ofs += req->in.vector[2].iov_len;
289 return NT_STATUS_INVALID_PARAMETER;
292 req->in.vector[3].iov_base = (void *)(inbuf + ofs);
293 req->in.vector[3].iov_len = size - ofs;
294 ofs += req->in.vector[3].iov_len;
296 req->current_idx = 1;
302 static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
303 uint64_t message_id, uint64_t seq_id)
305 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
308 if (seq_id < sconn->smb2.seqnum_low) {
309 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
310 "%llu (sequence id %llu) "
311 "(granted = %u, low = %llu, range = %u)\n",
312 (unsigned long long)message_id,
313 (unsigned long long)seq_id,
314 (unsigned int)sconn->smb2.credits_granted,
315 (unsigned long long)sconn->smb2.seqnum_low,
316 (unsigned int)sconn->smb2.seqnum_range));
320 if (seq_id >= sconn->smb2.seqnum_low + sconn->smb2.seqnum_range) {
321 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
322 "%llu (sequence id %llu) "
323 "(granted = %u, low = %llu, range = %u)\n",
324 (unsigned long long)message_id,
325 (unsigned long long)seq_id,
326 (unsigned int)sconn->smb2.credits_granted,
327 (unsigned long long)sconn->smb2.seqnum_low,
328 (unsigned int)sconn->smb2.seqnum_range));
332 offset = seq_id % sconn->smb2.max_credits;
334 if (bitmap_query(credits_bm, offset)) {
335 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
336 "%llu (sequence id %llu) "
337 "(granted = %u, low = %llu, range = %u) "
339 (unsigned long long)message_id,
340 (unsigned long long)seq_id,
341 (unsigned int)sconn->smb2.credits_granted,
342 (unsigned long long)sconn->smb2.seqnum_low,
343 (unsigned int)sconn->smb2.seqnum_range,
348 /* Mark the message_ids as seen in the bitmap. */
349 bitmap_set(credits_bm, offset);
351 if (seq_id != sconn->smb2.seqnum_low) {
356 * Move the window forward by all the message_id's
359 while (bitmap_query(credits_bm, offset)) {
360 DEBUG(10,("smb2_validate_sequence_number: clearing "
361 "id %llu (position %u) from bitmap\n",
362 (unsigned long long)(sconn->smb2.seqnum_low),
364 bitmap_clear(credits_bm, offset);
366 sconn->smb2.seqnum_low += 1;
367 sconn->smb2.seqnum_range -= 1;
368 offset = sconn->smb2.seqnum_low % sconn->smb2.max_credits;
374 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
375 const uint8_t *inhdr)
377 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
378 uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
381 if (opcode == SMB2_OP_CANCEL) {
382 /* SMB2_CANCEL requests by definition resend messageids. */
386 DEBUG(11, ("smb2_validate_message_id: mid %llu, credits_granted %llu, "
387 "seqnum low/range: %llu/%llu\n",
388 (unsigned long long) message_id,
389 (unsigned long long) sconn->smb2.credits_granted,
390 (unsigned long long) sconn->smb2.seqnum_low,
391 (unsigned long long) sconn->smb2.seqnum_range));
393 if (sconn->smb2.credits_granted < 1) {
394 DEBUG(0, ("smb2_validate_message_id: client used more "
395 "credits than granted, mid %llu, credits_granted %llu, "
396 "seqnum low/range: %llu/%llu\n",
397 (unsigned long long) message_id,
398 (unsigned long long) sconn->smb2.credits_granted,
399 (unsigned long long) sconn->smb2.seqnum_low,
400 (unsigned long long) sconn->smb2.seqnum_range));
404 ok = smb2_validate_sequence_number(sconn, message_id, message_id);
409 /* substract used credits */
410 sconn->smb2.credits_granted -= 1;
415 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
420 count = req->in.vector_count;
423 /* It's not a SMB2 request */
424 return NT_STATUS_INVALID_PARAMETER;
427 for (idx=1; idx < count; idx += 3) {
428 const uint8_t *inhdr = NULL;
430 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
431 return NT_STATUS_INVALID_PARAMETER;
434 if (req->in.vector[idx+1].iov_len < 2) {
435 return NT_STATUS_INVALID_PARAMETER;
438 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
440 /* Check the SMB2 header */
441 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
442 return NT_STATUS_INVALID_PARAMETER;
445 if (!smb2_validate_message_id(req->sconn, inhdr)) {
446 return NT_STATUS_INVALID_PARAMETER;
453 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
454 const struct iovec *in_vector,
455 struct iovec *out_vector)
457 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
458 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
459 uint16_t credits_requested;
463 uint16_t credits_granted = 0;
464 uint64_t credits_possible;
465 uint16_t current_max_credits;
468 * first we grant only 1/16th of the max range.
470 * Windows also starts with the 1/16th and then grants
471 * more later. I was only able to trigger higher
472 * values, when using a verify high credit charge.
474 * TODO: scale up depending one load, free memory
476 * Maybe also on the relationship between number
477 * of requests and the used sequence number.
478 * Which means we would grant more credits
479 * for client which use multi credit requests.
481 current_max_credits = sconn->smb2.max_credits / 16;
482 current_max_credits = MAX(current_max_credits, 1);
484 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
485 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
486 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
487 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
489 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
491 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
493 * In case we already send an async interim
494 * response, we should not grant
495 * credits on the final response.
498 } else if (credits_requested > 0) {
499 uint16_t additional_max = 0;
500 uint16_t additional_credits = credits_requested - 1;
503 case SMB2_OP_NEGPROT:
505 case SMB2_OP_SESSSETUP:
507 * Windows 2012 RC1 starts to grant
509 * with a successful session setup
511 if (NT_STATUS_IS_OK(out_status)) {
517 * We match windows and only grant additional credits
524 additional_credits = MIN(additional_credits, additional_max);
526 credits_granted = 1 + additional_credits;
527 } else if (sconn->smb2.credits_granted == 0) {
529 * Make sure the client has always at least one credit
535 * sequence numbers should not wrap
537 * 1. calculate the possible credits until
538 * the sequence numbers start to wrap on 64-bit.
540 * 2. UINT64_MAX is used for Break Notifications.
542 * 2. truncate the possible credits to the maximum
543 * credits we want to grant to the client in total.
545 * 3. remove the range we'll already granted to the client
546 * this makes sure the client consumes the lowest sequence
547 * number, before we can grant additional credits.
549 credits_possible = UINT64_MAX - sconn->smb2.seqnum_low;
550 if (credits_possible > 0) {
551 /* remove UINT64_MAX */
552 credits_possible -= 1;
554 credits_possible = MIN(credits_possible, current_max_credits);
555 credits_possible -= sconn->smb2.seqnum_range;
557 credits_granted = MIN(credits_granted, credits_possible);
559 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
560 sconn->smb2.credits_granted += credits_granted;
561 sconn->smb2.seqnum_range += credits_granted;
563 DEBUG(10,("smb2_set_operation_credit: requested %u, "
564 "granted %u, current possible/max %u/%u, "
565 "total granted/max/low/range %u/%u/%llu/%u\n",
566 (unsigned int)credits_requested,
567 (unsigned int)credits_granted,
568 (unsigned int)credits_possible,
569 (unsigned int)current_max_credits,
570 (unsigned int)sconn->smb2.credits_granted,
571 (unsigned int)sconn->smb2.max_credits,
572 (unsigned long long)sconn->smb2.seqnum_low,
573 (unsigned int)sconn->smb2.seqnum_range));
576 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
577 struct smbd_smb2_request *outreq)
580 uint16_t total_credits = 0;
582 count = outreq->out.vector_count;
584 for (idx=1; idx < count; idx += 3) {
585 uint8_t *outhdr = (uint8_t *)outreq->out.vector[idx].iov_base;
586 smb2_set_operation_credit(outreq->sconn,
587 &inreq->in.vector[idx],
588 &outreq->out.vector[idx]);
589 /* To match Windows, count up what we
591 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
592 /* Set to zero in all but the last reply. */
593 if (idx + 3 < count) {
594 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
596 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
601 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
603 struct iovec *vector;
607 count = req->in.vector_count;
608 vector = talloc_zero_array(req, struct iovec, count);
609 if (vector == NULL) {
610 return NT_STATUS_NO_MEMORY;
613 vector[0].iov_base = req->out.nbt_hdr;
614 vector[0].iov_len = 4;
615 SIVAL(req->out.nbt_hdr, 0, 0);
617 for (idx=1; idx < count; idx += 3) {
618 const uint8_t *inhdr = NULL;
620 uint8_t *outhdr = NULL;
621 uint8_t *outbody = NULL;
622 uint32_t next_command_ofs = 0;
623 struct iovec *current = &vector[idx];
625 if ((idx + 3) < count) {
626 /* we have a next command -
627 * setup for the error case. */
628 next_command_ofs = SMB2_HDR_BODY + 9;
631 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
632 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
634 outhdr = talloc_zero_array(vector, uint8_t,
636 if (outhdr == NULL) {
637 return NT_STATUS_NO_MEMORY;
640 outbody = outhdr + SMB2_HDR_BODY;
642 current[0].iov_base = (void *)outhdr;
643 current[0].iov_len = SMB2_HDR_BODY;
645 current[1].iov_base = (void *)outbody;
646 current[1].iov_len = 8;
648 current[2].iov_base = NULL;
649 current[2].iov_len = 0;
651 /* setup the SMB2 header */
652 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
653 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
654 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
655 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
656 SIVAL(outhdr, SMB2_HDR_STATUS,
657 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
658 SSVAL(outhdr, SMB2_HDR_OPCODE,
659 SVAL(inhdr, SMB2_HDR_OPCODE));
660 SIVAL(outhdr, SMB2_HDR_FLAGS,
661 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
662 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
663 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
664 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
665 SIVAL(outhdr, SMB2_HDR_PID,
666 IVAL(inhdr, SMB2_HDR_PID));
667 SIVAL(outhdr, SMB2_HDR_TID,
668 IVAL(inhdr, SMB2_HDR_TID));
669 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
670 BVAL(inhdr, SMB2_HDR_SESSION_ID));
671 memcpy(outhdr + SMB2_HDR_SIGNATURE,
672 inhdr + SMB2_HDR_SIGNATURE, 16);
674 /* setup error body header */
675 SSVAL(outbody, 0x00, 0x08 + 1);
676 SSVAL(outbody, 0x02, 0);
677 SIVAL(outbody, 0x04, 0);
680 req->out.vector = vector;
681 req->out.vector_count = count;
683 /* setup the length of the NBT packet */
684 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
686 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
691 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
693 const char *location)
695 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
697 exit_server_cleanly(reason);
700 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
701 struct iovec *outvec,
702 const struct iovec *srcvec)
704 /* vec[0] is always boilerplate and must
705 * be allocated with size OUTVEC_ALLOC_SIZE. */
707 outvec[0].iov_base = talloc_memdup(ctx,
710 if (!outvec[0].iov_base) {
713 outvec[0].iov_len = SMB2_HDR_BODY;
716 * If this is a "standard" vec[1] of length 8,
717 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
718 * then duplicate this. Else use talloc_memdup().
721 if (srcvec[1].iov_len == 8 &&
722 srcvec[1].iov_base ==
723 ((uint8_t *)srcvec[0].iov_base) +
725 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
727 outvec[1].iov_len = 8;
729 outvec[1].iov_base = talloc_memdup(ctx,
732 if (!outvec[1].iov_base) {
735 outvec[1].iov_len = srcvec[1].iov_len;
739 * If this is a "standard" vec[2] of length 1,
740 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
741 * then duplicate this. Else use talloc_memdup().
744 if (srcvec[2].iov_base &&
746 if (srcvec[2].iov_base ==
747 ((uint8_t *)srcvec[0].iov_base) +
748 (OUTVEC_ALLOC_SIZE - 1) &&
749 srcvec[2].iov_len == 1) {
750 /* Common SMB2 error packet case. */
751 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
752 (OUTVEC_ALLOC_SIZE - 1);
754 outvec[2].iov_base = talloc_memdup(ctx,
757 if (!outvec[2].iov_base) {
761 outvec[2].iov_len = srcvec[2].iov_len;
763 outvec[2].iov_base = NULL;
764 outvec[2].iov_len = 0;
769 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
771 struct smbd_smb2_request *newreq = NULL;
772 struct iovec *outvec = NULL;
773 int count = req->out.vector_count;
776 newreq = smbd_smb2_request_allocate(req->sconn);
781 newreq->sconn = req->sconn;
782 newreq->session = req->session;
783 newreq->do_signing = req->do_signing;
784 newreq->current_idx = req->current_idx;
785 newreq->async = false;
786 newreq->cancelled = false;
787 /* Note we are leaving:
791 uninitialized as NULL here as
792 they're not used in the interim
793 response code. JRA. */
795 outvec = talloc_zero_array(newreq, struct iovec, count);
800 newreq->out.vector = outvec;
801 newreq->out.vector_count = count;
803 /* Setup the outvec's identically to req. */
804 outvec[0].iov_base = newreq->out.nbt_hdr;
805 outvec[0].iov_len = 4;
806 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
808 /* Setup the vectors identically to the ones in req. */
809 for (i = 1; i < count; i += 3) {
810 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
821 smb2_setup_nbt_length(newreq->out.vector,
822 newreq->out.vector_count);
827 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
829 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
832 uint8_t *outhdr = NULL;
833 struct smbd_smb2_request *nreq = NULL;
835 /* Create a new smb2 request we'll use
836 for the interim return. */
837 nreq = dup_smb2_req(req);
839 return NT_STATUS_NO_MEMORY;
842 /* Lose the last 3 out vectors. They're the
843 ones we'll be using for the async reply. */
844 nreq->out.vector_count -= 3;
846 smb2_setup_nbt_length(nreq->out.vector,
847 nreq->out.vector_count);
849 /* Step back to the previous reply. */
850 i = nreq->current_idx - 3;
851 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
852 /* And end the chain. */
853 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
855 /* Calculate outgoing credits */
856 smb2_calculate_credits(req, nreq);
858 /* Re-sign if needed. */
859 if (nreq->do_signing) {
861 status = smb2_signing_sign_pdu(nreq->session->session_key,
862 &nreq->out.vector[i], 3);
863 if (!NT_STATUS_IS_OK(status)) {
867 if (DEBUGLEVEL >= 10) {
868 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
869 (unsigned int)nreq->current_idx );
870 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
871 (unsigned int)nreq->out.vector_count );
872 print_req_vectors(nreq);
874 nreq->subreq = tstream_writev_queue_send(nreq,
875 nreq->sconn->smb2.event_ctx,
876 nreq->sconn->smb2.stream,
877 nreq->sconn->smb2.send_queue,
879 nreq->out.vector_count);
881 if (nreq->subreq == NULL) {
882 return NT_STATUS_NO_MEMORY;
885 tevent_req_set_callback(nreq->subreq,
886 smbd_smb2_request_writev_done,
892 struct smbd_smb2_request_pending_state {
893 struct smbd_server_connection *sconn;
894 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
895 struct iovec vector[3];
898 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
900 struct smbd_smb2_request_pending_state *state =
901 tevent_req_callback_data(subreq,
902 struct smbd_smb2_request_pending_state);
903 struct smbd_server_connection *sconn = state->sconn;
907 ret = tstream_writev_queue_recv(subreq, &sys_errno);
910 NTSTATUS status = map_nt_error_from_unix(sys_errno);
911 smbd_server_connection_terminate(sconn, nt_errstr(status));
918 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
919 struct tevent_req *subreq)
922 struct smbd_smb2_request_pending_state *state = NULL;
923 int i = req->current_idx;
924 uint8_t *reqhdr = NULL;
926 uint8_t *body = NULL;
928 uint64_t message_id = 0;
929 uint64_t async_id = 0;
930 struct iovec *outvec = NULL;
932 if (!tevent_req_is_in_progress(subreq)) {
936 req->subreq = subreq;
940 /* We're already async. */
944 if (req->in.vector_count > i + 3) {
946 * We're trying to go async in a compound
947 * request chain. This is not allowed.
948 * Cancel the outstanding request.
950 bool ok = tevent_req_cancel(req->subreq);
954 TALLOC_FREE(req->subreq);
955 return smbd_smb2_request_error(req,
956 NT_STATUS_INTERNAL_ERROR);
959 if (DEBUGLEVEL >= 10) {
960 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
961 (unsigned int)req->current_idx );
962 print_req_vectors(req);
965 if (req->out.vector_count > 4) {
966 /* This is a compound reply. We
967 * must do an interim response
968 * followed by the async response
971 status = smb2_send_async_interim_response(req);
972 if (!NT_STATUS_IS_OK(status)) {
977 * We're splitting off the last SMB2
978 * request in a compound set, and the
979 * smb2_send_async_interim_response()
980 * call above just sent all the replies
981 * for the previous SMB2 requests in
982 * this compound set. So we're no longer
983 * in the "compound_related_in_progress"
984 * state, and this is no longer a compound
987 req->compound_related = false;
988 req->sconn->smb2.compound_related_in_progress = false;
991 /* Don't return an intermediate packet on a pipe read/write. */
992 if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
996 reqhdr = (uint8_t *)req->out.vector[i].iov_base;
997 flags = (IVAL(reqhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
998 message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
999 async_id = message_id; /* keep it simple for now... */
1002 * What we send is identical to a smbd_smb2_request_error
1003 * packet with an error status of STATUS_PENDING. Make use
1004 * of this fact sometime when refactoring. JRA.
1007 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1008 if (state == NULL) {
1009 return NT_STATUS_NO_MEMORY;
1011 state->sconn = req->sconn;
1013 state->vector[0].iov_base = (void *)state->buf;
1014 state->vector[0].iov_len = 4;
1016 state->vector[1].iov_base = state->buf + 4;
1017 state->vector[1].iov_len = SMB2_HDR_BODY;
1019 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
1020 state->vector[2].iov_len = 9;
1022 smb2_setup_nbt_length(state->vector, 3);
1024 hdr = (uint8_t *)state->vector[1].iov_base;
1025 body = (uint8_t *)state->vector[2].iov_base;
1027 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1028 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1029 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1030 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1031 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(reqhdr, SMB2_HDR_OPCODE));
1033 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1034 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1035 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1036 SBVAL(hdr, SMB2_HDR_PID, async_id);
1037 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1038 BVAL(reqhdr, SMB2_HDR_SESSION_ID));
1039 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
1041 SSVAL(body, 0x00, 0x08 + 1);
1043 SCVAL(body, 0x02, 0);
1044 SCVAL(body, 0x03, 0);
1045 SIVAL(body, 0x04, 0);
1046 /* Match W2K8R2... */
1047 SCVAL(body, 0x08, 0x21);
1049 /* Ensure we correctly go through crediting. Grant
1050 the credits now, and zero credits on the final
1052 smb2_set_operation_credit(req->sconn,
1056 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1058 if (req->do_signing) {
1059 status = smb2_signing_sign_pdu(req->session->session_key,
1060 &state->vector[1], 2);
1061 if (!NT_STATUS_IS_OK(status)) {
1066 subreq = tstream_writev_queue_send(state,
1067 req->sconn->smb2.event_ctx,
1068 req->sconn->smb2.stream,
1069 req->sconn->smb2.send_queue,
1073 if (subreq == NULL) {
1074 return NT_STATUS_NO_MEMORY;
1077 tevent_req_set_callback(subreq,
1078 smbd_smb2_request_pending_writev_done,
1081 /* Note we're going async with this request. */
1087 * Now manipulate req so that the outstanding async request
1088 * is the only one left in the struct smbd_smb2_request.
1091 if (req->current_idx == 1) {
1092 /* There was only one. */
1096 /* Re-arrange the in.vectors. */
1097 req->in.vector[1] = req->in.vector[i];
1098 req->in.vector[2] = req->in.vector[i+1];
1099 req->in.vector[3] = req->in.vector[i+2];
1100 req->in.vector_count = 4;
1101 /* Reset the new in size. */
1102 smb2_setup_nbt_length(req->in.vector, 4);
1104 /* Now recreate the out.vectors. */
1105 outvec = talloc_zero_array(req, struct iovec, 4);
1107 return NT_STATUS_NO_MEMORY;
1110 /* 0 is always boilerplate and must
1111 * be of size 4 for the length field. */
1113 outvec[0].iov_base = req->out.nbt_hdr;
1114 outvec[0].iov_len = 4;
1115 SIVAL(req->out.nbt_hdr, 0, 0);
1117 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
1118 return NT_STATUS_NO_MEMORY;
1121 TALLOC_FREE(req->out.vector);
1123 req->out.vector = outvec;
1125 req->current_idx = 1;
1126 req->out.vector_count = 4;
1130 smb2_setup_nbt_length(req->out.vector,
1131 req->out.vector_count);
1134 /* Ensure our final reply matches the interim one. */
1135 reqhdr = (uint8_t *)req->out.vector[1].iov_base;
1136 SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1137 SBVAL(reqhdr, SMB2_HDR_PID, async_id);
1140 const uint8_t *inhdr =
1141 (const uint8_t *)req->in.vector[1].iov_base;
1142 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1144 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1145 (unsigned long long)async_id ));
1149 return NT_STATUS_OK;
1152 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1154 struct smbd_server_connection *sconn = req->sconn;
1155 struct smbd_smb2_request *cur;
1156 const uint8_t *inhdr;
1157 int i = req->current_idx;
1159 uint64_t search_message_id;
1160 uint64_t search_async_id;
1163 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1165 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1166 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1167 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1170 * we don't need the request anymore
1171 * cancel requests never have a response
1173 DLIST_REMOVE(req->sconn->smb2.requests, req);
1176 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1177 const uint8_t *outhdr;
1178 uint64_t message_id;
1181 if (cur->compound_related) {
1183 * Never cancel anything in a compound request.
1184 * Way too hard to deal with the result.
1189 i = cur->current_idx;
1191 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1193 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1194 async_id = BVAL(outhdr, SMB2_HDR_PID);
1196 if (flags & SMB2_HDR_FLAG_ASYNC) {
1197 if (search_async_id == async_id) {
1198 found_id = async_id;
1202 if (search_message_id == message_id) {
1203 found_id = message_id;
1209 if (cur && cur->subreq) {
1210 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1211 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1212 "cancel opcode[%s] mid %llu\n",
1213 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1214 (unsigned long long)found_id ));
1215 tevent_req_cancel(cur->subreq);
1218 return NT_STATUS_OK;
1221 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1222 size_t expected_body_size)
1224 const uint8_t *inhdr;
1226 const uint8_t *inbody;
1227 int i = req->current_idx;
1229 size_t min_dyn_size = expected_body_size & 0x00000001;
1232 * The following should be checked already.
1234 if ((i+2) > req->in.vector_count) {
1235 return NT_STATUS_INTERNAL_ERROR;
1237 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1238 return NT_STATUS_INTERNAL_ERROR;
1240 if (req->in.vector[i+1].iov_len < 2) {
1241 return NT_STATUS_INTERNAL_ERROR;
1244 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1245 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1249 case SMB2_OP_GETINFO:
1255 * Now check the expected body size,
1256 * where the last byte might be in the
1257 * dynnamic section..
1259 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1260 return NT_STATUS_INVALID_PARAMETER;
1262 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1263 return NT_STATUS_INVALID_PARAMETER;
1266 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1268 body_size = SVAL(inbody, 0x00);
1269 if (body_size != expected_body_size) {
1270 return NT_STATUS_INVALID_PARAMETER;
1273 return NT_STATUS_OK;
1276 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1278 const uint8_t *inhdr;
1279 int i = req->current_idx;
1284 NTSTATUS session_status;
1285 uint32_t allowed_flags;
1286 NTSTATUS return_value;
1288 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1290 /* TODO: verify more things */
1292 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1293 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1294 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1295 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1296 smb2_opcode_name(opcode),
1297 (unsigned long long)mid));
1299 if (get_Protocol() >= PROTOCOL_SMB2) {
1301 * once the protocol is negotiated
1302 * SMB2_OP_NEGPROT is not allowed anymore
1304 if (opcode == SMB2_OP_NEGPROT) {
1305 /* drop the connection */
1306 return NT_STATUS_INVALID_PARAMETER;
1310 * if the protocol is not negotiated yet
1311 * only SMB2_OP_NEGPROT is allowed.
1313 if (opcode != SMB2_OP_NEGPROT) {
1314 /* drop the connection */
1315 return NT_STATUS_INVALID_PARAMETER;
1319 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1320 SMB2_HDR_FLAG_SIGNED |
1322 if (opcode == SMB2_OP_CANCEL) {
1323 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1325 if ((flags & ~allowed_flags) != 0) {
1326 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1330 * Check if the client provided a valid session id,
1331 * if so smbd_smb2_request_check_session() calls
1332 * set_current_user_info().
1334 * As some command don't require a valid session id
1335 * we defer the check of the session_status
1337 session_status = smbd_smb2_request_check_session(req);
1339 if (flags & SMB2_HDR_FLAG_CHAINED) {
1341 * This check is mostly for giving the correct error code
1342 * for compounded requests.
1344 if (!NT_STATUS_IS_OK(session_status)) {
1345 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1348 req->compat_chain_fsp = NULL;
1351 req->do_signing = false;
1352 if (flags & SMB2_HDR_FLAG_SIGNED) {
1353 if (!NT_STATUS_IS_OK(session_status)) {
1354 return smbd_smb2_request_error(req, session_status);
1357 req->do_signing = true;
1358 status = smb2_signing_check_pdu(req->session->session_key,
1359 &req->in.vector[i], 3);
1360 if (!NT_STATUS_IS_OK(status)) {
1361 return smbd_smb2_request_error(req, status);
1363 } else if (opcode == SMB2_OP_CANCEL) {
1364 /* Cancel requests are allowed to skip the signing */
1365 } else if (req->session && req->session->do_signing) {
1366 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1369 if (flags & SMB2_HDR_FLAG_CHAINED) {
1370 req->compound_related = true;
1371 req->sconn->smb2.compound_related_in_progress = true;
1375 case SMB2_OP_NEGPROT:
1376 /* This call needs to be run as root */
1377 change_to_root_user();
1380 START_PROFILE(smb2_negprot);
1381 return_value = smbd_smb2_request_process_negprot(req);
1382 END_PROFILE(smb2_negprot);
1386 case SMB2_OP_SESSSETUP:
1387 /* This call needs to be run as root */
1388 change_to_root_user();
1391 START_PROFILE(smb2_sesssetup);
1392 return_value = smbd_smb2_request_process_sesssetup(req);
1393 END_PROFILE(smb2_sesssetup);
1397 case SMB2_OP_LOGOFF:
1398 if (!NT_STATUS_IS_OK(session_status)) {
1399 return_value = smbd_smb2_request_error(req, session_status);
1403 /* This call needs to be run as root */
1404 change_to_root_user();
1407 START_PROFILE(smb2_logoff);
1408 return_value = smbd_smb2_request_process_logoff(req);
1409 END_PROFILE(smb2_logoff);
1414 if (!NT_STATUS_IS_OK(session_status)) {
1415 return_value = smbd_smb2_request_error(req, session_status);
1420 * This call needs to be run as root.
1422 * smbd_smb2_request_process_tcon()
1423 * calls make_connection_snum(), which will call
1424 * change_to_user(), when needed.
1426 change_to_root_user();
1429 START_PROFILE(smb2_tcon);
1430 return_value = smbd_smb2_request_process_tcon(req);
1431 END_PROFILE(smb2_tcon);
1436 if (!NT_STATUS_IS_OK(session_status)) {
1437 return_value = smbd_smb2_request_error(req, session_status);
1441 * This call needs to be run as user.
1443 * smbd_smb2_request_check_tcon()
1444 * calls change_to_user() on success.
1446 status = smbd_smb2_request_check_tcon(req);
1447 if (!NT_STATUS_IS_OK(status)) {
1448 return_value = smbd_smb2_request_error(req, status);
1451 /* This call needs to be run as root */
1452 change_to_root_user();
1456 START_PROFILE(smb2_tdis);
1457 return_value = smbd_smb2_request_process_tdis(req);
1458 END_PROFILE(smb2_tdis);
1462 case SMB2_OP_CREATE:
1463 if (!NT_STATUS_IS_OK(session_status)) {
1464 return_value = smbd_smb2_request_error(req, session_status);
1468 * This call needs to be run as user.
1470 * smbd_smb2_request_check_tcon()
1471 * calls change_to_user() on success.
1473 status = smbd_smb2_request_check_tcon(req);
1474 if (!NT_STATUS_IS_OK(status)) {
1475 return_value = smbd_smb2_request_error(req, status);
1480 START_PROFILE(smb2_create);
1481 return_value = smbd_smb2_request_process_create(req);
1482 END_PROFILE(smb2_create);
1487 if (!NT_STATUS_IS_OK(session_status)) {
1488 return_value = smbd_smb2_request_error(req, session_status);
1492 * This call needs to be run as user.
1494 * smbd_smb2_request_check_tcon()
1495 * calls change_to_user() on success.
1497 status = smbd_smb2_request_check_tcon(req);
1498 if (!NT_STATUS_IS_OK(status)) {
1499 return_value = smbd_smb2_request_error(req, status);
1504 START_PROFILE(smb2_close);
1505 return_value = smbd_smb2_request_process_close(req);
1506 END_PROFILE(smb2_close);
1511 if (!NT_STATUS_IS_OK(session_status)) {
1512 return_value = smbd_smb2_request_error(req, session_status);
1516 * This call needs to be run as user.
1518 * smbd_smb2_request_check_tcon()
1519 * calls change_to_user() on success.
1521 status = smbd_smb2_request_check_tcon(req);
1522 if (!NT_STATUS_IS_OK(status)) {
1523 return_value = smbd_smb2_request_error(req, status);
1528 START_PROFILE(smb2_flush);
1529 return_value = smbd_smb2_request_process_flush(req);
1530 END_PROFILE(smb2_flush);
1535 if (!NT_STATUS_IS_OK(session_status)) {
1536 return_value = smbd_smb2_request_error(req, session_status);
1540 * This call needs to be run as user.
1542 * smbd_smb2_request_check_tcon()
1543 * calls change_to_user() on success.
1545 status = smbd_smb2_request_check_tcon(req);
1546 if (!NT_STATUS_IS_OK(status)) {
1547 return_value = smbd_smb2_request_error(req, status);
1552 START_PROFILE(smb2_read);
1553 return_value = smbd_smb2_request_process_read(req);
1554 END_PROFILE(smb2_read);
1559 if (!NT_STATUS_IS_OK(session_status)) {
1560 return_value = smbd_smb2_request_error(req, session_status);
1564 * This call needs to be run as user.
1566 * smbd_smb2_request_check_tcon()
1567 * calls change_to_user() on success.
1569 status = smbd_smb2_request_check_tcon(req);
1570 if (!NT_STATUS_IS_OK(status)) {
1571 return_value = smbd_smb2_request_error(req, status);
1576 START_PROFILE(smb2_write);
1577 return_value = smbd_smb2_request_process_write(req);
1578 END_PROFILE(smb2_write);
1583 if (!NT_STATUS_IS_OK(session_status)) {
1584 /* Too ugly to live ? JRA. */
1585 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1586 session_status = NT_STATUS_FILE_CLOSED;
1588 return_value = smbd_smb2_request_error(req, session_status);
1592 * This call needs to be run as user.
1594 * smbd_smb2_request_check_tcon()
1595 * calls change_to_user() on success.
1597 status = smbd_smb2_request_check_tcon(req);
1598 if (!NT_STATUS_IS_OK(status)) {
1599 /* Too ugly to live ? JRA. */
1600 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1601 status = NT_STATUS_FILE_CLOSED;
1603 return_value = smbd_smb2_request_error(req, status);
1608 START_PROFILE(smb2_lock);
1609 return_value = smbd_smb2_request_process_lock(req);
1610 END_PROFILE(smb2_lock);
1615 if (!NT_STATUS_IS_OK(session_status)) {
1616 return_value = smbd_smb2_request_error(req, session_status);
1620 * This call needs to be run as user.
1622 * smbd_smb2_request_check_tcon()
1623 * calls change_to_user() on success.
1625 status = smbd_smb2_request_check_tcon(req);
1626 if (!NT_STATUS_IS_OK(status)) {
1627 return_value = smbd_smb2_request_error(req, status);
1632 START_PROFILE(smb2_ioctl);
1633 return_value = smbd_smb2_request_process_ioctl(req);
1634 END_PROFILE(smb2_ioctl);
1638 case SMB2_OP_CANCEL:
1640 * This call needs to be run as root
1642 * That is what we also do in the SMB1 case.
1644 change_to_root_user();
1647 START_PROFILE(smb2_cancel);
1648 return_value = smbd_smb2_request_process_cancel(req);
1649 END_PROFILE(smb2_cancel);
1653 case SMB2_OP_KEEPALIVE:
1654 /* This call needs to be run as root */
1655 change_to_root_user();
1658 START_PROFILE(smb2_keepalive);
1659 return_value = smbd_smb2_request_process_keepalive(req);
1660 END_PROFILE(smb2_keepalive);
1665 if (!NT_STATUS_IS_OK(session_status)) {
1666 return_value = smbd_smb2_request_error(req, session_status);
1670 * This call needs to be run as user.
1672 * smbd_smb2_request_check_tcon()
1673 * calls change_to_user() on success.
1675 status = smbd_smb2_request_check_tcon(req);
1676 if (!NT_STATUS_IS_OK(status)) {
1677 return_value = smbd_smb2_request_error(req, status);
1682 START_PROFILE(smb2_find);
1683 return_value = smbd_smb2_request_process_find(req);
1684 END_PROFILE(smb2_find);
1688 case SMB2_OP_NOTIFY:
1689 if (!NT_STATUS_IS_OK(session_status)) {
1690 return_value = smbd_smb2_request_error(req, session_status);
1694 * This call needs to be run as user.
1696 * smbd_smb2_request_check_tcon()
1697 * calls change_to_user() on success.
1699 status = smbd_smb2_request_check_tcon(req);
1700 if (!NT_STATUS_IS_OK(status)) {
1701 return_value = smbd_smb2_request_error(req, status);
1706 START_PROFILE(smb2_notify);
1707 return_value = smbd_smb2_request_process_notify(req);
1708 END_PROFILE(smb2_notify);
1712 case SMB2_OP_GETINFO:
1713 if (!NT_STATUS_IS_OK(session_status)) {
1714 return_value = smbd_smb2_request_error(req, session_status);
1718 * This call needs to be run as user.
1720 * smbd_smb2_request_check_tcon()
1721 * calls change_to_user() on success.
1723 status = smbd_smb2_request_check_tcon(req);
1724 if (!NT_STATUS_IS_OK(status)) {
1725 return_value = smbd_smb2_request_error(req, status);
1730 START_PROFILE(smb2_getinfo);
1731 return_value = smbd_smb2_request_process_getinfo(req);
1732 END_PROFILE(smb2_getinfo);
1736 case SMB2_OP_SETINFO:
1737 if (!NT_STATUS_IS_OK(session_status)) {
1738 return_value = smbd_smb2_request_error(req, session_status);
1742 * This call needs to be run as user.
1744 * smbd_smb2_request_check_tcon()
1745 * calls change_to_user() on success.
1747 status = smbd_smb2_request_check_tcon(req);
1748 if (!NT_STATUS_IS_OK(status)) {
1749 return_value = smbd_smb2_request_error(req, status);
1754 START_PROFILE(smb2_setinfo);
1755 return_value = smbd_smb2_request_process_setinfo(req);
1756 END_PROFILE(smb2_setinfo);
1761 if (!NT_STATUS_IS_OK(session_status)) {
1762 return_value = smbd_smb2_request_error(req, session_status);
1766 * This call needs to be run as user.
1768 * smbd_smb2_request_check_tcon()
1769 * calls change_to_user() on success.
1771 status = smbd_smb2_request_check_tcon(req);
1772 if (!NT_STATUS_IS_OK(status)) {
1773 return_value = smbd_smb2_request_error(req, status);
1778 START_PROFILE(smb2_break);
1779 return_value = smbd_smb2_request_process_break(req);
1780 END_PROFILE(smb2_break);
1785 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1788 return return_value;
1791 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1793 struct tevent_req *subreq;
1794 int i = req->current_idx;
1798 req->current_idx += 3;
1800 if (req->current_idx < req->out.vector_count) {
1802 * We must process the remaining compound
1803 * SMB2 requests before any new incoming SMB2
1804 * requests. This is because incoming SMB2
1805 * requests may include a cancel for a
1806 * compound request we haven't processed
1809 struct tevent_immediate *im = tevent_create_immediate(req);
1811 return NT_STATUS_NO_MEMORY;
1814 if (req->do_signing) {
1816 * We sign each reply as we go along.
1817 * We can do this as smb2_calculate_credits()
1818 * grants zero credits on every part of a
1819 * compound reply except the last one,
1820 * which is signed just before calling
1821 * tstream_writev_queue_send().
1824 status = smb2_signing_sign_pdu(req->session->session_key,
1825 &req->out.vector[i], 3);
1826 if (!NT_STATUS_IS_OK(status)) {
1832 tevent_schedule_immediate(im,
1833 req->sconn->smb2.event_ctx,
1834 smbd_smb2_request_dispatch_immediate,
1836 return NT_STATUS_OK;
1839 if (req->compound_related) {
1840 req->compound_related = false;
1841 req->sconn->smb2.compound_related_in_progress = false;
1844 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1846 /* Set credit for these operations (zero credits if this
1847 is a final reply for an async operation). */
1848 smb2_calculate_credits(req, req);
1850 if (req->do_signing) {
1852 status = smb2_signing_sign_pdu(req->session->session_key,
1853 &req->out.vector[i], 3);
1854 if (!NT_STATUS_IS_OK(status)) {
1859 if (DEBUGLEVEL >= 10) {
1860 dbgtext("smbd_smb2_request_reply: sending...\n");
1861 print_req_vectors(req);
1864 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1865 if (req->out.vector_count == 4 &&
1866 req->out.vector[3].iov_base == NULL &&
1867 req->out.vector[3].iov_len != 0) {
1868 /* Dynamic part is NULL. Chop it off,
1869 We're going to send it via sendfile. */
1870 req->out.vector_count -= 1;
1873 subreq = tstream_writev_queue_send(req,
1874 req->sconn->smb2.event_ctx,
1875 req->sconn->smb2.stream,
1876 req->sconn->smb2.send_queue,
1878 req->out.vector_count);
1879 if (subreq == NULL) {
1880 return NT_STATUS_NO_MEMORY;
1882 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1884 * We're done with this request -
1885 * move it off the "being processed" queue.
1887 DLIST_REMOVE(req->sconn->smb2.requests, req);
1889 return NT_STATUS_OK;
1892 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
1894 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1895 struct tevent_immediate *im,
1898 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1899 struct smbd_smb2_request);
1900 struct smbd_server_connection *sconn = req->sconn;
1905 if (DEBUGLEVEL >= 10) {
1906 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1907 req->current_idx, req->in.vector_count));
1908 print_req_vectors(req);
1911 status = smbd_smb2_request_dispatch(req);
1912 if (!NT_STATUS_IS_OK(status)) {
1913 smbd_server_connection_terminate(sconn, nt_errstr(status));
1917 status = smbd_smb2_request_next_incoming(sconn);
1918 if (!NT_STATUS_IS_OK(status)) {
1919 smbd_server_connection_terminate(sconn, nt_errstr(status));
1924 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1926 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1927 struct smbd_smb2_request);
1928 struct smbd_server_connection *sconn = req->sconn;
1933 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1934 TALLOC_FREE(subreq);
1937 status = map_nt_error_from_unix(sys_errno);
1938 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1939 nt_errstr(status)));
1940 smbd_server_connection_terminate(sconn, nt_errstr(status));
1944 status = smbd_smb2_request_next_incoming(sconn);
1945 if (!NT_STATUS_IS_OK(status)) {
1946 smbd_server_connection_terminate(sconn, nt_errstr(status));
1951 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1953 DATA_BLOB body, DATA_BLOB *dyn,
1954 const char *location)
1957 int i = req->current_idx;
1958 uint32_t next_command_ofs;
1960 DEBUG(10,("smbd_smb2_request_done_ex: "
1961 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1962 i, nt_errstr(status), (unsigned int)body.length,
1964 (unsigned int)(dyn ? dyn->length : 0),
1967 if (body.length < 2) {
1968 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1971 if ((body.length % 2) != 0) {
1972 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1975 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1977 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1978 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1980 req->out.vector[i+1].iov_base = (void *)body.data;
1981 req->out.vector[i+1].iov_len = body.length;
1984 req->out.vector[i+2].iov_base = (void *)dyn->data;
1985 req->out.vector[i+2].iov_len = dyn->length;
1987 req->out.vector[i+2].iov_base = NULL;
1988 req->out.vector[i+2].iov_len = 0;
1991 /* see if we need to recalculate the offset to the next response */
1992 if (next_command_ofs > 0) {
1993 next_command_ofs = SMB2_HDR_BODY;
1994 next_command_ofs += req->out.vector[i+1].iov_len;
1995 next_command_ofs += req->out.vector[i+2].iov_len;
1998 if ((next_command_ofs % 8) != 0) {
1999 size_t pad_size = 8 - (next_command_ofs % 8);
2000 if (req->out.vector[i+2].iov_len == 0) {
2002 * if the dyn buffer is empty
2003 * we can use it to add padding
2007 pad = talloc_zero_array(req->out.vector,
2010 return smbd_smb2_request_error(req,
2011 NT_STATUS_NO_MEMORY);
2014 req->out.vector[i+2].iov_base = (void *)pad;
2015 req->out.vector[i+2].iov_len = pad_size;
2018 * For now we copy the dynamic buffer
2019 * and add the padding to the new buffer
2026 old_size = req->out.vector[i+2].iov_len;
2027 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2029 new_size = old_size + pad_size;
2030 new_dyn = talloc_zero_array(req->out.vector,
2032 if (new_dyn == NULL) {
2033 return smbd_smb2_request_error(req,
2034 NT_STATUS_NO_MEMORY);
2037 memcpy(new_dyn, old_dyn, old_size);
2038 memset(new_dyn + old_size, 0, pad_size);
2040 req->out.vector[i+2].iov_base = (void *)new_dyn;
2041 req->out.vector[i+2].iov_len = new_size;
2043 next_command_ofs += pad_size;
2046 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2048 return smbd_smb2_request_reply(req);
2051 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2054 const char *location)
2057 int i = req->current_idx;
2058 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
2060 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2061 i, nt_errstr(status), info ? " +info" : "",
2064 body.data = outhdr + SMB2_HDR_BODY;
2066 SSVAL(body.data, 0, 9);
2069 SIVAL(body.data, 0x04, info->length);
2071 /* Allocated size of req->out.vector[i].iov_base
2072 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2073 * 1 byte without having to do an alloc.
2075 info = talloc_zero_array(req->out.vector,
2079 return NT_STATUS_NO_MEMORY;
2081 info->data = ((uint8_t *)outhdr) +
2082 OUTVEC_ALLOC_SIZE - 1;
2084 SCVAL(info->data, 0, 0);
2088 * Note: Even if there is an error, continue to process the request.
2092 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2096 struct smbd_smb2_send_oplock_break_state {
2097 struct smbd_server_connection *sconn;
2098 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2099 struct iovec vector;
2102 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2104 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2105 uint64_t file_id_persistent,
2106 uint64_t file_id_volatile,
2107 uint8_t oplock_level)
2109 struct smbd_smb2_send_oplock_break_state *state;
2110 struct tevent_req *subreq;
2114 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2115 if (state == NULL) {
2116 return NT_STATUS_NO_MEMORY;
2118 state->sconn = sconn;
2120 state->vector.iov_base = (void *)state->buf;
2121 state->vector.iov_len = sizeof(state->buf);
2123 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2124 hdr = state->buf + 4;
2125 body = hdr + SMB2_HDR_BODY;
2127 SIVAL(hdr, 0, SMB2_MAGIC);
2128 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2129 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2130 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2131 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2132 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2133 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2134 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2135 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2136 SIVAL(hdr, SMB2_HDR_PID, 0);
2137 SIVAL(hdr, SMB2_HDR_TID, 0);
2138 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2139 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2141 SSVAL(body, 0x00, 0x18);
2143 SCVAL(body, 0x02, oplock_level);
2144 SCVAL(body, 0x03, 0); /* reserved */
2145 SIVAL(body, 0x04, 0); /* reserved */
2146 SBVAL(body, 0x08, file_id_persistent);
2147 SBVAL(body, 0x10, file_id_volatile);
2149 subreq = tstream_writev_queue_send(state,
2150 sconn->smb2.event_ctx,
2152 sconn->smb2.send_queue,
2154 if (subreq == NULL) {
2155 return NT_STATUS_NO_MEMORY;
2157 tevent_req_set_callback(subreq,
2158 smbd_smb2_oplock_break_writev_done,
2161 return NT_STATUS_OK;
2164 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2166 struct smbd_smb2_send_oplock_break_state *state =
2167 tevent_req_callback_data(subreq,
2168 struct smbd_smb2_send_oplock_break_state);
2169 struct smbd_server_connection *sconn = state->sconn;
2173 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2174 TALLOC_FREE(subreq);
2176 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2177 smbd_server_connection_terminate(sconn, nt_errstr(status));
2184 struct smbd_smb2_request_read_state {
2186 bool asked_for_header;
2187 struct smbd_smb2_request *smb2_req;
2190 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2192 TALLOC_CTX *mem_ctx,
2193 struct iovec **_vector,
2195 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2197 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2198 struct tevent_context *ev,
2199 struct smbd_server_connection *sconn)
2201 struct tevent_req *req;
2202 struct smbd_smb2_request_read_state *state;
2203 struct tevent_req *subreq;
2205 req = tevent_req_create(mem_ctx, &state,
2206 struct smbd_smb2_request_read_state);
2211 state->asked_for_header = false;
2213 state->smb2_req = smbd_smb2_request_allocate(state);
2214 if (tevent_req_nomem(state->smb2_req, req)) {
2215 return tevent_req_post(req, ev);
2217 state->smb2_req->sconn = sconn;
2219 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2220 sconn->smb2.recv_queue,
2221 smbd_smb2_request_next_vector,
2223 if (tevent_req_nomem(subreq, req)) {
2224 return tevent_req_post(req, ev);
2226 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2231 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2233 TALLOC_CTX *mem_ctx,
2234 struct iovec **_vector,
2237 struct smbd_smb2_request_read_state *state =
2238 talloc_get_type_abort(private_data,
2239 struct smbd_smb2_request_read_state);
2240 struct smbd_smb2_request *req = state->smb2_req;
2241 struct iovec *vector;
2242 int idx = req->in.vector_count;
2244 uint8_t *buf = NULL;
2246 if (req->in.vector_count == 0) {
2248 * first we need to get the NBT header
2250 req->in.vector = talloc_array(req, struct iovec,
2251 req->in.vector_count + 1);
2252 if (req->in.vector == NULL) {
2255 req->in.vector_count += 1;
2257 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2258 req->in.vector[idx].iov_len = 4;
2260 vector = talloc_array(mem_ctx, struct iovec, 1);
2261 if (vector == NULL) {
2265 vector[0] = req->in.vector[idx];
2272 if (req->in.vector_count == 1) {
2274 * Now we analyze the NBT header
2276 state->missing = smb2_len(req->in.vector[0].iov_base);
2278 if (state->missing == 0) {
2279 /* if there're no remaining bytes, we're done */
2285 req->in.vector = talloc_realloc(req, req->in.vector,
2287 req->in.vector_count + 1);
2288 if (req->in.vector == NULL) {
2291 req->in.vector_count += 1;
2293 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2295 * it's a special NBT message,
2296 * so get all remaining bytes
2298 len = state->missing;
2299 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2301 * it's an invalid message, just read what we can get
2302 * and let the caller handle the error
2304 len = state->missing;
2307 * We assume it's a SMB2 request,
2308 * and we first get the header and the
2309 * first 2 bytes (the struct size) of the body
2311 len = SMB2_HDR_BODY + 2;
2313 state->asked_for_header = true;
2316 state->missing -= len;
2318 buf = talloc_array(req->in.vector, uint8_t, len);
2323 req->in.vector[idx].iov_base = (void *)buf;
2324 req->in.vector[idx].iov_len = len;
2326 vector = talloc_array(mem_ctx, struct iovec, 1);
2327 if (vector == NULL) {
2331 vector[0] = req->in.vector[idx];
2338 if (state->missing == 0) {
2339 /* if there're no remaining bytes, we're done */
2345 if (state->asked_for_header) {
2348 size_t next_command_ofs;
2353 bool invalid = false;
2355 state->asked_for_header = false;
2358 * We got the SMB2 header and the first 2 bytes
2359 * of the body. We fix the size to just the header
2360 * and manually copy the 2 first bytes to the body section
2362 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2363 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2365 /* allocate vectors for body and dynamic areas */
2366 req->in.vector = talloc_realloc(req, req->in.vector,
2368 req->in.vector_count + 2);
2369 if (req->in.vector == NULL) {
2372 req->in.vector_count += 2;
2374 full_size = state->missing + SMB2_HDR_BODY + 2;
2375 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2376 body_size = SVAL(hdr, SMB2_HDR_BODY);
2378 if (next_command_ofs != 0) {
2379 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2381 * this is invalid, just return a zero
2382 * body and let the caller deal with the error
2385 } else if (next_command_ofs > full_size) {
2387 * this is invalid, just return a zero
2388 * body and let the caller deal with the error
2392 full_size = next_command_ofs;
2397 if (body_size < 2) {
2399 * this is invalid, just return a zero
2400 * body and let the caller deal with the error
2405 if ((body_size % 2) != 0) {
2409 if (body_size > (full_size - SMB2_HDR_BODY)) {
2411 * this is invalid, just return a zero
2412 * body and let the caller deal with the error
2419 /* the caller should check this */
2423 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2425 state->missing -= (body_size - 2) + dyn_size;
2427 body = talloc_array(req->in.vector, uint8_t, body_size);
2432 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2437 req->in.vector[idx].iov_base = (void *)body;
2438 req->in.vector[idx].iov_len = body_size;
2439 req->in.vector[idx+1].iov_base = (void *)dyn;
2440 req->in.vector[idx+1].iov_len = dyn_size;
2442 vector = talloc_array(mem_ctx, struct iovec, 2);
2443 if (vector == NULL) {
2448 * the first 2 bytes of the body were already fetched
2449 * together with the header
2451 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2452 vector[0].iov_base = body + 2;
2453 vector[0].iov_len = body_size - 2;
2455 vector[1] = req->in.vector[idx+1];
2463 * when we endup here, we're looking for a new SMB2 request
2464 * next. And we ask for its header and the first 2 bytes of
2465 * the body (like we did for the first SMB2 request).
2468 req->in.vector = talloc_realloc(req, req->in.vector,
2470 req->in.vector_count + 1);
2471 if (req->in.vector == NULL) {
2474 req->in.vector_count += 1;
2477 * We assume it's a SMB2 request,
2478 * and we first get the header and the
2479 * first 2 bytes (the struct size) of the body
2481 len = SMB2_HDR_BODY + 2;
2483 if (len > state->missing) {
2484 /* let the caller handle the error */
2485 len = state->missing;
2488 state->missing -= len;
2489 state->asked_for_header = true;
2491 buf = talloc_array(req->in.vector, uint8_t, len);
2496 req->in.vector[idx].iov_base = (void *)buf;
2497 req->in.vector[idx].iov_len = len;
2499 vector = talloc_array(mem_ctx, struct iovec, 1);
2500 if (vector == NULL) {
2504 vector[0] = req->in.vector[idx];
2511 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2513 struct tevent_req *req =
2514 tevent_req_callback_data(subreq,
2520 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2522 status = map_nt_error_from_unix(sys_errno);
2523 tevent_req_nterror(req, status);
2527 tevent_req_done(req);
2530 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2531 TALLOC_CTX *mem_ctx,
2532 struct smbd_smb2_request **_smb2_req)
2534 struct smbd_smb2_request_read_state *state =
2535 tevent_req_data(req,
2536 struct smbd_smb2_request_read_state);
2539 if (tevent_req_is_nterror(req, &status)) {
2540 tevent_req_received(req);
2544 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2545 *_smb2_req = state->smb2_req;
2546 tevent_req_received(req);
2547 return NT_STATUS_OK;
2550 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2552 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2554 size_t max_send_queue_len;
2555 size_t cur_send_queue_len;
2556 struct tevent_req *subreq;
2558 if (sconn->smb2.compound_related_in_progress) {
2560 * Can't read another until the related
2563 return NT_STATUS_OK;
2566 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2568 * if there is already a smbd_smb2_request_read
2569 * pending, we are done.
2571 return NT_STATUS_OK;
2574 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2575 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2577 if (cur_send_queue_len > max_send_queue_len) {
2579 * if we have a lot of requests to send,
2580 * we wait until they are on the wire until we
2581 * ask for the next request.
2583 return NT_STATUS_OK;
2586 /* ask for the next request */
2587 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2588 if (subreq == NULL) {
2589 return NT_STATUS_NO_MEMORY;
2591 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2593 return NT_STATUS_OK;
2596 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2597 const uint8_t *inbuf, size_t size)
2600 struct smbd_smb2_request *req = NULL;
2602 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2603 (unsigned int)size));
2605 status = smbd_initialize_smb2(sconn);
2606 if (!NT_STATUS_IS_OK(status)) {
2607 smbd_server_connection_terminate(sconn, nt_errstr(status));
2611 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2612 if (!NT_STATUS_IS_OK(status)) {
2613 smbd_server_connection_terminate(sconn, nt_errstr(status));
2617 status = smbd_smb2_request_validate(req);
2618 if (!NT_STATUS_IS_OK(status)) {
2619 smbd_server_connection_terminate(sconn, nt_errstr(status));
2623 status = smbd_smb2_request_setup_out(req);
2624 if (!NT_STATUS_IS_OK(status)) {
2625 smbd_server_connection_terminate(sconn, nt_errstr(status));
2629 status = smbd_smb2_request_dispatch(req);
2630 if (!NT_STATUS_IS_OK(status)) {
2631 smbd_server_connection_terminate(sconn, nt_errstr(status));
2635 status = smbd_smb2_request_next_incoming(sconn);
2636 if (!NT_STATUS_IS_OK(status)) {
2637 smbd_server_connection_terminate(sconn, nt_errstr(status));
2641 sconn->num_requests++;
2644 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2646 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2647 struct smbd_server_connection);
2649 struct smbd_smb2_request *req = NULL;
2651 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2652 TALLOC_FREE(subreq);
2653 if (!NT_STATUS_IS_OK(status)) {
2654 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2655 nt_errstr(status)));
2656 smbd_server_connection_terminate(sconn, nt_errstr(status));
2660 if (req->in.nbt_hdr[0] != 0x00) {
2661 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2662 req->in.nbt_hdr[0]));
2667 req->current_idx = 1;
2669 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2670 req->current_idx, req->in.vector_count));
2672 status = smbd_smb2_request_validate(req);
2673 if (!NT_STATUS_IS_OK(status)) {
2674 smbd_server_connection_terminate(sconn, nt_errstr(status));
2678 status = smbd_smb2_request_setup_out(req);
2679 if (!NT_STATUS_IS_OK(status)) {
2680 smbd_server_connection_terminate(sconn, nt_errstr(status));
2684 status = smbd_smb2_request_dispatch(req);
2685 if (!NT_STATUS_IS_OK(status)) {
2686 smbd_server_connection_terminate(sconn, nt_errstr(status));
2691 status = smbd_smb2_request_next_incoming(sconn);
2692 if (!NT_STATUS_IS_OK(status)) {
2693 smbd_server_connection_terminate(sconn, nt_errstr(status));
2697 sconn->num_requests++;
2699 /* The timeout_processing function isn't run nearly
2700 often enough to implement 'max log size' without
2701 overrunning the size of the file by many megabytes.
2702 This is especially true if we are running at debug
2703 level 10. Checking every 50 SMB2s is a nice
2704 tradeoff of performance vs log file size overrun. */
2706 if ((sconn->num_requests % 50) == 0 &&
2707 need_to_check_log_size()) {
2708 change_to_root_user();