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"
36 #define DBGC_CLASS DBGC_SMB2
38 static void smbd_smb2_connection_handler(struct tevent_context
*ev
,
39 struct tevent_fd
*fde
,
42 static NTSTATUS
smbd_smb2_flush_send_queue(struct smbXsrv_connection
*xconn
);
44 static const struct smbd_smb2_dispatch_table
{
51 bool allow_invalid_fileid
;
53 } smbd_smb2_table
[] = {
54 #define _OP(o) .opcode = o, .name = #o
59 _OP(SMB2_OP_SESSSETUP
),
69 * This call needs to be run as root.
71 * smbd_smb2_request_process_tcon()
72 * calls make_connection_snum(), which will call
73 * change_to_user(), when needed.
102 .need_session
= true,
108 .need_session
= true,
113 .need_session
= true,
116 .allow_invalid_fileid
= true,
122 _OP(SMB2_OP_KEEPALIVE
),
125 _OP(SMB2_OP_QUERY_DIRECTORY
),
126 .need_session
= true,
131 .need_session
= true,
135 _OP(SMB2_OP_GETINFO
),
136 .need_session
= true,
140 _OP(SMB2_OP_SETINFO
),
141 .need_session
= true,
147 .need_session
= true,
152 * as LEASE breaks does not
158 const char *smb2_opcode_name(uint16_t opcode
)
160 if (opcode
>= ARRAY_SIZE(smbd_smb2_table
)) {
161 return "Bad SMB2 opcode";
163 return smbd_smb2_table
[opcode
].name
;
166 static const struct smbd_smb2_dispatch_table
*smbd_smb2_call(uint16_t opcode
)
168 const struct smbd_smb2_dispatch_table
*ret
= NULL
;
170 if (opcode
>= ARRAY_SIZE(smbd_smb2_table
)) {
174 ret
= &smbd_smb2_table
[opcode
];
176 SMB_ASSERT(ret
->opcode
== opcode
);
181 static void print_req_vectors(const struct smbd_smb2_request
*req
)
185 for (i
= 0; i
< req
->in
.vector_count
; i
++) {
186 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
188 (unsigned int)req
->in
.vector
[i
].iov_len
);
190 for (i
= 0; i
< req
->out
.vector_count
; i
++) {
191 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
193 (unsigned int)req
->out
.vector
[i
].iov_len
);
197 bool smbd_is_smb2_header(const uint8_t *inbuf
, size_t size
)
199 if (size
< (4 + SMB2_HDR_BODY
)) {
203 if (IVAL(inbuf
, 4) != SMB2_MAGIC
) {
210 bool smbd_smb2_is_compound(const struct smbd_smb2_request
*req
)
212 return req
->in
.vector_count
>= (2*SMBD_SMB2_NUM_IOV_PER_REQ
);
215 static NTSTATUS
smbd_initialize_smb2(struct smbXsrv_connection
*xconn
,
216 uint64_t expected_seq_low
)
218 TALLOC_FREE(xconn
->transport
.fde
);
220 xconn
->smb2
.credits
.seq_low
= expected_seq_low
;
221 xconn
->smb2
.credits
.seq_range
= 1;
222 xconn
->smb2
.credits
.granted
= 1;
223 xconn
->smb2
.credits
.max
= lp_smb2_max_credits();
224 xconn
->smb2
.credits
.bitmap
= bitmap_talloc(xconn
,
225 xconn
->smb2
.credits
.max
);
226 if (xconn
->smb2
.credits
.bitmap
== NULL
) {
227 return NT_STATUS_NO_MEMORY
;
230 xconn
->transport
.fde
= tevent_add_fd(
231 xconn
->client
->raw_ev_ctx
,
233 xconn
->transport
.sock
,
235 smbd_smb2_connection_handler
,
237 if (xconn
->transport
.fde
== NULL
) {
238 return NT_STATUS_NO_MEMORY
;
241 /* Ensure child is set to non-blocking mode */
242 set_blocking(xconn
->transport
.sock
, false);
246 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
247 #define _smb2_setlen(_buf,len) do { \
248 uint8_t *buf = (uint8_t *)_buf; \
250 buf[1] = ((len)&0xFF0000)>>16; \
251 buf[2] = ((len)&0xFF00)>>8; \
252 buf[3] = (len)&0xFF; \
255 static bool smb2_setup_nbt_length(struct iovec
*vector
, int count
)
263 len
= iov_buflen(vector
+1, count
-1);
265 if ((len
== -1) || (len
> 0xFFFFFF)) {
269 _smb2_setlen(vector
[0].iov_base
, len
);
273 static int smbd_smb2_request_destructor(struct smbd_smb2_request
*req
)
275 if (req
->first_key
.length
> 0) {
276 data_blob_clear_free(&req
->first_key
);
278 if (req
->last_key
.length
> 0) {
279 data_blob_clear_free(&req
->last_key
);
284 void smb2_request_set_async_internal(struct smbd_smb2_request
*req
,
287 req
->async_internal
= async_internal
;
290 static struct smbd_smb2_request
*smbd_smb2_request_allocate(TALLOC_CTX
*mem_ctx
)
292 TALLOC_CTX
*mem_pool
;
293 struct smbd_smb2_request
*req
;
296 /* Enable this to find subtle valgrind errors. */
297 mem_pool
= talloc_init("smbd_smb2_request_allocate");
299 mem_pool
= talloc_tos();
301 if (mem_pool
== NULL
) {
305 req
= talloc_zero(mem_pool
, struct smbd_smb2_request
);
307 talloc_free(mem_pool
);
310 talloc_reparent(mem_pool
, mem_ctx
, req
);
312 TALLOC_FREE(mem_pool
);
315 req
->last_session_id
= UINT64_MAX
;
316 req
->last_tid
= UINT32_MAX
;
318 talloc_set_destructor(req
, smbd_smb2_request_destructor
);
323 static NTSTATUS
smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection
*xconn
,
327 struct smbd_smb2_request
*req
,
331 TALLOC_CTX
*mem_ctx
= req
;
335 uint8_t *first_hdr
= buf
;
336 size_t verified_buflen
= 0;
341 * Note: index '0' is reserved for the transport protocol
343 iov
= req
->in
._vector
;
345 while (taken
< buflen
) {
346 size_t len
= buflen
- taken
;
347 uint8_t *hdr
= first_hdr
+ taken
;
350 size_t next_command_ofs
;
352 uint8_t *body
= NULL
;
355 struct iovec
*iov_alloc
= NULL
;
357 if (iov
!= req
->in
._vector
) {
361 if (verified_buflen
> taken
) {
362 len
= verified_buflen
- taken
;
369 DEBUG(10, ("%d bytes left, expected at least %d\n",
373 if (IVAL(hdr
, 0) == SMB2_TF_MAGIC
) {
374 struct smbXsrv_session
*s
= NULL
;
376 struct iovec tf_iov
[2];
380 if (xconn
->protocol
< PROTOCOL_SMB2_24
) {
381 DEBUG(10, ("Got SMB2_TRANSFORM header, "
382 "but dialect[0x%04X] is used\n",
383 xconn
->smb2
.server
.dialect
));
387 if (xconn
->smb2
.server
.cipher
== 0) {
388 DEBUG(10, ("Got SMB2_TRANSFORM header, "
389 "but not negotiated "
390 "client[0x%08X] server[0x%08X]\n",
391 xconn
->smb2
.client
.capabilities
,
392 xconn
->smb2
.server
.capabilities
));
396 if (len
< SMB2_TF_HDR_SIZE
) {
397 DEBUG(1, ("%d bytes left, expected at least %d\n",
398 (int)len
, SMB2_TF_HDR_SIZE
));
402 tf_len
= SMB2_TF_HDR_SIZE
;
405 hdr
= first_hdr
+ taken
;
406 enc_len
= IVAL(tf
, SMB2_TF_MSG_SIZE
);
407 uid
= BVAL(tf
, SMB2_TF_SESSION_ID
);
409 if (len
< SMB2_TF_HDR_SIZE
+ enc_len
) {
410 DEBUG(1, ("%d bytes left, expected at least %d\n",
412 (int)(SMB2_TF_HDR_SIZE
+ enc_len
)));
416 status
= smb2srv_session_lookup_conn(xconn
, uid
, now
,
419 DEBUG(1, ("invalid session[%llu] in "
420 "SMB2_TRANSFORM header\n",
421 (unsigned long long)uid
));
422 TALLOC_FREE(iov_alloc
);
423 return NT_STATUS_USER_SESSION_DELETED
;
426 tf_iov
[0].iov_base
= (void *)tf
;
427 tf_iov
[0].iov_len
= tf_len
;
428 tf_iov
[1].iov_base
= (void *)hdr
;
429 tf_iov
[1].iov_len
= enc_len
;
431 status
= smb2_signing_decrypt_pdu(s
->global
->decryption_key
,
432 xconn
->smb2
.server
.cipher
,
434 if (!NT_STATUS_IS_OK(status
)) {
435 TALLOC_FREE(iov_alloc
);
439 verified_buflen
= taken
+ enc_len
;
444 * We need the header plus the body length field
447 if (len
< SMB2_HDR_BODY
+ 2) {
448 DEBUG(10, ("%d bytes left, expected at least %d\n",
449 (int)len
, SMB2_HDR_BODY
));
452 if (IVAL(hdr
, 0) != SMB2_MAGIC
) {
453 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
457 if (SVAL(hdr
, 4) != SMB2_HDR_BODY
) {
458 DEBUG(10, ("Got HDR len %d, expected %d\n",
459 SVAL(hdr
, 4), SMB2_HDR_BODY
));
464 next_command_ofs
= IVAL(hdr
, SMB2_HDR_NEXT_COMMAND
);
465 body_size
= SVAL(hdr
, SMB2_HDR_BODY
);
467 if (next_command_ofs
!= 0) {
468 if (next_command_ofs
< (SMB2_HDR_BODY
+ 2)) {
471 if (next_command_ofs
> full_size
) {
474 full_size
= next_command_ofs
;
481 if (body_size
> (full_size
- SMB2_HDR_BODY
)) {
483 * let the caller handle the error
485 body_size
= full_size
- SMB2_HDR_BODY
;
487 body
= hdr
+ SMB2_HDR_BODY
;
488 dyn
= body
+ body_size
;
489 dyn_size
= full_size
- (SMB2_HDR_BODY
+ body_size
);
491 if (num_iov
>= ARRAY_SIZE(req
->in
._vector
)) {
492 struct iovec
*iov_tmp
= NULL
;
494 iov_tmp
= talloc_realloc(mem_ctx
, iov_alloc
,
497 SMBD_SMB2_NUM_IOV_PER_REQ
);
498 if (iov_tmp
== NULL
) {
499 TALLOC_FREE(iov_alloc
);
500 return NT_STATUS_NO_MEMORY
;
503 if (iov_alloc
== NULL
) {
506 sizeof(req
->in
._vector
));
512 num_iov
+= SMBD_SMB2_NUM_IOV_PER_REQ
;
514 cur
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= tf
;
515 cur
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= tf_len
;
516 cur
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
517 cur
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
518 cur
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
519 cur
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= body_size
;
520 cur
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
521 cur
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= dyn_size
;
531 if (iov
!= req
->in
._vector
) {
534 return NT_STATUS_INVALID_PARAMETER
;
537 static NTSTATUS
smbd_smb2_request_create(struct smbXsrv_connection
*xconn
,
538 const uint8_t *_inpdu
, size_t size
,
539 struct smbd_smb2_request
**_req
)
541 struct smbd_server_connection
*sconn
= xconn
->client
->sconn
;
542 struct smbd_smb2_request
*req
;
543 uint32_t protocol_version
;
544 uint8_t *inpdu
= NULL
;
545 const uint8_t *inhdr
= NULL
;
547 uint32_t next_command_ofs
;
551 if (size
< (SMB2_HDR_BODY
+ 2)) {
552 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size
));
553 return NT_STATUS_INVALID_PARAMETER
;
558 protocol_version
= IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
);
559 if (protocol_version
!= SMB2_MAGIC
) {
560 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
562 return NT_STATUS_INVALID_PARAMETER
;
565 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
566 if (cmd
!= SMB2_OP_NEGPROT
) {
567 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
569 return NT_STATUS_INVALID_PARAMETER
;
572 next_command_ofs
= IVAL(inhdr
, SMB2_HDR_NEXT_COMMAND
);
573 if (next_command_ofs
!= 0) {
574 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
576 return NT_STATUS_INVALID_PARAMETER
;
579 req
= smbd_smb2_request_allocate(xconn
);
581 return NT_STATUS_NO_MEMORY
;
586 inpdu
= talloc_memdup(req
, _inpdu
, size
);
588 return NT_STATUS_NO_MEMORY
;
591 req
->request_time
= timeval_current();
592 now
= timeval_to_nttime(&req
->request_time
);
594 status
= smbd_smb2_inbuf_parse_compound(xconn
,
598 req
, &req
->in
.vector
,
599 &req
->in
.vector_count
);
600 if (!NT_STATUS_IS_OK(status
)) {
605 req
->current_idx
= 1;
611 static bool smb2_validate_sequence_number(struct smbXsrv_connection
*xconn
,
612 uint64_t message_id
, uint64_t seq_id
)
614 struct bitmap
*credits_bm
= xconn
->smb2
.credits
.bitmap
;
618 seq_tmp
= xconn
->smb2
.credits
.seq_low
;
619 if (seq_id
< seq_tmp
) {
620 DBGC_ERR(DBGC_SMB2_CREDITS
,
621 "smb2_validate_sequence_number: bad message_id "
622 "%llu (sequence id %llu) "
623 "(granted = %u, low = %llu, range = %u)\n",
624 (unsigned long long)message_id
,
625 (unsigned long long)seq_id
,
626 (unsigned int)xconn
->smb2
.credits
.granted
,
627 (unsigned long long)xconn
->smb2
.credits
.seq_low
,
628 (unsigned int)xconn
->smb2
.credits
.seq_range
);
632 seq_tmp
+= xconn
->smb2
.credits
.seq_range
;
633 if (seq_id
>= seq_tmp
) {
634 DBGC_ERR(DBGC_SMB2_CREDITS
,
635 "smb2_validate_sequence_number: bad message_id "
636 "%llu (sequence id %llu) "
637 "(granted = %u, low = %llu, range = %u)\n",
638 (unsigned long long)message_id
,
639 (unsigned long long)seq_id
,
640 (unsigned int)xconn
->smb2
.credits
.granted
,
641 (unsigned long long)xconn
->smb2
.credits
.seq_low
,
642 (unsigned int)xconn
->smb2
.credits
.seq_range
);
646 offset
= seq_id
% xconn
->smb2
.credits
.max
;
648 if (bitmap_query(credits_bm
, offset
)) {
649 DBGC_ERR(DBGC_SMB2_CREDITS
,
650 "smb2_validate_sequence_number: duplicate message_id "
651 "%llu (sequence id %llu) "
652 "(granted = %u, low = %llu, range = %u) "
654 (unsigned long long)message_id
,
655 (unsigned long long)seq_id
,
656 (unsigned int)xconn
->smb2
.credits
.granted
,
657 (unsigned long long)xconn
->smb2
.credits
.seq_low
,
658 (unsigned int)xconn
->smb2
.credits
.seq_range
,
663 /* Mark the message_ids as seen in the bitmap. */
664 bitmap_set(credits_bm
, offset
);
666 if (seq_id
!= xconn
->smb2
.credits
.seq_low
) {
671 * Move the window forward by all the message_id's
674 while (bitmap_query(credits_bm
, offset
)) {
675 DBGC_DEBUG(DBGC_SMB2_CREDITS
,
676 "smb2_validate_sequence_number: clearing "
677 "id %llu (position %u) from bitmap\n",
678 (unsigned long long)(xconn
->smb2
.credits
.seq_low
),
680 bitmap_clear(credits_bm
, offset
);
682 xconn
->smb2
.credits
.seq_low
+= 1;
683 xconn
->smb2
.credits
.seq_range
-= 1;
684 offset
= xconn
->smb2
.credits
.seq_low
% xconn
->smb2
.credits
.max
;
690 static bool smb2_validate_message_id(struct smbXsrv_connection
*xconn
,
691 const uint8_t *inhdr
)
693 uint64_t message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
694 uint16_t opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
695 uint16_t credit_charge
= 1;
698 if (opcode
== SMB2_OP_CANCEL
) {
699 /* SMB2_CANCEL requests by definition resend messageids. */
703 if (xconn
->smb2
.credits
.multicredit
) {
704 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
705 credit_charge
= MAX(credit_charge
, 1);
710 ("smb2_validate_message_id: mid %llu (charge %llu), "
711 "credits_granted %llu, "
712 "seqnum low/range: %llu/%llu\n",
713 (unsigned long long) message_id
,
714 (unsigned long long) credit_charge
,
715 (unsigned long long) xconn
->smb2
.credits
.granted
,
716 (unsigned long long) xconn
->smb2
.credits
.seq_low
,
717 (unsigned long long) xconn
->smb2
.credits
.seq_range
));
719 if (xconn
->smb2
.credits
.granted
< credit_charge
) {
720 DBGC_ERR(DBGC_SMB2_CREDITS
,
721 "smb2_validate_message_id: client used more "
722 "credits than granted, mid %llu, charge %llu, "
723 "credits_granted %llu, "
724 "seqnum low/range: %llu/%llu\n",
725 (unsigned long long) message_id
,
726 (unsigned long long) credit_charge
,
727 (unsigned long long) xconn
->smb2
.credits
.granted
,
728 (unsigned long long) xconn
->smb2
.credits
.seq_low
,
729 (unsigned long long) xconn
->smb2
.credits
.seq_range
);
734 * now check the message ids
736 * for multi-credit requests we need to check all current mid plus
737 * the implicit mids caused by the credit charge
738 * e.g. current mid = 15, charge 5 => mark 15-19 as used
741 for (i
= 0; i
<= (credit_charge
-1); i
++) {
742 uint64_t id
= message_id
+ i
;
747 ("Iterating mid %llu charge %u (sequence %llu)\n",
748 (unsigned long long)message_id
,
750 (unsigned long long)id
));
752 ok
= smb2_validate_sequence_number(xconn
, message_id
, id
);
758 /* substract used credits */
759 xconn
->smb2
.credits
.granted
-= credit_charge
;
764 static NTSTATUS
smbd_smb2_request_validate(struct smbd_smb2_request
*req
)
769 count
= req
->in
.vector_count
;
771 if (count
< 1 + SMBD_SMB2_NUM_IOV_PER_REQ
) {
772 /* It's not a SMB2 request */
773 return NT_STATUS_INVALID_PARAMETER
;
776 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
777 struct iovec
*hdr
= SMBD_SMB2_IDX_HDR_IOV(req
,in
,idx
);
778 struct iovec
*body
= SMBD_SMB2_IDX_BODY_IOV(req
,in
,idx
);
779 const uint8_t *inhdr
= NULL
;
781 if (hdr
->iov_len
!= SMB2_HDR_BODY
) {
782 return NT_STATUS_INVALID_PARAMETER
;
785 if (body
->iov_len
< 2) {
786 return NT_STATUS_INVALID_PARAMETER
;
789 inhdr
= (const uint8_t *)hdr
->iov_base
;
791 /* Check the SMB2 header */
792 if (IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
) != SMB2_MAGIC
) {
793 return NT_STATUS_INVALID_PARAMETER
;
796 if (!smb2_validate_message_id(req
->xconn
, inhdr
)) {
797 return NT_STATUS_INVALID_PARAMETER
;
804 static void smb2_set_operation_credit(struct smbXsrv_connection
*xconn
,
805 const struct iovec
*in_vector
,
806 struct iovec
*out_vector
)
808 const uint8_t *inhdr
= (const uint8_t *)in_vector
->iov_base
;
809 uint8_t *outhdr
= (uint8_t *)out_vector
->iov_base
;
810 uint16_t credit_charge
= 1;
811 uint16_t credits_requested
;
815 uint16_t credits_granted
= 0;
816 uint64_t credits_possible
;
817 uint16_t current_max_credits
;
820 * first we grant only 1/16th of the max range.
822 * Windows also starts with the 1/16th and then grants
823 * more later. I was only able to trigger higher
824 * values, when using a very high credit charge.
826 * TODO: scale up depending on load, free memory
828 * Maybe also on the relationship between number
829 * of requests and the used sequence number.
830 * Which means we would grant more credits
831 * for client which use multi credit requests.
833 * The above is what Windows Server < 2016 is doing,
834 * but new servers use all credits (8192 by default).
836 current_max_credits
= xconn
->smb2
.credits
.max
;
837 current_max_credits
= MAX(current_max_credits
, 1);
839 if (xconn
->smb2
.credits
.multicredit
) {
840 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
841 credit_charge
= MAX(credit_charge
, 1);
844 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
845 credits_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
846 credits_requested
= MAX(credits_requested
, 1);
847 out_flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
848 out_status
= NT_STATUS(IVAL(outhdr
, SMB2_HDR_STATUS
));
850 SMB_ASSERT(xconn
->smb2
.credits
.max
>= xconn
->smb2
.credits
.granted
);
852 if (xconn
->smb2
.credits
.max
< credit_charge
) {
853 smbd_server_connection_terminate(xconn
,
854 "client error: credit charge > max credits\n");
858 if (out_flags
& SMB2_HDR_FLAG_ASYNC
) {
860 * In case we already send an async interim
861 * response, we should not grant
862 * credits on the final response.
866 uint16_t additional_possible
=
867 xconn
->smb2
.credits
.max
- credit_charge
;
868 uint16_t additional_max
= 0;
869 uint16_t additional_credits
= credits_requested
- 1;
872 case SMB2_OP_NEGPROT
:
874 case SMB2_OP_SESSSETUP
:
876 * Windows 2012 RC1 starts to grant
878 * with a successful session setup
880 if (NT_STATUS_IS_OK(out_status
)) {
881 additional_max
= xconn
->smb2
.credits
.max
;
886 * Windows Server < 2016 and older Samba versions
887 * used to only grant additional credits in
888 * chunks of 32 credits.
890 * But we match Windows Server 2016 and grant
891 * all credits as requested.
893 additional_max
= xconn
->smb2
.credits
.max
;
897 additional_max
= MIN(additional_max
, additional_possible
);
898 additional_credits
= MIN(additional_credits
, additional_max
);
900 credits_granted
= credit_charge
+ additional_credits
;
904 * sequence numbers should not wrap
906 * 1. calculate the possible credits until
907 * the sequence numbers start to wrap on 64-bit.
909 * 2. UINT64_MAX is used for Break Notifications.
911 * 2. truncate the possible credits to the maximum
912 * credits we want to grant to the client in total.
914 * 3. remove the range we'll already granted to the client
915 * this makes sure the client consumes the lowest sequence
916 * number, before we can grant additional credits.
918 credits_possible
= UINT64_MAX
- xconn
->smb2
.credits
.seq_low
;
919 if (credits_possible
> 0) {
920 /* remove UINT64_MAX */
921 credits_possible
-= 1;
923 credits_possible
= MIN(credits_possible
, current_max_credits
);
924 credits_possible
-= xconn
->smb2
.credits
.seq_range
;
926 credits_granted
= MIN(credits_granted
, credits_possible
);
928 SSVAL(outhdr
, SMB2_HDR_CREDIT
, credits_granted
);
929 xconn
->smb2
.credits
.granted
+= credits_granted
;
930 xconn
->smb2
.credits
.seq_range
+= credits_granted
;
932 DBGC_DEBUG(DBGC_SMB2_CREDITS
,
933 "smb2_set_operation_credit: requested %u, charge %u, "
934 "granted %u, current possible/max %u/%u, "
935 "total granted/max/low/range %u/%u/%llu/%u\n",
936 (unsigned int)credits_requested
,
937 (unsigned int)credit_charge
,
938 (unsigned int)credits_granted
,
939 (unsigned int)credits_possible
,
940 (unsigned int)current_max_credits
,
941 (unsigned int)xconn
->smb2
.credits
.granted
,
942 (unsigned int)xconn
->smb2
.credits
.max
,
943 (unsigned long long)xconn
->smb2
.credits
.seq_low
,
944 (unsigned int)xconn
->smb2
.credits
.seq_range
);
947 static void smb2_calculate_credits(const struct smbd_smb2_request
*inreq
,
948 struct smbd_smb2_request
*outreq
)
951 uint16_t total_credits
= 0;
953 count
= outreq
->out
.vector_count
;
955 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
956 struct iovec
*inhdr_v
= SMBD_SMB2_IDX_HDR_IOV(inreq
,in
,idx
);
957 struct iovec
*outhdr_v
= SMBD_SMB2_IDX_HDR_IOV(outreq
,out
,idx
);
958 uint8_t *outhdr
= (uint8_t *)outhdr_v
->iov_base
;
960 smb2_set_operation_credit(outreq
->xconn
, inhdr_v
, outhdr_v
);
962 /* To match Windows, count up what we
964 total_credits
+= SVAL(outhdr
, SMB2_HDR_CREDIT
);
965 /* Set to zero in all but the last reply. */
966 if (idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
< count
) {
967 SSVAL(outhdr
, SMB2_HDR_CREDIT
, 0);
969 SSVAL(outhdr
, SMB2_HDR_CREDIT
, total_credits
);
974 DATA_BLOB
smbd_smb2_generate_outbody(struct smbd_smb2_request
*req
, size_t size
)
976 if (req
->current_idx
<= 1) {
977 if (size
<= sizeof(req
->out
._body
)) {
978 return data_blob_const(req
->out
._body
, size
);
982 return data_blob_talloc(req
, NULL
, size
);
985 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
)
987 struct smbXsrv_connection
*xconn
= req
->xconn
;
989 struct iovec
*vector
;
994 count
= req
->in
.vector_count
;
995 if (count
<= ARRAY_SIZE(req
->out
._vector
)) {
997 vector
= req
->out
._vector
;
999 vector
= talloc_zero_array(req
, struct iovec
, count
);
1000 if (vector
== NULL
) {
1001 return NT_STATUS_NO_MEMORY
;
1006 vector
[0].iov_base
= req
->out
.nbt_hdr
;
1007 vector
[0].iov_len
= 4;
1008 SIVAL(req
->out
.nbt_hdr
, 0, 0);
1010 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
1011 struct iovec
*inhdr_v
= SMBD_SMB2_IDX_HDR_IOV(req
,in
,idx
);
1012 const uint8_t *inhdr
= (const uint8_t *)inhdr_v
->iov_base
;
1013 uint8_t *outhdr
= NULL
;
1014 uint8_t *outbody
= NULL
;
1015 uint32_t next_command_ofs
= 0;
1016 struct iovec
*current
= &vector
[idx
];
1018 if ((idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
) < count
) {
1019 /* we have a next command -
1020 * setup for the error case. */
1021 next_command_ofs
= SMB2_HDR_BODY
+ 9;
1025 outhdr
= req
->out
._hdr
;
1027 outhdr
= talloc_zero_array(mem_ctx
, uint8_t,
1029 if (outhdr
== NULL
) {
1030 return NT_STATUS_NO_MEMORY
;
1034 outbody
= outhdr
+ SMB2_HDR_BODY
;
1037 * SMBD_SMB2_TF_IOV_OFS might be used later
1039 current
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
1040 current
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
1042 current
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= (void *)outhdr
;
1043 current
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
1045 current
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= (void *)outbody
;
1046 current
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= 8;
1048 current
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= NULL
;
1049 current
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= 0;
1051 /* setup the SMB2 header */
1052 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
1053 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1054 SSVAL(outhdr
, SMB2_HDR_CREDIT_CHARGE
,
1055 SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
));
1056 SIVAL(outhdr
, SMB2_HDR_STATUS
,
1057 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
1058 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
1059 SVAL(inhdr
, SMB2_HDR_OPCODE
));
1060 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
1061 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
1062 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
1063 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
1064 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
1065 SIVAL(outhdr
, SMB2_HDR_PID
,
1066 IVAL(inhdr
, SMB2_HDR_PID
));
1067 SIVAL(outhdr
, SMB2_HDR_TID
,
1068 IVAL(inhdr
, SMB2_HDR_TID
));
1069 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
1070 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
1071 memcpy(outhdr
+ SMB2_HDR_SIGNATURE
,
1072 inhdr
+ SMB2_HDR_SIGNATURE
, 16);
1074 /* setup error body header */
1075 SSVAL(outbody
, 0x00, 0x08 + 1);
1076 SSVAL(outbody
, 0x02, 0);
1077 SIVAL(outbody
, 0x04, 0);
1080 req
->out
.vector
= vector
;
1081 req
->out
.vector_count
= count
;
1083 /* setup the length of the NBT packet */
1084 ok
= smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
1086 return NT_STATUS_INVALID_PARAMETER_MIX
;
1089 DLIST_ADD_END(xconn
->smb2
.requests
, req
);
1091 return NT_STATUS_OK
;
1094 void smbd_server_connection_terminate_ex(struct smbXsrv_connection
*xconn
,
1096 const char *location
)
1098 struct smbXsrv_client
*client
= xconn
->client
;
1100 DEBUG(10,("smbd_server_connection_terminate_ex: conn[%s] reason[%s] at %s\n",
1101 smbXsrv_connection_dbg(xconn
), reason
, location
));
1103 if (client
->connections
->next
!= NULL
) {
1104 /* TODO: cancel pending requests */
1105 DLIST_REMOVE(client
->connections
, xconn
);
1111 * The last connection was disconnected
1113 exit_server_cleanly(reason
);
1116 static bool dup_smb2_vec4(TALLOC_CTX
*ctx
,
1117 struct iovec
*outvec
,
1118 const struct iovec
*srcvec
)
1120 const uint8_t *srctf
;
1122 const uint8_t *srchdr
;
1124 const uint8_t *srcbody
;
1126 const uint8_t *expected_srcbody
;
1127 const uint8_t *srcdyn
;
1129 const uint8_t *expected_srcdyn
;
1135 srctf
= (const uint8_t *)srcvec
[SMBD_SMB2_TF_IOV_OFS
].iov_base
;
1136 srctf_len
= srcvec
[SMBD_SMB2_TF_IOV_OFS
].iov_len
;
1137 srchdr
= (const uint8_t *)srcvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
;
1138 srchdr_len
= srcvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
;
1139 srcbody
= (const uint8_t *)srcvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
;
1140 srcbody_len
= srcvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
;
1141 expected_srcbody
= srchdr
+ SMB2_HDR_BODY
;
1142 srcdyn
= (const uint8_t *)srcvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
;
1143 srcdyn_len
= srcvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
;
1144 expected_srcdyn
= srcbody
+ 8;
1146 if ((srctf_len
!= SMB2_TF_HDR_SIZE
) && (srctf_len
!= 0)) {
1150 if (srchdr_len
!= SMB2_HDR_BODY
) {
1154 if (srctf_len
== SMB2_TF_HDR_SIZE
) {
1155 dsttf
= talloc_memdup(ctx
, srctf
, SMB2_TF_HDR_SIZE
);
1156 if (dsttf
== NULL
) {
1162 outvec
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= (void *)dsttf
;
1163 outvec
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= srctf_len
;
1165 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1166 * be allocated with size OUTVEC_ALLOC_SIZE. */
1168 dsthdr
= talloc_memdup(ctx
, srchdr
, OUTVEC_ALLOC_SIZE
);
1169 if (dsthdr
== NULL
) {
1172 outvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= (void *)dsthdr
;
1173 outvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
1176 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1177 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1178 * then duplicate this. Else use talloc_memdup().
1181 if ((srcbody
== expected_srcbody
) && (srcbody_len
== 8)) {
1182 dstbody
= dsthdr
+ SMB2_HDR_BODY
;
1184 dstbody
= talloc_memdup(ctx
, srcbody
, srcbody_len
);
1185 if (dstbody
== NULL
) {
1189 outvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= (void *)dstbody
;
1190 outvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= srcbody_len
;
1193 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1195 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1196 * then duplicate this. Else use talloc_memdup().
1199 if ((srcdyn
== expected_srcdyn
) && (srcdyn_len
== 1)) {
1200 dstdyn
= dsthdr
+ SMB2_HDR_BODY
+ 8;
1201 } else if (srcdyn
== NULL
) {
1204 dstdyn
= talloc_memdup(ctx
, srcdyn
, srcdyn_len
);
1205 if (dstdyn
== NULL
) {
1209 outvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= (void *)dstdyn
;
1210 outvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= srcdyn_len
;
1215 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
1217 struct smbd_smb2_request
*newreq
= NULL
;
1218 struct iovec
*outvec
= NULL
;
1219 int count
= req
->out
.vector_count
;
1223 newreq
= smbd_smb2_request_allocate(req
->xconn
);
1228 newreq
->sconn
= req
->sconn
;
1229 newreq
->xconn
= req
->xconn
;
1230 newreq
->session
= req
->session
;
1231 newreq
->do_encryption
= req
->do_encryption
;
1232 newreq
->do_signing
= req
->do_signing
;
1233 newreq
->current_idx
= req
->current_idx
;
1235 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
1237 TALLOC_FREE(newreq
);
1240 newreq
->out
.vector
= outvec
;
1241 newreq
->out
.vector_count
= count
;
1243 /* Setup the outvec's identically to req. */
1244 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
1245 outvec
[0].iov_len
= 4;
1246 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
1248 /* Setup the vectors identically to the ones in req. */
1249 for (i
= 1; i
< count
; i
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
1250 if (!dup_smb2_vec4(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
1257 TALLOC_FREE(newreq
);
1261 ok
= smb2_setup_nbt_length(newreq
->out
.vector
,
1262 newreq
->out
.vector_count
);
1264 TALLOC_FREE(newreq
);
1271 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
1273 struct smbXsrv_connection
*xconn
= req
->xconn
;
1275 struct iovec
*firsttf
= NULL
;
1276 struct iovec
*outhdr_v
= NULL
;
1277 uint8_t *outhdr
= NULL
;
1278 struct smbd_smb2_request
*nreq
= NULL
;
1282 /* Create a new smb2 request we'll use
1283 for the interim return. */
1284 nreq
= dup_smb2_req(req
);
1286 return NT_STATUS_NO_MEMORY
;
1289 /* Lose the last X out vectors. They're the
1290 ones we'll be using for the async reply. */
1291 nreq
->out
.vector_count
-= SMBD_SMB2_NUM_IOV_PER_REQ
;
1293 ok
= smb2_setup_nbt_length(nreq
->out
.vector
,
1294 nreq
->out
.vector_count
);
1296 return NT_STATUS_INVALID_PARAMETER_MIX
;
1299 /* Step back to the previous reply. */
1300 nreq
->current_idx
-= SMBD_SMB2_NUM_IOV_PER_REQ
;
1301 firsttf
= SMBD_SMB2_IDX_TF_IOV(nreq
,out
,first_idx
);
1302 outhdr_v
= SMBD_SMB2_OUT_HDR_IOV(nreq
);
1303 outhdr
= SMBD_SMB2_OUT_HDR_PTR(nreq
);
1304 /* And end the chain. */
1305 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1307 /* Calculate outgoing credits */
1308 smb2_calculate_credits(req
, nreq
);
1310 if (DEBUGLEVEL
>= 10) {
1311 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1312 (unsigned int)nreq
->current_idx
);
1313 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1314 (unsigned int)nreq
->out
.vector_count
);
1315 print_req_vectors(nreq
);
1319 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1320 * we need to sign/encrypt here with the last/first key we remembered
1322 if (firsttf
->iov_len
== SMB2_TF_HDR_SIZE
) {
1323 status
= smb2_signing_encrypt_pdu(req
->first_key
,
1324 xconn
->smb2
.server
.cipher
,
1326 nreq
->out
.vector_count
- first_idx
);
1327 if (!NT_STATUS_IS_OK(status
)) {
1330 } else if (req
->last_key
.length
> 0) {
1331 status
= smb2_signing_sign_pdu(req
->last_key
,
1334 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
1335 if (!NT_STATUS_IS_OK(status
)) {
1340 nreq
->queue_entry
.mem_ctx
= nreq
;
1341 nreq
->queue_entry
.vector
= nreq
->out
.vector
;
1342 nreq
->queue_entry
.count
= nreq
->out
.vector_count
;
1343 DLIST_ADD_END(xconn
->smb2
.send_queue
, &nreq
->queue_entry
);
1344 xconn
->smb2
.send_queue_len
++;
1346 status
= smbd_smb2_flush_send_queue(xconn
);
1347 if (!NT_STATUS_IS_OK(status
)) {
1351 return NT_STATUS_OK
;
1354 struct smbd_smb2_request_pending_state
{
1355 struct smbd_smb2_send_queue queue_entry
;
1356 uint8_t buf
[NBT_HDR_SIZE
+ SMB2_TF_HDR_SIZE
+ SMB2_HDR_BODY
+ 0x08 + 1];
1357 struct iovec vector
[1 + SMBD_SMB2_NUM_IOV_PER_REQ
];
1360 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
1361 struct tevent_timer
*te
,
1362 struct timeval current_time
,
1363 void *private_data
);
1365 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
1366 struct tevent_req
*subreq
,
1367 uint32_t defer_time
)
1370 struct timeval defer_endtime
;
1371 uint8_t *outhdr
= NULL
;
1374 if (!tevent_req_is_in_progress(subreq
)) {
1376 * This is a performance optimization,
1377 * it avoids one tevent_loop iteration,
1378 * which means we avoid one
1379 * talloc_stackframe_pool/talloc_free pair.
1381 tevent_req_notify_callback(subreq
);
1382 return NT_STATUS_OK
;
1385 req
->subreq
= subreq
;
1388 if (req
->async_te
) {
1389 /* We're already async. */
1390 return NT_STATUS_OK
;
1393 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1394 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1395 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1396 /* We're already async. */
1397 return NT_STATUS_OK
;
1400 if (req
->async_internal
|| defer_time
== 0) {
1402 * An SMB2 request implementation wants to handle the request
1403 * asynchronously "internally" while keeping synchronous
1404 * behaviour for the SMB2 request. This means we don't send an
1405 * interim response and we can allow processing of compound SMB2
1406 * requests (cf the subsequent check) for all cases.
1408 return NT_STATUS_OK
;
1411 if (req
->in
.vector_count
> req
->current_idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
) {
1413 * We're trying to go async in a compound request
1414 * chain. This is only allowed for opens that cause an
1415 * oplock break or for the last operation in the
1416 * chain, otherwise it is not allowed. See
1417 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
1419 const uint8_t *inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1421 if (SVAL(inhdr
, SMB2_HDR_OPCODE
) != SMB2_OP_CREATE
) {
1423 * Cancel the outstanding request.
1425 bool ok
= tevent_req_cancel(req
->subreq
);
1427 return NT_STATUS_OK
;
1429 TALLOC_FREE(req
->subreq
);
1430 return smbd_smb2_request_error(req
,
1431 NT_STATUS_INTERNAL_ERROR
);
1435 if (DEBUGLEVEL
>= 10) {
1436 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1437 (unsigned int)req
->current_idx
);
1438 print_req_vectors(req
);
1441 if (req
->current_idx
> 1) {
1443 * We're going async in a compound
1444 * chain after the first request has
1445 * already been processed. Send an
1446 * interim response containing the
1447 * set of replies already generated.
1449 int idx
= req
->current_idx
;
1451 status
= smb2_send_async_interim_response(req
);
1452 if (!NT_STATUS_IS_OK(status
)) {
1455 if (req
->first_key
.length
> 0) {
1456 data_blob_clear_free(&req
->first_key
);
1459 req
->current_idx
= 1;
1462 * Re-arrange the in.vectors to remove what
1465 memmove(&req
->in
.vector
[1],
1466 &req
->in
.vector
[idx
],
1467 sizeof(req
->in
.vector
[0])*(req
->in
.vector_count
- idx
));
1468 req
->in
.vector_count
= 1 + (req
->in
.vector_count
- idx
);
1470 /* Re-arrange the out.vectors to match. */
1471 memmove(&req
->out
.vector
[1],
1472 &req
->out
.vector
[idx
],
1473 sizeof(req
->out
.vector
[0])*(req
->out
.vector_count
- idx
));
1474 req
->out
.vector_count
= 1 + (req
->out
.vector_count
- idx
);
1476 if (req
->in
.vector_count
== 1 + SMBD_SMB2_NUM_IOV_PER_REQ
) {
1478 * We only have one remaining request as
1479 * we've processed everything else.
1480 * This is no longer a compound request.
1482 req
->compound_related
= false;
1483 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1484 flags
= (IVAL(outhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
1485 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
);
1488 if (req
->last_key
.length
> 0) {
1489 data_blob_clear_free(&req
->last_key
);
1493 * smbd_smb2_request_pending_timer() just send a packet
1494 * to the client and doesn't need any impersonation.
1495 * So we use req->xconn->client->raw_ev_ctx instead
1496 * of req->ev_ctx here.
1498 defer_endtime
= timeval_current_ofs_usec(defer_time
);
1499 req
->async_te
= tevent_add_timer(req
->xconn
->client
->raw_ev_ctx
,
1501 smbd_smb2_request_pending_timer
,
1503 if (req
->async_te
== NULL
) {
1504 return NT_STATUS_NO_MEMORY
;
1507 return NT_STATUS_OK
;
1510 static DATA_BLOB
smbd_smb2_signing_key(struct smbXsrv_session
*session
,
1511 struct smbXsrv_connection
*xconn
)
1513 struct smbXsrv_channel_global0
*c
= NULL
;
1515 DATA_BLOB key
= data_blob_null
;
1517 status
= smbXsrv_session_find_channel(session
, xconn
, &c
);
1518 if (NT_STATUS_IS_OK(status
)) {
1519 key
= c
->signing_key
;
1522 if (key
.length
== 0) {
1523 key
= session
->global
->signing_key
;
1529 static NTSTATUS
smb2_get_new_nonce(struct smbXsrv_session
*session
,
1530 uint64_t *new_nonce_high
,
1531 uint64_t *new_nonce_low
)
1533 uint64_t nonce_high
;
1536 session
->nonce_low
+= 1;
1537 if (session
->nonce_low
== 0) {
1538 session
->nonce_low
+= 1;
1539 session
->nonce_high
+= 1;
1543 * CCM and GCM algorithms must never have their
1544 * nonce wrap, or the security of the whole
1545 * communication and the keys is destroyed.
1546 * We must drop the connection once we have
1547 * transfered too much data.
1549 * NOTE: We assume nonces greater than 8 bytes.
1551 if (session
->nonce_high
>= session
->nonce_high_max
) {
1552 return NT_STATUS_ENCRYPTION_FAILED
;
1555 nonce_high
= session
->nonce_high_random
;
1556 nonce_high
+= session
->nonce_high
;
1557 nonce_low
= session
->nonce_low
;
1559 *new_nonce_high
= nonce_high
;
1560 *new_nonce_low
= nonce_low
;
1561 return NT_STATUS_OK
;
1564 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
1565 struct tevent_timer
*te
,
1566 struct timeval current_time
,
1569 struct smbd_smb2_request
*req
=
1570 talloc_get_type_abort(private_data
,
1571 struct smbd_smb2_request
);
1572 struct smbXsrv_connection
*xconn
= req
->xconn
;
1573 struct smbd_smb2_request_pending_state
*state
= NULL
;
1574 uint8_t *outhdr
= NULL
;
1575 const uint8_t *inhdr
= NULL
;
1578 uint8_t *hdr
= NULL
;
1579 uint8_t *body
= NULL
;
1580 uint8_t *dyn
= NULL
;
1582 uint64_t session_id
= 0;
1583 uint64_t message_id
= 0;
1584 uint64_t nonce_high
= 0;
1585 uint64_t nonce_low
= 0;
1586 uint64_t async_id
= 0;
1590 TALLOC_FREE(req
->async_te
);
1592 /* Ensure our final reply matches the interim one. */
1593 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1594 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1595 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1596 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1597 session_id
= BVAL(outhdr
, SMB2_HDR_SESSION_ID
);
1599 async_id
= message_id
; /* keep it simple for now... */
1601 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1602 SBVAL(outhdr
, SMB2_HDR_ASYNC_ID
, async_id
);
1604 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1606 smb2_opcode_name(SVAL(inhdr
, SMB2_HDR_OPCODE
)),
1607 (unsigned long long)async_id
));
1610 * What we send is identical to a smbd_smb2_request_error
1611 * packet with an error status of STATUS_PENDING. Make use
1612 * of this fact sometime when refactoring. JRA.
1615 state
= talloc_zero(req
->xconn
, struct smbd_smb2_request_pending_state
);
1616 if (state
== NULL
) {
1617 smbd_server_connection_terminate(xconn
,
1618 nt_errstr(NT_STATUS_NO_MEMORY
));
1622 tf
= state
->buf
+ NBT_HDR_SIZE
;
1623 tf_len
= SMB2_TF_HDR_SIZE
;
1625 hdr
= tf
+ SMB2_TF_HDR_SIZE
;
1626 body
= hdr
+ SMB2_HDR_BODY
;
1629 if (req
->do_encryption
) {
1630 status
= smb2_get_new_nonce(req
->session
,
1633 if (!NT_STATUS_IS_OK(status
)) {
1634 smbd_server_connection_terminate(xconn
,
1640 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
1641 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
1642 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
1643 SBVAL(tf
, SMB2_TF_SESSION_ID
, session_id
);
1645 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
1646 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1647 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1648 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
1649 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(outhdr
, SMB2_HDR_OPCODE
));
1651 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
);
1652 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1653 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
1654 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
1655 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
1656 BVAL(outhdr
, SMB2_HDR_SESSION_ID
));
1657 memcpy(hdr
+SMB2_HDR_SIGNATURE
,
1658 outhdr
+SMB2_HDR_SIGNATURE
, 16);
1660 SSVAL(body
, 0x00, 0x08 + 1);
1662 SCVAL(body
, 0x02, 0);
1663 SCVAL(body
, 0x03, 0);
1664 SIVAL(body
, 0x04, 0);
1665 /* Match W2K8R2... */
1666 SCVAL(dyn
, 0x00, 0x21);
1668 state
->vector
[0].iov_base
= (void *)state
->buf
;
1669 state
->vector
[0].iov_len
= NBT_HDR_SIZE
;
1671 if (req
->do_encryption
) {
1672 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= tf
;
1673 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= tf_len
;
1675 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
1676 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
1679 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
1680 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
1682 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
1683 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_len
= 8;
1685 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
1686 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_len
= 1;
1688 ok
= smb2_setup_nbt_length(state
->vector
,
1689 1 + SMBD_SMB2_NUM_IOV_PER_REQ
);
1691 smbd_server_connection_terminate(
1692 xconn
, nt_errstr(NT_STATUS_INTERNAL_ERROR
));
1696 /* Ensure we correctly go through crediting. Grant
1697 the credits now, and zero credits on the final
1699 smb2_set_operation_credit(req
->xconn
,
1700 SMBD_SMB2_IN_HDR_IOV(req
),
1701 &state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
]);
1703 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1708 for (i
= 0; i
< ARRAY_SIZE(state
->vector
); i
++) {
1709 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1711 (unsigned int)ARRAY_SIZE(state
->vector
),
1712 (unsigned int)state
->vector
[i
].iov_len
);
1716 if (req
->do_encryption
) {
1717 struct smbXsrv_session
*x
= req
->session
;
1718 DATA_BLOB encryption_key
= x
->global
->encryption_key
;
1720 status
= smb2_signing_encrypt_pdu(encryption_key
,
1721 xconn
->smb2
.server
.cipher
,
1722 &state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
],
1723 SMBD_SMB2_NUM_IOV_PER_REQ
);
1724 if (!NT_STATUS_IS_OK(status
)) {
1725 smbd_server_connection_terminate(xconn
,
1729 } else if (req
->do_signing
) {
1730 struct smbXsrv_session
*x
= req
->session
;
1731 DATA_BLOB signing_key
= smbd_smb2_signing_key(x
, xconn
);
1733 status
= smb2_signing_sign_pdu(signing_key
,
1735 &state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
],
1736 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
1737 if (!NT_STATUS_IS_OK(status
)) {
1738 smbd_server_connection_terminate(xconn
,
1744 state
->queue_entry
.mem_ctx
= state
;
1745 state
->queue_entry
.vector
= state
->vector
;
1746 state
->queue_entry
.count
= ARRAY_SIZE(state
->vector
);
1747 DLIST_ADD_END(xconn
->smb2
.send_queue
, &state
->queue_entry
);
1748 xconn
->smb2
.send_queue_len
++;
1750 status
= smbd_smb2_flush_send_queue(xconn
);
1751 if (!NT_STATUS_IS_OK(status
)) {
1752 smbd_server_connection_terminate(xconn
,
1758 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
1760 struct smbXsrv_connection
*xconn
= req
->xconn
;
1761 struct smbd_smb2_request
*cur
;
1762 const uint8_t *inhdr
;
1764 uint64_t search_message_id
;
1765 uint64_t search_async_id
;
1768 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1770 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1771 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1772 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
1775 * We don't need the request anymore cancel requests never
1778 * We defer the TALLOC_FREE(req) to the caller.
1780 DLIST_REMOVE(xconn
->smb2
.requests
, req
);
1782 for (cur
= xconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
1783 const uint8_t *outhdr
;
1784 uint64_t message_id
;
1787 if (cur
->compound_related
) {
1789 * Never cancel anything in a compound request.
1790 * Way too hard to deal with the result.
1795 outhdr
= SMBD_SMB2_OUT_HDR_PTR(cur
);
1797 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1798 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
1800 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1801 if (search_async_id
== async_id
) {
1802 found_id
= async_id
;
1806 if (search_message_id
== message_id
) {
1807 found_id
= message_id
;
1813 if (cur
&& cur
->subreq
) {
1814 inhdr
= SMBD_SMB2_IN_HDR_PTR(cur
);
1815 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1816 "cancel opcode[%s] mid %llu\n",
1817 smb2_opcode_name(SVAL(inhdr
, SMB2_HDR_OPCODE
)),
1818 (unsigned long long)found_id
));
1819 tevent_req_cancel(cur
->subreq
);
1822 return NT_STATUS_OK
;
1825 /*************************************************************
1826 Ensure an incoming tid is a valid one for us to access.
1827 Change to the associated uid credentials and chdir to the
1828 valid tid directory.
1829 *************************************************************/
1831 static NTSTATUS
smbd_smb2_request_check_tcon(struct smbd_smb2_request
*req
)
1833 const uint8_t *inhdr
;
1836 struct smbXsrv_tcon
*tcon
;
1838 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1842 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1844 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1845 in_tid
= IVAL(inhdr
, SMB2_HDR_TID
);
1847 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1848 in_tid
= req
->last_tid
;
1853 status
= smb2srv_tcon_lookup(req
->session
,
1854 in_tid
, now
, &tcon
);
1855 if (!NT_STATUS_IS_OK(status
)) {
1859 if (!change_to_user(tcon
->compat
, req
->session
->compat
->vuid
)) {
1860 return NT_STATUS_ACCESS_DENIED
;
1864 req
->last_tid
= in_tid
;
1866 return NT_STATUS_OK
;
1869 /*************************************************************
1870 Ensure an incoming session_id is a valid one for us to access.
1871 *************************************************************/
1873 static NTSTATUS
smbd_smb2_request_check_session(struct smbd_smb2_request
*req
)
1875 const uint8_t *inhdr
;
1878 uint64_t in_session_id
;
1879 struct smbXsrv_session
*session
= NULL
;
1880 struct auth_session_info
*session_info
;
1882 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1884 req
->session
= NULL
;
1887 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1889 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1890 in_opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1891 in_session_id
= BVAL(inhdr
, SMB2_HDR_SESSION_ID
);
1893 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1894 in_session_id
= req
->last_session_id
;
1897 req
->last_session_id
= 0;
1899 /* look an existing session up */
1900 switch (in_opcode
) {
1901 case SMB2_OP_SESSSETUP
:
1903 * For a session bind request, we don't have the
1904 * channel set up at this point yet, so we defer
1905 * the verification that the connection belongs
1906 * to the session to the session setup code, which
1907 * can look at the session binding flags.
1909 status
= smb2srv_session_lookup_client(req
->xconn
->client
,
1914 status
= smb2srv_session_lookup_conn(req
->xconn
,
1920 req
->session
= session
;
1921 req
->last_session_id
= in_session_id
;
1923 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
1924 switch (in_opcode
) {
1925 case SMB2_OP_SESSSETUP
:
1926 status
= NT_STATUS_OK
;
1928 case SMB2_OP_LOGOFF
:
1931 case SMB2_OP_CANCEL
:
1932 case SMB2_OP_KEEPALIVE
:
1934 * [MS-SMB2] 3.3.5.2.9 Verifying the Session
1935 * specifies that LOGOFF, CLOSE and (UN)LOCK
1936 * should always be processed even on expired sessions.
1938 * Also see the logic in
1939 * smbd_smb2_request_process_lock().
1941 * The smb2.session.expire2 test shows that
1942 * CANCEL and KEEPALIVE/ECHO should also
1945 status
= NT_STATUS_OK
;
1951 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1952 switch (in_opcode
) {
1954 case SMB2_OP_CREATE
:
1955 case SMB2_OP_GETINFO
:
1956 case SMB2_OP_SETINFO
:
1957 return NT_STATUS_INVALID_HANDLE
;
1960 * Notice the check for
1961 * (session_info == NULL)
1964 status
= NT_STATUS_OK
;
1968 if (!NT_STATUS_IS_OK(status
)) {
1972 session_info
= session
->global
->auth_session_info
;
1973 if (session_info
== NULL
) {
1974 return NT_STATUS_INVALID_HANDLE
;
1977 return NT_STATUS_OK
;
1980 NTSTATUS
smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request
*req
,
1981 uint32_t data_length
)
1983 struct smbXsrv_connection
*xconn
= req
->xconn
;
1984 uint16_t needed_charge
;
1985 uint16_t credit_charge
= 1;
1986 const uint8_t *inhdr
;
1988 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1990 if (xconn
->smb2
.credits
.multicredit
) {
1991 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
1992 credit_charge
= MAX(credit_charge
, 1);
1995 needed_charge
= (data_length
- 1)/ 65536 + 1;
1997 DBGC_DEBUG(DBGC_SMB2_CREDITS
,
1998 "mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1999 (unsigned long long) BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
),
2000 credit_charge
, needed_charge
);
2002 if (needed_charge
> credit_charge
) {
2003 DBGC_WARNING(DBGC_SMB2_CREDITS
,
2004 "CreditCharge too low, given %d, needed %d\n",
2005 credit_charge
, needed_charge
);
2006 return NT_STATUS_INVALID_PARAMETER
;
2009 return NT_STATUS_OK
;
2012 NTSTATUS
smbd_smb2_request_verify_sizes(struct smbd_smb2_request
*req
,
2013 size_t expected_body_size
)
2015 struct iovec
*inhdr_v
;
2016 const uint8_t *inhdr
;
2018 const uint8_t *inbody
;
2020 size_t min_dyn_size
= expected_body_size
& 0x00000001;
2021 int max_idx
= req
->in
.vector_count
- SMBD_SMB2_NUM_IOV_PER_REQ
;
2024 * The following should be checked already.
2026 if (req
->in
.vector_count
< SMBD_SMB2_NUM_IOV_PER_REQ
) {
2027 return NT_STATUS_INTERNAL_ERROR
;
2029 if (req
->current_idx
> max_idx
) {
2030 return NT_STATUS_INTERNAL_ERROR
;
2033 inhdr_v
= SMBD_SMB2_IN_HDR_IOV(req
);
2034 if (inhdr_v
->iov_len
!= SMB2_HDR_BODY
) {
2035 return NT_STATUS_INTERNAL_ERROR
;
2037 if (SMBD_SMB2_IN_BODY_LEN(req
) < 2) {
2038 return NT_STATUS_INTERNAL_ERROR
;
2041 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
2042 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
2046 case SMB2_OP_GETINFO
:
2050 if (req
->smb1req
!= NULL
&& req
->smb1req
->unread_bytes
> 0) {
2051 if (req
->smb1req
->unread_bytes
< min_dyn_size
) {
2052 return NT_STATUS_INVALID_PARAMETER
;
2061 * Now check the expected body size,
2062 * where the last byte might be in the
2065 if (SMBD_SMB2_IN_BODY_LEN(req
) != (expected_body_size
& 0xFFFFFFFE)) {
2066 return NT_STATUS_INVALID_PARAMETER
;
2068 if (SMBD_SMB2_IN_DYN_LEN(req
) < min_dyn_size
) {
2069 return NT_STATUS_INVALID_PARAMETER
;
2072 inbody
= SMBD_SMB2_IN_BODY_PTR(req
);
2074 body_size
= SVAL(inbody
, 0x00);
2075 if (body_size
!= expected_body_size
) {
2076 return NT_STATUS_INVALID_PARAMETER
;
2079 return NT_STATUS_OK
;
2082 bool smbXsrv_is_encrypted(uint8_t encryption_flags
)
2084 return (!(encryption_flags
& SMBXSRV_PROCESSED_UNENCRYPTED_PACKET
)
2086 (encryption_flags
& (SMBXSRV_PROCESSED_ENCRYPTED_PACKET
|
2087 SMBXSRV_ENCRYPTION_DESIRED
|
2088 SMBXSRV_ENCRYPTION_REQUIRED
)));
2091 bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags
)
2093 return ((encryption_flags
& SMBXSRV_PROCESSED_ENCRYPTED_PACKET
) &&
2094 (encryption_flags
& SMBXSRV_PROCESSED_UNENCRYPTED_PACKET
));
2097 /* Set a flag if not already set, return true if set */
2098 bool smbXsrv_set_crypto_flag(uint8_t *flags
, uint8_t flag
)
2100 if ((flag
== 0) || (*flags
& flag
)) {
2109 * Update encryption state tracking flags, this can be used to
2110 * determine whether whether the session or tcon is "encrypted".
2112 static void smb2srv_update_crypto_flags(struct smbd_smb2_request
*req
,
2114 bool *update_session_globalp
,
2115 bool *update_tcon_globalp
)
2117 /* Default: assume unecrypted and unsigned */
2118 struct smbXsrv_session
*session
= req
->session
;
2119 struct smbXsrv_tcon
*tcon
= req
->tcon
;
2120 uint8_t encrypt_flag
= SMBXSRV_PROCESSED_UNENCRYPTED_PACKET
;
2121 uint8_t sign_flag
= SMBXSRV_PROCESSED_UNSIGNED_PACKET
;
2122 bool update_session
= false;
2123 bool update_tcon
= false;
2125 if (req
->was_encrypted
&& req
->do_encryption
) {
2126 encrypt_flag
= SMBXSRV_PROCESSED_ENCRYPTED_PACKET
;
2127 sign_flag
= SMBXSRV_PROCESSED_SIGNED_PACKET
;
2129 /* Unencrypted packet, can be signed */
2130 if (req
->do_signing
) {
2131 sign_flag
= SMBXSRV_PROCESSED_SIGNED_PACKET
;
2132 } else if (opcode
== SMB2_OP_CANCEL
) {
2133 /* Cancel requests are allowed to skip signing */
2134 sign_flag
&= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET
;
2138 update_session
|= smbXsrv_set_crypto_flag(
2139 &session
->global
->encryption_flags
, encrypt_flag
);
2140 update_session
|= smbXsrv_set_crypto_flag(
2141 &session
->global
->signing_flags
, sign_flag
);
2144 update_tcon
|= smbXsrv_set_crypto_flag(
2145 &tcon
->global
->encryption_flags
, encrypt_flag
);
2146 update_tcon
|= smbXsrv_set_crypto_flag(
2147 &tcon
->global
->signing_flags
, sign_flag
);
2150 *update_session_globalp
= update_session
;
2151 *update_tcon_globalp
= update_tcon
;
2155 bool smbXsrv_is_signed(uint8_t signing_flags
)
2158 * Signing is always enabled, so unless we got an unsigned
2159 * packet and at least one signed packet that was not
2160 * encrypted, the session or tcon is "signed".
2162 return (!(signing_flags
& SMBXSRV_PROCESSED_UNSIGNED_PACKET
) &&
2163 (signing_flags
& SMBXSRV_PROCESSED_SIGNED_PACKET
));
2166 bool smbXsrv_is_partially_signed(uint8_t signing_flags
)
2168 return ((signing_flags
& SMBXSRV_PROCESSED_UNSIGNED_PACKET
) &&
2169 (signing_flags
& SMBXSRV_PROCESSED_SIGNED_PACKET
));
2172 static NTSTATUS
smbd_smb2_request_dispatch_update_counts(
2173 struct smbd_smb2_request
*req
,
2176 struct smbXsrv_connection
*xconn
= req
->xconn
;
2177 const uint8_t *inhdr
;
2178 uint16_t channel_sequence
;
2179 uint8_t generation_wrap
= 0;
2182 struct smbXsrv_open
*op
;
2183 bool update_open
= false;
2184 NTSTATUS status
= NT_STATUS_OK
;
2186 SMB_ASSERT(!req
->request_counters_updated
);
2188 if (xconn
->protocol
< PROTOCOL_SMB2_22
) {
2189 return NT_STATUS_OK
;
2192 if (req
->compat_chain_fsp
== NULL
) {
2193 return NT_STATUS_OK
;
2196 op
= req
->compat_chain_fsp
->op
;
2198 return NT_STATUS_OK
;
2201 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
2202 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
2203 channel_sequence
= SVAL(inhdr
, SMB2_HDR_CHANNEL_SEQUENCE
);
2205 cmp
= channel_sequence
- op
->global
->channel_sequence
;
2208 * csn wrap. We need to watch out for long-running
2209 * requests that are still sitting on a previously
2210 * used csn. SMB2_OP_NOTIFY can take VERY long.
2212 generation_wrap
+= 1;
2215 if (abs(cmp
) > INT16_MAX
) {
2217 * [MS-SMB2] 3.3.5.2.10 - Verifying the Channel Sequence Number:
2219 * If the channel sequence number of the request and the one
2220 * known to the server are not equal, the channel sequence
2221 * number and outstanding request counts are only updated
2222 * "... if the unsigned difference using 16-bit arithmetic
2223 * between ChannelSequence and Open.ChannelSequence is less than
2224 * or equal to 0x7FFF ...".
2225 * Otherwise, an error is returned for the modifying
2226 * calls write, set_info, and ioctl.
2228 * There are currently two issues with the description:
2230 * * For the other calls, the document seems to imply
2231 * that processing continues without adapting the
2232 * counters (if the sequence numbers are not equal).
2234 * TODO: This needs clarification!
2236 * * Also, the behaviour if the difference is larger
2237 * than 0x7FFF is not clear. The document seems to
2238 * imply that if such a difference is reached,
2239 * the server starts to ignore the counters or
2240 * in the case of the modifying calls, return errors.
2242 * TODO: This needs clarification!
2244 * At this point Samba tries to be a little more
2245 * clever than the description in the MS-SMB2 document
2246 * by heuristically detecting and properly treating
2247 * a 16 bit overflow of the client-submitted sequence
2250 * If the stored channel sequence number is more than
2251 * 0x7FFF larger than the one from the request, then
2252 * the client-provided sequence number has likely
2253 * overflown. We treat this case as valid instead
2256 * The MS-SMB2 behaviour would be setting cmp = -1.
2261 if (flags
& SMB2_HDR_FLAG_REPLAY_OPERATION
) {
2262 if (cmp
== 0 && op
->pre_request_count
== 0) {
2263 op
->request_count
+= 1;
2264 req
->request_counters_updated
= true;
2265 } else if (cmp
> 0 && op
->pre_request_count
== 0) {
2266 op
->pre_request_count
+= op
->request_count
;
2267 op
->request_count
= 1;
2268 op
->global
->channel_sequence
= channel_sequence
;
2269 op
->global
->channel_generation
+= generation_wrap
;
2271 req
->request_counters_updated
= true;
2272 } else if (modify_call
) {
2273 return NT_STATUS_FILE_NOT_AVAILABLE
;
2277 op
->request_count
+= 1;
2278 req
->request_counters_updated
= true;
2279 } else if (cmp
> 0) {
2280 op
->pre_request_count
+= op
->request_count
;
2281 op
->request_count
= 1;
2282 op
->global
->channel_sequence
= channel_sequence
;
2283 op
->global
->channel_generation
+= generation_wrap
;
2285 req
->request_counters_updated
= true;
2286 } else if (modify_call
) {
2287 return NT_STATUS_FILE_NOT_AVAILABLE
;
2290 req
->channel_generation
= op
->global
->channel_generation
;
2293 status
= smbXsrv_open_update(op
);
2299 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
2301 struct smbXsrv_connection
*xconn
= req
->xconn
;
2302 const struct smbd_smb2_dispatch_table
*call
= NULL
;
2303 const struct iovec
*intf_v
= SMBD_SMB2_IN_TF_IOV(req
);
2304 const uint8_t *inhdr
;
2309 NTSTATUS session_status
;
2310 uint32_t allowed_flags
;
2311 NTSTATUS return_value
;
2312 struct smbXsrv_session
*x
= NULL
;
2313 bool signing_required
= false;
2314 bool encryption_desired
= false;
2315 bool encryption_required
= false;
2317 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
2319 DO_PROFILE_INC(request
);
2321 SMB_ASSERT(!req
->request_counters_updated
);
2323 /* TODO: verify more things */
2325 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
2326 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
2327 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
2328 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
2329 smb2_opcode_name(opcode
),
2330 (unsigned long long)mid
));
2332 if (xconn
->protocol
>= PROTOCOL_SMB2_02
) {
2334 * once the protocol is negotiated
2335 * SMB2_OP_NEGPROT is not allowed anymore
2337 if (opcode
== SMB2_OP_NEGPROT
) {
2338 /* drop the connection */
2339 return NT_STATUS_INVALID_PARAMETER
;
2343 * if the protocol is not negotiated yet
2344 * only SMB2_OP_NEGPROT is allowed.
2346 if (opcode
!= SMB2_OP_NEGPROT
) {
2347 /* drop the connection */
2348 return NT_STATUS_INVALID_PARAMETER
;
2353 * Check if the client provided a valid session id.
2355 * As some command don't require a valid session id
2356 * we defer the check of the session_status
2358 session_status
= smbd_smb2_request_check_session(req
);
2361 signing_required
= x
->global
->signing_flags
& SMBXSRV_SIGNING_REQUIRED
;
2362 encryption_desired
= x
->global
->encryption_flags
& SMBXSRV_ENCRYPTION_DESIRED
;
2363 encryption_required
= x
->global
->encryption_flags
& SMBXSRV_ENCRYPTION_REQUIRED
;
2366 req
->async_internal
= false;
2367 req
->do_signing
= false;
2368 if (opcode
!= SMB2_OP_SESSSETUP
) {
2369 req
->do_encryption
= encryption_desired
;
2371 req
->do_encryption
= false;
2373 req
->was_encrypted
= false;
2374 if (intf_v
->iov_len
== SMB2_TF_HDR_SIZE
) {
2375 const uint8_t *intf
= SMBD_SMB2_IN_TF_PTR(req
);
2376 uint64_t tf_session_id
= BVAL(intf
, SMB2_TF_SESSION_ID
);
2378 if (x
!= NULL
&& x
->global
->session_wire_id
!= tf_session_id
) {
2379 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2380 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
2381 (unsigned long long)x
->global
->session_wire_id
,
2382 (unsigned long long)tf_session_id
));
2384 * TODO: windows allows this...
2385 * should we drop the connection?
2387 * For now we just return ACCESS_DENIED
2388 * (Windows clients never trigger this)
2389 * and wait for an update of [MS-SMB2].
2391 return smbd_smb2_request_error(req
,
2392 NT_STATUS_ACCESS_DENIED
);
2395 req
->was_encrypted
= true;
2396 req
->do_encryption
= true;
2399 if (encryption_required
&& !req
->was_encrypted
) {
2400 req
->do_encryption
= true;
2401 return smbd_smb2_request_error(req
,
2402 NT_STATUS_ACCESS_DENIED
);
2405 call
= smbd_smb2_call(opcode
);
2407 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2410 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
2411 SMB2_HDR_FLAG_SIGNED
|
2413 if (xconn
->protocol
>= PROTOCOL_SMB3_11
) {
2414 allowed_flags
|= SMB2_HDR_FLAG_PRIORITY_MASK
;
2416 if (opcode
== SMB2_OP_NEGPROT
) {
2417 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11
) {
2418 allowed_flags
|= SMB2_HDR_FLAG_PRIORITY_MASK
;
2421 if (opcode
== SMB2_OP_CANCEL
) {
2422 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
2424 if (xconn
->protocol
>= PROTOCOL_SMB2_22
) {
2425 allowed_flags
|= SMB2_HDR_FLAG_REPLAY_OPERATION
;
2427 if ((flags
& ~allowed_flags
) != 0) {
2428 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2431 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
2433 * This check is mostly for giving the correct error code
2434 * for compounded requests.
2436 if (!NT_STATUS_IS_OK(session_status
)) {
2437 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2440 req
->compat_chain_fsp
= NULL
;
2443 if (req
->was_encrypted
) {
2444 signing_required
= false;
2445 } else if (signing_required
|| (flags
& SMB2_HDR_FLAG_SIGNED
)) {
2446 DATA_BLOB signing_key
= data_blob_null
;
2450 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2451 * If the SMB2 header of the SMB2 NEGOTIATE
2452 * request has the SMB2_FLAGS_SIGNED bit set in the
2453 * Flags field, the server MUST fail the request
2454 * with STATUS_INVALID_PARAMETER.
2456 * Microsoft test tool checks this.
2459 if ((opcode
== SMB2_OP_NEGPROT
) &&
2460 (flags
& SMB2_HDR_FLAG_SIGNED
)) {
2461 status
= NT_STATUS_INVALID_PARAMETER
;
2463 status
= NT_STATUS_USER_SESSION_DELETED
;
2465 return smbd_smb2_request_error(req
, status
);
2468 signing_key
= smbd_smb2_signing_key(x
, xconn
);
2471 * If we have a signing key, we should
2474 if (signing_key
.length
> 0) {
2475 req
->do_signing
= true;
2478 status
= smb2_signing_check_pdu(signing_key
,
2480 SMBD_SMB2_IN_HDR_IOV(req
),
2481 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2482 if (!NT_STATUS_IS_OK(status
)) {
2483 return smbd_smb2_request_error(req
, status
);
2487 * Now that we know the request was correctly signed
2488 * we have to sign the response too.
2490 req
->do_signing
= true;
2492 if (!NT_STATUS_IS_OK(session_status
)) {
2493 return smbd_smb2_request_error(req
, session_status
);
2495 } else if (opcode
== SMB2_OP_CANCEL
) {
2496 /* Cancel requests are allowed to skip the signing */
2497 } else if (signing_required
) {
2499 * If signing is required we try to sign
2500 * a possible error response
2502 req
->do_signing
= true;
2503 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
2506 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
2507 req
->compound_related
= true;
2510 if (call
->need_session
) {
2511 if (!NT_STATUS_IS_OK(session_status
)) {
2512 return smbd_smb2_request_error(req
, session_status
);
2516 if (call
->need_tcon
) {
2517 SMB_ASSERT(call
->need_session
);
2520 * This call needs to be run as user.
2522 * smbd_smb2_request_check_tcon()
2523 * calls change_to_user() on success.
2524 * Which implies set_current_user_info()
2525 * and chdir_current_service().
2527 status
= smbd_smb2_request_check_tcon(req
);
2528 if (!NT_STATUS_IS_OK(status
)) {
2529 return smbd_smb2_request_error(req
, status
);
2531 if (req
->tcon
->global
->encryption_flags
& SMBXSRV_ENCRYPTION_DESIRED
) {
2532 encryption_desired
= true;
2534 if (req
->tcon
->global
->encryption_flags
& SMBXSRV_ENCRYPTION_REQUIRED
) {
2535 encryption_required
= true;
2537 if (encryption_required
&& !req
->was_encrypted
) {
2538 req
->do_encryption
= true;
2539 return smbd_smb2_request_error(req
,
2540 NT_STATUS_ACCESS_DENIED
);
2541 } else if (encryption_desired
) {
2542 req
->do_encryption
= true;
2544 } else if (call
->need_session
) {
2545 struct auth_session_info
*session_info
= NULL
;
2548 * Unless we also have need_tcon (see above),
2549 * we still need to call set_current_user_info().
2552 session_info
= req
->session
->global
->auth_session_info
;
2553 if (session_info
== NULL
) {
2554 return NT_STATUS_INVALID_HANDLE
;
2557 set_current_user_info(session_info
->unix_info
->sanitized_username
,
2558 session_info
->unix_info
->unix_name
,
2559 session_info
->info
->domain_name
);
2563 bool update_session_global
= false;
2564 bool update_tcon_global
= false;
2566 smb2srv_update_crypto_flags(req
, opcode
,
2567 &update_session_global
,
2568 &update_tcon_global
);
2570 if (update_session_global
) {
2571 status
= smbXsrv_session_update(x
);
2572 if (!NT_STATUS_IS_OK(status
)) {
2573 return smbd_smb2_request_error(req
, status
);
2576 if (update_tcon_global
) {
2577 status
= smbXsrv_tcon_update(req
->tcon
);
2578 if (!NT_STATUS_IS_OK(status
)) {
2579 return smbd_smb2_request_error(req
, status
);
2584 if (call
->fileid_ofs
!= 0) {
2585 size_t needed
= call
->fileid_ofs
+ 16;
2586 const uint8_t *body
= SMBD_SMB2_IN_BODY_PTR(req
);
2587 size_t body_size
= SMBD_SMB2_IN_BODY_LEN(req
);
2588 uint64_t file_id_persistent
;
2589 uint64_t file_id_volatile
;
2590 struct files_struct
*fsp
;
2592 SMB_ASSERT(call
->need_tcon
);
2594 if (needed
> body_size
) {
2595 return smbd_smb2_request_error(req
,
2596 NT_STATUS_INVALID_PARAMETER
);
2599 file_id_persistent
= BVAL(body
, call
->fileid_ofs
+ 0);
2600 file_id_volatile
= BVAL(body
, call
->fileid_ofs
+ 8);
2602 fsp
= file_fsp_smb2(req
, file_id_persistent
, file_id_volatile
);
2604 if (!call
->allow_invalid_fileid
) {
2605 return smbd_smb2_request_error(req
,
2606 NT_STATUS_FILE_CLOSED
);
2609 if (file_id_persistent
!= UINT64_MAX
) {
2610 return smbd_smb2_request_error(req
,
2611 NT_STATUS_FILE_CLOSED
);
2613 if (file_id_volatile
!= UINT64_MAX
) {
2614 return smbd_smb2_request_error(req
,
2615 NT_STATUS_FILE_CLOSED
);
2620 status
= smbd_smb2_request_dispatch_update_counts(req
, call
->modify
);
2621 if (!NT_STATUS_IS_OK(status
)) {
2622 return smbd_smb2_request_error(req
, status
);
2625 if (call
->as_root
) {
2626 SMB_ASSERT(call
->fileid_ofs
== 0);
2627 /* This call needs to be run as root */
2628 change_to_root_user();
2629 req
->ev_ctx
= req
->sconn
->root_ev_ctx
;
2631 SMB_ASSERT(call
->need_tcon
);
2632 req
->ev_ctx
= req
->tcon
->compat
->user_ev_ctx
;
2635 #define _INBYTES(_r) \
2636 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
2639 case SMB2_OP_NEGPROT
:
2640 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot
, profile_p
,
2641 req
->profile
, _INBYTES(req
));
2642 return_value
= smbd_smb2_request_process_negprot(req
);
2645 case SMB2_OP_SESSSETUP
:
2646 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup
, profile_p
,
2647 req
->profile
, _INBYTES(req
));
2648 return_value
= smbd_smb2_request_process_sesssetup(req
);
2651 case SMB2_OP_LOGOFF
:
2652 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff
, profile_p
,
2653 req
->profile
, _INBYTES(req
));
2654 return_value
= smbd_smb2_request_process_logoff(req
);
2658 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon
, profile_p
,
2659 req
->profile
, _INBYTES(req
));
2660 return_value
= smbd_smb2_request_process_tcon(req
);
2664 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis
, profile_p
,
2665 req
->profile
, _INBYTES(req
));
2666 return_value
= smbd_smb2_request_process_tdis(req
);
2669 case SMB2_OP_CREATE
:
2670 if (req
->subreq
== NULL
) {
2671 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create
, profile_p
,
2672 req
->profile
, _INBYTES(req
));
2674 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req
->profile
);
2676 return_value
= smbd_smb2_request_process_create(req
);
2680 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close
, profile_p
,
2681 req
->profile
, _INBYTES(req
));
2682 return_value
= smbd_smb2_request_process_close(req
);
2686 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush
, profile_p
,
2687 req
->profile
, _INBYTES(req
));
2688 return_value
= smbd_smb2_request_process_flush(req
);
2692 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read
, profile_p
,
2693 req
->profile
, _INBYTES(req
));
2694 return_value
= smbd_smb2_request_process_read(req
);
2698 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write
, profile_p
,
2699 req
->profile
, _INBYTES(req
));
2700 return_value
= smbd_smb2_request_process_write(req
);
2704 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock
, profile_p
,
2705 req
->profile
, _INBYTES(req
));
2706 return_value
= smbd_smb2_request_process_lock(req
);
2710 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl
, profile_p
,
2711 req
->profile
, _INBYTES(req
));
2712 return_value
= smbd_smb2_request_process_ioctl(req
);
2715 case SMB2_OP_CANCEL
:
2716 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel
, profile_p
,
2717 req
->profile
, _INBYTES(req
));
2718 return_value
= smbd_smb2_request_process_cancel(req
);
2719 SMBPROFILE_IOBYTES_ASYNC_END(req
->profile
, 0);
2722 * We don't need the request anymore cancel requests never
2725 * smbd_smb2_request_process_cancel() already called
2726 * DLIST_REMOVE(xconn->smb2.requests, req);
2732 case SMB2_OP_KEEPALIVE
:
2733 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive
, profile_p
,
2734 req
->profile
, _INBYTES(req
));
2735 return_value
= smbd_smb2_request_process_keepalive(req
);
2738 case SMB2_OP_QUERY_DIRECTORY
:
2739 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find
, profile_p
,
2740 req
->profile
, _INBYTES(req
));
2741 return_value
= smbd_smb2_request_process_query_directory(req
);
2744 case SMB2_OP_NOTIFY
:
2745 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify
, profile_p
,
2746 req
->profile
, _INBYTES(req
));
2747 return_value
= smbd_smb2_request_process_notify(req
);
2750 case SMB2_OP_GETINFO
:
2751 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo
, profile_p
,
2752 req
->profile
, _INBYTES(req
));
2753 return_value
= smbd_smb2_request_process_getinfo(req
);
2756 case SMB2_OP_SETINFO
:
2757 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo
, profile_p
,
2758 req
->profile
, _INBYTES(req
));
2759 return_value
= smbd_smb2_request_process_setinfo(req
);
2763 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break
, profile_p
,
2764 req
->profile
, _INBYTES(req
));
2765 return_value
= smbd_smb2_request_process_break(req
);
2769 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2772 return return_value
;
2775 static void smbd_smb2_request_reply_update_counts(struct smbd_smb2_request
*req
)
2777 struct smbXsrv_connection
*xconn
= req
->xconn
;
2778 const uint8_t *inhdr
;
2779 uint16_t channel_sequence
;
2780 struct smbXsrv_open
*op
;
2782 if (!req
->request_counters_updated
) {
2786 req
->request_counters_updated
= false;
2788 if (xconn
->protocol
< PROTOCOL_SMB2_22
) {
2792 if (req
->compat_chain_fsp
== NULL
) {
2796 op
= req
->compat_chain_fsp
->op
;
2801 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
2802 channel_sequence
= SVAL(inhdr
, SMB2_HDR_CHANNEL_SEQUENCE
);
2804 if ((op
->global
->channel_sequence
== channel_sequence
) &&
2805 (op
->global
->channel_generation
== req
->channel_generation
)) {
2806 SMB_ASSERT(op
->request_count
> 0);
2807 op
->request_count
-= 1;
2809 SMB_ASSERT(op
->pre_request_count
> 0);
2810 op
->pre_request_count
-= 1;
2814 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
2816 struct smbXsrv_connection
*xconn
= req
->xconn
;
2818 struct iovec
*firsttf
= SMBD_SMB2_IDX_TF_IOV(req
,out
,first_idx
);
2819 struct iovec
*outhdr
= SMBD_SMB2_OUT_HDR_IOV(req
);
2820 struct iovec
*outdyn
= SMBD_SMB2_OUT_DYN_IOV(req
);
2825 TALLOC_FREE(req
->async_te
);
2827 /* MS-SMB2: 3.3.4.1 Sending Any Outgoing Message */
2828 smbd_smb2_request_reply_update_counts(req
);
2830 if (req
->do_encryption
&&
2831 (firsttf
->iov_len
== 0) &&
2832 (req
->first_key
.length
== 0) &&
2833 (req
->session
!= NULL
) &&
2834 (req
->session
->global
->encryption_key
.length
!= 0))
2836 DATA_BLOB encryption_key
= req
->session
->global
->encryption_key
;
2838 uint64_t session_id
= req
->session
->global
->session_wire_id
;
2839 uint64_t nonce_high
;
2842 status
= smb2_get_new_nonce(req
->session
,
2845 if (!NT_STATUS_IS_OK(status
)) {
2850 * We need to place the SMB2_TRANSFORM header before the
2855 * we need to remember the encryption key
2856 * and defer the signing/encryption until
2857 * we are sure that we do not change
2860 req
->first_key
= data_blob_dup_talloc(req
, encryption_key
);
2861 if (req
->first_key
.data
== NULL
) {
2862 return NT_STATUS_NO_MEMORY
;
2865 tf
= talloc_zero_array(req
, uint8_t,
2868 return NT_STATUS_NO_MEMORY
;
2871 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
2872 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
2873 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
2874 SBVAL(tf
, SMB2_TF_SESSION_ID
, session_id
);
2876 firsttf
->iov_base
= (void *)tf
;
2877 firsttf
->iov_len
= SMB2_TF_HDR_SIZE
;
2880 if ((req
->current_idx
> SMBD_SMB2_NUM_IOV_PER_REQ
) &&
2881 (req
->last_key
.length
> 0) &&
2882 (firsttf
->iov_len
== 0))
2884 int last_idx
= req
->current_idx
- SMBD_SMB2_NUM_IOV_PER_REQ
;
2885 struct iovec
*lasthdr
= SMBD_SMB2_IDX_HDR_IOV(req
,out
,last_idx
);
2888 * As we are sure the header of the last request in the
2889 * compound chain will not change, we can to sign here
2890 * with the last signing key we remembered.
2892 status
= smb2_signing_sign_pdu(req
->last_key
,
2895 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2896 if (!NT_STATUS_IS_OK(status
)) {
2900 if (req
->last_key
.length
> 0) {
2901 data_blob_clear_free(&req
->last_key
);
2904 SMBPROFILE_IOBYTES_ASYNC_END(req
->profile
,
2905 iov_buflen(outhdr
, SMBD_SMB2_NUM_IOV_PER_REQ
-1));
2907 req
->current_idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
;
2909 if (req
->current_idx
< req
->out
.vector_count
) {
2911 * We must process the remaining compound
2912 * SMB2 requests before any new incoming SMB2
2913 * requests. This is because incoming SMB2
2914 * requests may include a cancel for a
2915 * compound request we haven't processed
2918 struct tevent_immediate
*im
= tevent_create_immediate(req
);
2920 return NT_STATUS_NO_MEMORY
;
2923 if (req
->do_signing
&& firsttf
->iov_len
== 0) {
2924 struct smbXsrv_session
*x
= req
->session
;
2925 DATA_BLOB signing_key
= smbd_smb2_signing_key(x
, xconn
);
2928 * we need to remember the signing key
2929 * and defer the signing until
2930 * we are sure that we do not change
2933 req
->last_key
= data_blob_dup_talloc(req
, signing_key
);
2934 if (req
->last_key
.data
== NULL
) {
2935 return NT_STATUS_NO_MEMORY
;
2940 * smbd_smb2_request_dispatch() will redo the impersonation.
2941 * So we use req->xconn->client->raw_ev_ctx instead
2942 * of req->ev_ctx here.
2944 tevent_schedule_immediate(im
,
2945 req
->xconn
->client
->raw_ev_ctx
,
2946 smbd_smb2_request_dispatch_immediate
,
2948 return NT_STATUS_OK
;
2951 if (req
->compound_related
) {
2952 req
->compound_related
= false;
2955 ok
= smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
2957 return NT_STATUS_INVALID_PARAMETER_MIX
;
2960 /* Set credit for these operations (zero credits if this
2961 is a final reply for an async operation). */
2962 smb2_calculate_credits(req
, req
);
2965 * now check if we need to sign the current response
2967 if (firsttf
->iov_len
== SMB2_TF_HDR_SIZE
) {
2968 status
= smb2_signing_encrypt_pdu(req
->first_key
,
2969 xconn
->smb2
.server
.cipher
,
2971 req
->out
.vector_count
- first_idx
);
2972 if (!NT_STATUS_IS_OK(status
)) {
2975 } else if (req
->do_signing
) {
2976 struct smbXsrv_session
*x
= req
->session
;
2977 DATA_BLOB signing_key
= smbd_smb2_signing_key(x
, xconn
);
2979 status
= smb2_signing_sign_pdu(signing_key
,
2982 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2983 if (!NT_STATUS_IS_OK(status
)) {
2987 if (req
->first_key
.length
> 0) {
2988 data_blob_clear_free(&req
->first_key
);
2991 if (req
->preauth
!= NULL
) {
2992 struct hc_sha512state sctx
;
2995 samba_SHA512_Init(&sctx
);
2996 samba_SHA512_Update(&sctx
, req
->preauth
->sha512_value
,
2997 sizeof(req
->preauth
->sha512_value
));
2998 for (i
= 1; i
< req
->in
.vector_count
; i
++) {
2999 samba_SHA512_Update(&sctx
,
3000 req
->in
.vector
[i
].iov_base
,
3001 req
->in
.vector
[i
].iov_len
);
3003 samba_SHA512_Final(req
->preauth
->sha512_value
, &sctx
);
3005 samba_SHA512_Init(&sctx
);
3006 samba_SHA512_Update(&sctx
, req
->preauth
->sha512_value
,
3007 sizeof(req
->preauth
->sha512_value
));
3008 for (i
= 1; i
< req
->out
.vector_count
; i
++) {
3009 samba_SHA512_Update(&sctx
,
3010 req
->out
.vector
[i
].iov_base
,
3011 req
->out
.vector
[i
].iov_len
);
3013 samba_SHA512_Final(req
->preauth
->sha512_value
, &sctx
);
3015 req
->preauth
= NULL
;
3018 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
3019 if (req
->out
.vector_count
< (2*SMBD_SMB2_NUM_IOV_PER_REQ
) &&
3020 outdyn
->iov_base
== NULL
&& outdyn
->iov_len
!= 0) {
3021 /* Dynamic part is NULL. Chop it off,
3022 We're going to send it via sendfile. */
3023 req
->out
.vector_count
-= 1;
3027 * We're done with this request -
3028 * move it off the "being processed" queue.
3030 DLIST_REMOVE(xconn
->smb2
.requests
, req
);
3032 req
->queue_entry
.mem_ctx
= req
;
3033 req
->queue_entry
.vector
= req
->out
.vector
;
3034 req
->queue_entry
.count
= req
->out
.vector_count
;
3035 DLIST_ADD_END(xconn
->smb2
.send_queue
, &req
->queue_entry
);
3036 xconn
->smb2
.send_queue_len
++;
3038 status
= smbd_smb2_flush_send_queue(xconn
);
3039 if (!NT_STATUS_IS_OK(status
)) {
3043 return NT_STATUS_OK
;
3046 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbXsrv_connection
*xconn
);
3048 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
3049 struct tevent_immediate
*im
,
3052 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
3053 struct smbd_smb2_request
);
3054 struct smbXsrv_connection
*xconn
= req
->xconn
;
3059 if (DEBUGLEVEL
>= 10) {
3060 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
3061 req
->current_idx
, req
->in
.vector_count
));
3062 print_req_vectors(req
);
3065 status
= smbd_smb2_request_dispatch(req
);
3066 if (!NT_STATUS_IS_OK(status
)) {
3067 smbd_server_connection_terminate(xconn
, nt_errstr(status
));
3071 status
= smbd_smb2_request_next_incoming(xconn
);
3072 if (!NT_STATUS_IS_OK(status
)) {
3073 smbd_server_connection_terminate(xconn
, nt_errstr(status
));
3078 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
3080 DATA_BLOB body
, DATA_BLOB
*dyn
,
3081 const char *location
)
3084 struct iovec
*outbody_v
;
3085 struct iovec
*outdyn_v
;
3086 uint32_t next_command_ofs
;
3088 DEBUG(10,("smbd_smb2_request_done_ex: "
3089 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
3090 req
->current_idx
, nt_errstr(status
), (unsigned int)body
.length
,
3092 (unsigned int)(dyn
? dyn
->length
: 0),
3095 if (body
.length
< 2) {
3096 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
3099 if ((body
.length
% 2) != 0) {
3100 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
3103 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
3104 outbody_v
= SMBD_SMB2_OUT_BODY_IOV(req
);
3105 outdyn_v
= SMBD_SMB2_OUT_DYN_IOV(req
);
3107 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
3108 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
3110 outbody_v
->iov_base
= (void *)body
.data
;
3111 outbody_v
->iov_len
= body
.length
;
3114 outdyn_v
->iov_base
= (void *)dyn
->data
;
3115 outdyn_v
->iov_len
= dyn
->length
;
3117 outdyn_v
->iov_base
= NULL
;
3118 outdyn_v
->iov_len
= 0;
3122 * See if we need to recalculate the offset to the next response
3124 * Note that all responses may require padding (including the very last
3127 if (req
->out
.vector_count
>= (2 * SMBD_SMB2_NUM_IOV_PER_REQ
)) {
3128 next_command_ofs
= SMB2_HDR_BODY
;
3129 next_command_ofs
+= SMBD_SMB2_OUT_BODY_LEN(req
);
3130 next_command_ofs
+= SMBD_SMB2_OUT_DYN_LEN(req
);
3133 if ((next_command_ofs
% 8) != 0) {
3134 size_t pad_size
= 8 - (next_command_ofs
% 8);
3135 if (SMBD_SMB2_OUT_DYN_LEN(req
) == 0) {
3137 * if the dyn buffer is empty
3138 * we can use it to add padding
3142 pad
= talloc_zero_array(req
,
3145 return smbd_smb2_request_error(req
,
3146 NT_STATUS_NO_MEMORY
);
3149 outdyn_v
->iov_base
= (void *)pad
;
3150 outdyn_v
->iov_len
= pad_size
;
3153 * For now we copy the dynamic buffer
3154 * and add the padding to the new buffer
3161 old_size
= SMBD_SMB2_OUT_DYN_LEN(req
);
3162 old_dyn
= SMBD_SMB2_OUT_DYN_PTR(req
);
3164 new_size
= old_size
+ pad_size
;
3165 new_dyn
= talloc_zero_array(req
,
3167 if (new_dyn
== NULL
) {
3168 return smbd_smb2_request_error(req
,
3169 NT_STATUS_NO_MEMORY
);
3172 memcpy(new_dyn
, old_dyn
, old_size
);
3173 memset(new_dyn
+ old_size
, 0, pad_size
);
3175 outdyn_v
->iov_base
= (void *)new_dyn
;
3176 outdyn_v
->iov_len
= new_size
;
3178 next_command_ofs
+= pad_size
;
3181 if ((req
->current_idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
) >= req
->out
.vector_count
) {
3182 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
3184 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
3186 return smbd_smb2_request_reply(req
);
3189 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
3192 const char *location
)
3194 struct smbXsrv_connection
*xconn
= req
->xconn
;
3197 uint8_t *outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
3198 size_t unread_bytes
= smbd_smb2_unread_bytes(req
);
3200 DBG_NOTICE("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| "
3201 "at %s\n", req
->current_idx
, nt_errstr(status
),
3202 info
? " +info" : "", location
);
3205 /* Recvfile error. Drain incoming socket. */
3209 ret
= drain_socket(xconn
->transport
.sock
, unread_bytes
);
3210 if (ret
!= unread_bytes
) {
3214 error
= NT_STATUS_IO_DEVICE_ERROR
;
3216 error
= map_nt_error_from_unix_common(errno
);
3219 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
3220 "ret[%u] errno[%d] => %s\n",
3221 (unsigned)unread_bytes
,
3222 (unsigned)ret
, errno
, nt_errstr(error
)));
3227 body
.data
= outhdr
+ SMB2_HDR_BODY
;
3229 SSVAL(body
.data
, 0, 9);
3232 SIVAL(body
.data
, 0x04, info
->length
);
3234 /* Allocated size of req->out.vector[i].iov_base
3235 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
3236 * 1 byte without having to do an alloc.
3239 info
->data
= ((uint8_t *)outhdr
) +
3240 OUTVEC_ALLOC_SIZE
- 1;
3242 SCVAL(info
->data
, 0, 0);
3246 * Note: Even if there is an error, continue to process the request.
3250 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
3254 struct smbd_smb2_send_break_state
{
3255 struct smbd_smb2_send_queue queue_entry
;
3256 uint8_t nbt_hdr
[NBT_HDR_SIZE
];
3257 uint8_t tf
[SMB2_TF_HDR_SIZE
];
3258 uint8_t hdr
[SMB2_HDR_BODY
];
3259 struct iovec vector
[1+SMBD_SMB2_NUM_IOV_PER_REQ
];
3263 static NTSTATUS
smbd_smb2_send_break(struct smbXsrv_connection
*xconn
,
3264 struct smbXsrv_session
*session
,
3265 struct smbXsrv_tcon
*tcon
,
3266 const uint8_t *body
,
3269 struct smbd_smb2_send_break_state
*state
;
3270 bool do_encryption
= false;
3271 uint64_t session_wire_id
= 0;
3272 uint64_t nonce_high
= 0;
3273 uint64_t nonce_low
= 0;
3278 if (session
!= NULL
) {
3279 session_wire_id
= session
->global
->session_wire_id
;
3280 do_encryption
= session
->global
->encryption_flags
& SMBXSRV_ENCRYPTION_DESIRED
;
3281 if (tcon
->global
->encryption_flags
& SMBXSRV_ENCRYPTION_DESIRED
) {
3282 do_encryption
= true;
3286 statelen
= offsetof(struct smbd_smb2_send_break_state
, body
) +
3289 state
= talloc_zero_size(xconn
, statelen
);
3290 if (state
== NULL
) {
3291 return NT_STATUS_NO_MEMORY
;
3293 talloc_set_name_const(state
, "struct smbd_smb2_send_break_state");
3295 if (do_encryption
) {
3296 status
= smb2_get_new_nonce(session
,
3299 if (!NT_STATUS_IS_OK(status
)) {
3304 SIVAL(state
->tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
3305 SBVAL(state
->tf
, SMB2_TF_NONCE
+0, nonce_low
);
3306 SBVAL(state
->tf
, SMB2_TF_NONCE
+8, nonce_high
);
3307 SBVAL(state
->tf
, SMB2_TF_SESSION_ID
, session_wire_id
);
3309 SIVAL(state
->hdr
, 0, SMB2_MAGIC
);
3310 SSVAL(state
->hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
3311 SSVAL(state
->hdr
, SMB2_HDR_EPOCH
, 0);
3312 SIVAL(state
->hdr
, SMB2_HDR_STATUS
, 0);
3313 SSVAL(state
->hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
3314 SSVAL(state
->hdr
, SMB2_HDR_CREDIT
, 0);
3315 SIVAL(state
->hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
3316 SIVAL(state
->hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
3317 SBVAL(state
->hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
3318 SIVAL(state
->hdr
, SMB2_HDR_PID
, 0);
3319 SIVAL(state
->hdr
, SMB2_HDR_TID
, 0);
3320 SBVAL(state
->hdr
, SMB2_HDR_SESSION_ID
, 0);
3321 memset(state
->hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
3323 state
->vector
[0] = (struct iovec
) {
3324 .iov_base
= state
->nbt_hdr
,
3325 .iov_len
= sizeof(state
->nbt_hdr
)
3328 if (do_encryption
) {
3329 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
] = (struct iovec
) {
3330 .iov_base
= state
->tf
,
3331 .iov_len
= sizeof(state
->tf
)
3334 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
] = (struct iovec
) {
3340 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
] = (struct iovec
) {
3341 .iov_base
= state
->hdr
,
3342 .iov_len
= sizeof(state
->hdr
)
3345 memcpy(state
->body
, body
, body_len
);
3347 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
] = (struct iovec
) {
3348 .iov_base
= state
->body
,
3349 .iov_len
= body_len
/* no sizeof(state->body) .. :-) */
3353 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
3356 ok
= smb2_setup_nbt_length(state
->vector
,
3357 1 + SMBD_SMB2_NUM_IOV_PER_REQ
);
3359 return NT_STATUS_INVALID_PARAMETER_MIX
;
3362 if (do_encryption
) {
3363 DATA_BLOB encryption_key
= session
->global
->encryption_key
;
3365 status
= smb2_signing_encrypt_pdu(encryption_key
,
3366 xconn
->smb2
.server
.cipher
,
3367 &state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
],
3368 SMBD_SMB2_NUM_IOV_PER_REQ
);
3369 if (!NT_STATUS_IS_OK(status
)) {
3374 state
->queue_entry
.mem_ctx
= state
;
3375 state
->queue_entry
.vector
= state
->vector
;
3376 state
->queue_entry
.count
= ARRAY_SIZE(state
->vector
);
3377 DLIST_ADD_END(xconn
->smb2
.send_queue
, &state
->queue_entry
);
3378 xconn
->smb2
.send_queue_len
++;
3380 status
= smbd_smb2_flush_send_queue(xconn
);
3381 if (!NT_STATUS_IS_OK(status
)) {
3385 return NT_STATUS_OK
;
3388 NTSTATUS
smbd_smb2_send_oplock_break(struct smbXsrv_connection
*xconn
,
3389 struct smbXsrv_session
*session
,
3390 struct smbXsrv_tcon
*tcon
,
3391 struct smbXsrv_open
*op
,
3392 uint8_t oplock_level
)
3396 SSVAL(body
, 0x00, sizeof(body
));
3397 SCVAL(body
, 0x02, oplock_level
);
3398 SCVAL(body
, 0x03, 0); /* reserved */
3399 SIVAL(body
, 0x04, 0); /* reserved */
3400 SBVAL(body
, 0x08, op
->global
->open_persistent_id
);
3401 SBVAL(body
, 0x10, op
->global
->open_volatile_id
);
3403 return smbd_smb2_send_break(xconn
, NULL
, NULL
, body
, sizeof(body
));
3406 NTSTATUS
smbd_smb2_send_lease_break(struct smbXsrv_connection
*xconn
,
3408 uint32_t lease_flags
,
3409 struct smb2_lease_key
*lease_key
,
3410 uint32_t current_lease_state
,
3411 uint32_t new_lease_state
)
3415 SSVAL(body
, 0x00, sizeof(body
));
3416 SSVAL(body
, 0x02, new_epoch
);
3417 SIVAL(body
, 0x04, lease_flags
);
3418 SBVAL(body
, 0x08, lease_key
->data
[0]);
3419 SBVAL(body
, 0x10, lease_key
->data
[1]);
3420 SIVAL(body
, 0x18, current_lease_state
);
3421 SIVAL(body
, 0x1c, new_lease_state
);
3422 SIVAL(body
, 0x20, 0); /* BreakReason, MUST be 0 */
3423 SIVAL(body
, 0x24, 0); /* AccessMaskHint, MUST be 0 */
3424 SIVAL(body
, 0x28, 0); /* ShareMaskHint, MUST be 0 */
3426 return smbd_smb2_send_break(xconn
, NULL
, NULL
, body
, sizeof(body
));
3429 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state
*state
)
3433 uint64_t file_id_persistent
;
3434 uint64_t file_id_volatile
;
3435 struct smbXsrv_open
*op
= NULL
;
3436 struct files_struct
*fsp
= NULL
;
3437 const uint8_t *body
= NULL
;
3440 * This is only called with a pktbuf
3441 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
3445 if (IVAL(state
->pktbuf
, 0) == SMB2_TF_MAGIC
) {
3446 /* Transform header. Cannot recvfile. */
3449 if (IVAL(state
->pktbuf
, 0) != SMB2_MAGIC
) {
3450 /* Not SMB2. Normal error path will cope. */
3453 if (SVAL(state
->pktbuf
, 4) != SMB2_HDR_BODY
) {
3454 /* Not SMB2. Normal error path will cope. */
3457 if (SVAL(state
->pktbuf
, SMB2_HDR_OPCODE
) != SMB2_OP_WRITE
) {
3458 /* Needs to be a WRITE. */
3461 if (IVAL(state
->pktbuf
, SMB2_HDR_NEXT_COMMAND
) != 0) {
3462 /* Chained. Cannot recvfile. */
3465 flags
= IVAL(state
->pktbuf
, SMB2_HDR_FLAGS
);
3466 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
3467 /* Chained. Cannot recvfile. */
3470 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
3471 /* Signed. Cannot recvfile. */
3475 body
= &state
->pktbuf
[SMB2_HDR_BODY
];
3477 file_id_persistent
= BVAL(body
, 0x10);
3478 file_id_volatile
= BVAL(body
, 0x18);
3480 status
= smb2srv_open_lookup(state
->req
->xconn
,
3485 if (!NT_STATUS_IS_OK(status
)) {
3493 if (fsp
->conn
== NULL
) {
3497 if (IS_IPC(fsp
->conn
)) {
3500 if (IS_PRINT(fsp
->conn
)) {
3503 if (fsp
->base_fsp
!= NULL
) {
3507 DEBUG(10,("Doing recvfile write len = %u\n",
3508 (unsigned int)(state
->pktfull
- state
->pktlen
)));
3513 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbXsrv_connection
*xconn
)
3515 struct smbd_server_connection
*sconn
= xconn
->client
->sconn
;
3516 struct smbd_smb2_request_read_state
*state
= &xconn
->smb2
.request_read_state
;
3517 size_t max_send_queue_len
;
3518 size_t cur_send_queue_len
;
3520 if (!NT_STATUS_IS_OK(xconn
->transport
.status
)) {
3522 * we're not supposed to do any io
3524 return NT_STATUS_OK
;
3527 if (state
->req
!= NULL
) {
3529 * if there is already a tstream_readv_pdu
3530 * pending, we are done.
3532 return NT_STATUS_OK
;
3535 max_send_queue_len
= MAX(1, xconn
->smb2
.credits
.max
/16);
3536 cur_send_queue_len
= xconn
->smb2
.send_queue_len
;
3538 if (cur_send_queue_len
> max_send_queue_len
) {
3540 * if we have a lot of requests to send,
3541 * we wait until they are on the wire until we
3542 * ask for the next request.
3544 return NT_STATUS_OK
;
3547 /* ask for the next request */
3548 ZERO_STRUCTP(state
);
3549 state
->req
= smbd_smb2_request_allocate(xconn
);
3550 if (state
->req
== NULL
) {
3551 return NT_STATUS_NO_MEMORY
;
3553 state
->req
->sconn
= sconn
;
3554 state
->req
->xconn
= xconn
;
3555 state
->min_recv_size
= lp_min_receive_file_size();
3557 TEVENT_FD_READABLE(xconn
->transport
.fde
);
3559 return NT_STATUS_OK
;
3562 void smbd_smb2_process_negprot(struct smbXsrv_connection
*xconn
,
3563 uint64_t expected_seq_low
,
3564 const uint8_t *inpdu
, size_t size
)
3566 struct smbd_server_connection
*sconn
= xconn
->client
->sconn
;
3568 struct smbd_smb2_request
*req
= NULL
;
3570 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3571 (unsigned int)size
));
3573 status
= smbd_initialize_smb2(xconn
, expected_seq_low
);
3574 if (!NT_STATUS_IS_OK(status
)) {
3575 smbd_server_connection_terminate(xconn
, nt_errstr(status
));
3579 status
= smbd_smb2_request_create(xconn
, inpdu
, size
, &req
);
3580 if (!NT_STATUS_IS_OK(status
)) {
3581 smbd_server_connection_terminate(xconn
, nt_errstr(status
));
3585 status
= smbd_smb2_request_validate(req
);
3586 if (!NT_STATUS_IS_OK(status
)) {
3587 smbd_server_connection_terminate(xconn
, nt_errstr(status
));
3591 status
= smbd_smb2_request_setup_out(req
);
3592 if (!NT_STATUS_IS_OK(status
)) {
3593 smbd_server_connection_terminate(xconn
, nt_errstr(status
));
3599 * this was already counted at the SMB1 layer =>
3600 * smbd_smb2_request_dispatch() should not count it twice.
3602 if (profile_p
->values
.request_stats
.count
> 0) {
3603 profile_p
->values
.request_stats
.count
--;
3606 status
= smbd_smb2_request_dispatch(req
);
3607 if (!NT_STATUS_IS_OK(status
)) {
3608 smbd_server_connection_terminate(xconn
, nt_errstr(status
));
3612 status
= smbd_smb2_request_next_incoming(xconn
);
3613 if (!NT_STATUS_IS_OK(status
)) {
3614 smbd_server_connection_terminate(xconn
, nt_errstr(status
));
3618 sconn
->num_requests
++;
3621 static int socket_error_from_errno(int ret
,
3635 if (sys_errno
== 0) {
3639 if (sys_errno
== EINTR
) {
3644 if (sys_errno
== EINPROGRESS
) {
3649 if (sys_errno
== EAGAIN
) {
3654 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3655 if (sys_errno
== ENOMEM
) {
3661 #if EWOULDBLOCK != EAGAIN
3662 if (sys_errno
== EWOULDBLOCK
) {
3672 static NTSTATUS
smbd_smb2_flush_send_queue(struct smbXsrv_connection
*xconn
)
3679 if (xconn
->smb2
.send_queue
== NULL
) {
3680 TEVENT_FD_NOT_WRITEABLE(xconn
->transport
.fde
);
3681 return NT_STATUS_OK
;
3684 while (xconn
->smb2
.send_queue
!= NULL
) {
3685 struct smbd_smb2_send_queue
*e
= xconn
->smb2
.send_queue
;
3688 if (e
->sendfile_header
!= NULL
) {
3693 status
= NT_STATUS_INTERNAL_ERROR
;
3695 for (i
=0; i
< e
->count
; i
++) {
3696 size
+= e
->vector
[i
].iov_len
;
3699 if (size
<= e
->sendfile_header
->length
) {
3700 buf
= e
->sendfile_header
->data
;
3702 buf
= talloc_array(e
->mem_ctx
, uint8_t, size
);
3704 return NT_STATUS_NO_MEMORY
;
3709 for (i
=0; i
< e
->count
; i
++) {
3711 e
->vector
[i
].iov_base
,
3712 e
->vector
[i
].iov_len
);
3713 size
+= e
->vector
[i
].iov_len
;
3716 e
->sendfile_header
->data
= buf
;
3717 e
->sendfile_header
->length
= size
;
3718 e
->sendfile_status
= &status
;
3721 xconn
->smb2
.send_queue_len
--;
3722 DLIST_REMOVE(xconn
->smb2
.send_queue
, e
);
3724 * This triggers the sendfile path via
3727 talloc_free(e
->mem_ctx
);
3729 if (!NT_STATUS_IS_OK(status
)) {
3735 ret
= writev(xconn
->transport
.sock
, e
->vector
, e
->count
);
3737 /* propagate end of file */
3738 return NT_STATUS_INTERNAL_ERROR
;
3740 err
= socket_error_from_errno(ret
, errno
, &retry
);
3743 TEVENT_FD_WRITEABLE(xconn
->transport
.fde
);
3744 return NT_STATUS_OK
;
3747 return map_nt_error_from_unix_common(err
);
3750 ok
= iov_advance(&e
->vector
, &e
->count
, ret
);
3752 return NT_STATUS_INTERNAL_ERROR
;
3756 /* we have more to write */
3757 TEVENT_FD_WRITEABLE(xconn
->transport
.fde
);
3758 return NT_STATUS_OK
;
3761 xconn
->smb2
.send_queue_len
--;
3762 DLIST_REMOVE(xconn
->smb2
.send_queue
, e
);
3763 talloc_free(e
->mem_ctx
);
3767 * Restart reads if we were blocked on
3768 * draining the send queue.
3771 status
= smbd_smb2_request_next_incoming(xconn
);
3772 if (!NT_STATUS_IS_OK(status
)) {
3776 return NT_STATUS_OK
;
3779 static NTSTATUS
smbd_smb2_io_handler(struct smbXsrv_connection
*xconn
,
3782 struct smbd_server_connection
*sconn
= xconn
->client
->sconn
;
3783 struct smbd_smb2_request_read_state
*state
= &xconn
->smb2
.request_read_state
;
3784 struct smbd_smb2_request
*req
= NULL
;
3785 size_t min_recvfile_size
= UINT32_MAX
;
3792 if (!NT_STATUS_IS_OK(xconn
->transport
.status
)) {
3794 * we're not supposed to do any io
3796 TEVENT_FD_NOT_READABLE(xconn
->transport
.fde
);
3797 TEVENT_FD_NOT_WRITEABLE(xconn
->transport
.fde
);
3798 return NT_STATUS_OK
;
3801 if (fde_flags
& TEVENT_FD_WRITE
) {
3802 status
= smbd_smb2_flush_send_queue(xconn
);
3803 if (!NT_STATUS_IS_OK(status
)) {
3808 if (!(fde_flags
& TEVENT_FD_READ
)) {
3809 return NT_STATUS_OK
;
3812 if (state
->req
== NULL
) {
3813 TEVENT_FD_NOT_READABLE(xconn
->transport
.fde
);
3814 return NT_STATUS_OK
;
3818 if (!state
->hdr
.done
) {
3819 state
->hdr
.done
= true;
3821 state
->vector
.iov_base
= (void *)state
->hdr
.nbt
;
3822 state
->vector
.iov_len
= NBT_HDR_SIZE
;
3825 ret
= readv(xconn
->transport
.sock
, &state
->vector
, 1);
3827 /* propagate end of file */
3828 return NT_STATUS_END_OF_FILE
;
3830 err
= socket_error_from_errno(ret
, errno
, &retry
);
3833 TEVENT_FD_READABLE(xconn
->transport
.fde
);
3834 return NT_STATUS_OK
;
3837 return map_nt_error_from_unix_common(err
);
3840 if (ret
< state
->vector
.iov_len
) {
3842 base
= (uint8_t *)state
->vector
.iov_base
;
3844 state
->vector
.iov_base
= (void *)base
;
3845 state
->vector
.iov_len
-= ret
;
3846 /* we have more to read */
3847 TEVENT_FD_READABLE(xconn
->transport
.fde
);
3848 return NT_STATUS_OK
;
3851 if (state
->pktlen
> 0) {
3852 if (state
->doing_receivefile
&& !is_smb2_recvfile_write(state
)) {
3854 * Not a possible receivefile write.
3855 * Read the rest of the data.
3857 state
->doing_receivefile
= false;
3859 state
->pktbuf
= talloc_realloc(state
->req
,
3863 if (state
->pktbuf
== NULL
) {
3864 return NT_STATUS_NO_MEMORY
;
3867 state
->vector
.iov_base
= (void *)(state
->pktbuf
+
3869 state
->vector
.iov_len
= (state
->pktfull
-
3872 state
->pktlen
= state
->pktfull
;
3877 * Either this is a receivefile write so we've
3878 * done a short read, or if not we have all the data.
3884 * Now we analyze the NBT header
3886 if (state
->hdr
.nbt
[0] != 0x00) {
3887 state
->min_recv_size
= 0;
3889 state
->pktfull
= smb2_len(state
->hdr
.nbt
);
3890 if (state
->pktfull
== 0) {
3894 if (state
->min_recv_size
!= 0) {
3895 min_recvfile_size
= SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
;
3896 min_recvfile_size
+= state
->min_recv_size
;
3899 if (state
->pktfull
> min_recvfile_size
) {
3901 * Might be a receivefile write. Read the SMB2 HEADER +
3902 * SMB2_WRITE header first. Set 'doing_receivefile'
3903 * as we're *attempting* receivefile write. If this
3904 * turns out not to be a SMB2_WRITE request or otherwise
3905 * not suitable then we'll just read the rest of the data
3906 * the next time this function is called.
3908 state
->pktlen
= SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
;
3909 state
->doing_receivefile
= true;
3911 state
->pktlen
= state
->pktfull
;
3914 state
->pktbuf
= talloc_array(state
->req
, uint8_t, state
->pktlen
);
3915 if (state
->pktbuf
== NULL
) {
3916 return NT_STATUS_NO_MEMORY
;
3919 state
->vector
.iov_base
= (void *)state
->pktbuf
;
3920 state
->vector
.iov_len
= state
->pktlen
;
3926 if (state
->hdr
.nbt
[0] != 0x00) {
3927 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3928 state
->hdr
.nbt
[0]));
3931 ZERO_STRUCTP(state
);
3933 state
->min_recv_size
= lp_min_receive_file_size();
3941 req
->request_time
= timeval_current();
3942 now
= timeval_to_nttime(&req
->request_time
);
3944 status
= smbd_smb2_inbuf_parse_compound(xconn
,
3950 &req
->in
.vector_count
);
3951 if (!NT_STATUS_IS_OK(status
)) {
3955 if (state
->doing_receivefile
) {
3956 req
->smb1req
= talloc_zero(req
, struct smb_request
);
3957 if (req
->smb1req
== NULL
) {
3958 return NT_STATUS_NO_MEMORY
;
3960 req
->smb1req
->unread_bytes
= state
->pktfull
- state
->pktlen
;
3963 ZERO_STRUCTP(state
);
3965 req
->current_idx
= 1;
3967 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3968 req
->current_idx
, req
->in
.vector_count
));
3970 status
= smbd_smb2_request_validate(req
);
3971 if (!NT_STATUS_IS_OK(status
)) {
3975 status
= smbd_smb2_request_setup_out(req
);
3976 if (!NT_STATUS_IS_OK(status
)) {
3980 status
= smbd_smb2_request_dispatch(req
);
3981 if (!NT_STATUS_IS_OK(status
)) {
3985 sconn
->num_requests
++;
3987 /* The timeout_processing function isn't run nearly
3988 often enough to implement 'max log size' without
3989 overrunning the size of the file by many megabytes.
3990 This is especially true if we are running at debug
3991 level 10. Checking every 50 SMB2s is a nice
3992 tradeoff of performance vs log file size overrun. */
3994 if ((sconn
->num_requests
% 50) == 0 &&
3995 need_to_check_log_size()) {
3996 change_to_root_user();
4000 status
= smbd_smb2_request_next_incoming(xconn
);
4001 if (!NT_STATUS_IS_OK(status
)) {
4005 return NT_STATUS_OK
;
4008 static void smbd_smb2_connection_handler(struct tevent_context
*ev
,
4009 struct tevent_fd
*fde
,
4013 struct smbXsrv_connection
*xconn
=
4014 talloc_get_type_abort(private_data
,
4015 struct smbXsrv_connection
);
4018 status
= smbd_smb2_io_handler(xconn
, flags
);
4019 if (!NT_STATUS_IS_OK(status
)) {
4020 smbd_server_connection_terminate(xconn
, nt_errstr(status
));