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.credits_granted = 0;
118 sconn->smb2.max_credits = lp_smb2_max_credits();
119 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
120 DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR*sconn->smb2.max_credits);
121 if (sconn->smb2.credits_bitmap == NULL) {
122 return NT_STATUS_NO_MEMORY;
125 ret = tstream_bsd_existing_socket(sconn, sconn->sock,
126 &sconn->smb2.stream);
128 status = map_nt_error_from_unix(errno);
132 /* Ensure child is set to non-blocking mode */
133 set_blocking(sconn->sock, false);
137 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
138 #define _smb2_setlen(_buf,len) do { \
139 uint8_t *buf = (uint8_t *)_buf; \
141 buf[1] = ((len)&0xFF0000)>>16; \
142 buf[2] = ((len)&0xFF00)>>8; \
143 buf[3] = (len)&0xFF; \
146 static void smb2_setup_nbt_length(struct iovec *vector, int count)
151 for (i=1; i < count; i++) {
152 len += vector[i].iov_len;
155 _smb2_setlen(vector[0].iov_base, len);
158 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request **req)
161 (*req)->parent = NULL;
162 (*req)->mem_pool = NULL;
168 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
172 talloc_free(req->mem_pool);
178 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
180 TALLOC_CTX *mem_pool;
181 struct smbd_smb2_request **parent;
182 struct smbd_smb2_request *req;
185 /* Enable this to find subtle valgrind errors. */
186 mem_pool = talloc_init("smbd_smb2_request_allocate");
188 mem_pool = talloc_pool(mem_ctx, 8192);
190 if (mem_pool == NULL) {
194 parent = talloc(mem_pool, struct smbd_smb2_request *);
195 if (parent == NULL) {
196 talloc_free(mem_pool);
200 req = talloc_zero(parent, struct smbd_smb2_request);
202 talloc_free(mem_pool);
206 req->mem_pool = mem_pool;
207 req->parent = parent;
209 talloc_set_destructor(parent, smbd_smb2_request_parent_destructor);
210 talloc_set_destructor(req, smbd_smb2_request_destructor);
215 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
216 const uint8_t *inbuf, size_t size,
217 struct smbd_smb2_request **_req)
219 struct smbd_smb2_request *req;
220 uint32_t protocol_version;
221 const uint8_t *inhdr = NULL;
224 uint32_t next_command_ofs;
226 if (size < (4 + SMB2_HDR_BODY + 2)) {
227 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
228 return NT_STATUS_INVALID_PARAMETER;
233 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
234 if (protocol_version != SMB2_MAGIC) {
235 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
237 return NT_STATUS_INVALID_PARAMETER;
240 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
241 if (cmd != SMB2_OP_NEGPROT) {
242 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
244 return NT_STATUS_INVALID_PARAMETER;
247 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
248 if (next_command_ofs != 0) {
249 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
251 return NT_STATUS_INVALID_PARAMETER;
254 req = smbd_smb2_request_allocate(sconn);
256 return NT_STATUS_NO_MEMORY;
260 talloc_steal(req, inbuf);
262 req->in.vector = talloc_array(req, struct iovec, 4);
263 if (req->in.vector == NULL) {
265 return NT_STATUS_NO_MEMORY;
267 req->in.vector_count = 4;
269 memcpy(req->in.nbt_hdr, inbuf, 4);
272 req->in.vector[0].iov_base = (void *)req->in.nbt_hdr;
273 req->in.vector[0].iov_len = 4;
274 ofs += req->in.vector[0].iov_len;
276 req->in.vector[1].iov_base = (void *)(inbuf + ofs);
277 req->in.vector[1].iov_len = SMB2_HDR_BODY;
278 ofs += req->in.vector[1].iov_len;
280 req->in.vector[2].iov_base = (void *)(inbuf + ofs);
281 req->in.vector[2].iov_len = SVAL(inbuf, ofs) & 0xFFFE;
282 ofs += req->in.vector[2].iov_len;
285 return NT_STATUS_INVALID_PARAMETER;
288 req->in.vector[3].iov_base = (void *)(inbuf + ofs);
289 req->in.vector[3].iov_len = size - ofs;
290 ofs += req->in.vector[3].iov_len;
292 req->current_idx = 1;
298 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
299 const uint8_t *inhdr)
301 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
302 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
303 uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
304 unsigned int bitmap_offset;
306 if (opcode == SMB2_OP_CANCEL) {
307 /* SMB2_CANCEL requests by definition resend messageids. */
311 if (message_id < sconn->smb2.seqnum_low ||
312 message_id > (sconn->smb2.seqnum_low +
313 (sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR))) {
314 DEBUG(0,("smb2_validate_message_id: bad message_id "
315 "%llu (low = %llu, max = %lu)\n",
316 (unsigned long long)message_id,
317 (unsigned long long)sconn->smb2.seqnum_low,
318 (unsigned long)sconn->smb2.max_credits ));
322 if (sconn->smb2.credits_granted == 0) {
323 DEBUG(0,("smb2_validate_message_id: client used more "
324 "credits than granted message_id (%llu)\n",
325 (unsigned long long)message_id));
329 /* client just used a credit. */
330 sconn->smb2.credits_granted -= 1;
332 /* Mark the message_id as seen in the bitmap. */
333 bitmap_offset = (unsigned int)(message_id %
334 (uint64_t)(sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR));
335 if (bitmap_query(credits_bm, bitmap_offset)) {
336 DEBUG(0,("smb2_validate_message_id: duplicate message_id "
337 "%llu (bm offset %u)\n",
338 (unsigned long long)message_id,
342 bitmap_set(credits_bm, bitmap_offset);
344 if (message_id == sconn->smb2.seqnum_low + 1) {
345 /* Move the window forward by all the message_id's
347 while (bitmap_query(credits_bm, bitmap_offset)) {
348 DEBUG(10,("smb2_validate_message_id: clearing "
349 "id %llu (position %u) from bitmap\n",
350 (unsigned long long)(sconn->smb2.seqnum_low + 1),
352 bitmap_clear(credits_bm, bitmap_offset);
353 sconn->smb2.seqnum_low += 1;
354 bitmap_offset = (bitmap_offset + 1) %
355 (sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR);
362 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
367 count = req->in.vector_count;
370 /* It's not a SMB2 request */
371 return NT_STATUS_INVALID_PARAMETER;
374 for (idx=1; idx < count; idx += 3) {
375 const uint8_t *inhdr = NULL;
378 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
379 return NT_STATUS_INVALID_PARAMETER;
382 if (req->in.vector[idx+1].iov_len < 2) {
383 return NT_STATUS_INVALID_PARAMETER;
386 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
388 /* Check the SMB2 header */
389 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
390 return NT_STATUS_INVALID_PARAMETER;
393 if (!smb2_validate_message_id(req->sconn, inhdr)) {
394 return NT_STATUS_INVALID_PARAMETER;
397 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
400 * the 1st request should never have the
401 * SMB2_HDR_FLAG_CHAINED flag set
403 if (flags & SMB2_HDR_FLAG_CHAINED) {
404 req->next_status = NT_STATUS_INVALID_PARAMETER;
407 } else if (idx == 4) {
409 * the 2nd request triggers related vs. unrelated
410 * compounded requests
412 if (flags & SMB2_HDR_FLAG_CHAINED) {
413 req->compound_related = true;
415 } else if (idx > 4) {
418 * It seems the this tests are wrong
419 * see the SMB2-COMPOUND test
423 * all other requests should match the 2nd one
425 if (flags & SMB2_HDR_FLAG_CHAINED) {
426 if (!req->compound_related) {
428 NT_STATUS_INVALID_PARAMETER;
432 if (req->compound_related) {
434 NT_STATUS_INVALID_PARAMETER;
445 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
446 const struct iovec *in_vector,
447 struct iovec *out_vector)
449 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
450 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
451 uint16_t credits_requested;
453 uint16_t credits_granted = 0;
455 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
456 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
458 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
460 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
462 * In case we already send an async interim
463 * response, we should not grant
464 * credits on the final response.
466 credits_requested = 0;
469 if (credits_requested) {
470 uint16_t modified_credits_requested;
474 * Split up max_credits into 1/16ths, and then scale
475 * the requested credits by how many 16ths have been
476 * currently granted. Less than 1/16th == grant all
477 * requested (100%), scale down as more have been
478 * granted. Never ask for less than 1 as the client
479 * asked for at least 1. JRA.
482 multiplier = 16 - (((sconn->smb2.credits_granted * 16) / sconn->smb2.max_credits) % 16);
484 modified_credits_requested = (multiplier * credits_requested) / 16;
485 if (modified_credits_requested == 0) {
486 modified_credits_requested = 1;
489 /* Remember what we gave out. */
490 credits_granted = MIN(modified_credits_requested,
491 (sconn->smb2.max_credits - sconn->smb2.credits_granted));
494 if (credits_granted == 0 && sconn->smb2.credits_granted == 0) {
495 /* First negprot packet, or ensure the client credits can
496 never drop to zero. */
500 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
501 sconn->smb2.credits_granted += credits_granted;
503 DEBUG(10,("smb2_set_operation_credit: requested %u, "
504 "granted %u, total granted %u\n",
505 (unsigned int)credits_requested,
506 (unsigned int)credits_granted,
507 (unsigned int)sconn->smb2.credits_granted ));
510 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
511 struct smbd_smb2_request *outreq)
515 count = outreq->out.vector_count;
517 for (idx=1; idx < count; idx += 3) {
518 smb2_set_operation_credit(outreq->sconn,
519 &inreq->in.vector[idx],
520 &outreq->out.vector[idx]);
524 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
526 struct iovec *vector;
530 count = req->in.vector_count;
531 vector = talloc_zero_array(req, struct iovec, count);
532 if (vector == NULL) {
533 return NT_STATUS_NO_MEMORY;
536 vector[0].iov_base = req->out.nbt_hdr;
537 vector[0].iov_len = 4;
538 SIVAL(req->out.nbt_hdr, 0, 0);
540 for (idx=1; idx < count; idx += 3) {
541 const uint8_t *inhdr = NULL;
543 uint8_t *outhdr = NULL;
544 uint8_t *outbody = NULL;
545 uint32_t next_command_ofs = 0;
546 struct iovec *current = &vector[idx];
548 if ((idx + 3) < count) {
549 /* we have a next command -
550 * setup for the error case. */
551 next_command_ofs = SMB2_HDR_BODY + 9;
554 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
555 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
557 outhdr = talloc_zero_array(vector, uint8_t,
559 if (outhdr == NULL) {
560 return NT_STATUS_NO_MEMORY;
563 outbody = outhdr + SMB2_HDR_BODY;
565 current[0].iov_base = (void *)outhdr;
566 current[0].iov_len = SMB2_HDR_BODY;
568 current[1].iov_base = (void *)outbody;
569 current[1].iov_len = 8;
571 current[2].iov_base = NULL;
572 current[2].iov_len = 0;
574 /* setup the SMB2 header */
575 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
576 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
577 SSVAL(outhdr, SMB2_HDR_EPOCH, 0);
578 SIVAL(outhdr, SMB2_HDR_STATUS,
579 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
580 SSVAL(outhdr, SMB2_HDR_OPCODE,
581 SVAL(inhdr, SMB2_HDR_OPCODE));
582 SIVAL(outhdr, SMB2_HDR_FLAGS,
583 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
584 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
585 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
586 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
587 SIVAL(outhdr, SMB2_HDR_PID,
588 IVAL(inhdr, SMB2_HDR_PID));
589 SIVAL(outhdr, SMB2_HDR_TID,
590 IVAL(inhdr, SMB2_HDR_TID));
591 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
592 BVAL(inhdr, SMB2_HDR_SESSION_ID));
593 memset(outhdr + SMB2_HDR_SIGNATURE, 0, 16);
595 /* setup error body header */
596 SSVAL(outbody, 0x00, 0x08 + 1);
597 SSVAL(outbody, 0x02, 0);
598 SIVAL(outbody, 0x04, 0);
601 req->out.vector = vector;
602 req->out.vector_count = count;
604 /* setup the length of the NBT packet */
605 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
607 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
612 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
614 const char *location)
616 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
618 exit_server_cleanly(reason);
621 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
622 struct iovec *outvec,
623 const struct iovec *srcvec)
625 /* vec[0] is always boilerplate and must
626 * be allocated with size OUTVEC_ALLOC_SIZE. */
628 outvec[0].iov_base = talloc_memdup(ctx,
631 if (!outvec[0].iov_base) {
634 outvec[0].iov_len = SMB2_HDR_BODY;
637 * If this is a "standard" vec[1] of length 8,
638 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
639 * then duplicate this. Else use talloc_memdup().
642 if (srcvec[1].iov_len == 8 &&
643 srcvec[1].iov_base ==
644 ((uint8_t *)srcvec[0].iov_base) +
646 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
648 outvec[1].iov_len = 8;
650 outvec[1].iov_base = talloc_memdup(ctx,
653 if (!outvec[1].iov_base) {
656 outvec[1].iov_len = srcvec[1].iov_len;
660 * If this is a "standard" vec[2] of length 1,
661 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
662 * then duplicate this. Else use talloc_memdup().
665 if (srcvec[2].iov_base &&
667 if (srcvec[2].iov_base ==
668 ((uint8_t *)srcvec[0].iov_base) +
669 (OUTVEC_ALLOC_SIZE - 1) &&
670 srcvec[2].iov_len == 1) {
671 /* Common SMB2 error packet case. */
672 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
673 (OUTVEC_ALLOC_SIZE - 1);
675 outvec[2].iov_base = talloc_memdup(ctx,
678 if (!outvec[2].iov_base) {
682 outvec[2].iov_len = srcvec[2].iov_len;
684 outvec[2].iov_base = NULL;
685 outvec[2].iov_len = 0;
690 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
692 struct smbd_smb2_request *newreq = NULL;
693 struct iovec *outvec = NULL;
694 int count = req->out.vector_count;
697 newreq = smbd_smb2_request_allocate(req->sconn);
702 newreq->sconn = req->sconn;
703 newreq->session = req->session;
704 newreq->do_signing = req->do_signing;
705 newreq->current_idx = req->current_idx;
706 newreq->async = false;
707 newreq->cancelled = false;
708 /* Note we are leaving:
712 uninitialized as NULL here as
713 they're not used in the interim
714 response code. JRA. */
716 outvec = talloc_zero_array(newreq, struct iovec, count);
721 newreq->out.vector = outvec;
722 newreq->out.vector_count = count;
724 /* Setup the outvec's identically to req. */
725 outvec[0].iov_base = newreq->out.nbt_hdr;
726 outvec[0].iov_len = 4;
727 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
729 /* Setup the vectors identically to the ones in req. */
730 for (i = 1; i < count; i += 3) {
731 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
742 smb2_setup_nbt_length(newreq->out.vector,
743 newreq->out.vector_count);
748 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
750 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
753 uint8_t *outhdr = NULL;
754 struct smbd_smb2_request *nreq = NULL;
756 /* Create a new smb2 request we'll use
757 for the interim return. */
758 nreq = dup_smb2_req(req);
760 return NT_STATUS_NO_MEMORY;
763 /* Lose the last 3 out vectors. They're the
764 ones we'll be using for the async reply. */
765 nreq->out.vector_count -= 3;
767 smb2_setup_nbt_length(nreq->out.vector,
768 nreq->out.vector_count);
770 /* Step back to the previous reply. */
771 i = nreq->current_idx - 3;
772 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
773 /* And end the chain. */
774 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
776 /* Calculate outgoing credits */
777 smb2_calculate_credits(req, nreq);
779 /* Re-sign if needed. */
780 if (nreq->do_signing) {
782 status = smb2_signing_sign_pdu(nreq->session->session_key,
783 &nreq->out.vector[i], 3);
784 if (!NT_STATUS_IS_OK(status)) {
788 if (DEBUGLEVEL >= 10) {
789 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
790 (unsigned int)nreq->current_idx );
791 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
792 (unsigned int)nreq->out.vector_count );
793 print_req_vectors(nreq);
795 nreq->subreq = tstream_writev_queue_send(nreq,
796 nreq->sconn->smb2.event_ctx,
797 nreq->sconn->smb2.stream,
798 nreq->sconn->smb2.send_queue,
800 nreq->out.vector_count);
802 if (nreq->subreq == NULL) {
803 return NT_STATUS_NO_MEMORY;
806 tevent_req_set_callback(nreq->subreq,
807 smbd_smb2_request_writev_done,
813 struct smbd_smb2_request_pending_state {
814 struct smbd_server_connection *sconn;
815 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
816 struct iovec vector[3];
819 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
821 struct smbd_smb2_request_pending_state *state =
822 tevent_req_callback_data(subreq,
823 struct smbd_smb2_request_pending_state);
824 struct smbd_server_connection *sconn = state->sconn;
828 ret = tstream_writev_queue_recv(subreq, &sys_errno);
831 NTSTATUS status = map_nt_error_from_unix(sys_errno);
832 smbd_server_connection_terminate(sconn, nt_errstr(status));
839 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
840 struct tevent_req *subreq)
843 struct smbd_smb2_request_pending_state *state = NULL;
844 int i = req->current_idx;
845 uint8_t *reqhdr = NULL;
847 uint8_t *body = NULL;
849 uint64_t message_id = 0;
850 uint64_t async_id = 0;
851 struct iovec *outvec = NULL;
853 if (!tevent_req_is_in_progress(subreq)) {
857 req->subreq = subreq;
861 /* We're already async. */
865 if (req->in.vector_count > i + 3) {
867 * We're trying to go async in a compound
868 * request chain. This is not allowed.
869 * Cancel the outstanding request.
871 tevent_req_cancel(req->subreq);
872 return smbd_smb2_request_error(req,
873 NT_STATUS_INSUFFICIENT_RESOURCES);
876 if (DEBUGLEVEL >= 10) {
877 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
878 (unsigned int)req->current_idx );
879 print_req_vectors(req);
882 if (req->out.vector_count > 4) {
883 /* This is a compound reply. We
884 * must do an interim response
885 * followed by the async response
888 status = smb2_send_async_interim_response(req);
889 if (!NT_STATUS_IS_OK(status)) {
894 * We're splitting off the last SMB2
895 * request in a compound set, and the
896 * smb2_send_async_interim_response()
897 * call above just sent all the replies
898 * for the previous SMB2 requests in
899 * this compound set. So we're no longer
900 * in the "compound_related_in_progress"
901 * state, and this is no longer a compound
904 req->compound_related = false;
905 req->sconn->smb2.compound_related_in_progress = false;
908 /* Don't return an intermediate packet on a pipe read/write. */
909 if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
913 reqhdr = (uint8_t *)req->out.vector[i].iov_base;
914 flags = (IVAL(reqhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
915 message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
916 async_id = message_id; /* keep it simple for now... */
919 * What we send is identical to a smbd_smb2_request_error
920 * packet with an error status of STATUS_PENDING. Make use
921 * of this fact sometime when refactoring. JRA.
924 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
926 return NT_STATUS_NO_MEMORY;
928 state->sconn = req->sconn;
930 state->vector[0].iov_base = (void *)state->buf;
931 state->vector[0].iov_len = 4;
933 state->vector[1].iov_base = state->buf + 4;
934 state->vector[1].iov_len = SMB2_HDR_BODY;
936 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
937 state->vector[2].iov_len = 9;
939 smb2_setup_nbt_length(state->vector, 3);
941 hdr = (uint8_t *)state->vector[1].iov_base;
942 body = (uint8_t *)state->vector[2].iov_base;
944 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
945 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
946 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
947 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
948 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(reqhdr, SMB2_HDR_OPCODE));
950 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
951 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
952 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
953 SBVAL(hdr, SMB2_HDR_PID, async_id);
954 SBVAL(hdr, SMB2_HDR_SESSION_ID,
955 BVAL(reqhdr, SMB2_HDR_SESSION_ID));
956 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
958 SSVAL(body, 0x00, 0x08 + 1);
960 SCVAL(body, 0x02, 0);
961 SCVAL(body, 0x03, 0);
962 SIVAL(body, 0x04, 0);
963 /* Match W2K8R2... */
964 SCVAL(body, 0x08, 0x21);
966 /* Ensure we correctly go through crediting. Grant
967 the credits now, and zero credits on the final
969 smb2_set_operation_credit(req->sconn,
973 if (req->do_signing) {
974 status = smb2_signing_sign_pdu(req->session->session_key,
975 &state->vector[1], 2);
976 if (!NT_STATUS_IS_OK(status)) {
981 subreq = tstream_writev_queue_send(state,
982 req->sconn->smb2.event_ctx,
983 req->sconn->smb2.stream,
984 req->sconn->smb2.send_queue,
988 if (subreq == NULL) {
989 return NT_STATUS_NO_MEMORY;
992 tevent_req_set_callback(subreq,
993 smbd_smb2_request_pending_writev_done,
996 /* Note we're going async with this request. */
1002 * Now manipulate req so that the outstanding async request
1003 * is the only one left in the struct smbd_smb2_request.
1006 if (req->current_idx == 1) {
1007 /* There was only one. */
1011 /* Re-arrange the in.vectors. */
1012 req->in.vector[1] = req->in.vector[i];
1013 req->in.vector[2] = req->in.vector[i+1];
1014 req->in.vector[3] = req->in.vector[i+2];
1015 req->in.vector_count = 4;
1016 /* Reset the new in size. */
1017 smb2_setup_nbt_length(req->in.vector, 4);
1019 /* Now recreate the out.vectors. */
1020 outvec = talloc_zero_array(req, struct iovec, 4);
1022 return NT_STATUS_NO_MEMORY;
1025 /* 0 is always boilerplate and must
1026 * be of size 4 for the length field. */
1028 outvec[0].iov_base = req->out.nbt_hdr;
1029 outvec[0].iov_len = 4;
1030 SIVAL(req->out.nbt_hdr, 0, 0);
1032 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
1033 return NT_STATUS_NO_MEMORY;
1036 TALLOC_FREE(req->out.vector);
1038 req->out.vector = outvec;
1040 req->current_idx = 1;
1041 req->out.vector_count = 4;
1045 smb2_setup_nbt_length(req->out.vector,
1046 req->out.vector_count);
1049 /* Ensure our final reply matches the interim one. */
1050 reqhdr = (uint8_t *)req->out.vector[1].iov_base;
1051 SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1052 SBVAL(reqhdr, SMB2_HDR_PID, async_id);
1055 const uint8_t *inhdr =
1056 (const uint8_t *)req->in.vector[1].iov_base;
1057 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1059 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1060 (unsigned long long)async_id ));
1064 return NT_STATUS_OK;
1067 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1069 struct smbd_server_connection *sconn = req->sconn;
1070 struct smbd_smb2_request *cur;
1071 const uint8_t *inhdr;
1072 int i = req->current_idx;
1074 uint64_t search_message_id;
1075 uint64_t search_async_id;
1078 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1080 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1081 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1082 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1085 * we don't need the request anymore
1086 * cancel requests never have a response
1088 DLIST_REMOVE(req->sconn->smb2.requests, req);
1091 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1092 const uint8_t *outhdr;
1093 uint64_t message_id;
1096 i = cur->current_idx;
1098 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1100 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1101 async_id = BVAL(outhdr, SMB2_HDR_PID);
1103 if (flags & SMB2_HDR_FLAG_ASYNC) {
1104 if (search_async_id == async_id) {
1105 found_id = async_id;
1109 if (search_message_id == message_id) {
1110 found_id = message_id;
1116 if (cur && cur->subreq) {
1117 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1118 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1119 "cancel opcode[%s] mid %llu\n",
1120 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1121 (unsigned long long)found_id ));
1122 tevent_req_cancel(cur->subreq);
1125 return NT_STATUS_OK;
1128 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1130 const uint8_t *inhdr;
1131 int i = req->current_idx;
1136 NTSTATUS session_status;
1137 uint32_t allowed_flags;
1138 NTSTATUS return_value;
1140 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1142 /* TODO: verify more things */
1144 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1145 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1146 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1147 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1148 smb2_opcode_name(opcode),
1149 (unsigned long long)mid));
1151 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1152 SMB2_HDR_FLAG_SIGNED |
1154 if (opcode == SMB2_OP_CANCEL) {
1155 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1157 if ((flags & ~allowed_flags) != 0) {
1158 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1162 * Check if the client provided a valid session id,
1163 * if so smbd_smb2_request_check_session() calls
1164 * set_current_user_info().
1166 * As some command don't require a valid session id
1167 * we defer the check of the session_status
1169 session_status = smbd_smb2_request_check_session(req);
1171 req->do_signing = false;
1172 if (flags & SMB2_HDR_FLAG_SIGNED) {
1173 if (!NT_STATUS_IS_OK(session_status)) {
1174 return smbd_smb2_request_error(req, session_status);
1177 req->do_signing = true;
1178 status = smb2_signing_check_pdu(req->session->session_key,
1179 &req->in.vector[i], 3);
1180 if (!NT_STATUS_IS_OK(status)) {
1181 return smbd_smb2_request_error(req, status);
1183 } else if (opcode == SMB2_OP_CANCEL) {
1184 /* Cancel requests are allowed to skip the signing */
1185 } else if (req->session && req->session->do_signing) {
1186 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1189 if (flags & SMB2_HDR_FLAG_CHAINED) {
1191 * This check is mostly for giving the correct error code
1192 * for compounded requests.
1194 * TODO: we may need to move this after the session
1197 if (!NT_STATUS_IS_OK(req->next_status)) {
1198 return smbd_smb2_request_error(req, req->next_status);
1201 req->compat_chain_fsp = NULL;
1204 if (req->compound_related) {
1205 req->sconn->smb2.compound_related_in_progress = true;
1209 case SMB2_OP_NEGPROT:
1210 /* This call needs to be run as root */
1211 change_to_root_user();
1214 START_PROFILE(smb2_negprot);
1215 return_value = smbd_smb2_request_process_negprot(req);
1216 END_PROFILE(smb2_negprot);
1220 case SMB2_OP_SESSSETUP:
1221 /* This call needs to be run as root */
1222 change_to_root_user();
1225 START_PROFILE(smb2_sesssetup);
1226 return_value = smbd_smb2_request_process_sesssetup(req);
1227 END_PROFILE(smb2_sesssetup);
1231 case SMB2_OP_LOGOFF:
1232 if (!NT_STATUS_IS_OK(session_status)) {
1233 return_value = smbd_smb2_request_error(req, session_status);
1237 /* This call needs to be run as root */
1238 change_to_root_user();
1241 START_PROFILE(smb2_logoff);
1242 return_value = smbd_smb2_request_process_logoff(req);
1243 END_PROFILE(smb2_logoff);
1248 if (!NT_STATUS_IS_OK(session_status)) {
1249 return_value = smbd_smb2_request_error(req, session_status);
1254 * This call needs to be run as root.
1256 * smbd_smb2_request_process_tcon()
1257 * calls make_connection_snum(), which will call
1258 * change_to_user(), when needed.
1260 change_to_root_user();
1263 START_PROFILE(smb2_tcon);
1264 return_value = smbd_smb2_request_process_tcon(req);
1265 END_PROFILE(smb2_tcon);
1270 if (!NT_STATUS_IS_OK(session_status)) {
1271 return_value = smbd_smb2_request_error(req, session_status);
1275 * This call needs to be run as user.
1277 * smbd_smb2_request_check_tcon()
1278 * calls change_to_user() on success.
1280 status = smbd_smb2_request_check_tcon(req);
1281 if (!NT_STATUS_IS_OK(status)) {
1282 return_value = smbd_smb2_request_error(req, status);
1285 /* This call needs to be run as root */
1286 change_to_root_user();
1290 START_PROFILE(smb2_tdis);
1291 return_value = smbd_smb2_request_process_tdis(req);
1292 END_PROFILE(smb2_tdis);
1296 case SMB2_OP_CREATE:
1297 if (!NT_STATUS_IS_OK(session_status)) {
1298 return_value = smbd_smb2_request_error(req, session_status);
1302 * This call needs to be run as user.
1304 * smbd_smb2_request_check_tcon()
1305 * calls change_to_user() on success.
1307 status = smbd_smb2_request_check_tcon(req);
1308 if (!NT_STATUS_IS_OK(status)) {
1309 return_value = smbd_smb2_request_error(req, status);
1314 START_PROFILE(smb2_create);
1315 return_value = smbd_smb2_request_process_create(req);
1316 END_PROFILE(smb2_create);
1321 if (!NT_STATUS_IS_OK(session_status)) {
1322 return_value = smbd_smb2_request_error(req, session_status);
1326 * This call needs to be run as user.
1328 * smbd_smb2_request_check_tcon()
1329 * calls change_to_user() on success.
1331 status = smbd_smb2_request_check_tcon(req);
1332 if (!NT_STATUS_IS_OK(status)) {
1333 return_value = smbd_smb2_request_error(req, status);
1338 START_PROFILE(smb2_close);
1339 return_value = smbd_smb2_request_process_close(req);
1340 END_PROFILE(smb2_close);
1345 if (!NT_STATUS_IS_OK(session_status)) {
1346 return_value = smbd_smb2_request_error(req, session_status);
1350 * This call needs to be run as user.
1352 * smbd_smb2_request_check_tcon()
1353 * calls change_to_user() on success.
1355 status = smbd_smb2_request_check_tcon(req);
1356 if (!NT_STATUS_IS_OK(status)) {
1357 return_value = smbd_smb2_request_error(req, status);
1362 START_PROFILE(smb2_flush);
1363 return_value = smbd_smb2_request_process_flush(req);
1364 END_PROFILE(smb2_flush);
1369 if (!NT_STATUS_IS_OK(session_status)) {
1370 return_value = smbd_smb2_request_error(req, session_status);
1374 * This call needs to be run as user.
1376 * smbd_smb2_request_check_tcon()
1377 * calls change_to_user() on success.
1379 status = smbd_smb2_request_check_tcon(req);
1380 if (!NT_STATUS_IS_OK(status)) {
1381 return_value = smbd_smb2_request_error(req, status);
1386 START_PROFILE(smb2_read);
1387 return_value = smbd_smb2_request_process_read(req);
1388 END_PROFILE(smb2_read);
1393 if (!NT_STATUS_IS_OK(session_status)) {
1394 return_value = smbd_smb2_request_error(req, session_status);
1398 * This call needs to be run as user.
1400 * smbd_smb2_request_check_tcon()
1401 * calls change_to_user() on success.
1403 status = smbd_smb2_request_check_tcon(req);
1404 if (!NT_STATUS_IS_OK(status)) {
1405 return_value = smbd_smb2_request_error(req, status);
1410 START_PROFILE(smb2_write);
1411 return_value = smbd_smb2_request_process_write(req);
1412 END_PROFILE(smb2_write);
1417 if (!NT_STATUS_IS_OK(session_status)) {
1418 /* Too ugly to live ? JRA. */
1419 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1420 session_status = NT_STATUS_FILE_CLOSED;
1422 return_value = smbd_smb2_request_error(req, session_status);
1426 * This call needs to be run as user.
1428 * smbd_smb2_request_check_tcon()
1429 * calls change_to_user() on success.
1431 status = smbd_smb2_request_check_tcon(req);
1432 if (!NT_STATUS_IS_OK(status)) {
1433 /* Too ugly to live ? JRA. */
1434 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1435 status = NT_STATUS_FILE_CLOSED;
1437 return_value = smbd_smb2_request_error(req, status);
1442 START_PROFILE(smb2_lock);
1443 return_value = smbd_smb2_request_process_lock(req);
1444 END_PROFILE(smb2_lock);
1449 if (!NT_STATUS_IS_OK(session_status)) {
1450 return_value = smbd_smb2_request_error(req, session_status);
1454 * This call needs to be run as user.
1456 * smbd_smb2_request_check_tcon()
1457 * calls change_to_user() on success.
1459 status = smbd_smb2_request_check_tcon(req);
1460 if (!NT_STATUS_IS_OK(status)) {
1461 return_value = smbd_smb2_request_error(req, status);
1466 START_PROFILE(smb2_ioctl);
1467 return_value = smbd_smb2_request_process_ioctl(req);
1468 END_PROFILE(smb2_ioctl);
1472 case SMB2_OP_CANCEL:
1474 * This call needs to be run as root
1476 * That is what we also do in the SMB1 case.
1478 change_to_root_user();
1481 START_PROFILE(smb2_cancel);
1482 return_value = smbd_smb2_request_process_cancel(req);
1483 END_PROFILE(smb2_cancel);
1487 case SMB2_OP_KEEPALIVE:
1488 /* This call needs to be run as root */
1489 change_to_root_user();
1492 START_PROFILE(smb2_keepalive);
1493 return_value = smbd_smb2_request_process_keepalive(req);
1494 END_PROFILE(smb2_keepalive);
1499 if (!NT_STATUS_IS_OK(session_status)) {
1500 return_value = smbd_smb2_request_error(req, session_status);
1504 * This call needs to be run as user.
1506 * smbd_smb2_request_check_tcon()
1507 * calls change_to_user() on success.
1509 status = smbd_smb2_request_check_tcon(req);
1510 if (!NT_STATUS_IS_OK(status)) {
1511 return_value = smbd_smb2_request_error(req, status);
1516 START_PROFILE(smb2_find);
1517 return_value = smbd_smb2_request_process_find(req);
1518 END_PROFILE(smb2_find);
1522 case SMB2_OP_NOTIFY:
1523 if (!NT_STATUS_IS_OK(session_status)) {
1524 return_value = smbd_smb2_request_error(req, session_status);
1528 * This call needs to be run as user.
1530 * smbd_smb2_request_check_tcon()
1531 * calls change_to_user() on success.
1533 status = smbd_smb2_request_check_tcon(req);
1534 if (!NT_STATUS_IS_OK(status)) {
1535 return_value = smbd_smb2_request_error(req, status);
1540 START_PROFILE(smb2_notify);
1541 return_value = smbd_smb2_request_process_notify(req);
1542 END_PROFILE(smb2_notify);
1546 case SMB2_OP_GETINFO:
1547 if (!NT_STATUS_IS_OK(session_status)) {
1548 return_value = smbd_smb2_request_error(req, session_status);
1552 * This call needs to be run as user.
1554 * smbd_smb2_request_check_tcon()
1555 * calls change_to_user() on success.
1557 status = smbd_smb2_request_check_tcon(req);
1558 if (!NT_STATUS_IS_OK(status)) {
1559 return_value = smbd_smb2_request_error(req, status);
1564 START_PROFILE(smb2_getinfo);
1565 return_value = smbd_smb2_request_process_getinfo(req);
1566 END_PROFILE(smb2_getinfo);
1570 case SMB2_OP_SETINFO:
1571 if (!NT_STATUS_IS_OK(session_status)) {
1572 return_value = smbd_smb2_request_error(req, session_status);
1576 * This call needs to be run as user.
1578 * smbd_smb2_request_check_tcon()
1579 * calls change_to_user() on success.
1581 status = smbd_smb2_request_check_tcon(req);
1582 if (!NT_STATUS_IS_OK(status)) {
1583 return_value = smbd_smb2_request_error(req, status);
1588 START_PROFILE(smb2_setinfo);
1589 return_value = smbd_smb2_request_process_setinfo(req);
1590 END_PROFILE(smb2_setinfo);
1595 if (!NT_STATUS_IS_OK(session_status)) {
1596 return_value = smbd_smb2_request_error(req, session_status);
1600 * This call needs to be run as user.
1602 * smbd_smb2_request_check_tcon()
1603 * calls change_to_user() on success.
1605 status = smbd_smb2_request_check_tcon(req);
1606 if (!NT_STATUS_IS_OK(status)) {
1607 return_value = smbd_smb2_request_error(req, status);
1612 START_PROFILE(smb2_break);
1613 return_value = smbd_smb2_request_process_break(req);
1614 END_PROFILE(smb2_break);
1619 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1622 return return_value;
1625 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1627 struct tevent_req *subreq;
1628 int i = req->current_idx;
1632 req->current_idx += 3;
1634 if (req->current_idx < req->out.vector_count) {
1636 * We must process the remaining compound
1637 * SMB2 requests before any new incoming SMB2
1638 * requests. This is because incoming SMB2
1639 * requests may include a cancel for a
1640 * compound request we haven't processed
1643 struct tevent_immediate *im = tevent_create_immediate(req);
1645 return NT_STATUS_NO_MEMORY;
1647 tevent_schedule_immediate(im,
1648 req->sconn->smb2.event_ctx,
1649 smbd_smb2_request_dispatch_immediate,
1651 return NT_STATUS_OK;
1654 if (req->compound_related) {
1655 req->sconn->smb2.compound_related_in_progress = false;
1658 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1660 /* Set credit for this operation (zero credits if this
1661 is a final reply for an async operation). */
1662 smb2_set_operation_credit(req->sconn,
1664 &req->out.vector[i]);
1666 if (req->do_signing) {
1668 status = smb2_signing_sign_pdu(req->session->session_key,
1669 &req->out.vector[i], 3);
1670 if (!NT_STATUS_IS_OK(status)) {
1675 if (DEBUGLEVEL >= 10) {
1676 dbgtext("smbd_smb2_request_reply: sending...\n");
1677 print_req_vectors(req);
1680 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1681 if (req->out.vector_count == 4 &&
1682 req->out.vector[3].iov_base == NULL &&
1683 req->out.vector[3].iov_len != 0) {
1684 /* Dynamic part is NULL. Chop it off,
1685 We're going to send it via sendfile. */
1686 req->out.vector_count -= 1;
1689 subreq = tstream_writev_queue_send(req,
1690 req->sconn->smb2.event_ctx,
1691 req->sconn->smb2.stream,
1692 req->sconn->smb2.send_queue,
1694 req->out.vector_count);
1695 if (subreq == NULL) {
1696 return NT_STATUS_NO_MEMORY;
1698 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1700 * We're done with this request -
1701 * move it off the "being processed" queue.
1703 DLIST_REMOVE(req->sconn->smb2.requests, req);
1705 return NT_STATUS_OK;
1708 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
1710 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1711 struct tevent_immediate *im,
1714 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1715 struct smbd_smb2_request);
1716 struct smbd_server_connection *sconn = req->sconn;
1721 if (DEBUGLEVEL >= 10) {
1722 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1723 req->current_idx, req->in.vector_count));
1724 print_req_vectors(req);
1727 status = smbd_smb2_request_dispatch(req);
1728 if (!NT_STATUS_IS_OK(status)) {
1729 smbd_server_connection_terminate(sconn, nt_errstr(status));
1733 status = smbd_smb2_request_next_incoming(sconn);
1734 if (!NT_STATUS_IS_OK(status)) {
1735 smbd_server_connection_terminate(sconn, nt_errstr(status));
1740 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1742 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1743 struct smbd_smb2_request);
1744 struct smbd_server_connection *sconn = req->sconn;
1749 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1750 TALLOC_FREE(subreq);
1753 status = map_nt_error_from_unix(sys_errno);
1754 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1755 nt_errstr(status)));
1756 smbd_server_connection_terminate(sconn, nt_errstr(status));
1760 status = smbd_smb2_request_next_incoming(sconn);
1761 if (!NT_STATUS_IS_OK(status)) {
1762 smbd_server_connection_terminate(sconn, nt_errstr(status));
1767 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1769 DATA_BLOB body, DATA_BLOB *dyn,
1770 const char *location)
1773 int i = req->current_idx;
1774 uint32_t next_command_ofs;
1776 DEBUG(10,("smbd_smb2_request_done_ex: "
1777 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1778 i, nt_errstr(status), (unsigned int)body.length,
1780 (unsigned int)(dyn ? dyn->length : 0),
1783 if (body.length < 2) {
1784 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1787 if ((body.length % 2) != 0) {
1788 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1791 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1793 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1794 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1796 req->out.vector[i+1].iov_base = (void *)body.data;
1797 req->out.vector[i+1].iov_len = body.length;
1800 req->out.vector[i+2].iov_base = (void *)dyn->data;
1801 req->out.vector[i+2].iov_len = dyn->length;
1803 req->out.vector[i+2].iov_base = NULL;
1804 req->out.vector[i+2].iov_len = 0;
1807 /* see if we need to recalculate the offset to the next response */
1808 if (next_command_ofs > 0) {
1809 next_command_ofs = SMB2_HDR_BODY;
1810 next_command_ofs += req->out.vector[i+1].iov_len;
1811 next_command_ofs += req->out.vector[i+2].iov_len;
1814 if ((next_command_ofs % 8) != 0) {
1815 size_t pad_size = 8 - (next_command_ofs % 8);
1816 if (req->out.vector[i+2].iov_len == 0) {
1818 * if the dyn buffer is empty
1819 * we can use it to add padding
1823 pad = talloc_zero_array(req->out.vector,
1826 return smbd_smb2_request_error(req,
1827 NT_STATUS_NO_MEMORY);
1830 req->out.vector[i+2].iov_base = (void *)pad;
1831 req->out.vector[i+2].iov_len = pad_size;
1834 * For now we copy the dynamic buffer
1835 * and add the padding to the new buffer
1842 old_size = req->out.vector[i+2].iov_len;
1843 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
1845 new_size = old_size + pad_size;
1846 new_dyn = talloc_zero_array(req->out.vector,
1848 if (new_dyn == NULL) {
1849 return smbd_smb2_request_error(req,
1850 NT_STATUS_NO_MEMORY);
1853 memcpy(new_dyn, old_dyn, old_size);
1854 memset(new_dyn + old_size, 0, pad_size);
1856 req->out.vector[i+2].iov_base = (void *)new_dyn;
1857 req->out.vector[i+2].iov_len = new_size;
1859 next_command_ofs += pad_size;
1862 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1864 return smbd_smb2_request_reply(req);
1867 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
1870 const char *location)
1873 int i = req->current_idx;
1874 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
1876 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1877 i, nt_errstr(status), info ? " +info" : "",
1880 body.data = outhdr + SMB2_HDR_BODY;
1882 SSVAL(body.data, 0, 9);
1885 SIVAL(body.data, 0x04, info->length);
1887 /* Allocated size of req->out.vector[i].iov_base
1888 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
1889 * 1 byte without having to do an alloc.
1891 info = talloc_zero_array(req->out.vector,
1895 return NT_STATUS_NO_MEMORY;
1897 info->data = ((uint8_t *)outhdr) +
1898 OUTVEC_ALLOC_SIZE - 1;
1900 SCVAL(info->data, 0, 0);
1904 * if a request fails, all other remaining
1905 * compounded requests should fail too
1907 req->next_status = NT_STATUS_INVALID_PARAMETER;
1909 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
1913 struct smbd_smb2_send_oplock_break_state {
1914 struct smbd_server_connection *sconn;
1915 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
1916 struct iovec vector;
1919 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
1921 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
1922 uint64_t file_id_persistent,
1923 uint64_t file_id_volatile,
1924 uint8_t oplock_level)
1926 struct smbd_smb2_send_oplock_break_state *state;
1927 struct tevent_req *subreq;
1931 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
1932 if (state == NULL) {
1933 return NT_STATUS_NO_MEMORY;
1935 state->sconn = sconn;
1937 state->vector.iov_base = (void *)state->buf;
1938 state->vector.iov_len = sizeof(state->buf);
1940 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
1941 hdr = state->buf + 4;
1942 body = hdr + SMB2_HDR_BODY;
1944 SIVAL(hdr, 0, SMB2_MAGIC);
1945 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1946 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1947 SIVAL(hdr, SMB2_HDR_STATUS, 0);
1948 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
1949 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
1950 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
1951 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1952 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
1953 SIVAL(hdr, SMB2_HDR_PID, 0);
1954 SIVAL(hdr, SMB2_HDR_TID, 0);
1955 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
1956 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
1958 SSVAL(body, 0x00, 0x18);
1960 SCVAL(body, 0x02, oplock_level);
1961 SCVAL(body, 0x03, 0); /* reserved */
1962 SIVAL(body, 0x04, 0); /* reserved */
1963 SBVAL(body, 0x08, file_id_persistent);
1964 SBVAL(body, 0x10, file_id_volatile);
1966 subreq = tstream_writev_queue_send(state,
1967 sconn->smb2.event_ctx,
1969 sconn->smb2.send_queue,
1971 if (subreq == NULL) {
1972 return NT_STATUS_NO_MEMORY;
1974 tevent_req_set_callback(subreq,
1975 smbd_smb2_oplock_break_writev_done,
1978 return NT_STATUS_OK;
1981 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
1983 struct smbd_smb2_send_oplock_break_state *state =
1984 tevent_req_callback_data(subreq,
1985 struct smbd_smb2_send_oplock_break_state);
1986 struct smbd_server_connection *sconn = state->sconn;
1990 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1991 TALLOC_FREE(subreq);
1993 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1994 smbd_server_connection_terminate(sconn, nt_errstr(status));
2001 struct smbd_smb2_request_read_state {
2003 bool asked_for_header;
2004 struct smbd_smb2_request *smb2_req;
2007 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2009 TALLOC_CTX *mem_ctx,
2010 struct iovec **_vector,
2012 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2014 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2015 struct tevent_context *ev,
2016 struct smbd_server_connection *sconn)
2018 struct tevent_req *req;
2019 struct smbd_smb2_request_read_state *state;
2020 struct tevent_req *subreq;
2022 req = tevent_req_create(mem_ctx, &state,
2023 struct smbd_smb2_request_read_state);
2028 state->asked_for_header = false;
2030 state->smb2_req = smbd_smb2_request_allocate(state);
2031 if (tevent_req_nomem(state->smb2_req, req)) {
2032 return tevent_req_post(req, ev);
2034 state->smb2_req->sconn = sconn;
2036 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2037 sconn->smb2.recv_queue,
2038 smbd_smb2_request_next_vector,
2040 if (tevent_req_nomem(subreq, req)) {
2041 return tevent_req_post(req, ev);
2043 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2048 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2050 TALLOC_CTX *mem_ctx,
2051 struct iovec **_vector,
2054 struct smbd_smb2_request_read_state *state =
2055 talloc_get_type_abort(private_data,
2056 struct smbd_smb2_request_read_state);
2057 struct smbd_smb2_request *req = state->smb2_req;
2058 struct iovec *vector;
2059 int idx = req->in.vector_count;
2061 uint8_t *buf = NULL;
2063 if (req->in.vector_count == 0) {
2065 * first we need to get the NBT header
2067 req->in.vector = talloc_array(req, struct iovec,
2068 req->in.vector_count + 1);
2069 if (req->in.vector == NULL) {
2072 req->in.vector_count += 1;
2074 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2075 req->in.vector[idx].iov_len = 4;
2077 vector = talloc_array(mem_ctx, struct iovec, 1);
2078 if (vector == NULL) {
2082 vector[0] = req->in.vector[idx];
2089 if (req->in.vector_count == 1) {
2091 * Now we analyze the NBT header
2093 state->missing = smb2_len(req->in.vector[0].iov_base);
2095 if (state->missing == 0) {
2096 /* if there're no remaining bytes, we're done */
2102 req->in.vector = talloc_realloc(req, req->in.vector,
2104 req->in.vector_count + 1);
2105 if (req->in.vector == NULL) {
2108 req->in.vector_count += 1;
2110 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2112 * it's a special NBT message,
2113 * so get all remaining bytes
2115 len = state->missing;
2116 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2118 * it's an invalid message, just read what we can get
2119 * and let the caller handle the error
2121 len = state->missing;
2124 * We assume it's a SMB2 request,
2125 * and we first get the header and the
2126 * first 2 bytes (the struct size) of the body
2128 len = SMB2_HDR_BODY + 2;
2130 state->asked_for_header = true;
2133 state->missing -= len;
2135 buf = talloc_array(req->in.vector, uint8_t, len);
2140 req->in.vector[idx].iov_base = (void *)buf;
2141 req->in.vector[idx].iov_len = len;
2143 vector = talloc_array(mem_ctx, struct iovec, 1);
2144 if (vector == NULL) {
2148 vector[0] = req->in.vector[idx];
2155 if (state->missing == 0) {
2156 /* if there're no remaining bytes, we're done */
2162 if (state->asked_for_header) {
2165 size_t next_command_ofs;
2170 bool invalid = false;
2172 state->asked_for_header = false;
2175 * We got the SMB2 header and the first 2 bytes
2176 * of the body. We fix the size to just the header
2177 * and manually copy the 2 first bytes to the body section
2179 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2180 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2182 /* allocate vectors for body and dynamic areas */
2183 req->in.vector = talloc_realloc(req, req->in.vector,
2185 req->in.vector_count + 2);
2186 if (req->in.vector == NULL) {
2189 req->in.vector_count += 2;
2191 full_size = state->missing + SMB2_HDR_BODY + 2;
2192 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2193 body_size = SVAL(hdr, SMB2_HDR_BODY);
2195 if (next_command_ofs != 0) {
2196 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2198 * this is invalid, just return a zero
2199 * body and let the caller deal with the error
2202 } else if (next_command_ofs > full_size) {
2204 * this is invalid, just return a zero
2205 * body and let the caller deal with the error
2209 full_size = next_command_ofs;
2214 if (body_size < 2) {
2216 * this is invalid, just return a zero
2217 * body and let the caller deal with the error
2222 if ((body_size % 2) != 0) {
2226 if (body_size > (full_size - SMB2_HDR_BODY)) {
2228 * this is invalid, just return a zero
2229 * body and let the caller deal with the error
2236 /* the caller should check this */
2240 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2242 state->missing -= (body_size - 2) + dyn_size;
2244 body = talloc_array(req->in.vector, uint8_t, body_size);
2249 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2254 req->in.vector[idx].iov_base = (void *)body;
2255 req->in.vector[idx].iov_len = body_size;
2256 req->in.vector[idx+1].iov_base = (void *)dyn;
2257 req->in.vector[idx+1].iov_len = dyn_size;
2259 vector = talloc_array(mem_ctx, struct iovec, 2);
2260 if (vector == NULL) {
2265 * the first 2 bytes of the body were already fetched
2266 * together with the header
2268 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2269 vector[0].iov_base = body + 2;
2270 vector[0].iov_len = body_size - 2;
2272 vector[1] = req->in.vector[idx+1];
2280 * when we endup here, we're looking for a new SMB2 request
2281 * next. And we ask for its header and the first 2 bytes of
2282 * the body (like we did for the first SMB2 request).
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;
2294 * We assume it's a SMB2 request,
2295 * and we first get the header and the
2296 * first 2 bytes (the struct size) of the body
2298 len = SMB2_HDR_BODY + 2;
2300 if (len > state->missing) {
2301 /* let the caller handle the error */
2302 len = state->missing;
2305 state->missing -= len;
2306 state->asked_for_header = true;
2308 buf = talloc_array(req->in.vector, uint8_t, len);
2313 req->in.vector[idx].iov_base = (void *)buf;
2314 req->in.vector[idx].iov_len = len;
2316 vector = talloc_array(mem_ctx, struct iovec, 1);
2317 if (vector == NULL) {
2321 vector[0] = req->in.vector[idx];
2328 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2330 struct tevent_req *req =
2331 tevent_req_callback_data(subreq,
2337 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2339 status = map_nt_error_from_unix(sys_errno);
2340 tevent_req_nterror(req, status);
2344 tevent_req_done(req);
2347 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2348 TALLOC_CTX *mem_ctx,
2349 struct smbd_smb2_request **_smb2_req)
2351 struct smbd_smb2_request_read_state *state =
2352 tevent_req_data(req,
2353 struct smbd_smb2_request_read_state);
2356 if (tevent_req_is_nterror(req, &status)) {
2357 tevent_req_received(req);
2361 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2362 *_smb2_req = state->smb2_req;
2363 tevent_req_received(req);
2364 return NT_STATUS_OK;
2367 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2369 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2371 size_t max_send_queue_len;
2372 size_t cur_send_queue_len;
2373 struct tevent_req *subreq;
2375 if (sconn->smb2.compound_related_in_progress) {
2377 * Can't read another until the related
2380 return NT_STATUS_OK;
2383 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2385 * if there is already a smbd_smb2_request_read
2386 * pending, we are done.
2388 return NT_STATUS_OK;
2391 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2392 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2394 if (cur_send_queue_len > max_send_queue_len) {
2396 * if we have a lot of requests to send,
2397 * we wait until they are on the wire until we
2398 * ask for the next request.
2400 return NT_STATUS_OK;
2403 /* ask for the next request */
2404 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2405 if (subreq == NULL) {
2406 return NT_STATUS_NO_MEMORY;
2408 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2410 return NT_STATUS_OK;
2413 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2414 const uint8_t *inbuf, size_t size)
2417 struct smbd_smb2_request *req = NULL;
2419 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2420 (unsigned int)size));
2422 status = smbd_initialize_smb2(sconn);
2423 if (!NT_STATUS_IS_OK(status)) {
2424 smbd_server_connection_terminate(sconn, nt_errstr(status));
2428 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2429 if (!NT_STATUS_IS_OK(status)) {
2430 smbd_server_connection_terminate(sconn, nt_errstr(status));
2434 status = smbd_smb2_request_setup_out(req);
2435 if (!NT_STATUS_IS_OK(status)) {
2436 smbd_server_connection_terminate(sconn, nt_errstr(status));
2440 status = smbd_smb2_request_dispatch(req);
2441 if (!NT_STATUS_IS_OK(status)) {
2442 smbd_server_connection_terminate(sconn, nt_errstr(status));
2446 status = smbd_smb2_request_next_incoming(sconn);
2447 if (!NT_STATUS_IS_OK(status)) {
2448 smbd_server_connection_terminate(sconn, nt_errstr(status));
2452 sconn->num_requests++;
2455 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2457 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2458 struct smbd_server_connection);
2460 struct smbd_smb2_request *req = NULL;
2462 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2463 TALLOC_FREE(subreq);
2464 if (!NT_STATUS_IS_OK(status)) {
2465 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2466 nt_errstr(status)));
2467 smbd_server_connection_terminate(sconn, nt_errstr(status));
2471 if (req->in.nbt_hdr[0] != 0x00) {
2472 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2473 req->in.nbt_hdr[0]));
2478 req->current_idx = 1;
2480 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2481 req->current_idx, req->in.vector_count));
2483 status = smbd_smb2_request_validate(req);
2484 if (!NT_STATUS_IS_OK(status)) {
2485 smbd_server_connection_terminate(sconn, nt_errstr(status));
2489 status = smbd_smb2_request_setup_out(req);
2490 if (!NT_STATUS_IS_OK(status)) {
2491 smbd_server_connection_terminate(sconn, nt_errstr(status));
2495 status = smbd_smb2_request_dispatch(req);
2496 if (!NT_STATUS_IS_OK(status)) {
2497 smbd_server_connection_terminate(sconn, nt_errstr(status));
2502 status = smbd_smb2_request_next_incoming(sconn);
2503 if (!NT_STATUS_IS_OK(status)) {
2504 smbd_server_connection_terminate(sconn, nt_errstr(status));
2508 sconn->num_requests++;
2510 /* The timeout_processing function isn't run nearly
2511 often enough to implement 'max log size' without
2512 overrunning the size of the file by many megabytes.
2513 This is especially true if we are running at debug
2514 level 10. Checking every 50 SMB2s is a nice
2515 tradeoff of performance vs log file size overrun. */
2517 if ((sconn->num_requests % 50) == 0 &&
2518 need_to_check_log_size()) {
2519 change_to_root_user();