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"
30 #include "../librpc/gen_ndr/krb5pac.h"
31 #include "lib/util/iov_buf.h"
34 static void smbd_smb2_connection_handler(struct tevent_context *ev,
35 struct tevent_fd *fde,
38 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn);
40 static const struct smbd_smb2_dispatch_table {
47 bool allow_invalid_fileid;
48 } smbd_smb2_table[] = {
49 #define _OP(o) .opcode = o, .name = #o
54 _OP(SMB2_OP_SESSSETUP),
64 * This call needs to be run as root.
66 * smbd_smb2_request_process_tcon()
67 * calls make_connection_snum(), which will call
68 * change_to_user(), when needed.
102 .need_session = true,
107 .need_session = true,
110 .allow_invalid_fileid = true,
115 _OP(SMB2_OP_KEEPALIVE),
119 .need_session = true,
124 .need_session = true,
128 _OP(SMB2_OP_GETINFO),
129 .need_session = true,
133 _OP(SMB2_OP_SETINFO),
134 .need_session = true,
139 .need_session = true,
144 * as LEASE breaks does not
150 const char *smb2_opcode_name(uint16_t opcode)
152 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
153 return "Bad SMB2 opcode";
155 return smbd_smb2_table[opcode].name;
158 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
160 const struct smbd_smb2_dispatch_table *ret = NULL;
162 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
166 ret = &smbd_smb2_table[opcode];
168 SMB_ASSERT(ret->opcode == opcode);
173 static void print_req_vectors(const struct smbd_smb2_request *req)
177 for (i = 0; i < req->in.vector_count; i++) {
178 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
180 (unsigned int)req->in.vector[i].iov_len);
182 for (i = 0; i < req->out.vector_count; i++) {
183 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
185 (unsigned int)req->out.vector[i].iov_len);
189 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
191 if (size < (4 + SMB2_HDR_BODY)) {
195 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
202 static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn)
204 TALLOC_FREE(xconn->transport.fde);
206 xconn->smb2.credits.seq_low = 0;
207 xconn->smb2.credits.seq_range = 1;
208 xconn->smb2.credits.granted = 1;
209 xconn->smb2.credits.max = lp_smb2_max_credits();
210 xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
211 xconn->smb2.credits.max);
212 if (xconn->smb2.credits.bitmap == NULL) {
213 return NT_STATUS_NO_MEMORY;
216 xconn->transport.fde = tevent_add_fd(xconn->ev_ctx,
218 xconn->transport.sock,
220 smbd_smb2_connection_handler,
222 if (xconn->transport.fde == NULL) {
223 return NT_STATUS_NO_MEMORY;
226 /* Ensure child is set to non-blocking mode */
227 set_blocking(xconn->transport.sock, false);
231 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
232 #define _smb2_setlen(_buf,len) do { \
233 uint8_t *buf = (uint8_t *)_buf; \
235 buf[1] = ((len)&0xFF0000)>>16; \
236 buf[2] = ((len)&0xFF00)>>8; \
237 buf[3] = (len)&0xFF; \
240 static void smb2_setup_nbt_length(struct iovec *vector, int count)
245 for (i=1; i < count; i++) {
246 len += vector[i].iov_len;
249 _smb2_setlen(vector[0].iov_base, len);
252 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
254 if (req->first_key.length > 0) {
255 data_blob_clear_free(&req->first_key);
257 if (req->last_key.length > 0) {
258 data_blob_clear_free(&req->last_key);
263 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
265 TALLOC_CTX *mem_pool;
266 struct smbd_smb2_request *req;
269 /* Enable this to find subtle valgrind errors. */
270 mem_pool = talloc_init("smbd_smb2_request_allocate");
272 mem_pool = talloc_tos();
274 if (mem_pool == NULL) {
278 req = talloc_zero(mem_pool, struct smbd_smb2_request);
280 talloc_free(mem_pool);
283 talloc_reparent(mem_pool, mem_ctx, req);
285 TALLOC_FREE(mem_pool);
288 req->last_session_id = UINT64_MAX;
289 req->last_tid = UINT32_MAX;
291 talloc_set_destructor(req, smbd_smb2_request_destructor);
296 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
300 struct smbd_smb2_request *req,
304 TALLOC_CTX *mem_ctx = req;
308 uint8_t *first_hdr = buf;
309 size_t verified_buflen = 0;
314 * Note: index '0' is reserved for the transport protocol
316 iov = req->in._vector;
318 while (taken < buflen) {
319 size_t len = buflen - taken;
320 uint8_t *hdr = first_hdr + taken;
323 size_t next_command_ofs;
325 uint8_t *body = NULL;
328 struct iovec *iov_alloc = NULL;
330 if (iov != req->in._vector) {
334 if (verified_buflen > taken) {
335 len = verified_buflen - taken;
342 DEBUG(10, ("%d bytes left, expected at least %d\n",
346 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
347 struct smbXsrv_session *s = NULL;
349 struct iovec tf_iov[2];
353 if (xconn->protocol < PROTOCOL_SMB2_24) {
354 DEBUG(10, ("Got SMB2_TRANSFORM header, "
355 "but dialect[0x%04X] is used\n",
356 xconn->smb2.server.dialect));
360 if (xconn->smb2.server.cipher == 0) {
361 DEBUG(10, ("Got SMB2_TRANSFORM header, "
362 "but not negotiated "
363 "client[0x%08X] server[0x%08X]\n",
364 xconn->smb2.client.capabilities,
365 xconn->smb2.server.capabilities));
369 if (len < SMB2_TF_HDR_SIZE) {
370 DEBUG(1, ("%d bytes left, expected at least %d\n",
371 (int)len, SMB2_TF_HDR_SIZE));
375 tf_len = SMB2_TF_HDR_SIZE;
378 hdr = first_hdr + taken;
379 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
380 uid = BVAL(tf, SMB2_TF_SESSION_ID);
382 if (len < SMB2_TF_HDR_SIZE + enc_len) {
383 DEBUG(1, ("%d bytes left, expected at least %d\n",
385 (int)(SMB2_TF_HDR_SIZE + enc_len)));
389 status = smb2srv_session_lookup(xconn, uid, now, &s);
391 DEBUG(1, ("invalid session[%llu] in "
392 "SMB2_TRANSFORM header\n",
393 (unsigned long long)uid));
394 TALLOC_FREE(iov_alloc);
395 return NT_STATUS_USER_SESSION_DELETED;
398 tf_iov[0].iov_base = (void *)tf;
399 tf_iov[0].iov_len = tf_len;
400 tf_iov[1].iov_base = (void *)hdr;
401 tf_iov[1].iov_len = enc_len;
403 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
404 xconn->smb2.server.cipher,
406 if (!NT_STATUS_IS_OK(status)) {
407 TALLOC_FREE(iov_alloc);
411 verified_buflen = taken + enc_len;
416 * We need the header plus the body length field
419 if (len < SMB2_HDR_BODY + 2) {
420 DEBUG(10, ("%d bytes left, expected at least %d\n",
421 (int)len, SMB2_HDR_BODY));
424 if (IVAL(hdr, 0) != SMB2_MAGIC) {
425 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
429 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
430 DEBUG(10, ("Got HDR len %d, expected %d\n",
431 SVAL(hdr, 4), SMB2_HDR_BODY));
436 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
437 body_size = SVAL(hdr, SMB2_HDR_BODY);
439 if (next_command_ofs != 0) {
440 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
443 if (next_command_ofs > full_size) {
446 full_size = next_command_ofs;
453 if (body_size > (full_size - SMB2_HDR_BODY)) {
455 * let the caller handle the error
457 body_size = full_size - SMB2_HDR_BODY;
459 body = hdr + SMB2_HDR_BODY;
460 dyn = body + body_size;
461 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
463 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
464 struct iovec *iov_tmp = NULL;
466 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
469 SMBD_SMB2_NUM_IOV_PER_REQ);
470 if (iov_tmp == NULL) {
471 TALLOC_FREE(iov_alloc);
472 return NT_STATUS_NO_MEMORY;
475 if (iov_alloc == NULL) {
478 sizeof(req->in._vector));
484 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
486 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
487 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
488 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
489 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
490 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
491 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
492 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
493 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
503 if (iov != req->in._vector) {
506 return NT_STATUS_INVALID_PARAMETER;
509 static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
510 const uint8_t *_inpdu, size_t size,
511 struct smbd_smb2_request **_req)
513 struct smbd_server_connection *sconn = xconn->client->sconn;
514 struct smbd_smb2_request *req;
515 uint32_t protocol_version;
516 uint8_t *inpdu = NULL;
517 const uint8_t *inhdr = NULL;
519 uint32_t next_command_ofs;
523 if (size < (SMB2_HDR_BODY + 2)) {
524 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
525 return NT_STATUS_INVALID_PARAMETER;
530 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
531 if (protocol_version != SMB2_MAGIC) {
532 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
534 return NT_STATUS_INVALID_PARAMETER;
537 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
538 if (cmd != SMB2_OP_NEGPROT) {
539 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
541 return NT_STATUS_INVALID_PARAMETER;
544 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
545 if (next_command_ofs != 0) {
546 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
548 return NT_STATUS_INVALID_PARAMETER;
551 req = smbd_smb2_request_allocate(xconn);
553 return NT_STATUS_NO_MEMORY;
558 inpdu = talloc_memdup(req, _inpdu, size);
560 return NT_STATUS_NO_MEMORY;
563 req->request_time = timeval_current();
564 now = timeval_to_nttime(&req->request_time);
566 status = smbd_smb2_inbuf_parse_compound(xconn,
570 req, &req->in.vector,
571 &req->in.vector_count);
572 if (!NT_STATUS_IS_OK(status)) {
577 req->current_idx = 1;
583 static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
584 uint64_t message_id, uint64_t seq_id)
586 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
590 seq_tmp = xconn->smb2.credits.seq_low;
591 if (seq_id < seq_tmp) {
592 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
593 "%llu (sequence id %llu) "
594 "(granted = %u, low = %llu, range = %u)\n",
595 (unsigned long long)message_id,
596 (unsigned long long)seq_id,
597 (unsigned int)xconn->smb2.credits.granted,
598 (unsigned long long)xconn->smb2.credits.seq_low,
599 (unsigned int)xconn->smb2.credits.seq_range));
603 seq_tmp += xconn->smb2.credits.seq_range;
604 if (seq_id >= seq_tmp) {
605 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
606 "%llu (sequence id %llu) "
607 "(granted = %u, low = %llu, range = %u)\n",
608 (unsigned long long)message_id,
609 (unsigned long long)seq_id,
610 (unsigned int)xconn->smb2.credits.granted,
611 (unsigned long long)xconn->smb2.credits.seq_low,
612 (unsigned int)xconn->smb2.credits.seq_range));
616 offset = seq_id % xconn->smb2.credits.max;
618 if (bitmap_query(credits_bm, offset)) {
619 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
620 "%llu (sequence id %llu) "
621 "(granted = %u, low = %llu, range = %u) "
623 (unsigned long long)message_id,
624 (unsigned long long)seq_id,
625 (unsigned int)xconn->smb2.credits.granted,
626 (unsigned long long)xconn->smb2.credits.seq_low,
627 (unsigned int)xconn->smb2.credits.seq_range,
632 /* Mark the message_ids as seen in the bitmap. */
633 bitmap_set(credits_bm, offset);
635 if (seq_id != xconn->smb2.credits.seq_low) {
640 * Move the window forward by all the message_id's
643 while (bitmap_query(credits_bm, offset)) {
644 DEBUG(10,("smb2_validate_sequence_number: clearing "
645 "id %llu (position %u) from bitmap\n",
646 (unsigned long long)(xconn->smb2.credits.seq_low),
648 bitmap_clear(credits_bm, offset);
650 xconn->smb2.credits.seq_low += 1;
651 xconn->smb2.credits.seq_range -= 1;
652 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
658 static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
659 const uint8_t *inhdr)
661 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
662 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
663 uint16_t credit_charge = 1;
666 if (opcode == SMB2_OP_CANCEL) {
667 /* SMB2_CANCEL requests by definition resend messageids. */
671 if (xconn->smb2.credits.multicredit) {
672 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
673 credit_charge = MAX(credit_charge, 1);
676 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
677 "credits_granted %llu, "
678 "seqnum low/range: %llu/%llu\n",
679 (unsigned long long) message_id,
680 (unsigned long long) credit_charge,
681 (unsigned long long) xconn->smb2.credits.granted,
682 (unsigned long long) xconn->smb2.credits.seq_low,
683 (unsigned long long) xconn->smb2.credits.seq_range));
685 if (xconn->smb2.credits.granted < credit_charge) {
686 DEBUG(0, ("smb2_validate_message_id: client used more "
687 "credits than granted, mid %llu, charge %llu, "
688 "credits_granted %llu, "
689 "seqnum low/range: %llu/%llu\n",
690 (unsigned long long) message_id,
691 (unsigned long long) credit_charge,
692 (unsigned long long) xconn->smb2.credits.granted,
693 (unsigned long long) xconn->smb2.credits.seq_low,
694 (unsigned long long) xconn->smb2.credits.seq_range));
699 * now check the message ids
701 * for multi-credit requests we need to check all current mid plus
702 * the implicit mids caused by the credit charge
703 * e.g. current mid = 15, charge 5 => mark 15-19 as used
706 for (i = 0; i <= (credit_charge-1); i++) {
707 uint64_t id = message_id + i;
710 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
711 (unsigned long long)message_id,
713 (unsigned long long)id));
715 ok = smb2_validate_sequence_number(xconn, message_id, id);
721 /* substract used credits */
722 xconn->smb2.credits.granted -= credit_charge;
727 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
732 count = req->in.vector_count;
734 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
735 /* It's not a SMB2 request */
736 return NT_STATUS_INVALID_PARAMETER;
739 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
740 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
741 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
742 const uint8_t *inhdr = NULL;
744 if (hdr->iov_len != SMB2_HDR_BODY) {
745 return NT_STATUS_INVALID_PARAMETER;
748 if (body->iov_len < 2) {
749 return NT_STATUS_INVALID_PARAMETER;
752 inhdr = (const uint8_t *)hdr->iov_base;
754 /* Check the SMB2 header */
755 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
756 return NT_STATUS_INVALID_PARAMETER;
759 if (!smb2_validate_message_id(req->xconn, inhdr)) {
760 return NT_STATUS_INVALID_PARAMETER;
767 static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
768 const struct iovec *in_vector,
769 struct iovec *out_vector)
771 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
772 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
773 uint16_t credit_charge = 1;
774 uint16_t credits_requested;
778 uint16_t credits_granted = 0;
779 uint64_t credits_possible;
780 uint16_t current_max_credits;
783 * first we grant only 1/16th of the max range.
785 * Windows also starts with the 1/16th and then grants
786 * more later. I was only able to trigger higher
787 * values, when using a very high credit charge.
789 * TODO: scale up depending on load, free memory
791 * Maybe also on the relationship between number
792 * of requests and the used sequence number.
793 * Which means we would grant more credits
794 * for client which use multi credit requests.
796 current_max_credits = xconn->smb2.credits.max / 16;
797 current_max_credits = MAX(current_max_credits, 1);
799 if (xconn->smb2.credits.multicredit) {
800 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
801 credit_charge = MAX(credit_charge, 1);
804 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
805 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
806 credits_requested = MAX(credits_requested, 1);
807 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
808 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
810 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
812 if (xconn->smb2.credits.max < credit_charge) {
813 smbd_server_connection_terminate(xconn,
814 "client error: credit charge > max credits\n");
818 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
820 * In case we already send an async interim
821 * response, we should not grant
822 * credits on the final response.
826 uint16_t additional_possible =
827 xconn->smb2.credits.max - credit_charge;
828 uint16_t additional_max = 0;
829 uint16_t additional_credits = credits_requested - 1;
832 case SMB2_OP_NEGPROT:
834 case SMB2_OP_SESSSETUP:
836 * Windows 2012 RC1 starts to grant
838 * with a successful session setup
840 if (NT_STATUS_IS_OK(out_status)) {
846 * We match windows and only grant additional credits
853 additional_max = MIN(additional_max, additional_possible);
854 additional_credits = MIN(additional_credits, additional_max);
856 credits_granted = credit_charge + additional_credits;
860 * sequence numbers should not wrap
862 * 1. calculate the possible credits until
863 * the sequence numbers start to wrap on 64-bit.
865 * 2. UINT64_MAX is used for Break Notifications.
867 * 2. truncate the possible credits to the maximum
868 * credits we want to grant to the client in total.
870 * 3. remove the range we'll already granted to the client
871 * this makes sure the client consumes the lowest sequence
872 * number, before we can grant additional credits.
874 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
875 if (credits_possible > 0) {
876 /* remove UINT64_MAX */
877 credits_possible -= 1;
879 credits_possible = MIN(credits_possible, current_max_credits);
880 credits_possible -= xconn->smb2.credits.seq_range;
882 credits_granted = MIN(credits_granted, credits_possible);
884 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
885 xconn->smb2.credits.granted += credits_granted;
886 xconn->smb2.credits.seq_range += credits_granted;
888 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
889 "granted %u, current possible/max %u/%u, "
890 "total granted/max/low/range %u/%u/%llu/%u\n",
891 (unsigned int)credits_requested,
892 (unsigned int)credit_charge,
893 (unsigned int)credits_granted,
894 (unsigned int)credits_possible,
895 (unsigned int)current_max_credits,
896 (unsigned int)xconn->smb2.credits.granted,
897 (unsigned int)xconn->smb2.credits.max,
898 (unsigned long long)xconn->smb2.credits.seq_low,
899 (unsigned int)xconn->smb2.credits.seq_range));
902 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
903 struct smbd_smb2_request *outreq)
906 uint16_t total_credits = 0;
908 count = outreq->out.vector_count;
910 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
911 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
912 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
913 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
915 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
917 /* To match Windows, count up what we
919 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
920 /* Set to zero in all but the last reply. */
921 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
922 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
924 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
929 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
931 if (req->current_idx <= 1) {
932 if (size <= sizeof(req->out._body)) {
933 return data_blob_const(req->out._body, size);
937 return data_blob_talloc(req, NULL, size);
940 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
942 struct smbXsrv_connection *xconn = req->xconn;
944 struct iovec *vector;
948 count = req->in.vector_count;
949 if (count <= ARRAY_SIZE(req->out._vector)) {
951 vector = req->out._vector;
953 vector = talloc_zero_array(req, struct iovec, count);
954 if (vector == NULL) {
955 return NT_STATUS_NO_MEMORY;
960 vector[0].iov_base = req->out.nbt_hdr;
961 vector[0].iov_len = 4;
962 SIVAL(req->out.nbt_hdr, 0, 0);
964 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
965 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
966 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
967 uint8_t *outhdr = NULL;
968 uint8_t *outbody = NULL;
969 uint32_t next_command_ofs = 0;
970 struct iovec *current = &vector[idx];
972 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
973 /* we have a next command -
974 * setup for the error case. */
975 next_command_ofs = SMB2_HDR_BODY + 9;
979 outhdr = req->out._hdr;
981 outhdr = talloc_zero_array(mem_ctx, uint8_t,
983 if (outhdr == NULL) {
984 return NT_STATUS_NO_MEMORY;
988 outbody = outhdr + SMB2_HDR_BODY;
991 * SMBD_SMB2_TF_IOV_OFS might be used later
993 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
994 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
996 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
997 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
999 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1000 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1002 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1003 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1005 /* setup the SMB2 header */
1006 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1007 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1008 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1009 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1010 SIVAL(outhdr, SMB2_HDR_STATUS,
1011 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1012 SSVAL(outhdr, SMB2_HDR_OPCODE,
1013 SVAL(inhdr, SMB2_HDR_OPCODE));
1014 SIVAL(outhdr, SMB2_HDR_FLAGS,
1015 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1016 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1017 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1018 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1019 SIVAL(outhdr, SMB2_HDR_PID,
1020 IVAL(inhdr, SMB2_HDR_PID));
1021 SIVAL(outhdr, SMB2_HDR_TID,
1022 IVAL(inhdr, SMB2_HDR_TID));
1023 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1024 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1025 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1026 inhdr + SMB2_HDR_SIGNATURE, 16);
1028 /* setup error body header */
1029 SSVAL(outbody, 0x00, 0x08 + 1);
1030 SSVAL(outbody, 0x02, 0);
1031 SIVAL(outbody, 0x04, 0);
1034 req->out.vector = vector;
1035 req->out.vector_count = count;
1037 /* setup the length of the NBT packet */
1038 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1040 DLIST_ADD_END(xconn->smb2.requests, req, struct smbd_smb2_request *);
1042 return NT_STATUS_OK;
1045 void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
1047 const char *location)
1049 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1051 exit_server_cleanly(reason);
1054 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1055 struct iovec *outvec,
1056 const struct iovec *srcvec)
1058 const uint8_t *srctf;
1060 const uint8_t *srchdr;
1062 const uint8_t *srcbody;
1064 const uint8_t *expected_srcbody;
1065 const uint8_t *srcdyn;
1067 const uint8_t *expected_srcdyn;
1073 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1074 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1075 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1076 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1077 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1078 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1079 expected_srcbody = srchdr + SMB2_HDR_BODY;
1080 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1081 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1082 expected_srcdyn = srcbody + 8;
1084 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1088 if (srchdr_len != SMB2_HDR_BODY) {
1092 if (srctf_len == SMB2_TF_HDR_SIZE) {
1093 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1094 if (dsttf == NULL) {
1100 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1101 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1103 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1104 * be allocated with size OUTVEC_ALLOC_SIZE. */
1106 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1107 if (dsthdr == NULL) {
1110 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1111 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1114 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1115 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1116 * then duplicate this. Else use talloc_memdup().
1119 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1120 dstbody = dsthdr + SMB2_HDR_BODY;
1122 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1123 if (dstbody == NULL) {
1127 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1128 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1131 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1133 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1134 * then duplicate this. Else use talloc_memdup().
1137 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1138 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1139 } else if (srcdyn == NULL) {
1142 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1143 if (dstdyn == NULL) {
1147 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1148 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1153 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1155 struct smbd_smb2_request *newreq = NULL;
1156 struct iovec *outvec = NULL;
1157 int count = req->out.vector_count;
1160 newreq = smbd_smb2_request_allocate(req->xconn);
1165 newreq->sconn = req->sconn;
1166 newreq->xconn = req->xconn;
1167 newreq->session = req->session;
1168 newreq->do_encryption = req->do_encryption;
1169 newreq->do_signing = req->do_signing;
1170 newreq->current_idx = req->current_idx;
1172 outvec = talloc_zero_array(newreq, struct iovec, count);
1174 TALLOC_FREE(newreq);
1177 newreq->out.vector = outvec;
1178 newreq->out.vector_count = count;
1180 /* Setup the outvec's identically to req. */
1181 outvec[0].iov_base = newreq->out.nbt_hdr;
1182 outvec[0].iov_len = 4;
1183 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1185 /* Setup the vectors identically to the ones in req. */
1186 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1187 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1194 TALLOC_FREE(newreq);
1198 smb2_setup_nbt_length(newreq->out.vector,
1199 newreq->out.vector_count);
1204 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1206 struct smbXsrv_connection *xconn = req->xconn;
1208 struct iovec *firsttf = NULL;
1209 struct iovec *outhdr_v = NULL;
1210 uint8_t *outhdr = NULL;
1211 struct smbd_smb2_request *nreq = NULL;
1214 /* Create a new smb2 request we'll use
1215 for the interim return. */
1216 nreq = dup_smb2_req(req);
1218 return NT_STATUS_NO_MEMORY;
1221 /* Lose the last X out vectors. They're the
1222 ones we'll be using for the async reply. */
1223 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1225 smb2_setup_nbt_length(nreq->out.vector,
1226 nreq->out.vector_count);
1228 /* Step back to the previous reply. */
1229 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1230 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1231 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1232 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1233 /* And end the chain. */
1234 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1236 /* Calculate outgoing credits */
1237 smb2_calculate_credits(req, nreq);
1239 if (DEBUGLEVEL >= 10) {
1240 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1241 (unsigned int)nreq->current_idx );
1242 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1243 (unsigned int)nreq->out.vector_count );
1244 print_req_vectors(nreq);
1248 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1249 * we need to sign/encrypt here with the last/first key we remembered
1251 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1252 status = smb2_signing_encrypt_pdu(req->first_key,
1253 xconn->smb2.server.cipher,
1255 nreq->out.vector_count - first_idx);
1256 if (!NT_STATUS_IS_OK(status)) {
1259 } else if (req->last_key.length > 0) {
1260 status = smb2_signing_sign_pdu(req->last_key,
1263 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1264 if (!NT_STATUS_IS_OK(status)) {
1269 nreq->queue_entry.mem_ctx = nreq;
1270 nreq->queue_entry.vector = nreq->out.vector;
1271 nreq->queue_entry.count = nreq->out.vector_count;
1272 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry, NULL);
1273 xconn->smb2.send_queue_len++;
1275 status = smbd_smb2_flush_send_queue(xconn);
1276 if (!NT_STATUS_IS_OK(status)) {
1280 return NT_STATUS_OK;
1283 struct smbd_smb2_request_pending_state {
1284 struct smbd_smb2_send_queue queue_entry;
1285 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1286 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1289 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1290 struct tevent_timer *te,
1291 struct timeval current_time,
1292 void *private_data);
1294 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1295 struct tevent_req *subreq,
1296 uint32_t defer_time)
1299 struct timeval defer_endtime;
1300 uint8_t *outhdr = NULL;
1303 if (!tevent_req_is_in_progress(subreq)) {
1305 * This is a performance optimization,
1306 * it avoids one tevent_loop iteration,
1307 * which means we avoid one
1308 * talloc_stackframe_pool/talloc_free pair.
1310 tevent_req_notify_callback(subreq);
1311 return NT_STATUS_OK;
1314 req->subreq = subreq;
1317 if (req->async_te) {
1318 /* We're already async. */
1319 return NT_STATUS_OK;
1322 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1323 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1324 if (flags & SMB2_HDR_FLAG_ASYNC) {
1325 /* We're already async. */
1326 return NT_STATUS_OK;
1329 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1331 * We're trying to go async in a compound
1333 * This is only allowed for opens that
1334 * cause an oplock break, otherwise it
1335 * is not allowed. See [MS-SMB2].pdf
1336 * note <194> on Section 3.3.5.2.7.
1338 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1340 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1342 * Cancel the outstanding request.
1344 bool ok = tevent_req_cancel(req->subreq);
1346 return NT_STATUS_OK;
1348 TALLOC_FREE(req->subreq);
1349 return smbd_smb2_request_error(req,
1350 NT_STATUS_INTERNAL_ERROR);
1354 if (DEBUGLEVEL >= 10) {
1355 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1356 (unsigned int)req->current_idx );
1357 print_req_vectors(req);
1360 if (req->current_idx > 1) {
1362 * We're going async in a compound
1363 * chain after the first request has
1364 * already been processed. Send an
1365 * interim response containing the
1366 * set of replies already generated.
1368 int idx = req->current_idx;
1370 status = smb2_send_async_interim_response(req);
1371 if (!NT_STATUS_IS_OK(status)) {
1374 if (req->first_key.length > 0) {
1375 data_blob_clear_free(&req->first_key);
1378 req->current_idx = 1;
1381 * Re-arrange the in.vectors to remove what
1384 memmove(&req->in.vector[1],
1385 &req->in.vector[idx],
1386 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1387 req->in.vector_count = 1 + (req->in.vector_count - idx);
1389 /* Re-arrange the out.vectors to match. */
1390 memmove(&req->out.vector[1],
1391 &req->out.vector[idx],
1392 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1393 req->out.vector_count = 1 + (req->out.vector_count - idx);
1395 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1397 * We only have one remaining request as
1398 * we've processed everything else.
1399 * This is no longer a compound request.
1401 req->compound_related = false;
1402 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1403 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1404 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1407 if (req->last_key.length > 0) {
1408 data_blob_clear_free(&req->last_key);
1411 defer_endtime = timeval_current_ofs_usec(defer_time);
1412 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1414 smbd_smb2_request_pending_timer,
1416 if (req->async_te == NULL) {
1417 return NT_STATUS_NO_MEMORY;
1420 return NT_STATUS_OK;
1423 static DATA_BLOB smbd_smb2_signing_key(struct smbXsrv_session *session,
1424 struct smbXsrv_connection *xconn)
1426 struct smbXsrv_channel_global0 *c = NULL;
1428 DATA_BLOB key = data_blob_null;
1430 status = smbXsrv_session_find_channel(session, xconn, &c);
1431 if (NT_STATUS_IS_OK(status)) {
1432 key = c->signing_key;
1435 if (key.length == 0) {
1436 key = session->global->signing_key;
1442 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1443 struct tevent_timer *te,
1444 struct timeval current_time,
1447 struct smbd_smb2_request *req =
1448 talloc_get_type_abort(private_data,
1449 struct smbd_smb2_request);
1450 struct smbXsrv_connection *xconn = req->xconn;
1451 struct smbd_smb2_request_pending_state *state = NULL;
1452 uint8_t *outhdr = NULL;
1453 const uint8_t *inhdr = NULL;
1456 uint8_t *hdr = NULL;
1457 uint8_t *body = NULL;
1458 uint8_t *dyn = NULL;
1460 uint64_t session_id = 0;
1461 uint64_t message_id = 0;
1462 uint64_t nonce_high = 0;
1463 uint64_t nonce_low = 0;
1464 uint64_t async_id = 0;
1467 TALLOC_FREE(req->async_te);
1469 /* Ensure our final reply matches the interim one. */
1470 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1471 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1472 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1473 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1474 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1476 async_id = message_id; /* keep it simple for now... */
1478 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1479 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1481 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1483 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1484 (unsigned long long)async_id ));
1487 * What we send is identical to a smbd_smb2_request_error
1488 * packet with an error status of STATUS_PENDING. Make use
1489 * of this fact sometime when refactoring. JRA.
1492 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
1493 if (state == NULL) {
1494 smbd_server_connection_terminate(xconn,
1495 nt_errstr(NT_STATUS_NO_MEMORY));
1499 tf = state->buf + NBT_HDR_SIZE;
1500 tf_len = SMB2_TF_HDR_SIZE;
1502 hdr = tf + SMB2_TF_HDR_SIZE;
1503 body = hdr + SMB2_HDR_BODY;
1506 if (req->do_encryption) {
1507 struct smbXsrv_session *x = req->session;
1509 nonce_high = x->nonce_high;
1510 nonce_low = x->nonce_low;
1513 if (x->nonce_low == 0) {
1519 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1520 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1521 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1522 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1524 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1525 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1526 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1527 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1528 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1530 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1531 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1532 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1533 SBVAL(hdr, SMB2_HDR_PID, async_id);
1534 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1535 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1536 memcpy(hdr+SMB2_HDR_SIGNATURE,
1537 outhdr+SMB2_HDR_SIGNATURE, 16);
1539 SSVAL(body, 0x00, 0x08 + 1);
1541 SCVAL(body, 0x02, 0);
1542 SCVAL(body, 0x03, 0);
1543 SIVAL(body, 0x04, 0);
1544 /* Match W2K8R2... */
1545 SCVAL(dyn, 0x00, 0x21);
1547 state->vector[0].iov_base = (void *)state->buf;
1548 state->vector[0].iov_len = NBT_HDR_SIZE;
1550 if (req->do_encryption) {
1551 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1552 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1554 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1555 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1558 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1559 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1561 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1562 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1564 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1565 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1567 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1569 /* Ensure we correctly go through crediting. Grant
1570 the credits now, and zero credits on the final
1572 smb2_set_operation_credit(req->xconn,
1573 SMBD_SMB2_IN_HDR_IOV(req),
1574 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1576 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1581 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1582 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1584 (unsigned int)ARRAY_SIZE(state->vector),
1585 (unsigned int)state->vector[i].iov_len);
1589 if (req->do_encryption) {
1590 struct smbXsrv_session *x = req->session;
1591 DATA_BLOB encryption_key = x->global->encryption_key;
1593 status = smb2_signing_encrypt_pdu(encryption_key,
1594 xconn->smb2.server.cipher,
1595 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1596 SMBD_SMB2_NUM_IOV_PER_REQ);
1597 if (!NT_STATUS_IS_OK(status)) {
1598 smbd_server_connection_terminate(xconn,
1602 } else if (req->do_signing) {
1603 struct smbXsrv_session *x = req->session;
1604 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
1606 status = smb2_signing_sign_pdu(signing_key,
1608 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1609 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1610 if (!NT_STATUS_IS_OK(status)) {
1611 smbd_server_connection_terminate(xconn,
1617 state->queue_entry.mem_ctx = state;
1618 state->queue_entry.vector = state->vector;
1619 state->queue_entry.count = ARRAY_SIZE(state->vector);
1620 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
1621 xconn->smb2.send_queue_len++;
1623 status = smbd_smb2_flush_send_queue(xconn);
1624 if (!NT_STATUS_IS_OK(status)) {
1625 smbd_server_connection_terminate(xconn,
1631 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1633 struct smbXsrv_connection *xconn = req->xconn;
1634 struct smbd_smb2_request *cur;
1635 const uint8_t *inhdr;
1637 uint64_t search_message_id;
1638 uint64_t search_async_id;
1641 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1643 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1644 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1645 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1648 * we don't need the request anymore
1649 * cancel requests never have a response
1651 DLIST_REMOVE(xconn->smb2.requests, req);
1654 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1655 const uint8_t *outhdr;
1656 uint64_t message_id;
1659 if (cur->compound_related) {
1661 * Never cancel anything in a compound request.
1662 * Way too hard to deal with the result.
1667 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1669 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1670 async_id = BVAL(outhdr, SMB2_HDR_PID);
1672 if (flags & SMB2_HDR_FLAG_ASYNC) {
1673 if (search_async_id == async_id) {
1674 found_id = async_id;
1678 if (search_message_id == message_id) {
1679 found_id = message_id;
1685 if (cur && cur->subreq) {
1686 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1687 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1688 "cancel opcode[%s] mid %llu\n",
1689 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1690 (unsigned long long)found_id ));
1691 tevent_req_cancel(cur->subreq);
1694 return NT_STATUS_OK;
1697 /*************************************************************
1698 Ensure an incoming tid is a valid one for us to access.
1699 Change to the associated uid credentials and chdir to the
1700 valid tid directory.
1701 *************************************************************/
1703 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1705 const uint8_t *inhdr;
1708 struct smbXsrv_tcon *tcon;
1710 NTTIME now = timeval_to_nttime(&req->request_time);
1714 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1716 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1717 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1719 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1720 in_tid = req->last_tid;
1725 status = smb2srv_tcon_lookup(req->session,
1726 in_tid, now, &tcon);
1727 if (!NT_STATUS_IS_OK(status)) {
1731 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1732 return NT_STATUS_ACCESS_DENIED;
1735 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1736 if (!set_current_service(tcon->compat, 0, true)) {
1737 return NT_STATUS_ACCESS_DENIED;
1741 req->last_tid = in_tid;
1743 return NT_STATUS_OK;
1746 /*************************************************************
1747 Ensure an incoming session_id is a valid one for us to access.
1748 *************************************************************/
1750 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1752 const uint8_t *inhdr;
1755 uint64_t in_session_id;
1756 struct smbXsrv_session *session = NULL;
1757 struct auth_session_info *session_info;
1759 NTTIME now = timeval_to_nttime(&req->request_time);
1761 req->session = NULL;
1764 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1766 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1767 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1768 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1770 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1771 in_session_id = req->last_session_id;
1774 req->last_session_id = 0;
1776 /* lookup an existing session */
1777 status = smb2srv_session_lookup(req->xconn,
1781 req->session = session;
1782 req->last_session_id = in_session_id;
1784 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1785 switch (in_opcode) {
1786 case SMB2_OP_SESSSETUP:
1787 status = NT_STATUS_OK;
1793 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1794 switch (in_opcode) {
1796 case SMB2_OP_CREATE:
1797 case SMB2_OP_GETINFO:
1798 case SMB2_OP_SETINFO:
1799 return NT_STATUS_INVALID_HANDLE;
1802 * Notice the check for
1803 * (session_info == NULL)
1806 status = NT_STATUS_OK;
1810 if (!NT_STATUS_IS_OK(status)) {
1814 session_info = session->global->auth_session_info;
1815 if (session_info == NULL) {
1816 return NT_STATUS_INVALID_HANDLE;
1819 if (in_session_id != req->xconn->client->last_session_id) {
1820 req->xconn->client->last_session_id = in_session_id;
1821 set_current_user_info(session_info->unix_info->sanitized_username,
1822 session_info->unix_info->unix_name,
1823 session_info->info->domain_name);
1826 return NT_STATUS_OK;
1829 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1830 uint32_t data_length)
1832 struct smbXsrv_connection *xconn = req->xconn;
1833 uint16_t needed_charge;
1834 uint16_t credit_charge = 1;
1835 const uint8_t *inhdr;
1837 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1839 if (xconn->smb2.credits.multicredit) {
1840 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1841 credit_charge = MAX(credit_charge, 1);
1844 needed_charge = (data_length - 1)/ 65536 + 1;
1846 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1847 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1848 credit_charge, needed_charge));
1850 if (needed_charge > credit_charge) {
1851 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1852 credit_charge, needed_charge));
1853 return NT_STATUS_INVALID_PARAMETER;
1856 return NT_STATUS_OK;
1859 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1860 size_t expected_body_size)
1862 struct iovec *inhdr_v;
1863 const uint8_t *inhdr;
1865 const uint8_t *inbody;
1867 size_t min_dyn_size = expected_body_size & 0x00000001;
1868 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1871 * The following should be checked already.
1873 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1874 return NT_STATUS_INTERNAL_ERROR;
1876 if (req->current_idx > max_idx) {
1877 return NT_STATUS_INTERNAL_ERROR;
1880 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1881 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1882 return NT_STATUS_INTERNAL_ERROR;
1884 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1885 return NT_STATUS_INTERNAL_ERROR;
1888 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1889 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1893 case SMB2_OP_GETINFO:
1897 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
1898 if (req->smb1req->unread_bytes < min_dyn_size) {
1899 return NT_STATUS_INVALID_PARAMETER;
1908 * Now check the expected body size,
1909 * where the last byte might be in the
1912 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1913 return NT_STATUS_INVALID_PARAMETER;
1915 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1916 return NT_STATUS_INVALID_PARAMETER;
1919 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1921 body_size = SVAL(inbody, 0x00);
1922 if (body_size != expected_body_size) {
1923 return NT_STATUS_INVALID_PARAMETER;
1926 return NT_STATUS_OK;
1929 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1931 struct smbXsrv_connection *xconn = req->xconn;
1932 const struct smbd_smb2_dispatch_table *call = NULL;
1933 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1934 const uint8_t *inhdr;
1939 NTSTATUS session_status;
1940 uint32_t allowed_flags;
1941 NTSTATUS return_value;
1942 struct smbXsrv_session *x = NULL;
1943 bool signing_required = false;
1944 bool encryption_required = false;
1946 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1948 DO_PROFILE_INC(request);
1950 /* TODO: verify more things */
1952 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1953 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1954 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1955 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1956 smb2_opcode_name(opcode),
1957 (unsigned long long)mid));
1959 if (xconn->protocol >= PROTOCOL_SMB2_02) {
1961 * once the protocol is negotiated
1962 * SMB2_OP_NEGPROT is not allowed anymore
1964 if (opcode == SMB2_OP_NEGPROT) {
1965 /* drop the connection */
1966 return NT_STATUS_INVALID_PARAMETER;
1970 * if the protocol is not negotiated yet
1971 * only SMB2_OP_NEGPROT is allowed.
1973 if (opcode != SMB2_OP_NEGPROT) {
1974 /* drop the connection */
1975 return NT_STATUS_INVALID_PARAMETER;
1980 * Check if the client provided a valid session id,
1981 * if so smbd_smb2_request_check_session() calls
1982 * set_current_user_info().
1984 * As some command don't require a valid session id
1985 * we defer the check of the session_status
1987 session_status = smbd_smb2_request_check_session(req);
1990 signing_required = x->global->signing_required;
1991 encryption_required = x->global->encryption_required;
1994 req->do_signing = false;
1995 req->do_encryption = false;
1996 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
1997 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
1998 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
2000 if (x != NULL && x->global->session_wire_id != tf_session_id) {
2001 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2002 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
2003 (unsigned long long)x->global->session_wire_id,
2004 (unsigned long long)tf_session_id));
2006 * TODO: windows allows this...
2007 * should we drop the connection?
2009 * For now we just return ACCESS_DENIED
2010 * (Windows clients never trigger this)
2011 * and wait for an update of [MS-SMB2].
2013 return smbd_smb2_request_error(req,
2014 NT_STATUS_ACCESS_DENIED);
2017 req->do_encryption = true;
2020 if (encryption_required && !req->do_encryption) {
2021 return smbd_smb2_request_error(req,
2022 NT_STATUS_ACCESS_DENIED);
2025 call = smbd_smb2_call(opcode);
2027 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2030 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2031 SMB2_HDR_FLAG_SIGNED |
2033 if (opcode == SMB2_OP_CANCEL) {
2034 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2036 if ((flags & ~allowed_flags) != 0) {
2037 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2040 if (flags & SMB2_HDR_FLAG_CHAINED) {
2042 * This check is mostly for giving the correct error code
2043 * for compounded requests.
2045 if (!NT_STATUS_IS_OK(session_status)) {
2046 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2049 req->compat_chain_fsp = NULL;
2052 if (req->do_encryption) {
2053 signing_required = false;
2054 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2055 DATA_BLOB signing_key = data_blob_null;
2059 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2060 * If the SMB2 header of the SMB2 NEGOTIATE
2061 * request has the SMB2_FLAGS_SIGNED bit set in the
2062 * Flags field, the server MUST fail the request
2063 * with STATUS_INVALID_PARAMETER.
2065 * Microsoft test tool checks this.
2068 if ((opcode == SMB2_OP_NEGPROT) &&
2069 (flags & SMB2_HDR_FLAG_SIGNED)) {
2070 status = NT_STATUS_INVALID_PARAMETER;
2072 status = NT_STATUS_USER_SESSION_DELETED;
2074 return smbd_smb2_request_error(req, status);
2077 signing_key = smbd_smb2_signing_key(x, xconn);
2080 * If we have a signing key, we should
2083 if (signing_key.length > 0) {
2084 req->do_signing = true;
2087 status = smb2_signing_check_pdu(signing_key,
2089 SMBD_SMB2_IN_HDR_IOV(req),
2090 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2091 if (!NT_STATUS_IS_OK(status)) {
2092 return smbd_smb2_request_error(req, status);
2096 * Now that we know the request was correctly signed
2097 * we have to sign the response too.
2099 req->do_signing = true;
2101 if (!NT_STATUS_IS_OK(session_status)) {
2102 return smbd_smb2_request_error(req, session_status);
2104 } else if (opcode == SMB2_OP_CANCEL) {
2105 /* Cancel requests are allowed to skip the signing */
2106 } else if (signing_required) {
2108 * If signing is required we try to sign
2109 * a possible error response
2111 req->do_signing = true;
2112 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2115 if (flags & SMB2_HDR_FLAG_CHAINED) {
2116 req->compound_related = true;
2119 if (call->need_session) {
2120 if (!NT_STATUS_IS_OK(session_status)) {
2121 return smbd_smb2_request_error(req, session_status);
2125 if (call->need_tcon) {
2126 SMB_ASSERT(call->need_session);
2129 * This call needs to be run as user.
2131 * smbd_smb2_request_check_tcon()
2132 * calls change_to_user() on success.
2134 status = smbd_smb2_request_check_tcon(req);
2135 if (!NT_STATUS_IS_OK(status)) {
2136 return smbd_smb2_request_error(req, status);
2138 if (req->tcon->global->encryption_required) {
2139 encryption_required = true;
2141 if (encryption_required && !req->do_encryption) {
2142 return smbd_smb2_request_error(req,
2143 NT_STATUS_ACCESS_DENIED);
2147 if (call->fileid_ofs != 0) {
2148 size_t needed = call->fileid_ofs + 16;
2149 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2150 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2151 uint64_t file_id_persistent;
2152 uint64_t file_id_volatile;
2153 struct files_struct *fsp;
2155 SMB_ASSERT(call->need_tcon);
2157 if (needed > body_size) {
2158 return smbd_smb2_request_error(req,
2159 NT_STATUS_INVALID_PARAMETER);
2162 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2163 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2165 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2167 if (!call->allow_invalid_fileid) {
2168 return smbd_smb2_request_error(req,
2169 NT_STATUS_FILE_CLOSED);
2172 if (file_id_persistent != UINT64_MAX) {
2173 return smbd_smb2_request_error(req,
2174 NT_STATUS_FILE_CLOSED);
2176 if (file_id_volatile != UINT64_MAX) {
2177 return smbd_smb2_request_error(req,
2178 NT_STATUS_FILE_CLOSED);
2183 if (call->as_root) {
2184 SMB_ASSERT(call->fileid_ofs == 0);
2185 /* This call needs to be run as root */
2186 change_to_root_user();
2188 SMB_ASSERT(call->need_tcon);
2191 #define _INBYTES(_r) \
2192 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
2195 case SMB2_OP_NEGPROT:
2196 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
2197 req->profile, _INBYTES(req));
2198 return_value = smbd_smb2_request_process_negprot(req);
2201 case SMB2_OP_SESSSETUP:
2202 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
2203 req->profile, _INBYTES(req));
2204 return_value = smbd_smb2_request_process_sesssetup(req);
2207 case SMB2_OP_LOGOFF:
2208 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
2209 req->profile, _INBYTES(req));
2210 return_value = smbd_smb2_request_process_logoff(req);
2214 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
2215 req->profile, _INBYTES(req));
2216 return_value = smbd_smb2_request_process_tcon(req);
2220 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
2221 req->profile, _INBYTES(req));
2222 return_value = smbd_smb2_request_process_tdis(req);
2225 case SMB2_OP_CREATE:
2226 if (req->subreq == NULL) {
2227 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
2228 req->profile, _INBYTES(req));
2230 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
2232 return_value = smbd_smb2_request_process_create(req);
2236 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
2237 req->profile, _INBYTES(req));
2238 return_value = smbd_smb2_request_process_close(req);
2242 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
2243 req->profile, _INBYTES(req));
2244 return_value = smbd_smb2_request_process_flush(req);
2248 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
2249 req->profile, _INBYTES(req));
2250 return_value = smbd_smb2_request_process_read(req);
2254 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
2255 req->profile, _INBYTES(req));
2256 return_value = smbd_smb2_request_process_write(req);
2260 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
2261 req->profile, _INBYTES(req));
2262 return_value = smbd_smb2_request_process_lock(req);
2266 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
2267 req->profile, _INBYTES(req));
2268 return_value = smbd_smb2_request_process_ioctl(req);
2271 case SMB2_OP_CANCEL:
2272 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
2273 req->profile, _INBYTES(req));
2274 return_value = smbd_smb2_request_process_cancel(req);
2275 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
2278 case SMB2_OP_KEEPALIVE:
2279 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
2280 req->profile, _INBYTES(req));
2281 return_value = smbd_smb2_request_process_keepalive(req);
2285 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
2286 req->profile, _INBYTES(req));
2287 return_value = smbd_smb2_request_process_find(req);
2290 case SMB2_OP_NOTIFY:
2291 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
2292 req->profile, _INBYTES(req));
2293 return_value = smbd_smb2_request_process_notify(req);
2296 case SMB2_OP_GETINFO:
2297 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
2298 req->profile, _INBYTES(req));
2299 return_value = smbd_smb2_request_process_getinfo(req);
2302 case SMB2_OP_SETINFO:
2303 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
2304 req->profile, _INBYTES(req));
2305 return_value = smbd_smb2_request_process_setinfo(req);
2309 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
2310 req->profile, _INBYTES(req));
2311 return_value = smbd_smb2_request_process_break(req);
2315 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2318 return return_value;
2321 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2323 struct smbXsrv_connection *xconn = req->xconn;
2325 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2326 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2327 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2331 TALLOC_FREE(req->async_te);
2333 if (req->do_encryption &&
2334 (firsttf->iov_len == 0) &&
2335 (req->first_key.length == 0) &&
2336 (req->session != NULL) &&
2337 (req->session->global->encryption_key.length != 0))
2339 DATA_BLOB encryption_key = req->session->global->encryption_key;
2341 uint64_t session_id = req->session->global->session_wire_id;
2342 struct smbXsrv_session *x = req->session;
2343 uint64_t nonce_high;
2346 nonce_high = x->nonce_high;
2347 nonce_low = x->nonce_low;
2350 if (x->nonce_low == 0) {
2356 * We need to place the SMB2_TRANSFORM header before the
2361 * we need to remember the encryption key
2362 * and defer the signing/encryption until
2363 * we are sure that we do not change
2366 req->first_key = data_blob_dup_talloc(req, encryption_key);
2367 if (req->first_key.data == NULL) {
2368 return NT_STATUS_NO_MEMORY;
2371 tf = talloc_zero_array(req, uint8_t,
2374 return NT_STATUS_NO_MEMORY;
2377 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2378 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2379 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2380 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2382 firsttf->iov_base = (void *)tf;
2383 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2386 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2387 (req->last_key.length > 0) &&
2388 (firsttf->iov_len == 0))
2390 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2391 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2394 * As we are sure the header of the last request in the
2395 * compound chain will not change, we can to sign here
2396 * with the last signing key we remembered.
2398 status = smb2_signing_sign_pdu(req->last_key,
2401 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2402 if (!NT_STATUS_IS_OK(status)) {
2406 if (req->last_key.length > 0) {
2407 data_blob_clear_free(&req->last_key);
2410 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
2411 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
2413 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2415 if (req->current_idx < req->out.vector_count) {
2417 * We must process the remaining compound
2418 * SMB2 requests before any new incoming SMB2
2419 * requests. This is because incoming SMB2
2420 * requests may include a cancel for a
2421 * compound request we haven't processed
2424 struct tevent_immediate *im = tevent_create_immediate(req);
2426 return NT_STATUS_NO_MEMORY;
2429 if (req->do_signing && firsttf->iov_len == 0) {
2430 struct smbXsrv_session *x = req->session;
2431 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2434 * we need to remember the signing key
2435 * and defer the signing until
2436 * we are sure that we do not change
2439 req->last_key = data_blob_dup_talloc(req, signing_key);
2440 if (req->last_key.data == NULL) {
2441 return NT_STATUS_NO_MEMORY;
2445 tevent_schedule_immediate(im,
2447 smbd_smb2_request_dispatch_immediate,
2449 return NT_STATUS_OK;
2452 if (req->compound_related) {
2453 req->compound_related = false;
2456 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2458 /* Set credit for these operations (zero credits if this
2459 is a final reply for an async operation). */
2460 smb2_calculate_credits(req, req);
2463 * now check if we need to sign the current response
2465 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2466 status = smb2_signing_encrypt_pdu(req->first_key,
2467 xconn->smb2.server.cipher,
2469 req->out.vector_count - first_idx);
2470 if (!NT_STATUS_IS_OK(status)) {
2473 } else if (req->do_signing) {
2474 struct smbXsrv_session *x = req->session;
2475 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2477 status = smb2_signing_sign_pdu(signing_key,
2480 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2481 if (!NT_STATUS_IS_OK(status)) {
2485 if (req->first_key.length > 0) {
2486 data_blob_clear_free(&req->first_key);
2489 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2490 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2491 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2492 /* Dynamic part is NULL. Chop it off,
2493 We're going to send it via sendfile. */
2494 req->out.vector_count -= 1;
2498 * We're done with this request -
2499 * move it off the "being processed" queue.
2501 DLIST_REMOVE(xconn->smb2.requests, req);
2503 req->queue_entry.mem_ctx = req;
2504 req->queue_entry.vector = req->out.vector;
2505 req->queue_entry.count = req->out.vector_count;
2506 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry, NULL);
2507 xconn->smb2.send_queue_len++;
2509 status = smbd_smb2_flush_send_queue(xconn);
2510 if (!NT_STATUS_IS_OK(status)) {
2514 return NT_STATUS_OK;
2517 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
2519 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2520 struct tevent_immediate *im,
2523 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2524 struct smbd_smb2_request);
2525 struct smbXsrv_connection *xconn = req->xconn;
2530 if (DEBUGLEVEL >= 10) {
2531 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2532 req->current_idx, req->in.vector_count));
2533 print_req_vectors(req);
2536 status = smbd_smb2_request_dispatch(req);
2537 if (!NT_STATUS_IS_OK(status)) {
2538 smbd_server_connection_terminate(xconn, nt_errstr(status));
2542 status = smbd_smb2_request_next_incoming(xconn);
2543 if (!NT_STATUS_IS_OK(status)) {
2544 smbd_server_connection_terminate(xconn, nt_errstr(status));
2549 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2551 DATA_BLOB body, DATA_BLOB *dyn,
2552 const char *location)
2555 struct iovec *outbody_v;
2556 struct iovec *outdyn_v;
2557 uint32_t next_command_ofs;
2559 DEBUG(10,("smbd_smb2_request_done_ex: "
2560 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2561 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2563 (unsigned int)(dyn ? dyn->length : 0),
2566 if (body.length < 2) {
2567 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2570 if ((body.length % 2) != 0) {
2571 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2574 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2575 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2576 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2578 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2579 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2581 outbody_v->iov_base = (void *)body.data;
2582 outbody_v->iov_len = body.length;
2585 outdyn_v->iov_base = (void *)dyn->data;
2586 outdyn_v->iov_len = dyn->length;
2588 outdyn_v->iov_base = NULL;
2589 outdyn_v->iov_len = 0;
2592 /* see if we need to recalculate the offset to the next response */
2593 if (next_command_ofs > 0) {
2594 next_command_ofs = SMB2_HDR_BODY;
2595 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2596 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2599 if ((next_command_ofs % 8) != 0) {
2600 size_t pad_size = 8 - (next_command_ofs % 8);
2601 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2603 * if the dyn buffer is empty
2604 * we can use it to add padding
2608 pad = talloc_zero_array(req,
2611 return smbd_smb2_request_error(req,
2612 NT_STATUS_NO_MEMORY);
2615 outdyn_v->iov_base = (void *)pad;
2616 outdyn_v->iov_len = pad_size;
2619 * For now we copy the dynamic buffer
2620 * and add the padding to the new buffer
2627 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2628 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2630 new_size = old_size + pad_size;
2631 new_dyn = talloc_zero_array(req,
2633 if (new_dyn == NULL) {
2634 return smbd_smb2_request_error(req,
2635 NT_STATUS_NO_MEMORY);
2638 memcpy(new_dyn, old_dyn, old_size);
2639 memset(new_dyn + old_size, 0, pad_size);
2641 outdyn_v->iov_base = (void *)new_dyn;
2642 outdyn_v->iov_len = new_size;
2644 next_command_ofs += pad_size;
2647 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2649 return smbd_smb2_request_reply(req);
2652 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2655 const char *location)
2657 struct smbXsrv_connection *xconn = req->xconn;
2660 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2661 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2663 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2664 req->current_idx, nt_errstr(status), info ? " +info" : "",
2668 /* Recvfile error. Drain incoming socket. */
2672 ret = drain_socket(xconn->transport.sock, unread_bytes);
2673 if (ret != unread_bytes) {
2677 error = NT_STATUS_IO_DEVICE_ERROR;
2679 error = map_nt_error_from_unix_common(errno);
2682 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2683 "ret[%u] errno[%d] => %s\n",
2684 (unsigned)unread_bytes,
2685 (unsigned)ret, errno, nt_errstr(error)));
2690 body.data = outhdr + SMB2_HDR_BODY;
2692 SSVAL(body.data, 0, 9);
2695 SIVAL(body.data, 0x04, info->length);
2697 /* Allocated size of req->out.vector[i].iov_base
2698 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2699 * 1 byte without having to do an alloc.
2702 info->data = ((uint8_t *)outhdr) +
2703 OUTVEC_ALLOC_SIZE - 1;
2705 SCVAL(info->data, 0, 0);
2709 * Note: Even if there is an error, continue to process the request.
2713 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2717 struct smbd_smb2_send_break_state {
2718 struct smbd_smb2_send_queue queue_entry;
2719 uint8_t nbt_hdr[NBT_HDR_SIZE];
2720 uint8_t tf[SMB2_TF_HDR_SIZE];
2721 uint8_t hdr[SMB2_HDR_BODY];
2722 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2726 static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
2727 struct smbXsrv_session *session,
2728 struct smbXsrv_tcon *tcon,
2729 const uint8_t *body,
2732 struct smbd_smb2_send_break_state *state;
2733 bool do_encryption = false;
2734 uint64_t session_wire_id = 0;
2735 uint64_t nonce_high = 0;
2736 uint64_t nonce_low = 0;
2740 if (session != NULL) {
2741 session_wire_id = session->global->session_wire_id;
2742 do_encryption = session->global->encryption_required;
2743 if (tcon->global->encryption_required) {
2744 do_encryption = true;
2748 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
2751 state = talloc_zero_size(xconn, statelen);
2752 if (state == NULL) {
2753 return NT_STATUS_NO_MEMORY;
2755 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
2757 if (do_encryption) {
2758 nonce_high = session->nonce_high;
2759 nonce_low = session->nonce_low;
2761 session->nonce_low += 1;
2762 if (session->nonce_low == 0) {
2763 session->nonce_low += 1;
2764 session->nonce_high += 1;
2768 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2769 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
2770 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
2771 SBVAL(state->tf, SMB2_TF_SESSION_ID, session_wire_id);
2773 SIVAL(state->hdr, 0, SMB2_MAGIC);
2774 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2775 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
2776 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
2777 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2778 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
2779 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2780 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
2781 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2782 SIVAL(state->hdr, SMB2_HDR_PID, 0);
2783 SIVAL(state->hdr, SMB2_HDR_TID, 0);
2784 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
2785 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
2787 state->vector[0] = (struct iovec) {
2788 .iov_base = state->nbt_hdr,
2789 .iov_len = sizeof(state->nbt_hdr)
2792 if (do_encryption) {
2793 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2794 .iov_base = state->tf,
2795 .iov_len = sizeof(state->tf)
2798 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2804 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
2805 .iov_base = state->hdr,
2806 .iov_len = sizeof(state->hdr)
2809 memcpy(state->body, body, body_len);
2811 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
2812 .iov_base = state->body,
2813 .iov_len = body_len /* no sizeof(state->body) .. :-) */
2817 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
2820 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2822 if (do_encryption) {
2823 DATA_BLOB encryption_key = session->global->encryption_key;
2825 status = smb2_signing_encrypt_pdu(encryption_key,
2826 xconn->smb2.server.cipher,
2827 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2828 SMBD_SMB2_NUM_IOV_PER_REQ);
2829 if (!NT_STATUS_IS_OK(status)) {
2834 state->queue_entry.mem_ctx = state;
2835 state->queue_entry.vector = state->vector;
2836 state->queue_entry.count = ARRAY_SIZE(state->vector);
2837 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
2838 xconn->smb2.send_queue_len++;
2840 status = smbd_smb2_flush_send_queue(xconn);
2841 if (!NT_STATUS_IS_OK(status)) {
2845 return NT_STATUS_OK;
2848 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_connection *xconn,
2849 struct smbXsrv_session *session,
2850 struct smbXsrv_tcon *tcon,
2851 struct smbXsrv_open *op,
2852 uint8_t oplock_level)
2856 SSVAL(body, 0x00, sizeof(body));
2857 SCVAL(body, 0x02, oplock_level);
2858 SCVAL(body, 0x03, 0); /* reserved */
2859 SIVAL(body, 0x04, 0); /* reserved */
2860 SBVAL(body, 0x08, op->global->open_persistent_id);
2861 SBVAL(body, 0x10, op->global->open_volatile_id);
2863 return smbd_smb2_send_break(xconn, session, tcon, body, sizeof(body));
2866 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_connection *xconn,
2868 uint32_t lease_flags,
2869 struct smb2_lease_key *lease_key,
2870 uint32_t current_lease_state,
2871 uint32_t new_lease_state)
2875 SSVAL(body, 0x00, sizeof(body));
2876 SSVAL(body, 0x02, new_epoch);
2877 SIVAL(body, 0x04, lease_flags);
2878 SBVAL(body, 0x08, lease_key->data[0]);
2879 SBVAL(body, 0x10, lease_key->data[1]);
2880 SIVAL(body, 0x18, current_lease_state);
2881 SIVAL(body, 0x1c, new_lease_state);
2882 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
2883 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
2884 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
2886 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
2889 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2893 uint64_t file_id_persistent;
2894 uint64_t file_id_volatile;
2895 struct smbXsrv_open *op = NULL;
2896 struct files_struct *fsp = NULL;
2897 const uint8_t *body = NULL;
2900 * This is only called with a pktbuf
2901 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
2905 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
2906 /* Transform header. Cannot recvfile. */
2909 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
2910 /* Not SMB2. Normal error path will cope. */
2913 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
2914 /* Not SMB2. Normal error path will cope. */
2917 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
2918 /* Needs to be a WRITE. */
2921 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
2922 /* Chained. Cannot recvfile. */
2925 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
2926 if (flags & SMB2_HDR_FLAG_CHAINED) {
2927 /* Chained. Cannot recvfile. */
2930 if (flags & SMB2_HDR_FLAG_SIGNED) {
2931 /* Signed. Cannot recvfile. */
2935 body = &state->pktbuf[SMB2_HDR_BODY];
2937 file_id_persistent = BVAL(body, 0x10);
2938 file_id_volatile = BVAL(body, 0x18);
2940 status = smb2srv_open_lookup(state->req->xconn,
2945 if (!NT_STATUS_IS_OK(status)) {
2953 if (fsp->conn == NULL) {
2957 if (IS_IPC(fsp->conn)) {
2960 if (IS_PRINT(fsp->conn)) {
2964 DEBUG(10,("Doing recvfile write len = %u\n",
2965 (unsigned int)(state->pktfull - state->pktlen)));
2970 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
2972 struct smbd_server_connection *sconn = xconn->client->sconn;
2973 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
2974 size_t max_send_queue_len;
2975 size_t cur_send_queue_len;
2977 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
2979 * we're not supposed to do any io
2981 return NT_STATUS_OK;
2984 if (state->req != NULL) {
2986 * if there is already a tstream_readv_pdu
2987 * pending, we are done.
2989 return NT_STATUS_OK;
2992 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
2993 cur_send_queue_len = xconn->smb2.send_queue_len;
2995 if (cur_send_queue_len > max_send_queue_len) {
2997 * if we have a lot of requests to send,
2998 * we wait until they are on the wire until we
2999 * ask for the next request.
3001 return NT_STATUS_OK;
3004 /* ask for the next request */
3005 ZERO_STRUCTP(state);
3006 state->req = smbd_smb2_request_allocate(xconn);
3007 if (state->req == NULL) {
3008 return NT_STATUS_NO_MEMORY;
3010 state->req->sconn = sconn;
3011 state->req->xconn = xconn;
3012 state->min_recv_size = lp_min_receive_file_size();
3014 TEVENT_FD_READABLE(xconn->transport.fde);
3016 return NT_STATUS_OK;
3019 void smbd_smb2_first_negprot(struct smbXsrv_connection *xconn,
3020 const uint8_t *inpdu, size_t size)
3022 struct smbd_server_connection *sconn = xconn->client->sconn;
3024 struct smbd_smb2_request *req = NULL;
3026 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3027 (unsigned int)size));
3029 status = smbd_initialize_smb2(xconn);
3030 if (!NT_STATUS_IS_OK(status)) {
3031 smbd_server_connection_terminate(xconn, nt_errstr(status));
3035 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
3036 if (!NT_STATUS_IS_OK(status)) {
3037 smbd_server_connection_terminate(xconn, nt_errstr(status));
3041 status = smbd_smb2_request_validate(req);
3042 if (!NT_STATUS_IS_OK(status)) {
3043 smbd_server_connection_terminate(xconn, nt_errstr(status));
3047 status = smbd_smb2_request_setup_out(req);
3048 if (!NT_STATUS_IS_OK(status)) {
3049 smbd_server_connection_terminate(xconn, nt_errstr(status));
3055 * this was already counted at the SMB1 layer =>
3056 * smbd_smb2_request_dispatch() should not count it twice.
3058 if (profile_p->request_stats.count > 0) {
3059 profile_p->request_stats.count--;
3062 status = smbd_smb2_request_dispatch(req);
3063 if (!NT_STATUS_IS_OK(status)) {
3064 smbd_server_connection_terminate(xconn, nt_errstr(status));
3068 status = smbd_smb2_request_next_incoming(xconn);
3069 if (!NT_STATUS_IS_OK(status)) {
3070 smbd_server_connection_terminate(xconn, nt_errstr(status));
3074 sconn->num_requests++;
3077 static int socket_error_from_errno(int ret,
3091 if (sys_errno == 0) {
3095 if (sys_errno == EINTR) {
3100 if (sys_errno == EINPROGRESS) {
3105 if (sys_errno == EAGAIN) {
3110 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3111 if (sys_errno == ENOMEM) {
3117 #if EWOULDBLOCK != EAGAIN
3118 if (sys_errno == EWOULDBLOCK) {
3128 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3134 if (xconn->smb2.send_queue == NULL) {
3135 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3136 return NT_STATUS_OK;
3139 while (xconn->smb2.send_queue != NULL) {
3140 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3142 if (e->sendfile_header != NULL) {
3143 NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
3148 for (i=0; i < e->count; i++) {
3149 size += e->vector[i].iov_len;
3152 if (size <= e->sendfile_header->length) {
3153 buf = e->sendfile_header->data;
3155 buf = talloc_array(e->mem_ctx, uint8_t, size);
3157 return NT_STATUS_NO_MEMORY;
3162 for (i=0; i < e->count; i++) {
3164 e->vector[i].iov_base,
3165 e->vector[i].iov_len);
3166 size += e->vector[i].iov_len;
3169 e->sendfile_header->data = buf;
3170 e->sendfile_header->length = size;
3171 e->sendfile_status = &status;
3174 xconn->smb2.send_queue_len--;
3175 DLIST_REMOVE(xconn->smb2.send_queue, e);
3177 * This triggers the sendfile path via
3180 talloc_free(e->mem_ctx);
3182 if (!NT_STATUS_IS_OK(status)) {
3188 ret = writev(xconn->transport.sock, e->vector, e->count);
3190 /* propagate end of file */
3191 return NT_STATUS_INTERNAL_ERROR;
3193 err = socket_error_from_errno(ret, errno, &retry);
3196 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3197 return NT_STATUS_OK;
3200 return map_nt_error_from_unix_common(err);
3203 if (ret < e->vector[0].iov_len) {
3205 base = (uint8_t *)e->vector[0].iov_base;
3207 e->vector[0].iov_base = (void *)base;
3208 e->vector[0].iov_len -= ret;
3211 ret -= e->vector[0].iov_len;
3217 * there're maybe some empty vectors at the end
3218 * which we need to skip, otherwise we would get
3219 * ret == 0 from the readv() call and return EPIPE
3221 while (e->count > 0) {
3222 if (e->vector[0].iov_len > 0) {
3230 /* we have more to write */
3231 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3232 return NT_STATUS_OK;
3235 xconn->smb2.send_queue_len--;
3236 DLIST_REMOVE(xconn->smb2.send_queue, e);
3237 talloc_free(e->mem_ctx);
3240 return NT_STATUS_OK;
3243 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3246 struct smbd_server_connection *sconn = xconn->client->sconn;
3247 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3248 struct smbd_smb2_request *req = NULL;
3249 size_t min_recvfile_size = UINT32_MAX;
3256 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3258 * we're not supposed to do any io
3260 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3261 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3262 return NT_STATUS_OK;
3265 if (fde_flags & TEVENT_FD_WRITE) {
3266 status = smbd_smb2_flush_send_queue(xconn);
3267 if (!NT_STATUS_IS_OK(status)) {
3272 if (!(fde_flags & TEVENT_FD_READ)) {
3273 return NT_STATUS_OK;
3276 if (state->req == NULL) {
3277 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3278 return NT_STATUS_OK;
3282 if (!state->hdr.done) {
3283 state->hdr.done = true;
3285 state->vector.iov_base = (void *)state->hdr.nbt;
3286 state->vector.iov_len = NBT_HDR_SIZE;
3289 ret = readv(xconn->transport.sock, &state->vector, 1);
3291 /* propagate end of file */
3292 return NT_STATUS_END_OF_FILE;
3294 err = socket_error_from_errno(ret, errno, &retry);
3297 TEVENT_FD_READABLE(xconn->transport.fde);
3298 return NT_STATUS_OK;
3301 return map_nt_error_from_unix_common(err);
3304 if (ret < state->vector.iov_len) {
3306 base = (uint8_t *)state->vector.iov_base;
3308 state->vector.iov_base = (void *)base;
3309 state->vector.iov_len -= ret;
3310 /* we have more to read */
3311 TEVENT_FD_READABLE(xconn->transport.fde);
3312 return NT_STATUS_OK;
3315 if (state->pktlen > 0) {
3316 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3318 * Not a possible receivefile write.
3319 * Read the rest of the data.
3321 state->doing_receivefile = false;
3323 state->pktbuf = talloc_realloc(state->req,
3327 if (state->pktbuf == NULL) {
3328 return NT_STATUS_NO_MEMORY;
3331 state->vector.iov_base = (void *)(state->pktbuf +
3333 state->vector.iov_len = (state->pktfull -
3336 state->pktlen = state->pktfull;
3341 * Either this is a receivefile write so we've
3342 * done a short read, or if not we have all the data.
3348 * Now we analyze the NBT header
3350 if (state->hdr.nbt[0] != 0x00) {
3351 state->min_recv_size = 0;
3353 state->pktfull = smb2_len(state->hdr.nbt);
3354 if (state->pktfull == 0) {
3358 if (state->min_recv_size != 0) {
3359 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3360 min_recvfile_size += state->min_recv_size;
3363 if (state->pktfull > min_recvfile_size) {
3365 * Might be a receivefile write. Read the SMB2 HEADER +
3366 * SMB2_WRITE header first. Set 'doing_receivefile'
3367 * as we're *attempting* receivefile write. If this
3368 * turns out not to be a SMB2_WRITE request or otherwise
3369 * not suitable then we'll just read the rest of the data
3370 * the next time this function is called.
3372 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3373 state->doing_receivefile = true;
3375 state->pktlen = state->pktfull;
3378 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3379 if (state->pktbuf == NULL) {
3380 return NT_STATUS_NO_MEMORY;
3383 state->vector.iov_base = (void *)state->pktbuf;
3384 state->vector.iov_len = state->pktlen;
3390 if (state->hdr.nbt[0] != 0x00) {
3391 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3392 state->hdr.nbt[0]));
3395 ZERO_STRUCTP(state);
3397 state->min_recv_size = lp_min_receive_file_size();
3405 req->request_time = timeval_current();
3406 now = timeval_to_nttime(&req->request_time);
3408 status = smbd_smb2_inbuf_parse_compound(xconn,
3414 &req->in.vector_count);
3415 if (!NT_STATUS_IS_OK(status)) {
3419 if (state->doing_receivefile) {
3420 req->smb1req = talloc_zero(req, struct smb_request);
3421 if (req->smb1req == NULL) {
3422 return NT_STATUS_NO_MEMORY;
3424 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3427 ZERO_STRUCTP(state);
3429 req->current_idx = 1;
3431 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3432 req->current_idx, req->in.vector_count));
3434 status = smbd_smb2_request_validate(req);
3435 if (!NT_STATUS_IS_OK(status)) {
3439 status = smbd_smb2_request_setup_out(req);
3440 if (!NT_STATUS_IS_OK(status)) {
3444 status = smbd_smb2_request_dispatch(req);
3445 if (!NT_STATUS_IS_OK(status)) {
3449 sconn->num_requests++;
3451 /* The timeout_processing function isn't run nearly
3452 often enough to implement 'max log size' without
3453 overrunning the size of the file by many megabytes.
3454 This is especially true if we are running at debug
3455 level 10. Checking every 50 SMB2s is a nice
3456 tradeoff of performance vs log file size overrun. */
3458 if ((sconn->num_requests % 50) == 0 &&
3459 need_to_check_log_size()) {
3460 change_to_root_user();
3464 status = smbd_smb2_request_next_incoming(xconn);
3465 if (!NT_STATUS_IS_OK(status)) {
3469 return NT_STATUS_OK;
3472 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3473 struct tevent_fd *fde,
3477 struct smbXsrv_connection *xconn =
3478 talloc_get_type_abort(private_data,
3479 struct smbXsrv_connection);
3482 status = smbd_smb2_io_handler(xconn, flags);
3483 if (!NT_STATUS_IS_OK(status)) {
3484 smbd_server_connection_terminate(xconn, nt_errstr(status));