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 current_max_credits
= xconn
->smb2
.credits
.max
/ 16;
834 current_max_credits
= MAX(current_max_credits
, 1);
836 if (xconn
->smb2
.credits
.multicredit
) {
837 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
838 credit_charge
= MAX(credit_charge
, 1);
841 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
842 credits_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
843 credits_requested
= MAX(credits_requested
, 1);
844 out_flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
845 out_status
= NT_STATUS(IVAL(outhdr
, SMB2_HDR_STATUS
));
847 SMB_ASSERT(xconn
->smb2
.credits
.max
>= xconn
->smb2
.credits
.granted
);
849 if (xconn
->smb2
.credits
.max
< credit_charge
) {
850 smbd_server_connection_terminate(xconn
,
851 "client error: credit charge > max credits\n");
855 if (out_flags
& SMB2_HDR_FLAG_ASYNC
) {
857 * In case we already send an async interim
858 * response, we should not grant
859 * credits on the final response.
863 uint16_t additional_possible
=
864 xconn
->smb2
.credits
.max
- credit_charge
;
865 uint16_t additional_max
= 0;
866 uint16_t additional_credits
= credits_requested
- 1;
869 case SMB2_OP_NEGPROT
:
871 case SMB2_OP_SESSSETUP
:
873 * Windows 2012 RC1 starts to grant
875 * with a successful session setup
877 if (NT_STATUS_IS_OK(out_status
)) {
883 * We match windows and only grant additional credits
890 additional_max
= MIN(additional_max
, additional_possible
);
891 additional_credits
= MIN(additional_credits
, additional_max
);
893 credits_granted
= credit_charge
+ additional_credits
;
897 * sequence numbers should not wrap
899 * 1. calculate the possible credits until
900 * the sequence numbers start to wrap on 64-bit.
902 * 2. UINT64_MAX is used for Break Notifications.
904 * 2. truncate the possible credits to the maximum
905 * credits we want to grant to the client in total.
907 * 3. remove the range we'll already granted to the client
908 * this makes sure the client consumes the lowest sequence
909 * number, before we can grant additional credits.
911 credits_possible
= UINT64_MAX
- xconn
->smb2
.credits
.seq_low
;
912 if (credits_possible
> 0) {
913 /* remove UINT64_MAX */
914 credits_possible
-= 1;
916 credits_possible
= MIN(credits_possible
, current_max_credits
);
917 credits_possible
-= xconn
->smb2
.credits
.seq_range
;
919 credits_granted
= MIN(credits_granted
, credits_possible
);
921 SSVAL(outhdr
, SMB2_HDR_CREDIT
, credits_granted
);
922 xconn
->smb2
.credits
.granted
+= credits_granted
;
923 xconn
->smb2
.credits
.seq_range
+= credits_granted
;
925 DBGC_DEBUG(DBGC_SMB2_CREDITS
,
926 "smb2_set_operation_credit: requested %u, charge %u, "
927 "granted %u, current possible/max %u/%u, "
928 "total granted/max/low/range %u/%u/%llu/%u\n",
929 (unsigned int)credits_requested
,
930 (unsigned int)credit_charge
,
931 (unsigned int)credits_granted
,
932 (unsigned int)credits_possible
,
933 (unsigned int)current_max_credits
,
934 (unsigned int)xconn
->smb2
.credits
.granted
,
935 (unsigned int)xconn
->smb2
.credits
.max
,
936 (unsigned long long)xconn
->smb2
.credits
.seq_low
,
937 (unsigned int)xconn
->smb2
.credits
.seq_range
);
940 static void smb2_calculate_credits(const struct smbd_smb2_request
*inreq
,
941 struct smbd_smb2_request
*outreq
)
944 uint16_t total_credits
= 0;
946 count
= outreq
->out
.vector_count
;
948 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
949 struct iovec
*inhdr_v
= SMBD_SMB2_IDX_HDR_IOV(inreq
,in
,idx
);
950 struct iovec
*outhdr_v
= SMBD_SMB2_IDX_HDR_IOV(outreq
,out
,idx
);
951 uint8_t *outhdr
= (uint8_t *)outhdr_v
->iov_base
;
953 smb2_set_operation_credit(outreq
->xconn
, inhdr_v
, outhdr_v
);
955 /* To match Windows, count up what we
957 total_credits
+= SVAL(outhdr
, SMB2_HDR_CREDIT
);
958 /* Set to zero in all but the last reply. */
959 if (idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
< count
) {
960 SSVAL(outhdr
, SMB2_HDR_CREDIT
, 0);
962 SSVAL(outhdr
, SMB2_HDR_CREDIT
, total_credits
);
967 DATA_BLOB
smbd_smb2_generate_outbody(struct smbd_smb2_request
*req
, size_t size
)
969 if (req
->current_idx
<= 1) {
970 if (size
<= sizeof(req
->out
._body
)) {
971 return data_blob_const(req
->out
._body
, size
);
975 return data_blob_talloc(req
, NULL
, size
);
978 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
)
980 struct smbXsrv_connection
*xconn
= req
->xconn
;
982 struct iovec
*vector
;
987 count
= req
->in
.vector_count
;
988 if (count
<= ARRAY_SIZE(req
->out
._vector
)) {
990 vector
= req
->out
._vector
;
992 vector
= talloc_zero_array(req
, struct iovec
, count
);
993 if (vector
== NULL
) {
994 return NT_STATUS_NO_MEMORY
;
999 vector
[0].iov_base
= req
->out
.nbt_hdr
;
1000 vector
[0].iov_len
= 4;
1001 SIVAL(req
->out
.nbt_hdr
, 0, 0);
1003 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
1004 struct iovec
*inhdr_v
= SMBD_SMB2_IDX_HDR_IOV(req
,in
,idx
);
1005 const uint8_t *inhdr
= (const uint8_t *)inhdr_v
->iov_base
;
1006 uint8_t *outhdr
= NULL
;
1007 uint8_t *outbody
= NULL
;
1008 uint32_t next_command_ofs
= 0;
1009 struct iovec
*current
= &vector
[idx
];
1011 if ((idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
) < count
) {
1012 /* we have a next command -
1013 * setup for the error case. */
1014 next_command_ofs
= SMB2_HDR_BODY
+ 9;
1018 outhdr
= req
->out
._hdr
;
1020 outhdr
= talloc_zero_array(mem_ctx
, uint8_t,
1022 if (outhdr
== NULL
) {
1023 return NT_STATUS_NO_MEMORY
;
1027 outbody
= outhdr
+ SMB2_HDR_BODY
;
1030 * SMBD_SMB2_TF_IOV_OFS might be used later
1032 current
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
1033 current
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
1035 current
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= (void *)outhdr
;
1036 current
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
1038 current
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= (void *)outbody
;
1039 current
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= 8;
1041 current
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= NULL
;
1042 current
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= 0;
1044 /* setup the SMB2 header */
1045 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
1046 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1047 SSVAL(outhdr
, SMB2_HDR_CREDIT_CHARGE
,
1048 SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
));
1049 SIVAL(outhdr
, SMB2_HDR_STATUS
,
1050 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
1051 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
1052 SVAL(inhdr
, SMB2_HDR_OPCODE
));
1053 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
1054 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
1055 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
1056 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
1057 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
1058 SIVAL(outhdr
, SMB2_HDR_PID
,
1059 IVAL(inhdr
, SMB2_HDR_PID
));
1060 SIVAL(outhdr
, SMB2_HDR_TID
,
1061 IVAL(inhdr
, SMB2_HDR_TID
));
1062 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
1063 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
1064 memcpy(outhdr
+ SMB2_HDR_SIGNATURE
,
1065 inhdr
+ SMB2_HDR_SIGNATURE
, 16);
1067 /* setup error body header */
1068 SSVAL(outbody
, 0x00, 0x08 + 1);
1069 SSVAL(outbody
, 0x02, 0);
1070 SIVAL(outbody
, 0x04, 0);
1073 req
->out
.vector
= vector
;
1074 req
->out
.vector_count
= count
;
1076 /* setup the length of the NBT packet */
1077 ok
= smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
1079 return NT_STATUS_INVALID_PARAMETER_MIX
;
1082 DLIST_ADD_END(xconn
->smb2
.requests
, req
);
1084 return NT_STATUS_OK
;
1087 void smbd_server_connection_terminate_ex(struct smbXsrv_connection
*xconn
,
1089 const char *location
)
1091 struct smbXsrv_client
*client
= xconn
->client
;
1093 DEBUG(10,("smbd_server_connection_terminate_ex: conn[%s] reason[%s] at %s\n",
1094 smbXsrv_connection_dbg(xconn
), reason
, location
));
1096 if (client
->connections
->next
!= NULL
) {
1097 /* TODO: cancel pending requests */
1098 DLIST_REMOVE(client
->connections
, xconn
);
1100 DO_PROFILE_INC(disconnect
);
1105 * The last connection was disconnected
1107 exit_server_cleanly(reason
);
1110 static bool dup_smb2_vec4(TALLOC_CTX
*ctx
,
1111 struct iovec
*outvec
,
1112 const struct iovec
*srcvec
)
1114 const uint8_t *srctf
;
1116 const uint8_t *srchdr
;
1118 const uint8_t *srcbody
;
1120 const uint8_t *expected_srcbody
;
1121 const uint8_t *srcdyn
;
1123 const uint8_t *expected_srcdyn
;
1129 srctf
= (const uint8_t *)srcvec
[SMBD_SMB2_TF_IOV_OFS
].iov_base
;
1130 srctf_len
= srcvec
[SMBD_SMB2_TF_IOV_OFS
].iov_len
;
1131 srchdr
= (const uint8_t *)srcvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
;
1132 srchdr_len
= srcvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
;
1133 srcbody
= (const uint8_t *)srcvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
;
1134 srcbody_len
= srcvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
;
1135 expected_srcbody
= srchdr
+ SMB2_HDR_BODY
;
1136 srcdyn
= (const uint8_t *)srcvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
;
1137 srcdyn_len
= srcvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
;
1138 expected_srcdyn
= srcbody
+ 8;
1140 if ((srctf_len
!= SMB2_TF_HDR_SIZE
) && (srctf_len
!= 0)) {
1144 if (srchdr_len
!= SMB2_HDR_BODY
) {
1148 if (srctf_len
== SMB2_TF_HDR_SIZE
) {
1149 dsttf
= talloc_memdup(ctx
, srctf
, SMB2_TF_HDR_SIZE
);
1150 if (dsttf
== NULL
) {
1156 outvec
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= (void *)dsttf
;
1157 outvec
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= srctf_len
;
1159 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1160 * be allocated with size OUTVEC_ALLOC_SIZE. */
1162 dsthdr
= talloc_memdup(ctx
, srchdr
, OUTVEC_ALLOC_SIZE
);
1163 if (dsthdr
== NULL
) {
1166 outvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= (void *)dsthdr
;
1167 outvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
1170 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1171 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1172 * then duplicate this. Else use talloc_memdup().
1175 if ((srcbody
== expected_srcbody
) && (srcbody_len
== 8)) {
1176 dstbody
= dsthdr
+ SMB2_HDR_BODY
;
1178 dstbody
= talloc_memdup(ctx
, srcbody
, srcbody_len
);
1179 if (dstbody
== NULL
) {
1183 outvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= (void *)dstbody
;
1184 outvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= srcbody_len
;
1187 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1189 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1190 * then duplicate this. Else use talloc_memdup().
1193 if ((srcdyn
== expected_srcdyn
) && (srcdyn_len
== 1)) {
1194 dstdyn
= dsthdr
+ SMB2_HDR_BODY
+ 8;
1195 } else if (srcdyn
== NULL
) {
1198 dstdyn
= talloc_memdup(ctx
, srcdyn
, srcdyn_len
);
1199 if (dstdyn
== NULL
) {
1203 outvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= (void *)dstdyn
;
1204 outvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= srcdyn_len
;
1209 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
1211 struct smbd_smb2_request
*newreq
= NULL
;
1212 struct iovec
*outvec
= NULL
;
1213 int count
= req
->out
.vector_count
;
1217 newreq
= smbd_smb2_request_allocate(req
->xconn
);
1222 newreq
->sconn
= req
->sconn
;
1223 newreq
->xconn
= req
->xconn
;
1224 newreq
->session
= req
->session
;
1225 newreq
->do_encryption
= req
->do_encryption
;
1226 newreq
->do_signing
= req
->do_signing
;
1227 newreq
->current_idx
= req
->current_idx
;
1229 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
1231 TALLOC_FREE(newreq
);
1234 newreq
->out
.vector
= outvec
;
1235 newreq
->out
.vector_count
= count
;
1237 /* Setup the outvec's identically to req. */
1238 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
1239 outvec
[0].iov_len
= 4;
1240 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
1242 /* Setup the vectors identically to the ones in req. */
1243 for (i
= 1; i
< count
; i
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
1244 if (!dup_smb2_vec4(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
1251 TALLOC_FREE(newreq
);
1255 ok
= smb2_setup_nbt_length(newreq
->out
.vector
,
1256 newreq
->out
.vector_count
);
1258 TALLOC_FREE(newreq
);
1265 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
1267 struct smbXsrv_connection
*xconn
= req
->xconn
;
1269 struct iovec
*firsttf
= NULL
;
1270 struct iovec
*outhdr_v
= NULL
;
1271 uint8_t *outhdr
= NULL
;
1272 struct smbd_smb2_request
*nreq
= NULL
;
1276 /* Create a new smb2 request we'll use
1277 for the interim return. */
1278 nreq
= dup_smb2_req(req
);
1280 return NT_STATUS_NO_MEMORY
;
1283 /* Lose the last X out vectors. They're the
1284 ones we'll be using for the async reply. */
1285 nreq
->out
.vector_count
-= SMBD_SMB2_NUM_IOV_PER_REQ
;
1287 ok
= smb2_setup_nbt_length(nreq
->out
.vector
,
1288 nreq
->out
.vector_count
);
1290 return NT_STATUS_INVALID_PARAMETER_MIX
;
1293 /* Step back to the previous reply. */
1294 nreq
->current_idx
-= SMBD_SMB2_NUM_IOV_PER_REQ
;
1295 firsttf
= SMBD_SMB2_IDX_TF_IOV(nreq
,out
,first_idx
);
1296 outhdr_v
= SMBD_SMB2_OUT_HDR_IOV(nreq
);
1297 outhdr
= SMBD_SMB2_OUT_HDR_PTR(nreq
);
1298 /* And end the chain. */
1299 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1301 /* Calculate outgoing credits */
1302 smb2_calculate_credits(req
, nreq
);
1304 if (DEBUGLEVEL
>= 10) {
1305 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1306 (unsigned int)nreq
->current_idx
);
1307 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1308 (unsigned int)nreq
->out
.vector_count
);
1309 print_req_vectors(nreq
);
1313 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1314 * we need to sign/encrypt here with the last/first key we remembered
1316 if (firsttf
->iov_len
== SMB2_TF_HDR_SIZE
) {
1317 status
= smb2_signing_encrypt_pdu(req
->first_key
,
1318 xconn
->smb2
.server
.cipher
,
1320 nreq
->out
.vector_count
- first_idx
);
1321 if (!NT_STATUS_IS_OK(status
)) {
1324 } else if (req
->last_key
.length
> 0) {
1325 status
= smb2_signing_sign_pdu(req
->last_key
,
1328 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
1329 if (!NT_STATUS_IS_OK(status
)) {
1334 nreq
->queue_entry
.mem_ctx
= nreq
;
1335 nreq
->queue_entry
.vector
= nreq
->out
.vector
;
1336 nreq
->queue_entry
.count
= nreq
->out
.vector_count
;
1337 DLIST_ADD_END(xconn
->smb2
.send_queue
, &nreq
->queue_entry
);
1338 xconn
->smb2
.send_queue_len
++;
1340 status
= smbd_smb2_flush_send_queue(xconn
);
1341 if (!NT_STATUS_IS_OK(status
)) {
1345 return NT_STATUS_OK
;
1348 struct smbd_smb2_request_pending_state
{
1349 struct smbd_smb2_send_queue queue_entry
;
1350 uint8_t buf
[NBT_HDR_SIZE
+ SMB2_TF_HDR_SIZE
+ SMB2_HDR_BODY
+ 0x08 + 1];
1351 struct iovec vector
[1 + SMBD_SMB2_NUM_IOV_PER_REQ
];
1354 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
1355 struct tevent_timer
*te
,
1356 struct timeval current_time
,
1357 void *private_data
);
1359 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
1360 struct tevent_req
*subreq
,
1361 uint32_t defer_time
)
1364 struct timeval defer_endtime
;
1365 uint8_t *outhdr
= NULL
;
1368 if (!tevent_req_is_in_progress(subreq
)) {
1370 * This is a performance optimization,
1371 * it avoids one tevent_loop iteration,
1372 * which means we avoid one
1373 * talloc_stackframe_pool/talloc_free pair.
1375 tevent_req_notify_callback(subreq
);
1376 return NT_STATUS_OK
;
1379 req
->subreq
= subreq
;
1382 if (req
->async_te
) {
1383 /* We're already async. */
1384 return NT_STATUS_OK
;
1387 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1388 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1389 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1390 /* We're already async. */
1391 return NT_STATUS_OK
;
1394 if (req
->async_internal
) {
1396 * An SMB2 request implementation wants to handle the request
1397 * asynchronously "internally" while keeping synchronous
1398 * behaviour for the SMB2 request. This means we don't send an
1399 * interim response and we can allow processing of compound SMB2
1400 * requests (cf the subsequent check) for all cases.
1402 return NT_STATUS_OK
;
1405 if (req
->in
.vector_count
> req
->current_idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
) {
1407 * We're trying to go async in a compound request
1408 * chain. This is only allowed for opens that cause an
1409 * oplock break or for the last operation in the
1410 * chain, otherwise it is not allowed. See
1411 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
1413 const uint8_t *inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1415 if (SVAL(inhdr
, SMB2_HDR_OPCODE
) != SMB2_OP_CREATE
) {
1417 * Cancel the outstanding request.
1419 bool ok
= tevent_req_cancel(req
->subreq
);
1421 return NT_STATUS_OK
;
1423 TALLOC_FREE(req
->subreq
);
1424 return smbd_smb2_request_error(req
,
1425 NT_STATUS_INTERNAL_ERROR
);
1429 if (DEBUGLEVEL
>= 10) {
1430 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1431 (unsigned int)req
->current_idx
);
1432 print_req_vectors(req
);
1435 if (req
->current_idx
> 1) {
1437 * We're going async in a compound
1438 * chain after the first request has
1439 * already been processed. Send an
1440 * interim response containing the
1441 * set of replies already generated.
1443 int idx
= req
->current_idx
;
1445 status
= smb2_send_async_interim_response(req
);
1446 if (!NT_STATUS_IS_OK(status
)) {
1449 if (req
->first_key
.length
> 0) {
1450 data_blob_clear_free(&req
->first_key
);
1453 req
->current_idx
= 1;
1456 * Re-arrange the in.vectors to remove what
1459 memmove(&req
->in
.vector
[1],
1460 &req
->in
.vector
[idx
],
1461 sizeof(req
->in
.vector
[0])*(req
->in
.vector_count
- idx
));
1462 req
->in
.vector_count
= 1 + (req
->in
.vector_count
- idx
);
1464 /* Re-arrange the out.vectors to match. */
1465 memmove(&req
->out
.vector
[1],
1466 &req
->out
.vector
[idx
],
1467 sizeof(req
->out
.vector
[0])*(req
->out
.vector_count
- idx
));
1468 req
->out
.vector_count
= 1 + (req
->out
.vector_count
- idx
);
1470 if (req
->in
.vector_count
== 1 + SMBD_SMB2_NUM_IOV_PER_REQ
) {
1472 * We only have one remaining request as
1473 * we've processed everything else.
1474 * This is no longer a compound request.
1476 req
->compound_related
= false;
1477 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1478 flags
= (IVAL(outhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
1479 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
);
1482 if (req
->last_key
.length
> 0) {
1483 data_blob_clear_free(&req
->last_key
);
1487 * smbd_smb2_request_pending_timer() just send a packet
1488 * to the client and doesn't need any impersonation.
1489 * So we use req->xconn->client->raw_ev_ctx instead
1490 * of req->ev_ctx here.
1492 defer_endtime
= timeval_current_ofs_usec(defer_time
);
1493 req
->async_te
= tevent_add_timer(req
->xconn
->client
->raw_ev_ctx
,
1495 smbd_smb2_request_pending_timer
,
1497 if (req
->async_te
== NULL
) {
1498 return NT_STATUS_NO_MEMORY
;
1501 return NT_STATUS_OK
;
1504 static DATA_BLOB
smbd_smb2_signing_key(struct smbXsrv_session
*session
,
1505 struct smbXsrv_connection
*xconn
)
1507 struct smbXsrv_channel_global0
*c
= NULL
;
1509 DATA_BLOB key
= data_blob_null
;
1511 status
= smbXsrv_session_find_channel(session
, xconn
, &c
);
1512 if (NT_STATUS_IS_OK(status
)) {
1513 key
= c
->signing_key
;
1516 if (key
.length
== 0) {
1517 key
= session
->global
->signing_key
;
1523 static NTSTATUS
smb2_get_new_nonce(struct smbXsrv_session
*session
,
1524 uint64_t *new_nonce_high
,
1525 uint64_t *new_nonce_low
)
1527 uint64_t nonce_high
;
1530 session
->nonce_low
+= 1;
1531 if (session
->nonce_low
== 0) {
1532 session
->nonce_low
+= 1;
1533 session
->nonce_high
+= 1;
1537 * CCM and GCM algorithms must never have their
1538 * nonce wrap, or the security of the whole
1539 * communication and the keys is destroyed.
1540 * We must drop the connection once we have
1541 * transfered too much data.
1543 * NOTE: We assume nonces greater than 8 bytes.
1545 if (session
->nonce_high
>= session
->nonce_high_max
) {
1546 return NT_STATUS_ENCRYPTION_FAILED
;
1549 nonce_high
= session
->nonce_high_random
;
1550 nonce_high
+= session
->nonce_high
;
1551 nonce_low
= session
->nonce_low
;
1553 *new_nonce_high
= nonce_high
;
1554 *new_nonce_low
= nonce_low
;
1555 return NT_STATUS_OK
;
1558 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
1559 struct tevent_timer
*te
,
1560 struct timeval current_time
,
1563 struct smbd_smb2_request
*req
=
1564 talloc_get_type_abort(private_data
,
1565 struct smbd_smb2_request
);
1566 struct smbXsrv_connection
*xconn
= req
->xconn
;
1567 struct smbd_smb2_request_pending_state
*state
= NULL
;
1568 uint8_t *outhdr
= NULL
;
1569 const uint8_t *inhdr
= NULL
;
1572 uint8_t *hdr
= NULL
;
1573 uint8_t *body
= NULL
;
1574 uint8_t *dyn
= NULL
;
1576 uint64_t session_id
= 0;
1577 uint64_t message_id
= 0;
1578 uint64_t nonce_high
= 0;
1579 uint64_t nonce_low
= 0;
1580 uint64_t async_id
= 0;
1584 TALLOC_FREE(req
->async_te
);
1586 /* Ensure our final reply matches the interim one. */
1587 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1588 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1589 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1590 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1591 session_id
= BVAL(outhdr
, SMB2_HDR_SESSION_ID
);
1593 async_id
= message_id
; /* keep it simple for now... */
1595 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1596 SBVAL(outhdr
, SMB2_HDR_ASYNC_ID
, async_id
);
1598 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1600 smb2_opcode_name(SVAL(inhdr
, SMB2_HDR_OPCODE
)),
1601 (unsigned long long)async_id
));
1604 * What we send is identical to a smbd_smb2_request_error
1605 * packet with an error status of STATUS_PENDING. Make use
1606 * of this fact sometime when refactoring. JRA.
1609 state
= talloc_zero(req
->xconn
, struct smbd_smb2_request_pending_state
);
1610 if (state
== NULL
) {
1611 smbd_server_connection_terminate(xconn
,
1612 nt_errstr(NT_STATUS_NO_MEMORY
));
1616 tf
= state
->buf
+ NBT_HDR_SIZE
;
1617 tf_len
= SMB2_TF_HDR_SIZE
;
1619 hdr
= tf
+ SMB2_TF_HDR_SIZE
;
1620 body
= hdr
+ SMB2_HDR_BODY
;
1623 if (req
->do_encryption
) {
1624 status
= smb2_get_new_nonce(req
->session
,
1627 if (!NT_STATUS_IS_OK(status
)) {
1628 smbd_server_connection_terminate(xconn
,
1634 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
1635 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
1636 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
1637 SBVAL(tf
, SMB2_TF_SESSION_ID
, session_id
);
1639 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
1640 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1641 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1642 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
1643 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(outhdr
, SMB2_HDR_OPCODE
));
1645 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
);
1646 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1647 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
1648 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
1649 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
1650 BVAL(outhdr
, SMB2_HDR_SESSION_ID
));
1651 memcpy(hdr
+SMB2_HDR_SIGNATURE
,
1652 outhdr
+SMB2_HDR_SIGNATURE
, 16);
1654 SSVAL(body
, 0x00, 0x08 + 1);
1656 SCVAL(body
, 0x02, 0);
1657 SCVAL(body
, 0x03, 0);
1658 SIVAL(body
, 0x04, 0);
1659 /* Match W2K8R2... */
1660 SCVAL(dyn
, 0x00, 0x21);
1662 state
->vector
[0].iov_base
= (void *)state
->buf
;
1663 state
->vector
[0].iov_len
= NBT_HDR_SIZE
;
1665 if (req
->do_encryption
) {
1666 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= tf
;
1667 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= tf_len
;
1669 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
1670 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
1673 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
1674 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
1676 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
1677 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_len
= 8;
1679 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
1680 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_len
= 1;
1682 ok
= smb2_setup_nbt_length(state
->vector
,
1683 1 + SMBD_SMB2_NUM_IOV_PER_REQ
);
1685 smbd_server_connection_terminate(
1686 xconn
, nt_errstr(NT_STATUS_INTERNAL_ERROR
));
1690 /* Ensure we correctly go through crediting. Grant
1691 the credits now, and zero credits on the final
1693 smb2_set_operation_credit(req
->xconn
,
1694 SMBD_SMB2_IN_HDR_IOV(req
),
1695 &state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
]);
1697 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1702 for (i
= 0; i
< ARRAY_SIZE(state
->vector
); i
++) {
1703 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1705 (unsigned int)ARRAY_SIZE(state
->vector
),
1706 (unsigned int)state
->vector
[i
].iov_len
);
1710 if (req
->do_encryption
) {
1711 struct smbXsrv_session
*x
= req
->session
;
1712 DATA_BLOB encryption_key
= x
->global
->encryption_key
;
1714 status
= smb2_signing_encrypt_pdu(encryption_key
,
1715 xconn
->smb2
.server
.cipher
,
1716 &state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
],
1717 SMBD_SMB2_NUM_IOV_PER_REQ
);
1718 if (!NT_STATUS_IS_OK(status
)) {
1719 smbd_server_connection_terminate(xconn
,
1723 } else if (req
->do_signing
) {
1724 struct smbXsrv_session
*x
= req
->session
;
1725 DATA_BLOB signing_key
= smbd_smb2_signing_key(x
, xconn
);
1727 status
= smb2_signing_sign_pdu(signing_key
,
1729 &state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
],
1730 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
1731 if (!NT_STATUS_IS_OK(status
)) {
1732 smbd_server_connection_terminate(xconn
,
1738 state
->queue_entry
.mem_ctx
= state
;
1739 state
->queue_entry
.vector
= state
->vector
;
1740 state
->queue_entry
.count
= ARRAY_SIZE(state
->vector
);
1741 DLIST_ADD_END(xconn
->smb2
.send_queue
, &state
->queue_entry
);
1742 xconn
->smb2
.send_queue_len
++;
1744 status
= smbd_smb2_flush_send_queue(xconn
);
1745 if (!NT_STATUS_IS_OK(status
)) {
1746 smbd_server_connection_terminate(xconn
,
1752 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
1754 struct smbXsrv_connection
*xconn
= req
->xconn
;
1755 struct smbd_smb2_request
*cur
;
1756 const uint8_t *inhdr
;
1758 uint64_t search_message_id
;
1759 uint64_t search_async_id
;
1762 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1764 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1765 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1766 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
1769 * We don't need the request anymore cancel requests never
1772 * We defer the TALLOC_FREE(req) to the caller.
1774 DLIST_REMOVE(xconn
->smb2
.requests
, req
);
1776 for (cur
= xconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
1777 const uint8_t *outhdr
;
1778 uint64_t message_id
;
1781 if (cur
->compound_related
) {
1783 * Never cancel anything in a compound request.
1784 * Way too hard to deal with the result.
1789 outhdr
= SMBD_SMB2_OUT_HDR_PTR(cur
);
1791 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1792 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
1794 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1795 if (search_async_id
== async_id
) {
1796 found_id
= async_id
;
1800 if (search_message_id
== message_id
) {
1801 found_id
= message_id
;
1807 if (cur
&& cur
->subreq
) {
1808 inhdr
= SMBD_SMB2_IN_HDR_PTR(cur
);
1809 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1810 "cancel opcode[%s] mid %llu\n",
1811 smb2_opcode_name(SVAL(inhdr
, SMB2_HDR_OPCODE
)),
1812 (unsigned long long)found_id
));
1813 tevent_req_cancel(cur
->subreq
);
1816 return NT_STATUS_OK
;
1819 /*************************************************************
1820 Ensure an incoming tid is a valid one for us to access.
1821 Change to the associated uid credentials and chdir to the
1822 valid tid directory.
1823 *************************************************************/
1825 static NTSTATUS
smbd_smb2_request_check_tcon(struct smbd_smb2_request
*req
)
1827 const uint8_t *inhdr
;
1830 struct smbXsrv_tcon
*tcon
;
1832 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1836 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1838 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1839 in_tid
= IVAL(inhdr
, SMB2_HDR_TID
);
1841 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1842 in_tid
= req
->last_tid
;
1847 status
= smb2srv_tcon_lookup(req
->session
,
1848 in_tid
, now
, &tcon
);
1849 if (!NT_STATUS_IS_OK(status
)) {
1853 if (!change_to_user(tcon
->compat
, req
->session
->compat
->vuid
)) {
1854 return NT_STATUS_ACCESS_DENIED
;
1858 req
->last_tid
= in_tid
;
1860 return NT_STATUS_OK
;
1863 /*************************************************************
1864 Ensure an incoming session_id is a valid one for us to access.
1865 *************************************************************/
1867 static NTSTATUS
smbd_smb2_request_check_session(struct smbd_smb2_request
*req
)
1869 const uint8_t *inhdr
;
1872 uint64_t in_session_id
;
1873 struct smbXsrv_session
*session
= NULL
;
1874 struct auth_session_info
*session_info
;
1876 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1878 req
->session
= NULL
;
1881 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1883 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1884 in_opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1885 in_session_id
= BVAL(inhdr
, SMB2_HDR_SESSION_ID
);
1887 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1888 in_session_id
= req
->last_session_id
;
1891 req
->last_session_id
= 0;
1893 /* look an existing session up */
1894 switch (in_opcode
) {
1895 case SMB2_OP_SESSSETUP
:
1897 * For a session bind request, we don't have the
1898 * channel set up at this point yet, so we defer
1899 * the verification that the connection belongs
1900 * to the session to the session setup code, which
1901 * can look at the session binding flags.
1903 status
= smb2srv_session_lookup_client(req
->xconn
->client
,
1908 status
= smb2srv_session_lookup_conn(req
->xconn
,
1914 req
->session
= session
;
1915 req
->last_session_id
= in_session_id
;
1917 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
1918 switch (in_opcode
) {
1919 case SMB2_OP_SESSSETUP
:
1920 status
= NT_STATUS_OK
;
1922 case SMB2_OP_LOGOFF
:
1925 case SMB2_OP_CANCEL
:
1926 case SMB2_OP_KEEPALIVE
:
1928 * [MS-SMB2] 3.3.5.2.9 Verifying the Session
1929 * specifies that LOGOFF, CLOSE and (UN)LOCK
1930 * should always be processed even on expired sessions.
1932 * Also see the logic in
1933 * smbd_smb2_request_process_lock().
1935 * The smb2.session.expire2 test shows that
1936 * CANCEL and KEEPALIVE/ECHO should also
1939 status
= NT_STATUS_OK
;
1945 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1946 switch (in_opcode
) {
1948 case SMB2_OP_CREATE
:
1949 case SMB2_OP_GETINFO
:
1950 case SMB2_OP_SETINFO
:
1951 return NT_STATUS_INVALID_HANDLE
;
1954 * Notice the check for
1955 * (session_info == NULL)
1958 status
= NT_STATUS_OK
;
1962 if (!NT_STATUS_IS_OK(status
)) {
1966 session_info
= session
->global
->auth_session_info
;
1967 if (session_info
== NULL
) {
1968 return NT_STATUS_INVALID_HANDLE
;
1971 return NT_STATUS_OK
;
1974 NTSTATUS
smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request
*req
,
1975 uint32_t data_length
)
1977 struct smbXsrv_connection
*xconn
= req
->xconn
;
1978 uint16_t needed_charge
;
1979 uint16_t credit_charge
= 1;
1980 const uint8_t *inhdr
;
1982 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1984 if (xconn
->smb2
.credits
.multicredit
) {
1985 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
1986 credit_charge
= MAX(credit_charge
, 1);
1989 needed_charge
= (data_length
- 1)/ 65536 + 1;
1991 DBGC_DEBUG(DBGC_SMB2_CREDITS
,
1992 "mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1993 (unsigned long long) BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
),
1994 credit_charge
, needed_charge
);
1996 if (needed_charge
> credit_charge
) {
1997 DBGC_WARNING(DBGC_SMB2_CREDITS
,
1998 "CreditCharge too low, given %d, needed %d\n",
1999 credit_charge
, needed_charge
);
2000 return NT_STATUS_INVALID_PARAMETER
;
2003 return NT_STATUS_OK
;
2006 NTSTATUS
smbd_smb2_request_verify_sizes(struct smbd_smb2_request
*req
,
2007 size_t expected_body_size
)
2009 struct iovec
*inhdr_v
;
2010 const uint8_t *inhdr
;
2012 const uint8_t *inbody
;
2014 size_t min_dyn_size
= expected_body_size
& 0x00000001;
2015 int max_idx
= req
->in
.vector_count
- SMBD_SMB2_NUM_IOV_PER_REQ
;
2018 * The following should be checked already.
2020 if (req
->in
.vector_count
< SMBD_SMB2_NUM_IOV_PER_REQ
) {
2021 return NT_STATUS_INTERNAL_ERROR
;
2023 if (req
->current_idx
> max_idx
) {
2024 return NT_STATUS_INTERNAL_ERROR
;
2027 inhdr_v
= SMBD_SMB2_IN_HDR_IOV(req
);
2028 if (inhdr_v
->iov_len
!= SMB2_HDR_BODY
) {
2029 return NT_STATUS_INTERNAL_ERROR
;
2031 if (SMBD_SMB2_IN_BODY_LEN(req
) < 2) {
2032 return NT_STATUS_INTERNAL_ERROR
;
2035 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
2036 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
2040 case SMB2_OP_GETINFO
:
2044 if (req
->smb1req
!= NULL
&& req
->smb1req
->unread_bytes
> 0) {
2045 if (req
->smb1req
->unread_bytes
< min_dyn_size
) {
2046 return NT_STATUS_INVALID_PARAMETER
;
2055 * Now check the expected body size,
2056 * where the last byte might be in the
2059 if (SMBD_SMB2_IN_BODY_LEN(req
) != (expected_body_size
& 0xFFFFFFFE)) {
2060 return NT_STATUS_INVALID_PARAMETER
;
2062 if (SMBD_SMB2_IN_DYN_LEN(req
) < min_dyn_size
) {
2063 return NT_STATUS_INVALID_PARAMETER
;
2066 inbody
= SMBD_SMB2_IN_BODY_PTR(req
);
2068 body_size
= SVAL(inbody
, 0x00);
2069 if (body_size
!= expected_body_size
) {
2070 return NT_STATUS_INVALID_PARAMETER
;
2073 return NT_STATUS_OK
;
2076 bool smbXsrv_is_encrypted(uint8_t encryption_flags
)
2078 return (!(encryption_flags
& SMBXSRV_PROCESSED_UNENCRYPTED_PACKET
)
2080 (encryption_flags
& (SMBXSRV_PROCESSED_ENCRYPTED_PACKET
|
2081 SMBXSRV_ENCRYPTION_DESIRED
|
2082 SMBXSRV_ENCRYPTION_REQUIRED
)));
2085 bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags
)
2087 return ((encryption_flags
& SMBXSRV_PROCESSED_ENCRYPTED_PACKET
) &&
2088 (encryption_flags
& SMBXSRV_PROCESSED_UNENCRYPTED_PACKET
));
2091 /* Set a flag if not already set, return true if set */
2092 bool smbXsrv_set_crypto_flag(uint8_t *flags
, uint8_t flag
)
2094 if ((flag
== 0) || (*flags
& flag
)) {
2103 * Update encryption state tracking flags, this can be used to
2104 * determine whether whether the session or tcon is "encrypted".
2106 static void smb2srv_update_crypto_flags(struct smbd_smb2_request
*req
,
2108 bool *update_session_globalp
,
2109 bool *update_tcon_globalp
)
2111 /* Default: assume unecrypted and unsigned */
2112 struct smbXsrv_session
*session
= req
->session
;
2113 struct smbXsrv_tcon
*tcon
= req
->tcon
;
2114 uint8_t encrypt_flag
= SMBXSRV_PROCESSED_UNENCRYPTED_PACKET
;
2115 uint8_t sign_flag
= SMBXSRV_PROCESSED_UNSIGNED_PACKET
;
2116 bool update_session
= false;
2117 bool update_tcon
= false;
2119 if (req
->was_encrypted
&& req
->do_encryption
) {
2120 encrypt_flag
= SMBXSRV_PROCESSED_ENCRYPTED_PACKET
;
2121 sign_flag
= SMBXSRV_PROCESSED_SIGNED_PACKET
;
2123 /* Unencrypted packet, can be signed */
2124 if (req
->do_signing
) {
2125 sign_flag
= SMBXSRV_PROCESSED_SIGNED_PACKET
;
2126 } else if (opcode
== SMB2_OP_CANCEL
) {
2127 /* Cancel requests are allowed to skip signing */
2128 sign_flag
&= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET
;
2132 update_session
|= smbXsrv_set_crypto_flag(
2133 &session
->global
->encryption_flags
, encrypt_flag
);
2134 update_session
|= smbXsrv_set_crypto_flag(
2135 &session
->global
->signing_flags
, sign_flag
);
2138 update_tcon
|= smbXsrv_set_crypto_flag(
2139 &tcon
->global
->encryption_flags
, encrypt_flag
);
2140 update_tcon
|= smbXsrv_set_crypto_flag(
2141 &tcon
->global
->signing_flags
, sign_flag
);
2144 *update_session_globalp
= update_session
;
2145 *update_tcon_globalp
= update_tcon
;
2149 bool smbXsrv_is_signed(uint8_t signing_flags
)
2152 * Signing is always enabled, so unless we got an unsigned
2153 * packet and at least one signed packet that was not
2154 * encrypted, the session or tcon is "signed".
2156 return (!(signing_flags
& SMBXSRV_PROCESSED_UNSIGNED_PACKET
) &&
2157 (signing_flags
& SMBXSRV_PROCESSED_SIGNED_PACKET
));
2160 bool smbXsrv_is_partially_signed(uint8_t signing_flags
)
2162 return ((signing_flags
& SMBXSRV_PROCESSED_UNSIGNED_PACKET
) &&
2163 (signing_flags
& SMBXSRV_PROCESSED_SIGNED_PACKET
));
2166 static NTSTATUS
smbd_smb2_request_dispatch_update_counts(
2167 struct smbd_smb2_request
*req
,
2170 struct smbXsrv_connection
*xconn
= req
->xconn
;
2171 const uint8_t *inhdr
;
2172 uint16_t channel_sequence
;
2173 uint8_t generation_wrap
= 0;
2176 struct smbXsrv_open
*op
;
2177 bool update_open
= false;
2178 NTSTATUS status
= NT_STATUS_OK
;
2180 SMB_ASSERT(!req
->request_counters_updated
);
2182 if (xconn
->protocol
< PROTOCOL_SMB2_22
) {
2183 return NT_STATUS_OK
;
2186 if (req
->compat_chain_fsp
== NULL
) {
2187 return NT_STATUS_OK
;
2190 op
= req
->compat_chain_fsp
->op
;
2192 return NT_STATUS_OK
;
2195 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
2196 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
2197 channel_sequence
= SVAL(inhdr
, SMB2_HDR_CHANNEL_SEQUENCE
);
2199 cmp
= channel_sequence
- op
->global
->channel_sequence
;
2202 * csn wrap. We need to watch out for long-running
2203 * requests that are still sitting on a previously
2204 * used csn. SMB2_OP_NOTIFY can take VERY long.
2206 generation_wrap
+= 1;
2209 if (abs(cmp
) > INT16_MAX
) {
2211 * [MS-SMB2] 3.3.5.2.10 - Verifying the Channel Sequence Number:
2213 * If the channel sequence number of the request and the one
2214 * known to the server are not equal, the channel sequence
2215 * number and outstanding request counts are only updated
2216 * "... if the unsigned difference using 16-bit arithmetic
2217 * between ChannelSequence and Open.ChannelSequence is less than
2218 * or equal to 0x7FFF ...".
2219 * Otherwise, an error is returned for the modifying
2220 * calls write, set_info, and ioctl.
2222 * There are currently two issues with the description:
2224 * * For the other calls, the document seems to imply
2225 * that processing continues without adapting the
2226 * counters (if the sequence numbers are not equal).
2228 * TODO: This needs clarification!
2230 * * Also, the behaviour if the difference is larger
2231 * than 0x7FFF is not clear. The document seems to
2232 * imply that if such a difference is reached,
2233 * the server starts to ignore the counters or
2234 * in the case of the modifying calls, return errors.
2236 * TODO: This needs clarification!
2238 * At this point Samba tries to be a little more
2239 * clever than the description in the MS-SMB2 document
2240 * by heuristically detecting and properly treating
2241 * a 16 bit overflow of the client-submitted sequence
2244 * If the stored channel sequence number is more than
2245 * 0x7FFF larger than the one from the request, then
2246 * the client-provided sequence number has likely
2247 * overflown. We treat this case as valid instead
2250 * The MS-SMB2 behaviour would be setting cmp = -1.
2255 if (flags
& SMB2_HDR_FLAG_REPLAY_OPERATION
) {
2256 if (cmp
== 0 && op
->pre_request_count
== 0) {
2257 op
->request_count
+= 1;
2258 req
->request_counters_updated
= true;
2259 } else if (cmp
> 0 && op
->pre_request_count
== 0) {
2260 op
->pre_request_count
+= op
->request_count
;
2261 op
->request_count
= 1;
2262 op
->global
->channel_sequence
= channel_sequence
;
2263 op
->global
->channel_generation
+= generation_wrap
;
2265 req
->request_counters_updated
= true;
2266 } else if (modify_call
) {
2267 return NT_STATUS_FILE_NOT_AVAILABLE
;
2271 op
->request_count
+= 1;
2272 req
->request_counters_updated
= true;
2273 } else if (cmp
> 0) {
2274 op
->pre_request_count
+= op
->request_count
;
2275 op
->request_count
= 1;
2276 op
->global
->channel_sequence
= channel_sequence
;
2277 op
->global
->channel_generation
+= generation_wrap
;
2279 req
->request_counters_updated
= true;
2280 } else if (modify_call
) {
2281 return NT_STATUS_FILE_NOT_AVAILABLE
;
2284 req
->channel_generation
= op
->global
->channel_generation
;
2287 status
= smbXsrv_open_update(op
);
2293 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
2295 struct smbXsrv_connection
*xconn
= req
->xconn
;
2296 const struct smbd_smb2_dispatch_table
*call
= NULL
;
2297 const struct iovec
*intf_v
= SMBD_SMB2_IN_TF_IOV(req
);
2298 const uint8_t *inhdr
;
2303 NTSTATUS session_status
;
2304 uint32_t allowed_flags
;
2305 NTSTATUS return_value
;
2306 struct smbXsrv_session
*x
= NULL
;
2307 bool signing_required
= false;
2308 bool encryption_desired
= false;
2309 bool encryption_required
= false;
2311 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
2313 DO_PROFILE_INC(request
);
2315 SMB_ASSERT(!req
->request_counters_updated
);
2317 /* TODO: verify more things */
2319 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
2320 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
2321 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
2322 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
2323 smb2_opcode_name(opcode
),
2324 (unsigned long long)mid
));
2326 if (xconn
->protocol
>= PROTOCOL_SMB2_02
) {
2328 * once the protocol is negotiated
2329 * SMB2_OP_NEGPROT is not allowed anymore
2331 if (opcode
== SMB2_OP_NEGPROT
) {
2332 /* drop the connection */
2333 return NT_STATUS_INVALID_PARAMETER
;
2337 * if the protocol is not negotiated yet
2338 * only SMB2_OP_NEGPROT is allowed.
2340 if (opcode
!= SMB2_OP_NEGPROT
) {
2341 /* drop the connection */
2342 return NT_STATUS_INVALID_PARAMETER
;
2347 * Check if the client provided a valid session id.
2349 * As some command don't require a valid session id
2350 * we defer the check of the session_status
2352 session_status
= smbd_smb2_request_check_session(req
);
2355 signing_required
= x
->global
->signing_flags
& SMBXSRV_SIGNING_REQUIRED
;
2356 encryption_desired
= x
->global
->encryption_flags
& SMBXSRV_ENCRYPTION_DESIRED
;
2357 encryption_required
= x
->global
->encryption_flags
& SMBXSRV_ENCRYPTION_REQUIRED
;
2360 req
->async_internal
= false;
2361 req
->do_signing
= false;
2362 if (opcode
!= SMB2_OP_SESSSETUP
) {
2363 req
->do_encryption
= encryption_desired
;
2365 req
->do_encryption
= false;
2367 req
->was_encrypted
= false;
2368 if (intf_v
->iov_len
== SMB2_TF_HDR_SIZE
) {
2369 const uint8_t *intf
= SMBD_SMB2_IN_TF_PTR(req
);
2370 uint64_t tf_session_id
= BVAL(intf
, SMB2_TF_SESSION_ID
);
2372 if (x
!= NULL
&& x
->global
->session_wire_id
!= tf_session_id
) {
2373 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2374 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
2375 (unsigned long long)x
->global
->session_wire_id
,
2376 (unsigned long long)tf_session_id
));
2378 * TODO: windows allows this...
2379 * should we drop the connection?
2381 * For now we just return ACCESS_DENIED
2382 * (Windows clients never trigger this)
2383 * and wait for an update of [MS-SMB2].
2385 return smbd_smb2_request_error(req
,
2386 NT_STATUS_ACCESS_DENIED
);
2389 req
->was_encrypted
= true;
2390 req
->do_encryption
= true;
2393 if (encryption_required
&& !req
->was_encrypted
) {
2394 req
->do_encryption
= true;
2395 return smbd_smb2_request_error(req
,
2396 NT_STATUS_ACCESS_DENIED
);
2399 call
= smbd_smb2_call(opcode
);
2401 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2404 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
2405 SMB2_HDR_FLAG_SIGNED
|
2407 if (xconn
->protocol
>= PROTOCOL_SMB3_11
) {
2408 allowed_flags
|= SMB2_HDR_FLAG_PRIORITY_MASK
;
2410 if (opcode
== SMB2_OP_NEGPROT
) {
2411 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11
) {
2412 allowed_flags
|= SMB2_HDR_FLAG_PRIORITY_MASK
;
2415 if (opcode
== SMB2_OP_CANCEL
) {
2416 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
2418 if (xconn
->protocol
>= PROTOCOL_SMB2_22
) {
2419 allowed_flags
|= SMB2_HDR_FLAG_REPLAY_OPERATION
;
2421 if ((flags
& ~allowed_flags
) != 0) {
2422 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2425 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
2427 * This check is mostly for giving the correct error code
2428 * for compounded requests.
2430 if (!NT_STATUS_IS_OK(session_status
)) {
2431 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2434 req
->compat_chain_fsp
= NULL
;
2437 if (req
->was_encrypted
) {
2438 signing_required
= false;
2439 } else if (signing_required
|| (flags
& SMB2_HDR_FLAG_SIGNED
)) {
2440 DATA_BLOB signing_key
= data_blob_null
;
2444 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2445 * If the SMB2 header of the SMB2 NEGOTIATE
2446 * request has the SMB2_FLAGS_SIGNED bit set in the
2447 * Flags field, the server MUST fail the request
2448 * with STATUS_INVALID_PARAMETER.
2450 * Microsoft test tool checks this.
2453 if ((opcode
== SMB2_OP_NEGPROT
) &&
2454 (flags
& SMB2_HDR_FLAG_SIGNED
)) {
2455 status
= NT_STATUS_INVALID_PARAMETER
;
2457 status
= NT_STATUS_USER_SESSION_DELETED
;
2459 return smbd_smb2_request_error(req
, status
);
2462 signing_key
= smbd_smb2_signing_key(x
, xconn
);
2465 * If we have a signing key, we should
2468 if (signing_key
.length
> 0) {
2469 req
->do_signing
= true;
2472 status
= smb2_signing_check_pdu(signing_key
,
2474 SMBD_SMB2_IN_HDR_IOV(req
),
2475 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2476 if (!NT_STATUS_IS_OK(status
)) {
2477 return smbd_smb2_request_error(req
, status
);
2481 * Now that we know the request was correctly signed
2482 * we have to sign the response too.
2484 req
->do_signing
= true;
2486 if (!NT_STATUS_IS_OK(session_status
)) {
2487 return smbd_smb2_request_error(req
, session_status
);
2489 } else if (opcode
== SMB2_OP_CANCEL
) {
2490 /* Cancel requests are allowed to skip the signing */
2491 } else if (signing_required
) {
2493 * If signing is required we try to sign
2494 * a possible error response
2496 req
->do_signing
= true;
2497 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
2500 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
2501 req
->compound_related
= true;
2504 if (call
->need_session
) {
2505 if (!NT_STATUS_IS_OK(session_status
)) {
2506 return smbd_smb2_request_error(req
, session_status
);
2510 if (call
->need_tcon
) {
2511 SMB_ASSERT(call
->need_session
);
2514 * This call needs to be run as user.
2516 * smbd_smb2_request_check_tcon()
2517 * calls change_to_user() on success.
2518 * Which implies set_current_user_info()
2519 * and chdir_current_service().
2521 status
= smbd_smb2_request_check_tcon(req
);
2522 if (!NT_STATUS_IS_OK(status
)) {
2523 return smbd_smb2_request_error(req
, status
);
2525 if (req
->tcon
->global
->encryption_flags
& SMBXSRV_ENCRYPTION_DESIRED
) {
2526 encryption_desired
= true;
2528 if (req
->tcon
->global
->encryption_flags
& SMBXSRV_ENCRYPTION_REQUIRED
) {
2529 encryption_required
= true;
2531 if (encryption_required
&& !req
->was_encrypted
) {
2532 req
->do_encryption
= true;
2533 return smbd_smb2_request_error(req
,
2534 NT_STATUS_ACCESS_DENIED
);
2535 } else if (encryption_desired
) {
2536 req
->do_encryption
= true;
2538 } else if (call
->need_session
) {
2539 struct auth_session_info
*session_info
= NULL
;
2542 * Unless we also have need_tcon (see above),
2543 * we still need to call set_current_user_info().
2546 session_info
= req
->session
->global
->auth_session_info
;
2547 if (session_info
== NULL
) {
2548 return NT_STATUS_INVALID_HANDLE
;
2551 set_current_user_info(session_info
->unix_info
->sanitized_username
,
2552 session_info
->unix_info
->unix_name
,
2553 session_info
->info
->domain_name
);
2557 bool update_session_global
= false;
2558 bool update_tcon_global
= false;
2560 smb2srv_update_crypto_flags(req
, opcode
,
2561 &update_session_global
,
2562 &update_tcon_global
);
2564 if (update_session_global
) {
2565 status
= smbXsrv_session_update(x
);
2566 if (!NT_STATUS_IS_OK(status
)) {
2567 return smbd_smb2_request_error(req
, status
);
2570 if (update_tcon_global
) {
2571 status
= smbXsrv_tcon_update(req
->tcon
);
2572 if (!NT_STATUS_IS_OK(status
)) {
2573 return smbd_smb2_request_error(req
, status
);
2578 if (call
->fileid_ofs
!= 0) {
2579 size_t needed
= call
->fileid_ofs
+ 16;
2580 const uint8_t *body
= SMBD_SMB2_IN_BODY_PTR(req
);
2581 size_t body_size
= SMBD_SMB2_IN_BODY_LEN(req
);
2582 uint64_t file_id_persistent
;
2583 uint64_t file_id_volatile
;
2584 struct files_struct
*fsp
;
2586 SMB_ASSERT(call
->need_tcon
);
2588 if (needed
> body_size
) {
2589 return smbd_smb2_request_error(req
,
2590 NT_STATUS_INVALID_PARAMETER
);
2593 file_id_persistent
= BVAL(body
, call
->fileid_ofs
+ 0);
2594 file_id_volatile
= BVAL(body
, call
->fileid_ofs
+ 8);
2596 fsp
= file_fsp_smb2(req
, file_id_persistent
, file_id_volatile
);
2598 if (!call
->allow_invalid_fileid
) {
2599 return smbd_smb2_request_error(req
,
2600 NT_STATUS_FILE_CLOSED
);
2603 if (file_id_persistent
!= UINT64_MAX
) {
2604 return smbd_smb2_request_error(req
,
2605 NT_STATUS_FILE_CLOSED
);
2607 if (file_id_volatile
!= UINT64_MAX
) {
2608 return smbd_smb2_request_error(req
,
2609 NT_STATUS_FILE_CLOSED
);
2614 status
= smbd_smb2_request_dispatch_update_counts(req
, call
->modify
);
2615 if (!NT_STATUS_IS_OK(status
)) {
2616 return smbd_smb2_request_error(req
, status
);
2619 if (call
->as_root
) {
2620 SMB_ASSERT(call
->fileid_ofs
== 0);
2621 /* This call needs to be run as root */
2622 change_to_root_user();
2623 req
->ev_ctx
= req
->sconn
->root_ev_ctx
;
2625 SMB_ASSERT(call
->need_tcon
);
2626 req
->ev_ctx
= req
->tcon
->compat
->user_ev_ctx
;
2629 #define _INBYTES(_r) \
2630 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
2633 case SMB2_OP_NEGPROT
:
2634 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot
, profile_p
,
2635 req
->profile
, _INBYTES(req
));
2636 return_value
= smbd_smb2_request_process_negprot(req
);
2639 case SMB2_OP_SESSSETUP
:
2640 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup
, profile_p
,
2641 req
->profile
, _INBYTES(req
));
2642 return_value
= smbd_smb2_request_process_sesssetup(req
);
2645 case SMB2_OP_LOGOFF
:
2646 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff
, profile_p
,
2647 req
->profile
, _INBYTES(req
));
2648 return_value
= smbd_smb2_request_process_logoff(req
);
2652 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon
, profile_p
,
2653 req
->profile
, _INBYTES(req
));
2654 return_value
= smbd_smb2_request_process_tcon(req
);
2658 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis
, profile_p
,
2659 req
->profile
, _INBYTES(req
));
2660 return_value
= smbd_smb2_request_process_tdis(req
);
2663 case SMB2_OP_CREATE
:
2664 if (req
->subreq
== NULL
) {
2665 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create
, profile_p
,
2666 req
->profile
, _INBYTES(req
));
2668 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req
->profile
);
2670 return_value
= smbd_smb2_request_process_create(req
);
2674 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close
, profile_p
,
2675 req
->profile
, _INBYTES(req
));
2676 return_value
= smbd_smb2_request_process_close(req
);
2680 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush
, profile_p
,
2681 req
->profile
, _INBYTES(req
));
2682 return_value
= smbd_smb2_request_process_flush(req
);
2686 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read
, profile_p
,
2687 req
->profile
, _INBYTES(req
));
2688 return_value
= smbd_smb2_request_process_read(req
);
2692 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write
, profile_p
,
2693 req
->profile
, _INBYTES(req
));
2694 return_value
= smbd_smb2_request_process_write(req
);
2698 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock
, profile_p
,
2699 req
->profile
, _INBYTES(req
));
2700 return_value
= smbd_smb2_request_process_lock(req
);
2704 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl
, profile_p
,
2705 req
->profile
, _INBYTES(req
));
2706 return_value
= smbd_smb2_request_process_ioctl(req
);
2709 case SMB2_OP_CANCEL
:
2710 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel
, profile_p
,
2711 req
->profile
, _INBYTES(req
));
2712 return_value
= smbd_smb2_request_process_cancel(req
);
2713 SMBPROFILE_IOBYTES_ASYNC_END(req
->profile
, 0);
2716 * We don't need the request anymore cancel requests never
2719 * smbd_smb2_request_process_cancel() already called
2720 * DLIST_REMOVE(xconn->smb2.requests, req);
2726 case SMB2_OP_KEEPALIVE
:
2727 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive
, profile_p
,
2728 req
->profile
, _INBYTES(req
));
2729 return_value
= smbd_smb2_request_process_keepalive(req
);
2732 case SMB2_OP_QUERY_DIRECTORY
:
2733 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find
, profile_p
,
2734 req
->profile
, _INBYTES(req
));
2735 return_value
= smbd_smb2_request_process_query_directory(req
);
2738 case SMB2_OP_NOTIFY
:
2739 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify
, profile_p
,
2740 req
->profile
, _INBYTES(req
));
2741 return_value
= smbd_smb2_request_process_notify(req
);
2744 case SMB2_OP_GETINFO
:
2745 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo
, profile_p
,
2746 req
->profile
, _INBYTES(req
));
2747 return_value
= smbd_smb2_request_process_getinfo(req
);
2750 case SMB2_OP_SETINFO
:
2751 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo
, profile_p
,
2752 req
->profile
, _INBYTES(req
));
2753 return_value
= smbd_smb2_request_process_setinfo(req
);
2757 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break
, profile_p
,
2758 req
->profile
, _INBYTES(req
));
2759 return_value
= smbd_smb2_request_process_break(req
);
2763 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2766 return return_value
;
2769 static void smbd_smb2_request_reply_update_counts(struct smbd_smb2_request
*req
)
2771 struct smbXsrv_connection
*xconn
= req
->xconn
;
2772 const uint8_t *inhdr
;
2773 uint16_t channel_sequence
;
2774 struct smbXsrv_open
*op
;
2776 if (!req
->request_counters_updated
) {
2780 req
->request_counters_updated
= false;
2782 if (xconn
->protocol
< PROTOCOL_SMB2_22
) {
2786 if (req
->compat_chain_fsp
== NULL
) {
2790 op
= req
->compat_chain_fsp
->op
;
2795 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
2796 channel_sequence
= SVAL(inhdr
, SMB2_HDR_CHANNEL_SEQUENCE
);
2798 if ((op
->global
->channel_sequence
== channel_sequence
) &&
2799 (op
->global
->channel_generation
== req
->channel_generation
)) {
2800 SMB_ASSERT(op
->request_count
> 0);
2801 op
->request_count
-= 1;
2803 SMB_ASSERT(op
->pre_request_count
> 0);
2804 op
->pre_request_count
-= 1;
2808 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
2810 struct smbXsrv_connection
*xconn
= req
->xconn
;
2812 struct iovec
*firsttf
= SMBD_SMB2_IDX_TF_IOV(req
,out
,first_idx
);
2813 struct iovec
*outhdr
= SMBD_SMB2_OUT_HDR_IOV(req
);
2814 struct iovec
*outdyn
= SMBD_SMB2_OUT_DYN_IOV(req
);
2819 TALLOC_FREE(req
->async_te
);
2821 /* MS-SMB2: 3.3.4.1 Sending Any Outgoing Message */
2822 smbd_smb2_request_reply_update_counts(req
);
2824 if (req
->do_encryption
&&
2825 (firsttf
->iov_len
== 0) &&
2826 (req
->first_key
.length
== 0) &&
2827 (req
->session
!= NULL
) &&
2828 (req
->session
->global
->encryption_key
.length
!= 0))
2830 DATA_BLOB encryption_key
= req
->session
->global
->encryption_key
;
2832 uint64_t session_id
= req
->session
->global
->session_wire_id
;
2833 uint64_t nonce_high
;
2836 status
= smb2_get_new_nonce(req
->session
,
2839 if (!NT_STATUS_IS_OK(status
)) {
2844 * We need to place the SMB2_TRANSFORM header before the
2849 * we need to remember the encryption key
2850 * and defer the signing/encryption until
2851 * we are sure that we do not change
2854 req
->first_key
= data_blob_dup_talloc(req
, encryption_key
);
2855 if (req
->first_key
.data
== NULL
) {
2856 return NT_STATUS_NO_MEMORY
;
2859 tf
= talloc_zero_array(req
, uint8_t,
2862 return NT_STATUS_NO_MEMORY
;
2865 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
2866 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
2867 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
2868 SBVAL(tf
, SMB2_TF_SESSION_ID
, session_id
);
2870 firsttf
->iov_base
= (void *)tf
;
2871 firsttf
->iov_len
= SMB2_TF_HDR_SIZE
;
2874 if ((req
->current_idx
> SMBD_SMB2_NUM_IOV_PER_REQ
) &&
2875 (req
->last_key
.length
> 0) &&
2876 (firsttf
->iov_len
== 0))
2878 int last_idx
= req
->current_idx
- SMBD_SMB2_NUM_IOV_PER_REQ
;
2879 struct iovec
*lasthdr
= SMBD_SMB2_IDX_HDR_IOV(req
,out
,last_idx
);
2882 * As we are sure the header of the last request in the
2883 * compound chain will not change, we can to sign here
2884 * with the last signing key we remembered.
2886 status
= smb2_signing_sign_pdu(req
->last_key
,
2889 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2890 if (!NT_STATUS_IS_OK(status
)) {
2894 if (req
->last_key
.length
> 0) {
2895 data_blob_clear_free(&req
->last_key
);
2898 SMBPROFILE_IOBYTES_ASYNC_END(req
->profile
,
2899 iov_buflen(outhdr
, SMBD_SMB2_NUM_IOV_PER_REQ
-1));
2901 req
->current_idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
;
2903 if (req
->current_idx
< req
->out
.vector_count
) {
2905 * We must process the remaining compound
2906 * SMB2 requests before any new incoming SMB2
2907 * requests. This is because incoming SMB2
2908 * requests may include a cancel for a
2909 * compound request we haven't processed
2912 struct tevent_immediate
*im
= tevent_create_immediate(req
);
2914 return NT_STATUS_NO_MEMORY
;
2917 if (req
->do_signing
&& firsttf
->iov_len
== 0) {
2918 struct smbXsrv_session
*x
= req
->session
;
2919 DATA_BLOB signing_key
= smbd_smb2_signing_key(x
, xconn
);
2922 * we need to remember the signing key
2923 * and defer the signing until
2924 * we are sure that we do not change
2927 req
->last_key
= data_blob_dup_talloc(req
, signing_key
);
2928 if (req
->last_key
.data
== NULL
) {
2929 return NT_STATUS_NO_MEMORY
;
2934 * smbd_smb2_request_dispatch() will redo the impersonation.
2935 * So we use req->xconn->client->raw_ev_ctx instead
2936 * of req->ev_ctx here.
2938 tevent_schedule_immediate(im
,
2939 req
->xconn
->client
->raw_ev_ctx
,
2940 smbd_smb2_request_dispatch_immediate
,
2942 return NT_STATUS_OK
;
2945 if (req
->compound_related
) {
2946 req
->compound_related
= false;
2949 ok
= smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
2951 return NT_STATUS_INVALID_PARAMETER_MIX
;
2954 /* Set credit for these operations (zero credits if this
2955 is a final reply for an async operation). */
2956 smb2_calculate_credits(req
, req
);
2959 * now check if we need to sign the current response
2961 if (firsttf
->iov_len
== SMB2_TF_HDR_SIZE
) {
2962 status
= smb2_signing_encrypt_pdu(req
->first_key
,
2963 xconn
->smb2
.server
.cipher
,
2965 req
->out
.vector_count
- first_idx
);
2966 if (!NT_STATUS_IS_OK(status
)) {
2969 } else if (req
->do_signing
) {
2970 struct smbXsrv_session
*x
= req
->session
;
2971 DATA_BLOB signing_key
= smbd_smb2_signing_key(x
, xconn
);
2973 status
= smb2_signing_sign_pdu(signing_key
,
2976 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2977 if (!NT_STATUS_IS_OK(status
)) {
2981 if (req
->first_key
.length
> 0) {
2982 data_blob_clear_free(&req
->first_key
);
2985 if (req
->preauth
!= NULL
) {
2986 struct hc_sha512state sctx
;
2989 samba_SHA512_Init(&sctx
);
2990 samba_SHA512_Update(&sctx
, req
->preauth
->sha512_value
,
2991 sizeof(req
->preauth
->sha512_value
));
2992 for (i
= 1; i
< req
->in
.vector_count
; i
++) {
2993 samba_SHA512_Update(&sctx
,
2994 req
->in
.vector
[i
].iov_base
,
2995 req
->in
.vector
[i
].iov_len
);
2997 samba_SHA512_Final(req
->preauth
->sha512_value
, &sctx
);
2999 samba_SHA512_Init(&sctx
);
3000 samba_SHA512_Update(&sctx
, req
->preauth
->sha512_value
,
3001 sizeof(req
->preauth
->sha512_value
));
3002 for (i
= 1; i
< req
->out
.vector_count
; i
++) {
3003 samba_SHA512_Update(&sctx
,
3004 req
->out
.vector
[i
].iov_base
,
3005 req
->out
.vector
[i
].iov_len
);
3007 samba_SHA512_Final(req
->preauth
->sha512_value
, &sctx
);
3009 req
->preauth
= NULL
;
3012 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
3013 if (req
->out
.vector_count
< (2*SMBD_SMB2_NUM_IOV_PER_REQ
) &&
3014 outdyn
->iov_base
== NULL
&& outdyn
->iov_len
!= 0) {
3015 /* Dynamic part is NULL. Chop it off,
3016 We're going to send it via sendfile. */
3017 req
->out
.vector_count
-= 1;
3021 * We're done with this request -
3022 * move it off the "being processed" queue.
3024 DLIST_REMOVE(xconn
->smb2
.requests
, req
);
3026 req
->queue_entry
.mem_ctx
= req
;
3027 req
->queue_entry
.vector
= req
->out
.vector
;
3028 req
->queue_entry
.count
= req
->out
.vector_count
;
3029 DLIST_ADD_END(xconn
->smb2
.send_queue
, &req
->queue_entry
);
3030 xconn
->smb2
.send_queue_len
++;
3032 status
= smbd_smb2_flush_send_queue(xconn
);
3033 if (!NT_STATUS_IS_OK(status
)) {
3037 return NT_STATUS_OK
;
3040 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbXsrv_connection
*xconn
);
3042 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
3043 struct tevent_immediate
*im
,
3046 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
3047 struct smbd_smb2_request
);
3048 struct smbXsrv_connection
*xconn
= req
->xconn
;
3053 if (DEBUGLEVEL
>= 10) {
3054 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
3055 req
->current_idx
, req
->in
.vector_count
));
3056 print_req_vectors(req
);
3059 status
= smbd_smb2_request_dispatch(req
);
3060 if (!NT_STATUS_IS_OK(status
)) {
3061 smbd_server_connection_terminate(xconn
, nt_errstr(status
));
3065 status
= smbd_smb2_request_next_incoming(xconn
);
3066 if (!NT_STATUS_IS_OK(status
)) {
3067 smbd_server_connection_terminate(xconn
, nt_errstr(status
));
3072 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
3074 DATA_BLOB body
, DATA_BLOB
*dyn
,
3075 const char *location
)
3078 struct iovec
*outbody_v
;
3079 struct iovec
*outdyn_v
;
3080 uint32_t next_command_ofs
;
3082 DEBUG(10,("smbd_smb2_request_done_ex: "
3083 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
3084 req
->current_idx
, nt_errstr(status
), (unsigned int)body
.length
,
3086 (unsigned int)(dyn
? dyn
->length
: 0),
3089 if (body
.length
< 2) {
3090 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
3093 if ((body
.length
% 2) != 0) {
3094 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
3097 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
3098 outbody_v
= SMBD_SMB2_OUT_BODY_IOV(req
);
3099 outdyn_v
= SMBD_SMB2_OUT_DYN_IOV(req
);
3101 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
3102 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
3104 outbody_v
->iov_base
= (void *)body
.data
;
3105 outbody_v
->iov_len
= body
.length
;
3108 outdyn_v
->iov_base
= (void *)dyn
->data
;
3109 outdyn_v
->iov_len
= dyn
->length
;
3111 outdyn_v
->iov_base
= NULL
;
3112 outdyn_v
->iov_len
= 0;
3116 * See if we need to recalculate the offset to the next response
3118 * Note that all responses may require padding (including the very last
3121 if (req
->out
.vector_count
>= (2 * SMBD_SMB2_NUM_IOV_PER_REQ
)) {
3122 next_command_ofs
= SMB2_HDR_BODY
;
3123 next_command_ofs
+= SMBD_SMB2_OUT_BODY_LEN(req
);
3124 next_command_ofs
+= SMBD_SMB2_OUT_DYN_LEN(req
);
3127 if ((next_command_ofs
% 8) != 0) {
3128 size_t pad_size
= 8 - (next_command_ofs
% 8);
3129 if (SMBD_SMB2_OUT_DYN_LEN(req
) == 0) {
3131 * if the dyn buffer is empty
3132 * we can use it to add padding
3136 pad
= talloc_zero_array(req
,
3139 return smbd_smb2_request_error(req
,
3140 NT_STATUS_NO_MEMORY
);
3143 outdyn_v
->iov_base
= (void *)pad
;
3144 outdyn_v
->iov_len
= pad_size
;
3147 * For now we copy the dynamic buffer
3148 * and add the padding to the new buffer
3155 old_size
= SMBD_SMB2_OUT_DYN_LEN(req
);
3156 old_dyn
= SMBD_SMB2_OUT_DYN_PTR(req
);
3158 new_size
= old_size
+ pad_size
;
3159 new_dyn
= talloc_zero_array(req
,
3161 if (new_dyn
== NULL
) {
3162 return smbd_smb2_request_error(req
,
3163 NT_STATUS_NO_MEMORY
);
3166 memcpy(new_dyn
, old_dyn
, old_size
);
3167 memset(new_dyn
+ old_size
, 0, pad_size
);
3169 outdyn_v
->iov_base
= (void *)new_dyn
;
3170 outdyn_v
->iov_len
= new_size
;
3172 next_command_ofs
+= pad_size
;
3175 if ((req
->current_idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
) >= req
->out
.vector_count
) {
3176 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
3178 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
3180 return smbd_smb2_request_reply(req
);
3183 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
3186 const char *location
)
3188 struct smbXsrv_connection
*xconn
= req
->xconn
;
3191 uint8_t *outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
3192 size_t unread_bytes
= smbd_smb2_unread_bytes(req
);
3194 DBG_NOTICE("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| "
3195 "at %s\n", req
->current_idx
, nt_errstr(status
),
3196 info
? " +info" : "", location
);
3199 /* Recvfile error. Drain incoming socket. */
3203 ret
= drain_socket(xconn
->transport
.sock
, unread_bytes
);
3204 if (ret
!= unread_bytes
) {
3208 error
= NT_STATUS_IO_DEVICE_ERROR
;
3210 error
= map_nt_error_from_unix_common(errno
);
3213 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
3214 "ret[%u] errno[%d] => %s\n",
3215 (unsigned)unread_bytes
,
3216 (unsigned)ret
, errno
, nt_errstr(error
)));
3221 body
.data
= outhdr
+ SMB2_HDR_BODY
;
3223 SSVAL(body
.data
, 0, 9);
3226 SIVAL(body
.data
, 0x04, info
->length
);
3228 /* Allocated size of req->out.vector[i].iov_base
3229 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
3230 * 1 byte without having to do an alloc.
3233 info
->data
= ((uint8_t *)outhdr
) +
3234 OUTVEC_ALLOC_SIZE
- 1;
3236 SCVAL(info
->data
, 0, 0);
3240 * Note: Even if there is an error, continue to process the request.
3244 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
3248 struct smbd_smb2_send_break_state
{
3249 struct smbd_smb2_send_queue queue_entry
;
3250 uint8_t nbt_hdr
[NBT_HDR_SIZE
];
3251 uint8_t tf
[SMB2_TF_HDR_SIZE
];
3252 uint8_t hdr
[SMB2_HDR_BODY
];
3253 struct iovec vector
[1+SMBD_SMB2_NUM_IOV_PER_REQ
];
3257 static NTSTATUS
smbd_smb2_send_break(struct smbXsrv_connection
*xconn
,
3258 struct smbXsrv_session
*session
,
3259 struct smbXsrv_tcon
*tcon
,
3260 const uint8_t *body
,
3263 struct smbd_smb2_send_break_state
*state
;
3264 bool do_encryption
= false;
3265 uint64_t session_wire_id
= 0;
3266 uint64_t nonce_high
= 0;
3267 uint64_t nonce_low
= 0;
3272 if (session
!= NULL
) {
3273 session_wire_id
= session
->global
->session_wire_id
;
3274 do_encryption
= session
->global
->encryption_flags
& SMBXSRV_ENCRYPTION_DESIRED
;
3275 if (tcon
->global
->encryption_flags
& SMBXSRV_ENCRYPTION_DESIRED
) {
3276 do_encryption
= true;
3280 statelen
= offsetof(struct smbd_smb2_send_break_state
, body
) +
3283 state
= talloc_zero_size(xconn
, statelen
);
3284 if (state
== NULL
) {
3285 return NT_STATUS_NO_MEMORY
;
3287 talloc_set_name_const(state
, "struct smbd_smb2_send_break_state");
3289 if (do_encryption
) {
3290 status
= smb2_get_new_nonce(session
,
3293 if (!NT_STATUS_IS_OK(status
)) {
3298 SIVAL(state
->tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
3299 SBVAL(state
->tf
, SMB2_TF_NONCE
+0, nonce_low
);
3300 SBVAL(state
->tf
, SMB2_TF_NONCE
+8, nonce_high
);
3301 SBVAL(state
->tf
, SMB2_TF_SESSION_ID
, session_wire_id
);
3303 SIVAL(state
->hdr
, 0, SMB2_MAGIC
);
3304 SSVAL(state
->hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
3305 SSVAL(state
->hdr
, SMB2_HDR_EPOCH
, 0);
3306 SIVAL(state
->hdr
, SMB2_HDR_STATUS
, 0);
3307 SSVAL(state
->hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
3308 SSVAL(state
->hdr
, SMB2_HDR_CREDIT
, 0);
3309 SIVAL(state
->hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
3310 SIVAL(state
->hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
3311 SBVAL(state
->hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
3312 SIVAL(state
->hdr
, SMB2_HDR_PID
, 0);
3313 SIVAL(state
->hdr
, SMB2_HDR_TID
, 0);
3314 SBVAL(state
->hdr
, SMB2_HDR_SESSION_ID
, 0);
3315 memset(state
->hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
3317 state
->vector
[0] = (struct iovec
) {
3318 .iov_base
= state
->nbt_hdr
,
3319 .iov_len
= sizeof(state
->nbt_hdr
)
3322 if (do_encryption
) {
3323 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
] = (struct iovec
) {
3324 .iov_base
= state
->tf
,
3325 .iov_len
= sizeof(state
->tf
)
3328 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
] = (struct iovec
) {
3334 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
] = (struct iovec
) {
3335 .iov_base
= state
->hdr
,
3336 .iov_len
= sizeof(state
->hdr
)
3339 memcpy(state
->body
, body
, body_len
);
3341 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
] = (struct iovec
) {
3342 .iov_base
= state
->body
,
3343 .iov_len
= body_len
/* no sizeof(state->body) .. :-) */
3347 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
3350 ok
= smb2_setup_nbt_length(state
->vector
,
3351 1 + SMBD_SMB2_NUM_IOV_PER_REQ
);
3353 return NT_STATUS_INVALID_PARAMETER_MIX
;
3356 if (do_encryption
) {
3357 DATA_BLOB encryption_key
= session
->global
->encryption_key
;
3359 status
= smb2_signing_encrypt_pdu(encryption_key
,
3360 xconn
->smb2
.server
.cipher
,
3361 &state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
],
3362 SMBD_SMB2_NUM_IOV_PER_REQ
);
3363 if (!NT_STATUS_IS_OK(status
)) {
3368 state
->queue_entry
.mem_ctx
= state
;
3369 state
->queue_entry
.vector
= state
->vector
;
3370 state
->queue_entry
.count
= ARRAY_SIZE(state
->vector
);
3371 DLIST_ADD_END(xconn
->smb2
.send_queue
, &state
->queue_entry
);
3372 xconn
->smb2
.send_queue_len
++;
3374 status
= smbd_smb2_flush_send_queue(xconn
);
3375 if (!NT_STATUS_IS_OK(status
)) {
3379 return NT_STATUS_OK
;
3382 NTSTATUS
smbd_smb2_send_oplock_break(struct smbXsrv_connection
*xconn
,
3383 struct smbXsrv_session
*session
,
3384 struct smbXsrv_tcon
*tcon
,
3385 struct smbXsrv_open
*op
,
3386 uint8_t oplock_level
)
3390 SSVAL(body
, 0x00, sizeof(body
));
3391 SCVAL(body
, 0x02, oplock_level
);
3392 SCVAL(body
, 0x03, 0); /* reserved */
3393 SIVAL(body
, 0x04, 0); /* reserved */
3394 SBVAL(body
, 0x08, op
->global
->open_persistent_id
);
3395 SBVAL(body
, 0x10, op
->global
->open_volatile_id
);
3397 return smbd_smb2_send_break(xconn
, NULL
, NULL
, body
, sizeof(body
));
3400 NTSTATUS
smbd_smb2_send_lease_break(struct smbXsrv_connection
*xconn
,
3402 uint32_t lease_flags
,
3403 struct smb2_lease_key
*lease_key
,
3404 uint32_t current_lease_state
,
3405 uint32_t new_lease_state
)
3409 SSVAL(body
, 0x00, sizeof(body
));
3410 SSVAL(body
, 0x02, new_epoch
);
3411 SIVAL(body
, 0x04, lease_flags
);
3412 SBVAL(body
, 0x08, lease_key
->data
[0]);
3413 SBVAL(body
, 0x10, lease_key
->data
[1]);
3414 SIVAL(body
, 0x18, current_lease_state
);
3415 SIVAL(body
, 0x1c, new_lease_state
);
3416 SIVAL(body
, 0x20, 0); /* BreakReason, MUST be 0 */
3417 SIVAL(body
, 0x24, 0); /* AccessMaskHint, MUST be 0 */
3418 SIVAL(body
, 0x28, 0); /* ShareMaskHint, MUST be 0 */
3420 return smbd_smb2_send_break(xconn
, NULL
, NULL
, body
, sizeof(body
));
3423 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state
*state
)
3427 uint64_t file_id_persistent
;
3428 uint64_t file_id_volatile
;
3429 struct smbXsrv_open
*op
= NULL
;
3430 struct files_struct
*fsp
= NULL
;
3431 const uint8_t *body
= NULL
;
3434 * This is only called with a pktbuf
3435 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
3439 if (IVAL(state
->pktbuf
, 0) == SMB2_TF_MAGIC
) {
3440 /* Transform header. Cannot recvfile. */
3443 if (IVAL(state
->pktbuf
, 0) != SMB2_MAGIC
) {
3444 /* Not SMB2. Normal error path will cope. */
3447 if (SVAL(state
->pktbuf
, 4) != SMB2_HDR_BODY
) {
3448 /* Not SMB2. Normal error path will cope. */
3451 if (SVAL(state
->pktbuf
, SMB2_HDR_OPCODE
) != SMB2_OP_WRITE
) {
3452 /* Needs to be a WRITE. */
3455 if (IVAL(state
->pktbuf
, SMB2_HDR_NEXT_COMMAND
) != 0) {
3456 /* Chained. Cannot recvfile. */
3459 flags
= IVAL(state
->pktbuf
, SMB2_HDR_FLAGS
);
3460 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
3461 /* Chained. Cannot recvfile. */
3464 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
3465 /* Signed. Cannot recvfile. */
3469 body
= &state
->pktbuf
[SMB2_HDR_BODY
];
3471 file_id_persistent
= BVAL(body
, 0x10);
3472 file_id_volatile
= BVAL(body
, 0x18);
3474 status
= smb2srv_open_lookup(state
->req
->xconn
,
3479 if (!NT_STATUS_IS_OK(status
)) {
3487 if (fsp
->conn
== NULL
) {
3491 if (IS_IPC(fsp
->conn
)) {
3494 if (IS_PRINT(fsp
->conn
)) {
3498 DEBUG(10,("Doing recvfile write len = %u\n",
3499 (unsigned int)(state
->pktfull
- state
->pktlen
)));
3504 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbXsrv_connection
*xconn
)
3506 struct smbd_server_connection
*sconn
= xconn
->client
->sconn
;
3507 struct smbd_smb2_request_read_state
*state
= &xconn
->smb2
.request_read_state
;
3508 size_t max_send_queue_len
;
3509 size_t cur_send_queue_len
;
3511 if (!NT_STATUS_IS_OK(xconn
->transport
.status
)) {
3513 * we're not supposed to do any io
3515 return NT_STATUS_OK
;
3518 if (state
->req
!= NULL
) {
3520 * if there is already a tstream_readv_pdu
3521 * pending, we are done.
3523 return NT_STATUS_OK
;
3526 max_send_queue_len
= MAX(1, xconn
->smb2
.credits
.max
/16);
3527 cur_send_queue_len
= xconn
->smb2
.send_queue_len
;
3529 if (cur_send_queue_len
> max_send_queue_len
) {
3531 * if we have a lot of requests to send,
3532 * we wait until they are on the wire until we
3533 * ask for the next request.
3535 return NT_STATUS_OK
;
3538 /* ask for the next request */
3539 ZERO_STRUCTP(state
);
3540 state
->req
= smbd_smb2_request_allocate(xconn
);
3541 if (state
->req
== NULL
) {
3542 return NT_STATUS_NO_MEMORY
;
3544 state
->req
->sconn
= sconn
;
3545 state
->req
->xconn
= xconn
;
3546 state
->min_recv_size
= lp_min_receive_file_size();
3548 TEVENT_FD_READABLE(xconn
->transport
.fde
);
3550 return NT_STATUS_OK
;
3553 void smbd_smb2_process_negprot(struct smbXsrv_connection
*xconn
,
3554 uint64_t expected_seq_low
,
3555 const uint8_t *inpdu
, size_t size
)
3557 struct smbd_server_connection
*sconn
= xconn
->client
->sconn
;
3559 struct smbd_smb2_request
*req
= NULL
;
3561 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3562 (unsigned int)size
));
3564 status
= smbd_initialize_smb2(xconn
, expected_seq_low
);
3565 if (!NT_STATUS_IS_OK(status
)) {
3566 smbd_server_connection_terminate(xconn
, nt_errstr(status
));
3570 status
= smbd_smb2_request_create(xconn
, inpdu
, size
, &req
);
3571 if (!NT_STATUS_IS_OK(status
)) {
3572 smbd_server_connection_terminate(xconn
, nt_errstr(status
));
3576 status
= smbd_smb2_request_validate(req
);
3577 if (!NT_STATUS_IS_OK(status
)) {
3578 smbd_server_connection_terminate(xconn
, nt_errstr(status
));
3582 status
= smbd_smb2_request_setup_out(req
);
3583 if (!NT_STATUS_IS_OK(status
)) {
3584 smbd_server_connection_terminate(xconn
, nt_errstr(status
));
3590 * this was already counted at the SMB1 layer =>
3591 * smbd_smb2_request_dispatch() should not count it twice.
3593 if (profile_p
->values
.request_stats
.count
> 0) {
3594 profile_p
->values
.request_stats
.count
--;
3597 status
= smbd_smb2_request_dispatch(req
);
3598 if (!NT_STATUS_IS_OK(status
)) {
3599 smbd_server_connection_terminate(xconn
, nt_errstr(status
));
3603 status
= smbd_smb2_request_next_incoming(xconn
);
3604 if (!NT_STATUS_IS_OK(status
)) {
3605 smbd_server_connection_terminate(xconn
, nt_errstr(status
));
3609 sconn
->num_requests
++;
3612 static int socket_error_from_errno(int ret
,
3626 if (sys_errno
== 0) {
3630 if (sys_errno
== EINTR
) {
3635 if (sys_errno
== EINPROGRESS
) {
3640 if (sys_errno
== EAGAIN
) {
3645 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3646 if (sys_errno
== ENOMEM
) {
3652 #if EWOULDBLOCK != EAGAIN
3653 if (sys_errno
== EWOULDBLOCK
) {
3663 static NTSTATUS
smbd_smb2_flush_send_queue(struct smbXsrv_connection
*xconn
)
3670 if (xconn
->smb2
.send_queue
== NULL
) {
3671 TEVENT_FD_NOT_WRITEABLE(xconn
->transport
.fde
);
3672 return NT_STATUS_OK
;
3675 while (xconn
->smb2
.send_queue
!= NULL
) {
3676 struct smbd_smb2_send_queue
*e
= xconn
->smb2
.send_queue
;
3679 if (e
->sendfile_header
!= NULL
) {
3684 status
= NT_STATUS_INTERNAL_ERROR
;
3686 for (i
=0; i
< e
->count
; i
++) {
3687 size
+= e
->vector
[i
].iov_len
;
3690 if (size
<= e
->sendfile_header
->length
) {
3691 buf
= e
->sendfile_header
->data
;
3693 buf
= talloc_array(e
->mem_ctx
, uint8_t, size
);
3695 return NT_STATUS_NO_MEMORY
;
3700 for (i
=0; i
< e
->count
; i
++) {
3702 e
->vector
[i
].iov_base
,
3703 e
->vector
[i
].iov_len
);
3704 size
+= e
->vector
[i
].iov_len
;
3707 e
->sendfile_header
->data
= buf
;
3708 e
->sendfile_header
->length
= size
;
3709 e
->sendfile_status
= &status
;
3712 xconn
->smb2
.send_queue_len
--;
3713 DLIST_REMOVE(xconn
->smb2
.send_queue
, e
);
3715 * This triggers the sendfile path via
3718 talloc_free(e
->mem_ctx
);
3720 if (!NT_STATUS_IS_OK(status
)) {
3726 ret
= writev(xconn
->transport
.sock
, e
->vector
, e
->count
);
3728 /* propagate end of file */
3729 return NT_STATUS_INTERNAL_ERROR
;
3731 err
= socket_error_from_errno(ret
, errno
, &retry
);
3734 TEVENT_FD_WRITEABLE(xconn
->transport
.fde
);
3735 return NT_STATUS_OK
;
3738 return map_nt_error_from_unix_common(err
);
3741 ok
= iov_advance(&e
->vector
, &e
->count
, ret
);
3743 return NT_STATUS_INTERNAL_ERROR
;
3747 /* we have more to write */
3748 TEVENT_FD_WRITEABLE(xconn
->transport
.fde
);
3749 return NT_STATUS_OK
;
3752 xconn
->smb2
.send_queue_len
--;
3753 DLIST_REMOVE(xconn
->smb2
.send_queue
, e
);
3754 talloc_free(e
->mem_ctx
);
3758 * Restart reads if we were blocked on
3759 * draining the send queue.
3762 status
= smbd_smb2_request_next_incoming(xconn
);
3763 if (!NT_STATUS_IS_OK(status
)) {
3767 return NT_STATUS_OK
;
3770 static NTSTATUS
smbd_smb2_io_handler(struct smbXsrv_connection
*xconn
,
3773 struct smbd_server_connection
*sconn
= xconn
->client
->sconn
;
3774 struct smbd_smb2_request_read_state
*state
= &xconn
->smb2
.request_read_state
;
3775 struct smbd_smb2_request
*req
= NULL
;
3776 size_t min_recvfile_size
= UINT32_MAX
;
3783 if (!NT_STATUS_IS_OK(xconn
->transport
.status
)) {
3785 * we're not supposed to do any io
3787 TEVENT_FD_NOT_READABLE(xconn
->transport
.fde
);
3788 TEVENT_FD_NOT_WRITEABLE(xconn
->transport
.fde
);
3789 return NT_STATUS_OK
;
3792 if (fde_flags
& TEVENT_FD_WRITE
) {
3793 status
= smbd_smb2_flush_send_queue(xconn
);
3794 if (!NT_STATUS_IS_OK(status
)) {
3799 if (!(fde_flags
& TEVENT_FD_READ
)) {
3800 return NT_STATUS_OK
;
3803 if (state
->req
== NULL
) {
3804 TEVENT_FD_NOT_READABLE(xconn
->transport
.fde
);
3805 return NT_STATUS_OK
;
3809 if (!state
->hdr
.done
) {
3810 state
->hdr
.done
= true;
3812 state
->vector
.iov_base
= (void *)state
->hdr
.nbt
;
3813 state
->vector
.iov_len
= NBT_HDR_SIZE
;
3816 ret
= readv(xconn
->transport
.sock
, &state
->vector
, 1);
3818 /* propagate end of file */
3819 return NT_STATUS_END_OF_FILE
;
3821 err
= socket_error_from_errno(ret
, errno
, &retry
);
3824 TEVENT_FD_READABLE(xconn
->transport
.fde
);
3825 return NT_STATUS_OK
;
3828 return map_nt_error_from_unix_common(err
);
3831 if (ret
< state
->vector
.iov_len
) {
3833 base
= (uint8_t *)state
->vector
.iov_base
;
3835 state
->vector
.iov_base
= (void *)base
;
3836 state
->vector
.iov_len
-= ret
;
3837 /* we have more to read */
3838 TEVENT_FD_READABLE(xconn
->transport
.fde
);
3839 return NT_STATUS_OK
;
3842 if (state
->pktlen
> 0) {
3843 if (state
->doing_receivefile
&& !is_smb2_recvfile_write(state
)) {
3845 * Not a possible receivefile write.
3846 * Read the rest of the data.
3848 state
->doing_receivefile
= false;
3850 state
->pktbuf
= talloc_realloc(state
->req
,
3854 if (state
->pktbuf
== NULL
) {
3855 return NT_STATUS_NO_MEMORY
;
3858 state
->vector
.iov_base
= (void *)(state
->pktbuf
+
3860 state
->vector
.iov_len
= (state
->pktfull
-
3863 state
->pktlen
= state
->pktfull
;
3868 * Either this is a receivefile write so we've
3869 * done a short read, or if not we have all the data.
3875 * Now we analyze the NBT header
3877 if (state
->hdr
.nbt
[0] != 0x00) {
3878 state
->min_recv_size
= 0;
3880 state
->pktfull
= smb2_len(state
->hdr
.nbt
);
3881 if (state
->pktfull
== 0) {
3885 if (state
->min_recv_size
!= 0) {
3886 min_recvfile_size
= SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
;
3887 min_recvfile_size
+= state
->min_recv_size
;
3890 if (state
->pktfull
> min_recvfile_size
) {
3892 * Might be a receivefile write. Read the SMB2 HEADER +
3893 * SMB2_WRITE header first. Set 'doing_receivefile'
3894 * as we're *attempting* receivefile write. If this
3895 * turns out not to be a SMB2_WRITE request or otherwise
3896 * not suitable then we'll just read the rest of the data
3897 * the next time this function is called.
3899 state
->pktlen
= SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
;
3900 state
->doing_receivefile
= true;
3902 state
->pktlen
= state
->pktfull
;
3905 state
->pktbuf
= talloc_array(state
->req
, uint8_t, state
->pktlen
);
3906 if (state
->pktbuf
== NULL
) {
3907 return NT_STATUS_NO_MEMORY
;
3910 state
->vector
.iov_base
= (void *)state
->pktbuf
;
3911 state
->vector
.iov_len
= state
->pktlen
;
3917 if (state
->hdr
.nbt
[0] != 0x00) {
3918 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3919 state
->hdr
.nbt
[0]));
3922 ZERO_STRUCTP(state
);
3924 state
->min_recv_size
= lp_min_receive_file_size();
3932 req
->request_time
= timeval_current();
3933 now
= timeval_to_nttime(&req
->request_time
);
3935 status
= smbd_smb2_inbuf_parse_compound(xconn
,
3941 &req
->in
.vector_count
);
3942 if (!NT_STATUS_IS_OK(status
)) {
3946 if (state
->doing_receivefile
) {
3947 req
->smb1req
= talloc_zero(req
, struct smb_request
);
3948 if (req
->smb1req
== NULL
) {
3949 return NT_STATUS_NO_MEMORY
;
3951 req
->smb1req
->unread_bytes
= state
->pktfull
- state
->pktlen
;
3954 ZERO_STRUCTP(state
);
3956 req
->current_idx
= 1;
3958 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3959 req
->current_idx
, req
->in
.vector_count
));
3961 status
= smbd_smb2_request_validate(req
);
3962 if (!NT_STATUS_IS_OK(status
)) {
3966 status
= smbd_smb2_request_setup_out(req
);
3967 if (!NT_STATUS_IS_OK(status
)) {
3971 status
= smbd_smb2_request_dispatch(req
);
3972 if (!NT_STATUS_IS_OK(status
)) {
3976 sconn
->num_requests
++;
3978 /* The timeout_processing function isn't run nearly
3979 often enough to implement 'max log size' without
3980 overrunning the size of the file by many megabytes.
3981 This is especially true if we are running at debug
3982 level 10. Checking every 50 SMB2s is a nice
3983 tradeoff of performance vs log file size overrun. */
3985 if ((sconn
->num_requests
% 50) == 0 &&
3986 need_to_check_log_size()) {
3987 change_to_root_user();
3991 status
= smbd_smb2_request_next_incoming(xconn
);
3992 if (!NT_STATUS_IS_OK(status
)) {
3996 return NT_STATUS_OK
;
3999 static void smbd_smb2_connection_handler(struct tevent_context
*ev
,
4000 struct tevent_fd
*fde
,
4004 struct smbXsrv_connection
*xconn
=
4005 talloc_get_type_abort(private_data
,
4006 struct smbXsrv_connection
);
4009 status
= smbd_smb2_io_handler(xconn
, flags
);
4010 if (!NT_STATUS_IS_OK(status
)) {
4011 smbd_server_connection_terminate(xconn
, nt_errstr(status
));