2 Unix SMB/CIFS implementation.
5 Copyright (C) Stefan Metzmacher 2009
6 Copyright (C) Jeremy Allison 2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../libcli/smb/smb_common.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "../lib/util/tevent_ntstatus.h"
28 #include "smbprofile.h"
29 #include "../lib/util/bitmap.h"
31 #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9)
33 static const char *smb2_names[] = {
55 const char *smb2_opcode_name(uint16_t opcode)
58 return "Bad SMB2 opcode";
60 return smb2_names[opcode];
63 static void print_req_vectors(struct smbd_smb2_request *req)
67 for (i = 0; i < req->in.vector_count; i++) {
68 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
70 (unsigned int)req->in.vector[i].iov_len);
72 for (i = 0; i < req->out.vector_count; i++) {
73 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
75 (unsigned int)req->out.vector[i].iov_len);
79 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
81 if (size < (4 + SMB2_HDR_BODY)) {
85 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
92 static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
97 TALLOC_FREE(sconn->smb1.fde);
99 sconn->smb2.event_ctx = server_event_context();
101 sconn->smb2.recv_queue = tevent_queue_create(sconn, "smb2 recv queue");
102 if (sconn->smb2.recv_queue == NULL) {
103 return NT_STATUS_NO_MEMORY;
106 sconn->smb2.send_queue = tevent_queue_create(sconn, "smb2 send queue");
107 if (sconn->smb2.send_queue == NULL) {
108 return NT_STATUS_NO_MEMORY;
111 sconn->smb2.sessions.idtree = idr_init(sconn);
112 if (sconn->smb2.sessions.idtree == NULL) {
113 return NT_STATUS_NO_MEMORY;
115 sconn->smb2.sessions.limit = 0x0000FFFE;
116 sconn->smb2.sessions.list = NULL;
117 sconn->smb2.seqnum_low = 0;
118 sconn->smb2.credits_granted = 0;
119 sconn->smb2.max_credits = lp_smb2_max_credits();
120 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
121 DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR*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 talloc_set_destructor(parent, smbd_smb2_request_parent_destructor);
211 talloc_set_destructor(req, smbd_smb2_request_destructor);
216 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
217 const uint8_t *inbuf, size_t size,
218 struct smbd_smb2_request **_req)
220 struct smbd_smb2_request *req;
221 uint32_t protocol_version;
222 const uint8_t *inhdr = NULL;
225 uint32_t next_command_ofs;
227 if (size < (4 + SMB2_HDR_BODY + 2)) {
228 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
229 return NT_STATUS_INVALID_PARAMETER;
234 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
235 if (protocol_version != SMB2_MAGIC) {
236 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
238 return NT_STATUS_INVALID_PARAMETER;
241 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
242 if (cmd != SMB2_OP_NEGPROT) {
243 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
245 return NT_STATUS_INVALID_PARAMETER;
248 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
249 if (next_command_ofs != 0) {
250 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
252 return NT_STATUS_INVALID_PARAMETER;
255 req = smbd_smb2_request_allocate(sconn);
257 return NT_STATUS_NO_MEMORY;
261 talloc_steal(req, inbuf);
263 req->in.vector = talloc_array(req, struct iovec, 4);
264 if (req->in.vector == NULL) {
266 return NT_STATUS_NO_MEMORY;
268 req->in.vector_count = 4;
270 memcpy(req->in.nbt_hdr, inbuf, 4);
273 req->in.vector[0].iov_base = discard_const_p(void, req->in.nbt_hdr);
274 req->in.vector[0].iov_len = 4;
275 ofs += req->in.vector[0].iov_len;
277 req->in.vector[1].iov_base = discard_const_p(void, (inbuf + ofs));
278 req->in.vector[1].iov_len = SMB2_HDR_BODY;
279 ofs += req->in.vector[1].iov_len;
281 req->in.vector[2].iov_base = discard_const_p(void, (inbuf + ofs));
282 req->in.vector[2].iov_len = SVAL(inbuf, ofs) & 0xFFFE;
283 ofs += req->in.vector[2].iov_len;
286 return NT_STATUS_INVALID_PARAMETER;
289 req->in.vector[3].iov_base = discard_const_p(void, (inbuf + ofs));
290 req->in.vector[3].iov_len = size - ofs;
291 ofs += req->in.vector[3].iov_len;
293 req->current_idx = 1;
299 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
300 const uint8_t *inhdr)
302 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
303 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
304 uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
305 unsigned int bitmap_offset;
307 if (opcode == SMB2_OP_CANCEL) {
308 /* SMB2_CANCEL requests by definition resend messageids. */
312 if (message_id < sconn->smb2.seqnum_low ||
313 message_id > (sconn->smb2.seqnum_low +
314 (sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR))) {
315 DEBUG(0,("smb2_validate_message_id: bad message_id "
316 "%llu (low = %llu, max = %lu)\n",
317 (unsigned long long)message_id,
318 (unsigned long long)sconn->smb2.seqnum_low,
319 (unsigned long)sconn->smb2.max_credits ));
323 /* client just used a credit. */
324 SMB_ASSERT(sconn->smb2.credits_granted > 0);
325 sconn->smb2.credits_granted -= 1;
327 /* Mark the message_id as seen in the bitmap. */
328 bitmap_offset = (unsigned int)(message_id %
329 (uint64_t)(sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR));
330 if (bitmap_query(credits_bm, bitmap_offset)) {
331 DEBUG(0,("smb2_validate_message_id: duplicate message_id "
332 "%llu (bm offset %u)\n",
333 (unsigned long long)message_id,
337 bitmap_set(credits_bm, bitmap_offset);
339 if (message_id == sconn->smb2.seqnum_low + 1) {
340 /* Move the window forward by all the message_id's
342 while (bitmap_query(credits_bm, bitmap_offset)) {
343 DEBUG(10,("smb2_validate_message_id: clearing "
344 "id %llu (position %u) from bitmap\n",
345 (unsigned long long)(sconn->smb2.seqnum_low + 1),
347 bitmap_clear(credits_bm, bitmap_offset);
348 sconn->smb2.seqnum_low += 1;
349 bitmap_offset = (bitmap_offset + 1) %
350 (sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR);
357 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
361 bool compound_related = false;
363 count = req->in.vector_count;
366 /* It's not a SMB2 request */
367 return NT_STATUS_INVALID_PARAMETER;
370 for (idx=1; idx < count; idx += 3) {
371 const uint8_t *inhdr = NULL;
374 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
375 return NT_STATUS_INVALID_PARAMETER;
378 if (req->in.vector[idx+1].iov_len < 2) {
379 return NT_STATUS_INVALID_PARAMETER;
382 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
384 /* Check the SMB2 header */
385 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
386 return NT_STATUS_INVALID_PARAMETER;
389 if (!smb2_validate_message_id(req->sconn, inhdr)) {
390 return NT_STATUS_INVALID_PARAMETER;
393 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
396 * the 1st request should never have the
397 * SMB2_HDR_FLAG_CHAINED flag set
399 if (flags & SMB2_HDR_FLAG_CHAINED) {
400 req->next_status = NT_STATUS_INVALID_PARAMETER;
403 } else if (idx == 4) {
405 * the 2nd request triggers related vs. unrelated
406 * compounded requests
408 if (flags & SMB2_HDR_FLAG_CHAINED) {
409 compound_related = true;
411 } else if (idx > 4) {
414 * It seems the this tests are wrong
415 * see the SMB2-COMPOUND test
419 * all other requests should match the 2nd one
421 if (flags & SMB2_HDR_FLAG_CHAINED) {
422 if (!compound_related) {
424 NT_STATUS_INVALID_PARAMETER;
428 if (compound_related) {
430 NT_STATUS_INVALID_PARAMETER;
441 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
442 const struct iovec *in_vector,
443 struct iovec *out_vector)
445 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
446 uint16_t credits_requested = 0;
447 uint16_t credits_granted = 0;
449 if (in_vector != NULL) {
450 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
451 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
454 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
456 /* Remember what we gave out. */
457 credits_granted = MIN(credits_requested, (sconn->smb2.max_credits -
458 sconn->smb2.credits_granted));
460 if (credits_granted == 0 && sconn->smb2.credits_granted == 0) {
461 /* First negprot packet, or ensure the client credits can
462 never drop to zero. */
466 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
467 sconn->smb2.credits_granted += credits_granted;
469 DEBUG(10,("smb2_set_operation_credit: requested %u, "
470 "granted %u, total granted %u\n",
471 (unsigned int)credits_requested,
472 (unsigned int)credits_granted,
473 (unsigned int)sconn->smb2.credits_granted ));
476 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
477 struct smbd_smb2_request *outreq)
481 count = outreq->out.vector_count;
483 for (idx=1; idx < count; idx += 3) {
484 smb2_set_operation_credit(outreq->sconn,
485 &inreq->in.vector[idx],
486 &outreq->out.vector[idx]);
490 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
492 struct iovec *vector;
496 count = req->in.vector_count;
497 vector = talloc_zero_array(req, struct iovec, count);
498 if (vector == NULL) {
499 return NT_STATUS_NO_MEMORY;
502 vector[0].iov_base = req->out.nbt_hdr;
503 vector[0].iov_len = 4;
504 SIVAL(req->out.nbt_hdr, 0, 0);
506 for (idx=1; idx < count; idx += 3) {
507 const uint8_t *inhdr = NULL;
509 uint8_t *outhdr = NULL;
510 uint8_t *outbody = NULL;
511 uint32_t next_command_ofs = 0;
512 struct iovec *current = &vector[idx];
514 if ((idx + 3) < count) {
515 /* we have a next command -
516 * setup for the error case. */
517 next_command_ofs = SMB2_HDR_BODY + 9;
520 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
521 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
523 outhdr = talloc_zero_array(vector, uint8_t,
525 if (outhdr == NULL) {
526 return NT_STATUS_NO_MEMORY;
529 outbody = outhdr + SMB2_HDR_BODY;
531 current[0].iov_base = (void *)outhdr;
532 current[0].iov_len = SMB2_HDR_BODY;
534 current[1].iov_base = (void *)outbody;
535 current[1].iov_len = 8;
537 current[2].iov_base = NULL;
538 current[2].iov_len = 0;
540 /* setup the SMB2 header */
541 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
542 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
543 SSVAL(outhdr, SMB2_HDR_EPOCH, 0);
544 SIVAL(outhdr, SMB2_HDR_STATUS,
545 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
546 SSVAL(outhdr, SMB2_HDR_OPCODE,
547 SVAL(inhdr, SMB2_HDR_OPCODE));
548 SIVAL(outhdr, SMB2_HDR_FLAGS,
549 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
550 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
551 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
552 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
553 SIVAL(outhdr, SMB2_HDR_PID,
554 IVAL(inhdr, SMB2_HDR_PID));
555 SIVAL(outhdr, SMB2_HDR_TID,
556 IVAL(inhdr, SMB2_HDR_TID));
557 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
558 BVAL(inhdr, SMB2_HDR_SESSION_ID));
559 memset(outhdr + SMB2_HDR_SIGNATURE, 0, 16);
561 /* setup error body header */
562 SSVAL(outbody, 0x00, 0x08 + 1);
563 SSVAL(outbody, 0x02, 0);
564 SIVAL(outbody, 0x04, 0);
567 req->out.vector = vector;
568 req->out.vector_count = count;
570 /* setup the length of the NBT packet */
571 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
573 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
578 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
580 const char *location)
582 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
584 exit_server_cleanly(reason);
587 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
588 struct iovec *outvec,
589 const struct iovec *srcvec)
591 /* vec[0] is always boilerplate and must
592 * be allocated with size OUTVEC_ALLOC_SIZE. */
594 outvec[0].iov_base = talloc_memdup(ctx,
597 if (!outvec[0].iov_base) {
600 outvec[0].iov_len = SMB2_HDR_BODY;
603 * If this is a "standard" vec[1] of length 8,
604 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
605 * then duplicate this. Else use talloc_memdup().
608 if (srcvec[1].iov_len == 8 &&
609 srcvec[1].iov_base ==
610 ((uint8_t *)srcvec[0].iov_base) +
612 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
614 outvec[1].iov_len = 8;
616 outvec[1].iov_base = talloc_memdup(ctx,
619 if (!outvec[1].iov_base) {
622 outvec[1].iov_len = srcvec[1].iov_len;
626 * If this is a "standard" vec[2] of length 1,
627 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
628 * then duplicate this. Else use talloc_memdup().
631 if (srcvec[2].iov_base &&
633 if (srcvec[2].iov_base ==
634 ((uint8_t *)srcvec[0].iov_base) +
635 (OUTVEC_ALLOC_SIZE - 1) &&
636 srcvec[2].iov_len == 1) {
637 /* Common SMB2 error packet case. */
638 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
639 (OUTVEC_ALLOC_SIZE - 1);
641 outvec[2].iov_base = talloc_memdup(ctx,
644 if (!outvec[2].iov_base) {
648 outvec[2].iov_len = srcvec[2].iov_len;
650 outvec[2].iov_base = NULL;
651 outvec[2].iov_len = 0;
656 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
658 struct smbd_smb2_request *newreq = NULL;
659 struct iovec *outvec = NULL;
660 int count = req->out.vector_count;
663 newreq = smbd_smb2_request_allocate(req->sconn);
668 newreq->sconn = req->sconn;
669 newreq->session = req->session;
670 newreq->do_signing = req->do_signing;
671 newreq->current_idx = req->current_idx;
672 newreq->async = false;
673 newreq->cancelled = false;
674 /* Note we are leaving:
678 uninitialized as NULL here as
679 they're not used in the interim
680 response code. JRA. */
682 outvec = talloc_zero_array(newreq, struct iovec, count);
687 newreq->out.vector = outvec;
688 newreq->out.vector_count = count;
690 /* Setup the outvec's identically to req. */
691 outvec[0].iov_base = newreq->out.nbt_hdr;
692 outvec[0].iov_len = 4;
693 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
695 /* Setup the vectors identically to the ones in req. */
696 for (i = 1; i < count; i += 3) {
697 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
708 smb2_setup_nbt_length(newreq->out.vector,
709 newreq->out.vector_count);
714 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
716 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
719 uint8_t *outhdr = NULL;
720 struct smbd_smb2_request *nreq = NULL;
722 /* Create a new smb2 request we'll use
723 for the interim return. */
724 nreq = dup_smb2_req(req);
726 return NT_STATUS_NO_MEMORY;
729 /* Lose the last 3 out vectors. They're the
730 ones we'll be using for the async reply. */
731 nreq->out.vector_count -= 3;
733 smb2_setup_nbt_length(nreq->out.vector,
734 nreq->out.vector_count);
736 /* Step back to the previous reply. */
737 i = nreq->current_idx - 3;
738 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
739 /* And end the chain. */
740 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
742 /* Calculate outgoing credits */
743 smb2_calculate_credits(req, nreq);
745 /* Re-sign if needed. */
746 if (nreq->do_signing) {
748 status = smb2_signing_sign_pdu(nreq->session->session_key,
749 &nreq->out.vector[i], 3);
750 if (!NT_STATUS_IS_OK(status)) {
754 if (DEBUGLEVEL >= 10) {
755 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
756 (unsigned int)nreq->current_idx );
757 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
758 (unsigned int)nreq->out.vector_count );
759 print_req_vectors(nreq);
761 nreq->subreq = tstream_writev_queue_send(nreq,
762 nreq->sconn->smb2.event_ctx,
763 nreq->sconn->smb2.stream,
764 nreq->sconn->smb2.send_queue,
766 nreq->out.vector_count);
768 if (nreq->subreq == NULL) {
769 return NT_STATUS_NO_MEMORY;
772 tevent_req_set_callback(nreq->subreq,
773 smbd_smb2_request_writev_done,
779 struct smbd_smb2_request_pending_state {
780 struct smbd_server_connection *sconn;
781 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
782 struct iovec vector[3];
785 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
787 struct smbd_smb2_request_pending_state *state =
788 tevent_req_callback_data(subreq,
789 struct smbd_smb2_request_pending_state);
790 struct smbd_server_connection *sconn = state->sconn;
794 ret = tstream_writev_queue_recv(subreq, &sys_errno);
797 NTSTATUS status = map_nt_error_from_unix(sys_errno);
798 smbd_server_connection_terminate(sconn, nt_errstr(status));
805 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
806 struct tevent_req *subreq)
809 struct smbd_smb2_request_pending_state *state = NULL;
810 int i = req->current_idx;
811 uint8_t *reqhdr = NULL;
813 uint8_t *body = NULL;
815 uint64_t message_id = 0;
816 uint64_t async_id = 0;
817 struct iovec *outvec = NULL;
819 if (!tevent_req_is_in_progress(subreq)) {
823 req->subreq = subreq;
827 /* We're already async. */
831 if (req->in.vector_count > i + 3) {
833 * We're trying to go async in a compound
834 * request chain. This is not allowed.
835 * Cancel the outstanding request.
837 tevent_req_cancel(req->subreq);
838 return smbd_smb2_request_error(req,
839 NT_STATUS_INSUFFICIENT_RESOURCES);
842 if (DEBUGLEVEL >= 10) {
843 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
844 (unsigned int)req->current_idx );
845 print_req_vectors(req);
848 if (req->out.vector_count > 4) {
849 /* This is a compound reply. We
850 * must do an interim response
851 * followed by the async response
854 status = smb2_send_async_interim_response(req);
855 if (!NT_STATUS_IS_OK(status)) {
860 /* Don't return an intermediate packet on a pipe read/write. */
861 if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
865 reqhdr = (uint8_t *)req->out.vector[i].iov_base;
866 flags = (IVAL(reqhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
867 message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
868 async_id = message_id; /* keep it simple for now... */
871 * What we send is identical to a smbd_smb2_request_error
872 * packet with an error status of STATUS_PENDING. Make use
873 * of this fact sometime when refactoring. JRA.
876 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
878 return NT_STATUS_NO_MEMORY;
880 state->sconn = req->sconn;
882 state->vector[0].iov_base = (void *)state->buf;
883 state->vector[0].iov_len = 4;
885 state->vector[1].iov_base = state->buf + 4;
886 state->vector[1].iov_len = SMB2_HDR_BODY;
888 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
889 state->vector[2].iov_len = 9;
891 smb2_setup_nbt_length(state->vector, 3);
893 hdr = (uint8_t *)state->vector[1].iov_base;
894 body = (uint8_t *)state->vector[2].iov_base;
896 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
897 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
898 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
899 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
900 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(reqhdr, SMB2_HDR_OPCODE));
902 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
903 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
904 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
905 SBVAL(hdr, SMB2_HDR_PID, async_id);
906 SBVAL(hdr, SMB2_HDR_SESSION_ID,
907 BVAL(reqhdr, SMB2_HDR_SESSION_ID));
908 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
910 SSVAL(body, 0x00, 0x08 + 1);
912 SCVAL(body, 0x02, 0);
913 SCVAL(body, 0x03, 0);
914 SIVAL(body, 0x04, 0);
915 /* Match W2K8R2... */
916 SCVAL(body, 0x08, 0x21);
918 /* Ensure we correctly go through crediting. Grant
919 the credits now, and zero credits on the final
921 smb2_set_operation_credit(req->sconn,
925 if (req->do_signing) {
926 status = smb2_signing_sign_pdu(req->session->session_key,
927 &state->vector[1], 2);
928 if (!NT_STATUS_IS_OK(status)) {
933 subreq = tstream_writev_queue_send(state,
934 req->sconn->smb2.event_ctx,
935 req->sconn->smb2.stream,
936 req->sconn->smb2.send_queue,
940 if (subreq == NULL) {
941 return NT_STATUS_NO_MEMORY;
944 tevent_req_set_callback(subreq,
945 smbd_smb2_request_pending_writev_done,
948 /* Note we're going async with this request. */
952 * Now manipulate req so that the outstanding async request
953 * is the only one left in the struct smbd_smb2_request.
956 if (req->current_idx == 1) {
957 /* There was only one. */
961 /* Re-arrange the in.vectors. */
962 req->in.vector[1] = req->in.vector[i];
963 req->in.vector[2] = req->in.vector[i+1];
964 req->in.vector[3] = req->in.vector[i+2];
965 req->in.vector_count = 4;
966 /* Reset the new in size. */
967 smb2_setup_nbt_length(req->in.vector, 4);
969 /* Now recreate the out.vectors. */
970 outvec = talloc_zero_array(req, struct iovec, 4);
972 return NT_STATUS_NO_MEMORY;
975 /* 0 is always boilerplate and must
976 * be of size 4 for the length field. */
978 outvec[0].iov_base = req->out.nbt_hdr;
979 outvec[0].iov_len = 4;
980 SIVAL(req->out.nbt_hdr, 0, 0);
982 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
983 return NT_STATUS_NO_MEMORY;
986 TALLOC_FREE(req->out.vector);
988 req->out.vector = outvec;
990 req->current_idx = 1;
991 req->out.vector_count = 4;
995 smb2_setup_nbt_length(req->out.vector,
996 req->out.vector_count);
998 /* Ensure our final reply matches the interim one. */
999 reqhdr = (uint8_t *)req->out.vector[1].iov_base;
1000 SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1001 SBVAL(reqhdr, SMB2_HDR_PID, async_id);
1004 const uint8_t *inhdr =
1005 (const uint8_t *)req->in.vector[1].iov_base;
1006 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1008 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1009 (unsigned long long)async_id ));
1011 return NT_STATUS_OK;
1014 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1016 struct smbd_server_connection *sconn = req->sconn;
1017 struct smbd_smb2_request *cur;
1018 const uint8_t *inhdr;
1019 int i = req->current_idx;
1021 uint64_t search_message_id;
1022 uint64_t search_async_id;
1025 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1027 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1028 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1029 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1032 * we don't need the request anymore
1033 * cancel requests never have a response
1035 DLIST_REMOVE(req->sconn->smb2.requests, req);
1038 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1039 const uint8_t *outhdr;
1040 uint64_t message_id;
1043 i = cur->current_idx;
1045 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1047 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1048 async_id = BVAL(outhdr, SMB2_HDR_PID);
1050 if (flags & SMB2_HDR_FLAG_ASYNC) {
1051 if (search_async_id == async_id) {
1052 found_id = async_id;
1056 if (search_message_id == message_id) {
1057 found_id = message_id;
1063 if (cur && cur->subreq) {
1064 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1065 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1066 "cancel opcode[%s] mid %llu\n",
1067 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1068 (unsigned long long)found_id ));
1069 tevent_req_cancel(cur->subreq);
1072 return NT_STATUS_OK;
1075 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1077 const uint8_t *inhdr;
1078 int i = req->current_idx;
1083 NTSTATUS session_status;
1084 uint32_t allowed_flags;
1085 NTSTATUS return_value;
1087 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1089 /* TODO: verify more things */
1091 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1092 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1093 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1094 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1095 smb2_opcode_name(opcode),
1096 (unsigned long long)mid));
1098 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1099 SMB2_HDR_FLAG_SIGNED |
1101 if (opcode == SMB2_OP_CANCEL) {
1102 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1104 if ((flags & ~allowed_flags) != 0) {
1105 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1109 * Check if the client provided a valid session id,
1110 * if so smbd_smb2_request_check_session() calls
1111 * set_current_user_info().
1113 * As some command don't require a valid session id
1114 * we defer the check of the session_status
1116 session_status = smbd_smb2_request_check_session(req);
1118 req->do_signing = false;
1119 if (flags & SMB2_HDR_FLAG_SIGNED) {
1120 if (!NT_STATUS_IS_OK(session_status)) {
1121 return smbd_smb2_request_error(req, session_status);
1124 req->do_signing = true;
1125 status = smb2_signing_check_pdu(req->session->session_key,
1126 &req->in.vector[i], 3);
1127 if (!NT_STATUS_IS_OK(status)) {
1128 return smbd_smb2_request_error(req, status);
1130 } else if (req->session && req->session->do_signing) {
1131 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1134 if (flags & SMB2_HDR_FLAG_CHAINED) {
1136 * This check is mostly for giving the correct error code
1137 * for compounded requests.
1139 * TODO: we may need to move this after the session
1142 if (!NT_STATUS_IS_OK(req->next_status)) {
1143 return smbd_smb2_request_error(req, req->next_status);
1146 req->compat_chain_fsp = NULL;
1150 case SMB2_OP_NEGPROT:
1151 /* This call needs to be run as root */
1152 change_to_root_user();
1155 START_PROFILE(smb2_negprot);
1156 return_value = smbd_smb2_request_process_negprot(req);
1157 END_PROFILE(smb2_negprot);
1161 case SMB2_OP_SESSSETUP:
1162 /* This call needs to be run as root */
1163 change_to_root_user();
1166 START_PROFILE(smb2_sesssetup);
1167 return_value = smbd_smb2_request_process_sesssetup(req);
1168 END_PROFILE(smb2_sesssetup);
1172 case SMB2_OP_LOGOFF:
1173 if (!NT_STATUS_IS_OK(session_status)) {
1174 return_value = smbd_smb2_request_error(req, session_status);
1178 /* This call needs to be run as root */
1179 change_to_root_user();
1182 START_PROFILE(smb2_logoff);
1183 return_value = smbd_smb2_request_process_logoff(req);
1184 END_PROFILE(smb2_logoff);
1189 if (!NT_STATUS_IS_OK(session_status)) {
1190 return_value = smbd_smb2_request_error(req, session_status);
1195 * This call needs to be run as root.
1197 * smbd_smb2_request_process_tcon()
1198 * calls make_connection_snum(), which will call
1199 * change_to_user(), when needed.
1201 change_to_root_user();
1204 START_PROFILE(smb2_tcon);
1205 return_value = smbd_smb2_request_process_tcon(req);
1206 END_PROFILE(smb2_tcon);
1211 if (!NT_STATUS_IS_OK(session_status)) {
1212 return_value = smbd_smb2_request_error(req, session_status);
1216 * This call needs to be run as user.
1218 * smbd_smb2_request_check_tcon()
1219 * calls change_to_user() on success.
1221 status = smbd_smb2_request_check_tcon(req);
1222 if (!NT_STATUS_IS_OK(status)) {
1223 return_value = smbd_smb2_request_error(req, status);
1226 /* This call needs to be run as root */
1227 change_to_root_user();
1231 START_PROFILE(smb2_tdis);
1232 return_value = smbd_smb2_request_process_tdis(req);
1233 END_PROFILE(smb2_tdis);
1237 case SMB2_OP_CREATE:
1238 if (!NT_STATUS_IS_OK(session_status)) {
1239 return_value = smbd_smb2_request_error(req, session_status);
1243 * This call needs to be run as user.
1245 * smbd_smb2_request_check_tcon()
1246 * calls change_to_user() on success.
1248 status = smbd_smb2_request_check_tcon(req);
1249 if (!NT_STATUS_IS_OK(status)) {
1250 return_value = smbd_smb2_request_error(req, status);
1255 START_PROFILE(smb2_create);
1256 return_value = smbd_smb2_request_process_create(req);
1257 END_PROFILE(smb2_create);
1262 if (!NT_STATUS_IS_OK(session_status)) {
1263 return_value = smbd_smb2_request_error(req, session_status);
1267 * This call needs to be run as user.
1269 * smbd_smb2_request_check_tcon()
1270 * calls change_to_user() on success.
1272 status = smbd_smb2_request_check_tcon(req);
1273 if (!NT_STATUS_IS_OK(status)) {
1274 return_value = smbd_smb2_request_error(req, status);
1279 START_PROFILE(smb2_close);
1280 return_value = smbd_smb2_request_process_close(req);
1281 END_PROFILE(smb2_close);
1286 if (!NT_STATUS_IS_OK(session_status)) {
1287 return_value = smbd_smb2_request_error(req, session_status);
1291 * This call needs to be run as user.
1293 * smbd_smb2_request_check_tcon()
1294 * calls change_to_user() on success.
1296 status = smbd_smb2_request_check_tcon(req);
1297 if (!NT_STATUS_IS_OK(status)) {
1298 return_value = smbd_smb2_request_error(req, status);
1303 START_PROFILE(smb2_flush);
1304 return_value = smbd_smb2_request_process_flush(req);
1305 END_PROFILE(smb2_flush);
1310 if (!NT_STATUS_IS_OK(session_status)) {
1311 return_value = smbd_smb2_request_error(req, session_status);
1315 * This call needs to be run as user.
1317 * smbd_smb2_request_check_tcon()
1318 * calls change_to_user() on success.
1320 status = smbd_smb2_request_check_tcon(req);
1321 if (!NT_STATUS_IS_OK(status)) {
1322 return_value = smbd_smb2_request_error(req, status);
1327 START_PROFILE(smb2_read);
1328 return_value = smbd_smb2_request_process_read(req);
1329 END_PROFILE(smb2_read);
1334 if (!NT_STATUS_IS_OK(session_status)) {
1335 return_value = smbd_smb2_request_error(req, session_status);
1339 * This call needs to be run as user.
1341 * smbd_smb2_request_check_tcon()
1342 * calls change_to_user() on success.
1344 status = smbd_smb2_request_check_tcon(req);
1345 if (!NT_STATUS_IS_OK(status)) {
1346 return_value = smbd_smb2_request_error(req, status);
1351 START_PROFILE(smb2_write);
1352 return_value = smbd_smb2_request_process_write(req);
1353 END_PROFILE(smb2_write);
1358 if (!NT_STATUS_IS_OK(session_status)) {
1359 /* Too ugly to live ? JRA. */
1360 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1361 session_status = NT_STATUS_FILE_CLOSED;
1363 return_value = smbd_smb2_request_error(req, session_status);
1367 * This call needs to be run as user.
1369 * smbd_smb2_request_check_tcon()
1370 * calls change_to_user() on success.
1372 status = smbd_smb2_request_check_tcon(req);
1373 if (!NT_STATUS_IS_OK(status)) {
1374 /* Too ugly to live ? JRA. */
1375 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1376 status = NT_STATUS_FILE_CLOSED;
1378 return_value = smbd_smb2_request_error(req, status);
1383 START_PROFILE(smb2_lock);
1384 return_value = smbd_smb2_request_process_lock(req);
1385 END_PROFILE(smb2_lock);
1390 if (!NT_STATUS_IS_OK(session_status)) {
1391 return_value = smbd_smb2_request_error(req, session_status);
1395 * This call needs to be run as user.
1397 * smbd_smb2_request_check_tcon()
1398 * calls change_to_user() on success.
1400 status = smbd_smb2_request_check_tcon(req);
1401 if (!NT_STATUS_IS_OK(status)) {
1402 return_value = smbd_smb2_request_error(req, status);
1407 START_PROFILE(smb2_ioctl);
1408 return_value = smbd_smb2_request_process_ioctl(req);
1409 END_PROFILE(smb2_ioctl);
1413 case SMB2_OP_CANCEL:
1415 * This call needs to be run as root
1417 * That is what we also do in the SMB1 case.
1419 change_to_root_user();
1422 START_PROFILE(smb2_cancel);
1423 return_value = smbd_smb2_request_process_cancel(req);
1424 END_PROFILE(smb2_cancel);
1428 case SMB2_OP_KEEPALIVE:
1429 /* This call needs to be run as root */
1430 change_to_root_user();
1433 START_PROFILE(smb2_keepalive);
1434 return_value = smbd_smb2_request_process_keepalive(req);
1435 END_PROFILE(smb2_keepalive);
1440 if (!NT_STATUS_IS_OK(session_status)) {
1441 return_value = smbd_smb2_request_error(req, session_status);
1445 * This call needs to be run as user.
1447 * smbd_smb2_request_check_tcon()
1448 * calls change_to_user() on success.
1450 status = smbd_smb2_request_check_tcon(req);
1451 if (!NT_STATUS_IS_OK(status)) {
1452 return_value = smbd_smb2_request_error(req, status);
1457 START_PROFILE(smb2_find);
1458 return_value = smbd_smb2_request_process_find(req);
1459 END_PROFILE(smb2_find);
1463 case SMB2_OP_NOTIFY:
1464 if (!NT_STATUS_IS_OK(session_status)) {
1465 return_value = smbd_smb2_request_error(req, session_status);
1469 * This call needs to be run as user.
1471 * smbd_smb2_request_check_tcon()
1472 * calls change_to_user() on success.
1474 status = smbd_smb2_request_check_tcon(req);
1475 if (!NT_STATUS_IS_OK(status)) {
1476 return_value = smbd_smb2_request_error(req, status);
1481 START_PROFILE(smb2_notify);
1482 return_value = smbd_smb2_request_process_notify(req);
1483 END_PROFILE(smb2_notify);
1487 case SMB2_OP_GETINFO:
1488 if (!NT_STATUS_IS_OK(session_status)) {
1489 return_value = smbd_smb2_request_error(req, session_status);
1493 * This call needs to be run as user.
1495 * smbd_smb2_request_check_tcon()
1496 * calls change_to_user() on success.
1498 status = smbd_smb2_request_check_tcon(req);
1499 if (!NT_STATUS_IS_OK(status)) {
1500 return_value = smbd_smb2_request_error(req, status);
1505 START_PROFILE(smb2_getinfo);
1506 return_value = smbd_smb2_request_process_getinfo(req);
1507 END_PROFILE(smb2_getinfo);
1511 case SMB2_OP_SETINFO:
1512 if (!NT_STATUS_IS_OK(session_status)) {
1513 return_value = smbd_smb2_request_error(req, session_status);
1517 * This call needs to be run as user.
1519 * smbd_smb2_request_check_tcon()
1520 * calls change_to_user() on success.
1522 status = smbd_smb2_request_check_tcon(req);
1523 if (!NT_STATUS_IS_OK(status)) {
1524 return_value = smbd_smb2_request_error(req, status);
1529 START_PROFILE(smb2_setinfo);
1530 return_value = smbd_smb2_request_process_setinfo(req);
1531 END_PROFILE(smb2_setinfo);
1536 if (!NT_STATUS_IS_OK(session_status)) {
1537 return_value = smbd_smb2_request_error(req, session_status);
1541 * This call needs to be run as user.
1543 * smbd_smb2_request_check_tcon()
1544 * calls change_to_user() on success.
1546 status = smbd_smb2_request_check_tcon(req);
1547 if (!NT_STATUS_IS_OK(status)) {
1548 return_value = smbd_smb2_request_error(req, status);
1553 START_PROFILE(smb2_break);
1554 return_value = smbd_smb2_request_process_break(req);
1555 END_PROFILE(smb2_break);
1560 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1563 return return_value;
1566 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1568 struct tevent_req *subreq;
1569 int i = req->current_idx;
1573 req->current_idx += 3;
1575 if (req->current_idx < req->out.vector_count) {
1577 * We must process the remaining compound
1578 * SMB2 requests before any new incoming SMB2
1579 * requests. This is because incoming SMB2
1580 * requests may include a cancel for a
1581 * compound request we haven't processed
1584 struct tevent_immediate *im = tevent_create_immediate(req);
1586 return NT_STATUS_NO_MEMORY;
1588 tevent_schedule_immediate(im,
1589 req->sconn->smb2.event_ctx,
1590 smbd_smb2_request_dispatch_immediate,
1592 return NT_STATUS_OK;
1595 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1597 /* Set credit for this operation (zero credits if this
1598 is a final reply for an async operation). */
1599 smb2_set_operation_credit(req->sconn,
1600 req->async ? NULL : &req->in.vector[i],
1601 &req->out.vector[i]);
1603 if (req->do_signing) {
1605 status = smb2_signing_sign_pdu(req->session->session_key,
1606 &req->out.vector[i], 3);
1607 if (!NT_STATUS_IS_OK(status)) {
1612 if (DEBUGLEVEL >= 10) {
1613 dbgtext("smbd_smb2_request_reply: sending...\n");
1614 print_req_vectors(req);
1617 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1618 if (req->out.vector_count == 4 &&
1619 req->out.vector[3].iov_base == NULL &&
1620 req->out.vector[3].iov_len != 0) {
1621 /* Dynamic part is NULL. Chop it off,
1622 We're going to send it via sendfile. */
1623 req->out.vector_count -= 1;
1626 subreq = tstream_writev_queue_send(req,
1627 req->sconn->smb2.event_ctx,
1628 req->sconn->smb2.stream,
1629 req->sconn->smb2.send_queue,
1631 req->out.vector_count);
1632 if (subreq == NULL) {
1633 return NT_STATUS_NO_MEMORY;
1635 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1637 * We're done with this request -
1638 * move it off the "being processed" queue.
1640 DLIST_REMOVE(req->sconn->smb2.requests, req);
1642 return NT_STATUS_OK;
1645 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1646 struct tevent_immediate *im,
1649 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1650 struct smbd_smb2_request);
1651 struct smbd_server_connection *sconn = req->sconn;
1656 if (DEBUGLEVEL >= 10) {
1657 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1658 req->current_idx, req->in.vector_count));
1659 print_req_vectors(req);
1662 status = smbd_smb2_request_dispatch(req);
1663 if (!NT_STATUS_IS_OK(status)) {
1664 smbd_server_connection_terminate(sconn, nt_errstr(status));
1669 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1671 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1672 struct smbd_smb2_request);
1673 struct smbd_server_connection *sconn = req->sconn;
1677 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1678 TALLOC_FREE(subreq);
1681 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1682 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1683 nt_errstr(status)));
1684 smbd_server_connection_terminate(sconn, nt_errstr(status));
1689 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1691 DATA_BLOB body, DATA_BLOB *dyn,
1692 const char *location)
1695 int i = req->current_idx;
1696 uint32_t next_command_ofs;
1698 DEBUG(10,("smbd_smb2_request_done_ex: "
1699 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1700 i, nt_errstr(status), (unsigned int)body.length,
1702 (unsigned int)(dyn ? dyn->length : 0),
1705 if (body.length < 2) {
1706 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1709 if ((body.length % 2) != 0) {
1710 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1713 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1715 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1716 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1718 req->out.vector[i+1].iov_base = (void *)body.data;
1719 req->out.vector[i+1].iov_len = body.length;
1722 req->out.vector[i+2].iov_base = (void *)dyn->data;
1723 req->out.vector[i+2].iov_len = dyn->length;
1725 req->out.vector[i+2].iov_base = NULL;
1726 req->out.vector[i+2].iov_len = 0;
1729 /* see if we need to recalculate the offset to the next response */
1730 if (next_command_ofs > 0) {
1731 next_command_ofs = SMB2_HDR_BODY;
1732 next_command_ofs += req->out.vector[i+1].iov_len;
1733 next_command_ofs += req->out.vector[i+2].iov_len;
1736 if ((next_command_ofs % 8) != 0) {
1737 size_t pad_size = 8 - (next_command_ofs % 8);
1738 if (req->out.vector[i+2].iov_len == 0) {
1740 * if the dyn buffer is empty
1741 * we can use it to add padding
1745 pad = talloc_zero_array(req->out.vector,
1748 return smbd_smb2_request_error(req,
1749 NT_STATUS_NO_MEMORY);
1752 req->out.vector[i+2].iov_base = (void *)pad;
1753 req->out.vector[i+2].iov_len = pad_size;
1756 * For now we copy the dynamic buffer
1757 * and add the padding to the new buffer
1764 old_size = req->out.vector[i+2].iov_len;
1765 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
1767 new_size = old_size + pad_size;
1768 new_dyn = talloc_zero_array(req->out.vector,
1770 if (new_dyn == NULL) {
1771 return smbd_smb2_request_error(req,
1772 NT_STATUS_NO_MEMORY);
1775 memcpy(new_dyn, old_dyn, old_size);
1776 memset(new_dyn + old_size, 0, pad_size);
1778 req->out.vector[i+2].iov_base = (void *)new_dyn;
1779 req->out.vector[i+2].iov_len = new_size;
1781 next_command_ofs += pad_size;
1784 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1786 return smbd_smb2_request_reply(req);
1789 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
1792 const char *location)
1795 int i = req->current_idx;
1796 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
1798 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1799 i, nt_errstr(status), info ? " +info" : "",
1802 body.data = outhdr + SMB2_HDR_BODY;
1804 SSVAL(body.data, 0, 9);
1807 SIVAL(body.data, 0x04, info->length);
1809 /* Allocated size of req->out.vector[i].iov_base
1810 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
1811 * 1 byte without having to do an alloc.
1813 info = talloc_zero_array(req->out.vector,
1817 return NT_STATUS_NO_MEMORY;
1819 info->data = ((uint8_t *)outhdr) +
1820 OUTVEC_ALLOC_SIZE - 1;
1822 SCVAL(info->data, 0, 0);
1826 * if a request fails, all other remaining
1827 * compounded requests should fail too
1829 req->next_status = NT_STATUS_INVALID_PARAMETER;
1831 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
1835 struct smbd_smb2_send_oplock_break_state {
1836 struct smbd_server_connection *sconn;
1837 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
1838 struct iovec vector;
1841 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
1843 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
1844 uint64_t file_id_persistent,
1845 uint64_t file_id_volatile,
1846 uint8_t oplock_level)
1848 struct smbd_smb2_send_oplock_break_state *state;
1849 struct tevent_req *subreq;
1853 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
1854 if (state == NULL) {
1855 return NT_STATUS_NO_MEMORY;
1857 state->sconn = sconn;
1859 state->vector.iov_base = (void *)state->buf;
1860 state->vector.iov_len = sizeof(state->buf);
1862 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
1863 hdr = state->buf + 4;
1864 body = hdr + SMB2_HDR_BODY;
1866 SIVAL(hdr, 0, SMB2_MAGIC);
1867 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1868 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1869 SIVAL(hdr, SMB2_HDR_STATUS, 0);
1870 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
1871 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
1872 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
1873 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1874 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
1875 SIVAL(hdr, SMB2_HDR_PID, 0);
1876 SIVAL(hdr, SMB2_HDR_TID, 0);
1877 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
1878 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
1880 SSVAL(body, 0x00, 0x18);
1882 SCVAL(body, 0x02, oplock_level);
1883 SCVAL(body, 0x03, 0); /* reserved */
1884 SIVAL(body, 0x04, 0); /* reserved */
1885 SBVAL(body, 0x08, file_id_persistent);
1886 SBVAL(body, 0x10, file_id_volatile);
1888 subreq = tstream_writev_queue_send(state,
1889 sconn->smb2.event_ctx,
1891 sconn->smb2.send_queue,
1893 if (subreq == NULL) {
1894 return NT_STATUS_NO_MEMORY;
1896 tevent_req_set_callback(subreq,
1897 smbd_smb2_oplock_break_writev_done,
1900 return NT_STATUS_OK;
1903 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
1905 struct smbd_smb2_send_oplock_break_state *state =
1906 tevent_req_callback_data(subreq,
1907 struct smbd_smb2_send_oplock_break_state);
1908 struct smbd_server_connection *sconn = state->sconn;
1912 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1913 TALLOC_FREE(subreq);
1915 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1916 smbd_server_connection_terminate(sconn, nt_errstr(status));
1923 struct smbd_smb2_request_read_state {
1925 bool asked_for_header;
1926 struct smbd_smb2_request *smb2_req;
1929 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1931 TALLOC_CTX *mem_ctx,
1932 struct iovec **_vector,
1934 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
1936 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
1937 struct tevent_context *ev,
1938 struct smbd_server_connection *sconn)
1940 struct tevent_req *req;
1941 struct smbd_smb2_request_read_state *state;
1942 struct tevent_req *subreq;
1944 req = tevent_req_create(mem_ctx, &state,
1945 struct smbd_smb2_request_read_state);
1950 state->asked_for_header = false;
1952 state->smb2_req = smbd_smb2_request_allocate(state);
1953 if (tevent_req_nomem(state->smb2_req, req)) {
1954 return tevent_req_post(req, ev);
1956 state->smb2_req->sconn = sconn;
1958 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
1959 sconn->smb2.recv_queue,
1960 smbd_smb2_request_next_vector,
1962 if (tevent_req_nomem(subreq, req)) {
1963 return tevent_req_post(req, ev);
1965 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
1970 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1972 TALLOC_CTX *mem_ctx,
1973 struct iovec **_vector,
1976 struct smbd_smb2_request_read_state *state =
1977 talloc_get_type_abort(private_data,
1978 struct smbd_smb2_request_read_state);
1979 struct smbd_smb2_request *req = state->smb2_req;
1980 struct iovec *vector;
1981 int idx = req->in.vector_count;
1983 uint8_t *buf = NULL;
1985 if (req->in.vector_count == 0) {
1987 * first we need to get the NBT header
1989 req->in.vector = talloc_array(req, struct iovec,
1990 req->in.vector_count + 1);
1991 if (req->in.vector == NULL) {
1994 req->in.vector_count += 1;
1996 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
1997 req->in.vector[idx].iov_len = 4;
1999 vector = talloc_array(mem_ctx, struct iovec, 1);
2000 if (vector == NULL) {
2004 vector[0] = req->in.vector[idx];
2011 if (req->in.vector_count == 1) {
2013 * Now we analyze the NBT header
2015 state->missing = smb2_len(req->in.vector[0].iov_base);
2017 if (state->missing == 0) {
2018 /* if there're no remaining bytes, we're done */
2024 req->in.vector = talloc_realloc(req, req->in.vector,
2026 req->in.vector_count + 1);
2027 if (req->in.vector == NULL) {
2030 req->in.vector_count += 1;
2032 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2034 * it's a special NBT message,
2035 * so get all remaining bytes
2037 len = state->missing;
2038 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2040 * it's an invalid message, just read what we can get
2041 * and let the caller handle the error
2043 len = state->missing;
2046 * We assume it's a SMB2 request,
2047 * and we first get the header and the
2048 * first 2 bytes (the struct size) of the body
2050 len = SMB2_HDR_BODY + 2;
2052 state->asked_for_header = true;
2055 state->missing -= len;
2057 buf = talloc_array(req->in.vector, uint8_t, len);
2062 req->in.vector[idx].iov_base = (void *)buf;
2063 req->in.vector[idx].iov_len = len;
2065 vector = talloc_array(mem_ctx, struct iovec, 1);
2066 if (vector == NULL) {
2070 vector[0] = req->in.vector[idx];
2077 if (state->missing == 0) {
2078 /* if there're no remaining bytes, we're done */
2084 if (state->asked_for_header) {
2087 size_t next_command_ofs;
2092 bool invalid = false;
2094 state->asked_for_header = false;
2097 * We got the SMB2 header and the first 2 bytes
2098 * of the body. We fix the size to just the header
2099 * and manually copy the 2 first bytes to the body section
2101 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2102 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2104 /* allocate vectors for body and dynamic areas */
2105 req->in.vector = talloc_realloc(req, req->in.vector,
2107 req->in.vector_count + 2);
2108 if (req->in.vector == NULL) {
2111 req->in.vector_count += 2;
2113 full_size = state->missing + SMB2_HDR_BODY + 2;
2114 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2115 body_size = SVAL(hdr, SMB2_HDR_BODY);
2117 if (next_command_ofs != 0) {
2118 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2120 * this is invalid, just return a zero
2121 * body and let the caller deal with the error
2124 } else if (next_command_ofs > full_size) {
2126 * this is invalid, just return a zero
2127 * body and let the caller deal with the error
2131 full_size = next_command_ofs;
2136 if (body_size < 2) {
2138 * this is invalid, just return a zero
2139 * body and let the caller deal with the error
2145 * Mask out the lowest bit, the "dynamic" part
2150 if (body_size > (full_size - SMB2_HDR_BODY)) {
2152 * this is invalid, just return a zero
2153 * body and let the caller deal with the error
2160 /* the caller should check this */
2164 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2166 state->missing -= (body_size - 2) + dyn_size;
2168 body = talloc_array(req->in.vector, uint8_t, body_size);
2173 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2178 req->in.vector[idx].iov_base = (void *)body;
2179 req->in.vector[idx].iov_len = body_size;
2180 req->in.vector[idx+1].iov_base = (void *)dyn;
2181 req->in.vector[idx+1].iov_len = dyn_size;
2183 vector = talloc_array(mem_ctx, struct iovec, 2);
2184 if (vector == NULL) {
2189 * the first 2 bytes of the body were already fetched
2190 * together with the header
2192 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2193 vector[0].iov_base = body + 2;
2194 vector[0].iov_len = body_size - 2;
2196 vector[1] = req->in.vector[idx+1];
2204 * when we endup here, we're looking for a new SMB2 request
2205 * next. And we ask for its header and the first 2 bytes of
2206 * the body (like we did for the first SMB2 request).
2209 req->in.vector = talloc_realloc(req, req->in.vector,
2211 req->in.vector_count + 1);
2212 if (req->in.vector == NULL) {
2215 req->in.vector_count += 1;
2218 * We assume it's a SMB2 request,
2219 * and we first get the header and the
2220 * first 2 bytes (the struct size) of the body
2222 len = SMB2_HDR_BODY + 2;
2224 if (len > state->missing) {
2225 /* let the caller handle the error */
2226 len = state->missing;
2229 state->missing -= len;
2230 state->asked_for_header = true;
2232 buf = talloc_array(req->in.vector, uint8_t, len);
2237 req->in.vector[idx].iov_base = (void *)buf;
2238 req->in.vector[idx].iov_len = len;
2240 vector = talloc_array(mem_ctx, struct iovec, 1);
2241 if (vector == NULL) {
2245 vector[0] = req->in.vector[idx];
2252 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2254 struct tevent_req *req =
2255 tevent_req_callback_data(subreq,
2261 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2263 status = map_nt_error_from_unix(sys_errno);
2264 tevent_req_nterror(req, status);
2268 tevent_req_done(req);
2271 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2272 TALLOC_CTX *mem_ctx,
2273 struct smbd_smb2_request **_smb2_req)
2275 struct smbd_smb2_request_read_state *state =
2276 tevent_req_data(req,
2277 struct smbd_smb2_request_read_state);
2280 if (tevent_req_is_nterror(req, &status)) {
2281 tevent_req_received(req);
2285 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2286 *_smb2_req = state->smb2_req;
2287 tevent_req_received(req);
2288 return NT_STATUS_OK;
2291 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2293 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2294 const uint8_t *inbuf, size_t size)
2297 struct smbd_smb2_request *req = NULL;
2298 struct tevent_req *subreq;
2300 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2301 (unsigned int)size));
2303 status = smbd_initialize_smb2(sconn);
2304 if (!NT_STATUS_IS_OK(status)) {
2305 smbd_server_connection_terminate(sconn, nt_errstr(status));
2309 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2310 if (!NT_STATUS_IS_OK(status)) {
2311 smbd_server_connection_terminate(sconn, nt_errstr(status));
2315 status = smbd_smb2_request_setup_out(req);
2316 if (!NT_STATUS_IS_OK(status)) {
2317 smbd_server_connection_terminate(sconn, nt_errstr(status));
2321 status = smbd_smb2_request_dispatch(req);
2322 if (!NT_STATUS_IS_OK(status)) {
2323 smbd_server_connection_terminate(sconn, nt_errstr(status));
2327 /* ask for the next request */
2328 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2329 if (subreq == NULL) {
2330 smbd_server_connection_terminate(sconn, "no memory for reading");
2333 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2335 sconn->num_requests++;
2338 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2340 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2341 struct smbd_server_connection);
2343 struct smbd_smb2_request *req = NULL;
2345 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2346 TALLOC_FREE(subreq);
2347 if (!NT_STATUS_IS_OK(status)) {
2348 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2349 nt_errstr(status)));
2350 smbd_server_connection_terminate(sconn, nt_errstr(status));
2354 if (req->in.nbt_hdr[0] != 0x00) {
2355 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2356 req->in.nbt_hdr[0]));
2361 req->current_idx = 1;
2363 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2364 req->current_idx, req->in.vector_count));
2366 status = smbd_smb2_request_validate(req);
2367 if (!NT_STATUS_IS_OK(status)) {
2368 smbd_server_connection_terminate(sconn, nt_errstr(status));
2372 status = smbd_smb2_request_setup_out(req);
2373 if (!NT_STATUS_IS_OK(status)) {
2374 smbd_server_connection_terminate(sconn, nt_errstr(status));
2378 status = smbd_smb2_request_dispatch(req);
2379 if (!NT_STATUS_IS_OK(status)) {
2380 smbd_server_connection_terminate(sconn, nt_errstr(status));
2385 /* ask for the next request (this constructs the main loop) */
2386 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2387 if (subreq == NULL) {
2388 smbd_server_connection_terminate(sconn, "no memory for reading");
2391 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2393 sconn->num_requests++;
2395 /* The timeout_processing function isn't run nearly
2396 often enough to implement 'max log size' without
2397 overrunning the size of the file by many megabytes.
2398 This is especially true if we are running at debug
2399 level 10. Checking every 50 SMB2s is a nice
2400 tradeoff of performance vs log file size overrun. */
2402 if ((sconn->num_requests % 50) == 0 &&
2403 need_to_check_log_size()) {
2404 change_to_root_user();