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 #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9)
35 static const struct smbd_smb2_dispatch_table
{
42 bool allow_invalid_fileid
;
43 } smbd_smb2_table
[] = {
44 #define _OP(o) .opcode = o, .name = #o
49 _OP(SMB2_OP_SESSSETUP
),
59 * This call needs to be run as root.
61 * smbd_smb2_request_process_tcon()
62 * calls make_connection_snum(), which will call
63 * change_to_user(), when needed.
102 .need_session
= true,
105 .allow_invalid_fileid
= true,
110 _OP(SMB2_OP_KEEPALIVE
),
114 .need_session
= true,
119 .need_session
= true,
123 _OP(SMB2_OP_GETINFO
),
124 .need_session
= true,
128 _OP(SMB2_OP_SETINFO
),
129 .need_session
= true,
134 .need_session
= true,
139 * as LEASE breaks does not
145 const char *smb2_opcode_name(uint16_t opcode
)
147 if (opcode
>= ARRAY_SIZE(smbd_smb2_table
)) {
148 return "Bad SMB2 opcode";
150 return smbd_smb2_table
[opcode
].name
;
153 static const struct smbd_smb2_dispatch_table
*smbd_smb2_call(uint16_t opcode
)
155 const struct smbd_smb2_dispatch_table
*ret
= NULL
;
157 if (opcode
>= ARRAY_SIZE(smbd_smb2_table
)) {
161 ret
= &smbd_smb2_table
[opcode
];
163 SMB_ASSERT(ret
->opcode
== opcode
);
168 static void print_req_vectors(const struct smbd_smb2_request
*req
)
172 for (i
= 0; i
< req
->in
.vector_count
; i
++) {
173 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
175 (unsigned int)req
->in
.vector
[i
].iov_len
);
177 for (i
= 0; i
< req
->out
.vector_count
; i
++) {
178 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
180 (unsigned int)req
->out
.vector
[i
].iov_len
);
184 bool smbd_is_smb2_header(const uint8_t *inbuf
, size_t size
)
186 if (size
< (4 + SMB2_HDR_BODY
)) {
190 if (IVAL(inbuf
, 4) != SMB2_MAGIC
) {
197 static NTSTATUS
smbd_initialize_smb2(struct smbd_server_connection
*sconn
)
202 TALLOC_FREE(sconn
->smb1
.fde
);
204 sconn
->smb2
.recv_queue
= tevent_queue_create(sconn
, "smb2 recv queue");
205 if (sconn
->smb2
.recv_queue
== NULL
) {
206 return NT_STATUS_NO_MEMORY
;
209 sconn
->smb2
.send_queue
= tevent_queue_create(sconn
, "smb2 send queue");
210 if (sconn
->smb2
.send_queue
== NULL
) {
211 return NT_STATUS_NO_MEMORY
;
214 sconn
->smb2
.seqnum_low
= 0;
215 sconn
->smb2
.seqnum_range
= 1;
216 sconn
->smb2
.credits_granted
= 1;
217 sconn
->smb2
.max_credits
= lp_smb2_max_credits();
218 sconn
->smb2
.credits_bitmap
= bitmap_talloc(sconn
,
219 sconn
->smb2
.max_credits
);
220 if (sconn
->smb2
.credits_bitmap
== NULL
) {
221 return NT_STATUS_NO_MEMORY
;
224 ret
= tstream_bsd_existing_socket(sconn
, sconn
->sock
,
225 &sconn
->smb2
.stream
);
227 status
= map_nt_error_from_unix(errno
);
231 /* Ensure child is set to non-blocking mode */
232 set_blocking(sconn
->sock
, false);
236 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
237 #define _smb2_setlen(_buf,len) do { \
238 uint8_t *buf = (uint8_t *)_buf; \
240 buf[1] = ((len)&0xFF0000)>>16; \
241 buf[2] = ((len)&0xFF00)>>8; \
242 buf[3] = (len)&0xFF; \
245 static void smb2_setup_nbt_length(struct iovec
*vector
, int count
)
250 for (i
=1; i
< count
; i
++) {
251 len
+= vector
[i
].iov_len
;
254 _smb2_setlen(vector
[0].iov_base
, len
);
257 static int smbd_smb2_request_destructor(struct smbd_smb2_request
*req
)
259 data_blob_clear_free(&req
->first_key
);
260 data_blob_clear_free(&req
->last_key
);
264 static struct smbd_smb2_request
*smbd_smb2_request_allocate(TALLOC_CTX
*mem_ctx
)
266 TALLOC_CTX
*mem_pool
;
267 struct smbd_smb2_request
*req
;
270 /* Enable this to find subtle valgrind errors. */
271 mem_pool
= talloc_init("smbd_smb2_request_allocate");
273 mem_pool
= talloc_pool(mem_ctx
, 8192);
275 if (mem_pool
== NULL
) {
279 req
= talloc_zero(mem_pool
, struct smbd_smb2_request
);
281 talloc_free(mem_pool
);
284 talloc_reparent(mem_pool
, mem_ctx
, req
);
285 TALLOC_FREE(mem_pool
);
287 req
->last_session_id
= UINT64_MAX
;
288 req
->last_tid
= UINT32_MAX
;
290 talloc_set_destructor(req
, smbd_smb2_request_destructor
);
295 static NTSTATUS
smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection
*conn
,
306 uint8_t *first_hdr
= buf
;
307 size_t verified_buflen
= 0;
312 * Note: index '0' is reserved for the transport protocol
314 iov
= talloc_zero_array(mem_ctx
, struct iovec
, num_iov
);
316 return NT_STATUS_NO_MEMORY
;
319 while (taken
< buflen
) {
320 size_t len
= buflen
- taken
;
321 uint8_t *hdr
= first_hdr
+ taken
;
324 size_t next_command_ofs
;
326 uint8_t *body
= NULL
;
329 struct iovec
*iov_tmp
;
331 if (verified_buflen
> taken
) {
332 len
= verified_buflen
- taken
;
339 DEBUG(10, ("%d bytes left, expected at least %d\n",
343 if (IVAL(hdr
, 0) == SMB2_TF_MAGIC
) {
344 struct smbXsrv_session
*s
= NULL
;
346 struct iovec tf_iov
[2];
350 if (conn
->protocol
< PROTOCOL_SMB2_24
) {
351 DEBUG(10, ("Got SMB2_TRANSFORM header, "
352 "but dialect[0x%04X] is used\n",
353 conn
->smb2
.server
.dialect
));
357 if (!(conn
->smb2
.server
.capabilities
& SMB2_CAP_ENCRYPTION
)) {
358 DEBUG(10, ("Got SMB2_TRANSFORM header, "
359 "but not negotiated "
360 "client[0x%08X] server[0x%08X]\n",
361 conn
->smb2
.client
.capabilities
,
362 conn
->smb2
.server
.capabilities
));
366 if (len
< SMB2_TF_HDR_SIZE
) {
367 DEBUG(1, ("%d bytes left, expected at least %d\n",
368 (int)len
, SMB2_TF_HDR_SIZE
));
372 tf_len
= SMB2_TF_HDR_SIZE
;
375 hdr
= first_hdr
+ taken
;
376 enc_len
= IVAL(tf
, SMB2_TF_MSG_SIZE
);
377 uid
= BVAL(tf
, SMB2_TF_SESSION_ID
);
379 if (len
< SMB2_TF_HDR_SIZE
+ enc_len
) {
380 DEBUG(1, ("%d bytes left, expected at least %d\n",
382 (int)(SMB2_TF_HDR_SIZE
+ enc_len
)));
386 status
= smb2srv_session_lookup(conn
, uid
, now
, &s
);
388 DEBUG(1, ("invalid session[%llu] in "
389 "SMB2_TRANSFORM header\n",
390 (unsigned long long)uid
));
392 return NT_STATUS_USER_SESSION_DELETED
;
395 tf_iov
[0].iov_base
= (void *)tf
;
396 tf_iov
[0].iov_len
= tf_len
;
397 tf_iov
[1].iov_base
= (void *)hdr
;
398 tf_iov
[1].iov_len
= enc_len
;
400 status
= smb2_signing_decrypt_pdu(s
->global
->decryption_key
,
403 if (!NT_STATUS_IS_OK(status
)) {
408 verified_buflen
= taken
+ enc_len
;
413 * We need the header plus the body length field
416 if (len
< SMB2_HDR_BODY
+ 2) {
417 DEBUG(10, ("%d bytes left, expected at least %d\n",
418 (int)len
, SMB2_HDR_BODY
));
421 if (IVAL(hdr
, 0) != SMB2_MAGIC
) {
422 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
426 if (SVAL(hdr
, 4) != SMB2_HDR_BODY
) {
427 DEBUG(10, ("Got HDR len %d, expected %d\n",
428 SVAL(hdr
, 4), SMB2_HDR_BODY
));
433 next_command_ofs
= IVAL(hdr
, SMB2_HDR_NEXT_COMMAND
);
434 body_size
= SVAL(hdr
, SMB2_HDR_BODY
);
436 if (next_command_ofs
!= 0) {
437 if (next_command_ofs
< (SMB2_HDR_BODY
+ 2)) {
440 if (next_command_ofs
> full_size
) {
443 full_size
= next_command_ofs
;
450 if (body_size
> (full_size
- SMB2_HDR_BODY
)) {
452 * let the caller handle the error
454 body_size
= full_size
- SMB2_HDR_BODY
;
456 body
= hdr
+ SMB2_HDR_BODY
;
457 dyn
= body
+ body_size
;
458 dyn_size
= full_size
- (SMB2_HDR_BODY
+ body_size
);
460 iov_tmp
= talloc_realloc(mem_ctx
, iov
, struct iovec
,
461 num_iov
+ SMBD_SMB2_NUM_IOV_PER_REQ
);
462 if (iov_tmp
== NULL
) {
464 return NT_STATUS_NO_MEMORY
;
468 num_iov
+= SMBD_SMB2_NUM_IOV_PER_REQ
;
470 cur
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= tf
;
471 cur
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= tf_len
;
472 cur
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
473 cur
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
474 cur
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
475 cur
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= body_size
;
476 cur
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
477 cur
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= dyn_size
;
488 return NT_STATUS_INVALID_PARAMETER
;
491 static NTSTATUS
smbd_smb2_request_create(struct smbd_server_connection
*sconn
,
492 uint8_t *inbuf
, size_t size
,
493 struct smbd_smb2_request
**_req
)
495 struct smbd_smb2_request
*req
;
496 uint32_t protocol_version
;
497 const uint8_t *inhdr
= NULL
;
499 uint32_t next_command_ofs
;
503 if (size
< (4 + SMB2_HDR_BODY
+ 2)) {
504 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size
));
505 return NT_STATUS_INVALID_PARAMETER
;
510 protocol_version
= IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
);
511 if (protocol_version
!= SMB2_MAGIC
) {
512 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
514 return NT_STATUS_INVALID_PARAMETER
;
517 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
518 if (cmd
!= SMB2_OP_NEGPROT
) {
519 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
521 return NT_STATUS_INVALID_PARAMETER
;
524 next_command_ofs
= IVAL(inhdr
, SMB2_HDR_NEXT_COMMAND
);
525 if (next_command_ofs
!= 0) {
526 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
528 return NT_STATUS_INVALID_PARAMETER
;
531 req
= smbd_smb2_request_allocate(sconn
);
533 return NT_STATUS_NO_MEMORY
;
537 talloc_steal(req
, inbuf
);
539 req
->request_time
= timeval_current();
540 now
= timeval_to_nttime(&req
->request_time
);
542 status
= smbd_smb2_inbuf_parse_compound(sconn
->conn
,
544 inbuf
+ NBT_HDR_SIZE
,
546 req
, &req
->in
.vector
,
547 &req
->in
.vector_count
);
548 if (!NT_STATUS_IS_OK(status
)) {
553 req
->current_idx
= 1;
559 static bool smb2_validate_sequence_number(struct smbd_server_connection
*sconn
,
560 uint64_t message_id
, uint64_t seq_id
)
562 struct bitmap
*credits_bm
= sconn
->smb2
.credits_bitmap
;
565 if (seq_id
< sconn
->smb2
.seqnum_low
) {
566 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
567 "%llu (sequence id %llu) "
568 "(granted = %u, low = %llu, range = %u)\n",
569 (unsigned long long)message_id
,
570 (unsigned long long)seq_id
,
571 (unsigned int)sconn
->smb2
.credits_granted
,
572 (unsigned long long)sconn
->smb2
.seqnum_low
,
573 (unsigned int)sconn
->smb2
.seqnum_range
));
577 if (seq_id
>= sconn
->smb2
.seqnum_low
+ sconn
->smb2
.seqnum_range
) {
578 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
579 "%llu (sequence id %llu) "
580 "(granted = %u, low = %llu, range = %u)\n",
581 (unsigned long long)message_id
,
582 (unsigned long long)seq_id
,
583 (unsigned int)sconn
->smb2
.credits_granted
,
584 (unsigned long long)sconn
->smb2
.seqnum_low
,
585 (unsigned int)sconn
->smb2
.seqnum_range
));
589 offset
= seq_id
% sconn
->smb2
.max_credits
;
591 if (bitmap_query(credits_bm
, offset
)) {
592 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
593 "%llu (sequence id %llu) "
594 "(granted = %u, low = %llu, range = %u) "
596 (unsigned long long)message_id
,
597 (unsigned long long)seq_id
,
598 (unsigned int)sconn
->smb2
.credits_granted
,
599 (unsigned long long)sconn
->smb2
.seqnum_low
,
600 (unsigned int)sconn
->smb2
.seqnum_range
,
605 /* Mark the message_ids as seen in the bitmap. */
606 bitmap_set(credits_bm
, offset
);
608 if (seq_id
!= sconn
->smb2
.seqnum_low
) {
613 * Move the window forward by all the message_id's
616 while (bitmap_query(credits_bm
, offset
)) {
617 DEBUG(10,("smb2_validate_sequence_number: clearing "
618 "id %llu (position %u) from bitmap\n",
619 (unsigned long long)(sconn
->smb2
.seqnum_low
),
621 bitmap_clear(credits_bm
, offset
);
623 sconn
->smb2
.seqnum_low
+= 1;
624 sconn
->smb2
.seqnum_range
-= 1;
625 offset
= sconn
->smb2
.seqnum_low
% sconn
->smb2
.max_credits
;
631 static bool smb2_validate_message_id(struct smbd_server_connection
*sconn
,
632 const uint8_t *inhdr
)
634 uint64_t message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
635 uint16_t opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
636 uint16_t credit_charge
= 1;
639 if (opcode
== SMB2_OP_CANCEL
) {
640 /* SMB2_CANCEL requests by definition resend messageids. */
644 if (sconn
->smb2
.supports_multicredit
) {
645 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
646 credit_charge
= MAX(credit_charge
, 1);
649 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
650 "credits_granted %llu, "
651 "seqnum low/range: %llu/%llu\n",
652 (unsigned long long) message_id
,
653 (unsigned long long) credit_charge
,
654 (unsigned long long) sconn
->smb2
.credits_granted
,
655 (unsigned long long) sconn
->smb2
.seqnum_low
,
656 (unsigned long long) sconn
->smb2
.seqnum_range
));
658 if (sconn
->smb2
.credits_granted
< credit_charge
) {
659 DEBUG(0, ("smb2_validate_message_id: client used more "
660 "credits than granted, mid %llu, charge %llu, "
661 "credits_granted %llu, "
662 "seqnum low/range: %llu/%llu\n",
663 (unsigned long long) message_id
,
664 (unsigned long long) credit_charge
,
665 (unsigned long long) sconn
->smb2
.credits_granted
,
666 (unsigned long long) sconn
->smb2
.seqnum_low
,
667 (unsigned long long) sconn
->smb2
.seqnum_range
));
672 * now check the message ids
674 * for multi-credit requests we need to check all current mid plus
675 * the implicit mids caused by the credit charge
676 * e.g. current mid = 15, charge 5 => mark 15-19 as used
679 for (i
= 0; i
<= (credit_charge
-1); i
++) {
680 uint64_t id
= message_id
+ i
;
683 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
684 (unsigned long long)message_id
,
686 (unsigned long long)id
));
688 ok
= smb2_validate_sequence_number(sconn
, message_id
, id
);
694 /* substract used credits */
695 sconn
->smb2
.credits_granted
-= credit_charge
;
700 static NTSTATUS
smbd_smb2_request_validate(struct smbd_smb2_request
*req
)
705 count
= req
->in
.vector_count
;
707 if (count
< 1 + SMBD_SMB2_NUM_IOV_PER_REQ
) {
708 /* It's not a SMB2 request */
709 return NT_STATUS_INVALID_PARAMETER
;
712 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
713 struct iovec
*hdr
= SMBD_SMB2_IDX_HDR_IOV(req
,in
,idx
);
714 struct iovec
*body
= SMBD_SMB2_IDX_BODY_IOV(req
,in
,idx
);
715 const uint8_t *inhdr
= NULL
;
717 if (hdr
->iov_len
!= SMB2_HDR_BODY
) {
718 return NT_STATUS_INVALID_PARAMETER
;
721 if (body
->iov_len
< 2) {
722 return NT_STATUS_INVALID_PARAMETER
;
725 inhdr
= (const uint8_t *)hdr
->iov_base
;
727 /* Check the SMB2 header */
728 if (IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
) != SMB2_MAGIC
) {
729 return NT_STATUS_INVALID_PARAMETER
;
732 if (!smb2_validate_message_id(req
->sconn
, inhdr
)) {
733 return NT_STATUS_INVALID_PARAMETER
;
740 static void smb2_set_operation_credit(struct smbd_server_connection
*sconn
,
741 const struct iovec
*in_vector
,
742 struct iovec
*out_vector
)
744 const uint8_t *inhdr
= (const uint8_t *)in_vector
->iov_base
;
745 uint8_t *outhdr
= (uint8_t *)out_vector
->iov_base
;
746 uint16_t credit_charge
= 1;
747 uint16_t credits_requested
;
751 uint16_t credits_granted
= 0;
752 uint64_t credits_possible
;
753 uint16_t current_max_credits
;
756 * first we grant only 1/16th of the max range.
758 * Windows also starts with the 1/16th and then grants
759 * more later. I was only able to trigger higher
760 * values, when using a verify high credit charge.
762 * TODO: scale up depending one load, free memory
764 * Maybe also on the relationship between number
765 * of requests and the used sequence number.
766 * Which means we would grant more credits
767 * for client which use multi credit requests.
769 current_max_credits
= sconn
->smb2
.max_credits
/ 16;
770 current_max_credits
= MAX(current_max_credits
, 1);
772 if (sconn
->smb2
.supports_multicredit
) {
773 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
774 credit_charge
= MAX(credit_charge
, 1);
777 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
778 credits_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
779 out_flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
780 out_status
= NT_STATUS(IVAL(outhdr
, SMB2_HDR_STATUS
));
782 SMB_ASSERT(sconn
->smb2
.max_credits
>= sconn
->smb2
.credits_granted
);
783 SMB_ASSERT(sconn
->smb2
.max_credits
>= credit_charge
);
785 if (out_flags
& SMB2_HDR_FLAG_ASYNC
) {
787 * In case we already send an async interim
788 * response, we should not grant
789 * credits on the final response.
792 } else if (credits_requested
> 0) {
793 uint16_t additional_max
= 0;
794 uint16_t additional_credits
= credits_requested
- 1;
797 case SMB2_OP_NEGPROT
:
799 case SMB2_OP_SESSSETUP
:
801 * Windows 2012 RC1 starts to grant
803 * with a successful session setup
805 if (NT_STATUS_IS_OK(out_status
)) {
811 * We match windows and only grant additional credits
818 additional_credits
= MIN(additional_credits
, additional_max
);
820 credits_granted
= credit_charge
+ additional_credits
;
821 } else if (sconn
->smb2
.credits_granted
== 0) {
823 * Make sure the client has always at least one credit
829 * sequence numbers should not wrap
831 * 1. calculate the possible credits until
832 * the sequence numbers start to wrap on 64-bit.
834 * 2. UINT64_MAX is used for Break Notifications.
836 * 2. truncate the possible credits to the maximum
837 * credits we want to grant to the client in total.
839 * 3. remove the range we'll already granted to the client
840 * this makes sure the client consumes the lowest sequence
841 * number, before we can grant additional credits.
843 credits_possible
= UINT64_MAX
- sconn
->smb2
.seqnum_low
;
844 if (credits_possible
> 0) {
845 /* remove UINT64_MAX */
846 credits_possible
-= 1;
848 credits_possible
= MIN(credits_possible
, current_max_credits
);
849 credits_possible
-= sconn
->smb2
.seqnum_range
;
851 credits_granted
= MIN(credits_granted
, credits_possible
);
853 SSVAL(outhdr
, SMB2_HDR_CREDIT
, credits_granted
);
854 sconn
->smb2
.credits_granted
+= credits_granted
;
855 sconn
->smb2
.seqnum_range
+= credits_granted
;
857 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
858 "granted %u, current possible/max %u/%u, "
859 "total granted/max/low/range %u/%u/%llu/%u\n",
860 (unsigned int)credits_requested
,
861 (unsigned int)credit_charge
,
862 (unsigned int)credits_granted
,
863 (unsigned int)credits_possible
,
864 (unsigned int)current_max_credits
,
865 (unsigned int)sconn
->smb2
.credits_granted
,
866 (unsigned int)sconn
->smb2
.max_credits
,
867 (unsigned long long)sconn
->smb2
.seqnum_low
,
868 (unsigned int)sconn
->smb2
.seqnum_range
));
871 static void smb2_calculate_credits(const struct smbd_smb2_request
*inreq
,
872 struct smbd_smb2_request
*outreq
)
875 uint16_t total_credits
= 0;
877 count
= outreq
->out
.vector_count
;
879 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
880 struct iovec
*inhdr_v
= SMBD_SMB2_IDX_HDR_IOV(inreq
,in
,idx
);
881 struct iovec
*outhdr_v
= SMBD_SMB2_IDX_HDR_IOV(outreq
,out
,idx
);
882 uint8_t *outhdr
= (uint8_t *)outhdr_v
->iov_base
;
884 smb2_set_operation_credit(outreq
->sconn
, inhdr_v
, outhdr_v
);
886 /* To match Windows, count up what we
888 total_credits
+= SVAL(outhdr
, SMB2_HDR_CREDIT
);
889 /* Set to zero in all but the last reply. */
890 if (idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
< count
) {
891 SSVAL(outhdr
, SMB2_HDR_CREDIT
, 0);
893 SSVAL(outhdr
, SMB2_HDR_CREDIT
, total_credits
);
898 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
)
900 struct iovec
*vector
;
904 count
= req
->in
.vector_count
;
905 vector
= talloc_zero_array(req
, struct iovec
, count
);
906 if (vector
== NULL
) {
907 return NT_STATUS_NO_MEMORY
;
910 vector
[0].iov_base
= req
->out
.nbt_hdr
;
911 vector
[0].iov_len
= 4;
912 SIVAL(req
->out
.nbt_hdr
, 0, 0);
914 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
915 struct iovec
*inhdr_v
= SMBD_SMB2_IDX_HDR_IOV(req
,in
,idx
);
916 const uint8_t *inhdr
= (const uint8_t *)inhdr_v
->iov_base
;
917 uint8_t *outhdr
= NULL
;
918 uint8_t *outbody
= NULL
;
919 uint32_t next_command_ofs
= 0;
920 struct iovec
*current
= &vector
[idx
];
922 if ((idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
) < count
) {
923 /* we have a next command -
924 * setup for the error case. */
925 next_command_ofs
= SMB2_HDR_BODY
+ 9;
928 outhdr
= talloc_zero_array(vector
, uint8_t,
930 if (outhdr
== NULL
) {
931 return NT_STATUS_NO_MEMORY
;
934 outbody
= outhdr
+ SMB2_HDR_BODY
;
937 * SMBD_SMB2_TF_IOV_OFS might be used later
939 current
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
940 current
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
942 current
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= (void *)outhdr
;
943 current
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
945 current
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= (void *)outbody
;
946 current
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= 8;
948 current
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= NULL
;
949 current
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= 0;
951 /* setup the SMB2 header */
952 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
953 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
954 SSVAL(outhdr
, SMB2_HDR_CREDIT_CHARGE
,
955 SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
));
956 SIVAL(outhdr
, SMB2_HDR_STATUS
,
957 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
958 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
959 SVAL(inhdr
, SMB2_HDR_OPCODE
));
960 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
961 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
962 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
963 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
964 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
965 SIVAL(outhdr
, SMB2_HDR_PID
,
966 IVAL(inhdr
, SMB2_HDR_PID
));
967 SIVAL(outhdr
, SMB2_HDR_TID
,
968 IVAL(inhdr
, SMB2_HDR_TID
));
969 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
970 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
971 memcpy(outhdr
+ SMB2_HDR_SIGNATURE
,
972 inhdr
+ SMB2_HDR_SIGNATURE
, 16);
974 /* setup error body header */
975 SSVAL(outbody
, 0x00, 0x08 + 1);
976 SSVAL(outbody
, 0x02, 0);
977 SIVAL(outbody
, 0x04, 0);
980 req
->out
.vector
= vector
;
981 req
->out
.vector_count
= count
;
983 /* setup the length of the NBT packet */
984 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
986 DLIST_ADD_END(req
->sconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
991 void smbd_server_connection_terminate_ex(struct smbd_server_connection
*sconn
,
993 const char *location
)
995 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
997 exit_server_cleanly(reason
);
1000 static bool dup_smb2_vec4(TALLOC_CTX
*ctx
,
1001 struct iovec
*outvec
,
1002 const struct iovec
*srcvec
)
1004 const uint8_t *srctf
;
1006 const uint8_t *srchdr
;
1008 const uint8_t *srcbody
;
1010 const uint8_t *expected_srcbody
;
1011 const uint8_t *srcdyn
;
1013 const uint8_t *expected_srcdyn
;
1019 srctf
= (const uint8_t *)srcvec
[SMBD_SMB2_TF_IOV_OFS
].iov_base
;
1020 srctf_len
= srcvec
[SMBD_SMB2_TF_IOV_OFS
].iov_len
;
1021 srchdr
= (const uint8_t *)srcvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
;
1022 srchdr_len
= srcvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
;
1023 srcbody
= (const uint8_t *)srcvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
;
1024 srcbody_len
= srcvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
;
1025 expected_srcbody
= srchdr
+ SMB2_HDR_BODY
;
1026 srcdyn
= (const uint8_t *)srcvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
;
1027 srcdyn_len
= srcvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
;
1028 expected_srcdyn
= srcbody
+ 8;
1030 if ((srctf_len
!= SMB2_TF_HDR_SIZE
) && (srctf_len
!= 0)) {
1034 if (srchdr_len
!= SMB2_HDR_BODY
) {
1038 if (srctf_len
== SMB2_TF_HDR_SIZE
) {
1039 dsttf
= talloc_memdup(ctx
, srctf
, SMB2_TF_HDR_SIZE
);
1040 if (dsttf
== NULL
) {
1046 outvec
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= (void *)dsttf
;
1047 outvec
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= srctf_len
;
1049 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1050 * be allocated with size OUTVEC_ALLOC_SIZE. */
1052 dsthdr
= talloc_memdup(ctx
, srchdr
, OUTVEC_ALLOC_SIZE
);
1053 if (dsthdr
== NULL
) {
1056 outvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= (void *)dsthdr
;
1057 outvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
1060 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1061 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1062 * then duplicate this. Else use talloc_memdup().
1065 if ((srcbody
== expected_srcbody
) && (srcbody_len
== 8)) {
1066 dstbody
= dsthdr
+ SMB2_HDR_BODY
;
1068 dstbody
= talloc_memdup(ctx
, srcbody
, srcbody_len
);
1069 if (dstbody
== NULL
) {
1073 outvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= (void *)dstbody
;
1074 outvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= srcbody_len
;
1077 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1079 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1080 * then duplicate this. Else use talloc_memdup().
1083 if ((srcdyn
== expected_srcdyn
) && (srcdyn_len
== 1)) {
1084 dstdyn
= dsthdr
+ SMB2_HDR_BODY
+ 8;
1085 } else if (srcdyn
== NULL
) {
1088 dstdyn
= talloc_memdup(ctx
, srcdyn
, srcdyn_len
);
1089 if (dstdyn
== NULL
) {
1093 outvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= (void *)dstdyn
;
1094 outvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= srcdyn_len
;
1099 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
1101 struct smbd_smb2_request
*newreq
= NULL
;
1102 struct iovec
*outvec
= NULL
;
1103 int count
= req
->out
.vector_count
;
1106 newreq
= smbd_smb2_request_allocate(req
->sconn
);
1111 newreq
->sconn
= req
->sconn
;
1112 newreq
->session
= req
->session
;
1113 newreq
->do_encryption
= req
->do_encryption
;
1114 newreq
->do_signing
= req
->do_signing
;
1115 newreq
->current_idx
= req
->current_idx
;
1117 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
1119 TALLOC_FREE(newreq
);
1122 newreq
->out
.vector
= outvec
;
1123 newreq
->out
.vector_count
= count
;
1125 /* Setup the outvec's identically to req. */
1126 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
1127 outvec
[0].iov_len
= 4;
1128 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
1130 /* Setup the vectors identically to the ones in req. */
1131 for (i
= 1; i
< count
; i
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
1132 if (!dup_smb2_vec4(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
1139 TALLOC_FREE(newreq
);
1143 smb2_setup_nbt_length(newreq
->out
.vector
,
1144 newreq
->out
.vector_count
);
1149 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
);
1151 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
1153 struct smbXsrv_connection
*conn
= req
->sconn
->conn
;
1155 struct iovec
*firsttf
= NULL
;
1156 struct iovec
*outhdr_v
= NULL
;
1157 uint8_t *outhdr
= NULL
;
1158 struct smbd_smb2_request
*nreq
= NULL
;
1161 /* Create a new smb2 request we'll use
1162 for the interim return. */
1163 nreq
= dup_smb2_req(req
);
1165 return NT_STATUS_NO_MEMORY
;
1168 /* Lose the last X out vectors. They're the
1169 ones we'll be using for the async reply. */
1170 nreq
->out
.vector_count
-= SMBD_SMB2_NUM_IOV_PER_REQ
;
1172 smb2_setup_nbt_length(nreq
->out
.vector
,
1173 nreq
->out
.vector_count
);
1175 /* Step back to the previous reply. */
1176 nreq
->current_idx
-= SMBD_SMB2_NUM_IOV_PER_REQ
;
1177 firsttf
= SMBD_SMB2_IDX_TF_IOV(nreq
,out
,first_idx
);
1178 outhdr_v
= SMBD_SMB2_OUT_HDR_IOV(nreq
);
1179 outhdr
= SMBD_SMB2_OUT_HDR_PTR(nreq
);
1180 /* And end the chain. */
1181 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1183 /* Calculate outgoing credits */
1184 smb2_calculate_credits(req
, nreq
);
1186 if (DEBUGLEVEL
>= 10) {
1187 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1188 (unsigned int)nreq
->current_idx
);
1189 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1190 (unsigned int)nreq
->out
.vector_count
);
1191 print_req_vectors(nreq
);
1195 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1196 * we need to sign/encrypt here with the last/first key we remembered
1198 if (firsttf
->iov_len
== SMB2_TF_HDR_SIZE
) {
1199 status
= smb2_signing_encrypt_pdu(req
->first_key
,
1202 nreq
->out
.vector_count
- first_idx
);
1203 if (!NT_STATUS_IS_OK(status
)) {
1206 } else if (req
->last_key
.length
> 0) {
1207 status
= smb2_signing_sign_pdu(req
->last_key
,
1210 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
1211 if (!NT_STATUS_IS_OK(status
)) {
1216 nreq
->subreq
= tstream_writev_queue_send(nreq
,
1217 nreq
->sconn
->ev_ctx
,
1218 nreq
->sconn
->smb2
.stream
,
1219 nreq
->sconn
->smb2
.send_queue
,
1221 nreq
->out
.vector_count
);
1223 if (nreq
->subreq
== NULL
) {
1224 return NT_STATUS_NO_MEMORY
;
1227 tevent_req_set_callback(nreq
->subreq
,
1228 smbd_smb2_request_writev_done
,
1231 return NT_STATUS_OK
;
1234 struct smbd_smb2_request_pending_state
{
1235 struct smbd_server_connection
*sconn
;
1236 uint8_t buf
[NBT_HDR_SIZE
+ SMB2_TF_HDR_SIZE
+ SMB2_HDR_BODY
+ 0x08 + 1];
1237 struct iovec vector
[1 + SMBD_SMB2_NUM_IOV_PER_REQ
];
1240 static void smbd_smb2_request_pending_writev_done(struct tevent_req
*subreq
)
1242 struct smbd_smb2_request_pending_state
*state
=
1243 tevent_req_callback_data(subreq
,
1244 struct smbd_smb2_request_pending_state
);
1245 struct smbd_server_connection
*sconn
= state
->sconn
;
1249 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1250 TALLOC_FREE(subreq
);
1252 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
1253 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1260 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
1261 struct tevent_timer
*te
,
1262 struct timeval current_time
,
1263 void *private_data
);
1265 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
1266 struct tevent_req
*subreq
,
1267 uint32_t defer_time
)
1270 int idx
= req
->current_idx
;
1271 struct timeval defer_endtime
;
1272 uint8_t *outhdr
= NULL
;
1275 if (!tevent_req_is_in_progress(subreq
)) {
1276 return NT_STATUS_OK
;
1279 req
->subreq
= subreq
;
1282 if (req
->async_te
) {
1283 /* We're already async. */
1284 return NT_STATUS_OK
;
1287 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1288 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1289 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1290 /* We're already async. */
1291 return NT_STATUS_OK
;
1294 if (req
->in
.vector_count
> idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
) {
1296 * We're trying to go async in a compound
1297 * request chain. This is not allowed.
1298 * Cancel the outstanding request.
1300 bool ok
= tevent_req_cancel(req
->subreq
);
1302 return NT_STATUS_OK
;
1304 TALLOC_FREE(req
->subreq
);
1305 return smbd_smb2_request_error(req
,
1306 NT_STATUS_INTERNAL_ERROR
);
1309 if (DEBUGLEVEL
>= 10) {
1310 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1311 (unsigned int)req
->current_idx
);
1312 print_req_vectors(req
);
1315 if (req
->out
.vector_count
>= (2*SMBD_SMB2_NUM_IOV_PER_REQ
)) {
1317 * This is a compound reply. We
1318 * must do an interim response
1319 * followed by the async response
1322 status
= smb2_send_async_interim_response(req
);
1323 if (!NT_STATUS_IS_OK(status
)) {
1326 data_blob_clear_free(&req
->first_key
);
1329 * We're splitting off the last SMB2
1330 * request in a compound set, and the
1331 * smb2_send_async_interim_response()
1332 * call above just sent all the replies
1333 * for the previous SMB2 requests in
1334 * this compound set. So we're no longer
1335 * in the "compound_related_in_progress"
1336 * state, and this is no longer a compound
1339 req
->compound_related
= false;
1340 req
->sconn
->smb2
.compound_related_in_progress
= false;
1342 req
->current_idx
= 1;
1344 /* Re-arrange the in.vectors. */
1345 memmove(&req
->in
.vector
[req
->current_idx
],
1346 &req
->in
.vector
[idx
],
1347 sizeof(req
->in
.vector
[0])*SMBD_SMB2_NUM_IOV_PER_REQ
);
1348 req
->in
.vector_count
= req
->current_idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
;
1350 /* Re-arrange the out.vectors. */
1351 memmove(&req
->out
.vector
[req
->current_idx
],
1352 &req
->out
.vector
[idx
],
1353 sizeof(req
->out
.vector
[0])*SMBD_SMB2_NUM_IOV_PER_REQ
);
1354 req
->out
.vector_count
= req
->current_idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
;
1356 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1357 flags
= (IVAL(outhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
1358 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
);
1360 data_blob_clear_free(&req
->last_key
);
1362 defer_endtime
= timeval_current_ofs_usec(defer_time
);
1363 req
->async_te
= tevent_add_timer(req
->sconn
->ev_ctx
,
1365 smbd_smb2_request_pending_timer
,
1367 if (req
->async_te
== NULL
) {
1368 return NT_STATUS_NO_MEMORY
;
1371 return NT_STATUS_OK
;
1374 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
1375 struct tevent_timer
*te
,
1376 struct timeval current_time
,
1379 struct smbd_smb2_request
*req
=
1380 talloc_get_type_abort(private_data
,
1381 struct smbd_smb2_request
);
1382 struct smbd_smb2_request_pending_state
*state
= NULL
;
1383 uint8_t *outhdr
= NULL
;
1384 const uint8_t *inhdr
= NULL
;
1387 uint8_t *hdr
= NULL
;
1388 uint8_t *body
= NULL
;
1389 uint8_t *dyn
= NULL
;
1391 uint64_t session_id
= 0;
1392 uint64_t message_id
= 0;
1393 uint64_t nonce_high
= 0;
1394 uint64_t nonce_low
= 0;
1395 uint64_t async_id
= 0;
1396 struct tevent_req
*subreq
= NULL
;
1398 TALLOC_FREE(req
->async_te
);
1400 /* Ensure our final reply matches the interim one. */
1401 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1402 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1403 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1404 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1405 session_id
= BVAL(outhdr
, SMB2_HDR_SESSION_ID
);
1407 async_id
= message_id
; /* keep it simple for now... */
1409 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1410 SBVAL(outhdr
, SMB2_HDR_ASYNC_ID
, async_id
);
1412 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1414 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1415 (unsigned long long)async_id
));
1418 * What we send is identical to a smbd_smb2_request_error
1419 * packet with an error status of STATUS_PENDING. Make use
1420 * of this fact sometime when refactoring. JRA.
1423 state
= talloc_zero(req
->sconn
, struct smbd_smb2_request_pending_state
);
1424 if (state
== NULL
) {
1425 smbd_server_connection_terminate(req
->sconn
,
1426 nt_errstr(NT_STATUS_NO_MEMORY
));
1429 state
->sconn
= req
->sconn
;
1431 tf
= state
->buf
+ NBT_HDR_SIZE
;
1432 tf_len
= SMB2_TF_HDR_SIZE
;
1434 hdr
= tf
+ SMB2_TF_HDR_SIZE
;
1435 body
= hdr
+ SMB2_HDR_BODY
;
1438 if (req
->do_encryption
) {
1439 struct smbXsrv_session
*x
= req
->session
;
1441 nonce_high
= x
->nonce_high
;
1442 nonce_low
= x
->nonce_low
;
1445 if (x
->nonce_low
== 0) {
1451 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
1452 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
1453 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
1454 SBVAL(tf
, SMB2_TF_SESSION_ID
, session_id
);
1456 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
1457 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1458 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1459 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
1460 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(outhdr
, SMB2_HDR_OPCODE
));
1462 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
);
1463 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1464 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
1465 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
1466 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
1467 BVAL(outhdr
, SMB2_HDR_SESSION_ID
));
1468 memcpy(hdr
+SMB2_HDR_SIGNATURE
,
1469 outhdr
+SMB2_HDR_SIGNATURE
, 16);
1471 SSVAL(body
, 0x00, 0x08 + 1);
1473 SCVAL(body
, 0x02, 0);
1474 SCVAL(body
, 0x03, 0);
1475 SIVAL(body
, 0x04, 0);
1476 /* Match W2K8R2... */
1477 SCVAL(dyn
, 0x00, 0x21);
1479 state
->vector
[0].iov_base
= (void *)state
->buf
;
1480 state
->vector
[0].iov_len
= NBT_HDR_SIZE
;
1482 if (req
->do_encryption
) {
1483 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= tf
;
1484 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= tf_len
;
1486 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
1487 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
1490 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
1491 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
1493 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
1494 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_len
= 8;
1496 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
1497 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_len
= 1;
1499 smb2_setup_nbt_length(state
->vector
, 1 + SMBD_SMB2_NUM_IOV_PER_REQ
);
1501 /* Ensure we correctly go through crediting. Grant
1502 the credits now, and zero credits on the final
1504 smb2_set_operation_credit(req
->sconn
,
1505 SMBD_SMB2_IN_HDR_IOV(req
),
1506 &state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
]);
1508 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1513 for (i
= 0; i
< ARRAY_SIZE(state
->vector
); i
++) {
1514 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1516 (unsigned int)ARRAY_SIZE(state
->vector
),
1517 (unsigned int)state
->vector
[i
].iov_len
);
1521 if (req
->do_encryption
) {
1523 struct smbXsrv_session
*x
= req
->session
;
1524 struct smbXsrv_connection
*conn
= x
->connection
;
1525 DATA_BLOB encryption_key
= x
->global
->encryption_key
;
1527 status
= smb2_signing_encrypt_pdu(encryption_key
,
1529 &state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
],
1530 SMBD_SMB2_NUM_IOV_PER_REQ
);
1531 if (!NT_STATUS_IS_OK(status
)) {
1532 smbd_server_connection_terminate(req
->sconn
,
1536 } else if (req
->do_signing
) {
1538 struct smbXsrv_session
*x
= req
->session
;
1539 struct smbXsrv_connection
*conn
= x
->connection
;
1540 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
1542 status
= smb2_signing_sign_pdu(signing_key
,
1544 &state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
],
1545 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
1546 if (!NT_STATUS_IS_OK(status
)) {
1547 smbd_server_connection_terminate(req
->sconn
,
1553 subreq
= tstream_writev_queue_send(state
,
1554 state
->sconn
->ev_ctx
,
1555 state
->sconn
->smb2
.stream
,
1556 state
->sconn
->smb2
.send_queue
,
1558 ARRAY_SIZE(state
->vector
));
1559 if (subreq
== NULL
) {
1560 smbd_server_connection_terminate(state
->sconn
,
1561 nt_errstr(NT_STATUS_NO_MEMORY
));
1564 tevent_req_set_callback(subreq
,
1565 smbd_smb2_request_pending_writev_done
,
1569 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
1571 struct smbd_server_connection
*sconn
= req
->sconn
;
1572 struct smbd_smb2_request
*cur
;
1573 const uint8_t *inhdr
;
1575 uint64_t search_message_id
;
1576 uint64_t search_async_id
;
1579 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1581 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1582 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1583 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
1586 * we don't need the request anymore
1587 * cancel requests never have a response
1589 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1592 for (cur
= sconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
1593 const uint8_t *outhdr
;
1594 uint64_t message_id
;
1597 outhdr
= SMBD_SMB2_OUT_HDR_PTR(cur
);
1599 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1600 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
1602 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1603 if (search_async_id
== async_id
) {
1604 found_id
= async_id
;
1608 if (search_message_id
== message_id
) {
1609 found_id
= message_id
;
1615 if (cur
&& cur
->subreq
) {
1616 inhdr
= SMBD_SMB2_IN_HDR_PTR(cur
);
1617 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1618 "cancel opcode[%s] mid %llu\n",
1619 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1620 (unsigned long long)found_id
));
1621 tevent_req_cancel(cur
->subreq
);
1624 return NT_STATUS_OK
;
1627 /*************************************************************
1628 Ensure an incoming tid is a valid one for us to access.
1629 Change to the associated uid credentials and chdir to the
1630 valid tid directory.
1631 *************************************************************/
1633 static NTSTATUS
smbd_smb2_request_check_tcon(struct smbd_smb2_request
*req
)
1635 const uint8_t *inhdr
;
1638 struct smbXsrv_tcon
*tcon
;
1640 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1644 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1646 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1647 in_tid
= IVAL(inhdr
, SMB2_HDR_TID
);
1649 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1650 in_tid
= req
->last_tid
;
1655 status
= smb2srv_tcon_lookup(req
->session
,
1656 in_tid
, now
, &tcon
);
1657 if (!NT_STATUS_IS_OK(status
)) {
1661 if (!change_to_user(tcon
->compat
, req
->session
->compat
->vuid
)) {
1662 return NT_STATUS_ACCESS_DENIED
;
1665 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1666 if (!set_current_service(tcon
->compat
, 0, true)) {
1667 return NT_STATUS_ACCESS_DENIED
;
1671 req
->last_tid
= in_tid
;
1673 return NT_STATUS_OK
;
1676 /*************************************************************
1677 Ensure an incoming session_id is a valid one for us to access.
1678 *************************************************************/
1680 static NTSTATUS
smbd_smb2_request_check_session(struct smbd_smb2_request
*req
)
1682 const uint8_t *inhdr
;
1685 uint64_t in_session_id
;
1686 struct smbXsrv_session
*session
= NULL
;
1687 struct auth_session_info
*session_info
;
1689 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1691 req
->session
= NULL
;
1694 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1696 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1697 in_opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1698 in_session_id
= BVAL(inhdr
, SMB2_HDR_SESSION_ID
);
1700 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1701 in_session_id
= req
->last_session_id
;
1704 req
->last_session_id
= 0;
1706 /* lookup an existing session */
1707 status
= smb2srv_session_lookup(req
->sconn
->conn
,
1711 req
->session
= session
;
1712 req
->last_session_id
= in_session_id
;
1714 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
1715 switch (in_opcode
) {
1716 case SMB2_OP_SESSSETUP
:
1717 status
= NT_STATUS_OK
;
1723 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1724 switch (in_opcode
) {
1726 case SMB2_OP_CREATE
:
1727 case SMB2_OP_GETINFO
:
1728 case SMB2_OP_SETINFO
:
1729 return NT_STATUS_INVALID_HANDLE
;
1732 * Notice the check for
1733 * (session_info == NULL)
1736 status
= NT_STATUS_OK
;
1740 if (!NT_STATUS_IS_OK(status
)) {
1744 session_info
= session
->global
->auth_session_info
;
1745 if (session_info
== NULL
) {
1746 return NT_STATUS_INVALID_HANDLE
;
1749 set_current_user_info(session_info
->unix_info
->sanitized_username
,
1750 session_info
->unix_info
->unix_name
,
1751 session_info
->info
->domain_name
);
1753 return NT_STATUS_OK
;
1756 NTSTATUS
smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request
*req
,
1757 uint32_t data_length
)
1759 uint16_t needed_charge
;
1760 uint16_t credit_charge
= 1;
1761 const uint8_t *inhdr
;
1763 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1765 if (req
->sconn
->smb2
.supports_multicredit
) {
1766 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
1767 credit_charge
= MAX(credit_charge
, 1);
1770 needed_charge
= (data_length
- 1)/ 65536 + 1;
1772 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1773 (unsigned long long) BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
),
1774 credit_charge
, needed_charge
));
1776 if (needed_charge
> credit_charge
) {
1777 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1778 credit_charge
, needed_charge
));
1779 return NT_STATUS_INVALID_PARAMETER
;
1782 return NT_STATUS_OK
;
1785 NTSTATUS
smbd_smb2_request_verify_sizes(struct smbd_smb2_request
*req
,
1786 size_t expected_body_size
)
1788 struct iovec
*inhdr_v
;
1789 const uint8_t *inhdr
;
1791 const uint8_t *inbody
;
1793 size_t min_dyn_size
= expected_body_size
& 0x00000001;
1794 int max_idx
= req
->in
.vector_count
- SMBD_SMB2_NUM_IOV_PER_REQ
;
1797 * The following should be checked already.
1799 if (req
->in
.vector_count
< SMBD_SMB2_NUM_IOV_PER_REQ
) {
1800 return NT_STATUS_INTERNAL_ERROR
;
1802 if (req
->current_idx
> max_idx
) {
1803 return NT_STATUS_INTERNAL_ERROR
;
1806 inhdr_v
= SMBD_SMB2_IN_HDR_IOV(req
);
1807 if (inhdr_v
->iov_len
!= SMB2_HDR_BODY
) {
1808 return NT_STATUS_INTERNAL_ERROR
;
1810 if (SMBD_SMB2_IN_BODY_LEN(req
) < 2) {
1811 return NT_STATUS_INTERNAL_ERROR
;
1814 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1815 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1819 case SMB2_OP_GETINFO
:
1825 * Now check the expected body size,
1826 * where the last byte might be in the
1829 if (SMBD_SMB2_IN_BODY_LEN(req
) != (expected_body_size
& 0xFFFFFFFE)) {
1830 return NT_STATUS_INVALID_PARAMETER
;
1832 if (SMBD_SMB2_IN_DYN_LEN(req
) < min_dyn_size
) {
1833 return NT_STATUS_INVALID_PARAMETER
;
1836 inbody
= SMBD_SMB2_IN_BODY_PTR(req
);
1838 body_size
= SVAL(inbody
, 0x00);
1839 if (body_size
!= expected_body_size
) {
1840 return NT_STATUS_INVALID_PARAMETER
;
1843 return NT_STATUS_OK
;
1846 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
1848 struct smbXsrv_connection
*conn
= req
->sconn
->conn
;
1849 const struct smbd_smb2_dispatch_table
*call
= NULL
;
1850 const struct iovec
*intf_v
= SMBD_SMB2_IN_TF_IOV(req
);
1851 const uint8_t *inhdr
;
1856 NTSTATUS session_status
;
1857 uint32_t allowed_flags
;
1858 NTSTATUS return_value
;
1859 struct smbXsrv_session
*x
= NULL
;
1860 bool signing_required
= false;
1861 bool encryption_required
= false;
1863 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1865 /* TODO: verify more things */
1867 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1868 opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1869 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1870 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1871 smb2_opcode_name(opcode
),
1872 (unsigned long long)mid
));
1874 if (conn
->protocol
>= PROTOCOL_SMB2_02
) {
1876 * once the protocol is negotiated
1877 * SMB2_OP_NEGPROT is not allowed anymore
1879 if (opcode
== SMB2_OP_NEGPROT
) {
1880 /* drop the connection */
1881 return NT_STATUS_INVALID_PARAMETER
;
1885 * if the protocol is not negotiated yet
1886 * only SMB2_OP_NEGPROT is allowed.
1888 if (opcode
!= SMB2_OP_NEGPROT
) {
1889 /* drop the connection */
1890 return NT_STATUS_INVALID_PARAMETER
;
1895 * Check if the client provided a valid session id,
1896 * if so smbd_smb2_request_check_session() calls
1897 * set_current_user_info().
1899 * As some command don't require a valid session id
1900 * we defer the check of the session_status
1902 session_status
= smbd_smb2_request_check_session(req
);
1905 signing_required
= x
->global
->signing_required
;
1906 encryption_required
= x
->global
->encryption_required
;
1908 if (opcode
== SMB2_OP_SESSSETUP
&&
1909 x
->global
->channels
[0].signing_key
.length
) {
1910 signing_required
= true;
1914 req
->do_signing
= false;
1915 req
->do_encryption
= false;
1916 if (intf_v
->iov_len
== SMB2_TF_HDR_SIZE
) {
1917 const uint8_t *intf
= SMBD_SMB2_IN_TF_PTR(req
);
1918 uint64_t tf_session_id
= BVAL(intf
, SMB2_TF_SESSION_ID
);
1920 if (x
!= NULL
&& x
->global
->session_wire_id
!= tf_session_id
) {
1921 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1922 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1923 (unsigned long long)x
->global
->session_wire_id
,
1924 (unsigned long long)tf_session_id
));
1926 * TODO: windows allows this...
1927 * should we drop the connection?
1929 * For now we just return ACCESS_DENIED
1930 * (Windows clients never trigger this)
1931 * and wait for an update of [MS-SMB2].
1933 return smbd_smb2_request_error(req
,
1934 NT_STATUS_ACCESS_DENIED
);
1937 req
->do_encryption
= true;
1940 if (encryption_required
&& !req
->do_encryption
) {
1941 return smbd_smb2_request_error(req
,
1942 NT_STATUS_ACCESS_DENIED
);
1945 call
= smbd_smb2_call(opcode
);
1947 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1950 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
1951 SMB2_HDR_FLAG_SIGNED
|
1953 if (opcode
== SMB2_OP_CANCEL
) {
1954 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
1956 if ((flags
& ~allowed_flags
) != 0) {
1957 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1960 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
1962 * This check is mostly for giving the correct error code
1963 * for compounded requests.
1965 if (!NT_STATUS_IS_OK(session_status
)) {
1966 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1969 req
->compat_chain_fsp
= NULL
;
1972 if (req
->do_encryption
) {
1973 signing_required
= false;
1974 } else if (flags
& SMB2_HDR_FLAG_SIGNED
) {
1975 DATA_BLOB signing_key
;
1978 return smbd_smb2_request_error(
1979 req
, NT_STATUS_ACCESS_DENIED
);
1982 signing_key
= x
->global
->channels
[0].signing_key
;
1985 * If we have a signing key, we should
1988 if (signing_key
.length
> 0) {
1989 req
->do_signing
= true;
1992 status
= smb2_signing_check_pdu(signing_key
,
1994 SMBD_SMB2_IN_HDR_IOV(req
),
1995 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
1996 if (!NT_STATUS_IS_OK(status
)) {
1997 return smbd_smb2_request_error(req
, status
);
2001 * Now that we know the request was correctly signed
2002 * we have to sign the response too.
2004 req
->do_signing
= true;
2006 if (!NT_STATUS_IS_OK(session_status
)) {
2007 return smbd_smb2_request_error(req
, session_status
);
2009 } else if (opcode
== SMB2_OP_CANCEL
) {
2010 /* Cancel requests are allowed to skip the signing */
2011 } else if (signing_required
) {
2013 * If signing is required we try to sign
2014 * a possible error response
2016 req
->do_signing
= true;
2017 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
2020 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
2021 req
->compound_related
= true;
2022 req
->sconn
->smb2
.compound_related_in_progress
= true;
2025 if (call
->need_session
) {
2026 if (!NT_STATUS_IS_OK(session_status
)) {
2027 return smbd_smb2_request_error(req
, session_status
);
2031 if (call
->need_tcon
) {
2032 SMB_ASSERT(call
->need_session
);
2035 * This call needs to be run as user.
2037 * smbd_smb2_request_check_tcon()
2038 * calls change_to_user() on success.
2040 status
= smbd_smb2_request_check_tcon(req
);
2041 if (!NT_STATUS_IS_OK(status
)) {
2042 return smbd_smb2_request_error(req
, status
);
2044 if (req
->tcon
->global
->encryption_required
) {
2045 encryption_required
= true;
2047 if (encryption_required
&& !req
->do_encryption
) {
2048 return smbd_smb2_request_error(req
,
2049 NT_STATUS_ACCESS_DENIED
);
2053 if (call
->fileid_ofs
!= 0) {
2054 size_t needed
= call
->fileid_ofs
+ 16;
2055 const uint8_t *body
= SMBD_SMB2_IN_BODY_PTR(req
);
2056 size_t body_size
= SMBD_SMB2_IN_BODY_LEN(req
);
2057 uint64_t file_id_persistent
;
2058 uint64_t file_id_volatile
;
2059 struct files_struct
*fsp
;
2061 SMB_ASSERT(call
->need_tcon
);
2063 if (needed
> body_size
) {
2064 return smbd_smb2_request_error(req
,
2065 NT_STATUS_INVALID_PARAMETER
);
2068 file_id_persistent
= BVAL(body
, call
->fileid_ofs
+ 0);
2069 file_id_volatile
= BVAL(body
, call
->fileid_ofs
+ 8);
2071 fsp
= file_fsp_smb2(req
, file_id_persistent
, file_id_volatile
);
2073 if (!call
->allow_invalid_fileid
) {
2074 return smbd_smb2_request_error(req
,
2075 NT_STATUS_FILE_CLOSED
);
2078 if (file_id_persistent
!= UINT64_MAX
) {
2079 return smbd_smb2_request_error(req
,
2080 NT_STATUS_FILE_CLOSED
);
2082 if (file_id_volatile
!= UINT64_MAX
) {
2083 return smbd_smb2_request_error(req
,
2084 NT_STATUS_FILE_CLOSED
);
2089 if (call
->as_root
) {
2090 SMB_ASSERT(call
->fileid_ofs
== 0);
2091 /* This call needs to be run as root */
2092 change_to_root_user();
2094 SMB_ASSERT(call
->need_tcon
);
2098 case SMB2_OP_NEGPROT
:
2100 START_PROFILE(smb2_negprot
);
2101 return_value
= smbd_smb2_request_process_negprot(req
);
2102 END_PROFILE(smb2_negprot
);
2106 case SMB2_OP_SESSSETUP
:
2108 START_PROFILE(smb2_sesssetup
);
2109 return_value
= smbd_smb2_request_process_sesssetup(req
);
2110 END_PROFILE(smb2_sesssetup
);
2114 case SMB2_OP_LOGOFF
:
2116 START_PROFILE(smb2_logoff
);
2117 return_value
= smbd_smb2_request_process_logoff(req
);
2118 END_PROFILE(smb2_logoff
);
2124 START_PROFILE(smb2_tcon
);
2125 return_value
= smbd_smb2_request_process_tcon(req
);
2126 END_PROFILE(smb2_tcon
);
2132 START_PROFILE(smb2_tdis
);
2133 return_value
= smbd_smb2_request_process_tdis(req
);
2134 END_PROFILE(smb2_tdis
);
2138 case SMB2_OP_CREATE
:
2140 START_PROFILE(smb2_create
);
2141 return_value
= smbd_smb2_request_process_create(req
);
2142 END_PROFILE(smb2_create
);
2148 START_PROFILE(smb2_close
);
2149 return_value
= smbd_smb2_request_process_close(req
);
2150 END_PROFILE(smb2_close
);
2156 START_PROFILE(smb2_flush
);
2157 return_value
= smbd_smb2_request_process_flush(req
);
2158 END_PROFILE(smb2_flush
);
2164 START_PROFILE(smb2_read
);
2165 return_value
= smbd_smb2_request_process_read(req
);
2166 END_PROFILE(smb2_read
);
2172 START_PROFILE(smb2_write
);
2173 return_value
= smbd_smb2_request_process_write(req
);
2174 END_PROFILE(smb2_write
);
2180 START_PROFILE(smb2_lock
);
2181 return_value
= smbd_smb2_request_process_lock(req
);
2182 END_PROFILE(smb2_lock
);
2188 START_PROFILE(smb2_ioctl
);
2189 return_value
= smbd_smb2_request_process_ioctl(req
);
2190 END_PROFILE(smb2_ioctl
);
2194 case SMB2_OP_CANCEL
:
2196 START_PROFILE(smb2_cancel
);
2197 return_value
= smbd_smb2_request_process_cancel(req
);
2198 END_PROFILE(smb2_cancel
);
2202 case SMB2_OP_KEEPALIVE
:
2204 START_PROFILE(smb2_keepalive
);
2205 return_value
= smbd_smb2_request_process_keepalive(req
);
2206 END_PROFILE(smb2_keepalive
);
2212 START_PROFILE(smb2_find
);
2213 return_value
= smbd_smb2_request_process_find(req
);
2214 END_PROFILE(smb2_find
);
2218 case SMB2_OP_NOTIFY
:
2220 START_PROFILE(smb2_notify
);
2221 return_value
= smbd_smb2_request_process_notify(req
);
2222 END_PROFILE(smb2_notify
);
2226 case SMB2_OP_GETINFO
:
2228 START_PROFILE(smb2_getinfo
);
2229 return_value
= smbd_smb2_request_process_getinfo(req
);
2230 END_PROFILE(smb2_getinfo
);
2234 case SMB2_OP_SETINFO
:
2236 START_PROFILE(smb2_setinfo
);
2237 return_value
= smbd_smb2_request_process_setinfo(req
);
2238 END_PROFILE(smb2_setinfo
);
2244 START_PROFILE(smb2_break
);
2245 return_value
= smbd_smb2_request_process_break(req
);
2246 END_PROFILE(smb2_break
);
2251 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2254 return return_value
;
2257 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
2259 struct smbXsrv_connection
*conn
= req
->sconn
->conn
;
2260 struct tevent_req
*subreq
;
2262 struct iovec
*firsttf
= SMBD_SMB2_IDX_TF_IOV(req
,out
,first_idx
);
2263 struct iovec
*outhdr
= SMBD_SMB2_OUT_HDR_IOV(req
);
2264 struct iovec
*outdyn
= SMBD_SMB2_OUT_DYN_IOV(req
);
2267 TALLOC_FREE(req
->async_te
);
2269 if (req
->do_encryption
&&
2270 (firsttf
->iov_len
== 0) &&
2271 (req
->first_key
.length
== 0) &&
2272 (req
->session
!= NULL
) &&
2273 (req
->session
->global
->encryption_key
.length
!= 0))
2275 DATA_BLOB encryption_key
= req
->session
->global
->encryption_key
;
2277 uint64_t session_id
= req
->session
->global
->session_wire_id
;
2278 struct smbXsrv_session
*x
= req
->session
;
2279 uint64_t nonce_high
;
2282 nonce_high
= x
->nonce_high
;
2283 nonce_low
= x
->nonce_low
;
2286 if (x
->nonce_low
== 0) {
2292 * We need to place the SMB2_TRANSFORM header before the
2297 * we need to remember the encryption key
2298 * and defer the signing/encryption until
2299 * we are sure that we do not change
2302 req
->first_key
= data_blob_dup_talloc(req
, encryption_key
);
2303 if (req
->first_key
.data
== NULL
) {
2304 return NT_STATUS_NO_MEMORY
;
2307 tf
= talloc_zero_array(req
->out
.vector
, uint8_t,
2310 return NT_STATUS_NO_MEMORY
;
2313 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
2314 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
2315 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
2316 SBVAL(tf
, SMB2_TF_SESSION_ID
, session_id
);
2318 firsttf
->iov_base
= (void *)tf
;
2319 firsttf
->iov_len
= SMB2_TF_HDR_SIZE
;
2322 if ((req
->current_idx
> SMBD_SMB2_NUM_IOV_PER_REQ
) &&
2323 (req
->last_key
.length
> 0) &&
2324 (firsttf
->iov_len
== 0))
2326 int last_idx
= req
->current_idx
- SMBD_SMB2_NUM_IOV_PER_REQ
;
2327 struct iovec
*lasthdr
= SMBD_SMB2_IDX_HDR_IOV(req
,out
,last_idx
);
2331 * As we are sure the header of the last request in the
2332 * compound chain will not change, we can to sign here
2333 * with the last signing key we remembered.
2335 status
= smb2_signing_sign_pdu(req
->last_key
,
2338 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2339 if (!NT_STATUS_IS_OK(status
)) {
2343 data_blob_clear_free(&req
->last_key
);
2345 req
->current_idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
;
2347 if (req
->current_idx
< req
->out
.vector_count
) {
2349 * We must process the remaining compound
2350 * SMB2 requests before any new incoming SMB2
2351 * requests. This is because incoming SMB2
2352 * requests may include a cancel for a
2353 * compound request we haven't processed
2356 struct tevent_immediate
*im
= tevent_create_immediate(req
);
2358 return NT_STATUS_NO_MEMORY
;
2361 if (req
->do_signing
&& firsttf
->iov_len
== 0) {
2362 struct smbXsrv_session
*x
= req
->session
;
2363 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
2366 * we need to remember the signing key
2367 * and defer the signing until
2368 * we are sure that we do not change
2371 req
->last_key
= data_blob_dup_talloc(req
, signing_key
);
2372 if (req
->last_key
.data
== NULL
) {
2373 return NT_STATUS_NO_MEMORY
;
2377 tevent_schedule_immediate(im
,
2379 smbd_smb2_request_dispatch_immediate
,
2381 return NT_STATUS_OK
;
2384 if (req
->compound_related
) {
2385 req
->compound_related
= false;
2386 req
->sconn
->smb2
.compound_related_in_progress
= false;
2389 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
2391 /* Set credit for these operations (zero credits if this
2392 is a final reply for an async operation). */
2393 smb2_calculate_credits(req
, req
);
2396 * now check if we need to sign the current response
2398 if (firsttf
->iov_len
== SMB2_TF_HDR_SIZE
) {
2401 status
= smb2_signing_encrypt_pdu(req
->first_key
,
2404 req
->out
.vector_count
- first_idx
);
2405 if (!NT_STATUS_IS_OK(status
)) {
2408 } else if (req
->do_signing
) {
2410 struct smbXsrv_session
*x
= req
->session
;
2411 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
2413 status
= smb2_signing_sign_pdu(signing_key
,
2416 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2417 if (!NT_STATUS_IS_OK(status
)) {
2421 data_blob_clear_free(&req
->first_key
);
2423 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2424 if (req
->out
.vector_count
< (2*SMBD_SMB2_NUM_IOV_PER_REQ
) &&
2425 outdyn
->iov_base
== NULL
&& outdyn
->iov_len
!= 0) {
2426 /* Dynamic part is NULL. Chop it off,
2427 We're going to send it via sendfile. */
2428 req
->out
.vector_count
-= 1;
2431 subreq
= tstream_writev_queue_send(req
,
2433 req
->sconn
->smb2
.stream
,
2434 req
->sconn
->smb2
.send_queue
,
2436 req
->out
.vector_count
);
2437 if (subreq
== NULL
) {
2438 return NT_STATUS_NO_MEMORY
;
2440 tevent_req_set_callback(subreq
, smbd_smb2_request_writev_done
, req
);
2442 * We're done with this request -
2443 * move it off the "being processed" queue.
2445 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
2447 return NT_STATUS_OK
;
2450 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
);
2452 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
2453 struct tevent_immediate
*im
,
2456 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
2457 struct smbd_smb2_request
);
2458 struct smbd_server_connection
*sconn
= req
->sconn
;
2463 if (DEBUGLEVEL
>= 10) {
2464 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2465 req
->current_idx
, req
->in
.vector_count
));
2466 print_req_vectors(req
);
2469 status
= smbd_smb2_request_dispatch(req
);
2470 if (!NT_STATUS_IS_OK(status
)) {
2471 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2475 status
= smbd_smb2_request_next_incoming(sconn
);
2476 if (!NT_STATUS_IS_OK(status
)) {
2477 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2482 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
)
2484 struct smbd_smb2_request
*req
= tevent_req_callback_data(subreq
,
2485 struct smbd_smb2_request
);
2486 struct smbd_server_connection
*sconn
= req
->sconn
;
2491 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
2492 TALLOC_FREE(subreq
);
2495 status
= map_nt_error_from_unix(sys_errno
);
2496 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2497 nt_errstr(status
)));
2498 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2502 status
= smbd_smb2_request_next_incoming(sconn
);
2503 if (!NT_STATUS_IS_OK(status
)) {
2504 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2509 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
2511 DATA_BLOB body
, DATA_BLOB
*dyn
,
2512 const char *location
)
2515 struct iovec
*outbody_v
;
2516 struct iovec
*outdyn_v
;
2517 uint32_t next_command_ofs
;
2519 DEBUG(10,("smbd_smb2_request_done_ex: "
2520 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2521 req
->current_idx
, nt_errstr(status
), (unsigned int)body
.length
,
2523 (unsigned int)(dyn
? dyn
->length
: 0),
2526 if (body
.length
< 2) {
2527 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2530 if ((body
.length
% 2) != 0) {
2531 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2534 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
2535 outbody_v
= SMBD_SMB2_OUT_BODY_IOV(req
);
2536 outdyn_v
= SMBD_SMB2_OUT_DYN_IOV(req
);
2538 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
2539 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
2541 outbody_v
->iov_base
= (void *)body
.data
;
2542 outbody_v
->iov_len
= body
.length
;
2545 outdyn_v
->iov_base
= (void *)dyn
->data
;
2546 outdyn_v
->iov_len
= dyn
->length
;
2548 outdyn_v
->iov_base
= NULL
;
2549 outdyn_v
->iov_len
= 0;
2552 /* see if we need to recalculate the offset to the next response */
2553 if (next_command_ofs
> 0) {
2554 next_command_ofs
= SMB2_HDR_BODY
;
2555 next_command_ofs
+= SMBD_SMB2_OUT_BODY_LEN(req
);
2556 next_command_ofs
+= SMBD_SMB2_OUT_DYN_LEN(req
);
2559 if ((next_command_ofs
% 8) != 0) {
2560 size_t pad_size
= 8 - (next_command_ofs
% 8);
2561 if (SMBD_SMB2_OUT_DYN_LEN(req
) == 0) {
2563 * if the dyn buffer is empty
2564 * we can use it to add padding
2568 pad
= talloc_zero_array(req
->out
.vector
,
2571 return smbd_smb2_request_error(req
,
2572 NT_STATUS_NO_MEMORY
);
2575 outdyn_v
->iov_base
= (void *)pad
;
2576 outdyn_v
->iov_len
= pad_size
;
2579 * For now we copy the dynamic buffer
2580 * and add the padding to the new buffer
2587 old_size
= SMBD_SMB2_OUT_DYN_LEN(req
);
2588 old_dyn
= SMBD_SMB2_OUT_DYN_PTR(req
);
2590 new_size
= old_size
+ pad_size
;
2591 new_dyn
= talloc_zero_array(req
->out
.vector
,
2593 if (new_dyn
== NULL
) {
2594 return smbd_smb2_request_error(req
,
2595 NT_STATUS_NO_MEMORY
);
2598 memcpy(new_dyn
, old_dyn
, old_size
);
2599 memset(new_dyn
+ old_size
, 0, pad_size
);
2601 outdyn_v
->iov_base
= (void *)new_dyn
;
2602 outdyn_v
->iov_len
= new_size
;
2604 next_command_ofs
+= pad_size
;
2607 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
2609 return smbd_smb2_request_reply(req
);
2612 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
2615 const char *location
)
2618 uint8_t *outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
2620 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2621 req
->current_idx
, nt_errstr(status
), info
? " +info" : "",
2624 body
.data
= outhdr
+ SMB2_HDR_BODY
;
2626 SSVAL(body
.data
, 0, 9);
2629 SIVAL(body
.data
, 0x04, info
->length
);
2631 /* Allocated size of req->out.vector[i].iov_base
2632 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2633 * 1 byte without having to do an alloc.
2635 info
= talloc_zero_array(req
->out
.vector
,
2639 return NT_STATUS_NO_MEMORY
;
2641 info
->data
= ((uint8_t *)outhdr
) +
2642 OUTVEC_ALLOC_SIZE
- 1;
2644 SCVAL(info
->data
, 0, 0);
2648 * Note: Even if there is an error, continue to process the request.
2652 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
2656 struct smbd_smb2_send_oplock_break_state
{
2657 struct smbd_server_connection
*sconn
;
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 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
);
2664 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
2665 struct smbXsrv_session
*session
,
2666 struct smbXsrv_tcon
*tcon
,
2667 struct smbXsrv_open
*op
,
2668 uint8_t oplock_level
)
2670 struct smbd_smb2_send_oplock_break_state
*state
;
2671 struct smbXsrv_connection
*conn
= sconn
->conn
;
2672 struct tevent_req
*subreq
;
2680 bool do_encryption
= session
->global
->encryption_required
;
2681 uint64_t nonce_high
= 0;
2682 uint64_t nonce_low
= 0;
2684 if (tcon
->global
->encryption_required
) {
2685 do_encryption
= true;
2688 state
= talloc(sconn
, struct smbd_smb2_send_oplock_break_state
);
2689 if (state
== NULL
) {
2690 return NT_STATUS_NO_MEMORY
;
2692 state
->sconn
= sconn
;
2694 tf
= state
->buf
+ NBT_HDR_SIZE
;
2695 tf_len
= SMB2_TF_HDR_SIZE
;
2697 body
= hdr
+ SMB2_HDR_BODY
;
2699 dyn
= body
+ body_len
;
2702 if (do_encryption
) {
2703 nonce_high
= session
->nonce_high
;
2704 nonce_low
= session
->nonce_low
;
2706 session
->nonce_low
+= 1;
2707 if (session
->nonce_low
== 0) {
2708 session
->nonce_low
+= 1;
2709 session
->nonce_high
+= 1;
2713 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
2714 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
2715 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
2716 SBVAL(tf
, SMB2_TF_SESSION_ID
, session
->global
->session_wire_id
);
2718 SIVAL(hdr
, 0, SMB2_MAGIC
);
2719 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
2720 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
2721 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
2722 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
2723 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
2724 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
2725 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
2726 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
2727 SIVAL(hdr
, SMB2_HDR_PID
, 0);
2728 SIVAL(hdr
, SMB2_HDR_TID
, 0);
2729 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
2730 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
2732 SSVAL(body
, 0x00, body_len
);
2734 SCVAL(body
, 0x02, oplock_level
);
2735 SCVAL(body
, 0x03, 0); /* reserved */
2736 SIVAL(body
, 0x04, 0); /* reserved */
2737 SBVAL(body
, 0x08, op
->global
->open_persistent_id
);
2738 SBVAL(body
, 0x10, op
->global
->open_volatile_id
);
2740 state
->vector
[0].iov_base
= (void *)state
->buf
;
2741 state
->vector
[0].iov_len
= NBT_HDR_SIZE
;
2743 if (do_encryption
) {
2744 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= tf
;
2745 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= tf_len
;
2747 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
2748 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
2751 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
2752 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
2754 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
2755 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_len
= body_len
;
2757 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
2758 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_len
= dyn_len
;
2760 smb2_setup_nbt_length(state
->vector
, 1 + SMBD_SMB2_NUM_IOV_PER_REQ
);
2762 if (do_encryption
) {
2764 DATA_BLOB encryption_key
= session
->global
->encryption_key
;
2766 status
= smb2_signing_encrypt_pdu(encryption_key
,
2768 &state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
],
2769 SMBD_SMB2_NUM_IOV_PER_REQ
);
2770 if (!NT_STATUS_IS_OK(status
)) {
2775 subreq
= tstream_writev_queue_send(state
,
2778 sconn
->smb2
.send_queue
,
2780 ARRAY_SIZE(state
->vector
));
2781 if (subreq
== NULL
) {
2782 return NT_STATUS_NO_MEMORY
;
2784 tevent_req_set_callback(subreq
,
2785 smbd_smb2_oplock_break_writev_done
,
2788 return NT_STATUS_OK
;
2791 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
)
2793 struct smbd_smb2_send_oplock_break_state
*state
=
2794 tevent_req_callback_data(subreq
,
2795 struct smbd_smb2_send_oplock_break_state
);
2796 struct smbd_server_connection
*sconn
= state
->sconn
;
2800 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
2801 TALLOC_FREE(subreq
);
2803 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
2804 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2811 struct smbd_smb2_request_read_state
{
2812 struct tevent_context
*ev
;
2813 struct smbd_server_connection
*sconn
;
2814 struct smbd_smb2_request
*smb2_req
;
2816 uint8_t nbt
[NBT_HDR_SIZE
];
2823 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2825 TALLOC_CTX
*mem_ctx
,
2826 struct iovec
**_vector
,
2828 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
);
2830 static struct tevent_req
*smbd_smb2_request_read_send(TALLOC_CTX
*mem_ctx
,
2831 struct tevent_context
*ev
,
2832 struct smbd_server_connection
*sconn
)
2834 struct tevent_req
*req
;
2835 struct smbd_smb2_request_read_state
*state
;
2836 struct tevent_req
*subreq
;
2838 req
= tevent_req_create(mem_ctx
, &state
,
2839 struct smbd_smb2_request_read_state
);
2844 state
->sconn
= sconn
;
2846 state
->smb2_req
= smbd_smb2_request_allocate(state
);
2847 if (tevent_req_nomem(state
->smb2_req
, req
)) {
2848 return tevent_req_post(req
, ev
);
2850 state
->smb2_req
->sconn
= sconn
;
2852 subreq
= tstream_readv_pdu_queue_send(state
->smb2_req
,
2854 state
->sconn
->smb2
.stream
,
2855 state
->sconn
->smb2
.recv_queue
,
2856 smbd_smb2_request_next_vector
,
2858 if (tevent_req_nomem(subreq
, req
)) {
2859 return tevent_req_post(req
, ev
);
2861 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
2866 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2868 TALLOC_CTX
*mem_ctx
,
2869 struct iovec
**_vector
,
2872 struct smbd_smb2_request_read_state
*state
=
2873 talloc_get_type_abort(private_data
,
2874 struct smbd_smb2_request_read_state
);
2875 struct iovec
*vector
;
2877 if (state
->pktlen
> 0) {
2878 /* if there're no remaining bytes, we're done */
2884 if (!state
->hdr
.done
) {
2886 * first we need to get the NBT header
2888 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2889 if (vector
== NULL
) {
2893 vector
[0].iov_base
= (void *)state
->hdr
.nbt
;
2894 vector
[0].iov_len
= NBT_HDR_SIZE
;
2899 state
->hdr
.done
= true;
2904 * Now we analyze the NBT header
2906 state
->pktlen
= smb2_len(state
->hdr
.nbt
);
2908 if (state
->pktlen
== 0) {
2909 /* if there're no remaining bytes, we're done */
2915 state
->pktbuf
= talloc_array(state
->smb2_req
, uint8_t, state
->pktlen
);
2916 if (state
->pktbuf
== NULL
) {
2920 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2921 if (vector
== NULL
) {
2925 vector
[0].iov_base
= (void *)state
->pktbuf
;
2926 vector
[0].iov_len
= state
->pktlen
;
2933 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
)
2935 struct tevent_req
*req
=
2936 tevent_req_callback_data(subreq
,
2938 struct smbd_smb2_request_read_state
*state
=
2939 tevent_req_data(req
,
2940 struct smbd_smb2_request_read_state
);
2946 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
2947 TALLOC_FREE(subreq
);
2949 status
= map_nt_error_from_unix(sys_errno
);
2950 tevent_req_nterror(req
, status
);
2954 if (state
->hdr
.nbt
[0] != 0x00) {
2955 DEBUG(1,("smbd_smb2_request_read_done: ignore NBT[0x%02X] msg\n",
2956 state
->hdr
.nbt
[0]));
2958 ZERO_STRUCT(state
->hdr
);
2959 TALLOC_FREE(state
->pktbuf
);
2962 subreq
= tstream_readv_pdu_queue_send(state
->smb2_req
,
2964 state
->sconn
->smb2
.stream
,
2965 state
->sconn
->smb2
.recv_queue
,
2966 smbd_smb2_request_next_vector
,
2968 if (tevent_req_nomem(subreq
, req
)) {
2971 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
2975 state
->smb2_req
->request_time
= timeval_current();
2976 now
= timeval_to_nttime(&state
->smb2_req
->request_time
);
2978 status
= smbd_smb2_inbuf_parse_compound(state
->smb2_req
->sconn
->conn
,
2983 &state
->smb2_req
->in
.vector
,
2984 &state
->smb2_req
->in
.vector_count
);
2985 if (tevent_req_nterror(req
, status
)) {
2989 state
->smb2_req
->current_idx
= 1;
2991 tevent_req_done(req
);
2994 static NTSTATUS
smbd_smb2_request_read_recv(struct tevent_req
*req
,
2995 TALLOC_CTX
*mem_ctx
,
2996 struct smbd_smb2_request
**_smb2_req
)
2998 struct smbd_smb2_request_read_state
*state
=
2999 tevent_req_data(req
,
3000 struct smbd_smb2_request_read_state
);
3003 if (tevent_req_is_nterror(req
, &status
)) {
3004 tevent_req_received(req
);
3008 *_smb2_req
= talloc_move(mem_ctx
, &state
->smb2_req
);
3009 tevent_req_received(req
);
3010 return NT_STATUS_OK
;
3013 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
);
3015 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
)
3017 size_t max_send_queue_len
;
3018 size_t cur_send_queue_len
;
3019 struct tevent_req
*subreq
;
3021 if (sconn
->smb2
.compound_related_in_progress
) {
3023 * Can't read another until the related
3026 return NT_STATUS_OK
;
3029 if (tevent_queue_length(sconn
->smb2
.recv_queue
) > 0) {
3031 * if there is already a smbd_smb2_request_read
3032 * pending, we are done.
3034 return NT_STATUS_OK
;
3037 max_send_queue_len
= MAX(1, sconn
->smb2
.max_credits
/16);
3038 cur_send_queue_len
= tevent_queue_length(sconn
->smb2
.send_queue
);
3040 if (cur_send_queue_len
> max_send_queue_len
) {
3042 * if we have a lot of requests to send,
3043 * we wait until they are on the wire until we
3044 * ask for the next request.
3046 return NT_STATUS_OK
;
3049 /* ask for the next request */
3050 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->ev_ctx
, sconn
);
3051 if (subreq
== NULL
) {
3052 return NT_STATUS_NO_MEMORY
;
3054 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);
3056 return NT_STATUS_OK
;
3059 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
3060 uint8_t *inbuf
, size_t size
)
3063 struct smbd_smb2_request
*req
= NULL
;
3065 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3066 (unsigned int)size
));
3068 status
= smbd_initialize_smb2(sconn
);
3069 if (!NT_STATUS_IS_OK(status
)) {
3070 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3074 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
3075 if (!NT_STATUS_IS_OK(status
)) {
3076 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3080 status
= smbd_smb2_request_validate(req
);
3081 if (!NT_STATUS_IS_OK(status
)) {
3082 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3086 status
= smbd_smb2_request_setup_out(req
);
3087 if (!NT_STATUS_IS_OK(status
)) {
3088 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3092 status
= smbd_smb2_request_dispatch(req
);
3093 if (!NT_STATUS_IS_OK(status
)) {
3094 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3098 status
= smbd_smb2_request_next_incoming(sconn
);
3099 if (!NT_STATUS_IS_OK(status
)) {
3100 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3104 sconn
->num_requests
++;
3107 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
)
3109 struct smbd_server_connection
*sconn
= tevent_req_callback_data(subreq
,
3110 struct smbd_server_connection
);
3112 struct smbd_smb2_request
*req
= NULL
;
3114 status
= smbd_smb2_request_read_recv(subreq
, sconn
, &req
);
3115 TALLOC_FREE(subreq
);
3116 if (!NT_STATUS_IS_OK(status
)) {
3117 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
3118 nt_errstr(status
)));
3119 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3123 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
3124 req
->current_idx
, req
->in
.vector_count
));
3126 status
= smbd_smb2_request_validate(req
);
3127 if (!NT_STATUS_IS_OK(status
)) {
3128 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3132 status
= smbd_smb2_request_setup_out(req
);
3133 if (!NT_STATUS_IS_OK(status
)) {
3134 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3138 status
= smbd_smb2_request_dispatch(req
);
3139 if (!NT_STATUS_IS_OK(status
)) {
3140 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3144 status
= smbd_smb2_request_next_incoming(sconn
);
3145 if (!NT_STATUS_IS_OK(status
)) {
3146 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3150 sconn
->num_requests
++;
3152 /* The timeout_processing function isn't run nearly
3153 often enough to implement 'max log size' without
3154 overrunning the size of the file by many megabytes.
3155 This is especially true if we are running at debug
3156 level 10. Checking every 50 SMB2s is a nice
3157 tradeoff of performance vs log file size overrun. */
3159 if ((sconn
->num_requests
% 50) == 0 &&
3160 need_to_check_log_size()) {
3161 change_to_root_user();