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 very high credit charge.
762 * TODO: scale up depending on 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
);
784 if (sconn
->smb2
.max_credits
< credit_charge
) {
785 smbd_server_connection_terminate(sconn
,
786 "client error: credit charge > max credits\n");
790 if (out_flags
& SMB2_HDR_FLAG_ASYNC
) {
792 * In case we already send an async interim
793 * response, we should not grant
794 * credits on the final response.
797 } else if (credits_requested
> 0) {
798 uint16_t additional_max
= 0;
799 uint16_t additional_credits
= credits_requested
- 1;
802 case SMB2_OP_NEGPROT
:
804 case SMB2_OP_SESSSETUP
:
806 * Windows 2012 RC1 starts to grant
808 * with a successful session setup
810 if (NT_STATUS_IS_OK(out_status
)) {
816 * We match windows and only grant additional credits
823 additional_credits
= MIN(additional_credits
, additional_max
);
825 credits_granted
= credit_charge
+ additional_credits
;
826 } else if (sconn
->smb2
.credits_granted
== 0) {
828 * Make sure the client has always at least one credit
834 * sequence numbers should not wrap
836 * 1. calculate the possible credits until
837 * the sequence numbers start to wrap on 64-bit.
839 * 2. UINT64_MAX is used for Break Notifications.
841 * 2. truncate the possible credits to the maximum
842 * credits we want to grant to the client in total.
844 * 3. remove the range we'll already granted to the client
845 * this makes sure the client consumes the lowest sequence
846 * number, before we can grant additional credits.
848 credits_possible
= UINT64_MAX
- sconn
->smb2
.seqnum_low
;
849 if (credits_possible
> 0) {
850 /* remove UINT64_MAX */
851 credits_possible
-= 1;
853 credits_possible
= MIN(credits_possible
, current_max_credits
);
854 credits_possible
-= sconn
->smb2
.seqnum_range
;
856 credits_granted
= MIN(credits_granted
, credits_possible
);
858 SSVAL(outhdr
, SMB2_HDR_CREDIT
, credits_granted
);
859 sconn
->smb2
.credits_granted
+= credits_granted
;
860 sconn
->smb2
.seqnum_range
+= credits_granted
;
862 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
863 "granted %u, current possible/max %u/%u, "
864 "total granted/max/low/range %u/%u/%llu/%u\n",
865 (unsigned int)credits_requested
,
866 (unsigned int)credit_charge
,
867 (unsigned int)credits_granted
,
868 (unsigned int)credits_possible
,
869 (unsigned int)current_max_credits
,
870 (unsigned int)sconn
->smb2
.credits_granted
,
871 (unsigned int)sconn
->smb2
.max_credits
,
872 (unsigned long long)sconn
->smb2
.seqnum_low
,
873 (unsigned int)sconn
->smb2
.seqnum_range
));
876 static void smb2_calculate_credits(const struct smbd_smb2_request
*inreq
,
877 struct smbd_smb2_request
*outreq
)
880 uint16_t total_credits
= 0;
882 count
= outreq
->out
.vector_count
;
884 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
885 struct iovec
*inhdr_v
= SMBD_SMB2_IDX_HDR_IOV(inreq
,in
,idx
);
886 struct iovec
*outhdr_v
= SMBD_SMB2_IDX_HDR_IOV(outreq
,out
,idx
);
887 uint8_t *outhdr
= (uint8_t *)outhdr_v
->iov_base
;
889 smb2_set_operation_credit(outreq
->sconn
, inhdr_v
, outhdr_v
);
891 /* To match Windows, count up what we
893 total_credits
+= SVAL(outhdr
, SMB2_HDR_CREDIT
);
894 /* Set to zero in all but the last reply. */
895 if (idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
< count
) {
896 SSVAL(outhdr
, SMB2_HDR_CREDIT
, 0);
898 SSVAL(outhdr
, SMB2_HDR_CREDIT
, total_credits
);
903 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
)
905 struct iovec
*vector
;
909 count
= req
->in
.vector_count
;
910 vector
= talloc_zero_array(req
, struct iovec
, count
);
911 if (vector
== NULL
) {
912 return NT_STATUS_NO_MEMORY
;
915 vector
[0].iov_base
= req
->out
.nbt_hdr
;
916 vector
[0].iov_len
= 4;
917 SIVAL(req
->out
.nbt_hdr
, 0, 0);
919 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
920 struct iovec
*inhdr_v
= SMBD_SMB2_IDX_HDR_IOV(req
,in
,idx
);
921 const uint8_t *inhdr
= (const uint8_t *)inhdr_v
->iov_base
;
922 uint8_t *outhdr
= NULL
;
923 uint8_t *outbody
= NULL
;
924 uint32_t next_command_ofs
= 0;
925 struct iovec
*current
= &vector
[idx
];
927 if ((idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
) < count
) {
928 /* we have a next command -
929 * setup for the error case. */
930 next_command_ofs
= SMB2_HDR_BODY
+ 9;
933 outhdr
= talloc_zero_array(vector
, uint8_t,
935 if (outhdr
== NULL
) {
936 return NT_STATUS_NO_MEMORY
;
939 outbody
= outhdr
+ SMB2_HDR_BODY
;
942 * SMBD_SMB2_TF_IOV_OFS might be used later
944 current
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
945 current
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
947 current
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= (void *)outhdr
;
948 current
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
950 current
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= (void *)outbody
;
951 current
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= 8;
953 current
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= NULL
;
954 current
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= 0;
956 /* setup the SMB2 header */
957 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
958 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
959 SSVAL(outhdr
, SMB2_HDR_CREDIT_CHARGE
,
960 SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
));
961 SIVAL(outhdr
, SMB2_HDR_STATUS
,
962 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
963 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
964 SVAL(inhdr
, SMB2_HDR_OPCODE
));
965 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
966 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
967 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
968 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
969 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
970 SIVAL(outhdr
, SMB2_HDR_PID
,
971 IVAL(inhdr
, SMB2_HDR_PID
));
972 SIVAL(outhdr
, SMB2_HDR_TID
,
973 IVAL(inhdr
, SMB2_HDR_TID
));
974 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
975 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
976 memcpy(outhdr
+ SMB2_HDR_SIGNATURE
,
977 inhdr
+ SMB2_HDR_SIGNATURE
, 16);
979 /* setup error body header */
980 SSVAL(outbody
, 0x00, 0x08 + 1);
981 SSVAL(outbody
, 0x02, 0);
982 SIVAL(outbody
, 0x04, 0);
985 req
->out
.vector
= vector
;
986 req
->out
.vector_count
= count
;
988 /* setup the length of the NBT packet */
989 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
991 DLIST_ADD_END(req
->sconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
996 void smbd_server_connection_terminate_ex(struct smbd_server_connection
*sconn
,
998 const char *location
)
1000 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1002 exit_server_cleanly(reason
);
1005 static bool dup_smb2_vec4(TALLOC_CTX
*ctx
,
1006 struct iovec
*outvec
,
1007 const struct iovec
*srcvec
)
1009 const uint8_t *srctf
;
1011 const uint8_t *srchdr
;
1013 const uint8_t *srcbody
;
1015 const uint8_t *expected_srcbody
;
1016 const uint8_t *srcdyn
;
1018 const uint8_t *expected_srcdyn
;
1024 srctf
= (const uint8_t *)srcvec
[SMBD_SMB2_TF_IOV_OFS
].iov_base
;
1025 srctf_len
= srcvec
[SMBD_SMB2_TF_IOV_OFS
].iov_len
;
1026 srchdr
= (const uint8_t *)srcvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
;
1027 srchdr_len
= srcvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
;
1028 srcbody
= (const uint8_t *)srcvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
;
1029 srcbody_len
= srcvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
;
1030 expected_srcbody
= srchdr
+ SMB2_HDR_BODY
;
1031 srcdyn
= (const uint8_t *)srcvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
;
1032 srcdyn_len
= srcvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
;
1033 expected_srcdyn
= srcbody
+ 8;
1035 if ((srctf_len
!= SMB2_TF_HDR_SIZE
) && (srctf_len
!= 0)) {
1039 if (srchdr_len
!= SMB2_HDR_BODY
) {
1043 if (srctf_len
== SMB2_TF_HDR_SIZE
) {
1044 dsttf
= talloc_memdup(ctx
, srctf
, SMB2_TF_HDR_SIZE
);
1045 if (dsttf
== NULL
) {
1051 outvec
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= (void *)dsttf
;
1052 outvec
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= srctf_len
;
1054 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1055 * be allocated with size OUTVEC_ALLOC_SIZE. */
1057 dsthdr
= talloc_memdup(ctx
, srchdr
, OUTVEC_ALLOC_SIZE
);
1058 if (dsthdr
== NULL
) {
1061 outvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= (void *)dsthdr
;
1062 outvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
1065 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1066 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1067 * then duplicate this. Else use talloc_memdup().
1070 if ((srcbody
== expected_srcbody
) && (srcbody_len
== 8)) {
1071 dstbody
= dsthdr
+ SMB2_HDR_BODY
;
1073 dstbody
= talloc_memdup(ctx
, srcbody
, srcbody_len
);
1074 if (dstbody
== NULL
) {
1078 outvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= (void *)dstbody
;
1079 outvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= srcbody_len
;
1082 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1084 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1085 * then duplicate this. Else use talloc_memdup().
1088 if ((srcdyn
== expected_srcdyn
) && (srcdyn_len
== 1)) {
1089 dstdyn
= dsthdr
+ SMB2_HDR_BODY
+ 8;
1090 } else if (srcdyn
== NULL
) {
1093 dstdyn
= talloc_memdup(ctx
, srcdyn
, srcdyn_len
);
1094 if (dstdyn
== NULL
) {
1098 outvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= (void *)dstdyn
;
1099 outvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= srcdyn_len
;
1104 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
1106 struct smbd_smb2_request
*newreq
= NULL
;
1107 struct iovec
*outvec
= NULL
;
1108 int count
= req
->out
.vector_count
;
1111 newreq
= smbd_smb2_request_allocate(req
->sconn
);
1116 newreq
->sconn
= req
->sconn
;
1117 newreq
->session
= req
->session
;
1118 newreq
->do_encryption
= req
->do_encryption
;
1119 newreq
->do_signing
= req
->do_signing
;
1120 newreq
->current_idx
= req
->current_idx
;
1122 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
1124 TALLOC_FREE(newreq
);
1127 newreq
->out
.vector
= outvec
;
1128 newreq
->out
.vector_count
= count
;
1130 /* Setup the outvec's identically to req. */
1131 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
1132 outvec
[0].iov_len
= 4;
1133 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
1135 /* Setup the vectors identically to the ones in req. */
1136 for (i
= 1; i
< count
; i
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
1137 if (!dup_smb2_vec4(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
1144 TALLOC_FREE(newreq
);
1148 smb2_setup_nbt_length(newreq
->out
.vector
,
1149 newreq
->out
.vector_count
);
1154 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
);
1156 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
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
->subreq
= tstream_writev_queue_send(nreq
,
1222 nreq
->sconn
->ev_ctx
,
1223 nreq
->sconn
->smb2
.stream
,
1224 nreq
->sconn
->smb2
.send_queue
,
1226 nreq
->out
.vector_count
);
1228 if (nreq
->subreq
== NULL
) {
1229 return NT_STATUS_NO_MEMORY
;
1232 tevent_req_set_callback(nreq
->subreq
,
1233 smbd_smb2_request_writev_done
,
1236 return NT_STATUS_OK
;
1239 struct smbd_smb2_request_pending_state
{
1240 struct smbd_server_connection
*sconn
;
1241 uint8_t buf
[NBT_HDR_SIZE
+ SMB2_TF_HDR_SIZE
+ SMB2_HDR_BODY
+ 0x08 + 1];
1242 struct iovec vector
[1 + SMBD_SMB2_NUM_IOV_PER_REQ
];
1245 static void smbd_smb2_request_pending_writev_done(struct tevent_req
*subreq
)
1247 struct smbd_smb2_request_pending_state
*state
=
1248 tevent_req_callback_data(subreq
,
1249 struct smbd_smb2_request_pending_state
);
1250 struct smbd_server_connection
*sconn
= state
->sconn
;
1254 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1255 TALLOC_FREE(subreq
);
1257 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
1258 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1265 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
1266 struct tevent_timer
*te
,
1267 struct timeval current_time
,
1268 void *private_data
);
1270 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
1271 struct tevent_req
*subreq
,
1272 uint32_t defer_time
)
1275 int idx
= req
->current_idx
;
1276 struct timeval defer_endtime
;
1277 uint8_t *outhdr
= NULL
;
1280 if (!tevent_req_is_in_progress(subreq
)) {
1281 return NT_STATUS_OK
;
1284 req
->subreq
= subreq
;
1287 if (req
->async_te
) {
1288 /* We're already async. */
1289 return NT_STATUS_OK
;
1292 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1293 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1294 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1295 /* We're already async. */
1296 return NT_STATUS_OK
;
1299 if (req
->in
.vector_count
> idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
) {
1301 * We're trying to go async in a compound
1302 * request chain. This is not allowed.
1303 * Cancel the outstanding request.
1305 bool ok
= tevent_req_cancel(req
->subreq
);
1307 return NT_STATUS_OK
;
1309 TALLOC_FREE(req
->subreq
);
1310 return smbd_smb2_request_error(req
,
1311 NT_STATUS_INTERNAL_ERROR
);
1314 if (DEBUGLEVEL
>= 10) {
1315 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1316 (unsigned int)req
->current_idx
);
1317 print_req_vectors(req
);
1320 if (req
->out
.vector_count
>= (2*SMBD_SMB2_NUM_IOV_PER_REQ
)) {
1322 * This is a compound reply. We
1323 * must do an interim response
1324 * followed by the async response
1327 status
= smb2_send_async_interim_response(req
);
1328 if (!NT_STATUS_IS_OK(status
)) {
1331 data_blob_clear_free(&req
->first_key
);
1334 * We're splitting off the last SMB2
1335 * request in a compound set, and the
1336 * smb2_send_async_interim_response()
1337 * call above just sent all the replies
1338 * for the previous SMB2 requests in
1339 * this compound set. So we're no longer
1340 * in the "compound_related_in_progress"
1341 * state, and this is no longer a compound
1344 req
->compound_related
= false;
1345 req
->sconn
->smb2
.compound_related_in_progress
= false;
1347 req
->current_idx
= 1;
1349 /* Re-arrange the in.vectors. */
1350 memmove(&req
->in
.vector
[req
->current_idx
],
1351 &req
->in
.vector
[idx
],
1352 sizeof(req
->in
.vector
[0])*SMBD_SMB2_NUM_IOV_PER_REQ
);
1353 req
->in
.vector_count
= req
->current_idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
;
1355 /* Re-arrange the out.vectors. */
1356 memmove(&req
->out
.vector
[req
->current_idx
],
1357 &req
->out
.vector
[idx
],
1358 sizeof(req
->out
.vector
[0])*SMBD_SMB2_NUM_IOV_PER_REQ
);
1359 req
->out
.vector_count
= req
->current_idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
;
1361 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1362 flags
= (IVAL(outhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
1363 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
);
1365 data_blob_clear_free(&req
->last_key
);
1367 defer_endtime
= timeval_current_ofs_usec(defer_time
);
1368 req
->async_te
= tevent_add_timer(req
->sconn
->ev_ctx
,
1370 smbd_smb2_request_pending_timer
,
1372 if (req
->async_te
== NULL
) {
1373 return NT_STATUS_NO_MEMORY
;
1376 return NT_STATUS_OK
;
1379 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
1380 struct tevent_timer
*te
,
1381 struct timeval current_time
,
1384 struct smbd_smb2_request
*req
=
1385 talloc_get_type_abort(private_data
,
1386 struct smbd_smb2_request
);
1387 struct smbd_smb2_request_pending_state
*state
= NULL
;
1388 uint8_t *outhdr
= NULL
;
1389 const uint8_t *inhdr
= NULL
;
1392 uint8_t *hdr
= NULL
;
1393 uint8_t *body
= NULL
;
1394 uint8_t *dyn
= NULL
;
1396 uint64_t session_id
= 0;
1397 uint64_t message_id
= 0;
1398 uint64_t nonce_high
= 0;
1399 uint64_t nonce_low
= 0;
1400 uint64_t async_id
= 0;
1401 struct tevent_req
*subreq
= NULL
;
1403 TALLOC_FREE(req
->async_te
);
1405 /* Ensure our final reply matches the interim one. */
1406 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1407 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1408 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1409 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1410 session_id
= BVAL(outhdr
, SMB2_HDR_SESSION_ID
);
1412 async_id
= message_id
; /* keep it simple for now... */
1414 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1415 SBVAL(outhdr
, SMB2_HDR_ASYNC_ID
, async_id
);
1417 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1419 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1420 (unsigned long long)async_id
));
1423 * What we send is identical to a smbd_smb2_request_error
1424 * packet with an error status of STATUS_PENDING. Make use
1425 * of this fact sometime when refactoring. JRA.
1428 state
= talloc_zero(req
->sconn
, struct smbd_smb2_request_pending_state
);
1429 if (state
== NULL
) {
1430 smbd_server_connection_terminate(req
->sconn
,
1431 nt_errstr(NT_STATUS_NO_MEMORY
));
1434 state
->sconn
= req
->sconn
;
1436 tf
= state
->buf
+ NBT_HDR_SIZE
;
1437 tf_len
= SMB2_TF_HDR_SIZE
;
1439 hdr
= tf
+ SMB2_TF_HDR_SIZE
;
1440 body
= hdr
+ SMB2_HDR_BODY
;
1443 if (req
->do_encryption
) {
1444 struct smbXsrv_session
*x
= req
->session
;
1446 nonce_high
= x
->nonce_high
;
1447 nonce_low
= x
->nonce_low
;
1450 if (x
->nonce_low
== 0) {
1456 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
1457 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
1458 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
1459 SBVAL(tf
, SMB2_TF_SESSION_ID
, session_id
);
1461 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
1462 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1463 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1464 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
1465 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(outhdr
, SMB2_HDR_OPCODE
));
1467 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
);
1468 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1469 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
1470 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
1471 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
1472 BVAL(outhdr
, SMB2_HDR_SESSION_ID
));
1473 memcpy(hdr
+SMB2_HDR_SIGNATURE
,
1474 outhdr
+SMB2_HDR_SIGNATURE
, 16);
1476 SSVAL(body
, 0x00, 0x08 + 1);
1478 SCVAL(body
, 0x02, 0);
1479 SCVAL(body
, 0x03, 0);
1480 SIVAL(body
, 0x04, 0);
1481 /* Match W2K8R2... */
1482 SCVAL(dyn
, 0x00, 0x21);
1484 state
->vector
[0].iov_base
= (void *)state
->buf
;
1485 state
->vector
[0].iov_len
= NBT_HDR_SIZE
;
1487 if (req
->do_encryption
) {
1488 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= tf
;
1489 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= tf_len
;
1491 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
1492 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
1495 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
1496 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
1498 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
1499 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_len
= 8;
1501 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
1502 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_len
= 1;
1504 smb2_setup_nbt_length(state
->vector
, 1 + SMBD_SMB2_NUM_IOV_PER_REQ
);
1506 /* Ensure we correctly go through crediting. Grant
1507 the credits now, and zero credits on the final
1509 smb2_set_operation_credit(req
->sconn
,
1510 SMBD_SMB2_IN_HDR_IOV(req
),
1511 &state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
]);
1513 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1518 for (i
= 0; i
< ARRAY_SIZE(state
->vector
); i
++) {
1519 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1521 (unsigned int)ARRAY_SIZE(state
->vector
),
1522 (unsigned int)state
->vector
[i
].iov_len
);
1526 if (req
->do_encryption
) {
1528 struct smbXsrv_session
*x
= req
->session
;
1529 struct smbXsrv_connection
*conn
= x
->connection
;
1530 DATA_BLOB encryption_key
= x
->global
->encryption_key
;
1532 status
= smb2_signing_encrypt_pdu(encryption_key
,
1534 &state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
],
1535 SMBD_SMB2_NUM_IOV_PER_REQ
);
1536 if (!NT_STATUS_IS_OK(status
)) {
1537 smbd_server_connection_terminate(req
->sconn
,
1541 } else if (req
->do_signing
) {
1543 struct smbXsrv_session
*x
= req
->session
;
1544 struct smbXsrv_connection
*conn
= x
->connection
;
1545 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
1547 status
= smb2_signing_sign_pdu(signing_key
,
1549 &state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
],
1550 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
1551 if (!NT_STATUS_IS_OK(status
)) {
1552 smbd_server_connection_terminate(req
->sconn
,
1558 subreq
= tstream_writev_queue_send(state
,
1559 state
->sconn
->ev_ctx
,
1560 state
->sconn
->smb2
.stream
,
1561 state
->sconn
->smb2
.send_queue
,
1563 ARRAY_SIZE(state
->vector
));
1564 if (subreq
== NULL
) {
1565 smbd_server_connection_terminate(state
->sconn
,
1566 nt_errstr(NT_STATUS_NO_MEMORY
));
1569 tevent_req_set_callback(subreq
,
1570 smbd_smb2_request_pending_writev_done
,
1574 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
1576 struct smbd_server_connection
*sconn
= req
->sconn
;
1577 struct smbd_smb2_request
*cur
;
1578 const uint8_t *inhdr
;
1580 uint64_t search_message_id
;
1581 uint64_t search_async_id
;
1584 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1586 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1587 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1588 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
1591 * we don't need the request anymore
1592 * cancel requests never have a response
1594 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1597 for (cur
= sconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
1598 const uint8_t *outhdr
;
1599 uint64_t message_id
;
1602 outhdr
= SMBD_SMB2_OUT_HDR_PTR(cur
);
1604 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1605 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
1607 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1608 if (search_async_id
== async_id
) {
1609 found_id
= async_id
;
1613 if (search_message_id
== message_id
) {
1614 found_id
= message_id
;
1620 if (cur
&& cur
->subreq
) {
1621 inhdr
= SMBD_SMB2_IN_HDR_PTR(cur
);
1622 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1623 "cancel opcode[%s] mid %llu\n",
1624 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1625 (unsigned long long)found_id
));
1626 tevent_req_cancel(cur
->subreq
);
1629 return NT_STATUS_OK
;
1632 /*************************************************************
1633 Ensure an incoming tid is a valid one for us to access.
1634 Change to the associated uid credentials and chdir to the
1635 valid tid directory.
1636 *************************************************************/
1638 static NTSTATUS
smbd_smb2_request_check_tcon(struct smbd_smb2_request
*req
)
1640 const uint8_t *inhdr
;
1643 struct smbXsrv_tcon
*tcon
;
1645 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1649 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1651 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1652 in_tid
= IVAL(inhdr
, SMB2_HDR_TID
);
1654 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1655 in_tid
= req
->last_tid
;
1660 status
= smb2srv_tcon_lookup(req
->session
,
1661 in_tid
, now
, &tcon
);
1662 if (!NT_STATUS_IS_OK(status
)) {
1666 if (!change_to_user(tcon
->compat
, req
->session
->compat
->vuid
)) {
1667 return NT_STATUS_ACCESS_DENIED
;
1670 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1671 if (!set_current_service(tcon
->compat
, 0, true)) {
1672 return NT_STATUS_ACCESS_DENIED
;
1676 req
->last_tid
= in_tid
;
1678 return NT_STATUS_OK
;
1681 /*************************************************************
1682 Ensure an incoming session_id is a valid one for us to access.
1683 *************************************************************/
1685 static NTSTATUS
smbd_smb2_request_check_session(struct smbd_smb2_request
*req
)
1687 const uint8_t *inhdr
;
1690 uint64_t in_session_id
;
1691 struct smbXsrv_session
*session
= NULL
;
1692 struct auth_session_info
*session_info
;
1694 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1696 req
->session
= NULL
;
1699 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1701 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1702 in_opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1703 in_session_id
= BVAL(inhdr
, SMB2_HDR_SESSION_ID
);
1705 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1706 in_session_id
= req
->last_session_id
;
1709 req
->last_session_id
= 0;
1711 /* lookup an existing session */
1712 status
= smb2srv_session_lookup(req
->sconn
->conn
,
1716 req
->session
= session
;
1717 req
->last_session_id
= in_session_id
;
1719 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
1720 switch (in_opcode
) {
1721 case SMB2_OP_SESSSETUP
:
1722 status
= NT_STATUS_OK
;
1728 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1729 switch (in_opcode
) {
1731 case SMB2_OP_CREATE
:
1732 case SMB2_OP_GETINFO
:
1733 case SMB2_OP_SETINFO
:
1734 return NT_STATUS_INVALID_HANDLE
;
1737 * Notice the check for
1738 * (session_info == NULL)
1741 status
= NT_STATUS_OK
;
1745 if (!NT_STATUS_IS_OK(status
)) {
1749 session_info
= session
->global
->auth_session_info
;
1750 if (session_info
== NULL
) {
1751 return NT_STATUS_INVALID_HANDLE
;
1754 set_current_user_info(session_info
->unix_info
->sanitized_username
,
1755 session_info
->unix_info
->unix_name
,
1756 session_info
->info
->domain_name
);
1758 return NT_STATUS_OK
;
1761 NTSTATUS
smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request
*req
,
1762 uint32_t data_length
)
1764 uint16_t needed_charge
;
1765 uint16_t credit_charge
= 1;
1766 const uint8_t *inhdr
;
1768 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1770 if (req
->sconn
->smb2
.supports_multicredit
) {
1771 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
1772 credit_charge
= MAX(credit_charge
, 1);
1775 needed_charge
= (data_length
- 1)/ 65536 + 1;
1777 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1778 (unsigned long long) BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
),
1779 credit_charge
, needed_charge
));
1781 if (needed_charge
> credit_charge
) {
1782 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1783 credit_charge
, needed_charge
));
1784 return NT_STATUS_INVALID_PARAMETER
;
1787 return NT_STATUS_OK
;
1790 NTSTATUS
smbd_smb2_request_verify_sizes(struct smbd_smb2_request
*req
,
1791 size_t expected_body_size
)
1793 struct iovec
*inhdr_v
;
1794 const uint8_t *inhdr
;
1796 const uint8_t *inbody
;
1798 size_t min_dyn_size
= expected_body_size
& 0x00000001;
1799 int max_idx
= req
->in
.vector_count
- SMBD_SMB2_NUM_IOV_PER_REQ
;
1802 * The following should be checked already.
1804 if (req
->in
.vector_count
< SMBD_SMB2_NUM_IOV_PER_REQ
) {
1805 return NT_STATUS_INTERNAL_ERROR
;
1807 if (req
->current_idx
> max_idx
) {
1808 return NT_STATUS_INTERNAL_ERROR
;
1811 inhdr_v
= SMBD_SMB2_IN_HDR_IOV(req
);
1812 if (inhdr_v
->iov_len
!= SMB2_HDR_BODY
) {
1813 return NT_STATUS_INTERNAL_ERROR
;
1815 if (SMBD_SMB2_IN_BODY_LEN(req
) < 2) {
1816 return NT_STATUS_INTERNAL_ERROR
;
1819 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1820 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1824 case SMB2_OP_GETINFO
:
1830 * Now check the expected body size,
1831 * where the last byte might be in the
1834 if (SMBD_SMB2_IN_BODY_LEN(req
) != (expected_body_size
& 0xFFFFFFFE)) {
1835 return NT_STATUS_INVALID_PARAMETER
;
1837 if (SMBD_SMB2_IN_DYN_LEN(req
) < min_dyn_size
) {
1838 return NT_STATUS_INVALID_PARAMETER
;
1841 inbody
= SMBD_SMB2_IN_BODY_PTR(req
);
1843 body_size
= SVAL(inbody
, 0x00);
1844 if (body_size
!= expected_body_size
) {
1845 return NT_STATUS_INVALID_PARAMETER
;
1848 return NT_STATUS_OK
;
1851 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
1853 struct smbXsrv_connection
*conn
= req
->sconn
->conn
;
1854 const struct smbd_smb2_dispatch_table
*call
= NULL
;
1855 const struct iovec
*intf_v
= SMBD_SMB2_IN_TF_IOV(req
);
1856 const uint8_t *inhdr
;
1861 NTSTATUS session_status
;
1862 uint32_t allowed_flags
;
1863 NTSTATUS return_value
;
1864 struct smbXsrv_session
*x
= NULL
;
1865 bool signing_required
= false;
1866 bool encryption_required
= false;
1868 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1870 /* TODO: verify more things */
1872 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1873 opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1874 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1875 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1876 smb2_opcode_name(opcode
),
1877 (unsigned long long)mid
));
1879 if (conn
->protocol
>= PROTOCOL_SMB2_02
) {
1881 * once the protocol is negotiated
1882 * SMB2_OP_NEGPROT is not allowed anymore
1884 if (opcode
== SMB2_OP_NEGPROT
) {
1885 /* drop the connection */
1886 return NT_STATUS_INVALID_PARAMETER
;
1890 * if the protocol is not negotiated yet
1891 * only SMB2_OP_NEGPROT is allowed.
1893 if (opcode
!= SMB2_OP_NEGPROT
) {
1894 /* drop the connection */
1895 return NT_STATUS_INVALID_PARAMETER
;
1900 * Check if the client provided a valid session id,
1901 * if so smbd_smb2_request_check_session() calls
1902 * set_current_user_info().
1904 * As some command don't require a valid session id
1905 * we defer the check of the session_status
1907 session_status
= smbd_smb2_request_check_session(req
);
1910 signing_required
= x
->global
->signing_required
;
1911 encryption_required
= x
->global
->encryption_required
;
1913 if (opcode
== SMB2_OP_SESSSETUP
&&
1914 x
->global
->channels
[0].signing_key
.length
) {
1915 signing_required
= true;
1919 req
->do_signing
= false;
1920 req
->do_encryption
= false;
1921 if (intf_v
->iov_len
== SMB2_TF_HDR_SIZE
) {
1922 const uint8_t *intf
= SMBD_SMB2_IN_TF_PTR(req
);
1923 uint64_t tf_session_id
= BVAL(intf
, SMB2_TF_SESSION_ID
);
1925 if (x
!= NULL
&& x
->global
->session_wire_id
!= tf_session_id
) {
1926 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1927 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1928 (unsigned long long)x
->global
->session_wire_id
,
1929 (unsigned long long)tf_session_id
));
1931 * TODO: windows allows this...
1932 * should we drop the connection?
1934 * For now we just return ACCESS_DENIED
1935 * (Windows clients never trigger this)
1936 * and wait for an update of [MS-SMB2].
1938 return smbd_smb2_request_error(req
,
1939 NT_STATUS_ACCESS_DENIED
);
1942 req
->do_encryption
= true;
1945 if (encryption_required
&& !req
->do_encryption
) {
1946 return smbd_smb2_request_error(req
,
1947 NT_STATUS_ACCESS_DENIED
);
1950 call
= smbd_smb2_call(opcode
);
1952 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1955 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
1956 SMB2_HDR_FLAG_SIGNED
|
1958 if (opcode
== SMB2_OP_CANCEL
) {
1959 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
1961 if ((flags
& ~allowed_flags
) != 0) {
1962 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1965 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
1967 * This check is mostly for giving the correct error code
1968 * for compounded requests.
1970 if (!NT_STATUS_IS_OK(session_status
)) {
1971 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1974 req
->compat_chain_fsp
= NULL
;
1977 if (req
->do_encryption
) {
1978 signing_required
= false;
1979 } else if (flags
& SMB2_HDR_FLAG_SIGNED
) {
1980 DATA_BLOB signing_key
;
1983 return smbd_smb2_request_error(
1984 req
, NT_STATUS_ACCESS_DENIED
);
1987 signing_key
= x
->global
->channels
[0].signing_key
;
1990 * If we have a signing key, we should
1993 if (signing_key
.length
> 0) {
1994 req
->do_signing
= true;
1997 status
= smb2_signing_check_pdu(signing_key
,
1999 SMBD_SMB2_IN_HDR_IOV(req
),
2000 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2001 if (!NT_STATUS_IS_OK(status
)) {
2002 return smbd_smb2_request_error(req
, status
);
2006 * Now that we know the request was correctly signed
2007 * we have to sign the response too.
2009 req
->do_signing
= true;
2011 if (!NT_STATUS_IS_OK(session_status
)) {
2012 return smbd_smb2_request_error(req
, session_status
);
2014 } else if (opcode
== SMB2_OP_CANCEL
) {
2015 /* Cancel requests are allowed to skip the signing */
2016 } else if (signing_required
) {
2018 * If signing is required we try to sign
2019 * a possible error response
2021 req
->do_signing
= true;
2022 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
2025 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
2026 req
->compound_related
= true;
2027 req
->sconn
->smb2
.compound_related_in_progress
= 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 smbXsrv_connection
*conn
= req
->sconn
->conn
;
2265 struct tevent_req
*subreq
;
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
);
2272 TALLOC_FREE(req
->async_te
);
2274 if (req
->do_encryption
&&
2275 (firsttf
->iov_len
== 0) &&
2276 (req
->first_key
.length
== 0) &&
2277 (req
->session
!= NULL
) &&
2278 (req
->session
->global
->encryption_key
.length
!= 0))
2280 DATA_BLOB encryption_key
= req
->session
->global
->encryption_key
;
2282 uint64_t session_id
= req
->session
->global
->session_wire_id
;
2283 struct smbXsrv_session
*x
= req
->session
;
2284 uint64_t nonce_high
;
2287 nonce_high
= x
->nonce_high
;
2288 nonce_low
= x
->nonce_low
;
2291 if (x
->nonce_low
== 0) {
2297 * We need to place the SMB2_TRANSFORM header before the
2302 * we need to remember the encryption key
2303 * and defer the signing/encryption until
2304 * we are sure that we do not change
2307 req
->first_key
= data_blob_dup_talloc(req
, encryption_key
);
2308 if (req
->first_key
.data
== NULL
) {
2309 return NT_STATUS_NO_MEMORY
;
2312 tf
= talloc_zero_array(req
->out
.vector
, uint8_t,
2315 return NT_STATUS_NO_MEMORY
;
2318 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
2319 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
2320 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
2321 SBVAL(tf
, SMB2_TF_SESSION_ID
, session_id
);
2323 firsttf
->iov_base
= (void *)tf
;
2324 firsttf
->iov_len
= SMB2_TF_HDR_SIZE
;
2327 if ((req
->current_idx
> SMBD_SMB2_NUM_IOV_PER_REQ
) &&
2328 (req
->last_key
.length
> 0) &&
2329 (firsttf
->iov_len
== 0))
2331 int last_idx
= req
->current_idx
- SMBD_SMB2_NUM_IOV_PER_REQ
;
2332 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;
2391 req
->sconn
->smb2
.compound_related_in_progress
= false;
2394 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
2396 /* Set credit for these operations (zero credits if this
2397 is a final reply for an async operation). */
2398 smb2_calculate_credits(req
, req
);
2401 * now check if we need to sign the current response
2403 if (firsttf
->iov_len
== SMB2_TF_HDR_SIZE
) {
2406 status
= smb2_signing_encrypt_pdu(req
->first_key
,
2409 req
->out
.vector_count
- first_idx
);
2410 if (!NT_STATUS_IS_OK(status
)) {
2413 } else if (req
->do_signing
) {
2415 struct smbXsrv_session
*x
= req
->session
;
2416 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
2418 status
= smb2_signing_sign_pdu(signing_key
,
2421 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2422 if (!NT_STATUS_IS_OK(status
)) {
2426 data_blob_clear_free(&req
->first_key
);
2428 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2429 if (req
->out
.vector_count
< (2*SMBD_SMB2_NUM_IOV_PER_REQ
) &&
2430 outdyn
->iov_base
== NULL
&& outdyn
->iov_len
!= 0) {
2431 /* Dynamic part is NULL. Chop it off,
2432 We're going to send it via sendfile. */
2433 req
->out
.vector_count
-= 1;
2436 subreq
= tstream_writev_queue_send(req
,
2438 req
->sconn
->smb2
.stream
,
2439 req
->sconn
->smb2
.send_queue
,
2441 req
->out
.vector_count
);
2442 if (subreq
== NULL
) {
2443 return NT_STATUS_NO_MEMORY
;
2445 tevent_req_set_callback(subreq
, smbd_smb2_request_writev_done
, req
);
2447 * We're done with this request -
2448 * move it off the "being processed" queue.
2450 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
2452 return NT_STATUS_OK
;
2455 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
);
2457 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
2458 struct tevent_immediate
*im
,
2461 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
2462 struct smbd_smb2_request
);
2463 struct smbd_server_connection
*sconn
= req
->sconn
;
2468 if (DEBUGLEVEL
>= 10) {
2469 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2470 req
->current_idx
, req
->in
.vector_count
));
2471 print_req_vectors(req
);
2474 status
= smbd_smb2_request_dispatch(req
);
2475 if (!NT_STATUS_IS_OK(status
)) {
2476 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2480 status
= smbd_smb2_request_next_incoming(sconn
);
2481 if (!NT_STATUS_IS_OK(status
)) {
2482 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2487 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
)
2489 struct smbd_smb2_request
*req
= tevent_req_callback_data(subreq
,
2490 struct smbd_smb2_request
);
2491 struct smbd_server_connection
*sconn
= req
->sconn
;
2496 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
2497 TALLOC_FREE(subreq
);
2500 status
= map_nt_error_from_unix(sys_errno
);
2501 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2502 nt_errstr(status
)));
2503 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2507 status
= smbd_smb2_request_next_incoming(sconn
);
2508 if (!NT_STATUS_IS_OK(status
)) {
2509 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2514 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
2516 DATA_BLOB body
, DATA_BLOB
*dyn
,
2517 const char *location
)
2520 struct iovec
*outbody_v
;
2521 struct iovec
*outdyn_v
;
2522 uint32_t next_command_ofs
;
2524 DEBUG(10,("smbd_smb2_request_done_ex: "
2525 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2526 req
->current_idx
, nt_errstr(status
), (unsigned int)body
.length
,
2528 (unsigned int)(dyn
? dyn
->length
: 0),
2531 if (body
.length
< 2) {
2532 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2535 if ((body
.length
% 2) != 0) {
2536 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2539 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
2540 outbody_v
= SMBD_SMB2_OUT_BODY_IOV(req
);
2541 outdyn_v
= SMBD_SMB2_OUT_DYN_IOV(req
);
2543 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
2544 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
2546 outbody_v
->iov_base
= (void *)body
.data
;
2547 outbody_v
->iov_len
= body
.length
;
2550 outdyn_v
->iov_base
= (void *)dyn
->data
;
2551 outdyn_v
->iov_len
= dyn
->length
;
2553 outdyn_v
->iov_base
= NULL
;
2554 outdyn_v
->iov_len
= 0;
2557 /* see if we need to recalculate the offset to the next response */
2558 if (next_command_ofs
> 0) {
2559 next_command_ofs
= SMB2_HDR_BODY
;
2560 next_command_ofs
+= SMBD_SMB2_OUT_BODY_LEN(req
);
2561 next_command_ofs
+= SMBD_SMB2_OUT_DYN_LEN(req
);
2564 if ((next_command_ofs
% 8) != 0) {
2565 size_t pad_size
= 8 - (next_command_ofs
% 8);
2566 if (SMBD_SMB2_OUT_DYN_LEN(req
) == 0) {
2568 * if the dyn buffer is empty
2569 * we can use it to add padding
2573 pad
= talloc_zero_array(req
->out
.vector
,
2576 return smbd_smb2_request_error(req
,
2577 NT_STATUS_NO_MEMORY
);
2580 outdyn_v
->iov_base
= (void *)pad
;
2581 outdyn_v
->iov_len
= pad_size
;
2584 * For now we copy the dynamic buffer
2585 * and add the padding to the new buffer
2592 old_size
= SMBD_SMB2_OUT_DYN_LEN(req
);
2593 old_dyn
= SMBD_SMB2_OUT_DYN_PTR(req
);
2595 new_size
= old_size
+ pad_size
;
2596 new_dyn
= talloc_zero_array(req
->out
.vector
,
2598 if (new_dyn
== NULL
) {
2599 return smbd_smb2_request_error(req
,
2600 NT_STATUS_NO_MEMORY
);
2603 memcpy(new_dyn
, old_dyn
, old_size
);
2604 memset(new_dyn
+ old_size
, 0, pad_size
);
2606 outdyn_v
->iov_base
= (void *)new_dyn
;
2607 outdyn_v
->iov_len
= new_size
;
2609 next_command_ofs
+= pad_size
;
2612 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
2614 return smbd_smb2_request_reply(req
);
2617 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
2620 const char *location
)
2623 uint8_t *outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
2625 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2626 req
->current_idx
, nt_errstr(status
), info
? " +info" : "",
2629 body
.data
= outhdr
+ SMB2_HDR_BODY
;
2631 SSVAL(body
.data
, 0, 9);
2634 SIVAL(body
.data
, 0x04, info
->length
);
2636 /* Allocated size of req->out.vector[i].iov_base
2637 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2638 * 1 byte without having to do an alloc.
2640 info
= talloc_zero_array(req
->out
.vector
,
2644 return NT_STATUS_NO_MEMORY
;
2646 info
->data
= ((uint8_t *)outhdr
) +
2647 OUTVEC_ALLOC_SIZE
- 1;
2649 SCVAL(info
->data
, 0, 0);
2653 * Note: Even if there is an error, continue to process the request.
2657 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
2661 struct smbd_smb2_send_oplock_break_state
{
2662 struct smbd_server_connection
*sconn
;
2663 uint8_t buf
[NBT_HDR_SIZE
+ SMB2_TF_HDR_SIZE
+ SMB2_HDR_BODY
+ 0x18];
2664 struct iovec vector
[1+SMBD_SMB2_NUM_IOV_PER_REQ
];
2667 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
);
2669 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
2670 struct smbXsrv_session
*session
,
2671 struct smbXsrv_tcon
*tcon
,
2672 struct smbXsrv_open
*op
,
2673 uint8_t oplock_level
)
2675 struct smbd_smb2_send_oplock_break_state
*state
;
2676 struct smbXsrv_connection
*conn
= sconn
->conn
;
2677 struct tevent_req
*subreq
;
2685 bool do_encryption
= session
->global
->encryption_required
;
2686 uint64_t nonce_high
= 0;
2687 uint64_t nonce_low
= 0;
2689 if (tcon
->global
->encryption_required
) {
2690 do_encryption
= true;
2693 state
= talloc(sconn
, struct smbd_smb2_send_oplock_break_state
);
2694 if (state
== NULL
) {
2695 return NT_STATUS_NO_MEMORY
;
2697 state
->sconn
= sconn
;
2699 tf
= state
->buf
+ NBT_HDR_SIZE
;
2700 tf_len
= SMB2_TF_HDR_SIZE
;
2702 body
= hdr
+ SMB2_HDR_BODY
;
2704 dyn
= body
+ body_len
;
2707 if (do_encryption
) {
2708 nonce_high
= session
->nonce_high
;
2709 nonce_low
= session
->nonce_low
;
2711 session
->nonce_low
+= 1;
2712 if (session
->nonce_low
== 0) {
2713 session
->nonce_low
+= 1;
2714 session
->nonce_high
+= 1;
2718 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
2719 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
2720 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
2721 SBVAL(tf
, SMB2_TF_SESSION_ID
, session
->global
->session_wire_id
);
2723 SIVAL(hdr
, 0, SMB2_MAGIC
);
2724 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
2725 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
2726 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
2727 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
2728 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
2729 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
2730 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
2731 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
2732 SIVAL(hdr
, SMB2_HDR_PID
, 0);
2733 SIVAL(hdr
, SMB2_HDR_TID
, 0);
2734 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
2735 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
2737 SSVAL(body
, 0x00, body_len
);
2739 SCVAL(body
, 0x02, oplock_level
);
2740 SCVAL(body
, 0x03, 0); /* reserved */
2741 SIVAL(body
, 0x04, 0); /* reserved */
2742 SBVAL(body
, 0x08, op
->global
->open_persistent_id
);
2743 SBVAL(body
, 0x10, op
->global
->open_volatile_id
);
2745 state
->vector
[0].iov_base
= (void *)state
->buf
;
2746 state
->vector
[0].iov_len
= NBT_HDR_SIZE
;
2748 if (do_encryption
) {
2749 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= tf
;
2750 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= tf_len
;
2752 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
2753 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
2756 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
2757 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
2759 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
2760 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_len
= body_len
;
2762 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
2763 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_len
= dyn_len
;
2765 smb2_setup_nbt_length(state
->vector
, 1 + SMBD_SMB2_NUM_IOV_PER_REQ
);
2767 if (do_encryption
) {
2769 DATA_BLOB encryption_key
= session
->global
->encryption_key
;
2771 status
= smb2_signing_encrypt_pdu(encryption_key
,
2773 &state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
],
2774 SMBD_SMB2_NUM_IOV_PER_REQ
);
2775 if (!NT_STATUS_IS_OK(status
)) {
2780 subreq
= tstream_writev_queue_send(state
,
2783 sconn
->smb2
.send_queue
,
2785 ARRAY_SIZE(state
->vector
));
2786 if (subreq
== NULL
) {
2787 return NT_STATUS_NO_MEMORY
;
2789 tevent_req_set_callback(subreq
,
2790 smbd_smb2_oplock_break_writev_done
,
2793 return NT_STATUS_OK
;
2796 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
)
2798 struct smbd_smb2_send_oplock_break_state
*state
=
2799 tevent_req_callback_data(subreq
,
2800 struct smbd_smb2_send_oplock_break_state
);
2801 struct smbd_server_connection
*sconn
= state
->sconn
;
2805 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
2806 TALLOC_FREE(subreq
);
2808 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
2809 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2816 struct smbd_smb2_request_read_state
{
2817 struct tevent_context
*ev
;
2818 struct smbd_server_connection
*sconn
;
2819 struct smbd_smb2_request
*smb2_req
;
2821 uint8_t nbt
[NBT_HDR_SIZE
];
2828 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2830 TALLOC_CTX
*mem_ctx
,
2831 struct iovec
**_vector
,
2833 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
);
2835 static struct tevent_req
*smbd_smb2_request_read_send(TALLOC_CTX
*mem_ctx
,
2836 struct tevent_context
*ev
,
2837 struct smbd_server_connection
*sconn
)
2839 struct tevent_req
*req
;
2840 struct smbd_smb2_request_read_state
*state
;
2841 struct tevent_req
*subreq
;
2843 req
= tevent_req_create(mem_ctx
, &state
,
2844 struct smbd_smb2_request_read_state
);
2849 state
->sconn
= sconn
;
2851 state
->smb2_req
= smbd_smb2_request_allocate(state
);
2852 if (tevent_req_nomem(state
->smb2_req
, req
)) {
2853 return tevent_req_post(req
, ev
);
2855 state
->smb2_req
->sconn
= sconn
;
2857 subreq
= tstream_readv_pdu_queue_send(state
->smb2_req
,
2859 state
->sconn
->smb2
.stream
,
2860 state
->sconn
->smb2
.recv_queue
,
2861 smbd_smb2_request_next_vector
,
2863 if (tevent_req_nomem(subreq
, req
)) {
2864 return tevent_req_post(req
, ev
);
2866 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
2871 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2873 TALLOC_CTX
*mem_ctx
,
2874 struct iovec
**_vector
,
2877 struct smbd_smb2_request_read_state
*state
=
2878 talloc_get_type_abort(private_data
,
2879 struct smbd_smb2_request_read_state
);
2880 struct iovec
*vector
;
2882 if (state
->pktlen
> 0) {
2883 /* if there're no remaining bytes, we're done */
2889 if (!state
->hdr
.done
) {
2891 * first we need to get the NBT header
2893 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2894 if (vector
== NULL
) {
2898 vector
[0].iov_base
= (void *)state
->hdr
.nbt
;
2899 vector
[0].iov_len
= NBT_HDR_SIZE
;
2904 state
->hdr
.done
= true;
2909 * Now we analyze the NBT header
2911 state
->pktlen
= smb2_len(state
->hdr
.nbt
);
2913 if (state
->pktlen
== 0) {
2914 /* if there're no remaining bytes, we're done */
2920 state
->pktbuf
= talloc_array(state
->smb2_req
, uint8_t, state
->pktlen
);
2921 if (state
->pktbuf
== NULL
) {
2925 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2926 if (vector
== NULL
) {
2930 vector
[0].iov_base
= (void *)state
->pktbuf
;
2931 vector
[0].iov_len
= state
->pktlen
;
2938 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
)
2940 struct tevent_req
*req
=
2941 tevent_req_callback_data(subreq
,
2943 struct smbd_smb2_request_read_state
*state
=
2944 tevent_req_data(req
,
2945 struct smbd_smb2_request_read_state
);
2951 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
2952 TALLOC_FREE(subreq
);
2954 status
= map_nt_error_from_unix(sys_errno
);
2955 tevent_req_nterror(req
, status
);
2959 if (state
->hdr
.nbt
[0] != 0x00) {
2960 DEBUG(1,("smbd_smb2_request_read_done: ignore NBT[0x%02X] msg\n",
2961 state
->hdr
.nbt
[0]));
2963 ZERO_STRUCT(state
->hdr
);
2964 TALLOC_FREE(state
->pktbuf
);
2967 subreq
= tstream_readv_pdu_queue_send(state
->smb2_req
,
2969 state
->sconn
->smb2
.stream
,
2970 state
->sconn
->smb2
.recv_queue
,
2971 smbd_smb2_request_next_vector
,
2973 if (tevent_req_nomem(subreq
, req
)) {
2976 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
2980 state
->smb2_req
->request_time
= timeval_current();
2981 now
= timeval_to_nttime(&state
->smb2_req
->request_time
);
2983 status
= smbd_smb2_inbuf_parse_compound(state
->smb2_req
->sconn
->conn
,
2988 &state
->smb2_req
->in
.vector
,
2989 &state
->smb2_req
->in
.vector_count
);
2990 if (tevent_req_nterror(req
, status
)) {
2994 state
->smb2_req
->current_idx
= 1;
2996 tevent_req_done(req
);
2999 static NTSTATUS
smbd_smb2_request_read_recv(struct tevent_req
*req
,
3000 TALLOC_CTX
*mem_ctx
,
3001 struct smbd_smb2_request
**_smb2_req
)
3003 struct smbd_smb2_request_read_state
*state
=
3004 tevent_req_data(req
,
3005 struct smbd_smb2_request_read_state
);
3008 if (tevent_req_is_nterror(req
, &status
)) {
3009 tevent_req_received(req
);
3013 *_smb2_req
= talloc_move(mem_ctx
, &state
->smb2_req
);
3014 tevent_req_received(req
);
3015 return NT_STATUS_OK
;
3018 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
);
3020 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
)
3022 size_t max_send_queue_len
;
3023 size_t cur_send_queue_len
;
3024 struct tevent_req
*subreq
;
3026 if (sconn
->smb2
.compound_related_in_progress
) {
3028 * Can't read another until the related
3031 return NT_STATUS_OK
;
3034 if (tevent_queue_length(sconn
->smb2
.recv_queue
) > 0) {
3036 * if there is already a smbd_smb2_request_read
3037 * pending, we are done.
3039 return NT_STATUS_OK
;
3042 max_send_queue_len
= MAX(1, sconn
->smb2
.max_credits
/16);
3043 cur_send_queue_len
= tevent_queue_length(sconn
->smb2
.send_queue
);
3045 if (cur_send_queue_len
> max_send_queue_len
) {
3047 * if we have a lot of requests to send,
3048 * we wait until they are on the wire until we
3049 * ask for the next request.
3051 return NT_STATUS_OK
;
3054 /* ask for the next request */
3055 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->ev_ctx
, sconn
);
3056 if (subreq
== NULL
) {
3057 return NT_STATUS_NO_MEMORY
;
3059 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);
3061 return NT_STATUS_OK
;
3064 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
3065 uint8_t *inbuf
, size_t size
)
3068 struct smbd_smb2_request
*req
= NULL
;
3070 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3071 (unsigned int)size
));
3073 status
= smbd_initialize_smb2(sconn
);
3074 if (!NT_STATUS_IS_OK(status
)) {
3075 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3079 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
3080 if (!NT_STATUS_IS_OK(status
)) {
3081 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3085 status
= smbd_smb2_request_validate(req
);
3086 if (!NT_STATUS_IS_OK(status
)) {
3087 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3091 status
= smbd_smb2_request_setup_out(req
);
3092 if (!NT_STATUS_IS_OK(status
)) {
3093 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3097 status
= smbd_smb2_request_dispatch(req
);
3098 if (!NT_STATUS_IS_OK(status
)) {
3099 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3103 status
= smbd_smb2_request_next_incoming(sconn
);
3104 if (!NT_STATUS_IS_OK(status
)) {
3105 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3109 sconn
->num_requests
++;
3112 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
)
3114 struct smbd_server_connection
*sconn
= tevent_req_callback_data(subreq
,
3115 struct smbd_server_connection
);
3117 struct smbd_smb2_request
*req
= NULL
;
3119 status
= smbd_smb2_request_read_recv(subreq
, sconn
, &req
);
3120 TALLOC_FREE(subreq
);
3121 if (!NT_STATUS_IS_OK(status
)) {
3122 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
3123 nt_errstr(status
)));
3124 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3128 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
3129 req
->current_idx
, req
->in
.vector_count
));
3131 status
= smbd_smb2_request_validate(req
);
3132 if (!NT_STATUS_IS_OK(status
)) {
3133 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3137 status
= smbd_smb2_request_setup_out(req
);
3138 if (!NT_STATUS_IS_OK(status
)) {
3139 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3143 status
= smbd_smb2_request_dispatch(req
);
3144 if (!NT_STATUS_IS_OK(status
)) {
3145 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3149 status
= smbd_smb2_request_next_incoming(sconn
);
3150 if (!NT_STATUS_IS_OK(status
)) {
3151 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3155 sconn
->num_requests
++;
3157 /* The timeout_processing function isn't run nearly
3158 often enough to implement 'max log size' without
3159 overrunning the size of the file by many megabytes.
3160 This is especially true if we are running at debug
3161 level 10. Checking every 50 SMB2s is a nice
3162 tradeoff of performance vs log file size overrun. */
3164 if ((sconn
->num_requests
% 50) == 0 &&
3165 need_to_check_log_size()) {
3166 change_to_root_user();