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"
33 static void smbd_smb2_connection_handler(struct tevent_context
*ev
,
34 struct tevent_fd
*fde
,
37 static NTSTATUS
smbd_smb2_io_handler(struct smbd_server_connection
*sconn
,
40 #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9)
42 static const struct smbd_smb2_dispatch_table
{
49 bool allow_invalid_fileid
;
50 } smbd_smb2_table
[] = {
51 #define _OP(o) .opcode = o, .name = #o
56 _OP(SMB2_OP_SESSSETUP
),
66 * This call needs to be run as root.
68 * smbd_smb2_request_process_tcon()
69 * calls make_connection_snum(), which will call
70 * change_to_user(), when needed.
104 .need_session
= true,
109 .need_session
= true,
112 .allow_invalid_fileid
= true,
117 _OP(SMB2_OP_KEEPALIVE
),
121 .need_session
= true,
126 .need_session
= true,
130 _OP(SMB2_OP_GETINFO
),
131 .need_session
= true,
135 _OP(SMB2_OP_SETINFO
),
136 .need_session
= true,
141 .need_session
= true,
146 * as LEASE breaks does not
152 const char *smb2_opcode_name(uint16_t opcode
)
154 if (opcode
>= ARRAY_SIZE(smbd_smb2_table
)) {
155 return "Bad SMB2 opcode";
157 return smbd_smb2_table
[opcode
].name
;
160 static const struct smbd_smb2_dispatch_table
*smbd_smb2_call(uint16_t opcode
)
162 const struct smbd_smb2_dispatch_table
*ret
= NULL
;
164 if (opcode
>= ARRAY_SIZE(smbd_smb2_table
)) {
168 ret
= &smbd_smb2_table
[opcode
];
170 SMB_ASSERT(ret
->opcode
== opcode
);
175 static void print_req_vectors(const struct smbd_smb2_request
*req
)
179 for (i
= 0; i
< req
->in
.vector_count
; i
++) {
180 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
182 (unsigned int)req
->in
.vector
[i
].iov_len
);
184 for (i
= 0; i
< req
->out
.vector_count
; i
++) {
185 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
187 (unsigned int)req
->out
.vector
[i
].iov_len
);
191 bool smbd_is_smb2_header(const uint8_t *inbuf
, size_t size
)
193 if (size
< (4 + SMB2_HDR_BODY
)) {
197 if (IVAL(inbuf
, 4) != SMB2_MAGIC
) {
204 static NTSTATUS
smbd_initialize_smb2(struct smbd_server_connection
*sconn
)
206 TALLOC_FREE(sconn
->smb1
.fde
);
208 sconn
->smb2
.send_queue
= NULL
;
210 sconn
->smb2
.seqnum_low
= 0;
211 sconn
->smb2
.seqnum_range
= 1;
212 sconn
->smb2
.credits_granted
= 1;
213 sconn
->smb2
.max_credits
= lp_smb2_max_credits();
214 sconn
->smb2
.credits_bitmap
= bitmap_talloc(sconn
,
215 sconn
->smb2
.max_credits
);
216 if (sconn
->smb2
.credits_bitmap
== NULL
) {
217 return NT_STATUS_NO_MEMORY
;
220 sconn
->smb2
.fde
= tevent_add_fd(sconn
->ev_ctx
,
224 smbd_smb2_connection_handler
,
226 if (sconn
->smb2
.fde
== NULL
) {
227 return NT_STATUS_NO_MEMORY
;
230 /* Ensure child is set to non-blocking mode */
231 set_blocking(sconn
->sock
, false);
235 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
236 #define _smb2_setlen(_buf,len) do { \
237 uint8_t *buf = (uint8_t *)_buf; \
239 buf[1] = ((len)&0xFF0000)>>16; \
240 buf[2] = ((len)&0xFF00)>>8; \
241 buf[3] = (len)&0xFF; \
244 static void smb2_setup_nbt_length(struct iovec
*vector
, int count
)
249 for (i
=1; i
< count
; i
++) {
250 len
+= vector
[i
].iov_len
;
253 _smb2_setlen(vector
[0].iov_base
, len
);
256 static int smbd_smb2_request_destructor(struct smbd_smb2_request
*req
)
258 data_blob_clear_free(&req
->first_key
);
259 data_blob_clear_free(&req
->last_key
);
263 static struct smbd_smb2_request
*smbd_smb2_request_allocate(TALLOC_CTX
*mem_ctx
)
265 TALLOC_CTX
*mem_pool
;
266 struct smbd_smb2_request
*req
;
269 /* Enable this to find subtle valgrind errors. */
270 mem_pool
= talloc_init("smbd_smb2_request_allocate");
272 mem_pool
= talloc_tos();
274 if (mem_pool
== NULL
) {
278 req
= talloc_zero(mem_pool
, struct smbd_smb2_request
);
280 talloc_free(mem_pool
);
283 talloc_reparent(mem_pool
, mem_ctx
, req
);
285 TALLOC_FREE(mem_pool
);
288 req
->last_session_id
= UINT64_MAX
;
289 req
->last_tid
= UINT32_MAX
;
291 talloc_set_destructor(req
, smbd_smb2_request_destructor
);
296 static NTSTATUS
smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection
*conn
,
307 uint8_t *first_hdr
= buf
;
308 size_t verified_buflen
= 0;
313 * Note: index '0' is reserved for the transport protocol
315 iov
= talloc_zero_array(mem_ctx
, struct iovec
, num_iov
);
317 return NT_STATUS_NO_MEMORY
;
320 while (taken
< buflen
) {
321 size_t len
= buflen
- taken
;
322 uint8_t *hdr
= first_hdr
+ taken
;
325 size_t next_command_ofs
;
327 uint8_t *body
= NULL
;
330 struct iovec
*iov_tmp
;
332 if (verified_buflen
> taken
) {
333 len
= verified_buflen
- taken
;
340 DEBUG(10, ("%d bytes left, expected at least %d\n",
344 if (IVAL(hdr
, 0) == SMB2_TF_MAGIC
) {
345 struct smbXsrv_session
*s
= NULL
;
347 struct iovec tf_iov
[2];
351 if (conn
->protocol
< PROTOCOL_SMB2_24
) {
352 DEBUG(10, ("Got SMB2_TRANSFORM header, "
353 "but dialect[0x%04X] is used\n",
354 conn
->smb2
.server
.dialect
));
358 if (!(conn
->smb2
.server
.capabilities
& SMB2_CAP_ENCRYPTION
)) {
359 DEBUG(10, ("Got SMB2_TRANSFORM header, "
360 "but not negotiated "
361 "client[0x%08X] server[0x%08X]\n",
362 conn
->smb2
.client
.capabilities
,
363 conn
->smb2
.server
.capabilities
));
367 if (len
< SMB2_TF_HDR_SIZE
) {
368 DEBUG(1, ("%d bytes left, expected at least %d\n",
369 (int)len
, SMB2_TF_HDR_SIZE
));
373 tf_len
= SMB2_TF_HDR_SIZE
;
376 hdr
= first_hdr
+ taken
;
377 enc_len
= IVAL(tf
, SMB2_TF_MSG_SIZE
);
378 uid
= BVAL(tf
, SMB2_TF_SESSION_ID
);
380 if (len
< SMB2_TF_HDR_SIZE
+ enc_len
) {
381 DEBUG(1, ("%d bytes left, expected at least %d\n",
383 (int)(SMB2_TF_HDR_SIZE
+ enc_len
)));
387 status
= smb2srv_session_lookup(conn
, uid
, now
, &s
);
389 DEBUG(1, ("invalid session[%llu] in "
390 "SMB2_TRANSFORM header\n",
391 (unsigned long long)uid
));
393 return NT_STATUS_USER_SESSION_DELETED
;
396 tf_iov
[0].iov_base
= (void *)tf
;
397 tf_iov
[0].iov_len
= tf_len
;
398 tf_iov
[1].iov_base
= (void *)hdr
;
399 tf_iov
[1].iov_len
= enc_len
;
401 status
= smb2_signing_decrypt_pdu(s
->global
->decryption_key
,
404 if (!NT_STATUS_IS_OK(status
)) {
409 verified_buflen
= taken
+ enc_len
;
414 * We need the header plus the body length field
417 if (len
< SMB2_HDR_BODY
+ 2) {
418 DEBUG(10, ("%d bytes left, expected at least %d\n",
419 (int)len
, SMB2_HDR_BODY
));
422 if (IVAL(hdr
, 0) != SMB2_MAGIC
) {
423 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
427 if (SVAL(hdr
, 4) != SMB2_HDR_BODY
) {
428 DEBUG(10, ("Got HDR len %d, expected %d\n",
429 SVAL(hdr
, 4), SMB2_HDR_BODY
));
434 next_command_ofs
= IVAL(hdr
, SMB2_HDR_NEXT_COMMAND
);
435 body_size
= SVAL(hdr
, SMB2_HDR_BODY
);
437 if (next_command_ofs
!= 0) {
438 if (next_command_ofs
< (SMB2_HDR_BODY
+ 2)) {
441 if (next_command_ofs
> full_size
) {
444 full_size
= next_command_ofs
;
451 if (body_size
> (full_size
- SMB2_HDR_BODY
)) {
453 * let the caller handle the error
455 body_size
= full_size
- SMB2_HDR_BODY
;
457 body
= hdr
+ SMB2_HDR_BODY
;
458 dyn
= body
+ body_size
;
459 dyn_size
= full_size
- (SMB2_HDR_BODY
+ body_size
);
461 iov_tmp
= talloc_realloc(mem_ctx
, iov
, struct iovec
,
462 num_iov
+ SMBD_SMB2_NUM_IOV_PER_REQ
);
463 if (iov_tmp
== NULL
) {
465 return NT_STATUS_NO_MEMORY
;
469 num_iov
+= SMBD_SMB2_NUM_IOV_PER_REQ
;
471 cur
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= tf
;
472 cur
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= tf_len
;
473 cur
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
474 cur
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
475 cur
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
476 cur
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= body_size
;
477 cur
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
478 cur
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= dyn_size
;
489 return NT_STATUS_INVALID_PARAMETER
;
492 static NTSTATUS
smbd_smb2_request_create(struct smbd_server_connection
*sconn
,
493 uint8_t *inbuf
, size_t size
,
494 struct smbd_smb2_request
**_req
)
496 struct smbd_smb2_request
*req
;
497 uint32_t protocol_version
;
498 const uint8_t *inhdr
= NULL
;
500 uint32_t next_command_ofs
;
504 if (size
< (4 + SMB2_HDR_BODY
+ 2)) {
505 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size
));
506 return NT_STATUS_INVALID_PARAMETER
;
511 protocol_version
= IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
);
512 if (protocol_version
!= SMB2_MAGIC
) {
513 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
515 return NT_STATUS_INVALID_PARAMETER
;
518 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
519 if (cmd
!= SMB2_OP_NEGPROT
) {
520 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
522 return NT_STATUS_INVALID_PARAMETER
;
525 next_command_ofs
= IVAL(inhdr
, SMB2_HDR_NEXT_COMMAND
);
526 if (next_command_ofs
!= 0) {
527 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
529 return NT_STATUS_INVALID_PARAMETER
;
532 req
= smbd_smb2_request_allocate(sconn
);
534 return NT_STATUS_NO_MEMORY
;
538 talloc_steal(req
, inbuf
);
540 req
->request_time
= timeval_current();
541 now
= timeval_to_nttime(&req
->request_time
);
543 status
= smbd_smb2_inbuf_parse_compound(sconn
->conn
,
545 inbuf
+ NBT_HDR_SIZE
,
547 req
, &req
->in
.vector
,
548 &req
->in
.vector_count
);
549 if (!NT_STATUS_IS_OK(status
)) {
554 req
->current_idx
= 1;
560 static bool smb2_validate_sequence_number(struct smbd_server_connection
*sconn
,
561 uint64_t message_id
, uint64_t seq_id
)
563 struct bitmap
*credits_bm
= sconn
->smb2
.credits_bitmap
;
566 if (seq_id
< sconn
->smb2
.seqnum_low
) {
567 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
568 "%llu (sequence id %llu) "
569 "(granted = %u, low = %llu, range = %u)\n",
570 (unsigned long long)message_id
,
571 (unsigned long long)seq_id
,
572 (unsigned int)sconn
->smb2
.credits_granted
,
573 (unsigned long long)sconn
->smb2
.seqnum_low
,
574 (unsigned int)sconn
->smb2
.seqnum_range
));
578 if (seq_id
>= sconn
->smb2
.seqnum_low
+ sconn
->smb2
.seqnum_range
) {
579 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
580 "%llu (sequence id %llu) "
581 "(granted = %u, low = %llu, range = %u)\n",
582 (unsigned long long)message_id
,
583 (unsigned long long)seq_id
,
584 (unsigned int)sconn
->smb2
.credits_granted
,
585 (unsigned long long)sconn
->smb2
.seqnum_low
,
586 (unsigned int)sconn
->smb2
.seqnum_range
));
590 offset
= seq_id
% sconn
->smb2
.max_credits
;
592 if (bitmap_query(credits_bm
, offset
)) {
593 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
594 "%llu (sequence id %llu) "
595 "(granted = %u, low = %llu, range = %u) "
597 (unsigned long long)message_id
,
598 (unsigned long long)seq_id
,
599 (unsigned int)sconn
->smb2
.credits_granted
,
600 (unsigned long long)sconn
->smb2
.seqnum_low
,
601 (unsigned int)sconn
->smb2
.seqnum_range
,
606 /* Mark the message_ids as seen in the bitmap. */
607 bitmap_set(credits_bm
, offset
);
609 if (seq_id
!= sconn
->smb2
.seqnum_low
) {
614 * Move the window forward by all the message_id's
617 while (bitmap_query(credits_bm
, offset
)) {
618 DEBUG(10,("smb2_validate_sequence_number: clearing "
619 "id %llu (position %u) from bitmap\n",
620 (unsigned long long)(sconn
->smb2
.seqnum_low
),
622 bitmap_clear(credits_bm
, offset
);
624 sconn
->smb2
.seqnum_low
+= 1;
625 sconn
->smb2
.seqnum_range
-= 1;
626 offset
= sconn
->smb2
.seqnum_low
% sconn
->smb2
.max_credits
;
632 static bool smb2_validate_message_id(struct smbd_server_connection
*sconn
,
633 const uint8_t *inhdr
)
635 uint64_t message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
636 uint16_t opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
637 uint16_t credit_charge
= 1;
640 if (opcode
== SMB2_OP_CANCEL
) {
641 /* SMB2_CANCEL requests by definition resend messageids. */
645 if (sconn
->smb2
.supports_multicredit
) {
646 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
647 credit_charge
= MAX(credit_charge
, 1);
650 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
651 "credits_granted %llu, "
652 "seqnum low/range: %llu/%llu\n",
653 (unsigned long long) message_id
,
654 (unsigned long long) credit_charge
,
655 (unsigned long long) sconn
->smb2
.credits_granted
,
656 (unsigned long long) sconn
->smb2
.seqnum_low
,
657 (unsigned long long) sconn
->smb2
.seqnum_range
));
659 if (sconn
->smb2
.credits_granted
< credit_charge
) {
660 DEBUG(0, ("smb2_validate_message_id: client used more "
661 "credits than granted, mid %llu, charge %llu, "
662 "credits_granted %llu, "
663 "seqnum low/range: %llu/%llu\n",
664 (unsigned long long) message_id
,
665 (unsigned long long) credit_charge
,
666 (unsigned long long) sconn
->smb2
.credits_granted
,
667 (unsigned long long) sconn
->smb2
.seqnum_low
,
668 (unsigned long long) sconn
->smb2
.seqnum_range
));
673 * now check the message ids
675 * for multi-credit requests we need to check all current mid plus
676 * the implicit mids caused by the credit charge
677 * e.g. current mid = 15, charge 5 => mark 15-19 as used
680 for (i
= 0; i
<= (credit_charge
-1); i
++) {
681 uint64_t id
= message_id
+ i
;
684 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
685 (unsigned long long)message_id
,
687 (unsigned long long)id
));
689 ok
= smb2_validate_sequence_number(sconn
, message_id
, id
);
695 /* substract used credits */
696 sconn
->smb2
.credits_granted
-= credit_charge
;
701 static NTSTATUS
smbd_smb2_request_validate(struct smbd_smb2_request
*req
)
706 count
= req
->in
.vector_count
;
708 if (count
< 1 + SMBD_SMB2_NUM_IOV_PER_REQ
) {
709 /* It's not a SMB2 request */
710 return NT_STATUS_INVALID_PARAMETER
;
713 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
714 struct iovec
*hdr
= SMBD_SMB2_IDX_HDR_IOV(req
,in
,idx
);
715 struct iovec
*body
= SMBD_SMB2_IDX_BODY_IOV(req
,in
,idx
);
716 const uint8_t *inhdr
= NULL
;
718 if (hdr
->iov_len
!= SMB2_HDR_BODY
) {
719 return NT_STATUS_INVALID_PARAMETER
;
722 if (body
->iov_len
< 2) {
723 return NT_STATUS_INVALID_PARAMETER
;
726 inhdr
= (const uint8_t *)hdr
->iov_base
;
728 /* Check the SMB2 header */
729 if (IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
) != SMB2_MAGIC
) {
730 return NT_STATUS_INVALID_PARAMETER
;
733 if (!smb2_validate_message_id(req
->sconn
, inhdr
)) {
734 return NT_STATUS_INVALID_PARAMETER
;
741 static void smb2_set_operation_credit(struct smbd_server_connection
*sconn
,
742 const struct iovec
*in_vector
,
743 struct iovec
*out_vector
)
745 const uint8_t *inhdr
= (const uint8_t *)in_vector
->iov_base
;
746 uint8_t *outhdr
= (uint8_t *)out_vector
->iov_base
;
747 uint16_t credit_charge
= 1;
748 uint16_t credits_requested
;
752 uint16_t credits_granted
= 0;
753 uint64_t credits_possible
;
754 uint16_t current_max_credits
;
757 * first we grant only 1/16th of the max range.
759 * Windows also starts with the 1/16th and then grants
760 * more later. I was only able to trigger higher
761 * values, when using a very high credit charge.
763 * TODO: scale up depending on load, free memory
765 * Maybe also on the relationship between number
766 * of requests and the used sequence number.
767 * Which means we would grant more credits
768 * for client which use multi credit requests.
770 current_max_credits
= sconn
->smb2
.max_credits
/ 16;
771 current_max_credits
= MAX(current_max_credits
, 1);
773 if (sconn
->smb2
.supports_multicredit
) {
774 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
775 credit_charge
= MAX(credit_charge
, 1);
778 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
779 credits_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
780 out_flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
781 out_status
= NT_STATUS(IVAL(outhdr
, SMB2_HDR_STATUS
));
783 SMB_ASSERT(sconn
->smb2
.max_credits
>= sconn
->smb2
.credits_granted
);
785 if (sconn
->smb2
.max_credits
< credit_charge
) {
786 smbd_server_connection_terminate(sconn
,
787 "client error: credit charge > max credits\n");
791 if (out_flags
& SMB2_HDR_FLAG_ASYNC
) {
793 * In case we already send an async interim
794 * response, we should not grant
795 * credits on the final response.
798 } else if (credits_requested
> 0) {
799 uint16_t additional_max
= 0;
800 uint16_t additional_credits
= credits_requested
- 1;
803 case SMB2_OP_NEGPROT
:
805 case SMB2_OP_SESSSETUP
:
807 * Windows 2012 RC1 starts to grant
809 * with a successful session setup
811 if (NT_STATUS_IS_OK(out_status
)) {
817 * We match windows and only grant additional credits
824 additional_credits
= MIN(additional_credits
, additional_max
);
826 credits_granted
= credit_charge
+ additional_credits
;
827 } else if (sconn
->smb2
.credits_granted
== 0) {
829 * Make sure the client has always at least one credit
835 * sequence numbers should not wrap
837 * 1. calculate the possible credits until
838 * the sequence numbers start to wrap on 64-bit.
840 * 2. UINT64_MAX is used for Break Notifications.
842 * 2. truncate the possible credits to the maximum
843 * credits we want to grant to the client in total.
845 * 3. remove the range we'll already granted to the client
846 * this makes sure the client consumes the lowest sequence
847 * number, before we can grant additional credits.
849 credits_possible
= UINT64_MAX
- sconn
->smb2
.seqnum_low
;
850 if (credits_possible
> 0) {
851 /* remove UINT64_MAX */
852 credits_possible
-= 1;
854 credits_possible
= MIN(credits_possible
, current_max_credits
);
855 credits_possible
-= sconn
->smb2
.seqnum_range
;
857 credits_granted
= MIN(credits_granted
, credits_possible
);
859 SSVAL(outhdr
, SMB2_HDR_CREDIT
, credits_granted
);
860 sconn
->smb2
.credits_granted
+= credits_granted
;
861 sconn
->smb2
.seqnum_range
+= credits_granted
;
863 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
864 "granted %u, current possible/max %u/%u, "
865 "total granted/max/low/range %u/%u/%llu/%u\n",
866 (unsigned int)credits_requested
,
867 (unsigned int)credit_charge
,
868 (unsigned int)credits_granted
,
869 (unsigned int)credits_possible
,
870 (unsigned int)current_max_credits
,
871 (unsigned int)sconn
->smb2
.credits_granted
,
872 (unsigned int)sconn
->smb2
.max_credits
,
873 (unsigned long long)sconn
->smb2
.seqnum_low
,
874 (unsigned int)sconn
->smb2
.seqnum_range
));
877 static void smb2_calculate_credits(const struct smbd_smb2_request
*inreq
,
878 struct smbd_smb2_request
*outreq
)
881 uint16_t total_credits
= 0;
883 count
= outreq
->out
.vector_count
;
885 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
886 struct iovec
*inhdr_v
= SMBD_SMB2_IDX_HDR_IOV(inreq
,in
,idx
);
887 struct iovec
*outhdr_v
= SMBD_SMB2_IDX_HDR_IOV(outreq
,out
,idx
);
888 uint8_t *outhdr
= (uint8_t *)outhdr_v
->iov_base
;
890 smb2_set_operation_credit(outreq
->sconn
, inhdr_v
, outhdr_v
);
892 /* To match Windows, count up what we
894 total_credits
+= SVAL(outhdr
, SMB2_HDR_CREDIT
);
895 /* Set to zero in all but the last reply. */
896 if (idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
< count
) {
897 SSVAL(outhdr
, SMB2_HDR_CREDIT
, 0);
899 SSVAL(outhdr
, SMB2_HDR_CREDIT
, total_credits
);
904 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
)
906 struct iovec
*vector
;
910 count
= req
->in
.vector_count
;
911 vector
= talloc_zero_array(req
, struct iovec
, count
);
912 if (vector
== NULL
) {
913 return NT_STATUS_NO_MEMORY
;
916 vector
[0].iov_base
= req
->out
.nbt_hdr
;
917 vector
[0].iov_len
= 4;
918 SIVAL(req
->out
.nbt_hdr
, 0, 0);
920 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
921 struct iovec
*inhdr_v
= SMBD_SMB2_IDX_HDR_IOV(req
,in
,idx
);
922 const uint8_t *inhdr
= (const uint8_t *)inhdr_v
->iov_base
;
923 uint8_t *outhdr
= NULL
;
924 uint8_t *outbody
= NULL
;
925 uint32_t next_command_ofs
= 0;
926 struct iovec
*current
= &vector
[idx
];
928 if ((idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
) < count
) {
929 /* we have a next command -
930 * setup for the error case. */
931 next_command_ofs
= SMB2_HDR_BODY
+ 9;
934 outhdr
= talloc_zero_array(vector
, uint8_t,
936 if (outhdr
== NULL
) {
937 return NT_STATUS_NO_MEMORY
;
940 outbody
= outhdr
+ SMB2_HDR_BODY
;
943 * SMBD_SMB2_TF_IOV_OFS might be used later
945 current
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
946 current
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
948 current
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= (void *)outhdr
;
949 current
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
951 current
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= (void *)outbody
;
952 current
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= 8;
954 current
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= NULL
;
955 current
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= 0;
957 /* setup the SMB2 header */
958 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
959 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
960 SSVAL(outhdr
, SMB2_HDR_CREDIT_CHARGE
,
961 SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
));
962 SIVAL(outhdr
, SMB2_HDR_STATUS
,
963 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
964 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
965 SVAL(inhdr
, SMB2_HDR_OPCODE
));
966 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
967 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
968 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
969 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
970 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
971 SIVAL(outhdr
, SMB2_HDR_PID
,
972 IVAL(inhdr
, SMB2_HDR_PID
));
973 SIVAL(outhdr
, SMB2_HDR_TID
,
974 IVAL(inhdr
, SMB2_HDR_TID
));
975 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
976 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
977 memcpy(outhdr
+ SMB2_HDR_SIGNATURE
,
978 inhdr
+ SMB2_HDR_SIGNATURE
, 16);
980 /* setup error body header */
981 SSVAL(outbody
, 0x00, 0x08 + 1);
982 SSVAL(outbody
, 0x02, 0);
983 SIVAL(outbody
, 0x04, 0);
986 req
->out
.vector
= vector
;
987 req
->out
.vector_count
= count
;
989 /* setup the length of the NBT packet */
990 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
992 DLIST_ADD_END(req
->sconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
997 void smbd_server_connection_terminate_ex(struct smbd_server_connection
*sconn
,
999 const char *location
)
1001 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1003 exit_server_cleanly(reason
);
1006 static bool dup_smb2_vec4(TALLOC_CTX
*ctx
,
1007 struct iovec
*outvec
,
1008 const struct iovec
*srcvec
)
1010 const uint8_t *srctf
;
1012 const uint8_t *srchdr
;
1014 const uint8_t *srcbody
;
1016 const uint8_t *expected_srcbody
;
1017 const uint8_t *srcdyn
;
1019 const uint8_t *expected_srcdyn
;
1025 srctf
= (const uint8_t *)srcvec
[SMBD_SMB2_TF_IOV_OFS
].iov_base
;
1026 srctf_len
= srcvec
[SMBD_SMB2_TF_IOV_OFS
].iov_len
;
1027 srchdr
= (const uint8_t *)srcvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
;
1028 srchdr_len
= srcvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
;
1029 srcbody
= (const uint8_t *)srcvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
;
1030 srcbody_len
= srcvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
;
1031 expected_srcbody
= srchdr
+ SMB2_HDR_BODY
;
1032 srcdyn
= (const uint8_t *)srcvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
;
1033 srcdyn_len
= srcvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
;
1034 expected_srcdyn
= srcbody
+ 8;
1036 if ((srctf_len
!= SMB2_TF_HDR_SIZE
) && (srctf_len
!= 0)) {
1040 if (srchdr_len
!= SMB2_HDR_BODY
) {
1044 if (srctf_len
== SMB2_TF_HDR_SIZE
) {
1045 dsttf
= talloc_memdup(ctx
, srctf
, SMB2_TF_HDR_SIZE
);
1046 if (dsttf
== NULL
) {
1052 outvec
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= (void *)dsttf
;
1053 outvec
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= srctf_len
;
1055 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1056 * be allocated with size OUTVEC_ALLOC_SIZE. */
1058 dsthdr
= talloc_memdup(ctx
, srchdr
, OUTVEC_ALLOC_SIZE
);
1059 if (dsthdr
== NULL
) {
1062 outvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= (void *)dsthdr
;
1063 outvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
1066 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1067 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1068 * then duplicate this. Else use talloc_memdup().
1071 if ((srcbody
== expected_srcbody
) && (srcbody_len
== 8)) {
1072 dstbody
= dsthdr
+ SMB2_HDR_BODY
;
1074 dstbody
= talloc_memdup(ctx
, srcbody
, srcbody_len
);
1075 if (dstbody
== NULL
) {
1079 outvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= (void *)dstbody
;
1080 outvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= srcbody_len
;
1083 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1085 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1086 * then duplicate this. Else use talloc_memdup().
1089 if ((srcdyn
== expected_srcdyn
) && (srcdyn_len
== 1)) {
1090 dstdyn
= dsthdr
+ SMB2_HDR_BODY
+ 8;
1091 } else if (srcdyn
== NULL
) {
1094 dstdyn
= talloc_memdup(ctx
, srcdyn
, srcdyn_len
);
1095 if (dstdyn
== NULL
) {
1099 outvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= (void *)dstdyn
;
1100 outvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= srcdyn_len
;
1105 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
1107 struct smbd_smb2_request
*newreq
= NULL
;
1108 struct iovec
*outvec
= NULL
;
1109 int count
= req
->out
.vector_count
;
1112 newreq
= smbd_smb2_request_allocate(req
->sconn
);
1117 newreq
->sconn
= req
->sconn
;
1118 newreq
->session
= req
->session
;
1119 newreq
->do_encryption
= req
->do_encryption
;
1120 newreq
->do_signing
= req
->do_signing
;
1121 newreq
->current_idx
= req
->current_idx
;
1123 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
1125 TALLOC_FREE(newreq
);
1128 newreq
->out
.vector
= outvec
;
1129 newreq
->out
.vector_count
= count
;
1131 /* Setup the outvec's identically to req. */
1132 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
1133 outvec
[0].iov_len
= 4;
1134 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
1136 /* Setup the vectors identically to the ones in req. */
1137 for (i
= 1; i
< count
; i
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
1138 if (!dup_smb2_vec4(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
1145 TALLOC_FREE(newreq
);
1149 smb2_setup_nbt_length(newreq
->out
.vector
,
1150 newreq
->out
.vector_count
);
1155 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
1157 struct smbd_server_connection
*sconn
= req
->sconn
;
1158 struct smbXsrv_connection
*conn
= req
->sconn
->conn
;
1160 struct iovec
*firsttf
= NULL
;
1161 struct iovec
*outhdr_v
= NULL
;
1162 uint8_t *outhdr
= NULL
;
1163 struct smbd_smb2_request
*nreq
= NULL
;
1166 /* Create a new smb2 request we'll use
1167 for the interim return. */
1168 nreq
= dup_smb2_req(req
);
1170 return NT_STATUS_NO_MEMORY
;
1173 /* Lose the last X out vectors. They're the
1174 ones we'll be using for the async reply. */
1175 nreq
->out
.vector_count
-= SMBD_SMB2_NUM_IOV_PER_REQ
;
1177 smb2_setup_nbt_length(nreq
->out
.vector
,
1178 nreq
->out
.vector_count
);
1180 /* Step back to the previous reply. */
1181 nreq
->current_idx
-= SMBD_SMB2_NUM_IOV_PER_REQ
;
1182 firsttf
= SMBD_SMB2_IDX_TF_IOV(nreq
,out
,first_idx
);
1183 outhdr_v
= SMBD_SMB2_OUT_HDR_IOV(nreq
);
1184 outhdr
= SMBD_SMB2_OUT_HDR_PTR(nreq
);
1185 /* And end the chain. */
1186 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1188 /* Calculate outgoing credits */
1189 smb2_calculate_credits(req
, nreq
);
1191 if (DEBUGLEVEL
>= 10) {
1192 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1193 (unsigned int)nreq
->current_idx
);
1194 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1195 (unsigned int)nreq
->out
.vector_count
);
1196 print_req_vectors(nreq
);
1200 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1201 * we need to sign/encrypt here with the last/first key we remembered
1203 if (firsttf
->iov_len
== SMB2_TF_HDR_SIZE
) {
1204 status
= smb2_signing_encrypt_pdu(req
->first_key
,
1207 nreq
->out
.vector_count
- first_idx
);
1208 if (!NT_STATUS_IS_OK(status
)) {
1211 } else if (req
->last_key
.length
> 0) {
1212 status
= smb2_signing_sign_pdu(req
->last_key
,
1215 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
1216 if (!NT_STATUS_IS_OK(status
)) {
1221 nreq
->queue_entry
.mem_ctx
= nreq
;
1222 nreq
->queue_entry
.vector
= nreq
->out
.vector
;
1223 nreq
->queue_entry
.count
= nreq
->out
.vector_count
;
1224 DLIST_ADD_END(nreq
->sconn
->smb2
.send_queue
, &nreq
->queue_entry
, NULL
);
1225 nreq
->sconn
->smb2
.send_queue_len
++;
1227 status
= smbd_smb2_io_handler(sconn
, TEVENT_FD_WRITE
);
1228 if (!NT_STATUS_IS_OK(status
)) {
1232 return NT_STATUS_OK
;
1235 struct smbd_smb2_request_pending_state
{
1236 struct smbd_server_connection
*sconn
;
1237 struct smbd_smb2_send_queue queue_entry
;
1238 uint8_t buf
[NBT_HDR_SIZE
+ SMB2_TF_HDR_SIZE
+ SMB2_HDR_BODY
+ 0x08 + 1];
1239 struct iovec vector
[1 + SMBD_SMB2_NUM_IOV_PER_REQ
];
1242 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
1243 struct tevent_timer
*te
,
1244 struct timeval current_time
,
1245 void *private_data
);
1247 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
1248 struct tevent_req
*subreq
,
1249 uint32_t defer_time
)
1252 struct timeval defer_endtime
;
1253 uint8_t *outhdr
= NULL
;
1256 if (!tevent_req_is_in_progress(subreq
)) {
1258 * This is a performance optimization,
1259 * it avoids one tevent_loop iteration,
1260 * which means we avoid one
1261 * talloc_stackframe_pool/talloc_free pair.
1263 tevent_req_notify_callback(subreq
);
1264 return NT_STATUS_OK
;
1267 req
->subreq
= subreq
;
1270 if (req
->async_te
) {
1271 /* We're already async. */
1272 return NT_STATUS_OK
;
1275 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1276 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1277 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1278 /* We're already async. */
1279 return NT_STATUS_OK
;
1282 if (req
->in
.vector_count
> req
->current_idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
) {
1284 * We're trying to go async in a compound
1286 * This is only allowed for opens that
1287 * cause an oplock break, otherwise it
1288 * is not allowed. See [MS-SMB2].pdf
1289 * note <194> on Section 3.3.5.2.7.
1291 const uint8_t *inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1293 if (SVAL(inhdr
, SMB2_HDR_OPCODE
) != SMB2_OP_CREATE
) {
1295 * Cancel the outstanding request.
1297 bool ok
= tevent_req_cancel(req
->subreq
);
1299 return NT_STATUS_OK
;
1301 TALLOC_FREE(req
->subreq
);
1302 return smbd_smb2_request_error(req
,
1303 NT_STATUS_INTERNAL_ERROR
);
1307 if (DEBUGLEVEL
>= 10) {
1308 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1309 (unsigned int)req
->current_idx
);
1310 print_req_vectors(req
);
1313 if (req
->current_idx
> 1) {
1315 * We're going async in a compound
1316 * chain after the first request has
1317 * already been processed. Send an
1318 * interim response containing the
1319 * set of replies already generated.
1321 int idx
= req
->current_idx
;
1323 status
= smb2_send_async_interim_response(req
);
1324 if (!NT_STATUS_IS_OK(status
)) {
1327 data_blob_clear_free(&req
->first_key
);
1329 req
->current_idx
= 1;
1332 * Re-arrange the in.vectors to remove what
1335 memmove(&req
->in
.vector
[1],
1336 &req
->in
.vector
[idx
],
1337 sizeof(req
->in
.vector
[0])*(req
->in
.vector_count
- idx
));
1338 req
->in
.vector_count
= 1 + (req
->in
.vector_count
- idx
);
1340 /* Re-arrange the out.vectors to match. */
1341 memmove(&req
->out
.vector
[1],
1342 &req
->out
.vector
[idx
],
1343 sizeof(req
->out
.vector
[0])*(req
->out
.vector_count
- idx
));
1344 req
->out
.vector_count
= 1 + (req
->out
.vector_count
- idx
);
1346 if (req
->in
.vector_count
== 1 + SMBD_SMB2_NUM_IOV_PER_REQ
) {
1348 * We only have one remaining request as
1349 * we've processed everything else.
1350 * This is no longer a compound request.
1352 req
->compound_related
= false;
1353 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1354 flags
= (IVAL(outhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
1355 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
);
1358 data_blob_clear_free(&req
->last_key
);
1360 defer_endtime
= timeval_current_ofs_usec(defer_time
);
1361 req
->async_te
= tevent_add_timer(req
->sconn
->ev_ctx
,
1363 smbd_smb2_request_pending_timer
,
1365 if (req
->async_te
== NULL
) {
1366 return NT_STATUS_NO_MEMORY
;
1369 return NT_STATUS_OK
;
1372 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
1373 struct tevent_timer
*te
,
1374 struct timeval current_time
,
1377 struct smbd_smb2_request
*req
=
1378 talloc_get_type_abort(private_data
,
1379 struct smbd_smb2_request
);
1380 struct smbd_server_connection
*sconn
= req
->sconn
;
1381 struct smbd_smb2_request_pending_state
*state
= NULL
;
1382 uint8_t *outhdr
= NULL
;
1383 const uint8_t *inhdr
= NULL
;
1386 uint8_t *hdr
= NULL
;
1387 uint8_t *body
= NULL
;
1388 uint8_t *dyn
= NULL
;
1390 uint64_t session_id
= 0;
1391 uint64_t message_id
= 0;
1392 uint64_t nonce_high
= 0;
1393 uint64_t nonce_low
= 0;
1394 uint64_t async_id
= 0;
1397 TALLOC_FREE(req
->async_te
);
1399 /* Ensure our final reply matches the interim one. */
1400 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1401 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1402 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1403 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1404 session_id
= BVAL(outhdr
, SMB2_HDR_SESSION_ID
);
1406 async_id
= message_id
; /* keep it simple for now... */
1408 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1409 SBVAL(outhdr
, SMB2_HDR_ASYNC_ID
, async_id
);
1411 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1413 smb2_opcode_name(SVAL(inhdr
, SMB2_HDR_OPCODE
)),
1414 (unsigned long long)async_id
));
1417 * What we send is identical to a smbd_smb2_request_error
1418 * packet with an error status of STATUS_PENDING. Make use
1419 * of this fact sometime when refactoring. JRA.
1422 state
= talloc_zero(req
->sconn
, struct smbd_smb2_request_pending_state
);
1423 if (state
== NULL
) {
1424 smbd_server_connection_terminate(req
->sconn
,
1425 nt_errstr(NT_STATUS_NO_MEMORY
));
1428 state
->sconn
= req
->sconn
;
1430 tf
= state
->buf
+ NBT_HDR_SIZE
;
1431 tf_len
= SMB2_TF_HDR_SIZE
;
1433 hdr
= tf
+ SMB2_TF_HDR_SIZE
;
1434 body
= hdr
+ SMB2_HDR_BODY
;
1437 if (req
->do_encryption
) {
1438 struct smbXsrv_session
*x
= req
->session
;
1440 nonce_high
= x
->nonce_high
;
1441 nonce_low
= x
->nonce_low
;
1444 if (x
->nonce_low
== 0) {
1450 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
1451 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
1452 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
1453 SBVAL(tf
, SMB2_TF_SESSION_ID
, session_id
);
1455 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
1456 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1457 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1458 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
1459 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(outhdr
, SMB2_HDR_OPCODE
));
1461 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
);
1462 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1463 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
1464 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
1465 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
1466 BVAL(outhdr
, SMB2_HDR_SESSION_ID
));
1467 memcpy(hdr
+SMB2_HDR_SIGNATURE
,
1468 outhdr
+SMB2_HDR_SIGNATURE
, 16);
1470 SSVAL(body
, 0x00, 0x08 + 1);
1472 SCVAL(body
, 0x02, 0);
1473 SCVAL(body
, 0x03, 0);
1474 SIVAL(body
, 0x04, 0);
1475 /* Match W2K8R2... */
1476 SCVAL(dyn
, 0x00, 0x21);
1478 state
->vector
[0].iov_base
= (void *)state
->buf
;
1479 state
->vector
[0].iov_len
= NBT_HDR_SIZE
;
1481 if (req
->do_encryption
) {
1482 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= tf
;
1483 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= tf_len
;
1485 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
1486 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
1489 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
1490 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
1492 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
1493 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_len
= 8;
1495 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
1496 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_len
= 1;
1498 smb2_setup_nbt_length(state
->vector
, 1 + SMBD_SMB2_NUM_IOV_PER_REQ
);
1500 /* Ensure we correctly go through crediting. Grant
1501 the credits now, and zero credits on the final
1503 smb2_set_operation_credit(req
->sconn
,
1504 SMBD_SMB2_IN_HDR_IOV(req
),
1505 &state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
]);
1507 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1512 for (i
= 0; i
< ARRAY_SIZE(state
->vector
); i
++) {
1513 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1515 (unsigned int)ARRAY_SIZE(state
->vector
),
1516 (unsigned int)state
->vector
[i
].iov_len
);
1520 if (req
->do_encryption
) {
1521 struct smbXsrv_session
*x
= req
->session
;
1522 struct smbXsrv_connection
*conn
= x
->connection
;
1523 DATA_BLOB encryption_key
= x
->global
->encryption_key
;
1525 status
= smb2_signing_encrypt_pdu(encryption_key
,
1527 &state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
],
1528 SMBD_SMB2_NUM_IOV_PER_REQ
);
1529 if (!NT_STATUS_IS_OK(status
)) {
1530 smbd_server_connection_terminate(req
->sconn
,
1534 } else if (req
->do_signing
) {
1535 struct smbXsrv_session
*x
= req
->session
;
1536 struct smbXsrv_connection
*conn
= x
->connection
;
1537 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
1539 status
= smb2_signing_sign_pdu(signing_key
,
1541 &state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
],
1542 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
1543 if (!NT_STATUS_IS_OK(status
)) {
1544 smbd_server_connection_terminate(req
->sconn
,
1550 state
->queue_entry
.mem_ctx
= state
;
1551 state
->queue_entry
.vector
= state
->vector
;
1552 state
->queue_entry
.count
= ARRAY_SIZE(state
->vector
);
1553 DLIST_ADD_END(sconn
->smb2
.send_queue
, &state
->queue_entry
, NULL
);
1554 sconn
->smb2
.send_queue_len
++;
1556 status
= smbd_smb2_io_handler(sconn
, TEVENT_FD_WRITE
);
1557 if (!NT_STATUS_IS_OK(status
)) {
1558 smbd_server_connection_terminate(sconn
,
1564 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
1566 struct smbd_server_connection
*sconn
= req
->sconn
;
1567 struct smbd_smb2_request
*cur
;
1568 const uint8_t *inhdr
;
1570 uint64_t search_message_id
;
1571 uint64_t search_async_id
;
1574 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1576 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1577 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1578 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
1581 * we don't need the request anymore
1582 * cancel requests never have a response
1584 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1587 for (cur
= sconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
1588 const uint8_t *outhdr
;
1589 uint64_t message_id
;
1592 if (cur
->compound_related
) {
1594 * Never cancel anything in a compound request.
1595 * Way too hard to deal with the result.
1600 outhdr
= SMBD_SMB2_OUT_HDR_PTR(cur
);
1602 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1603 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
1605 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1606 if (search_async_id
== async_id
) {
1607 found_id
= async_id
;
1611 if (search_message_id
== message_id
) {
1612 found_id
= message_id
;
1618 if (cur
&& cur
->subreq
) {
1619 inhdr
= SMBD_SMB2_IN_HDR_PTR(cur
);
1620 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1621 "cancel opcode[%s] mid %llu\n",
1622 smb2_opcode_name(SVAL(inhdr
, SMB2_HDR_OPCODE
)),
1623 (unsigned long long)found_id
));
1624 tevent_req_cancel(cur
->subreq
);
1627 return NT_STATUS_OK
;
1630 /*************************************************************
1631 Ensure an incoming tid is a valid one for us to access.
1632 Change to the associated uid credentials and chdir to the
1633 valid tid directory.
1634 *************************************************************/
1636 static NTSTATUS
smbd_smb2_request_check_tcon(struct smbd_smb2_request
*req
)
1638 const uint8_t *inhdr
;
1641 struct smbXsrv_tcon
*tcon
;
1643 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1647 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1649 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1650 in_tid
= IVAL(inhdr
, SMB2_HDR_TID
);
1652 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1653 in_tid
= req
->last_tid
;
1658 status
= smb2srv_tcon_lookup(req
->session
,
1659 in_tid
, now
, &tcon
);
1660 if (!NT_STATUS_IS_OK(status
)) {
1664 if (!change_to_user(tcon
->compat
, req
->session
->compat
->vuid
)) {
1665 return NT_STATUS_ACCESS_DENIED
;
1668 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1669 if (!set_current_service(tcon
->compat
, 0, true)) {
1670 return NT_STATUS_ACCESS_DENIED
;
1674 req
->last_tid
= in_tid
;
1676 return NT_STATUS_OK
;
1679 /*************************************************************
1680 Ensure an incoming session_id is a valid one for us to access.
1681 *************************************************************/
1683 static NTSTATUS
smbd_smb2_request_check_session(struct smbd_smb2_request
*req
)
1685 const uint8_t *inhdr
;
1688 uint64_t in_session_id
;
1689 struct smbXsrv_session
*session
= NULL
;
1690 struct auth_session_info
*session_info
;
1692 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1694 req
->session
= NULL
;
1697 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1699 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1700 in_opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1701 in_session_id
= BVAL(inhdr
, SMB2_HDR_SESSION_ID
);
1703 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1704 in_session_id
= req
->last_session_id
;
1707 req
->last_session_id
= 0;
1709 /* lookup an existing session */
1710 status
= smb2srv_session_lookup(req
->sconn
->conn
,
1714 req
->session
= session
;
1715 req
->last_session_id
= in_session_id
;
1717 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
1718 switch (in_opcode
) {
1719 case SMB2_OP_SESSSETUP
:
1720 status
= NT_STATUS_OK
;
1726 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1727 switch (in_opcode
) {
1729 case SMB2_OP_CREATE
:
1730 case SMB2_OP_GETINFO
:
1731 case SMB2_OP_SETINFO
:
1732 return NT_STATUS_INVALID_HANDLE
;
1735 * Notice the check for
1736 * (session_info == NULL)
1739 status
= NT_STATUS_OK
;
1743 if (!NT_STATUS_IS_OK(status
)) {
1747 session_info
= session
->global
->auth_session_info
;
1748 if (session_info
== NULL
) {
1749 return NT_STATUS_INVALID_HANDLE
;
1752 if (in_session_id
!= req
->sconn
->conn
->last_session_id
) {
1753 req
->sconn
->conn
->last_session_id
= in_session_id
;
1754 set_current_user_info(session_info
->unix_info
->sanitized_username
,
1755 session_info
->unix_info
->unix_name
,
1756 session_info
->info
->domain_name
);
1759 return NT_STATUS_OK
;
1762 NTSTATUS
smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request
*req
,
1763 uint32_t data_length
)
1765 uint16_t needed_charge
;
1766 uint16_t credit_charge
= 1;
1767 const uint8_t *inhdr
;
1769 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1771 if (req
->sconn
->smb2
.supports_multicredit
) {
1772 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
1773 credit_charge
= MAX(credit_charge
, 1);
1776 needed_charge
= (data_length
- 1)/ 65536 + 1;
1778 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1779 (unsigned long long) BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
),
1780 credit_charge
, needed_charge
));
1782 if (needed_charge
> credit_charge
) {
1783 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1784 credit_charge
, needed_charge
));
1785 return NT_STATUS_INVALID_PARAMETER
;
1788 return NT_STATUS_OK
;
1791 NTSTATUS
smbd_smb2_request_verify_sizes(struct smbd_smb2_request
*req
,
1792 size_t expected_body_size
)
1794 struct iovec
*inhdr_v
;
1795 const uint8_t *inhdr
;
1797 const uint8_t *inbody
;
1799 size_t min_dyn_size
= expected_body_size
& 0x00000001;
1800 int max_idx
= req
->in
.vector_count
- SMBD_SMB2_NUM_IOV_PER_REQ
;
1803 * The following should be checked already.
1805 if (req
->in
.vector_count
< SMBD_SMB2_NUM_IOV_PER_REQ
) {
1806 return NT_STATUS_INTERNAL_ERROR
;
1808 if (req
->current_idx
> max_idx
) {
1809 return NT_STATUS_INTERNAL_ERROR
;
1812 inhdr_v
= SMBD_SMB2_IN_HDR_IOV(req
);
1813 if (inhdr_v
->iov_len
!= SMB2_HDR_BODY
) {
1814 return NT_STATUS_INTERNAL_ERROR
;
1816 if (SMBD_SMB2_IN_BODY_LEN(req
) < 2) {
1817 return NT_STATUS_INTERNAL_ERROR
;
1820 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1821 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1825 case SMB2_OP_GETINFO
:
1831 * Now check the expected body size,
1832 * where the last byte might be in the
1835 if (SMBD_SMB2_IN_BODY_LEN(req
) != (expected_body_size
& 0xFFFFFFFE)) {
1836 return NT_STATUS_INVALID_PARAMETER
;
1838 if (SMBD_SMB2_IN_DYN_LEN(req
) < min_dyn_size
) {
1839 return NT_STATUS_INVALID_PARAMETER
;
1842 inbody
= SMBD_SMB2_IN_BODY_PTR(req
);
1844 body_size
= SVAL(inbody
, 0x00);
1845 if (body_size
!= expected_body_size
) {
1846 return NT_STATUS_INVALID_PARAMETER
;
1849 return NT_STATUS_OK
;
1852 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
1854 struct smbXsrv_connection
*conn
= req
->sconn
->conn
;
1855 const struct smbd_smb2_dispatch_table
*call
= NULL
;
1856 const struct iovec
*intf_v
= SMBD_SMB2_IN_TF_IOV(req
);
1857 const uint8_t *inhdr
;
1862 NTSTATUS session_status
;
1863 uint32_t allowed_flags
;
1864 NTSTATUS return_value
;
1865 struct smbXsrv_session
*x
= NULL
;
1866 bool signing_required
= false;
1867 bool encryption_required
= false;
1869 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1871 /* TODO: verify more things */
1873 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1874 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1875 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1876 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1877 smb2_opcode_name(opcode
),
1878 (unsigned long long)mid
));
1880 if (conn
->protocol
>= PROTOCOL_SMB2_02
) {
1882 * once the protocol is negotiated
1883 * SMB2_OP_NEGPROT is not allowed anymore
1885 if (opcode
== SMB2_OP_NEGPROT
) {
1886 /* drop the connection */
1887 return NT_STATUS_INVALID_PARAMETER
;
1891 * if the protocol is not negotiated yet
1892 * only SMB2_OP_NEGPROT is allowed.
1894 if (opcode
!= SMB2_OP_NEGPROT
) {
1895 /* drop the connection */
1896 return NT_STATUS_INVALID_PARAMETER
;
1901 * Check if the client provided a valid session id,
1902 * if so smbd_smb2_request_check_session() calls
1903 * set_current_user_info().
1905 * As some command don't require a valid session id
1906 * we defer the check of the session_status
1908 session_status
= smbd_smb2_request_check_session(req
);
1911 signing_required
= x
->global
->signing_required
;
1912 encryption_required
= x
->global
->encryption_required
;
1914 if (opcode
== SMB2_OP_SESSSETUP
&&
1915 x
->global
->channels
[0].signing_key
.length
) {
1916 signing_required
= true;
1920 req
->do_signing
= false;
1921 req
->do_encryption
= false;
1922 if (intf_v
->iov_len
== SMB2_TF_HDR_SIZE
) {
1923 const uint8_t *intf
= SMBD_SMB2_IN_TF_PTR(req
);
1924 uint64_t tf_session_id
= BVAL(intf
, SMB2_TF_SESSION_ID
);
1926 if (x
!= NULL
&& x
->global
->session_wire_id
!= tf_session_id
) {
1927 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1928 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1929 (unsigned long long)x
->global
->session_wire_id
,
1930 (unsigned long long)tf_session_id
));
1932 * TODO: windows allows this...
1933 * should we drop the connection?
1935 * For now we just return ACCESS_DENIED
1936 * (Windows clients never trigger this)
1937 * and wait for an update of [MS-SMB2].
1939 return smbd_smb2_request_error(req
,
1940 NT_STATUS_ACCESS_DENIED
);
1943 req
->do_encryption
= true;
1946 if (encryption_required
&& !req
->do_encryption
) {
1947 return smbd_smb2_request_error(req
,
1948 NT_STATUS_ACCESS_DENIED
);
1951 call
= smbd_smb2_call(opcode
);
1953 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1956 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
1957 SMB2_HDR_FLAG_SIGNED
|
1959 if (opcode
== SMB2_OP_CANCEL
) {
1960 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
1962 if ((flags
& ~allowed_flags
) != 0) {
1963 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1966 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
1968 * This check is mostly for giving the correct error code
1969 * for compounded requests.
1971 if (!NT_STATUS_IS_OK(session_status
)) {
1972 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1975 req
->compat_chain_fsp
= NULL
;
1978 if (req
->do_encryption
) {
1979 signing_required
= false;
1980 } else if (flags
& SMB2_HDR_FLAG_SIGNED
) {
1981 DATA_BLOB signing_key
;
1984 return smbd_smb2_request_error(
1985 req
, NT_STATUS_ACCESS_DENIED
);
1988 signing_key
= x
->global
->channels
[0].signing_key
;
1991 * If we have a signing key, we should
1994 if (signing_key
.length
> 0) {
1995 req
->do_signing
= true;
1998 status
= smb2_signing_check_pdu(signing_key
,
2000 SMBD_SMB2_IN_HDR_IOV(req
),
2001 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2002 if (!NT_STATUS_IS_OK(status
)) {
2003 return smbd_smb2_request_error(req
, status
);
2007 * Now that we know the request was correctly signed
2008 * we have to sign the response too.
2010 req
->do_signing
= true;
2012 if (!NT_STATUS_IS_OK(session_status
)) {
2013 return smbd_smb2_request_error(req
, session_status
);
2015 } else if (opcode
== SMB2_OP_CANCEL
) {
2016 /* Cancel requests are allowed to skip the signing */
2017 } else if (signing_required
) {
2019 * If signing is required we try to sign
2020 * a possible error response
2022 req
->do_signing
= true;
2023 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
2026 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
2027 req
->compound_related
= true;
2030 if (call
->need_session
) {
2031 if (!NT_STATUS_IS_OK(session_status
)) {
2032 return smbd_smb2_request_error(req
, session_status
);
2036 if (call
->need_tcon
) {
2037 SMB_ASSERT(call
->need_session
);
2040 * This call needs to be run as user.
2042 * smbd_smb2_request_check_tcon()
2043 * calls change_to_user() on success.
2045 status
= smbd_smb2_request_check_tcon(req
);
2046 if (!NT_STATUS_IS_OK(status
)) {
2047 return smbd_smb2_request_error(req
, status
);
2049 if (req
->tcon
->global
->encryption_required
) {
2050 encryption_required
= true;
2052 if (encryption_required
&& !req
->do_encryption
) {
2053 return smbd_smb2_request_error(req
,
2054 NT_STATUS_ACCESS_DENIED
);
2058 if (call
->fileid_ofs
!= 0) {
2059 size_t needed
= call
->fileid_ofs
+ 16;
2060 const uint8_t *body
= SMBD_SMB2_IN_BODY_PTR(req
);
2061 size_t body_size
= SMBD_SMB2_IN_BODY_LEN(req
);
2062 uint64_t file_id_persistent
;
2063 uint64_t file_id_volatile
;
2064 struct files_struct
*fsp
;
2066 SMB_ASSERT(call
->need_tcon
);
2068 if (needed
> body_size
) {
2069 return smbd_smb2_request_error(req
,
2070 NT_STATUS_INVALID_PARAMETER
);
2073 file_id_persistent
= BVAL(body
, call
->fileid_ofs
+ 0);
2074 file_id_volatile
= BVAL(body
, call
->fileid_ofs
+ 8);
2076 fsp
= file_fsp_smb2(req
, file_id_persistent
, file_id_volatile
);
2078 if (!call
->allow_invalid_fileid
) {
2079 return smbd_smb2_request_error(req
,
2080 NT_STATUS_FILE_CLOSED
);
2083 if (file_id_persistent
!= UINT64_MAX
) {
2084 return smbd_smb2_request_error(req
,
2085 NT_STATUS_FILE_CLOSED
);
2087 if (file_id_volatile
!= UINT64_MAX
) {
2088 return smbd_smb2_request_error(req
,
2089 NT_STATUS_FILE_CLOSED
);
2094 if (call
->as_root
) {
2095 SMB_ASSERT(call
->fileid_ofs
== 0);
2096 /* This call needs to be run as root */
2097 change_to_root_user();
2099 SMB_ASSERT(call
->need_tcon
);
2103 case SMB2_OP_NEGPROT
:
2105 START_PROFILE(smb2_negprot
);
2106 return_value
= smbd_smb2_request_process_negprot(req
);
2107 END_PROFILE(smb2_negprot
);
2111 case SMB2_OP_SESSSETUP
:
2113 START_PROFILE(smb2_sesssetup
);
2114 return_value
= smbd_smb2_request_process_sesssetup(req
);
2115 END_PROFILE(smb2_sesssetup
);
2119 case SMB2_OP_LOGOFF
:
2121 START_PROFILE(smb2_logoff
);
2122 return_value
= smbd_smb2_request_process_logoff(req
);
2123 END_PROFILE(smb2_logoff
);
2129 START_PROFILE(smb2_tcon
);
2130 return_value
= smbd_smb2_request_process_tcon(req
);
2131 END_PROFILE(smb2_tcon
);
2137 START_PROFILE(smb2_tdis
);
2138 return_value
= smbd_smb2_request_process_tdis(req
);
2139 END_PROFILE(smb2_tdis
);
2143 case SMB2_OP_CREATE
:
2145 START_PROFILE(smb2_create
);
2146 return_value
= smbd_smb2_request_process_create(req
);
2147 END_PROFILE(smb2_create
);
2153 START_PROFILE(smb2_close
);
2154 return_value
= smbd_smb2_request_process_close(req
);
2155 END_PROFILE(smb2_close
);
2161 START_PROFILE(smb2_flush
);
2162 return_value
= smbd_smb2_request_process_flush(req
);
2163 END_PROFILE(smb2_flush
);
2169 START_PROFILE(smb2_read
);
2170 return_value
= smbd_smb2_request_process_read(req
);
2171 END_PROFILE(smb2_read
);
2177 START_PROFILE(smb2_write
);
2178 return_value
= smbd_smb2_request_process_write(req
);
2179 END_PROFILE(smb2_write
);
2185 START_PROFILE(smb2_lock
);
2186 return_value
= smbd_smb2_request_process_lock(req
);
2187 END_PROFILE(smb2_lock
);
2193 START_PROFILE(smb2_ioctl
);
2194 return_value
= smbd_smb2_request_process_ioctl(req
);
2195 END_PROFILE(smb2_ioctl
);
2199 case SMB2_OP_CANCEL
:
2201 START_PROFILE(smb2_cancel
);
2202 return_value
= smbd_smb2_request_process_cancel(req
);
2203 END_PROFILE(smb2_cancel
);
2207 case SMB2_OP_KEEPALIVE
:
2209 START_PROFILE(smb2_keepalive
);
2210 return_value
= smbd_smb2_request_process_keepalive(req
);
2211 END_PROFILE(smb2_keepalive
);
2217 START_PROFILE(smb2_find
);
2218 return_value
= smbd_smb2_request_process_find(req
);
2219 END_PROFILE(smb2_find
);
2223 case SMB2_OP_NOTIFY
:
2225 START_PROFILE(smb2_notify
);
2226 return_value
= smbd_smb2_request_process_notify(req
);
2227 END_PROFILE(smb2_notify
);
2231 case SMB2_OP_GETINFO
:
2233 START_PROFILE(smb2_getinfo
);
2234 return_value
= smbd_smb2_request_process_getinfo(req
);
2235 END_PROFILE(smb2_getinfo
);
2239 case SMB2_OP_SETINFO
:
2241 START_PROFILE(smb2_setinfo
);
2242 return_value
= smbd_smb2_request_process_setinfo(req
);
2243 END_PROFILE(smb2_setinfo
);
2249 START_PROFILE(smb2_break
);
2250 return_value
= smbd_smb2_request_process_break(req
);
2251 END_PROFILE(smb2_break
);
2256 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2259 return return_value
;
2262 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
2264 struct smbd_server_connection
*sconn
= req
->sconn
;
2265 struct smbXsrv_connection
*conn
= req
->sconn
->conn
;
2267 struct iovec
*firsttf
= SMBD_SMB2_IDX_TF_IOV(req
,out
,first_idx
);
2268 struct iovec
*outhdr
= SMBD_SMB2_OUT_HDR_IOV(req
);
2269 struct iovec
*outdyn
= SMBD_SMB2_OUT_DYN_IOV(req
);
2273 TALLOC_FREE(req
->async_te
);
2275 if (req
->do_encryption
&&
2276 (firsttf
->iov_len
== 0) &&
2277 (req
->first_key
.length
== 0) &&
2278 (req
->session
!= NULL
) &&
2279 (req
->session
->global
->encryption_key
.length
!= 0))
2281 DATA_BLOB encryption_key
= req
->session
->global
->encryption_key
;
2283 uint64_t session_id
= req
->session
->global
->session_wire_id
;
2284 struct smbXsrv_session
*x
= req
->session
;
2285 uint64_t nonce_high
;
2288 nonce_high
= x
->nonce_high
;
2289 nonce_low
= x
->nonce_low
;
2292 if (x
->nonce_low
== 0) {
2298 * We need to place the SMB2_TRANSFORM header before the
2303 * we need to remember the encryption key
2304 * and defer the signing/encryption until
2305 * we are sure that we do not change
2308 req
->first_key
= data_blob_dup_talloc(req
, encryption_key
);
2309 if (req
->first_key
.data
== NULL
) {
2310 return NT_STATUS_NO_MEMORY
;
2313 tf
= talloc_zero_array(req
->out
.vector
, uint8_t,
2316 return NT_STATUS_NO_MEMORY
;
2319 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
2320 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
2321 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
2322 SBVAL(tf
, SMB2_TF_SESSION_ID
, session_id
);
2324 firsttf
->iov_base
= (void *)tf
;
2325 firsttf
->iov_len
= SMB2_TF_HDR_SIZE
;
2328 if ((req
->current_idx
> SMBD_SMB2_NUM_IOV_PER_REQ
) &&
2329 (req
->last_key
.length
> 0) &&
2330 (firsttf
->iov_len
== 0))
2332 int last_idx
= req
->current_idx
- SMBD_SMB2_NUM_IOV_PER_REQ
;
2333 struct iovec
*lasthdr
= SMBD_SMB2_IDX_HDR_IOV(req
,out
,last_idx
);
2336 * As we are sure the header of the last request in the
2337 * compound chain will not change, we can to sign here
2338 * with the last signing key we remembered.
2340 status
= smb2_signing_sign_pdu(req
->last_key
,
2343 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2344 if (!NT_STATUS_IS_OK(status
)) {
2348 data_blob_clear_free(&req
->last_key
);
2350 req
->current_idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
;
2352 if (req
->current_idx
< req
->out
.vector_count
) {
2354 * We must process the remaining compound
2355 * SMB2 requests before any new incoming SMB2
2356 * requests. This is because incoming SMB2
2357 * requests may include a cancel for a
2358 * compound request we haven't processed
2361 struct tevent_immediate
*im
= tevent_create_immediate(req
);
2363 return NT_STATUS_NO_MEMORY
;
2366 if (req
->do_signing
&& firsttf
->iov_len
== 0) {
2367 struct smbXsrv_session
*x
= req
->session
;
2368 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
2371 * we need to remember the signing key
2372 * and defer the signing until
2373 * we are sure that we do not change
2376 req
->last_key
= data_blob_dup_talloc(req
, signing_key
);
2377 if (req
->last_key
.data
== NULL
) {
2378 return NT_STATUS_NO_MEMORY
;
2382 tevent_schedule_immediate(im
,
2384 smbd_smb2_request_dispatch_immediate
,
2386 return NT_STATUS_OK
;
2389 if (req
->compound_related
) {
2390 req
->compound_related
= false;
2393 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
2395 /* Set credit for these operations (zero credits if this
2396 is a final reply for an async operation). */
2397 smb2_calculate_credits(req
, req
);
2400 * now check if we need to sign the current response
2402 if (firsttf
->iov_len
== SMB2_TF_HDR_SIZE
) {
2403 status
= smb2_signing_encrypt_pdu(req
->first_key
,
2406 req
->out
.vector_count
- first_idx
);
2407 if (!NT_STATUS_IS_OK(status
)) {
2410 } else if (req
->do_signing
) {
2411 struct smbXsrv_session
*x
= req
->session
;
2412 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
2414 status
= smb2_signing_sign_pdu(signing_key
,
2417 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2418 if (!NT_STATUS_IS_OK(status
)) {
2422 data_blob_clear_free(&req
->first_key
);
2424 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2425 if (req
->out
.vector_count
< (2*SMBD_SMB2_NUM_IOV_PER_REQ
) &&
2426 outdyn
->iov_base
== NULL
&& outdyn
->iov_len
!= 0) {
2427 /* Dynamic part is NULL. Chop it off,
2428 We're going to send it via sendfile. */
2429 req
->out
.vector_count
-= 1;
2433 * We're done with this request -
2434 * move it off the "being processed" queue.
2436 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
2438 req
->queue_entry
.mem_ctx
= req
;
2439 req
->queue_entry
.vector
= req
->out
.vector
;
2440 req
->queue_entry
.count
= req
->out
.vector_count
;
2441 DLIST_ADD_END(req
->sconn
->smb2
.send_queue
, &req
->queue_entry
, NULL
);
2442 req
->sconn
->smb2
.send_queue_len
++;
2444 status
= smbd_smb2_io_handler(sconn
, TEVENT_FD_WRITE
);
2445 if (!NT_STATUS_IS_OK(status
)) {
2449 return NT_STATUS_OK
;
2452 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
);
2454 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
2455 struct tevent_immediate
*im
,
2458 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
2459 struct smbd_smb2_request
);
2460 struct smbd_server_connection
*sconn
= req
->sconn
;
2465 if (DEBUGLEVEL
>= 10) {
2466 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2467 req
->current_idx
, req
->in
.vector_count
));
2468 print_req_vectors(req
);
2471 status
= smbd_smb2_request_dispatch(req
);
2472 if (!NT_STATUS_IS_OK(status
)) {
2473 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2477 status
= smbd_smb2_request_next_incoming(sconn
);
2478 if (!NT_STATUS_IS_OK(status
)) {
2479 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2484 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
2486 DATA_BLOB body
, DATA_BLOB
*dyn
,
2487 const char *location
)
2490 struct iovec
*outbody_v
;
2491 struct iovec
*outdyn_v
;
2492 uint32_t next_command_ofs
;
2494 DEBUG(10,("smbd_smb2_request_done_ex: "
2495 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2496 req
->current_idx
, nt_errstr(status
), (unsigned int)body
.length
,
2498 (unsigned int)(dyn
? dyn
->length
: 0),
2501 if (body
.length
< 2) {
2502 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2505 if ((body
.length
% 2) != 0) {
2506 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2509 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
2510 outbody_v
= SMBD_SMB2_OUT_BODY_IOV(req
);
2511 outdyn_v
= SMBD_SMB2_OUT_DYN_IOV(req
);
2513 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
2514 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
2516 outbody_v
->iov_base
= (void *)body
.data
;
2517 outbody_v
->iov_len
= body
.length
;
2520 outdyn_v
->iov_base
= (void *)dyn
->data
;
2521 outdyn_v
->iov_len
= dyn
->length
;
2523 outdyn_v
->iov_base
= NULL
;
2524 outdyn_v
->iov_len
= 0;
2527 /* see if we need to recalculate the offset to the next response */
2528 if (next_command_ofs
> 0) {
2529 next_command_ofs
= SMB2_HDR_BODY
;
2530 next_command_ofs
+= SMBD_SMB2_OUT_BODY_LEN(req
);
2531 next_command_ofs
+= SMBD_SMB2_OUT_DYN_LEN(req
);
2534 if ((next_command_ofs
% 8) != 0) {
2535 size_t pad_size
= 8 - (next_command_ofs
% 8);
2536 if (SMBD_SMB2_OUT_DYN_LEN(req
) == 0) {
2538 * if the dyn buffer is empty
2539 * we can use it to add padding
2543 pad
= talloc_zero_array(req
->out
.vector
,
2546 return smbd_smb2_request_error(req
,
2547 NT_STATUS_NO_MEMORY
);
2550 outdyn_v
->iov_base
= (void *)pad
;
2551 outdyn_v
->iov_len
= pad_size
;
2554 * For now we copy the dynamic buffer
2555 * and add the padding to the new buffer
2562 old_size
= SMBD_SMB2_OUT_DYN_LEN(req
);
2563 old_dyn
= SMBD_SMB2_OUT_DYN_PTR(req
);
2565 new_size
= old_size
+ pad_size
;
2566 new_dyn
= talloc_zero_array(req
->out
.vector
,
2568 if (new_dyn
== NULL
) {
2569 return smbd_smb2_request_error(req
,
2570 NT_STATUS_NO_MEMORY
);
2573 memcpy(new_dyn
, old_dyn
, old_size
);
2574 memset(new_dyn
+ old_size
, 0, pad_size
);
2576 outdyn_v
->iov_base
= (void *)new_dyn
;
2577 outdyn_v
->iov_len
= new_size
;
2579 next_command_ofs
+= pad_size
;
2582 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
2584 return smbd_smb2_request_reply(req
);
2587 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
2590 const char *location
)
2593 uint8_t *outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
2594 size_t unread_bytes
= smbd_smb2_unread_bytes(req
);
2596 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2597 req
->current_idx
, nt_errstr(status
), info
? " +info" : "",
2601 /* Recvfile error. Drain incoming socket. */
2605 ret
= drain_socket(req
->sconn
->sock
, unread_bytes
);
2606 if (ret
!= unread_bytes
) {
2610 error
= NT_STATUS_IO_DEVICE_ERROR
;
2612 error
= map_nt_error_from_unix_common(errno
);
2615 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2616 "ret[%u] errno[%d] => %s\n",
2617 (unsigned)unread_bytes
,
2618 (unsigned)ret
, errno
, nt_errstr(error
)));
2623 body
.data
= outhdr
+ SMB2_HDR_BODY
;
2625 SSVAL(body
.data
, 0, 9);
2628 SIVAL(body
.data
, 0x04, info
->length
);
2630 /* Allocated size of req->out.vector[i].iov_base
2631 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2632 * 1 byte without having to do an alloc.
2634 info
= talloc_zero_array(req
->out
.vector
,
2638 return NT_STATUS_NO_MEMORY
;
2640 info
->data
= ((uint8_t *)outhdr
) +
2641 OUTVEC_ALLOC_SIZE
- 1;
2643 SCVAL(info
->data
, 0, 0);
2647 * Note: Even if there is an error, continue to process the request.
2651 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
2655 struct smbd_smb2_send_oplock_break_state
{
2656 struct smbd_server_connection
*sconn
;
2657 struct smbd_smb2_send_queue queue_entry
;
2658 uint8_t buf
[NBT_HDR_SIZE
+ SMB2_TF_HDR_SIZE
+ SMB2_HDR_BODY
+ 0x18];
2659 struct iovec vector
[1+SMBD_SMB2_NUM_IOV_PER_REQ
];
2662 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
2663 struct smbXsrv_session
*session
,
2664 struct smbXsrv_tcon
*tcon
,
2665 struct smbXsrv_open
*op
,
2666 uint8_t oplock_level
)
2668 struct smbd_smb2_send_oplock_break_state
*state
;
2669 struct smbXsrv_connection
*conn
= sconn
->conn
;
2677 bool do_encryption
= session
->global
->encryption_required
;
2678 uint64_t nonce_high
= 0;
2679 uint64_t nonce_low
= 0;
2682 if (tcon
->global
->encryption_required
) {
2683 do_encryption
= true;
2686 state
= talloc_zero(sconn
, struct smbd_smb2_send_oplock_break_state
);
2687 if (state
== NULL
) {
2688 return NT_STATUS_NO_MEMORY
;
2690 state
->sconn
= sconn
;
2692 tf
= state
->buf
+ NBT_HDR_SIZE
;
2693 tf_len
= SMB2_TF_HDR_SIZE
;
2695 body
= hdr
+ SMB2_HDR_BODY
;
2697 dyn
= body
+ body_len
;
2700 if (do_encryption
) {
2701 nonce_high
= session
->nonce_high
;
2702 nonce_low
= session
->nonce_low
;
2704 session
->nonce_low
+= 1;
2705 if (session
->nonce_low
== 0) {
2706 session
->nonce_low
+= 1;
2707 session
->nonce_high
+= 1;
2711 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
2712 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
2713 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
2714 SBVAL(tf
, SMB2_TF_SESSION_ID
, session
->global
->session_wire_id
);
2716 SIVAL(hdr
, 0, SMB2_MAGIC
);
2717 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
2718 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
2719 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
2720 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
2721 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
2722 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
2723 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
2724 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
2725 SIVAL(hdr
, SMB2_HDR_PID
, 0);
2726 SIVAL(hdr
, SMB2_HDR_TID
, 0);
2727 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
2728 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
2730 SSVAL(body
, 0x00, body_len
);
2732 SCVAL(body
, 0x02, oplock_level
);
2733 SCVAL(body
, 0x03, 0); /* reserved */
2734 SIVAL(body
, 0x04, 0); /* reserved */
2735 SBVAL(body
, 0x08, op
->global
->open_persistent_id
);
2736 SBVAL(body
, 0x10, op
->global
->open_volatile_id
);
2738 state
->vector
[0].iov_base
= (void *)state
->buf
;
2739 state
->vector
[0].iov_len
= NBT_HDR_SIZE
;
2741 if (do_encryption
) {
2742 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= tf
;
2743 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= tf_len
;
2745 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
2746 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
2749 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
2750 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
2752 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
2753 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_len
= body_len
;
2755 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
2756 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_len
= dyn_len
;
2758 smb2_setup_nbt_length(state
->vector
, 1 + SMBD_SMB2_NUM_IOV_PER_REQ
);
2760 if (do_encryption
) {
2761 DATA_BLOB encryption_key
= session
->global
->encryption_key
;
2763 status
= smb2_signing_encrypt_pdu(encryption_key
,
2765 &state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
],
2766 SMBD_SMB2_NUM_IOV_PER_REQ
);
2767 if (!NT_STATUS_IS_OK(status
)) {
2772 state
->queue_entry
.mem_ctx
= state
;
2773 state
->queue_entry
.vector
= state
->vector
;
2774 state
->queue_entry
.count
= ARRAY_SIZE(state
->vector
);
2775 DLIST_ADD_END(state
->sconn
->smb2
.send_queue
, &state
->queue_entry
, NULL
);
2776 state
->sconn
->smb2
.send_queue_len
++;
2778 status
= smbd_smb2_io_handler(sconn
, TEVENT_FD_WRITE
);
2779 if (!NT_STATUS_IS_OK(status
)) {
2783 return NT_STATUS_OK
;
2786 static size_t get_min_receive_file_size(struct smbd_smb2_request
*smb2_req
)
2788 if (smb2_req
->do_signing
) {
2791 if (smb2_req
->do_encryption
) {
2794 return (size_t)lp_min_receive_file_size();
2797 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state
*state
)
2801 if (IVAL(state
->pktbuf
, 0) == SMB2_TF_MAGIC
) {
2802 /* Transform header. Cannot recvfile. */
2805 if (IVAL(state
->pktbuf
, 0) != SMB2_MAGIC
) {
2806 /* Not SMB2. Normal error path will cope. */
2809 if (SVAL(state
->pktbuf
, 4) != SMB2_HDR_BODY
) {
2810 /* Not SMB2. Normal error path will cope. */
2813 if (SVAL(state
->pktbuf
, SMB2_HDR_OPCODE
) != SMB2_OP_WRITE
) {
2814 /* Needs to be a WRITE. */
2817 if (IVAL(state
->pktbuf
, SMB2_HDR_NEXT_COMMAND
) != 0) {
2818 /* Chained. Cannot recvfile. */
2821 flags
= IVAL(state
->pktbuf
, SMB2_HDR_FLAGS
);
2822 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
2823 /* Chained. Cannot recvfile. */
2826 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
2827 /* Signed. Cannot recvfile. */
2831 DEBUG(10,("Doing recvfile write len = %u\n",
2832 (unsigned int)(state
->pktlen
-
2833 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
)));
2838 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
)
2840 struct smbd_smb2_request_read_state
*state
= &sconn
->smb2
.request_read_state
;
2841 size_t max_send_queue_len
;
2842 size_t cur_send_queue_len
;
2844 if (!NT_STATUS_IS_OK(sconn
->status
)) {
2846 * we're not supposed to do any io
2848 return NT_STATUS_OK
;
2851 if (state
->req
!= NULL
) {
2853 * if there is already a tstream_readv_pdu
2854 * pending, we are done.
2856 return NT_STATUS_OK
;
2859 max_send_queue_len
= MAX(1, sconn
->smb2
.max_credits
/16);
2860 cur_send_queue_len
= sconn
->smb2
.send_queue_len
;
2862 if (cur_send_queue_len
> max_send_queue_len
) {
2864 * if we have a lot of requests to send,
2865 * we wait until they are on the wire until we
2866 * ask for the next request.
2868 return NT_STATUS_OK
;
2871 /* ask for the next request */
2872 ZERO_STRUCTP(state
);
2873 state
->req
= smbd_smb2_request_allocate(sconn
);
2874 if (state
->req
== NULL
) {
2875 return NT_STATUS_NO_MEMORY
;
2877 state
->req
->sconn
= sconn
;
2878 state
->min_recv_size
= get_min_receive_file_size(state
->req
);
2880 TEVENT_FD_READABLE(sconn
->smb2
.fde
);
2882 return NT_STATUS_OK
;
2885 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
2886 uint8_t *inbuf
, size_t size
)
2889 struct smbd_smb2_request
*req
= NULL
;
2891 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2892 (unsigned int)size
));
2894 status
= smbd_initialize_smb2(sconn
);
2895 if (!NT_STATUS_IS_OK(status
)) {
2896 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2900 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
2901 if (!NT_STATUS_IS_OK(status
)) {
2902 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2906 status
= smbd_smb2_request_validate(req
);
2907 if (!NT_STATUS_IS_OK(status
)) {
2908 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2912 status
= smbd_smb2_request_setup_out(req
);
2913 if (!NT_STATUS_IS_OK(status
)) {
2914 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2918 status
= smbd_smb2_request_dispatch(req
);
2919 if (!NT_STATUS_IS_OK(status
)) {
2920 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2924 status
= smbd_smb2_request_next_incoming(sconn
);
2925 if (!NT_STATUS_IS_OK(status
)) {
2926 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2930 sconn
->num_requests
++;
2933 static int socket_error_from_errno(int ret
,
2947 if (sys_errno
== 0) {
2951 if (sys_errno
== EINTR
) {
2956 if (sys_errno
== EINPROGRESS
) {
2961 if (sys_errno
== EAGAIN
) {
2966 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
2967 if (sys_errno
== ENOMEM
) {
2973 if (sys_errno
== EWOULDBLOCK
) {
2982 static NTSTATUS
smbd_smb2_flush_send_queue(struct smbd_server_connection
*sconn
)
2988 if (sconn
->smb2
.send_queue
== NULL
) {
2989 TEVENT_FD_NOT_WRITEABLE(sconn
->smb2
.fde
);
2990 return NT_STATUS_OK
;
2993 while (sconn
->smb2
.send_queue
!= NULL
) {
2994 struct smbd_smb2_send_queue
*e
= sconn
->smb2
.send_queue
;
2996 if (e
->sendfile_header
!= NULL
) {
3001 for (i
=0; i
< e
->count
; i
++) {
3002 size
+= e
->vector
[i
].iov_len
;
3005 buf
= talloc_array(e
->mem_ctx
, uint8_t, size
);
3007 return NT_STATUS_NO_MEMORY
;
3011 for (i
=0; i
< e
->count
; i
++) {
3013 e
->vector
[i
].iov_base
,
3014 e
->vector
[i
].iov_len
);
3015 size
+= e
->vector
[i
].iov_len
;
3018 e
->sendfile_header
->data
= buf
;
3019 e
->sendfile_header
->length
= size
;
3022 sconn
->smb2
.send_queue_len
--;
3023 DLIST_REMOVE(sconn
->smb2
.send_queue
, e
);
3024 talloc_free(e
->mem_ctx
);
3028 ret
= writev(sconn
->sock
, e
->vector
, e
->count
);
3030 /* propagate end of file */
3031 return NT_STATUS_INTERNAL_ERROR
;
3033 err
= socket_error_from_errno(ret
, errno
, &retry
);
3036 TEVENT_FD_WRITEABLE(sconn
->smb2
.fde
);
3037 return NT_STATUS_OK
;
3040 return map_nt_error_from_unix_common(err
);
3043 if (ret
< e
->vector
[0].iov_len
) {
3045 base
= (uint8_t *)e
->vector
[0].iov_base
;
3047 e
->vector
[0].iov_base
= (void *)base
;
3048 e
->vector
[0].iov_len
-= ret
;
3051 ret
-= e
->vector
[0].iov_len
;
3057 * there're maybe some empty vectors at the end
3058 * which we need to skip, otherwise we would get
3059 * ret == 0 from the readv() call and return EPIPE
3061 while (e
->count
> 0) {
3062 if (e
->vector
[0].iov_len
> 0) {
3070 /* we have more to write */
3071 TEVENT_FD_WRITEABLE(sconn
->smb2
.fde
);
3072 return NT_STATUS_OK
;
3075 sconn
->smb2
.send_queue_len
--;
3076 DLIST_REMOVE(sconn
->smb2
.send_queue
, e
);
3077 talloc_free(e
->mem_ctx
);
3080 return NT_STATUS_OK
;
3083 static NTSTATUS
smbd_smb2_io_handler(struct smbd_server_connection
*sconn
,
3086 struct smbd_smb2_request_read_state
*state
= &sconn
->smb2
.request_read_state
;
3087 struct smbd_smb2_request
*req
= NULL
;
3088 size_t min_recvfile_size
= UINT32_MAX
;
3095 if (!NT_STATUS_IS_OK(sconn
->status
)) {
3097 * we're not supposed to do any io
3099 TEVENT_FD_NOT_READABLE(sconn
->smb2
.fde
);
3100 TEVENT_FD_NOT_WRITEABLE(sconn
->smb2
.fde
);
3101 return NT_STATUS_OK
;
3104 if (fde_flags
& TEVENT_FD_WRITE
) {
3105 status
= smbd_smb2_flush_send_queue(sconn
);
3106 if (!NT_STATUS_IS_OK(status
)) {
3111 if (!(fde_flags
& TEVENT_FD_READ
)) {
3112 return NT_STATUS_OK
;
3115 if (state
->req
== NULL
) {
3116 TEVENT_FD_NOT_READABLE(sconn
->smb2
.fde
);
3117 return NT_STATUS_OK
;
3121 if (!state
->hdr
.done
) {
3122 state
->hdr
.done
= true;
3124 state
->vector
.iov_base
= (void *)state
->hdr
.nbt
;
3125 state
->vector
.iov_len
= NBT_HDR_SIZE
;
3128 ret
= readv(sconn
->sock
, &state
->vector
, 1);
3130 /* propagate end of file */
3131 return NT_STATUS_END_OF_FILE
;
3133 err
= socket_error_from_errno(ret
, errno
, &retry
);
3136 TEVENT_FD_READABLE(sconn
->smb2
.fde
);
3137 return NT_STATUS_OK
;
3140 return map_nt_error_from_unix_common(err
);
3143 if (ret
< state
->vector
.iov_len
) {
3145 base
= (uint8_t *)state
->vector
.iov_base
;
3147 state
->vector
.iov_base
= (void *)base
;
3148 state
->vector
.iov_len
-= ret
;
3149 /* we have more to read */
3150 TEVENT_FD_READABLE(sconn
->smb2
.fde
);
3151 return NT_STATUS_OK
;
3154 if (state
->pktlen
> 0) {
3155 if (state
->doing_receivefile
&& !is_smb2_recvfile_write(state
)) {
3157 * Not a possible receivefile write.
3158 * Read the rest of the data.
3160 state
->doing_receivefile
= false;
3161 state
->vector
.iov_base
= (void *)(state
->pktbuf
+
3162 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
);
3163 state
->vector
.iov_len
= (state
->pktlen
-
3164 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
);
3169 * Either this is a receivefile write so we've
3170 * done a short read, or if not we have all the data.
3176 * Now we analyze the NBT header
3178 state
->pktlen
= smb2_len(state
->hdr
.nbt
);
3179 if (state
->pktlen
== 0) {
3183 state
->pktbuf
= talloc_array(state
->req
, uint8_t, state
->pktlen
);
3184 if (state
->pktbuf
== NULL
) {
3185 return NT_STATUS_NO_MEMORY
;
3188 state
->vector
.iov_base
= (void *)state
->pktbuf
;
3190 if (state
->min_recv_size
!= 0) {
3191 min_recvfile_size
= SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
;
3192 min_recvfile_size
+= state
->min_recv_size
;
3195 if (state
->pktlen
> min_recvfile_size
) {
3197 * Might be a receivefile write. Read the SMB2 HEADER +
3198 * SMB2_WRITE header first. Set 'doing_receivefile'
3199 * as we're *attempting* receivefile write. If this
3200 * turns out not to be a SMB2_WRITE request or otherwise
3201 * not suitable then we'll just read the rest of the data
3202 * the next time this function is called.
3204 state
->vector
.iov_len
= SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
;
3205 state
->doing_receivefile
= true;
3207 state
->vector
.iov_len
= state
->pktlen
;
3214 if (state
->hdr
.nbt
[0] != 0x00) {
3215 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3216 state
->hdr
.nbt
[0]));
3219 ZERO_STRUCTP(state
);
3221 state
->min_recv_size
= get_min_receive_file_size(state
->req
);
3229 req
->request_time
= timeval_current();
3230 now
= timeval_to_nttime(&req
->request_time
);
3232 status
= smbd_smb2_inbuf_parse_compound(req
->sconn
->conn
,
3238 &req
->in
.vector_count
);
3239 if (!NT_STATUS_IS_OK(status
)) {
3243 if (state
->doing_receivefile
) {
3244 req
->smb1req
= talloc_zero(req
, struct smb_request
);
3245 if (req
->smb1req
== NULL
) {
3246 return NT_STATUS_NO_MEMORY
;
3248 req
->smb1req
->unread_bytes
=
3249 state
->pktlen
- SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
;
3252 ZERO_STRUCTP(state
);
3254 req
->current_idx
= 1;
3256 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3257 req
->current_idx
, req
->in
.vector_count
));
3259 status
= smbd_smb2_request_validate(req
);
3260 if (!NT_STATUS_IS_OK(status
)) {
3264 status
= smbd_smb2_request_setup_out(req
);
3265 if (!NT_STATUS_IS_OK(status
)) {
3269 status
= smbd_smb2_request_dispatch(req
);
3270 if (!NT_STATUS_IS_OK(status
)) {
3274 sconn
->num_requests
++;
3276 /* The timeout_processing function isn't run nearly
3277 often enough to implement 'max log size' without
3278 overrunning the size of the file by many megabytes.
3279 This is especially true if we are running at debug
3280 level 10. Checking every 50 SMB2s is a nice
3281 tradeoff of performance vs log file size overrun. */
3283 if ((sconn
->num_requests
% 50) == 0 &&
3284 need_to_check_log_size()) {
3285 change_to_root_user();
3289 status
= smbd_smb2_request_next_incoming(sconn
);
3290 if (!NT_STATUS_IS_OK(status
)) {
3294 return NT_STATUS_OK
;
3297 static void smbd_smb2_connection_handler(struct tevent_context
*ev
,
3298 struct tevent_fd
*fde
,
3302 struct smbd_server_connection
*sconn
=
3303 talloc_get_type_abort(private_data
,
3304 struct smbd_server_connection
);
3307 status
= smbd_smb2_io_handler(sconn
, flags
);
3308 if (!NT_STATUS_IS_OK(status
)) {
3309 smbd_server_connection_terminate(sconn
, nt_errstr(status
));