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);
1108 session_status = smbd_smb2_request_check_session(req);
1110 req->do_signing = false;
1111 if (flags & SMB2_HDR_FLAG_SIGNED) {
1112 if (!NT_STATUS_IS_OK(session_status)) {
1113 return smbd_smb2_request_error(req, session_status);
1116 req->do_signing = true;
1117 status = smb2_signing_check_pdu(req->session->session_key,
1118 &req->in.vector[i], 3);
1119 if (!NT_STATUS_IS_OK(status)) {
1120 return smbd_smb2_request_error(req, status);
1122 } else if (req->session && req->session->do_signing) {
1123 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1126 if (flags & SMB2_HDR_FLAG_CHAINED) {
1128 * This check is mostly for giving the correct error code
1129 * for compounded requests.
1131 * TODO: we may need to move this after the session
1134 if (!NT_STATUS_IS_OK(req->next_status)) {
1135 return smbd_smb2_request_error(req, req->next_status);
1138 req->compat_chain_fsp = NULL;
1142 case SMB2_OP_NEGPROT:
1143 /* This call needs to be run as root */
1144 change_to_root_user();
1147 START_PROFILE(smb2_negprot);
1148 return_value = smbd_smb2_request_process_negprot(req);
1149 END_PROFILE(smb2_negprot);
1153 case SMB2_OP_SESSSETUP:
1154 /* This call needs to be run as root */
1155 change_to_root_user();
1158 START_PROFILE(smb2_sesssetup);
1159 return_value = smbd_smb2_request_process_sesssetup(req);
1160 END_PROFILE(smb2_sesssetup);
1164 case SMB2_OP_LOGOFF:
1165 if (!NT_STATUS_IS_OK(session_status)) {
1166 return_value = smbd_smb2_request_error(req, session_status);
1170 /* This call needs to be run as root */
1171 change_to_root_user();
1174 START_PROFILE(smb2_logoff);
1175 return_value = smbd_smb2_request_process_logoff(req);
1176 END_PROFILE(smb2_logoff);
1181 if (!NT_STATUS_IS_OK(session_status)) {
1182 return_value = smbd_smb2_request_error(req, session_status);
1186 /* This call needs to be run as root */
1187 change_to_root_user();
1190 START_PROFILE(smb2_tcon);
1191 return_value = smbd_smb2_request_process_tcon(req);
1192 END_PROFILE(smb2_tcon);
1197 if (!NT_STATUS_IS_OK(session_status)) {
1198 return_value = smbd_smb2_request_error(req, session_status);
1201 status = smbd_smb2_request_check_tcon(req);
1202 if (!NT_STATUS_IS_OK(status)) {
1203 return_value = smbd_smb2_request_error(req, status);
1206 /* This call needs to be run as root */
1207 change_to_root_user();
1211 START_PROFILE(smb2_tdis);
1212 return_value = smbd_smb2_request_process_tdis(req);
1213 END_PROFILE(smb2_tdis);
1217 case SMB2_OP_CREATE:
1218 if (!NT_STATUS_IS_OK(session_status)) {
1219 return_value = smbd_smb2_request_error(req, session_status);
1222 status = smbd_smb2_request_check_tcon(req);
1223 if (!NT_STATUS_IS_OK(status)) {
1224 return_value = smbd_smb2_request_error(req, status);
1229 START_PROFILE(smb2_create);
1230 return_value = smbd_smb2_request_process_create(req);
1231 END_PROFILE(smb2_create);
1236 if (!NT_STATUS_IS_OK(session_status)) {
1237 return_value = smbd_smb2_request_error(req, session_status);
1240 status = smbd_smb2_request_check_tcon(req);
1241 if (!NT_STATUS_IS_OK(status)) {
1242 return_value = smbd_smb2_request_error(req, status);
1247 START_PROFILE(smb2_close);
1248 return_value = smbd_smb2_request_process_close(req);
1249 END_PROFILE(smb2_close);
1254 if (!NT_STATUS_IS_OK(session_status)) {
1255 return_value = smbd_smb2_request_error(req, session_status);
1258 status = smbd_smb2_request_check_tcon(req);
1259 if (!NT_STATUS_IS_OK(status)) {
1260 return_value = smbd_smb2_request_error(req, status);
1265 START_PROFILE(smb2_flush);
1266 return_value = smbd_smb2_request_process_flush(req);
1267 END_PROFILE(smb2_flush);
1272 if (!NT_STATUS_IS_OK(session_status)) {
1273 return_value = smbd_smb2_request_error(req, session_status);
1276 status = smbd_smb2_request_check_tcon(req);
1277 if (!NT_STATUS_IS_OK(status)) {
1278 return_value = smbd_smb2_request_error(req, status);
1283 START_PROFILE(smb2_read);
1284 return_value = smbd_smb2_request_process_read(req);
1285 END_PROFILE(smb2_read);
1290 if (!NT_STATUS_IS_OK(session_status)) {
1291 return_value = smbd_smb2_request_error(req, session_status);
1294 status = smbd_smb2_request_check_tcon(req);
1295 if (!NT_STATUS_IS_OK(status)) {
1296 return_value = smbd_smb2_request_error(req, status);
1301 START_PROFILE(smb2_write);
1302 return_value = smbd_smb2_request_process_write(req);
1303 END_PROFILE(smb2_write);
1308 if (!NT_STATUS_IS_OK(session_status)) {
1309 /* Too ugly to live ? JRA. */
1310 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1311 session_status = NT_STATUS_FILE_CLOSED;
1313 return_value = smbd_smb2_request_error(req, session_status);
1316 status = smbd_smb2_request_check_tcon(req);
1317 if (!NT_STATUS_IS_OK(status)) {
1318 /* Too ugly to live ? JRA. */
1319 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1320 status = NT_STATUS_FILE_CLOSED;
1322 return_value = smbd_smb2_request_error(req, status);
1327 START_PROFILE(smb2_lock);
1328 return_value = smbd_smb2_request_process_lock(req);
1329 END_PROFILE(smb2_lock);
1334 if (!NT_STATUS_IS_OK(session_status)) {
1335 return_value = smbd_smb2_request_error(req, session_status);
1338 status = smbd_smb2_request_check_tcon(req);
1339 if (!NT_STATUS_IS_OK(status)) {
1340 return_value = smbd_smb2_request_error(req, status);
1345 START_PROFILE(smb2_ioctl);
1346 return_value = smbd_smb2_request_process_ioctl(req);
1347 END_PROFILE(smb2_ioctl);
1351 case SMB2_OP_CANCEL:
1352 /* This call needs to be run as root */
1353 change_to_root_user();
1356 START_PROFILE(smb2_cancel);
1357 return_value = smbd_smb2_request_process_cancel(req);
1358 END_PROFILE(smb2_cancel);
1362 case SMB2_OP_KEEPALIVE:
1363 /* This call needs to be run as root */
1364 change_to_root_user();
1367 START_PROFILE(smb2_keepalive);
1368 return_value = smbd_smb2_request_process_keepalive(req);
1369 END_PROFILE(smb2_keepalive);
1374 if (!NT_STATUS_IS_OK(session_status)) {
1375 return_value = smbd_smb2_request_error(req, session_status);
1378 status = smbd_smb2_request_check_tcon(req);
1379 if (!NT_STATUS_IS_OK(status)) {
1380 return_value = smbd_smb2_request_error(req, status);
1385 START_PROFILE(smb2_find);
1386 return_value = smbd_smb2_request_process_find(req);
1387 END_PROFILE(smb2_find);
1391 case SMB2_OP_NOTIFY:
1392 if (!NT_STATUS_IS_OK(session_status)) {
1393 return_value = smbd_smb2_request_error(req, session_status);
1396 status = smbd_smb2_request_check_tcon(req);
1397 if (!NT_STATUS_IS_OK(status)) {
1398 return_value = smbd_smb2_request_error(req, status);
1403 START_PROFILE(smb2_notify);
1404 return_value = smbd_smb2_request_process_notify(req);
1405 END_PROFILE(smb2_notify);
1409 case SMB2_OP_GETINFO:
1410 if (!NT_STATUS_IS_OK(session_status)) {
1411 return_value = smbd_smb2_request_error(req, session_status);
1414 status = smbd_smb2_request_check_tcon(req);
1415 if (!NT_STATUS_IS_OK(status)) {
1416 return_value = smbd_smb2_request_error(req, status);
1421 START_PROFILE(smb2_getinfo);
1422 return_value = smbd_smb2_request_process_getinfo(req);
1423 END_PROFILE(smb2_getinfo);
1427 case SMB2_OP_SETINFO:
1428 if (!NT_STATUS_IS_OK(session_status)) {
1429 return_value = smbd_smb2_request_error(req, session_status);
1432 status = smbd_smb2_request_check_tcon(req);
1433 if (!NT_STATUS_IS_OK(status)) {
1434 return_value = smbd_smb2_request_error(req, status);
1439 START_PROFILE(smb2_setinfo);
1440 return_value = smbd_smb2_request_process_setinfo(req);
1441 END_PROFILE(smb2_setinfo);
1446 if (!NT_STATUS_IS_OK(session_status)) {
1447 return_value = smbd_smb2_request_error(req, session_status);
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_break);
1458 return_value = smbd_smb2_request_process_break(req);
1459 END_PROFILE(smb2_break);
1464 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1467 return return_value;
1470 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1472 struct tevent_req *subreq;
1473 int i = req->current_idx;
1477 req->current_idx += 3;
1479 if (req->current_idx < req->out.vector_count) {
1481 * We must process the remaining compound
1482 * SMB2 requests before any new incoming SMB2
1483 * requests. This is because incoming SMB2
1484 * requests may include a cancel for a
1485 * compound request we haven't processed
1488 struct tevent_immediate *im = tevent_create_immediate(req);
1490 return NT_STATUS_NO_MEMORY;
1492 tevent_schedule_immediate(im,
1493 req->sconn->smb2.event_ctx,
1494 smbd_smb2_request_dispatch_immediate,
1496 return NT_STATUS_OK;
1499 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1501 /* Set credit for this operation (zero credits if this
1502 is a final reply for an async operation). */
1503 smb2_set_operation_credit(req->sconn,
1504 req->async ? NULL : &req->in.vector[i],
1505 &req->out.vector[i]);
1507 if (req->do_signing) {
1509 status = smb2_signing_sign_pdu(req->session->session_key,
1510 &req->out.vector[i], 3);
1511 if (!NT_STATUS_IS_OK(status)) {
1516 if (DEBUGLEVEL >= 10) {
1517 dbgtext("smbd_smb2_request_reply: sending...\n");
1518 print_req_vectors(req);
1521 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1522 if (req->out.vector_count == 4 &&
1523 req->out.vector[3].iov_base == NULL &&
1524 req->out.vector[3].iov_len != 0) {
1525 /* Dynamic part is NULL. Chop it off,
1526 We're going to send it via sendfile. */
1527 req->out.vector_count -= 1;
1530 subreq = tstream_writev_queue_send(req,
1531 req->sconn->smb2.event_ctx,
1532 req->sconn->smb2.stream,
1533 req->sconn->smb2.send_queue,
1535 req->out.vector_count);
1536 if (subreq == NULL) {
1537 return NT_STATUS_NO_MEMORY;
1539 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1541 * We're done with this request -
1542 * move it off the "being processed" queue.
1544 DLIST_REMOVE(req->sconn->smb2.requests, req);
1546 return NT_STATUS_OK;
1549 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1550 struct tevent_immediate *im,
1553 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1554 struct smbd_smb2_request);
1555 struct smbd_server_connection *sconn = req->sconn;
1560 if (DEBUGLEVEL >= 10) {
1561 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1562 req->current_idx, req->in.vector_count));
1563 print_req_vectors(req);
1566 status = smbd_smb2_request_dispatch(req);
1567 if (!NT_STATUS_IS_OK(status)) {
1568 smbd_server_connection_terminate(sconn, nt_errstr(status));
1573 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1575 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1576 struct smbd_smb2_request);
1577 struct smbd_server_connection *sconn = req->sconn;
1581 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1582 TALLOC_FREE(subreq);
1585 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1586 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1587 nt_errstr(status)));
1588 smbd_server_connection_terminate(sconn, nt_errstr(status));
1593 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1595 DATA_BLOB body, DATA_BLOB *dyn,
1596 const char *location)
1599 int i = req->current_idx;
1600 uint32_t next_command_ofs;
1602 DEBUG(10,("smbd_smb2_request_done_ex: "
1603 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1604 i, nt_errstr(status), (unsigned int)body.length,
1606 (unsigned int)(dyn ? dyn->length : 0),
1609 if (body.length < 2) {
1610 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1613 if ((body.length % 2) != 0) {
1614 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1617 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1619 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1620 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1622 req->out.vector[i+1].iov_base = (void *)body.data;
1623 req->out.vector[i+1].iov_len = body.length;
1626 req->out.vector[i+2].iov_base = (void *)dyn->data;
1627 req->out.vector[i+2].iov_len = dyn->length;
1629 req->out.vector[i+2].iov_base = NULL;
1630 req->out.vector[i+2].iov_len = 0;
1633 /* see if we need to recalculate the offset to the next response */
1634 if (next_command_ofs > 0) {
1635 next_command_ofs = SMB2_HDR_BODY;
1636 next_command_ofs += req->out.vector[i+1].iov_len;
1637 next_command_ofs += req->out.vector[i+2].iov_len;
1640 if ((next_command_ofs % 8) != 0) {
1641 size_t pad_size = 8 - (next_command_ofs % 8);
1642 if (req->out.vector[i+2].iov_len == 0) {
1644 * if the dyn buffer is empty
1645 * we can use it to add padding
1649 pad = talloc_zero_array(req->out.vector,
1652 return smbd_smb2_request_error(req,
1653 NT_STATUS_NO_MEMORY);
1656 req->out.vector[i+2].iov_base = (void *)pad;
1657 req->out.vector[i+2].iov_len = pad_size;
1660 * For now we copy the dynamic buffer
1661 * and add the padding to the new buffer
1668 old_size = req->out.vector[i+2].iov_len;
1669 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
1671 new_size = old_size + pad_size;
1672 new_dyn = talloc_zero_array(req->out.vector,
1674 if (new_dyn == NULL) {
1675 return smbd_smb2_request_error(req,
1676 NT_STATUS_NO_MEMORY);
1679 memcpy(new_dyn, old_dyn, old_size);
1680 memset(new_dyn + old_size, 0, pad_size);
1682 req->out.vector[i+2].iov_base = (void *)new_dyn;
1683 req->out.vector[i+2].iov_len = new_size;
1685 next_command_ofs += pad_size;
1688 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1690 return smbd_smb2_request_reply(req);
1693 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
1696 const char *location)
1699 int i = req->current_idx;
1700 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
1702 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1703 i, nt_errstr(status), info ? " +info" : "",
1706 body.data = outhdr + SMB2_HDR_BODY;
1708 SSVAL(body.data, 0, 9);
1711 SIVAL(body.data, 0x04, info->length);
1713 /* Allocated size of req->out.vector[i].iov_base
1714 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
1715 * 1 byte without having to do an alloc.
1717 info = talloc_zero_array(req->out.vector,
1721 return NT_STATUS_NO_MEMORY;
1723 info->data = ((uint8_t *)outhdr) +
1724 OUTVEC_ALLOC_SIZE - 1;
1726 SCVAL(info->data, 0, 0);
1730 * if a request fails, all other remaining
1731 * compounded requests should fail too
1733 req->next_status = NT_STATUS_INVALID_PARAMETER;
1735 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
1739 struct smbd_smb2_send_oplock_break_state {
1740 struct smbd_server_connection *sconn;
1741 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
1742 struct iovec vector;
1745 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
1747 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
1748 uint64_t file_id_persistent,
1749 uint64_t file_id_volatile,
1750 uint8_t oplock_level)
1752 struct smbd_smb2_send_oplock_break_state *state;
1753 struct tevent_req *subreq;
1757 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
1758 if (state == NULL) {
1759 return NT_STATUS_NO_MEMORY;
1761 state->sconn = sconn;
1763 state->vector.iov_base = (void *)state->buf;
1764 state->vector.iov_len = sizeof(state->buf);
1766 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
1767 hdr = state->buf + 4;
1768 body = hdr + SMB2_HDR_BODY;
1770 SIVAL(hdr, 0, SMB2_MAGIC);
1771 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1772 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1773 SIVAL(hdr, SMB2_HDR_STATUS, 0);
1774 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
1775 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
1776 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
1777 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1778 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
1779 SIVAL(hdr, SMB2_HDR_PID, 0);
1780 SIVAL(hdr, SMB2_HDR_TID, 0);
1781 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
1782 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
1784 SSVAL(body, 0x00, 0x18);
1786 SCVAL(body, 0x02, oplock_level);
1787 SCVAL(body, 0x03, 0); /* reserved */
1788 SIVAL(body, 0x04, 0); /* reserved */
1789 SBVAL(body, 0x08, file_id_persistent);
1790 SBVAL(body, 0x10, file_id_volatile);
1792 subreq = tstream_writev_queue_send(state,
1793 sconn->smb2.event_ctx,
1795 sconn->smb2.send_queue,
1797 if (subreq == NULL) {
1798 return NT_STATUS_NO_MEMORY;
1800 tevent_req_set_callback(subreq,
1801 smbd_smb2_oplock_break_writev_done,
1804 return NT_STATUS_OK;
1807 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
1809 struct smbd_smb2_send_oplock_break_state *state =
1810 tevent_req_callback_data(subreq,
1811 struct smbd_smb2_send_oplock_break_state);
1812 struct smbd_server_connection *sconn = state->sconn;
1816 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1817 TALLOC_FREE(subreq);
1819 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1820 smbd_server_connection_terminate(sconn, nt_errstr(status));
1827 struct smbd_smb2_request_read_state {
1829 bool asked_for_header;
1830 struct smbd_smb2_request *smb2_req;
1833 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1835 TALLOC_CTX *mem_ctx,
1836 struct iovec **_vector,
1838 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
1840 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
1841 struct tevent_context *ev,
1842 struct smbd_server_connection *sconn)
1844 struct tevent_req *req;
1845 struct smbd_smb2_request_read_state *state;
1846 struct tevent_req *subreq;
1848 req = tevent_req_create(mem_ctx, &state,
1849 struct smbd_smb2_request_read_state);
1854 state->asked_for_header = false;
1856 state->smb2_req = smbd_smb2_request_allocate(state);
1857 if (tevent_req_nomem(state->smb2_req, req)) {
1858 return tevent_req_post(req, ev);
1860 state->smb2_req->sconn = sconn;
1862 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
1863 sconn->smb2.recv_queue,
1864 smbd_smb2_request_next_vector,
1866 if (tevent_req_nomem(subreq, req)) {
1867 return tevent_req_post(req, ev);
1869 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
1874 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1876 TALLOC_CTX *mem_ctx,
1877 struct iovec **_vector,
1880 struct smbd_smb2_request_read_state *state =
1881 talloc_get_type_abort(private_data,
1882 struct smbd_smb2_request_read_state);
1883 struct smbd_smb2_request *req = state->smb2_req;
1884 struct iovec *vector;
1885 int idx = req->in.vector_count;
1887 uint8_t *buf = NULL;
1889 if (req->in.vector_count == 0) {
1891 * first we need to get the NBT header
1893 req->in.vector = talloc_array(req, struct iovec,
1894 req->in.vector_count + 1);
1895 if (req->in.vector == NULL) {
1898 req->in.vector_count += 1;
1900 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
1901 req->in.vector[idx].iov_len = 4;
1903 vector = talloc_array(mem_ctx, struct iovec, 1);
1904 if (vector == NULL) {
1908 vector[0] = req->in.vector[idx];
1915 if (req->in.vector_count == 1) {
1917 * Now we analyze the NBT header
1919 state->missing = smb2_len(req->in.vector[0].iov_base);
1921 if (state->missing == 0) {
1922 /* if there're no remaining bytes, we're done */
1928 req->in.vector = talloc_realloc(req, req->in.vector,
1930 req->in.vector_count + 1);
1931 if (req->in.vector == NULL) {
1934 req->in.vector_count += 1;
1936 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
1938 * it's a special NBT message,
1939 * so get all remaining bytes
1941 len = state->missing;
1942 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
1944 * it's an invalid message, just read what we can get
1945 * and let the caller handle the error
1947 len = state->missing;
1950 * We assume it's a SMB2 request,
1951 * and we first get the header and the
1952 * first 2 bytes (the struct size) of the body
1954 len = SMB2_HDR_BODY + 2;
1956 state->asked_for_header = true;
1959 state->missing -= len;
1961 buf = talloc_array(req->in.vector, uint8_t, len);
1966 req->in.vector[idx].iov_base = (void *)buf;
1967 req->in.vector[idx].iov_len = len;
1969 vector = talloc_array(mem_ctx, struct iovec, 1);
1970 if (vector == NULL) {
1974 vector[0] = req->in.vector[idx];
1981 if (state->missing == 0) {
1982 /* if there're no remaining bytes, we're done */
1988 if (state->asked_for_header) {
1991 size_t next_command_ofs;
1996 bool invalid = false;
1998 state->asked_for_header = false;
2001 * We got the SMB2 header and the first 2 bytes
2002 * of the body. We fix the size to just the header
2003 * and manually copy the 2 first bytes to the body section
2005 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2006 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2008 /* allocate vectors for body and dynamic areas */
2009 req->in.vector = talloc_realloc(req, req->in.vector,
2011 req->in.vector_count + 2);
2012 if (req->in.vector == NULL) {
2015 req->in.vector_count += 2;
2017 full_size = state->missing + SMB2_HDR_BODY + 2;
2018 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2019 body_size = SVAL(hdr, SMB2_HDR_BODY);
2021 if (next_command_ofs != 0) {
2022 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2024 * this is invalid, just return a zero
2025 * body and let the caller deal with the error
2028 } else if (next_command_ofs > full_size) {
2030 * this is invalid, just return a zero
2031 * body and let the caller deal with the error
2035 full_size = next_command_ofs;
2040 if (body_size < 2) {
2042 * this is invalid, just return a zero
2043 * body and let the caller deal with the error
2049 * Mask out the lowest bit, the "dynamic" part
2054 if (body_size > (full_size - SMB2_HDR_BODY)) {
2056 * this is invalid, just return a zero
2057 * body and let the caller deal with the error
2064 /* the caller should check this */
2068 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2070 state->missing -= (body_size - 2) + dyn_size;
2072 body = talloc_array(req->in.vector, uint8_t, body_size);
2077 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2082 req->in.vector[idx].iov_base = (void *)body;
2083 req->in.vector[idx].iov_len = body_size;
2084 req->in.vector[idx+1].iov_base = (void *)dyn;
2085 req->in.vector[idx+1].iov_len = dyn_size;
2087 vector = talloc_array(mem_ctx, struct iovec, 2);
2088 if (vector == NULL) {
2093 * the first 2 bytes of the body were already fetched
2094 * together with the header
2096 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2097 vector[0].iov_base = body + 2;
2098 vector[0].iov_len = body_size - 2;
2100 vector[1] = req->in.vector[idx+1];
2108 * when we endup here, we're looking for a new SMB2 request
2109 * next. And we ask for its header and the first 2 bytes of
2110 * the body (like we did for the first SMB2 request).
2113 req->in.vector = talloc_realloc(req, req->in.vector,
2115 req->in.vector_count + 1);
2116 if (req->in.vector == NULL) {
2119 req->in.vector_count += 1;
2122 * We assume it's a SMB2 request,
2123 * and we first get the header and the
2124 * first 2 bytes (the struct size) of the body
2126 len = SMB2_HDR_BODY + 2;
2128 if (len > state->missing) {
2129 /* let the caller handle the error */
2130 len = state->missing;
2133 state->missing -= len;
2134 state->asked_for_header = true;
2136 buf = talloc_array(req->in.vector, uint8_t, len);
2141 req->in.vector[idx].iov_base = (void *)buf;
2142 req->in.vector[idx].iov_len = len;
2144 vector = talloc_array(mem_ctx, struct iovec, 1);
2145 if (vector == NULL) {
2149 vector[0] = req->in.vector[idx];
2156 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2158 struct tevent_req *req =
2159 tevent_req_callback_data(subreq,
2165 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2167 status = map_nt_error_from_unix(sys_errno);
2168 tevent_req_nterror(req, status);
2172 tevent_req_done(req);
2175 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2176 TALLOC_CTX *mem_ctx,
2177 struct smbd_smb2_request **_smb2_req)
2179 struct smbd_smb2_request_read_state *state =
2180 tevent_req_data(req,
2181 struct smbd_smb2_request_read_state);
2184 if (tevent_req_is_nterror(req, &status)) {
2185 tevent_req_received(req);
2189 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2190 *_smb2_req = state->smb2_req;
2191 tevent_req_received(req);
2192 return NT_STATUS_OK;
2195 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2197 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2198 const uint8_t *inbuf, size_t size)
2201 struct smbd_smb2_request *req = NULL;
2202 struct tevent_req *subreq;
2204 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2205 (unsigned int)size));
2207 status = smbd_initialize_smb2(sconn);
2208 if (!NT_STATUS_IS_OK(status)) {
2209 smbd_server_connection_terminate(sconn, nt_errstr(status));
2213 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2214 if (!NT_STATUS_IS_OK(status)) {
2215 smbd_server_connection_terminate(sconn, nt_errstr(status));
2219 status = smbd_smb2_request_setup_out(req);
2220 if (!NT_STATUS_IS_OK(status)) {
2221 smbd_server_connection_terminate(sconn, nt_errstr(status));
2225 status = smbd_smb2_request_dispatch(req);
2226 if (!NT_STATUS_IS_OK(status)) {
2227 smbd_server_connection_terminate(sconn, nt_errstr(status));
2231 /* ask for the next request */
2232 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2233 if (subreq == NULL) {
2234 smbd_server_connection_terminate(sconn, "no memory for reading");
2237 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2239 sconn->num_requests++;
2242 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2244 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2245 struct smbd_server_connection);
2247 struct smbd_smb2_request *req = NULL;
2249 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2250 TALLOC_FREE(subreq);
2251 if (!NT_STATUS_IS_OK(status)) {
2252 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2253 nt_errstr(status)));
2254 smbd_server_connection_terminate(sconn, nt_errstr(status));
2258 if (req->in.nbt_hdr[0] != 0x00) {
2259 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2260 req->in.nbt_hdr[0]));
2265 req->current_idx = 1;
2267 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2268 req->current_idx, req->in.vector_count));
2270 status = smbd_smb2_request_validate(req);
2271 if (!NT_STATUS_IS_OK(status)) {
2272 smbd_server_connection_terminate(sconn, nt_errstr(status));
2276 status = smbd_smb2_request_setup_out(req);
2277 if (!NT_STATUS_IS_OK(status)) {
2278 smbd_server_connection_terminate(sconn, nt_errstr(status));
2282 status = smbd_smb2_request_dispatch(req);
2283 if (!NT_STATUS_IS_OK(status)) {
2284 smbd_server_connection_terminate(sconn, nt_errstr(status));
2289 /* ask for the next request (this constructs the main loop) */
2290 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2291 if (subreq == NULL) {
2292 smbd_server_connection_terminate(sconn, "no memory for reading");
2295 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2297 sconn->num_requests++;
2299 /* The timeout_processing function isn't run nearly
2300 often enough to implement 'max log size' without
2301 overrunning the size of the file by many megabytes.
2302 This is especially true if we are running at debug
2303 level 10. Checking every 50 SMB2s is a nice
2304 tradeoff of performance vs log file size overrun. */
2306 if ((sconn->num_requests % 50) == 0 &&
2307 need_to_check_log_size()) {
2308 change_to_root_user();