2 Unix SMB/CIFS implementation.
5 Copyright (C) Stefan Metzmacher 2009
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "smbd/globals.h"
23 #include "../libcli/smb/smb_common.h"
24 #include "../lib/tsocket/tsocket.h"
26 static const char *smb2_names[] = {
48 const char *smb2_opcode_name(uint16_t opcode)
51 return "Bad SMB2 opcode";
53 return smb2_names[opcode];
56 static void print_req_vectors(struct smbd_smb2_request *req)
60 for (i = 0; i < req->in.vector_count; i++) {
61 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
63 (unsigned int)req->in.vector[i].iov_len);
65 for (i = 0; i < req->out.vector_count; i++) {
66 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
68 (unsigned int)req->out.vector[i].iov_len);
72 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
74 if (size < (4 + SMB2_HDR_BODY)) {
78 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
85 static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
90 TALLOC_FREE(sconn->smb1.fde);
92 sconn->smb2.event_ctx = smbd_event_context();
94 sconn->smb2.recv_queue = tevent_queue_create(sconn, "smb2 recv queue");
95 if (sconn->smb2.recv_queue == NULL) {
96 return NT_STATUS_NO_MEMORY;
99 sconn->smb2.send_queue = tevent_queue_create(sconn, "smb2 send queue");
100 if (sconn->smb2.send_queue == NULL) {
101 return NT_STATUS_NO_MEMORY;
104 sconn->smb2.sessions.idtree = idr_init(sconn);
105 if (sconn->smb2.sessions.idtree == NULL) {
106 return NT_STATUS_NO_MEMORY;
108 sconn->smb2.sessions.limit = 0x0000FFFE;
109 sconn->smb2.sessions.list = NULL;
111 ret = tstream_bsd_existing_socket(sconn, smbd_server_fd(),
112 &sconn->smb2.stream);
114 status = map_nt_error_from_unix(errno);
118 /* Ensure child is set to non-blocking mode */
119 set_blocking(smbd_server_fd(),false);
123 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
124 #define _smb2_setlen(_buf,len) do { \
125 uint8_t *buf = (uint8_t *)_buf; \
127 buf[1] = ((len)&0xFF0000)>>16; \
128 buf[2] = ((len)&0xFF00)>>8; \
129 buf[3] = (len)&0xFF; \
132 static void smb2_setup_nbt_length(struct iovec *vector, int count)
137 for (i=1; i < count; i++) {
138 len += vector[i].iov_len;
141 _smb2_setlen(vector[0].iov_base, len);
144 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request **req)
147 (*req)->parent = NULL;
148 (*req)->mem_pool = NULL;
154 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
156 if (req->out.vector) {
157 DLIST_REMOVE(req->sconn->smb2.requests, req);
162 talloc_free(req->mem_pool);
168 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
170 TALLOC_CTX *mem_pool;
171 struct smbd_smb2_request **parent;
172 struct smbd_smb2_request *req;
174 mem_pool = talloc_pool(mem_ctx, 8192);
175 if (mem_pool == NULL) {
179 parent = talloc(mem_pool, struct smbd_smb2_request *);
180 if (parent == NULL) {
181 talloc_free(mem_pool);
185 req = talloc_zero(parent, struct smbd_smb2_request);
187 talloc_free(mem_pool);
191 req->mem_pool = mem_pool;
192 req->parent = parent;
194 talloc_set_destructor(parent, smbd_smb2_request_parent_destructor);
195 talloc_set_destructor(req, smbd_smb2_request_destructor);
200 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
201 const uint8_t *inbuf, size_t size,
202 struct smbd_smb2_request **_req)
204 struct smbd_smb2_request *req;
205 uint32_t protocol_version;
206 const uint8_t *inhdr = NULL;
209 uint32_t next_command_ofs;
211 if (size < (4 + SMB2_HDR_BODY + 2)) {
212 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
213 return NT_STATUS_INVALID_PARAMETER;
218 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
219 if (protocol_version != SMB2_MAGIC) {
220 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
222 return NT_STATUS_INVALID_PARAMETER;
225 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
226 if (cmd != SMB2_OP_NEGPROT) {
227 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
229 return NT_STATUS_INVALID_PARAMETER;
232 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
233 if (next_command_ofs != 0) {
234 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
236 return NT_STATUS_INVALID_PARAMETER;
239 req = smbd_smb2_request_allocate(sconn);
241 return NT_STATUS_NO_MEMORY;
245 talloc_steal(req, inbuf);
247 req->in.vector = talloc_array(req, struct iovec, 4);
248 if (req->in.vector == NULL) {
250 return NT_STATUS_NO_MEMORY;
252 req->in.vector_count = 4;
254 memcpy(req->in.nbt_hdr, inbuf, 4);
257 req->in.vector[0].iov_base = (void *)req->in.nbt_hdr;
258 req->in.vector[0].iov_len = 4;
259 ofs += req->in.vector[0].iov_len;
261 req->in.vector[1].iov_base = (void *)(inbuf + ofs);
262 req->in.vector[1].iov_len = SMB2_HDR_BODY;
263 ofs += req->in.vector[1].iov_len;
265 req->in.vector[2].iov_base = (void *)(inbuf + ofs);
266 req->in.vector[2].iov_len = SVAL(inbuf, ofs) & 0xFFFE;
267 ofs += req->in.vector[2].iov_len;
270 return NT_STATUS_INVALID_PARAMETER;
273 req->in.vector[3].iov_base = (void *)(inbuf + ofs);
274 req->in.vector[3].iov_len = size - ofs;
275 ofs += req->in.vector[3].iov_len;
277 req->current_idx = 1;
283 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req,
284 uint16_t *p_creds_requested)
288 bool compound_related = false;
290 *p_creds_requested = 0;
291 count = req->in.vector_count;
294 /* It's not a SMB2 request */
295 return NT_STATUS_INVALID_PARAMETER;
298 for (idx=1; idx < count; idx += 3) {
299 uint16_t creds_requested = 0;
300 const uint8_t *inhdr = NULL;
303 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
304 return NT_STATUS_INVALID_PARAMETER;
307 if (req->in.vector[idx+1].iov_len < 2) {
308 return NT_STATUS_INVALID_PARAMETER;
311 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
313 /* setup the SMB2 header */
314 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
315 return NT_STATUS_INVALID_PARAMETER;
318 creds_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
319 if (*p_creds_requested + creds_requested < creds_requested) {
320 *p_creds_requested = 65535;
322 *p_creds_requested += creds_requested;
325 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
328 * the 1st request should never have the
329 * SMB2_HDR_FLAG_CHAINED flag set
331 if (flags & SMB2_HDR_FLAG_CHAINED) {
332 req->next_status = NT_STATUS_INVALID_PARAMETER;
335 } else if (idx == 4) {
337 * the 2nd request triggers related vs. unrelated
338 * compounded requests
340 if (flags & SMB2_HDR_FLAG_CHAINED) {
341 compound_related = true;
343 } else if (idx > 4) {
346 * It seems the this tests are wrong
347 * see the SMB2-COMPOUND test
351 * all other requests should match the 2nd one
353 if (flags & SMB2_HDR_FLAG_CHAINED) {
354 if (!compound_related) {
356 NT_STATUS_INVALID_PARAMETER;
360 if (compound_related) {
362 NT_STATUS_INVALID_PARAMETER;
373 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req, uint16_t creds)
375 struct iovec *vector;
379 count = req->in.vector_count;
380 vector = talloc_array(req, struct iovec, count);
381 if (vector == NULL) {
382 return NT_STATUS_NO_MEMORY;
385 vector[0].iov_base = req->out.nbt_hdr;
386 vector[0].iov_len = 4;
387 SIVAL(req->out.nbt_hdr, 0, 0);
389 for (idx=1; idx < count; idx += 3) {
390 const uint8_t *inhdr = NULL;
392 uint8_t *outhdr = NULL;
393 uint8_t *outbody = NULL;
394 uint32_t next_command_ofs = 0;
395 struct iovec *current = &vector[idx];
397 if ((idx + 3) < count) {
398 /* we have a next command */
399 next_command_ofs = SMB2_HDR_BODY + 8;
402 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
403 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
405 outhdr = talloc_array(vector, uint8_t,
407 if (outhdr == NULL) {
408 return NT_STATUS_NO_MEMORY;
411 outbody = outhdr + SMB2_HDR_BODY;
413 current[0].iov_base = (void *)outhdr;
414 current[0].iov_len = SMB2_HDR_BODY;
416 current[1].iov_base = (void *)outbody;
417 current[1].iov_len = 8;
419 current[2].iov_base = NULL;
420 current[2].iov_len = 0;
422 /* setup the SMB2 header */
423 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
424 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
425 SSVAL(outhdr, SMB2_HDR_EPOCH, 0);
426 SIVAL(outhdr, SMB2_HDR_STATUS,
427 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
428 SSVAL(outhdr, SMB2_HDR_OPCODE,
429 SVAL(inhdr, SMB2_HDR_OPCODE));
430 SSVAL(outhdr, SMB2_HDR_CREDIT, creds);
431 SIVAL(outhdr, SMB2_HDR_FLAGS,
432 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
433 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
434 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
435 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
436 SIVAL(outhdr, SMB2_HDR_PID,
437 IVAL(inhdr, SMB2_HDR_PID));
438 SIVAL(outhdr, SMB2_HDR_TID,
439 IVAL(inhdr, SMB2_HDR_TID));
440 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
441 BVAL(inhdr, SMB2_HDR_SESSION_ID));
442 memset(outhdr + SMB2_HDR_SIGNATURE, 0, 16);
444 /* setup error body header */
445 SSVAL(outbody, 0x00, 0x08 + 1);
446 SSVAL(outbody, 0x02, 0);
447 SIVAL(outbody, 0x04, 0);
450 req->out.vector = vector;
451 req->out.vector_count = count;
453 /* setup the length of the NBT packet */
454 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
456 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
461 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
463 const char *location)
465 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
467 exit_server_cleanly(reason);
470 static bool dup_smb2_vec(struct iovec *dstvec,
471 const struct iovec *srcvec,
475 if (srcvec[offset].iov_len &&
476 srcvec[offset].iov_base) {
477 dstvec[offset].iov_base = talloc_memdup(dstvec,
478 srcvec[offset].iov_base,
479 srcvec[offset].iov_len);
480 if (!dstvec[offset].iov_base) {
483 dstvec[offset].iov_len = srcvec[offset].iov_len;
485 dstvec[offset].iov_base = NULL;
486 dstvec[offset].iov_len = 0;
491 static struct smbd_smb2_request *dup_smb2_req(struct smbd_smb2_request *req)
493 struct smbd_smb2_request *newreq = NULL;
494 struct iovec *outvec = NULL;
495 int count = req->out.vector_count;
498 newreq = smbd_smb2_request_allocate(req->sconn);
503 newreq->sconn = req->sconn;
504 newreq->do_signing = req->do_signing;
505 newreq->current_idx = req->current_idx;
506 newreq->async = false;
507 newreq->cancelled = false;
509 outvec = talloc_array(newreq, struct iovec, count);
514 newreq->out.vector = outvec;
515 newreq->out.vector_count = count;
517 /* Setup the outvec's identically to req. */
518 outvec[0].iov_base = newreq->out.nbt_hdr;
519 outvec[0].iov_len = 4;
520 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
522 for (i = 1; i < count; i++) {
523 if (!dup_smb2_vec(outvec,
531 smb2_setup_nbt_length(newreq->out.vector,
532 newreq->out.vector_count);
537 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
539 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
540 struct tevent_req *subreq)
542 int i = req->current_idx;
543 struct smbd_smb2_request *nreq = NULL;
544 uint8_t *outhdr = NULL;
545 uint8_t *outbody = NULL;
547 uint64_t message_id = 0;
548 uint64_t async_id = 0;
549 struct iovec *outvec = NULL;
551 if (!tevent_req_is_in_progress(subreq)) {
556 /* We're already async. */
560 if (req->in.vector_count > i + 3) {
562 * We're trying to go async in a compound
563 * request chain. This is not allowed.
564 * Cancel the outstanding request.
566 tevent_req_cancel(subreq);
567 return smbd_smb2_request_error(req,
568 NT_STATUS_INSUFFICIENT_RESOURCES);
571 req->subreq = subreq;
574 if (DEBUGLEVEL >= 10) {
575 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
576 (unsigned int)req->current_idx );
577 print_req_vectors(req);
580 /* Create a new smb2 request we'll use to return. */
581 nreq = dup_smb2_req(req);
583 return NT_STATUS_NO_MEMORY;
586 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
588 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
589 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
591 async_id = message_id; /* keep it simple for now... */
592 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
593 SBVAL(outhdr, SMB2_HDR_PID, async_id);
594 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
596 nreq->out.vector[i+1].iov_base = talloc_zero_array(nreq->out.vector,
599 if (!nreq->out.vector[i+1].iov_base) {
600 return NT_STATUS_NO_MEMORY;
602 nreq->out.vector[i+1].iov_len = 9;
603 outbody = (uint8_t *)nreq->out.vector[i+1].iov_base;
605 /* setup error body header */
606 SSVAL(outbody, 0x00, 0x08 + 1);
607 SSVAL(outbody, 0x02, 0);
608 SIVAL(outbody, 0x04, 0);
609 /* Match W2K8R2... */
610 SCVAL(outbody, 8, 0x21);
612 nreq->out.vector[i+2].iov_base = NULL;
613 nreq->out.vector[i+2].iov_len = 0;
615 smb2_setup_nbt_length(nreq->out.vector,
616 nreq->out.vector_count);
618 if (nreq->do_signing) {
620 status = smb2_signing_sign_pdu(nreq->session->session_key,
621 &nreq->out.vector[i], 3);
622 if (!NT_STATUS_IS_OK(status)) {
627 if (DEBUGLEVEL >= 10) {
628 dbgtext("smbd_smb2_request_pending_queue: nreq->current_idx = %u\n",
629 (unsigned int)nreq->current_idx );
630 dbgtext("smbd_smb2_request_pending_queue: returning %u vectors\n",
631 (unsigned int)nreq->out.vector_count );
632 print_req_vectors(nreq);
635 nreq->subreq = tstream_writev_queue_send(nreq,
636 nreq->sconn->smb2.event_ctx,
637 nreq->sconn->smb2.stream,
638 nreq->sconn->smb2.send_queue,
640 nreq->out.vector_count);
642 if (nreq->subreq == NULL) {
643 return NT_STATUS_NO_MEMORY;
646 tevent_req_set_callback(nreq->subreq,
647 smbd_smb2_request_writev_done,
650 /* Note we're going async with this request. */
654 * Now manipulate req so that the outstanding async request
655 * is the only one left in the struct smbd_smb2_request.
658 if (req->current_idx == 1) {
659 /* There was only one. */
663 /* Re-arrange the in.vectors. */
664 req->in.vector[1] = req->in.vector[i];
665 req->in.vector[2] = req->in.vector[i+1];
666 req->in.vector[3] = req->in.vector[i+2];
667 req->in.vector_count = 4;
668 /* Reset the new in size. */
669 smb2_setup_nbt_length(req->in.vector, 4);
671 /* Now recreate the out.vectors. */
672 outvec = talloc_array(req, struct iovec, 4);
674 return NT_STATUS_NO_MEMORY;
676 outvec[0].iov_base = req->out.nbt_hdr;
677 outvec[0].iov_len = 4;
678 SIVAL(req->out.nbt_hdr, 0, 0);
680 outvec[1].iov_base = talloc_memdup(outvec,
681 req->out.vector[i].iov_base,
683 if (!outvec[1].iov_base) {
684 return NT_STATUS_NO_MEMORY;
686 outvec[1].iov_len = SMB2_HDR_BODY;
688 outvec[2].iov_base = ((uint8_t *)outvec[1].iov_base) +
690 outvec[2].iov_len = 8;
692 if (req->out.vector[i+2].iov_base &&
693 req->out.vector[i+2].iov_len) {
694 outvec[3].iov_base = talloc_memdup(outvec,
695 req->out.vector[i+2].iov_base,
696 req->out.vector[i+2].iov_len);
697 if (!outvec[3].iov_base) {
698 return NT_STATUS_NO_MEMORY;
700 outvec[3].iov_len = req->out.vector[i+2].iov_len;
702 outvec[3].iov_base = NULL;
703 outvec[3].iov_len = 0;
706 TALLOC_FREE(req->out.vector);
708 req->out.vector = outvec;
710 req->current_idx = 1;
711 req->out.vector_count = 4;
715 smb2_setup_nbt_length(req->out.vector,
716 req->out.vector_count);
718 /* Ensure our final reply matches the interim one. */
719 outhdr = (uint8_t *)req->out.vector[1].iov_base;
720 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
721 SBVAL(outhdr, SMB2_HDR_PID, async_id);
724 const uint8_t *inhdr =
725 (const uint8_t *)req->in.vector[1].iov_base;
726 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
728 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
729 (unsigned long long)async_id ));
734 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
736 struct smbd_server_connection *sconn = req->sconn;
737 struct smbd_smb2_request *cur;
738 const uint8_t *inhdr;
739 int i = req->current_idx;
741 uint64_t search_message_id;
742 uint64_t search_async_id;
745 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
747 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
748 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
749 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
752 * we don't need the request anymore
753 * cancel requests never have a response
757 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
758 const uint8_t *outhdr;
762 i = cur->current_idx;
764 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
766 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
767 async_id = BVAL(outhdr, SMB2_HDR_PID);
769 if (flags & SMB2_HDR_FLAG_ASYNC) {
770 if (search_async_id == async_id) {
775 if (search_message_id == message_id) {
776 found_id = message_id;
782 if (cur && cur->subreq) {
783 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
784 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
785 "cancel opcode[%s] mid %llu\n",
786 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
787 (unsigned long long)found_id ));
788 tevent_req_cancel(cur->subreq);
789 TALLOC_FREE(cur->subreq);
796 static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
798 const uint8_t *inhdr;
799 int i = req->current_idx;
804 NTSTATUS session_status;
805 uint32_t allowed_flags;
807 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
809 /* TODO: verify more things */
811 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
812 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
813 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
814 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
815 smb2_opcode_name(opcode),
816 (unsigned long long)mid));
818 allowed_flags = SMB2_HDR_FLAG_CHAINED |
819 SMB2_HDR_FLAG_SIGNED |
821 if (opcode == SMB2_OP_CANCEL) {
822 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
824 if ((flags & ~allowed_flags) != 0) {
825 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
828 session_status = smbd_smb2_request_check_session(req);
830 req->do_signing = false;
831 if (flags & SMB2_HDR_FLAG_SIGNED) {
832 if (!NT_STATUS_IS_OK(session_status)) {
833 return smbd_smb2_request_error(req, session_status);
836 req->do_signing = true;
837 status = smb2_signing_check_pdu(req->session->session_key,
838 &req->in.vector[i], 3);
839 if (!NT_STATUS_IS_OK(status)) {
840 return smbd_smb2_request_error(req, status);
842 } else if (req->session && req->session->do_signing) {
843 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
846 if (flags & SMB2_HDR_FLAG_CHAINED) {
848 * This check is mostly for giving the correct error code
849 * for compounded requests.
851 * TODO: we may need to move this after the session
854 if (!NT_STATUS_IS_OK(req->next_status)) {
855 return smbd_smb2_request_error(req, req->next_status);
858 req->compat_chain_fsp = NULL;
862 case SMB2_OP_NEGPROT:
863 return smbd_smb2_request_process_negprot(req);
865 case SMB2_OP_SESSSETUP:
866 return smbd_smb2_request_process_sesssetup(req);
869 if (!NT_STATUS_IS_OK(session_status)) {
870 return smbd_smb2_request_error(req, session_status);
872 return smbd_smb2_request_process_logoff(req);
875 if (!NT_STATUS_IS_OK(session_status)) {
876 return smbd_smb2_request_error(req, session_status);
878 status = smbd_smb2_request_check_session(req);
879 if (!NT_STATUS_IS_OK(status)) {
880 return smbd_smb2_request_error(req, status);
882 return smbd_smb2_request_process_tcon(req);
885 if (!NT_STATUS_IS_OK(session_status)) {
886 return smbd_smb2_request_error(req, session_status);
888 status = smbd_smb2_request_check_tcon(req);
889 if (!NT_STATUS_IS_OK(status)) {
890 return smbd_smb2_request_error(req, status);
892 return smbd_smb2_request_process_tdis(req);
895 if (!NT_STATUS_IS_OK(session_status)) {
896 return smbd_smb2_request_error(req, session_status);
898 status = smbd_smb2_request_check_tcon(req);
899 if (!NT_STATUS_IS_OK(status)) {
900 return smbd_smb2_request_error(req, status);
902 return smbd_smb2_request_process_create(req);
905 if (!NT_STATUS_IS_OK(session_status)) {
906 return smbd_smb2_request_error(req, session_status);
908 status = smbd_smb2_request_check_tcon(req);
909 if (!NT_STATUS_IS_OK(status)) {
910 return smbd_smb2_request_error(req, status);
912 return smbd_smb2_request_process_close(req);
915 if (!NT_STATUS_IS_OK(session_status)) {
916 return smbd_smb2_request_error(req, session_status);
918 status = smbd_smb2_request_check_tcon(req);
919 if (!NT_STATUS_IS_OK(status)) {
920 return smbd_smb2_request_error(req, status);
922 return smbd_smb2_request_process_flush(req);
925 if (!NT_STATUS_IS_OK(session_status)) {
926 return smbd_smb2_request_error(req, session_status);
928 status = smbd_smb2_request_check_tcon(req);
929 if (!NT_STATUS_IS_OK(status)) {
930 return smbd_smb2_request_error(req, status);
932 return smbd_smb2_request_process_read(req);
935 if (!NT_STATUS_IS_OK(session_status)) {
936 return smbd_smb2_request_error(req, session_status);
938 status = smbd_smb2_request_check_tcon(req);
939 if (!NT_STATUS_IS_OK(status)) {
940 return smbd_smb2_request_error(req, status);
942 return smbd_smb2_request_process_write(req);
945 if (!NT_STATUS_IS_OK(session_status)) {
946 return smbd_smb2_request_error(req, session_status);
948 status = smbd_smb2_request_check_tcon(req);
949 if (!NT_STATUS_IS_OK(status)) {
950 return smbd_smb2_request_error(req, status);
952 return smbd_smb2_request_process_lock(req);
955 if (!NT_STATUS_IS_OK(session_status)) {
956 return smbd_smb2_request_error(req, session_status);
958 status = smbd_smb2_request_check_tcon(req);
959 if (!NT_STATUS_IS_OK(status)) {
960 return smbd_smb2_request_error(req, status);
962 return smbd_smb2_request_process_ioctl(req);
965 return smbd_smb2_request_process_cancel(req);
967 case SMB2_OP_KEEPALIVE:
968 return smbd_smb2_request_process_keepalive(req);
971 if (!NT_STATUS_IS_OK(session_status)) {
972 return smbd_smb2_request_error(req, session_status);
974 status = smbd_smb2_request_check_tcon(req);
975 if (!NT_STATUS_IS_OK(status)) {
976 return smbd_smb2_request_error(req, status);
978 return smbd_smb2_request_process_find(req);
981 if (!NT_STATUS_IS_OK(session_status)) {
982 return smbd_smb2_request_error(req, session_status);
984 status = smbd_smb2_request_check_tcon(req);
985 if (!NT_STATUS_IS_OK(status)) {
986 return smbd_smb2_request_error(req, status);
988 return smbd_smb2_request_process_notify(req);
990 case SMB2_OP_GETINFO:
991 if (!NT_STATUS_IS_OK(session_status)) {
992 return smbd_smb2_request_error(req, session_status);
994 status = smbd_smb2_request_check_tcon(req);
995 if (!NT_STATUS_IS_OK(status)) {
996 return smbd_smb2_request_error(req, status);
998 return smbd_smb2_request_process_getinfo(req);
1000 case SMB2_OP_SETINFO:
1001 if (!NT_STATUS_IS_OK(session_status)) {
1002 return smbd_smb2_request_error(req, session_status);
1004 status = smbd_smb2_request_check_tcon(req);
1005 if (!NT_STATUS_IS_OK(status)) {
1006 return smbd_smb2_request_error(req, status);
1008 return smbd_smb2_request_process_setinfo(req);
1011 if (!NT_STATUS_IS_OK(session_status)) {
1012 return smbd_smb2_request_error(req, session_status);
1014 status = smbd_smb2_request_check_tcon(req);
1015 if (!NT_STATUS_IS_OK(status)) {
1016 return smbd_smb2_request_error(req, status);
1018 return smbd_smb2_request_process_break(req);
1021 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1024 static void smbd_smb2_request_dispatch_compound(struct tevent_context *ctx,
1025 struct tevent_immediate *im,
1026 void *private_data);
1028 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1030 struct tevent_req *subreq;
1034 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1036 if (req->do_signing) {
1037 int i = req->current_idx;
1039 status = smb2_signing_sign_pdu(req->session->session_key,
1040 &req->out.vector[i], 3);
1041 if (!NT_STATUS_IS_OK(status)) {
1046 req->current_idx += 3;
1048 if (req->current_idx < req->out.vector_count) {
1050 * We must process the remaining compound
1051 * SMB2 requests before any new incoming SMB2
1052 * requests. This is because incoming SMB2
1053 * requests may include a cancel for a
1054 * compound request we haven't processed
1057 struct tevent_immediate *im = tevent_create_immediate(req);
1059 return NT_STATUS_NO_MEMORY;
1061 tevent_schedule_immediate(im,
1062 req->sconn->smb2.event_ctx,
1063 smbd_smb2_request_dispatch_compound,
1065 return NT_STATUS_OK;
1068 if (DEBUGLEVEL >= 10) {
1069 dbgtext("smbd_smb2_request_reply: sending...\n");
1070 print_req_vectors(req);
1073 subreq = tstream_writev_queue_send(req,
1074 req->sconn->smb2.event_ctx,
1075 req->sconn->smb2.stream,
1076 req->sconn->smb2.send_queue,
1078 req->out.vector_count);
1079 if (subreq == NULL) {
1080 return NT_STATUS_NO_MEMORY;
1082 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1084 return NT_STATUS_OK;
1087 static void smbd_smb2_request_dispatch_compound(struct tevent_context *ctx,
1088 struct tevent_immediate *im,
1091 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1092 struct smbd_smb2_request);
1093 struct smbd_server_connection *sconn = req->sconn;
1098 if (DEBUGLEVEL >= 10) {
1099 DEBUG(10,("smbd_smb2_request_dispatch_compound: idx[%d] of %d vectors\n",
1100 req->current_idx, req->in.vector_count));
1101 print_req_vectors(req);
1104 status = smbd_smb2_request_dispatch(req);
1105 if (!NT_STATUS_IS_OK(status)) {
1106 smbd_server_connection_terminate(sconn, nt_errstr(status));
1111 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1113 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1114 struct smbd_smb2_request);
1115 struct smbd_server_connection *sconn = req->sconn;
1119 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1120 TALLOC_FREE(subreq);
1123 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1124 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1125 nt_errstr(status)));
1126 smbd_server_connection_terminate(sconn, nt_errstr(status));
1131 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
1134 const char *location)
1138 int i = req->current_idx;
1140 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1141 i, nt_errstr(status), info ? " +info" : "",
1144 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1146 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1148 outbody = outhdr + SMB2_HDR_BODY;
1150 req->out.vector[i+1].iov_base = (void *)outbody;
1151 req->out.vector[i+1].iov_len = 8;
1154 SIVAL(outbody, 0x04, info->length);
1155 req->out.vector[i+2].iov_base = (void *)info->data;
1156 req->out.vector[i+2].iov_len = info->length;
1158 req->out.vector[i+2].iov_base = NULL;
1159 req->out.vector[i+2].iov_len = 0;
1163 * if a request fails, all other remaining
1164 * compounded requests should fail too
1166 req->next_status = NT_STATUS_INVALID_PARAMETER;
1168 return smbd_smb2_request_reply(req);
1171 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1173 DATA_BLOB body, DATA_BLOB *dyn,
1174 const char *location)
1178 int i = req->current_idx;
1179 uint32_t next_command_ofs;
1181 DEBUG(10,("smbd_smb2_request_done_ex: "
1182 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1183 i, nt_errstr(status), (unsigned int)body.length,
1185 (unsigned int)(dyn ? dyn->length : 0),
1188 if (body.length < 2) {
1189 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1192 if ((body.length % 2) != 0) {
1193 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1196 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1197 /* the fallback dynamic buffer */
1198 outdyn = outhdr + SMB2_HDR_BODY + 8;
1200 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1201 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1203 req->out.vector[i+1].iov_base = (void *)body.data;
1204 req->out.vector[i+1].iov_len = body.length;
1207 req->out.vector[i+2].iov_base = (void *)dyn->data;
1208 req->out.vector[i+2].iov_len = dyn->length;
1210 req->out.vector[i+2].iov_base = NULL;
1211 req->out.vector[i+2].iov_len = 0;
1214 /* see if we need to recalculate the offset to the next response */
1215 if (next_command_ofs > 0) {
1216 next_command_ofs = SMB2_HDR_BODY;
1217 next_command_ofs += req->out.vector[i+1].iov_len;
1218 next_command_ofs += req->out.vector[i+2].iov_len;
1221 if ((next_command_ofs % 8) != 0) {
1222 size_t pad_size = 8 - (next_command_ofs % 8);
1223 if (req->out.vector[i+2].iov_len == 0) {
1225 * if the dyn buffer is empty
1226 * we can use it to add padding
1230 pad = talloc_zero_array(req->out.vector,
1233 return smbd_smb2_request_error(req,
1234 NT_STATUS_NO_MEMORY);
1237 req->out.vector[i+2].iov_base = (void *)pad;
1238 req->out.vector[i+2].iov_len = pad_size;
1241 * For now we copy the dynamic buffer
1242 * and add the padding to the new buffer
1249 old_size = req->out.vector[i+2].iov_len;
1250 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
1252 new_size = old_size + pad_size;
1253 new_dyn = talloc_array(req->out.vector,
1255 if (new_dyn == NULL) {
1256 return smbd_smb2_request_error(req,
1257 NT_STATUS_NO_MEMORY);
1260 memcpy(new_dyn, old_dyn, old_size);
1261 memset(new_dyn + old_size, 0, pad_size);
1263 req->out.vector[i+2].iov_base = (void *)new_dyn;
1264 req->out.vector[i+2].iov_len = new_size;
1266 TALLOC_FREE(old_dyn);
1268 next_command_ofs += pad_size;
1271 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1273 return smbd_smb2_request_reply(req);
1276 struct smbd_smb2_send_oplock_break_state {
1277 struct smbd_server_connection *sconn;
1278 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
1279 struct iovec vector;
1282 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
1284 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
1285 uint64_t file_id_persistent,
1286 uint64_t file_id_volatile,
1287 uint8_t oplock_level)
1289 struct smbd_smb2_send_oplock_break_state *state;
1290 struct tevent_req *subreq;
1294 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
1295 if (state == NULL) {
1296 return NT_STATUS_NO_MEMORY;
1298 state->sconn = sconn;
1300 state->vector.iov_base = (void *)state->buf;
1301 state->vector.iov_len = sizeof(state->buf);
1303 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
1304 hdr = state->buf + 4;
1305 body = hdr + SMB2_HDR_BODY;
1307 SIVAL(hdr, 0, SMB2_MAGIC);
1308 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1309 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1310 SIVAL(hdr, SMB2_HDR_STATUS, 0);
1311 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
1312 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
1313 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
1314 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1315 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
1316 SIVAL(hdr, SMB2_HDR_PID, 0);
1317 SIVAL(hdr, SMB2_HDR_TID, 0);
1318 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
1319 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
1321 SSVAL(body, 0x00, 0x18);
1323 SCVAL(body, 0x02, oplock_level);
1324 SCVAL(body, 0x03, 0); /* reserved */
1325 SIVAL(body, 0x04, 0); /* reserved */
1326 SBVAL(body, 0x08, file_id_persistent);
1327 SBVAL(body, 0x10, file_id_volatile);
1329 subreq = tstream_writev_queue_send(state,
1330 sconn->smb2.event_ctx,
1332 sconn->smb2.send_queue,
1334 if (subreq == NULL) {
1335 return NT_STATUS_NO_MEMORY;
1337 tevent_req_set_callback(subreq,
1338 smbd_smb2_oplock_break_writev_done,
1341 return NT_STATUS_OK;
1344 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
1346 struct smbd_smb2_send_oplock_break_state *state =
1347 tevent_req_callback_data(subreq,
1348 struct smbd_smb2_send_oplock_break_state);
1349 struct smbd_server_connection *sconn = state->sconn;
1353 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1354 TALLOC_FREE(subreq);
1356 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1357 smbd_server_connection_terminate(sconn, nt_errstr(status));
1364 struct smbd_smb2_request_read_state {
1366 bool asked_for_header;
1367 struct smbd_smb2_request *smb2_req;
1370 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1372 TALLOC_CTX *mem_ctx,
1373 struct iovec **_vector,
1375 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
1377 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
1378 struct tevent_context *ev,
1379 struct smbd_server_connection *sconn)
1381 struct tevent_req *req;
1382 struct smbd_smb2_request_read_state *state;
1383 struct tevent_req *subreq;
1385 req = tevent_req_create(mem_ctx, &state,
1386 struct smbd_smb2_request_read_state);
1391 state->asked_for_header = false;
1393 state->smb2_req = smbd_smb2_request_allocate(state);
1394 if (tevent_req_nomem(state->smb2_req, req)) {
1395 return tevent_req_post(req, ev);
1397 state->smb2_req->sconn = sconn;
1399 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
1400 sconn->smb2.recv_queue,
1401 smbd_smb2_request_next_vector,
1403 if (tevent_req_nomem(subreq, req)) {
1404 return tevent_req_post(req, ev);
1406 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
1411 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1413 TALLOC_CTX *mem_ctx,
1414 struct iovec **_vector,
1417 struct smbd_smb2_request_read_state *state =
1418 talloc_get_type_abort(private_data,
1419 struct smbd_smb2_request_read_state);
1420 struct smbd_smb2_request *req = state->smb2_req;
1421 struct iovec *vector;
1422 int idx = req->in.vector_count;
1424 uint8_t *buf = NULL;
1426 if (req->in.vector_count == 0) {
1428 * first we need to get the NBT header
1430 req->in.vector = talloc_array(req, struct iovec,
1431 req->in.vector_count + 1);
1432 if (req->in.vector == NULL) {
1435 req->in.vector_count += 1;
1437 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
1438 req->in.vector[idx].iov_len = 4;
1440 vector = talloc_array(mem_ctx, struct iovec, 1);
1441 if (vector == NULL) {
1445 vector[0] = req->in.vector[idx];
1452 if (req->in.vector_count == 1) {
1454 * Now we analyze the NBT header
1456 state->missing = smb2_len(req->in.vector[0].iov_base);
1458 if (state->missing == 0) {
1459 /* if there're no remaining bytes, we're done */
1465 req->in.vector = talloc_realloc(req, req->in.vector,
1467 req->in.vector_count + 1);
1468 if (req->in.vector == NULL) {
1471 req->in.vector_count += 1;
1473 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
1475 * it's a special NBT message,
1476 * so get all remaining bytes
1478 len = state->missing;
1479 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
1481 * it's an invalid message, just read what we can get
1482 * and let the caller handle the error
1484 len = state->missing;
1487 * We assume it's a SMB2 request,
1488 * and we first get the header and the
1489 * first 2 bytes (the struct size) of the body
1491 len = SMB2_HDR_BODY + 2;
1493 state->asked_for_header = true;
1496 state->missing -= len;
1498 buf = talloc_array(req->in.vector, uint8_t, len);
1503 req->in.vector[idx].iov_base = (void *)buf;
1504 req->in.vector[idx].iov_len = len;
1506 vector = talloc_array(mem_ctx, struct iovec, 1);
1507 if (vector == NULL) {
1511 vector[0] = req->in.vector[idx];
1518 if (state->missing == 0) {
1519 /* if there're no remaining bytes, we're done */
1525 if (state->asked_for_header) {
1528 size_t next_command_ofs;
1533 bool invalid = false;
1535 state->asked_for_header = false;
1538 * We got the SMB2 header and the first 2 bytes
1539 * of the body. We fix the size to just the header
1540 * and manually copy the 2 first bytes to the body section
1542 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
1543 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
1545 /* allocate vectors for body and dynamic areas */
1546 req->in.vector = talloc_realloc(req, req->in.vector,
1548 req->in.vector_count + 2);
1549 if (req->in.vector == NULL) {
1552 req->in.vector_count += 2;
1554 full_size = state->missing + SMB2_HDR_BODY + 2;
1555 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
1556 body_size = SVAL(hdr, SMB2_HDR_BODY);
1558 if (next_command_ofs != 0) {
1559 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
1561 * this is invalid, just return a zero
1562 * body and let the caller deal with the error
1565 } else if (next_command_ofs > full_size) {
1567 * this is invalid, just return a zero
1568 * body and let the caller deal with the error
1572 full_size = next_command_ofs;
1577 if (body_size < 2) {
1579 * this is invalid, just return a zero
1580 * body and let the caller deal with the error
1585 if ((body_size % 2) != 0) {
1589 if (body_size > (full_size - SMB2_HDR_BODY)) {
1591 * this is invalid, just return a zero
1592 * body and let the caller deal with the error
1599 /* the caller should check this */
1603 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
1605 state->missing -= (body_size - 2) + dyn_size;
1607 body = talloc_array(req->in.vector, uint8_t, body_size);
1612 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
1617 req->in.vector[idx].iov_base = (void *)body;
1618 req->in.vector[idx].iov_len = body_size;
1619 req->in.vector[idx+1].iov_base = (void *)dyn;
1620 req->in.vector[idx+1].iov_len = dyn_size;
1622 vector = talloc_array(mem_ctx, struct iovec, 2);
1623 if (vector == NULL) {
1628 * the first 2 bytes of the body were already fetched
1629 * together with the header
1631 memcpy(body, hdr + SMB2_HDR_BODY, 2);
1632 vector[0].iov_base = body + 2;
1633 vector[0].iov_len = body_size - 2;
1635 vector[1] = req->in.vector[idx+1];
1643 * when we endup here, we're looking for a new SMB2 request
1644 * next. And we ask for its header and the first 2 bytes of
1645 * the body (like we did for the first SMB2 request).
1648 req->in.vector = talloc_realloc(req, req->in.vector,
1650 req->in.vector_count + 1);
1651 if (req->in.vector == NULL) {
1654 req->in.vector_count += 1;
1657 * We assume it's a SMB2 request,
1658 * and we first get the header and the
1659 * first 2 bytes (the struct size) of the body
1661 len = SMB2_HDR_BODY + 2;
1663 if (len > state->missing) {
1664 /* let the caller handle the error */
1665 len = state->missing;
1668 state->missing -= len;
1669 state->asked_for_header = true;
1671 buf = talloc_array(req->in.vector, uint8_t, len);
1676 req->in.vector[idx].iov_base = (void *)buf;
1677 req->in.vector[idx].iov_len = len;
1679 vector = talloc_array(mem_ctx, struct iovec, 1);
1680 if (vector == NULL) {
1684 vector[0] = req->in.vector[idx];
1691 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
1693 struct tevent_req *req =
1694 tevent_req_callback_data(subreq,
1700 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
1702 status = map_nt_error_from_unix(sys_errno);
1703 tevent_req_nterror(req, status);
1707 tevent_req_done(req);
1710 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
1711 TALLOC_CTX *mem_ctx,
1712 struct smbd_smb2_request **_smb2_req)
1714 struct smbd_smb2_request_read_state *state =
1715 tevent_req_data(req,
1716 struct smbd_smb2_request_read_state);
1719 if (tevent_req_is_nterror(req, &status)) {
1720 tevent_req_received(req);
1724 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
1725 *_smb2_req = state->smb2_req;
1726 tevent_req_received(req);
1727 return NT_STATUS_OK;
1730 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
1732 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
1733 const uint8_t *inbuf, size_t size)
1736 struct smbd_smb2_request *req;
1737 struct tevent_req *subreq;
1739 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
1740 (unsigned int)size));
1742 status = smbd_initialize_smb2(sconn);
1743 if (!NT_STATUS_IS_OK(status)) {
1744 smbd_server_connection_terminate(sconn, nt_errstr(status));
1748 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
1749 if (!NT_STATUS_IS_OK(status)) {
1750 smbd_server_connection_terminate(sconn, nt_errstr(status));
1754 status = smbd_smb2_request_setup_out(req, (uint16_t)lp_maxmux());
1755 if (!NT_STATUS_IS_OK(status)) {
1756 smbd_server_connection_terminate(sconn, nt_errstr(status));
1760 status = smbd_smb2_request_dispatch(req);
1761 if (!NT_STATUS_IS_OK(status)) {
1762 smbd_server_connection_terminate(sconn, nt_errstr(status));
1766 /* ask for the next request */
1767 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
1768 if (subreq == NULL) {
1769 smbd_server_connection_terminate(sconn, "no memory for reading");
1772 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
1775 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
1777 uint16_t creds_requested = 0;
1778 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
1779 struct smbd_server_connection);
1781 struct smbd_smb2_request *req = NULL;
1783 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
1784 TALLOC_FREE(subreq);
1785 if (!NT_STATUS_IS_OK(status)) {
1786 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
1787 nt_errstr(status)));
1788 smbd_server_connection_terminate(sconn, nt_errstr(status));
1792 if (req->in.nbt_hdr[0] != 0x00) {
1793 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
1794 req->in.nbt_hdr[0]));
1799 req->current_idx = 1;
1801 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
1802 req->current_idx, req->in.vector_count));
1804 status = smbd_smb2_request_validate(req, &creds_requested);
1805 if (!NT_STATUS_IS_OK(status)) {
1806 smbd_server_connection_terminate(sconn, nt_errstr(status));
1810 status = smbd_smb2_request_setup_out(req, 5);
1811 if (!NT_STATUS_IS_OK(status)) {
1812 smbd_server_connection_terminate(sconn, nt_errstr(status));
1816 status = smbd_smb2_request_dispatch(req);
1817 if (!NT_STATUS_IS_OK(status)) {
1818 smbd_server_connection_terminate(sconn, nt_errstr(status));
1823 /* ask for the next request (this constructs the main loop) */
1824 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
1825 if (subreq == NULL) {
1826 smbd_server_connection_terminate(sconn, "no memory for reading");
1829 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);