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"
33 #include "lib/crypto/sha512.h"
35 static void smbd_smb2_connection_handler(struct tevent_context *ev,
36 struct tevent_fd *fde,
39 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn);
41 static const struct smbd_smb2_dispatch_table {
48 bool allow_invalid_fileid;
50 } smbd_smb2_table[] = {
51 #define _OP(o) .opcode = o, .name = #o
56 _OP(SMB2_OP_SESSSETUP),
66 * This call needs to be run as root.
68 * smbd_smb2_request_process_tcon()
69 * calls make_connection_snum(), which will call
70 * change_to_user(), when needed.
105 .need_session = true,
110 .need_session = true,
113 .allow_invalid_fileid = true,
119 _OP(SMB2_OP_KEEPALIVE),
122 _OP(SMB2_OP_QUERY_DIRECTORY),
123 .need_session = true,
128 .need_session = true,
132 _OP(SMB2_OP_GETINFO),
133 .need_session = true,
137 _OP(SMB2_OP_SETINFO),
138 .need_session = true,
144 .need_session = true,
149 * as LEASE breaks does not
155 const char *smb2_opcode_name(uint16_t opcode)
157 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
158 return "Bad SMB2 opcode";
160 return smbd_smb2_table[opcode].name;
163 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
165 const struct smbd_smb2_dispatch_table *ret = NULL;
167 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
171 ret = &smbd_smb2_table[opcode];
173 SMB_ASSERT(ret->opcode == opcode);
178 static void print_req_vectors(const struct smbd_smb2_request *req)
182 for (i = 0; i < req->in.vector_count; i++) {
183 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
185 (unsigned int)req->in.vector[i].iov_len);
187 for (i = 0; i < req->out.vector_count; i++) {
188 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
190 (unsigned int)req->out.vector[i].iov_len);
194 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
196 if (size < (4 + SMB2_HDR_BODY)) {
200 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
207 static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn)
209 TALLOC_FREE(xconn->transport.fde);
211 xconn->smb2.credits.seq_low = 0;
212 xconn->smb2.credits.seq_range = 1;
213 xconn->smb2.credits.granted = 1;
214 xconn->smb2.credits.max = lp_smb2_max_credits();
215 xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
216 xconn->smb2.credits.max);
217 if (xconn->smb2.credits.bitmap == NULL) {
218 return NT_STATUS_NO_MEMORY;
221 xconn->transport.fde = tevent_add_fd(xconn->ev_ctx,
223 xconn->transport.sock,
225 smbd_smb2_connection_handler,
227 if (xconn->transport.fde == NULL) {
228 return NT_STATUS_NO_MEMORY;
231 /* Ensure child is set to non-blocking mode */
232 set_blocking(xconn->transport.sock, false);
236 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
237 #define _smb2_setlen(_buf,len) do { \
238 uint8_t *buf = (uint8_t *)_buf; \
240 buf[1] = ((len)&0xFF0000)>>16; \
241 buf[2] = ((len)&0xFF00)>>8; \
242 buf[3] = (len)&0xFF; \
245 static bool smb2_setup_nbt_length(struct iovec *vector, int count)
253 len = iov_buflen(vector+1, count-1);
255 if ((len == -1) || (len > 0xFFFFFF)) {
259 _smb2_setlen(vector[0].iov_base, len);
263 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
265 if (req->first_key.length > 0) {
266 data_blob_clear_free(&req->first_key);
268 if (req->last_key.length > 0) {
269 data_blob_clear_free(&req->last_key);
274 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
276 TALLOC_CTX *mem_pool;
277 struct smbd_smb2_request *req;
280 /* Enable this to find subtle valgrind errors. */
281 mem_pool = talloc_init("smbd_smb2_request_allocate");
283 mem_pool = talloc_tos();
285 if (mem_pool == NULL) {
289 req = talloc_zero(mem_pool, struct smbd_smb2_request);
291 talloc_free(mem_pool);
294 talloc_reparent(mem_pool, mem_ctx, req);
296 TALLOC_FREE(mem_pool);
299 req->last_session_id = UINT64_MAX;
300 req->last_tid = UINT32_MAX;
302 talloc_set_destructor(req, smbd_smb2_request_destructor);
307 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
311 struct smbd_smb2_request *req,
315 TALLOC_CTX *mem_ctx = req;
319 uint8_t *first_hdr = buf;
320 size_t verified_buflen = 0;
325 * Note: index '0' is reserved for the transport protocol
327 iov = req->in._vector;
329 while (taken < buflen) {
330 size_t len = buflen - taken;
331 uint8_t *hdr = first_hdr + taken;
334 size_t next_command_ofs;
336 uint8_t *body = NULL;
339 struct iovec *iov_alloc = NULL;
341 if (iov != req->in._vector) {
345 if (verified_buflen > taken) {
346 len = verified_buflen - taken;
353 DEBUG(10, ("%d bytes left, expected at least %d\n",
357 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
358 struct smbXsrv_session *s = NULL;
360 struct iovec tf_iov[2];
364 if (xconn->protocol < PROTOCOL_SMB2_24) {
365 DEBUG(10, ("Got SMB2_TRANSFORM header, "
366 "but dialect[0x%04X] is used\n",
367 xconn->smb2.server.dialect));
371 if (xconn->smb2.server.cipher == 0) {
372 DEBUG(10, ("Got SMB2_TRANSFORM header, "
373 "but not negotiated "
374 "client[0x%08X] server[0x%08X]\n",
375 xconn->smb2.client.capabilities,
376 xconn->smb2.server.capabilities));
380 if (len < SMB2_TF_HDR_SIZE) {
381 DEBUG(1, ("%d bytes left, expected at least %d\n",
382 (int)len, SMB2_TF_HDR_SIZE));
386 tf_len = SMB2_TF_HDR_SIZE;
389 hdr = first_hdr + taken;
390 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
391 uid = BVAL(tf, SMB2_TF_SESSION_ID);
393 if (len < SMB2_TF_HDR_SIZE + enc_len) {
394 DEBUG(1, ("%d bytes left, expected at least %d\n",
396 (int)(SMB2_TF_HDR_SIZE + enc_len)));
400 status = smb2srv_session_lookup_conn(xconn, uid, now,
403 DEBUG(1, ("invalid session[%llu] in "
404 "SMB2_TRANSFORM header\n",
405 (unsigned long long)uid));
406 TALLOC_FREE(iov_alloc);
407 return NT_STATUS_USER_SESSION_DELETED;
410 tf_iov[0].iov_base = (void *)tf;
411 tf_iov[0].iov_len = tf_len;
412 tf_iov[1].iov_base = (void *)hdr;
413 tf_iov[1].iov_len = enc_len;
415 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
416 xconn->smb2.server.cipher,
418 if (!NT_STATUS_IS_OK(status)) {
419 TALLOC_FREE(iov_alloc);
423 verified_buflen = taken + enc_len;
428 * We need the header plus the body length field
431 if (len < SMB2_HDR_BODY + 2) {
432 DEBUG(10, ("%d bytes left, expected at least %d\n",
433 (int)len, SMB2_HDR_BODY));
436 if (IVAL(hdr, 0) != SMB2_MAGIC) {
437 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
441 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
442 DEBUG(10, ("Got HDR len %d, expected %d\n",
443 SVAL(hdr, 4), SMB2_HDR_BODY));
448 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
449 body_size = SVAL(hdr, SMB2_HDR_BODY);
451 if (next_command_ofs != 0) {
452 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
455 if (next_command_ofs > full_size) {
458 full_size = next_command_ofs;
465 if (body_size > (full_size - SMB2_HDR_BODY)) {
467 * let the caller handle the error
469 body_size = full_size - SMB2_HDR_BODY;
471 body = hdr + SMB2_HDR_BODY;
472 dyn = body + body_size;
473 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
475 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
476 struct iovec *iov_tmp = NULL;
478 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
481 SMBD_SMB2_NUM_IOV_PER_REQ);
482 if (iov_tmp == NULL) {
483 TALLOC_FREE(iov_alloc);
484 return NT_STATUS_NO_MEMORY;
487 if (iov_alloc == NULL) {
490 sizeof(req->in._vector));
496 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
498 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
499 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
500 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
501 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
502 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
503 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
504 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
505 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
515 if (iov != req->in._vector) {
518 return NT_STATUS_INVALID_PARAMETER;
521 static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
522 const uint8_t *_inpdu, size_t size,
523 struct smbd_smb2_request **_req)
525 struct smbd_server_connection *sconn = xconn->client->sconn;
526 struct smbd_smb2_request *req;
527 uint32_t protocol_version;
528 uint8_t *inpdu = NULL;
529 const uint8_t *inhdr = NULL;
531 uint32_t next_command_ofs;
535 if (size < (SMB2_HDR_BODY + 2)) {
536 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
537 return NT_STATUS_INVALID_PARAMETER;
542 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
543 if (protocol_version != SMB2_MAGIC) {
544 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
546 return NT_STATUS_INVALID_PARAMETER;
549 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
550 if (cmd != SMB2_OP_NEGPROT) {
551 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
553 return NT_STATUS_INVALID_PARAMETER;
556 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
557 if (next_command_ofs != 0) {
558 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
560 return NT_STATUS_INVALID_PARAMETER;
563 req = smbd_smb2_request_allocate(xconn);
565 return NT_STATUS_NO_MEMORY;
570 inpdu = talloc_memdup(req, _inpdu, size);
572 return NT_STATUS_NO_MEMORY;
575 req->request_time = timeval_current();
576 now = timeval_to_nttime(&req->request_time);
578 status = smbd_smb2_inbuf_parse_compound(xconn,
582 req, &req->in.vector,
583 &req->in.vector_count);
584 if (!NT_STATUS_IS_OK(status)) {
589 req->current_idx = 1;
595 static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
596 uint64_t message_id, uint64_t seq_id)
598 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
602 seq_tmp = xconn->smb2.credits.seq_low;
603 if (seq_id < seq_tmp) {
604 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
605 "%llu (sequence id %llu) "
606 "(granted = %u, low = %llu, range = %u)\n",
607 (unsigned long long)message_id,
608 (unsigned long long)seq_id,
609 (unsigned int)xconn->smb2.credits.granted,
610 (unsigned long long)xconn->smb2.credits.seq_low,
611 (unsigned int)xconn->smb2.credits.seq_range));
615 seq_tmp += xconn->smb2.credits.seq_range;
616 if (seq_id >= seq_tmp) {
617 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
618 "%llu (sequence id %llu) "
619 "(granted = %u, low = %llu, range = %u)\n",
620 (unsigned long long)message_id,
621 (unsigned long long)seq_id,
622 (unsigned int)xconn->smb2.credits.granted,
623 (unsigned long long)xconn->smb2.credits.seq_low,
624 (unsigned int)xconn->smb2.credits.seq_range));
628 offset = seq_id % xconn->smb2.credits.max;
630 if (bitmap_query(credits_bm, offset)) {
631 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
632 "%llu (sequence id %llu) "
633 "(granted = %u, low = %llu, range = %u) "
635 (unsigned long long)message_id,
636 (unsigned long long)seq_id,
637 (unsigned int)xconn->smb2.credits.granted,
638 (unsigned long long)xconn->smb2.credits.seq_low,
639 (unsigned int)xconn->smb2.credits.seq_range,
644 /* Mark the message_ids as seen in the bitmap. */
645 bitmap_set(credits_bm, offset);
647 if (seq_id != xconn->smb2.credits.seq_low) {
652 * Move the window forward by all the message_id's
655 while (bitmap_query(credits_bm, offset)) {
656 DEBUG(10,("smb2_validate_sequence_number: clearing "
657 "id %llu (position %u) from bitmap\n",
658 (unsigned long long)(xconn->smb2.credits.seq_low),
660 bitmap_clear(credits_bm, offset);
662 xconn->smb2.credits.seq_low += 1;
663 xconn->smb2.credits.seq_range -= 1;
664 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
670 static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
671 const uint8_t *inhdr)
673 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
674 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
675 uint16_t credit_charge = 1;
678 if (opcode == SMB2_OP_CANCEL) {
679 /* SMB2_CANCEL requests by definition resend messageids. */
683 if (xconn->smb2.credits.multicredit) {
684 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
685 credit_charge = MAX(credit_charge, 1);
688 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
689 "credits_granted %llu, "
690 "seqnum low/range: %llu/%llu\n",
691 (unsigned long long) message_id,
692 (unsigned long long) credit_charge,
693 (unsigned long long) xconn->smb2.credits.granted,
694 (unsigned long long) xconn->smb2.credits.seq_low,
695 (unsigned long long) xconn->smb2.credits.seq_range));
697 if (xconn->smb2.credits.granted < credit_charge) {
698 DEBUG(0, ("smb2_validate_message_id: client used more "
699 "credits than granted, mid %llu, charge %llu, "
700 "credits_granted %llu, "
701 "seqnum low/range: %llu/%llu\n",
702 (unsigned long long) message_id,
703 (unsigned long long) credit_charge,
704 (unsigned long long) xconn->smb2.credits.granted,
705 (unsigned long long) xconn->smb2.credits.seq_low,
706 (unsigned long long) xconn->smb2.credits.seq_range));
711 * now check the message ids
713 * for multi-credit requests we need to check all current mid plus
714 * the implicit mids caused by the credit charge
715 * e.g. current mid = 15, charge 5 => mark 15-19 as used
718 for (i = 0; i <= (credit_charge-1); i++) {
719 uint64_t id = message_id + i;
722 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
723 (unsigned long long)message_id,
725 (unsigned long long)id));
727 ok = smb2_validate_sequence_number(xconn, message_id, id);
733 /* substract used credits */
734 xconn->smb2.credits.granted -= credit_charge;
739 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
744 count = req->in.vector_count;
746 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
747 /* It's not a SMB2 request */
748 return NT_STATUS_INVALID_PARAMETER;
751 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
752 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
753 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
754 const uint8_t *inhdr = NULL;
756 if (hdr->iov_len != SMB2_HDR_BODY) {
757 return NT_STATUS_INVALID_PARAMETER;
760 if (body->iov_len < 2) {
761 return NT_STATUS_INVALID_PARAMETER;
764 inhdr = (const uint8_t *)hdr->iov_base;
766 /* Check the SMB2 header */
767 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
768 return NT_STATUS_INVALID_PARAMETER;
771 if (!smb2_validate_message_id(req->xconn, inhdr)) {
772 return NT_STATUS_INVALID_PARAMETER;
779 static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
780 const struct iovec *in_vector,
781 struct iovec *out_vector)
783 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
784 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
785 uint16_t credit_charge = 1;
786 uint16_t credits_requested;
790 uint16_t credits_granted = 0;
791 uint64_t credits_possible;
792 uint16_t current_max_credits;
795 * first we grant only 1/16th of the max range.
797 * Windows also starts with the 1/16th and then grants
798 * more later. I was only able to trigger higher
799 * values, when using a very high credit charge.
801 * TODO: scale up depending on load, free memory
803 * Maybe also on the relationship between number
804 * of requests and the used sequence number.
805 * Which means we would grant more credits
806 * for client which use multi credit requests.
808 current_max_credits = xconn->smb2.credits.max / 16;
809 current_max_credits = MAX(current_max_credits, 1);
811 if (xconn->smb2.credits.multicredit) {
812 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
813 credit_charge = MAX(credit_charge, 1);
816 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
817 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
818 credits_requested = MAX(credits_requested, 1);
819 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
820 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
822 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
824 if (xconn->smb2.credits.max < credit_charge) {
825 smbd_server_connection_terminate(xconn,
826 "client error: credit charge > max credits\n");
830 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
832 * In case we already send an async interim
833 * response, we should not grant
834 * credits on the final response.
838 uint16_t additional_possible =
839 xconn->smb2.credits.max - credit_charge;
840 uint16_t additional_max = 0;
841 uint16_t additional_credits = credits_requested - 1;
844 case SMB2_OP_NEGPROT:
846 case SMB2_OP_SESSSETUP:
848 * Windows 2012 RC1 starts to grant
850 * with a successful session setup
852 if (NT_STATUS_IS_OK(out_status)) {
858 * We match windows and only grant additional credits
865 additional_max = MIN(additional_max, additional_possible);
866 additional_credits = MIN(additional_credits, additional_max);
868 credits_granted = credit_charge + additional_credits;
872 * sequence numbers should not wrap
874 * 1. calculate the possible credits until
875 * the sequence numbers start to wrap on 64-bit.
877 * 2. UINT64_MAX is used for Break Notifications.
879 * 2. truncate the possible credits to the maximum
880 * credits we want to grant to the client in total.
882 * 3. remove the range we'll already granted to the client
883 * this makes sure the client consumes the lowest sequence
884 * number, before we can grant additional credits.
886 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
887 if (credits_possible > 0) {
888 /* remove UINT64_MAX */
889 credits_possible -= 1;
891 credits_possible = MIN(credits_possible, current_max_credits);
892 credits_possible -= xconn->smb2.credits.seq_range;
894 credits_granted = MIN(credits_granted, credits_possible);
896 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
897 xconn->smb2.credits.granted += credits_granted;
898 xconn->smb2.credits.seq_range += credits_granted;
900 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
901 "granted %u, current possible/max %u/%u, "
902 "total granted/max/low/range %u/%u/%llu/%u\n",
903 (unsigned int)credits_requested,
904 (unsigned int)credit_charge,
905 (unsigned int)credits_granted,
906 (unsigned int)credits_possible,
907 (unsigned int)current_max_credits,
908 (unsigned int)xconn->smb2.credits.granted,
909 (unsigned int)xconn->smb2.credits.max,
910 (unsigned long long)xconn->smb2.credits.seq_low,
911 (unsigned int)xconn->smb2.credits.seq_range));
914 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
915 struct smbd_smb2_request *outreq)
918 uint16_t total_credits = 0;
920 count = outreq->out.vector_count;
922 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
923 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
924 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
925 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
927 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
929 /* To match Windows, count up what we
931 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
932 /* Set to zero in all but the last reply. */
933 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
934 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
936 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
941 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
943 if (req->current_idx <= 1) {
944 if (size <= sizeof(req->out._body)) {
945 return data_blob_const(req->out._body, size);
949 return data_blob_talloc(req, NULL, size);
952 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
954 struct smbXsrv_connection *xconn = req->xconn;
956 struct iovec *vector;
961 count = req->in.vector_count;
962 if (count <= ARRAY_SIZE(req->out._vector)) {
964 vector = req->out._vector;
966 vector = talloc_zero_array(req, struct iovec, count);
967 if (vector == NULL) {
968 return NT_STATUS_NO_MEMORY;
973 vector[0].iov_base = req->out.nbt_hdr;
974 vector[0].iov_len = 4;
975 SIVAL(req->out.nbt_hdr, 0, 0);
977 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
978 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
979 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
980 uint8_t *outhdr = NULL;
981 uint8_t *outbody = NULL;
982 uint32_t next_command_ofs = 0;
983 struct iovec *current = &vector[idx];
985 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
986 /* we have a next command -
987 * setup for the error case. */
988 next_command_ofs = SMB2_HDR_BODY + 9;
992 outhdr = req->out._hdr;
994 outhdr = talloc_zero_array(mem_ctx, uint8_t,
996 if (outhdr == NULL) {
997 return NT_STATUS_NO_MEMORY;
1001 outbody = outhdr + SMB2_HDR_BODY;
1004 * SMBD_SMB2_TF_IOV_OFS might be used later
1006 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1007 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1009 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
1010 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1012 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1013 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1015 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1016 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1018 /* setup the SMB2 header */
1019 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1020 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1021 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1022 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1023 SIVAL(outhdr, SMB2_HDR_STATUS,
1024 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1025 SSVAL(outhdr, SMB2_HDR_OPCODE,
1026 SVAL(inhdr, SMB2_HDR_OPCODE));
1027 SIVAL(outhdr, SMB2_HDR_FLAGS,
1028 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1029 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1030 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1031 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1032 SIVAL(outhdr, SMB2_HDR_PID,
1033 IVAL(inhdr, SMB2_HDR_PID));
1034 SIVAL(outhdr, SMB2_HDR_TID,
1035 IVAL(inhdr, SMB2_HDR_TID));
1036 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1037 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1038 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1039 inhdr + SMB2_HDR_SIGNATURE, 16);
1041 /* setup error body header */
1042 SSVAL(outbody, 0x00, 0x08 + 1);
1043 SSVAL(outbody, 0x02, 0);
1044 SIVAL(outbody, 0x04, 0);
1047 req->out.vector = vector;
1048 req->out.vector_count = count;
1050 /* setup the length of the NBT packet */
1051 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1053 return NT_STATUS_INVALID_PARAMETER_MIX;
1056 DLIST_ADD_END(xconn->smb2.requests, req, struct smbd_smb2_request *);
1058 return NT_STATUS_OK;
1061 void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
1063 const char *location)
1065 struct smbXsrv_client *client = xconn->client;
1067 DEBUG(10,("smbd_server_connection_terminate_ex: conn[%s] reason[%s] at %s\n",
1068 smbXsrv_connection_dbg(xconn), reason, location));
1070 if (client->connections->next != NULL) {
1071 /* TODO: cancel pending requests */
1072 DLIST_REMOVE(client->connections, xconn);
1078 * The last connection was disconnected
1080 exit_server_cleanly(reason);
1083 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1084 struct iovec *outvec,
1085 const struct iovec *srcvec)
1087 const uint8_t *srctf;
1089 const uint8_t *srchdr;
1091 const uint8_t *srcbody;
1093 const uint8_t *expected_srcbody;
1094 const uint8_t *srcdyn;
1096 const uint8_t *expected_srcdyn;
1102 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1103 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1104 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1105 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1106 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1107 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1108 expected_srcbody = srchdr + SMB2_HDR_BODY;
1109 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1110 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1111 expected_srcdyn = srcbody + 8;
1113 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1117 if (srchdr_len != SMB2_HDR_BODY) {
1121 if (srctf_len == SMB2_TF_HDR_SIZE) {
1122 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1123 if (dsttf == NULL) {
1129 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1130 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1132 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1133 * be allocated with size OUTVEC_ALLOC_SIZE. */
1135 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1136 if (dsthdr == NULL) {
1139 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1140 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1143 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1144 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1145 * then duplicate this. Else use talloc_memdup().
1148 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1149 dstbody = dsthdr + SMB2_HDR_BODY;
1151 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1152 if (dstbody == NULL) {
1156 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1157 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1160 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1162 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1163 * then duplicate this. Else use talloc_memdup().
1166 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1167 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1168 } else if (srcdyn == NULL) {
1171 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1172 if (dstdyn == NULL) {
1176 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1177 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1182 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1184 struct smbd_smb2_request *newreq = NULL;
1185 struct iovec *outvec = NULL;
1186 int count = req->out.vector_count;
1190 newreq = smbd_smb2_request_allocate(req->xconn);
1195 newreq->sconn = req->sconn;
1196 newreq->xconn = req->xconn;
1197 newreq->session = req->session;
1198 newreq->do_encryption = req->do_encryption;
1199 newreq->do_signing = req->do_signing;
1200 newreq->current_idx = req->current_idx;
1202 outvec = talloc_zero_array(newreq, struct iovec, count);
1204 TALLOC_FREE(newreq);
1207 newreq->out.vector = outvec;
1208 newreq->out.vector_count = count;
1210 /* Setup the outvec's identically to req. */
1211 outvec[0].iov_base = newreq->out.nbt_hdr;
1212 outvec[0].iov_len = 4;
1213 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1215 /* Setup the vectors identically to the ones in req. */
1216 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1217 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1224 TALLOC_FREE(newreq);
1228 ok = smb2_setup_nbt_length(newreq->out.vector,
1229 newreq->out.vector_count);
1231 TALLOC_FREE(newreq);
1238 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1240 struct smbXsrv_connection *xconn = req->xconn;
1242 struct iovec *firsttf = NULL;
1243 struct iovec *outhdr_v = NULL;
1244 uint8_t *outhdr = NULL;
1245 struct smbd_smb2_request *nreq = NULL;
1249 /* Create a new smb2 request we'll use
1250 for the interim return. */
1251 nreq = dup_smb2_req(req);
1253 return NT_STATUS_NO_MEMORY;
1256 /* Lose the last X out vectors. They're the
1257 ones we'll be using for the async reply. */
1258 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1260 ok = smb2_setup_nbt_length(nreq->out.vector,
1261 nreq->out.vector_count);
1263 return NT_STATUS_INVALID_PARAMETER_MIX;
1266 /* Step back to the previous reply. */
1267 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1268 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1269 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1270 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1271 /* And end the chain. */
1272 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1274 /* Calculate outgoing credits */
1275 smb2_calculate_credits(req, nreq);
1277 if (DEBUGLEVEL >= 10) {
1278 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1279 (unsigned int)nreq->current_idx );
1280 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1281 (unsigned int)nreq->out.vector_count );
1282 print_req_vectors(nreq);
1286 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1287 * we need to sign/encrypt here with the last/first key we remembered
1289 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1290 status = smb2_signing_encrypt_pdu(req->first_key,
1291 xconn->smb2.server.cipher,
1293 nreq->out.vector_count - first_idx);
1294 if (!NT_STATUS_IS_OK(status)) {
1297 } else if (req->last_key.length > 0) {
1298 status = smb2_signing_sign_pdu(req->last_key,
1301 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1302 if (!NT_STATUS_IS_OK(status)) {
1307 nreq->queue_entry.mem_ctx = nreq;
1308 nreq->queue_entry.vector = nreq->out.vector;
1309 nreq->queue_entry.count = nreq->out.vector_count;
1310 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry, NULL);
1311 xconn->smb2.send_queue_len++;
1313 status = smbd_smb2_flush_send_queue(xconn);
1314 if (!NT_STATUS_IS_OK(status)) {
1318 return NT_STATUS_OK;
1321 struct smbd_smb2_request_pending_state {
1322 struct smbd_smb2_send_queue queue_entry;
1323 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1324 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1327 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1328 struct tevent_timer *te,
1329 struct timeval current_time,
1330 void *private_data);
1332 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1333 struct tevent_req *subreq,
1334 uint32_t defer_time)
1337 struct timeval defer_endtime;
1338 uint8_t *outhdr = NULL;
1341 if (!tevent_req_is_in_progress(subreq)) {
1343 * This is a performance optimization,
1344 * it avoids one tevent_loop iteration,
1345 * which means we avoid one
1346 * talloc_stackframe_pool/talloc_free pair.
1348 tevent_req_notify_callback(subreq);
1349 return NT_STATUS_OK;
1352 req->subreq = subreq;
1355 if (req->async_te) {
1356 /* We're already async. */
1357 return NT_STATUS_OK;
1360 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1361 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1362 if (flags & SMB2_HDR_FLAG_ASYNC) {
1363 /* We're already async. */
1364 return NT_STATUS_OK;
1367 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1369 * We're trying to go async in a compound request
1370 * chain. This is only allowed for opens that cause an
1371 * oplock break or for the last operation in the
1372 * chain, otherwise it is not allowed. See
1373 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
1375 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1377 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1379 * Cancel the outstanding request.
1381 bool ok = tevent_req_cancel(req->subreq);
1383 return NT_STATUS_OK;
1385 TALLOC_FREE(req->subreq);
1386 return smbd_smb2_request_error(req,
1387 NT_STATUS_INTERNAL_ERROR);
1391 if (DEBUGLEVEL >= 10) {
1392 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1393 (unsigned int)req->current_idx );
1394 print_req_vectors(req);
1397 if (req->current_idx > 1) {
1399 * We're going async in a compound
1400 * chain after the first request has
1401 * already been processed. Send an
1402 * interim response containing the
1403 * set of replies already generated.
1405 int idx = req->current_idx;
1407 status = smb2_send_async_interim_response(req);
1408 if (!NT_STATUS_IS_OK(status)) {
1411 if (req->first_key.length > 0) {
1412 data_blob_clear_free(&req->first_key);
1415 req->current_idx = 1;
1418 * Re-arrange the in.vectors to remove what
1421 memmove(&req->in.vector[1],
1422 &req->in.vector[idx],
1423 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1424 req->in.vector_count = 1 + (req->in.vector_count - idx);
1426 /* Re-arrange the out.vectors to match. */
1427 memmove(&req->out.vector[1],
1428 &req->out.vector[idx],
1429 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1430 req->out.vector_count = 1 + (req->out.vector_count - idx);
1432 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1434 * We only have one remaining request as
1435 * we've processed everything else.
1436 * This is no longer a compound request.
1438 req->compound_related = false;
1439 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1440 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1441 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1444 if (req->last_key.length > 0) {
1445 data_blob_clear_free(&req->last_key);
1448 defer_endtime = timeval_current_ofs_usec(defer_time);
1449 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1451 smbd_smb2_request_pending_timer,
1453 if (req->async_te == NULL) {
1454 return NT_STATUS_NO_MEMORY;
1457 return NT_STATUS_OK;
1460 static DATA_BLOB smbd_smb2_signing_key(struct smbXsrv_session *session,
1461 struct smbXsrv_connection *xconn)
1463 struct smbXsrv_channel_global0 *c = NULL;
1465 DATA_BLOB key = data_blob_null;
1467 status = smbXsrv_session_find_channel(session, xconn, &c);
1468 if (NT_STATUS_IS_OK(status)) {
1469 key = c->signing_key;
1472 if (key.length == 0) {
1473 key = session->global->signing_key;
1479 static NTSTATUS smb2_get_new_nonce(struct smbXsrv_session *session,
1480 uint64_t *new_nonce_high,
1481 uint64_t *new_nonce_low)
1483 uint64_t nonce_high;
1486 session->nonce_low += 1;
1487 if (session->nonce_low == 0) {
1488 session->nonce_low += 1;
1489 session->nonce_high += 1;
1493 * CCM and GCM algorithms must never have their
1494 * nonce wrap, or the security of the whole
1495 * communication and the keys is destroyed.
1496 * We must drop the connection once we have
1497 * transfered too much data.
1499 * NOTE: We assume nonces greater than 8 bytes.
1501 if (session->nonce_high >= session->nonce_high_max) {
1502 return NT_STATUS_ENCRYPTION_FAILED;
1505 nonce_high = session->nonce_high_random;
1506 nonce_high += session->nonce_high;
1507 nonce_low = session->nonce_low;
1509 *new_nonce_high = nonce_high;
1510 *new_nonce_low = nonce_low;
1511 return NT_STATUS_OK;
1514 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1515 struct tevent_timer *te,
1516 struct timeval current_time,
1519 struct smbd_smb2_request *req =
1520 talloc_get_type_abort(private_data,
1521 struct smbd_smb2_request);
1522 struct smbXsrv_connection *xconn = req->xconn;
1523 struct smbd_smb2_request_pending_state *state = NULL;
1524 uint8_t *outhdr = NULL;
1525 const uint8_t *inhdr = NULL;
1528 uint8_t *hdr = NULL;
1529 uint8_t *body = NULL;
1530 uint8_t *dyn = NULL;
1532 uint64_t session_id = 0;
1533 uint64_t message_id = 0;
1534 uint64_t nonce_high = 0;
1535 uint64_t nonce_low = 0;
1536 uint64_t async_id = 0;
1540 TALLOC_FREE(req->async_te);
1542 /* Ensure our final reply matches the interim one. */
1543 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1544 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1545 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1546 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1547 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1549 async_id = message_id; /* keep it simple for now... */
1551 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1552 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1554 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1556 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1557 (unsigned long long)async_id ));
1560 * What we send is identical to a smbd_smb2_request_error
1561 * packet with an error status of STATUS_PENDING. Make use
1562 * of this fact sometime when refactoring. JRA.
1565 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
1566 if (state == NULL) {
1567 smbd_server_connection_terminate(xconn,
1568 nt_errstr(NT_STATUS_NO_MEMORY));
1572 tf = state->buf + NBT_HDR_SIZE;
1573 tf_len = SMB2_TF_HDR_SIZE;
1575 hdr = tf + SMB2_TF_HDR_SIZE;
1576 body = hdr + SMB2_HDR_BODY;
1579 if (req->do_encryption) {
1580 status = smb2_get_new_nonce(req->session,
1583 if (!NT_STATUS_IS_OK(status)) {
1584 smbd_server_connection_terminate(xconn,
1590 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1591 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1592 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1593 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1595 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1596 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1597 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1598 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1599 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1601 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1602 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1603 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1604 SBVAL(hdr, SMB2_HDR_PID, async_id);
1605 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1606 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1607 memcpy(hdr+SMB2_HDR_SIGNATURE,
1608 outhdr+SMB2_HDR_SIGNATURE, 16);
1610 SSVAL(body, 0x00, 0x08 + 1);
1612 SCVAL(body, 0x02, 0);
1613 SCVAL(body, 0x03, 0);
1614 SIVAL(body, 0x04, 0);
1615 /* Match W2K8R2... */
1616 SCVAL(dyn, 0x00, 0x21);
1618 state->vector[0].iov_base = (void *)state->buf;
1619 state->vector[0].iov_len = NBT_HDR_SIZE;
1621 if (req->do_encryption) {
1622 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1623 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1625 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1626 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1629 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1630 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1632 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1633 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1635 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1636 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1638 ok = smb2_setup_nbt_length(state->vector,
1639 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1641 smbd_server_connection_terminate(
1642 xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
1646 /* Ensure we correctly go through crediting. Grant
1647 the credits now, and zero credits on the final
1649 smb2_set_operation_credit(req->xconn,
1650 SMBD_SMB2_IN_HDR_IOV(req),
1651 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1653 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1658 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1659 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1661 (unsigned int)ARRAY_SIZE(state->vector),
1662 (unsigned int)state->vector[i].iov_len);
1666 if (req->do_encryption) {
1667 struct smbXsrv_session *x = req->session;
1668 DATA_BLOB encryption_key = x->global->encryption_key;
1670 status = smb2_signing_encrypt_pdu(encryption_key,
1671 xconn->smb2.server.cipher,
1672 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1673 SMBD_SMB2_NUM_IOV_PER_REQ);
1674 if (!NT_STATUS_IS_OK(status)) {
1675 smbd_server_connection_terminate(xconn,
1679 } else if (req->do_signing) {
1680 struct smbXsrv_session *x = req->session;
1681 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
1683 status = smb2_signing_sign_pdu(signing_key,
1685 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1686 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1687 if (!NT_STATUS_IS_OK(status)) {
1688 smbd_server_connection_terminate(xconn,
1694 state->queue_entry.mem_ctx = state;
1695 state->queue_entry.vector = state->vector;
1696 state->queue_entry.count = ARRAY_SIZE(state->vector);
1697 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
1698 xconn->smb2.send_queue_len++;
1700 status = smbd_smb2_flush_send_queue(xconn);
1701 if (!NT_STATUS_IS_OK(status)) {
1702 smbd_server_connection_terminate(xconn,
1708 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1710 struct smbXsrv_connection *xconn = req->xconn;
1711 struct smbd_smb2_request *cur;
1712 const uint8_t *inhdr;
1714 uint64_t search_message_id;
1715 uint64_t search_async_id;
1718 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1720 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1721 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1722 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1725 * we don't need the request anymore
1726 * cancel requests never have a response
1728 DLIST_REMOVE(xconn->smb2.requests, req);
1731 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1732 const uint8_t *outhdr;
1733 uint64_t message_id;
1736 if (cur->compound_related) {
1738 * Never cancel anything in a compound request.
1739 * Way too hard to deal with the result.
1744 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1746 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1747 async_id = BVAL(outhdr, SMB2_HDR_PID);
1749 if (flags & SMB2_HDR_FLAG_ASYNC) {
1750 if (search_async_id == async_id) {
1751 found_id = async_id;
1755 if (search_message_id == message_id) {
1756 found_id = message_id;
1762 if (cur && cur->subreq) {
1763 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1764 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1765 "cancel opcode[%s] mid %llu\n",
1766 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1767 (unsigned long long)found_id ));
1768 tevent_req_cancel(cur->subreq);
1771 return NT_STATUS_OK;
1774 /*************************************************************
1775 Ensure an incoming tid is a valid one for us to access.
1776 Change to the associated uid credentials and chdir to the
1777 valid tid directory.
1778 *************************************************************/
1780 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1782 const uint8_t *inhdr;
1785 struct smbXsrv_tcon *tcon;
1787 NTTIME now = timeval_to_nttime(&req->request_time);
1791 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1793 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1794 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1796 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1797 in_tid = req->last_tid;
1802 status = smb2srv_tcon_lookup(req->session,
1803 in_tid, now, &tcon);
1804 if (!NT_STATUS_IS_OK(status)) {
1808 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1809 return NT_STATUS_ACCESS_DENIED;
1812 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1813 if (!set_current_service(tcon->compat, 0, true)) {
1814 return NT_STATUS_ACCESS_DENIED;
1818 req->last_tid = in_tid;
1820 return NT_STATUS_OK;
1823 /*************************************************************
1824 Ensure an incoming session_id is a valid one for us to access.
1825 *************************************************************/
1827 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1829 const uint8_t *inhdr;
1832 uint64_t in_session_id;
1833 struct smbXsrv_session *session = NULL;
1834 struct auth_session_info *session_info;
1836 NTTIME now = timeval_to_nttime(&req->request_time);
1838 req->session = NULL;
1841 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1843 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1844 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1845 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1847 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1848 in_session_id = req->last_session_id;
1851 req->last_session_id = 0;
1853 /* look an existing session up */
1854 switch (in_opcode) {
1855 case SMB2_OP_SESSSETUP:
1857 * For a session bind request, we don't have the
1858 * channel set up at this point yet, so we defer
1859 * the verification that the connection belongs
1860 * to the session to the session setup code, which
1861 * can look at the session binding flags.
1863 status = smb2srv_session_lookup_client(req->xconn->client,
1868 status = smb2srv_session_lookup_conn(req->xconn,
1874 req->session = session;
1875 req->last_session_id = in_session_id;
1877 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1878 switch (in_opcode) {
1879 case SMB2_OP_SESSSETUP:
1880 status = NT_STATUS_OK;
1886 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1887 switch (in_opcode) {
1889 case SMB2_OP_CREATE:
1890 case SMB2_OP_GETINFO:
1891 case SMB2_OP_SETINFO:
1892 return NT_STATUS_INVALID_HANDLE;
1895 * Notice the check for
1896 * (session_info == NULL)
1899 status = NT_STATUS_OK;
1903 if (!NT_STATUS_IS_OK(status)) {
1907 session_info = session->global->auth_session_info;
1908 if (session_info == NULL) {
1909 return NT_STATUS_INVALID_HANDLE;
1912 if (in_session_id != req->xconn->client->last_session_id) {
1913 req->xconn->client->last_session_id = in_session_id;
1914 set_current_user_info(session_info->unix_info->sanitized_username,
1915 session_info->unix_info->unix_name,
1916 session_info->info->domain_name);
1919 return NT_STATUS_OK;
1922 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1923 uint32_t data_length)
1925 struct smbXsrv_connection *xconn = req->xconn;
1926 uint16_t needed_charge;
1927 uint16_t credit_charge = 1;
1928 const uint8_t *inhdr;
1930 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1932 if (xconn->smb2.credits.multicredit) {
1933 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1934 credit_charge = MAX(credit_charge, 1);
1937 needed_charge = (data_length - 1)/ 65536 + 1;
1939 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1940 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1941 credit_charge, needed_charge));
1943 if (needed_charge > credit_charge) {
1944 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1945 credit_charge, needed_charge));
1946 return NT_STATUS_INVALID_PARAMETER;
1949 return NT_STATUS_OK;
1952 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1953 size_t expected_body_size)
1955 struct iovec *inhdr_v;
1956 const uint8_t *inhdr;
1958 const uint8_t *inbody;
1960 size_t min_dyn_size = expected_body_size & 0x00000001;
1961 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1964 * The following should be checked already.
1966 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1967 return NT_STATUS_INTERNAL_ERROR;
1969 if (req->current_idx > max_idx) {
1970 return NT_STATUS_INTERNAL_ERROR;
1973 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1974 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1975 return NT_STATUS_INTERNAL_ERROR;
1977 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1978 return NT_STATUS_INTERNAL_ERROR;
1981 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1982 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1986 case SMB2_OP_GETINFO:
1990 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
1991 if (req->smb1req->unread_bytes < min_dyn_size) {
1992 return NT_STATUS_INVALID_PARAMETER;
2001 * Now check the expected body size,
2002 * where the last byte might be in the
2005 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
2006 return NT_STATUS_INVALID_PARAMETER;
2008 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
2009 return NT_STATUS_INVALID_PARAMETER;
2012 inbody = SMBD_SMB2_IN_BODY_PTR(req);
2014 body_size = SVAL(inbody, 0x00);
2015 if (body_size != expected_body_size) {
2016 return NT_STATUS_INVALID_PARAMETER;
2019 return NT_STATUS_OK;
2022 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
2024 struct smbXsrv_connection *xconn = req->xconn;
2025 const struct smbd_smb2_dispatch_table *call = NULL;
2026 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
2027 const uint8_t *inhdr;
2031 uint16_t channel_sequence;
2033 NTSTATUS session_status;
2034 uint32_t allowed_flags;
2035 NTSTATUS return_value;
2036 struct smbXsrv_session *x = NULL;
2037 bool signing_required = false;
2038 bool encryption_desired = false;
2039 bool encryption_required = false;
2040 struct smbXsrv_open *op = NULL;
2042 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2044 DO_PROFILE_INC(request);
2046 /* TODO: verify more things */
2048 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2049 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2050 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2051 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2052 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
2053 smb2_opcode_name(opcode),
2054 (unsigned long long)mid));
2056 if (xconn->protocol >= PROTOCOL_SMB2_02) {
2058 * once the protocol is negotiated
2059 * SMB2_OP_NEGPROT is not allowed anymore
2061 if (opcode == SMB2_OP_NEGPROT) {
2062 /* drop the connection */
2063 return NT_STATUS_INVALID_PARAMETER;
2067 * if the protocol is not negotiated yet
2068 * only SMB2_OP_NEGPROT is allowed.
2070 if (opcode != SMB2_OP_NEGPROT) {
2071 /* drop the connection */
2072 return NT_STATUS_INVALID_PARAMETER;
2077 * Check if the client provided a valid session id,
2078 * if so smbd_smb2_request_check_session() calls
2079 * set_current_user_info().
2081 * As some command don't require a valid session id
2082 * we defer the check of the session_status
2084 session_status = smbd_smb2_request_check_session(req);
2087 signing_required = x->global->signing_required;
2088 encryption_desired = x->encryption_desired;
2089 encryption_required = x->global->encryption_required;
2092 req->do_signing = false;
2093 req->do_encryption = false;
2094 req->was_encrypted = false;
2095 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
2096 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
2097 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
2099 if (x != NULL && x->global->session_wire_id != tf_session_id) {
2100 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2101 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
2102 (unsigned long long)x->global->session_wire_id,
2103 (unsigned long long)tf_session_id));
2105 * TODO: windows allows this...
2106 * should we drop the connection?
2108 * For now we just return ACCESS_DENIED
2109 * (Windows clients never trigger this)
2110 * and wait for an update of [MS-SMB2].
2112 return smbd_smb2_request_error(req,
2113 NT_STATUS_ACCESS_DENIED);
2116 req->was_encrypted = true;
2119 if (encryption_required && !req->was_encrypted) {
2120 return smbd_smb2_request_error(req,
2121 NT_STATUS_ACCESS_DENIED);
2124 call = smbd_smb2_call(opcode);
2126 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2129 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2130 SMB2_HDR_FLAG_SIGNED |
2132 if (xconn->protocol >= PROTOCOL_SMB3_11) {
2133 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2135 if (opcode == SMB2_OP_NEGPROT) {
2136 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11) {
2137 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2140 if (opcode == SMB2_OP_CANCEL) {
2141 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2143 if (xconn->protocol >= PROTOCOL_SMB2_22) {
2144 allowed_flags |= SMB2_HDR_FLAG_REPLAY_OPERATION;
2146 if ((flags & ~allowed_flags) != 0) {
2147 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2150 if (flags & SMB2_HDR_FLAG_CHAINED) {
2152 * This check is mostly for giving the correct error code
2153 * for compounded requests.
2155 if (!NT_STATUS_IS_OK(session_status)) {
2156 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2159 req->compat_chain_fsp = NULL;
2162 if (req->was_encrypted) {
2163 signing_required = false;
2164 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2165 DATA_BLOB signing_key = data_blob_null;
2169 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2170 * If the SMB2 header of the SMB2 NEGOTIATE
2171 * request has the SMB2_FLAGS_SIGNED bit set in the
2172 * Flags field, the server MUST fail the request
2173 * with STATUS_INVALID_PARAMETER.
2175 * Microsoft test tool checks this.
2178 if ((opcode == SMB2_OP_NEGPROT) &&
2179 (flags & SMB2_HDR_FLAG_SIGNED)) {
2180 status = NT_STATUS_INVALID_PARAMETER;
2182 status = NT_STATUS_USER_SESSION_DELETED;
2184 return smbd_smb2_request_error(req, status);
2187 signing_key = smbd_smb2_signing_key(x, xconn);
2190 * If we have a signing key, we should
2193 if (signing_key.length > 0) {
2194 req->do_signing = true;
2197 status = smb2_signing_check_pdu(signing_key,
2199 SMBD_SMB2_IN_HDR_IOV(req),
2200 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2201 if (!NT_STATUS_IS_OK(status)) {
2202 return smbd_smb2_request_error(req, status);
2206 * Now that we know the request was correctly signed
2207 * we have to sign the response too.
2209 req->do_signing = true;
2211 if (!NT_STATUS_IS_OK(session_status)) {
2212 return smbd_smb2_request_error(req, session_status);
2214 } else if (opcode == SMB2_OP_CANCEL) {
2215 /* Cancel requests are allowed to skip the signing */
2216 } else if (signing_required) {
2218 * If signing is required we try to sign
2219 * a possible error response
2221 req->do_signing = true;
2222 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2225 if (flags & SMB2_HDR_FLAG_CHAINED) {
2226 req->compound_related = true;
2229 if (call->need_session) {
2230 if (!NT_STATUS_IS_OK(session_status)) {
2231 return smbd_smb2_request_error(req, session_status);
2235 if (call->need_tcon) {
2236 SMB_ASSERT(call->need_session);
2239 * This call needs to be run as user.
2241 * smbd_smb2_request_check_tcon()
2242 * calls change_to_user() on success.
2244 status = smbd_smb2_request_check_tcon(req);
2245 if (!NT_STATUS_IS_OK(status)) {
2246 return smbd_smb2_request_error(req, status);
2248 if (req->tcon->encryption_desired) {
2249 encryption_desired = true;
2251 if (req->tcon->global->encryption_required) {
2252 encryption_required = true;
2254 if (encryption_required && !req->was_encrypted) {
2255 return smbd_smb2_request_error(req,
2256 NT_STATUS_ACCESS_DENIED);
2260 if (req->was_encrypted || encryption_desired) {
2261 req->do_encryption = true;
2264 if (call->fileid_ofs != 0) {
2265 size_t needed = call->fileid_ofs + 16;
2266 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2267 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2268 uint64_t file_id_persistent;
2269 uint64_t file_id_volatile;
2270 struct files_struct *fsp;
2272 SMB_ASSERT(call->need_tcon);
2274 if (needed > body_size) {
2275 return smbd_smb2_request_error(req,
2276 NT_STATUS_INVALID_PARAMETER);
2279 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2280 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2282 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2286 if (!call->allow_invalid_fileid) {
2287 return smbd_smb2_request_error(req,
2288 NT_STATUS_FILE_CLOSED);
2291 if (file_id_persistent != UINT64_MAX) {
2292 return smbd_smb2_request_error(req,
2293 NT_STATUS_FILE_CLOSED);
2295 if (file_id_volatile != UINT64_MAX) {
2296 return smbd_smb2_request_error(req,
2297 NT_STATUS_FILE_CLOSED);
2302 if ((xconn->protocol >= PROTOCOL_SMB2_22) && (op != NULL)) {
2303 int cmp = channel_sequence - op->global->channel_sequence;
2304 //bool overflow = false;
2305 bool update_open = false;
2307 if (abs(cmp) > INT16_MAX) {
2309 * we like to handle an 16-bit overflow here.
2311 * If the difference between the numbers
2312 * if more than 15-bit, it is likely to be an overflow.
2318 if (!(flags & SMB2_HDR_FLAG_REPLAY_OPERATION)) {
2320 op->request_count += 1;
2321 } else if (cmp > 0) {
2322 op->pre_request_count += op->request_count;
2323 op->request_count = 0;
2324 op->request_count += 1;
2325 op->global->channel_sequence = channel_sequence;
2327 } else if (call->modify) {
2328 return smbd_smb2_request_error(req,
2329 NT_STATUS_FILE_NOT_AVAILABLE);
2333 if (op->pre_request_count == 0) {
2334 op->request_count += 1;
2335 } else if (call->modify) {
2336 return smbd_smb2_request_error(req,
2337 NT_STATUS_FILE_NOT_AVAILABLE);
2339 } else if (cmp > 0) {
2340 if (op->pre_request_count == 0) {
2341 op->request_count += 1;
2342 op->global->channel_sequence =
2345 } else if (call->modify) {
2346 return smbd_smb2_request_error(req,
2347 NT_STATUS_FILE_NOT_AVAILABLE);
2351 return smbd_smb2_request_error(req,
2352 NT_STATUS_FILE_NOT_AVAILABLE);
2358 status = smbXsrv_open_update(op);
2359 if (!NT_STATUS_IS_OK(status)) {
2360 return smbd_smb2_request_error(req, status);
2365 if (call->as_root) {
2366 SMB_ASSERT(call->fileid_ofs == 0);
2367 /* This call needs to be run as root */
2368 change_to_root_user();
2370 SMB_ASSERT(call->need_tcon);
2373 #define _INBYTES(_r) \
2374 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
2377 case SMB2_OP_NEGPROT:
2378 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
2379 req->profile, _INBYTES(req));
2380 return_value = smbd_smb2_request_process_negprot(req);
2383 case SMB2_OP_SESSSETUP:
2384 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
2385 req->profile, _INBYTES(req));
2386 return_value = smbd_smb2_request_process_sesssetup(req);
2389 case SMB2_OP_LOGOFF:
2390 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
2391 req->profile, _INBYTES(req));
2392 return_value = smbd_smb2_request_process_logoff(req);
2396 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
2397 req->profile, _INBYTES(req));
2398 return_value = smbd_smb2_request_process_tcon(req);
2402 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
2403 req->profile, _INBYTES(req));
2404 return_value = smbd_smb2_request_process_tdis(req);
2407 case SMB2_OP_CREATE:
2408 if (req->subreq == NULL) {
2409 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
2410 req->profile, _INBYTES(req));
2412 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
2414 return_value = smbd_smb2_request_process_create(req);
2418 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
2419 req->profile, _INBYTES(req));
2420 return_value = smbd_smb2_request_process_close(req);
2424 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
2425 req->profile, _INBYTES(req));
2426 return_value = smbd_smb2_request_process_flush(req);
2430 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
2431 req->profile, _INBYTES(req));
2432 return_value = smbd_smb2_request_process_read(req);
2436 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
2437 req->profile, _INBYTES(req));
2438 return_value = smbd_smb2_request_process_write(req);
2442 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
2443 req->profile, _INBYTES(req));
2444 return_value = smbd_smb2_request_process_lock(req);
2448 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
2449 req->profile, _INBYTES(req));
2450 return_value = smbd_smb2_request_process_ioctl(req);
2453 case SMB2_OP_CANCEL:
2454 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
2455 req->profile, _INBYTES(req));
2456 return_value = smbd_smb2_request_process_cancel(req);
2457 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
2460 case SMB2_OP_KEEPALIVE:
2461 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
2462 req->profile, _INBYTES(req));
2463 return_value = smbd_smb2_request_process_keepalive(req);
2466 case SMB2_OP_QUERY_DIRECTORY:
2467 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
2468 req->profile, _INBYTES(req));
2469 return_value = smbd_smb2_request_process_query_directory(req);
2472 case SMB2_OP_NOTIFY:
2473 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
2474 req->profile, _INBYTES(req));
2475 return_value = smbd_smb2_request_process_notify(req);
2478 case SMB2_OP_GETINFO:
2479 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
2480 req->profile, _INBYTES(req));
2481 return_value = smbd_smb2_request_process_getinfo(req);
2484 case SMB2_OP_SETINFO:
2485 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
2486 req->profile, _INBYTES(req));
2487 return_value = smbd_smb2_request_process_setinfo(req);
2491 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
2492 req->profile, _INBYTES(req));
2493 return_value = smbd_smb2_request_process_break(req);
2497 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2500 return return_value;
2503 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2505 struct smbXsrv_connection *xconn = req->xconn;
2507 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2508 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2509 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2514 TALLOC_FREE(req->async_te);
2516 if (req->do_encryption &&
2517 (firsttf->iov_len == 0) &&
2518 (req->first_key.length == 0) &&
2519 (req->session != NULL) &&
2520 (req->session->global->encryption_key.length != 0))
2522 DATA_BLOB encryption_key = req->session->global->encryption_key;
2524 uint64_t session_id = req->session->global->session_wire_id;
2525 uint64_t nonce_high;
2528 status = smb2_get_new_nonce(req->session,
2531 if (!NT_STATUS_IS_OK(status)) {
2536 * We need to place the SMB2_TRANSFORM header before the
2541 * we need to remember the encryption key
2542 * and defer the signing/encryption until
2543 * we are sure that we do not change
2546 req->first_key = data_blob_dup_talloc(req, encryption_key);
2547 if (req->first_key.data == NULL) {
2548 return NT_STATUS_NO_MEMORY;
2551 tf = talloc_zero_array(req, uint8_t,
2554 return NT_STATUS_NO_MEMORY;
2557 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2558 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2559 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2560 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2562 firsttf->iov_base = (void *)tf;
2563 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2566 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2567 (req->last_key.length > 0) &&
2568 (firsttf->iov_len == 0))
2570 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2571 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2574 * As we are sure the header of the last request in the
2575 * compound chain will not change, we can to sign here
2576 * with the last signing key we remembered.
2578 status = smb2_signing_sign_pdu(req->last_key,
2581 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2582 if (!NT_STATUS_IS_OK(status)) {
2586 if (req->last_key.length > 0) {
2587 data_blob_clear_free(&req->last_key);
2590 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
2591 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
2593 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2595 if (req->current_idx < req->out.vector_count) {
2597 * We must process the remaining compound
2598 * SMB2 requests before any new incoming SMB2
2599 * requests. This is because incoming SMB2
2600 * requests may include a cancel for a
2601 * compound request we haven't processed
2604 struct tevent_immediate *im = tevent_create_immediate(req);
2606 return NT_STATUS_NO_MEMORY;
2609 if (req->do_signing && firsttf->iov_len == 0) {
2610 struct smbXsrv_session *x = req->session;
2611 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2614 * we need to remember the signing key
2615 * and defer the signing until
2616 * we are sure that we do not change
2619 req->last_key = data_blob_dup_talloc(req, signing_key);
2620 if (req->last_key.data == NULL) {
2621 return NT_STATUS_NO_MEMORY;
2625 tevent_schedule_immediate(im,
2627 smbd_smb2_request_dispatch_immediate,
2629 return NT_STATUS_OK;
2632 if (req->compound_related) {
2633 req->compound_related = false;
2636 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2638 return NT_STATUS_INVALID_PARAMETER_MIX;
2641 /* Set credit for these operations (zero credits if this
2642 is a final reply for an async operation). */
2643 smb2_calculate_credits(req, req);
2646 * now check if we need to sign the current response
2648 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2649 status = smb2_signing_encrypt_pdu(req->first_key,
2650 xconn->smb2.server.cipher,
2652 req->out.vector_count - first_idx);
2653 if (!NT_STATUS_IS_OK(status)) {
2656 } else if (req->do_signing) {
2657 struct smbXsrv_session *x = req->session;
2658 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2660 status = smb2_signing_sign_pdu(signing_key,
2663 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2664 if (!NT_STATUS_IS_OK(status)) {
2668 if (req->first_key.length > 0) {
2669 data_blob_clear_free(&req->first_key);
2672 if (req->preauth != NULL) {
2673 struct hc_sha512state sctx;
2676 samba_SHA512_Init(&sctx);
2677 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2678 sizeof(req->preauth->sha512_value));
2679 for (i = 1; i < req->in.vector_count; i++) {
2680 samba_SHA512_Update(&sctx,
2681 req->in.vector[i].iov_base,
2682 req->in.vector[i].iov_len);
2684 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2686 samba_SHA512_Init(&sctx);
2687 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2688 sizeof(req->preauth->sha512_value));
2689 for (i = 1; i < req->out.vector_count; i++) {
2690 samba_SHA512_Update(&sctx,
2691 req->out.vector[i].iov_base,
2692 req->out.vector[i].iov_len);
2694 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2696 req->preauth = NULL;
2699 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2700 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2701 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2702 /* Dynamic part is NULL. Chop it off,
2703 We're going to send it via sendfile. */
2704 req->out.vector_count -= 1;
2708 * We're done with this request -
2709 * move it off the "being processed" queue.
2711 DLIST_REMOVE(xconn->smb2.requests, req);
2713 req->queue_entry.mem_ctx = req;
2714 req->queue_entry.vector = req->out.vector;
2715 req->queue_entry.count = req->out.vector_count;
2716 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry, NULL);
2717 xconn->smb2.send_queue_len++;
2719 status = smbd_smb2_flush_send_queue(xconn);
2720 if (!NT_STATUS_IS_OK(status)) {
2724 return NT_STATUS_OK;
2727 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
2729 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2730 struct tevent_immediate *im,
2733 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2734 struct smbd_smb2_request);
2735 struct smbXsrv_connection *xconn = req->xconn;
2740 if (DEBUGLEVEL >= 10) {
2741 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2742 req->current_idx, req->in.vector_count));
2743 print_req_vectors(req);
2746 status = smbd_smb2_request_dispatch(req);
2747 if (!NT_STATUS_IS_OK(status)) {
2748 smbd_server_connection_terminate(xconn, nt_errstr(status));
2752 status = smbd_smb2_request_next_incoming(xconn);
2753 if (!NT_STATUS_IS_OK(status)) {
2754 smbd_server_connection_terminate(xconn, nt_errstr(status));
2759 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2761 DATA_BLOB body, DATA_BLOB *dyn,
2762 const char *location)
2765 struct iovec *outbody_v;
2766 struct iovec *outdyn_v;
2767 uint32_t next_command_ofs;
2769 DEBUG(10,("smbd_smb2_request_done_ex: "
2770 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2771 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2773 (unsigned int)(dyn ? dyn->length : 0),
2776 if (body.length < 2) {
2777 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2780 if ((body.length % 2) != 0) {
2781 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2784 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2785 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2786 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2788 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2789 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2791 outbody_v->iov_base = (void *)body.data;
2792 outbody_v->iov_len = body.length;
2795 outdyn_v->iov_base = (void *)dyn->data;
2796 outdyn_v->iov_len = dyn->length;
2798 outdyn_v->iov_base = NULL;
2799 outdyn_v->iov_len = 0;
2803 * See if we need to recalculate the offset to the next response
2805 * Note that all responses may require padding (including the very last
2808 if (req->out.vector_count >= (2 * SMBD_SMB2_NUM_IOV_PER_REQ)) {
2809 next_command_ofs = SMB2_HDR_BODY;
2810 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2811 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2814 if ((next_command_ofs % 8) != 0) {
2815 size_t pad_size = 8 - (next_command_ofs % 8);
2816 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2818 * if the dyn buffer is empty
2819 * we can use it to add padding
2823 pad = talloc_zero_array(req,
2826 return smbd_smb2_request_error(req,
2827 NT_STATUS_NO_MEMORY);
2830 outdyn_v->iov_base = (void *)pad;
2831 outdyn_v->iov_len = pad_size;
2834 * For now we copy the dynamic buffer
2835 * and add the padding to the new buffer
2842 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2843 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2845 new_size = old_size + pad_size;
2846 new_dyn = talloc_zero_array(req,
2848 if (new_dyn == NULL) {
2849 return smbd_smb2_request_error(req,
2850 NT_STATUS_NO_MEMORY);
2853 memcpy(new_dyn, old_dyn, old_size);
2854 memset(new_dyn + old_size, 0, pad_size);
2856 outdyn_v->iov_base = (void *)new_dyn;
2857 outdyn_v->iov_len = new_size;
2859 next_command_ofs += pad_size;
2862 if ((req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) >= req->out.vector_count) {
2863 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
2865 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2867 return smbd_smb2_request_reply(req);
2870 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2873 const char *location)
2875 struct smbXsrv_connection *xconn = req->xconn;
2878 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2879 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2881 DBG_NOTICE("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| "
2882 "at %s\n", req->current_idx, nt_errstr(status),
2883 info ? " +info" : "", location);
2886 /* Recvfile error. Drain incoming socket. */
2890 ret = drain_socket(xconn->transport.sock, unread_bytes);
2891 if (ret != unread_bytes) {
2895 error = NT_STATUS_IO_DEVICE_ERROR;
2897 error = map_nt_error_from_unix_common(errno);
2900 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2901 "ret[%u] errno[%d] => %s\n",
2902 (unsigned)unread_bytes,
2903 (unsigned)ret, errno, nt_errstr(error)));
2908 body.data = outhdr + SMB2_HDR_BODY;
2910 SSVAL(body.data, 0, 9);
2913 SIVAL(body.data, 0x04, info->length);
2915 /* Allocated size of req->out.vector[i].iov_base
2916 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2917 * 1 byte without having to do an alloc.
2920 info->data = ((uint8_t *)outhdr) +
2921 OUTVEC_ALLOC_SIZE - 1;
2923 SCVAL(info->data, 0, 0);
2927 * Note: Even if there is an error, continue to process the request.
2931 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2935 struct smbd_smb2_send_break_state {
2936 struct smbd_smb2_send_queue queue_entry;
2937 uint8_t nbt_hdr[NBT_HDR_SIZE];
2938 uint8_t tf[SMB2_TF_HDR_SIZE];
2939 uint8_t hdr[SMB2_HDR_BODY];
2940 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2944 static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
2945 struct smbXsrv_session *session,
2946 struct smbXsrv_tcon *tcon,
2947 const uint8_t *body,
2950 struct smbd_smb2_send_break_state *state;
2951 bool do_encryption = false;
2952 uint64_t session_wire_id = 0;
2953 uint64_t nonce_high = 0;
2954 uint64_t nonce_low = 0;
2959 if (session != NULL) {
2960 session_wire_id = session->global->session_wire_id;
2961 do_encryption = session->encryption_desired;
2962 if (tcon->encryption_desired) {
2963 do_encryption = true;
2967 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
2970 state = talloc_zero_size(xconn, statelen);
2971 if (state == NULL) {
2972 return NT_STATUS_NO_MEMORY;
2974 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
2976 if (do_encryption) {
2977 status = smb2_get_new_nonce(session,
2980 if (!NT_STATUS_IS_OK(status)) {
2985 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2986 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
2987 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
2988 SBVAL(state->tf, SMB2_TF_SESSION_ID, session_wire_id);
2990 SIVAL(state->hdr, 0, SMB2_MAGIC);
2991 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2992 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
2993 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
2994 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2995 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
2996 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2997 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
2998 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2999 SIVAL(state->hdr, SMB2_HDR_PID, 0);
3000 SIVAL(state->hdr, SMB2_HDR_TID, 0);
3001 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
3002 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
3004 state->vector[0] = (struct iovec) {
3005 .iov_base = state->nbt_hdr,
3006 .iov_len = sizeof(state->nbt_hdr)
3009 if (do_encryption) {
3010 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3011 .iov_base = state->tf,
3012 .iov_len = sizeof(state->tf)
3015 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3021 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
3022 .iov_base = state->hdr,
3023 .iov_len = sizeof(state->hdr)
3026 memcpy(state->body, body, body_len);
3028 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
3029 .iov_base = state->body,
3030 .iov_len = body_len /* no sizeof(state->body) .. :-) */
3034 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
3037 ok = smb2_setup_nbt_length(state->vector,
3038 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
3040 return NT_STATUS_INVALID_PARAMETER_MIX;
3043 if (do_encryption) {
3044 DATA_BLOB encryption_key = session->global->encryption_key;
3046 status = smb2_signing_encrypt_pdu(encryption_key,
3047 xconn->smb2.server.cipher,
3048 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
3049 SMBD_SMB2_NUM_IOV_PER_REQ);
3050 if (!NT_STATUS_IS_OK(status)) {
3055 state->queue_entry.mem_ctx = state;
3056 state->queue_entry.vector = state->vector;
3057 state->queue_entry.count = ARRAY_SIZE(state->vector);
3058 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
3059 xconn->smb2.send_queue_len++;
3061 status = smbd_smb2_flush_send_queue(xconn);
3062 if (!NT_STATUS_IS_OK(status)) {
3066 return NT_STATUS_OK;
3069 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_connection *xconn,
3070 struct smbXsrv_session *session,
3071 struct smbXsrv_tcon *tcon,
3072 struct smbXsrv_open *op,
3073 uint8_t oplock_level)
3077 SSVAL(body, 0x00, sizeof(body));
3078 SCVAL(body, 0x02, oplock_level);
3079 SCVAL(body, 0x03, 0); /* reserved */
3080 SIVAL(body, 0x04, 0); /* reserved */
3081 SBVAL(body, 0x08, op->global->open_persistent_id);
3082 SBVAL(body, 0x10, op->global->open_volatile_id);
3084 return smbd_smb2_send_break(xconn, session, tcon, body, sizeof(body));
3087 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_connection *xconn,
3089 uint32_t lease_flags,
3090 struct smb2_lease_key *lease_key,
3091 uint32_t current_lease_state,
3092 uint32_t new_lease_state)
3096 SSVAL(body, 0x00, sizeof(body));
3097 SSVAL(body, 0x02, new_epoch);
3098 SIVAL(body, 0x04, lease_flags);
3099 SBVAL(body, 0x08, lease_key->data[0]);
3100 SBVAL(body, 0x10, lease_key->data[1]);
3101 SIVAL(body, 0x18, current_lease_state);
3102 SIVAL(body, 0x1c, new_lease_state);
3103 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
3104 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
3105 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
3107 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3110 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
3114 uint64_t file_id_persistent;
3115 uint64_t file_id_volatile;
3116 struct smbXsrv_open *op = NULL;
3117 struct files_struct *fsp = NULL;
3118 const uint8_t *body = NULL;
3121 * This is only called with a pktbuf
3122 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
3126 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
3127 /* Transform header. Cannot recvfile. */
3130 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
3131 /* Not SMB2. Normal error path will cope. */
3134 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
3135 /* Not SMB2. Normal error path will cope. */
3138 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
3139 /* Needs to be a WRITE. */
3142 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
3143 /* Chained. Cannot recvfile. */
3146 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
3147 if (flags & SMB2_HDR_FLAG_CHAINED) {
3148 /* Chained. Cannot recvfile. */
3151 if (flags & SMB2_HDR_FLAG_SIGNED) {
3152 /* Signed. Cannot recvfile. */
3156 body = &state->pktbuf[SMB2_HDR_BODY];
3158 file_id_persistent = BVAL(body, 0x10);
3159 file_id_volatile = BVAL(body, 0x18);
3161 status = smb2srv_open_lookup(state->req->xconn,
3166 if (!NT_STATUS_IS_OK(status)) {
3174 if (fsp->conn == NULL) {
3178 if (IS_IPC(fsp->conn)) {
3181 if (IS_PRINT(fsp->conn)) {
3185 DEBUG(10,("Doing recvfile write len = %u\n",
3186 (unsigned int)(state->pktfull - state->pktlen)));
3191 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
3193 struct smbd_server_connection *sconn = xconn->client->sconn;
3194 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3195 size_t max_send_queue_len;
3196 size_t cur_send_queue_len;
3198 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3200 * we're not supposed to do any io
3202 return NT_STATUS_OK;
3205 if (state->req != NULL) {
3207 * if there is already a tstream_readv_pdu
3208 * pending, we are done.
3210 return NT_STATUS_OK;
3213 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
3214 cur_send_queue_len = xconn->smb2.send_queue_len;
3216 if (cur_send_queue_len > max_send_queue_len) {
3218 * if we have a lot of requests to send,
3219 * we wait until they are on the wire until we
3220 * ask for the next request.
3222 return NT_STATUS_OK;
3225 /* ask for the next request */
3226 ZERO_STRUCTP(state);
3227 state->req = smbd_smb2_request_allocate(xconn);
3228 if (state->req == NULL) {
3229 return NT_STATUS_NO_MEMORY;
3231 state->req->sconn = sconn;
3232 state->req->xconn = xconn;
3233 state->min_recv_size = lp_min_receive_file_size();
3235 TEVENT_FD_READABLE(xconn->transport.fde);
3237 return NT_STATUS_OK;
3240 void smbd_smb2_first_negprot(struct smbXsrv_connection *xconn,
3241 const uint8_t *inpdu, size_t size)
3243 struct smbd_server_connection *sconn = xconn->client->sconn;
3245 struct smbd_smb2_request *req = NULL;
3247 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3248 (unsigned int)size));
3250 status = smbd_initialize_smb2(xconn);
3251 if (!NT_STATUS_IS_OK(status)) {
3252 smbd_server_connection_terminate(xconn, nt_errstr(status));
3256 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
3257 if (!NT_STATUS_IS_OK(status)) {
3258 smbd_server_connection_terminate(xconn, nt_errstr(status));
3262 status = smbd_smb2_request_validate(req);
3263 if (!NT_STATUS_IS_OK(status)) {
3264 smbd_server_connection_terminate(xconn, nt_errstr(status));
3268 status = smbd_smb2_request_setup_out(req);
3269 if (!NT_STATUS_IS_OK(status)) {
3270 smbd_server_connection_terminate(xconn, nt_errstr(status));
3276 * this was already counted at the SMB1 layer =>
3277 * smbd_smb2_request_dispatch() should not count it twice.
3279 if (profile_p->values.request_stats.count > 0) {
3280 profile_p->values.request_stats.count--;
3283 status = smbd_smb2_request_dispatch(req);
3284 if (!NT_STATUS_IS_OK(status)) {
3285 smbd_server_connection_terminate(xconn, nt_errstr(status));
3289 status = smbd_smb2_request_next_incoming(xconn);
3290 if (!NT_STATUS_IS_OK(status)) {
3291 smbd_server_connection_terminate(xconn, nt_errstr(status));
3295 sconn->num_requests++;
3298 static int socket_error_from_errno(int ret,
3312 if (sys_errno == 0) {
3316 if (sys_errno == EINTR) {
3321 if (sys_errno == EINPROGRESS) {
3326 if (sys_errno == EAGAIN) {
3331 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3332 if (sys_errno == ENOMEM) {
3338 #if EWOULDBLOCK != EAGAIN
3339 if (sys_errno == EWOULDBLOCK) {
3349 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3355 if (xconn->smb2.send_queue == NULL) {
3356 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3357 return NT_STATUS_OK;
3360 while (xconn->smb2.send_queue != NULL) {
3361 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3364 if (e->sendfile_header != NULL) {
3365 NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
3370 for (i=0; i < e->count; i++) {
3371 size += e->vector[i].iov_len;
3374 if (size <= e->sendfile_header->length) {
3375 buf = e->sendfile_header->data;
3377 buf = talloc_array(e->mem_ctx, uint8_t, size);
3379 return NT_STATUS_NO_MEMORY;
3384 for (i=0; i < e->count; i++) {
3386 e->vector[i].iov_base,
3387 e->vector[i].iov_len);
3388 size += e->vector[i].iov_len;
3391 e->sendfile_header->data = buf;
3392 e->sendfile_header->length = size;
3393 e->sendfile_status = &status;
3396 xconn->smb2.send_queue_len--;
3397 DLIST_REMOVE(xconn->smb2.send_queue, e);
3399 * This triggers the sendfile path via
3402 talloc_free(e->mem_ctx);
3404 if (!NT_STATUS_IS_OK(status)) {
3410 ret = writev(xconn->transport.sock, e->vector, e->count);
3412 /* propagate end of file */
3413 return NT_STATUS_INTERNAL_ERROR;
3415 err = socket_error_from_errno(ret, errno, &retry);
3418 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3419 return NT_STATUS_OK;
3422 return map_nt_error_from_unix_common(err);
3425 ok = iov_advance(&e->vector, &e->count, ret);
3427 return NT_STATUS_INTERNAL_ERROR;
3431 /* we have more to write */
3432 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3433 return NT_STATUS_OK;
3436 xconn->smb2.send_queue_len--;
3437 DLIST_REMOVE(xconn->smb2.send_queue, e);
3438 talloc_free(e->mem_ctx);
3441 return NT_STATUS_OK;
3444 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3447 struct smbd_server_connection *sconn = xconn->client->sconn;
3448 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3449 struct smbd_smb2_request *req = NULL;
3450 size_t min_recvfile_size = UINT32_MAX;
3457 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3459 * we're not supposed to do any io
3461 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3462 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3463 return NT_STATUS_OK;
3466 if (fde_flags & TEVENT_FD_WRITE) {
3467 status = smbd_smb2_flush_send_queue(xconn);
3468 if (!NT_STATUS_IS_OK(status)) {
3473 if (!(fde_flags & TEVENT_FD_READ)) {
3474 return NT_STATUS_OK;
3477 if (state->req == NULL) {
3478 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3479 return NT_STATUS_OK;
3483 if (!state->hdr.done) {
3484 state->hdr.done = true;
3486 state->vector.iov_base = (void *)state->hdr.nbt;
3487 state->vector.iov_len = NBT_HDR_SIZE;
3490 ret = readv(xconn->transport.sock, &state->vector, 1);
3492 /* propagate end of file */
3493 return NT_STATUS_END_OF_FILE;
3495 err = socket_error_from_errno(ret, errno, &retry);
3498 TEVENT_FD_READABLE(xconn->transport.fde);
3499 return NT_STATUS_OK;
3502 return map_nt_error_from_unix_common(err);
3505 if (ret < state->vector.iov_len) {
3507 base = (uint8_t *)state->vector.iov_base;
3509 state->vector.iov_base = (void *)base;
3510 state->vector.iov_len -= ret;
3511 /* we have more to read */
3512 TEVENT_FD_READABLE(xconn->transport.fde);
3513 return NT_STATUS_OK;
3516 if (state->pktlen > 0) {
3517 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3519 * Not a possible receivefile write.
3520 * Read the rest of the data.
3522 state->doing_receivefile = false;
3524 state->pktbuf = talloc_realloc(state->req,
3528 if (state->pktbuf == NULL) {
3529 return NT_STATUS_NO_MEMORY;
3532 state->vector.iov_base = (void *)(state->pktbuf +
3534 state->vector.iov_len = (state->pktfull -
3537 state->pktlen = state->pktfull;
3542 * Either this is a receivefile write so we've
3543 * done a short read, or if not we have all the data.
3549 * Now we analyze the NBT header
3551 if (state->hdr.nbt[0] != 0x00) {
3552 state->min_recv_size = 0;
3554 state->pktfull = smb2_len(state->hdr.nbt);
3555 if (state->pktfull == 0) {
3559 if (state->min_recv_size != 0) {
3560 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3561 min_recvfile_size += state->min_recv_size;
3564 if (state->pktfull > min_recvfile_size) {
3566 * Might be a receivefile write. Read the SMB2 HEADER +
3567 * SMB2_WRITE header first. Set 'doing_receivefile'
3568 * as we're *attempting* receivefile write. If this
3569 * turns out not to be a SMB2_WRITE request or otherwise
3570 * not suitable then we'll just read the rest of the data
3571 * the next time this function is called.
3573 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3574 state->doing_receivefile = true;
3576 state->pktlen = state->pktfull;
3579 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3580 if (state->pktbuf == NULL) {
3581 return NT_STATUS_NO_MEMORY;
3584 state->vector.iov_base = (void *)state->pktbuf;
3585 state->vector.iov_len = state->pktlen;
3591 if (state->hdr.nbt[0] != 0x00) {
3592 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3593 state->hdr.nbt[0]));
3596 ZERO_STRUCTP(state);
3598 state->min_recv_size = lp_min_receive_file_size();
3606 req->request_time = timeval_current();
3607 now = timeval_to_nttime(&req->request_time);
3609 status = smbd_smb2_inbuf_parse_compound(xconn,
3615 &req->in.vector_count);
3616 if (!NT_STATUS_IS_OK(status)) {
3620 if (state->doing_receivefile) {
3621 req->smb1req = talloc_zero(req, struct smb_request);
3622 if (req->smb1req == NULL) {
3623 return NT_STATUS_NO_MEMORY;
3625 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3628 ZERO_STRUCTP(state);
3630 req->current_idx = 1;
3632 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3633 req->current_idx, req->in.vector_count));
3635 status = smbd_smb2_request_validate(req);
3636 if (!NT_STATUS_IS_OK(status)) {
3640 status = smbd_smb2_request_setup_out(req);
3641 if (!NT_STATUS_IS_OK(status)) {
3645 status = smbd_smb2_request_dispatch(req);
3646 if (!NT_STATUS_IS_OK(status)) {
3650 sconn->num_requests++;
3652 /* The timeout_processing function isn't run nearly
3653 often enough to implement 'max log size' without
3654 overrunning the size of the file by many megabytes.
3655 This is especially true if we are running at debug
3656 level 10. Checking every 50 SMB2s is a nice
3657 tradeoff of performance vs log file size overrun. */
3659 if ((sconn->num_requests % 50) == 0 &&
3660 need_to_check_log_size()) {
3661 change_to_root_user();
3665 status = smbd_smb2_request_next_incoming(xconn);
3666 if (!NT_STATUS_IS_OK(status)) {
3670 return NT_STATUS_OK;
3673 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3674 struct tevent_fd *fde,
3678 struct smbXsrv_connection *xconn =
3679 talloc_get_type_abort(private_data,
3680 struct smbXsrv_connection);
3683 status = smbd_smb2_io_handler(xconn, flags);
3684 if (!NT_STATUS_IS_OK(status)) {
3685 smbd_server_connection_terminate(xconn, nt_errstr(status));