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/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 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
807 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
809 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
811 if (xconn->smb2.credits.max < credit_charge) {
812 smbd_server_connection_terminate(xconn,
813 "client error: credit charge > max credits\n");
817 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
819 * In case we already send an async interim
820 * response, we should not grant
821 * credits on the final response.
824 } else if (credits_requested > 0) {
825 uint16_t additional_max = 0;
826 uint16_t additional_credits = credits_requested - 1;
829 case SMB2_OP_NEGPROT:
831 case SMB2_OP_SESSSETUP:
833 * Windows 2012 RC1 starts to grant
835 * with a successful session setup
837 if (NT_STATUS_IS_OK(out_status)) {
843 * We match windows and only grant additional credits
850 additional_credits = MIN(additional_credits, additional_max);
852 credits_granted = credit_charge + additional_credits;
853 } else if (xconn->smb2.credits.granted == 0) {
855 * Make sure the client has always at least one credit
861 * sequence numbers should not wrap
863 * 1. calculate the possible credits until
864 * the sequence numbers start to wrap on 64-bit.
866 * 2. UINT64_MAX is used for Break Notifications.
868 * 2. truncate the possible credits to the maximum
869 * credits we want to grant to the client in total.
871 * 3. remove the range we'll already granted to the client
872 * this makes sure the client consumes the lowest sequence
873 * number, before we can grant additional credits.
875 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
876 if (credits_possible > 0) {
877 /* remove UINT64_MAX */
878 credits_possible -= 1;
880 credits_possible = MIN(credits_possible, current_max_credits);
881 credits_possible -= xconn->smb2.credits.seq_range;
883 credits_granted = MIN(credits_granted, credits_possible);
885 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
886 xconn->smb2.credits.granted += credits_granted;
887 xconn->smb2.credits.seq_range += credits_granted;
889 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
890 "granted %u, current possible/max %u/%u, "
891 "total granted/max/low/range %u/%u/%llu/%u\n",
892 (unsigned int)credits_requested,
893 (unsigned int)credit_charge,
894 (unsigned int)credits_granted,
895 (unsigned int)credits_possible,
896 (unsigned int)current_max_credits,
897 (unsigned int)xconn->smb2.credits.granted,
898 (unsigned int)xconn->smb2.credits.max,
899 (unsigned long long)xconn->smb2.credits.seq_low,
900 (unsigned int)xconn->smb2.credits.seq_range));
903 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
904 struct smbd_smb2_request *outreq)
907 uint16_t total_credits = 0;
909 count = outreq->out.vector_count;
911 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
912 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
913 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
914 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
916 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
918 /* To match Windows, count up what we
920 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
921 /* Set to zero in all but the last reply. */
922 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
923 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
925 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
930 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
932 if (req->current_idx <= 1) {
933 if (size <= sizeof(req->out._body)) {
934 return data_blob_const(req->out._body, size);
938 return data_blob_talloc(req, NULL, size);
941 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
943 struct smbXsrv_connection *xconn = req->xconn;
945 struct iovec *vector;
949 count = req->in.vector_count;
950 if (count <= ARRAY_SIZE(req->out._vector)) {
952 vector = req->out._vector;
954 vector = talloc_zero_array(req, struct iovec, count);
955 if (vector == NULL) {
956 return NT_STATUS_NO_MEMORY;
961 vector[0].iov_base = req->out.nbt_hdr;
962 vector[0].iov_len = 4;
963 SIVAL(req->out.nbt_hdr, 0, 0);
965 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
966 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
967 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
968 uint8_t *outhdr = NULL;
969 uint8_t *outbody = NULL;
970 uint32_t next_command_ofs = 0;
971 struct iovec *current = &vector[idx];
973 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
974 /* we have a next command -
975 * setup for the error case. */
976 next_command_ofs = SMB2_HDR_BODY + 9;
980 outhdr = req->out._hdr;
982 outhdr = talloc_zero_array(mem_ctx, uint8_t,
984 if (outhdr == NULL) {
985 return NT_STATUS_NO_MEMORY;
989 outbody = outhdr + SMB2_HDR_BODY;
992 * SMBD_SMB2_TF_IOV_OFS might be used later
994 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
995 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
997 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
998 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1000 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1001 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1003 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1004 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1006 /* setup the SMB2 header */
1007 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1008 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1009 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1010 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1011 SIVAL(outhdr, SMB2_HDR_STATUS,
1012 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1013 SSVAL(outhdr, SMB2_HDR_OPCODE,
1014 SVAL(inhdr, SMB2_HDR_OPCODE));
1015 SIVAL(outhdr, SMB2_HDR_FLAGS,
1016 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1017 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1018 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1019 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1020 SIVAL(outhdr, SMB2_HDR_PID,
1021 IVAL(inhdr, SMB2_HDR_PID));
1022 SIVAL(outhdr, SMB2_HDR_TID,
1023 IVAL(inhdr, SMB2_HDR_TID));
1024 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1025 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1026 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1027 inhdr + SMB2_HDR_SIGNATURE, 16);
1029 /* setup error body header */
1030 SSVAL(outbody, 0x00, 0x08 + 1);
1031 SSVAL(outbody, 0x02, 0);
1032 SIVAL(outbody, 0x04, 0);
1035 req->out.vector = vector;
1036 req->out.vector_count = count;
1038 /* setup the length of the NBT packet */
1039 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1041 DLIST_ADD_END(xconn->smb2.requests, req, struct smbd_smb2_request *);
1043 return NT_STATUS_OK;
1046 void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
1048 const char *location)
1050 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1052 exit_server_cleanly(reason);
1055 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1056 struct iovec *outvec,
1057 const struct iovec *srcvec)
1059 const uint8_t *srctf;
1061 const uint8_t *srchdr;
1063 const uint8_t *srcbody;
1065 const uint8_t *expected_srcbody;
1066 const uint8_t *srcdyn;
1068 const uint8_t *expected_srcdyn;
1074 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1075 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1076 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1077 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1078 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1079 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1080 expected_srcbody = srchdr + SMB2_HDR_BODY;
1081 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1082 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1083 expected_srcdyn = srcbody + 8;
1085 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1089 if (srchdr_len != SMB2_HDR_BODY) {
1093 if (srctf_len == SMB2_TF_HDR_SIZE) {
1094 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1095 if (dsttf == NULL) {
1101 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1102 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1104 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1105 * be allocated with size OUTVEC_ALLOC_SIZE. */
1107 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1108 if (dsthdr == NULL) {
1111 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1112 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1115 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1116 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1117 * then duplicate this. Else use talloc_memdup().
1120 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1121 dstbody = dsthdr + SMB2_HDR_BODY;
1123 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1124 if (dstbody == NULL) {
1128 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1129 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1132 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1134 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1135 * then duplicate this. Else use talloc_memdup().
1138 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1139 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1140 } else if (srcdyn == NULL) {
1143 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1144 if (dstdyn == NULL) {
1148 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1149 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1154 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1156 struct smbd_smb2_request *newreq = NULL;
1157 struct iovec *outvec = NULL;
1158 int count = req->out.vector_count;
1161 newreq = smbd_smb2_request_allocate(req->xconn);
1166 newreq->sconn = req->sconn;
1167 newreq->xconn = req->xconn;
1168 newreq->session = req->session;
1169 newreq->do_encryption = req->do_encryption;
1170 newreq->do_signing = req->do_signing;
1171 newreq->current_idx = req->current_idx;
1173 outvec = talloc_zero_array(newreq, struct iovec, count);
1175 TALLOC_FREE(newreq);
1178 newreq->out.vector = outvec;
1179 newreq->out.vector_count = count;
1181 /* Setup the outvec's identically to req. */
1182 outvec[0].iov_base = newreq->out.nbt_hdr;
1183 outvec[0].iov_len = 4;
1184 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1186 /* Setup the vectors identically to the ones in req. */
1187 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1188 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1195 TALLOC_FREE(newreq);
1199 smb2_setup_nbt_length(newreq->out.vector,
1200 newreq->out.vector_count);
1205 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1207 struct smbXsrv_connection *xconn = req->xconn;
1209 struct iovec *firsttf = NULL;
1210 struct iovec *outhdr_v = NULL;
1211 uint8_t *outhdr = NULL;
1212 struct smbd_smb2_request *nreq = NULL;
1215 /* Create a new smb2 request we'll use
1216 for the interim return. */
1217 nreq = dup_smb2_req(req);
1219 return NT_STATUS_NO_MEMORY;
1222 /* Lose the last X out vectors. They're the
1223 ones we'll be using for the async reply. */
1224 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1226 smb2_setup_nbt_length(nreq->out.vector,
1227 nreq->out.vector_count);
1229 /* Step back to the previous reply. */
1230 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1231 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1232 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1233 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1234 /* And end the chain. */
1235 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1237 /* Calculate outgoing credits */
1238 smb2_calculate_credits(req, nreq);
1240 if (DEBUGLEVEL >= 10) {
1241 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1242 (unsigned int)nreq->current_idx );
1243 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1244 (unsigned int)nreq->out.vector_count );
1245 print_req_vectors(nreq);
1249 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1250 * we need to sign/encrypt here with the last/first key we remembered
1252 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1253 status = smb2_signing_encrypt_pdu(req->first_key,
1254 xconn->smb2.server.cipher,
1256 nreq->out.vector_count - first_idx);
1257 if (!NT_STATUS_IS_OK(status)) {
1260 } else if (req->last_key.length > 0) {
1261 status = smb2_signing_sign_pdu(req->last_key,
1264 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1265 if (!NT_STATUS_IS_OK(status)) {
1270 nreq->queue_entry.mem_ctx = nreq;
1271 nreq->queue_entry.vector = nreq->out.vector;
1272 nreq->queue_entry.count = nreq->out.vector_count;
1273 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry, NULL);
1274 xconn->smb2.send_queue_len++;
1276 status = smbd_smb2_flush_send_queue(xconn);
1277 if (!NT_STATUS_IS_OK(status)) {
1281 return NT_STATUS_OK;
1284 struct smbd_smb2_request_pending_state {
1285 struct smbd_smb2_send_queue queue_entry;
1286 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1287 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1290 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1291 struct tevent_timer *te,
1292 struct timeval current_time,
1293 void *private_data);
1295 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1296 struct tevent_req *subreq,
1297 uint32_t defer_time)
1300 struct timeval defer_endtime;
1301 uint8_t *outhdr = NULL;
1304 if (!tevent_req_is_in_progress(subreq)) {
1306 * This is a performance optimization,
1307 * it avoids one tevent_loop iteration,
1308 * which means we avoid one
1309 * talloc_stackframe_pool/talloc_free pair.
1311 tevent_req_notify_callback(subreq);
1312 return NT_STATUS_OK;
1315 req->subreq = subreq;
1318 if (req->async_te) {
1319 /* We're already async. */
1320 return NT_STATUS_OK;
1323 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1324 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1325 if (flags & SMB2_HDR_FLAG_ASYNC) {
1326 /* We're already async. */
1327 return NT_STATUS_OK;
1330 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1332 * We're trying to go async in a compound
1334 * This is only allowed for opens that
1335 * cause an oplock break, otherwise it
1336 * is not allowed. See [MS-SMB2].pdf
1337 * note <194> on Section 3.3.5.2.7.
1339 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1341 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1343 * Cancel the outstanding request.
1345 bool ok = tevent_req_cancel(req->subreq);
1347 return NT_STATUS_OK;
1349 TALLOC_FREE(req->subreq);
1350 return smbd_smb2_request_error(req,
1351 NT_STATUS_INTERNAL_ERROR);
1355 if (DEBUGLEVEL >= 10) {
1356 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1357 (unsigned int)req->current_idx );
1358 print_req_vectors(req);
1361 if (req->current_idx > 1) {
1363 * We're going async in a compound
1364 * chain after the first request has
1365 * already been processed. Send an
1366 * interim response containing the
1367 * set of replies already generated.
1369 int idx = req->current_idx;
1371 status = smb2_send_async_interim_response(req);
1372 if (!NT_STATUS_IS_OK(status)) {
1375 if (req->first_key.length > 0) {
1376 data_blob_clear_free(&req->first_key);
1379 req->current_idx = 1;
1382 * Re-arrange the in.vectors to remove what
1385 memmove(&req->in.vector[1],
1386 &req->in.vector[idx],
1387 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1388 req->in.vector_count = 1 + (req->in.vector_count - idx);
1390 /* Re-arrange the out.vectors to match. */
1391 memmove(&req->out.vector[1],
1392 &req->out.vector[idx],
1393 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1394 req->out.vector_count = 1 + (req->out.vector_count - idx);
1396 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1398 * We only have one remaining request as
1399 * we've processed everything else.
1400 * This is no longer a compound request.
1402 req->compound_related = false;
1403 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1404 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1405 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1408 if (req->last_key.length > 0) {
1409 data_blob_clear_free(&req->last_key);
1412 defer_endtime = timeval_current_ofs_usec(defer_time);
1413 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1415 smbd_smb2_request_pending_timer,
1417 if (req->async_te == NULL) {
1418 return NT_STATUS_NO_MEMORY;
1421 return NT_STATUS_OK;
1424 static DATA_BLOB smbd_smb2_signing_key(struct smbXsrv_session *session,
1425 struct smbXsrv_connection *xconn)
1427 struct smbXsrv_channel_global0 *c = NULL;
1429 DATA_BLOB key = data_blob_null;
1431 status = smbXsrv_session_find_channel(session, xconn, &c);
1432 if (NT_STATUS_IS_OK(status)) {
1433 key = c->signing_key;
1436 if (key.length == 0) {
1437 key = session->global->signing_key;
1443 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1444 struct tevent_timer *te,
1445 struct timeval current_time,
1448 struct smbd_smb2_request *req =
1449 talloc_get_type_abort(private_data,
1450 struct smbd_smb2_request);
1451 struct smbXsrv_connection *xconn = req->xconn;
1452 struct smbd_smb2_request_pending_state *state = NULL;
1453 uint8_t *outhdr = NULL;
1454 const uint8_t *inhdr = NULL;
1457 uint8_t *hdr = NULL;
1458 uint8_t *body = NULL;
1459 uint8_t *dyn = NULL;
1461 uint64_t session_id = 0;
1462 uint64_t message_id = 0;
1463 uint64_t nonce_high = 0;
1464 uint64_t nonce_low = 0;
1465 uint64_t async_id = 0;
1468 TALLOC_FREE(req->async_te);
1470 /* Ensure our final reply matches the interim one. */
1471 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1472 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1473 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1474 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1475 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1477 async_id = message_id; /* keep it simple for now... */
1479 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1480 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1482 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1484 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1485 (unsigned long long)async_id ));
1488 * What we send is identical to a smbd_smb2_request_error
1489 * packet with an error status of STATUS_PENDING. Make use
1490 * of this fact sometime when refactoring. JRA.
1493 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
1494 if (state == NULL) {
1495 smbd_server_connection_terminate(xconn,
1496 nt_errstr(NT_STATUS_NO_MEMORY));
1500 tf = state->buf + NBT_HDR_SIZE;
1501 tf_len = SMB2_TF_HDR_SIZE;
1503 hdr = tf + SMB2_TF_HDR_SIZE;
1504 body = hdr + SMB2_HDR_BODY;
1507 if (req->do_encryption) {
1508 struct smbXsrv_session *x = req->session;
1510 nonce_high = x->nonce_high;
1511 nonce_low = x->nonce_low;
1514 if (x->nonce_low == 0) {
1520 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1521 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1522 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1523 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1525 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1526 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1527 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1528 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1529 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1531 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1532 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1533 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1534 SBVAL(hdr, SMB2_HDR_PID, async_id);
1535 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1536 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1537 memcpy(hdr+SMB2_HDR_SIGNATURE,
1538 outhdr+SMB2_HDR_SIGNATURE, 16);
1540 SSVAL(body, 0x00, 0x08 + 1);
1542 SCVAL(body, 0x02, 0);
1543 SCVAL(body, 0x03, 0);
1544 SIVAL(body, 0x04, 0);
1545 /* Match W2K8R2... */
1546 SCVAL(dyn, 0x00, 0x21);
1548 state->vector[0].iov_base = (void *)state->buf;
1549 state->vector[0].iov_len = NBT_HDR_SIZE;
1551 if (req->do_encryption) {
1552 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1553 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1555 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1556 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1559 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1560 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1562 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1563 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1565 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1566 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1568 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1570 /* Ensure we correctly go through crediting. Grant
1571 the credits now, and zero credits on the final
1573 smb2_set_operation_credit(req->xconn,
1574 SMBD_SMB2_IN_HDR_IOV(req),
1575 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1577 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1582 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1583 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1585 (unsigned int)ARRAY_SIZE(state->vector),
1586 (unsigned int)state->vector[i].iov_len);
1590 if (req->do_encryption) {
1591 struct smbXsrv_session *x = req->session;
1592 DATA_BLOB encryption_key = x->global->encryption_key;
1594 status = smb2_signing_encrypt_pdu(encryption_key,
1595 xconn->smb2.server.cipher,
1596 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1597 SMBD_SMB2_NUM_IOV_PER_REQ);
1598 if (!NT_STATUS_IS_OK(status)) {
1599 smbd_server_connection_terminate(xconn,
1603 } else if (req->do_signing) {
1604 struct smbXsrv_session *x = req->session;
1605 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
1607 status = smb2_signing_sign_pdu(signing_key,
1609 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1610 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1611 if (!NT_STATUS_IS_OK(status)) {
1612 smbd_server_connection_terminate(xconn,
1618 state->queue_entry.mem_ctx = state;
1619 state->queue_entry.vector = state->vector;
1620 state->queue_entry.count = ARRAY_SIZE(state->vector);
1621 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
1622 xconn->smb2.send_queue_len++;
1624 status = smbd_smb2_flush_send_queue(xconn);
1625 if (!NT_STATUS_IS_OK(status)) {
1626 smbd_server_connection_terminate(xconn,
1632 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1634 struct smbXsrv_connection *xconn = req->xconn;
1635 struct smbd_smb2_request *cur;
1636 const uint8_t *inhdr;
1638 uint64_t search_message_id;
1639 uint64_t search_async_id;
1642 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1644 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1645 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1646 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1649 * we don't need the request anymore
1650 * cancel requests never have a response
1652 DLIST_REMOVE(xconn->smb2.requests, req);
1655 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1656 const uint8_t *outhdr;
1657 uint64_t message_id;
1660 if (cur->compound_related) {
1662 * Never cancel anything in a compound request.
1663 * Way too hard to deal with the result.
1668 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1670 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1671 async_id = BVAL(outhdr, SMB2_HDR_PID);
1673 if (flags & SMB2_HDR_FLAG_ASYNC) {
1674 if (search_async_id == async_id) {
1675 found_id = async_id;
1679 if (search_message_id == message_id) {
1680 found_id = message_id;
1686 if (cur && cur->subreq) {
1687 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1688 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1689 "cancel opcode[%s] mid %llu\n",
1690 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1691 (unsigned long long)found_id ));
1692 tevent_req_cancel(cur->subreq);
1695 return NT_STATUS_OK;
1698 /*************************************************************
1699 Ensure an incoming tid is a valid one for us to access.
1700 Change to the associated uid credentials and chdir to the
1701 valid tid directory.
1702 *************************************************************/
1704 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1706 const uint8_t *inhdr;
1709 struct smbXsrv_tcon *tcon;
1711 NTTIME now = timeval_to_nttime(&req->request_time);
1715 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1717 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1718 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1720 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1721 in_tid = req->last_tid;
1726 status = smb2srv_tcon_lookup(req->session,
1727 in_tid, now, &tcon);
1728 if (!NT_STATUS_IS_OK(status)) {
1732 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1733 return NT_STATUS_ACCESS_DENIED;
1736 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1737 if (!set_current_service(tcon->compat, 0, true)) {
1738 return NT_STATUS_ACCESS_DENIED;
1742 req->last_tid = in_tid;
1744 return NT_STATUS_OK;
1747 /*************************************************************
1748 Ensure an incoming session_id is a valid one for us to access.
1749 *************************************************************/
1751 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1753 const uint8_t *inhdr;
1756 uint64_t in_session_id;
1757 struct smbXsrv_session *session = NULL;
1758 struct auth_session_info *session_info;
1760 NTTIME now = timeval_to_nttime(&req->request_time);
1762 req->session = NULL;
1765 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1767 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1768 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1769 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1771 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1772 in_session_id = req->last_session_id;
1775 req->last_session_id = 0;
1777 /* lookup an existing session */
1778 status = smb2srv_session_lookup(req->xconn,
1782 req->session = session;
1783 req->last_session_id = in_session_id;
1785 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1786 switch (in_opcode) {
1787 case SMB2_OP_SESSSETUP:
1788 status = NT_STATUS_OK;
1794 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1795 switch (in_opcode) {
1797 case SMB2_OP_CREATE:
1798 case SMB2_OP_GETINFO:
1799 case SMB2_OP_SETINFO:
1800 return NT_STATUS_INVALID_HANDLE;
1803 * Notice the check for
1804 * (session_info == NULL)
1807 status = NT_STATUS_OK;
1811 if (!NT_STATUS_IS_OK(status)) {
1815 session_info = session->global->auth_session_info;
1816 if (session_info == NULL) {
1817 return NT_STATUS_INVALID_HANDLE;
1820 if (in_session_id != req->xconn->client->last_session_id) {
1821 req->xconn->client->last_session_id = in_session_id;
1822 set_current_user_info(session_info->unix_info->sanitized_username,
1823 session_info->unix_info->unix_name,
1824 session_info->info->domain_name);
1827 return NT_STATUS_OK;
1830 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1831 uint32_t data_length)
1833 struct smbXsrv_connection *xconn = req->xconn;
1834 uint16_t needed_charge;
1835 uint16_t credit_charge = 1;
1836 const uint8_t *inhdr;
1838 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1840 if (xconn->smb2.credits.multicredit) {
1841 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1842 credit_charge = MAX(credit_charge, 1);
1845 needed_charge = (data_length - 1)/ 65536 + 1;
1847 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1848 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1849 credit_charge, needed_charge));
1851 if (needed_charge > credit_charge) {
1852 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1853 credit_charge, needed_charge));
1854 return NT_STATUS_INVALID_PARAMETER;
1857 return NT_STATUS_OK;
1860 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1861 size_t expected_body_size)
1863 struct iovec *inhdr_v;
1864 const uint8_t *inhdr;
1866 const uint8_t *inbody;
1868 size_t min_dyn_size = expected_body_size & 0x00000001;
1869 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1872 * The following should be checked already.
1874 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1875 return NT_STATUS_INTERNAL_ERROR;
1877 if (req->current_idx > max_idx) {
1878 return NT_STATUS_INTERNAL_ERROR;
1881 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1882 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1883 return NT_STATUS_INTERNAL_ERROR;
1885 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1886 return NT_STATUS_INTERNAL_ERROR;
1889 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1890 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1894 case SMB2_OP_GETINFO:
1898 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
1899 if (req->smb1req->unread_bytes < min_dyn_size) {
1900 return NT_STATUS_INVALID_PARAMETER;
1909 * Now check the expected body size,
1910 * where the last byte might be in the
1913 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1914 return NT_STATUS_INVALID_PARAMETER;
1916 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1917 return NT_STATUS_INVALID_PARAMETER;
1920 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1922 body_size = SVAL(inbody, 0x00);
1923 if (body_size != expected_body_size) {
1924 return NT_STATUS_INVALID_PARAMETER;
1927 return NT_STATUS_OK;
1930 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1932 struct smbXsrv_connection *xconn = req->xconn;
1933 const struct smbd_smb2_dispatch_table *call = NULL;
1934 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1935 const uint8_t *inhdr;
1940 NTSTATUS session_status;
1941 uint32_t allowed_flags;
1942 NTSTATUS return_value;
1943 struct smbXsrv_session *x = NULL;
1944 bool signing_required = false;
1945 bool encryption_required = false;
1947 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1949 DO_PROFILE_INC(request);
1951 /* TODO: verify more things */
1953 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1954 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1955 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1956 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1957 smb2_opcode_name(opcode),
1958 (unsigned long long)mid));
1960 if (xconn->protocol >= PROTOCOL_SMB2_02) {
1962 * once the protocol is negotiated
1963 * SMB2_OP_NEGPROT is not allowed anymore
1965 if (opcode == SMB2_OP_NEGPROT) {
1966 /* drop the connection */
1967 return NT_STATUS_INVALID_PARAMETER;
1971 * if the protocol is not negotiated yet
1972 * only SMB2_OP_NEGPROT is allowed.
1974 if (opcode != SMB2_OP_NEGPROT) {
1975 /* drop the connection */
1976 return NT_STATUS_INVALID_PARAMETER;
1981 * Check if the client provided a valid session id,
1982 * if so smbd_smb2_request_check_session() calls
1983 * set_current_user_info().
1985 * As some command don't require a valid session id
1986 * we defer the check of the session_status
1988 session_status = smbd_smb2_request_check_session(req);
1991 signing_required = x->global->signing_required;
1992 encryption_required = x->global->encryption_required;
1995 req->do_signing = false;
1996 req->do_encryption = false;
1997 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
1998 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
1999 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
2001 if (x != NULL && x->global->session_wire_id != tf_session_id) {
2002 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2003 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
2004 (unsigned long long)x->global->session_wire_id,
2005 (unsigned long long)tf_session_id));
2007 * TODO: windows allows this...
2008 * should we drop the connection?
2010 * For now we just return ACCESS_DENIED
2011 * (Windows clients never trigger this)
2012 * and wait for an update of [MS-SMB2].
2014 return smbd_smb2_request_error(req,
2015 NT_STATUS_ACCESS_DENIED);
2018 req->do_encryption = true;
2021 if (encryption_required && !req->do_encryption) {
2022 return smbd_smb2_request_error(req,
2023 NT_STATUS_ACCESS_DENIED);
2026 call = smbd_smb2_call(opcode);
2028 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2031 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2032 SMB2_HDR_FLAG_SIGNED |
2034 if (opcode == SMB2_OP_CANCEL) {
2035 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2037 if ((flags & ~allowed_flags) != 0) {
2038 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2041 if (flags & SMB2_HDR_FLAG_CHAINED) {
2043 * This check is mostly for giving the correct error code
2044 * for compounded requests.
2046 if (!NT_STATUS_IS_OK(session_status)) {
2047 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2050 req->compat_chain_fsp = NULL;
2053 if (req->do_encryption) {
2054 signing_required = false;
2055 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2056 DATA_BLOB signing_key = data_blob_null;
2060 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2061 * If the SMB2 header of the SMB2 NEGOTIATE
2062 * request has the SMB2_FLAGS_SIGNED bit set in the
2063 * Flags field, the server MUST fail the request
2064 * with STATUS_INVALID_PARAMETER.
2066 * Microsoft test tool checks this.
2069 if ((opcode == SMB2_OP_NEGPROT) &&
2070 (flags & SMB2_HDR_FLAG_SIGNED)) {
2071 status = NT_STATUS_INVALID_PARAMETER;
2073 status = NT_STATUS_USER_SESSION_DELETED;
2075 return smbd_smb2_request_error(req, status);
2078 signing_key = smbd_smb2_signing_key(x, xconn);
2081 * If we have a signing key, we should
2084 if (signing_key.length > 0) {
2085 req->do_signing = true;
2088 status = smb2_signing_check_pdu(signing_key,
2090 SMBD_SMB2_IN_HDR_IOV(req),
2091 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2092 if (!NT_STATUS_IS_OK(status)) {
2093 return smbd_smb2_request_error(req, status);
2097 * Now that we know the request was correctly signed
2098 * we have to sign the response too.
2100 req->do_signing = true;
2102 if (!NT_STATUS_IS_OK(session_status)) {
2103 return smbd_smb2_request_error(req, session_status);
2105 } else if (opcode == SMB2_OP_CANCEL) {
2106 /* Cancel requests are allowed to skip the signing */
2107 } else if (signing_required) {
2109 * If signing is required we try to sign
2110 * a possible error response
2112 req->do_signing = true;
2113 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2116 if (flags & SMB2_HDR_FLAG_CHAINED) {
2117 req->compound_related = true;
2120 if (call->need_session) {
2121 if (!NT_STATUS_IS_OK(session_status)) {
2122 return smbd_smb2_request_error(req, session_status);
2126 if (call->need_tcon) {
2127 SMB_ASSERT(call->need_session);
2130 * This call needs to be run as user.
2132 * smbd_smb2_request_check_tcon()
2133 * calls change_to_user() on success.
2135 status = smbd_smb2_request_check_tcon(req);
2136 if (!NT_STATUS_IS_OK(status)) {
2137 return smbd_smb2_request_error(req, status);
2139 if (req->tcon->global->encryption_required) {
2140 encryption_required = true;
2142 if (encryption_required && !req->do_encryption) {
2143 return smbd_smb2_request_error(req,
2144 NT_STATUS_ACCESS_DENIED);
2148 if (call->fileid_ofs != 0) {
2149 size_t needed = call->fileid_ofs + 16;
2150 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2151 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2152 uint64_t file_id_persistent;
2153 uint64_t file_id_volatile;
2154 struct files_struct *fsp;
2156 SMB_ASSERT(call->need_tcon);
2158 if (needed > body_size) {
2159 return smbd_smb2_request_error(req,
2160 NT_STATUS_INVALID_PARAMETER);
2163 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2164 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2166 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2168 if (!call->allow_invalid_fileid) {
2169 return smbd_smb2_request_error(req,
2170 NT_STATUS_FILE_CLOSED);
2173 if (file_id_persistent != UINT64_MAX) {
2174 return smbd_smb2_request_error(req,
2175 NT_STATUS_FILE_CLOSED);
2177 if (file_id_volatile != UINT64_MAX) {
2178 return smbd_smb2_request_error(req,
2179 NT_STATUS_FILE_CLOSED);
2184 if (call->as_root) {
2185 SMB_ASSERT(call->fileid_ofs == 0);
2186 /* This call needs to be run as root */
2187 change_to_root_user();
2189 SMB_ASSERT(call->need_tcon);
2192 #define _INBYTES(_r) \
2193 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
2196 case SMB2_OP_NEGPROT:
2197 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
2198 req->profile, _INBYTES(req));
2199 return_value = smbd_smb2_request_process_negprot(req);
2202 case SMB2_OP_SESSSETUP:
2203 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
2204 req->profile, _INBYTES(req));
2205 return_value = smbd_smb2_request_process_sesssetup(req);
2208 case SMB2_OP_LOGOFF:
2209 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
2210 req->profile, _INBYTES(req));
2211 return_value = smbd_smb2_request_process_logoff(req);
2215 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
2216 req->profile, _INBYTES(req));
2217 return_value = smbd_smb2_request_process_tcon(req);
2221 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
2222 req->profile, _INBYTES(req));
2223 return_value = smbd_smb2_request_process_tdis(req);
2226 case SMB2_OP_CREATE:
2227 if (req->subreq == NULL) {
2228 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
2229 req->profile, _INBYTES(req));
2231 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
2233 return_value = smbd_smb2_request_process_create(req);
2237 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
2238 req->profile, _INBYTES(req));
2239 return_value = smbd_smb2_request_process_close(req);
2243 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
2244 req->profile, _INBYTES(req));
2245 return_value = smbd_smb2_request_process_flush(req);
2249 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
2250 req->profile, _INBYTES(req));
2251 return_value = smbd_smb2_request_process_read(req);
2255 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
2256 req->profile, _INBYTES(req));
2257 return_value = smbd_smb2_request_process_write(req);
2261 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
2262 req->profile, _INBYTES(req));
2263 return_value = smbd_smb2_request_process_lock(req);
2267 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
2268 req->profile, _INBYTES(req));
2269 return_value = smbd_smb2_request_process_ioctl(req);
2272 case SMB2_OP_CANCEL:
2273 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
2274 req->profile, _INBYTES(req));
2275 return_value = smbd_smb2_request_process_cancel(req);
2276 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
2279 case SMB2_OP_KEEPALIVE:
2280 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
2281 req->profile, _INBYTES(req));
2282 return_value = smbd_smb2_request_process_keepalive(req);
2286 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
2287 req->profile, _INBYTES(req));
2288 return_value = smbd_smb2_request_process_find(req);
2291 case SMB2_OP_NOTIFY:
2292 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
2293 req->profile, _INBYTES(req));
2294 return_value = smbd_smb2_request_process_notify(req);
2297 case SMB2_OP_GETINFO:
2298 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
2299 req->profile, _INBYTES(req));
2300 return_value = smbd_smb2_request_process_getinfo(req);
2303 case SMB2_OP_SETINFO:
2304 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
2305 req->profile, _INBYTES(req));
2306 return_value = smbd_smb2_request_process_setinfo(req);
2310 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
2311 req->profile, _INBYTES(req));
2312 return_value = smbd_smb2_request_process_break(req);
2316 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2319 return return_value;
2322 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2324 struct smbXsrv_connection *xconn = req->xconn;
2326 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2327 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2328 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2332 TALLOC_FREE(req->async_te);
2334 if (req->do_encryption &&
2335 (firsttf->iov_len == 0) &&
2336 (req->first_key.length == 0) &&
2337 (req->session != NULL) &&
2338 (req->session->global->encryption_key.length != 0))
2340 DATA_BLOB encryption_key = req->session->global->encryption_key;
2342 uint64_t session_id = req->session->global->session_wire_id;
2343 struct smbXsrv_session *x = req->session;
2344 uint64_t nonce_high;
2347 nonce_high = x->nonce_high;
2348 nonce_low = x->nonce_low;
2351 if (x->nonce_low == 0) {
2357 * We need to place the SMB2_TRANSFORM header before the
2362 * we need to remember the encryption key
2363 * and defer the signing/encryption until
2364 * we are sure that we do not change
2367 req->first_key = data_blob_dup_talloc(req, encryption_key);
2368 if (req->first_key.data == NULL) {
2369 return NT_STATUS_NO_MEMORY;
2372 tf = talloc_zero_array(req, uint8_t,
2375 return NT_STATUS_NO_MEMORY;
2378 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2379 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2380 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2381 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2383 firsttf->iov_base = (void *)tf;
2384 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2387 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2388 (req->last_key.length > 0) &&
2389 (firsttf->iov_len == 0))
2391 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2392 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2395 * As we are sure the header of the last request in the
2396 * compound chain will not change, we can to sign here
2397 * with the last signing key we remembered.
2399 status = smb2_signing_sign_pdu(req->last_key,
2402 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2403 if (!NT_STATUS_IS_OK(status)) {
2407 if (req->last_key.length > 0) {
2408 data_blob_clear_free(&req->last_key);
2411 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
2412 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
2414 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2416 if (req->current_idx < req->out.vector_count) {
2418 * We must process the remaining compound
2419 * SMB2 requests before any new incoming SMB2
2420 * requests. This is because incoming SMB2
2421 * requests may include a cancel for a
2422 * compound request we haven't processed
2425 struct tevent_immediate *im = tevent_create_immediate(req);
2427 return NT_STATUS_NO_MEMORY;
2430 if (req->do_signing && firsttf->iov_len == 0) {
2431 struct smbXsrv_session *x = req->session;
2432 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2435 * we need to remember the signing key
2436 * and defer the signing until
2437 * we are sure that we do not change
2440 req->last_key = data_blob_dup_talloc(req, signing_key);
2441 if (req->last_key.data == NULL) {
2442 return NT_STATUS_NO_MEMORY;
2446 tevent_schedule_immediate(im,
2448 smbd_smb2_request_dispatch_immediate,
2450 return NT_STATUS_OK;
2453 if (req->compound_related) {
2454 req->compound_related = false;
2457 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2459 /* Set credit for these operations (zero credits if this
2460 is a final reply for an async operation). */
2461 smb2_calculate_credits(req, req);
2464 * now check if we need to sign the current response
2466 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2467 status = smb2_signing_encrypt_pdu(req->first_key,
2468 xconn->smb2.server.cipher,
2470 req->out.vector_count - first_idx);
2471 if (!NT_STATUS_IS_OK(status)) {
2474 } else if (req->do_signing) {
2475 struct smbXsrv_session *x = req->session;
2476 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2478 status = smb2_signing_sign_pdu(signing_key,
2481 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2482 if (!NT_STATUS_IS_OK(status)) {
2486 if (req->first_key.length > 0) {
2487 data_blob_clear_free(&req->first_key);
2490 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2491 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2492 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2493 /* Dynamic part is NULL. Chop it off,
2494 We're going to send it via sendfile. */
2495 req->out.vector_count -= 1;
2499 * We're done with this request -
2500 * move it off the "being processed" queue.
2502 DLIST_REMOVE(xconn->smb2.requests, req);
2504 req->queue_entry.mem_ctx = req;
2505 req->queue_entry.vector = req->out.vector;
2506 req->queue_entry.count = req->out.vector_count;
2507 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry, NULL);
2508 xconn->smb2.send_queue_len++;
2510 status = smbd_smb2_flush_send_queue(xconn);
2511 if (!NT_STATUS_IS_OK(status)) {
2515 return NT_STATUS_OK;
2518 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
2520 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2521 struct tevent_immediate *im,
2524 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2525 struct smbd_smb2_request);
2526 struct smbXsrv_connection *xconn = req->xconn;
2531 if (DEBUGLEVEL >= 10) {
2532 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2533 req->current_idx, req->in.vector_count));
2534 print_req_vectors(req);
2537 status = smbd_smb2_request_dispatch(req);
2538 if (!NT_STATUS_IS_OK(status)) {
2539 smbd_server_connection_terminate(xconn, nt_errstr(status));
2543 status = smbd_smb2_request_next_incoming(xconn);
2544 if (!NT_STATUS_IS_OK(status)) {
2545 smbd_server_connection_terminate(xconn, nt_errstr(status));
2550 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2552 DATA_BLOB body, DATA_BLOB *dyn,
2553 const char *location)
2556 struct iovec *outbody_v;
2557 struct iovec *outdyn_v;
2558 uint32_t next_command_ofs;
2560 DEBUG(10,("smbd_smb2_request_done_ex: "
2561 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2562 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2564 (unsigned int)(dyn ? dyn->length : 0),
2567 if (body.length < 2) {
2568 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2571 if ((body.length % 2) != 0) {
2572 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2575 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2576 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2577 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2579 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2580 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2582 outbody_v->iov_base = (void *)body.data;
2583 outbody_v->iov_len = body.length;
2586 outdyn_v->iov_base = (void *)dyn->data;
2587 outdyn_v->iov_len = dyn->length;
2589 outdyn_v->iov_base = NULL;
2590 outdyn_v->iov_len = 0;
2593 /* see if we need to recalculate the offset to the next response */
2594 if (next_command_ofs > 0) {
2595 next_command_ofs = SMB2_HDR_BODY;
2596 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2597 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2600 if ((next_command_ofs % 8) != 0) {
2601 size_t pad_size = 8 - (next_command_ofs % 8);
2602 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2604 * if the dyn buffer is empty
2605 * we can use it to add padding
2609 pad = talloc_zero_array(req,
2612 return smbd_smb2_request_error(req,
2613 NT_STATUS_NO_MEMORY);
2616 outdyn_v->iov_base = (void *)pad;
2617 outdyn_v->iov_len = pad_size;
2620 * For now we copy the dynamic buffer
2621 * and add the padding to the new buffer
2628 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2629 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2631 new_size = old_size + pad_size;
2632 new_dyn = talloc_zero_array(req,
2634 if (new_dyn == NULL) {
2635 return smbd_smb2_request_error(req,
2636 NT_STATUS_NO_MEMORY);
2639 memcpy(new_dyn, old_dyn, old_size);
2640 memset(new_dyn + old_size, 0, pad_size);
2642 outdyn_v->iov_base = (void *)new_dyn;
2643 outdyn_v->iov_len = new_size;
2645 next_command_ofs += pad_size;
2648 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2650 return smbd_smb2_request_reply(req);
2653 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2656 const char *location)
2658 struct smbXsrv_connection *xconn = req->xconn;
2661 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2662 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2664 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2665 req->current_idx, nt_errstr(status), info ? " +info" : "",
2669 /* Recvfile error. Drain incoming socket. */
2673 ret = drain_socket(xconn->transport.sock, unread_bytes);
2674 if (ret != unread_bytes) {
2678 error = NT_STATUS_IO_DEVICE_ERROR;
2680 error = map_nt_error_from_unix_common(errno);
2683 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2684 "ret[%u] errno[%d] => %s\n",
2685 (unsigned)unread_bytes,
2686 (unsigned)ret, errno, nt_errstr(error)));
2691 body.data = outhdr + SMB2_HDR_BODY;
2693 SSVAL(body.data, 0, 9);
2696 SIVAL(body.data, 0x04, info->length);
2698 /* Allocated size of req->out.vector[i].iov_base
2699 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2700 * 1 byte without having to do an alloc.
2703 info->data = ((uint8_t *)outhdr) +
2704 OUTVEC_ALLOC_SIZE - 1;
2706 SCVAL(info->data, 0, 0);
2710 * Note: Even if there is an error, continue to process the request.
2714 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2718 struct smbd_smb2_send_break_state {
2719 struct smbd_smb2_send_queue queue_entry;
2720 uint8_t nbt_hdr[NBT_HDR_SIZE];
2721 uint8_t tf[SMB2_TF_HDR_SIZE];
2722 uint8_t hdr[SMB2_HDR_BODY];
2723 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2727 static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
2728 struct smbXsrv_session *session,
2729 struct smbXsrv_tcon *tcon,
2730 const uint8_t *body,
2733 struct smbd_smb2_send_break_state *state;
2734 bool do_encryption = false;
2735 uint64_t session_wire_id = 0;
2736 uint64_t nonce_high = 0;
2737 uint64_t nonce_low = 0;
2741 if (session != NULL) {
2742 session_wire_id = session->global->session_wire_id;
2743 do_encryption = session->global->encryption_required;
2744 if (tcon->global->encryption_required) {
2745 do_encryption = true;
2749 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
2752 state = talloc_zero_size(xconn, statelen);
2753 if (state == NULL) {
2754 return NT_STATUS_NO_MEMORY;
2756 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
2758 if (do_encryption) {
2759 nonce_high = session->nonce_high;
2760 nonce_low = session->nonce_low;
2762 session->nonce_low += 1;
2763 if (session->nonce_low == 0) {
2764 session->nonce_low += 1;
2765 session->nonce_high += 1;
2769 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2770 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
2771 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
2772 SBVAL(state->tf, SMB2_TF_SESSION_ID, session_wire_id);
2774 SIVAL(state->hdr, 0, SMB2_MAGIC);
2775 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2776 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
2777 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
2778 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2779 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
2780 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2781 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
2782 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2783 SIVAL(state->hdr, SMB2_HDR_PID, 0);
2784 SIVAL(state->hdr, SMB2_HDR_TID, 0);
2785 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
2786 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
2788 state->vector[0] = (struct iovec) {
2789 .iov_base = state->nbt_hdr,
2790 .iov_len = sizeof(state->nbt_hdr)
2793 if (do_encryption) {
2794 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2795 .iov_base = state->tf,
2796 .iov_len = sizeof(state->tf)
2799 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2805 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
2806 .iov_base = state->hdr,
2807 .iov_len = sizeof(state->hdr)
2810 memcpy(state->body, body, body_len);
2812 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
2813 .iov_base = state->body,
2814 .iov_len = body_len /* no sizeof(state->body) .. :-) */
2818 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
2821 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2823 if (do_encryption) {
2824 DATA_BLOB encryption_key = session->global->encryption_key;
2826 status = smb2_signing_encrypt_pdu(encryption_key,
2827 xconn->smb2.server.cipher,
2828 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2829 SMBD_SMB2_NUM_IOV_PER_REQ);
2830 if (!NT_STATUS_IS_OK(status)) {
2835 state->queue_entry.mem_ctx = state;
2836 state->queue_entry.vector = state->vector;
2837 state->queue_entry.count = ARRAY_SIZE(state->vector);
2838 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
2839 xconn->smb2.send_queue_len++;
2841 status = smbd_smb2_flush_send_queue(xconn);
2842 if (!NT_STATUS_IS_OK(status)) {
2846 return NT_STATUS_OK;
2849 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_connection *xconn,
2850 struct smbXsrv_session *session,
2851 struct smbXsrv_tcon *tcon,
2852 struct smbXsrv_open *op,
2853 uint8_t oplock_level)
2857 SSVAL(body, 0x00, sizeof(body));
2858 SCVAL(body, 0x02, oplock_level);
2859 SCVAL(body, 0x03, 0); /* reserved */
2860 SIVAL(body, 0x04, 0); /* reserved */
2861 SBVAL(body, 0x08, op->global->open_persistent_id);
2862 SBVAL(body, 0x10, op->global->open_volatile_id);
2864 return smbd_smb2_send_break(xconn, session, tcon, body, sizeof(body));
2867 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_connection *xconn,
2869 uint32_t lease_flags,
2870 struct smb2_lease_key *lease_key,
2871 uint32_t current_lease_state,
2872 uint32_t new_lease_state)
2876 SSVAL(body, 0x00, sizeof(body));
2877 SSVAL(body, 0x02, new_epoch);
2878 SIVAL(body, 0x04, lease_flags);
2879 SBVAL(body, 0x08, lease_key->data[0]);
2880 SBVAL(body, 0x10, lease_key->data[1]);
2881 SIVAL(body, 0x18, current_lease_state);
2882 SIVAL(body, 0x1c, new_lease_state);
2883 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
2884 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
2885 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
2887 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
2890 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2894 uint64_t file_id_persistent;
2895 uint64_t file_id_volatile;
2896 struct smbXsrv_open *op = NULL;
2897 struct files_struct *fsp = NULL;
2898 const uint8_t *body = NULL;
2901 * This is only called with a pktbuf
2902 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
2906 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
2907 /* Transform header. Cannot recvfile. */
2910 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
2911 /* Not SMB2. Normal error path will cope. */
2914 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
2915 /* Not SMB2. Normal error path will cope. */
2918 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
2919 /* Needs to be a WRITE. */
2922 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
2923 /* Chained. Cannot recvfile. */
2926 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
2927 if (flags & SMB2_HDR_FLAG_CHAINED) {
2928 /* Chained. Cannot recvfile. */
2931 if (flags & SMB2_HDR_FLAG_SIGNED) {
2932 /* Signed. Cannot recvfile. */
2936 body = &state->pktbuf[SMB2_HDR_BODY];
2938 file_id_persistent = BVAL(body, 0x10);
2939 file_id_volatile = BVAL(body, 0x18);
2941 status = smb2srv_open_lookup(state->req->xconn,
2946 if (!NT_STATUS_IS_OK(status)) {
2954 if (fsp->conn == NULL) {
2958 if (IS_IPC(fsp->conn)) {
2961 if (IS_PRINT(fsp->conn)) {
2965 DEBUG(10,("Doing recvfile write len = %u\n",
2966 (unsigned int)(state->pktfull - state->pktlen)));
2971 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
2973 struct smbd_server_connection *sconn = xconn->client->sconn;
2974 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
2975 size_t max_send_queue_len;
2976 size_t cur_send_queue_len;
2978 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
2980 * we're not supposed to do any io
2982 return NT_STATUS_OK;
2985 if (state->req != NULL) {
2987 * if there is already a tstream_readv_pdu
2988 * pending, we are done.
2990 return NT_STATUS_OK;
2993 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
2994 cur_send_queue_len = xconn->smb2.send_queue_len;
2996 if (cur_send_queue_len > max_send_queue_len) {
2998 * if we have a lot of requests to send,
2999 * we wait until they are on the wire until we
3000 * ask for the next request.
3002 return NT_STATUS_OK;
3005 /* ask for the next request */
3006 ZERO_STRUCTP(state);
3007 state->req = smbd_smb2_request_allocate(xconn);
3008 if (state->req == NULL) {
3009 return NT_STATUS_NO_MEMORY;
3011 state->req->sconn = sconn;
3012 state->req->xconn = xconn;
3013 state->min_recv_size = lp_min_receive_file_size();
3015 TEVENT_FD_READABLE(xconn->transport.fde);
3017 return NT_STATUS_OK;
3020 void smbd_smb2_first_negprot(struct smbXsrv_connection *xconn,
3021 const uint8_t *inpdu, size_t size)
3023 struct smbd_server_connection *sconn = xconn->client->sconn;
3025 struct smbd_smb2_request *req = NULL;
3027 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3028 (unsigned int)size));
3030 status = smbd_initialize_smb2(xconn);
3031 if (!NT_STATUS_IS_OK(status)) {
3032 smbd_server_connection_terminate(xconn, nt_errstr(status));
3036 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
3037 if (!NT_STATUS_IS_OK(status)) {
3038 smbd_server_connection_terminate(xconn, nt_errstr(status));
3042 status = smbd_smb2_request_validate(req);
3043 if (!NT_STATUS_IS_OK(status)) {
3044 smbd_server_connection_terminate(xconn, nt_errstr(status));
3048 status = smbd_smb2_request_setup_out(req);
3049 if (!NT_STATUS_IS_OK(status)) {
3050 smbd_server_connection_terminate(xconn, nt_errstr(status));
3056 * this was already counted at the SMB1 layer =>
3057 * smbd_smb2_request_dispatch() should not count it twice.
3059 if (profile_p->request_stats.count > 0) {
3060 profile_p->request_stats.count--;
3063 status = smbd_smb2_request_dispatch(req);
3064 if (!NT_STATUS_IS_OK(status)) {
3065 smbd_server_connection_terminate(xconn, nt_errstr(status));
3069 status = smbd_smb2_request_next_incoming(xconn);
3070 if (!NT_STATUS_IS_OK(status)) {
3071 smbd_server_connection_terminate(xconn, nt_errstr(status));
3075 sconn->num_requests++;
3078 static int socket_error_from_errno(int ret,
3092 if (sys_errno == 0) {
3096 if (sys_errno == EINTR) {
3101 if (sys_errno == EINPROGRESS) {
3106 if (sys_errno == EAGAIN) {
3111 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3112 if (sys_errno == ENOMEM) {
3118 #if EWOULDBLOCK != EAGAIN
3119 if (sys_errno == EWOULDBLOCK) {
3129 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3135 if (xconn->smb2.send_queue == NULL) {
3136 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3137 return NT_STATUS_OK;
3140 while (xconn->smb2.send_queue != NULL) {
3141 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3143 if (e->sendfile_header != NULL) {
3144 NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
3149 for (i=0; i < e->count; i++) {
3150 size += e->vector[i].iov_len;
3153 if (size <= e->sendfile_header->length) {
3154 buf = e->sendfile_header->data;
3156 buf = talloc_array(e->mem_ctx, uint8_t, size);
3158 return NT_STATUS_NO_MEMORY;
3163 for (i=0; i < e->count; i++) {
3165 e->vector[i].iov_base,
3166 e->vector[i].iov_len);
3167 size += e->vector[i].iov_len;
3170 e->sendfile_header->data = buf;
3171 e->sendfile_header->length = size;
3172 e->sendfile_status = &status;
3175 xconn->smb2.send_queue_len--;
3176 DLIST_REMOVE(xconn->smb2.send_queue, e);
3178 * This triggers the sendfile path via
3181 talloc_free(e->mem_ctx);
3183 if (!NT_STATUS_IS_OK(status)) {
3189 ret = writev(xconn->transport.sock, e->vector, e->count);
3191 /* propagate end of file */
3192 return NT_STATUS_INTERNAL_ERROR;
3194 err = socket_error_from_errno(ret, errno, &retry);
3197 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3198 return NT_STATUS_OK;
3201 return map_nt_error_from_unix_common(err);
3204 if (ret < e->vector[0].iov_len) {
3206 base = (uint8_t *)e->vector[0].iov_base;
3208 e->vector[0].iov_base = (void *)base;
3209 e->vector[0].iov_len -= ret;
3212 ret -= e->vector[0].iov_len;
3218 * there're maybe some empty vectors at the end
3219 * which we need to skip, otherwise we would get
3220 * ret == 0 from the readv() call and return EPIPE
3222 while (e->count > 0) {
3223 if (e->vector[0].iov_len > 0) {
3231 /* we have more to write */
3232 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3233 return NT_STATUS_OK;
3236 xconn->smb2.send_queue_len--;
3237 DLIST_REMOVE(xconn->smb2.send_queue, e);
3238 talloc_free(e->mem_ctx);
3241 return NT_STATUS_OK;
3244 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3247 struct smbd_server_connection *sconn = xconn->client->sconn;
3248 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3249 struct smbd_smb2_request *req = NULL;
3250 size_t min_recvfile_size = UINT32_MAX;
3257 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3259 * we're not supposed to do any io
3261 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3262 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3263 return NT_STATUS_OK;
3266 if (fde_flags & TEVENT_FD_WRITE) {
3267 status = smbd_smb2_flush_send_queue(xconn);
3268 if (!NT_STATUS_IS_OK(status)) {
3273 if (!(fde_flags & TEVENT_FD_READ)) {
3274 return NT_STATUS_OK;
3277 if (state->req == NULL) {
3278 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3279 return NT_STATUS_OK;
3283 if (!state->hdr.done) {
3284 state->hdr.done = true;
3286 state->vector.iov_base = (void *)state->hdr.nbt;
3287 state->vector.iov_len = NBT_HDR_SIZE;
3290 ret = readv(xconn->transport.sock, &state->vector, 1);
3292 /* propagate end of file */
3293 return NT_STATUS_END_OF_FILE;
3295 err = socket_error_from_errno(ret, errno, &retry);
3298 TEVENT_FD_READABLE(xconn->transport.fde);
3299 return NT_STATUS_OK;
3302 return map_nt_error_from_unix_common(err);
3305 if (ret < state->vector.iov_len) {
3307 base = (uint8_t *)state->vector.iov_base;
3309 state->vector.iov_base = (void *)base;
3310 state->vector.iov_len -= ret;
3311 /* we have more to read */
3312 TEVENT_FD_READABLE(xconn->transport.fde);
3313 return NT_STATUS_OK;
3316 if (state->pktlen > 0) {
3317 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3319 * Not a possible receivefile write.
3320 * Read the rest of the data.
3322 state->doing_receivefile = false;
3324 state->pktbuf = talloc_realloc(state->req,
3328 if (state->pktbuf == NULL) {
3329 return NT_STATUS_NO_MEMORY;
3332 state->vector.iov_base = (void *)(state->pktbuf +
3334 state->vector.iov_len = (state->pktfull -
3337 state->pktlen = state->pktfull;
3342 * Either this is a receivefile write so we've
3343 * done a short read, or if not we have all the data.
3349 * Now we analyze the NBT header
3351 if (state->hdr.nbt[0] != 0x00) {
3352 state->min_recv_size = 0;
3354 state->pktfull = smb2_len(state->hdr.nbt);
3355 if (state->pktfull == 0) {
3359 if (state->min_recv_size != 0) {
3360 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3361 min_recvfile_size += state->min_recv_size;
3364 if (state->pktfull > min_recvfile_size) {
3366 * Might be a receivefile write. Read the SMB2 HEADER +
3367 * SMB2_WRITE header first. Set 'doing_receivefile'
3368 * as we're *attempting* receivefile write. If this
3369 * turns out not to be a SMB2_WRITE request or otherwise
3370 * not suitable then we'll just read the rest of the data
3371 * the next time this function is called.
3373 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3374 state->doing_receivefile = true;
3376 state->pktlen = state->pktfull;
3379 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3380 if (state->pktbuf == NULL) {
3381 return NT_STATUS_NO_MEMORY;
3384 state->vector.iov_base = (void *)state->pktbuf;
3385 state->vector.iov_len = state->pktlen;
3391 if (state->hdr.nbt[0] != 0x00) {
3392 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3393 state->hdr.nbt[0]));
3396 ZERO_STRUCTP(state);
3398 state->min_recv_size = lp_min_receive_file_size();
3406 req->request_time = timeval_current();
3407 now = timeval_to_nttime(&req->request_time);
3409 status = smbd_smb2_inbuf_parse_compound(xconn,
3415 &req->in.vector_count);
3416 if (!NT_STATUS_IS_OK(status)) {
3420 if (state->doing_receivefile) {
3421 req->smb1req = talloc_zero(req, struct smb_request);
3422 if (req->smb1req == NULL) {
3423 return NT_STATUS_NO_MEMORY;
3425 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3428 ZERO_STRUCTP(state);
3430 req->current_idx = 1;
3432 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3433 req->current_idx, req->in.vector_count));
3435 status = smbd_smb2_request_validate(req);
3436 if (!NT_STATUS_IS_OK(status)) {
3440 status = smbd_smb2_request_setup_out(req);
3441 if (!NT_STATUS_IS_OK(status)) {
3445 status = smbd_smb2_request_dispatch(req);
3446 if (!NT_STATUS_IS_OK(status)) {
3450 sconn->num_requests++;
3452 /* The timeout_processing function isn't run nearly
3453 often enough to implement 'max log size' without
3454 overrunning the size of the file by many megabytes.
3455 This is especially true if we are running at debug
3456 level 10. Checking every 50 SMB2s is a nice
3457 tradeoff of performance vs log file size overrun. */
3459 if ((sconn->num_requests % 50) == 0 &&
3460 need_to_check_log_size()) {
3461 change_to_root_user();
3465 status = smbd_smb2_request_next_incoming(xconn);
3466 if (!NT_STATUS_IS_OK(status)) {
3470 return NT_STATUS_OK;
3473 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3474 struct tevent_fd *fde,
3478 struct smbXsrv_connection *xconn =
3479 talloc_get_type_abort(private_data,
3480 struct smbXsrv_connection);
3483 status = smbd_smb2_io_handler(xconn, flags);
3484 if (!NT_STATUS_IS_OK(status)) {
3485 smbd_server_connection_terminate(xconn, nt_errstr(status));