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
= SVAL(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
);
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(SVAL(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(SVAL(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
= SVAL(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
= SVAL(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
);
2624 size_t unread_bytes
= smbd_smb2_unread_bytes(req
);
2626 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2627 req
->current_idx
, nt_errstr(status
), info
? " +info" : "",
2631 /* Recvfile error. Drain incoming socket. */
2632 size_t ret
= drain_socket(req
->sconn
->sock
, unread_bytes
);
2633 if (ret
!= unread_bytes
) {
2634 smbd_server_connection_terminate(req
->sconn
,
2635 "Failed to drain SMB2 socket\n");
2639 body
.data
= outhdr
+ SMB2_HDR_BODY
;
2641 SSVAL(body
.data
, 0, 9);
2644 SIVAL(body
.data
, 0x04, info
->length
);
2646 /* Allocated size of req->out.vector[i].iov_base
2647 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2648 * 1 byte without having to do an alloc.
2650 info
= talloc_zero_array(req
->out
.vector
,
2654 return NT_STATUS_NO_MEMORY
;
2656 info
->data
= ((uint8_t *)outhdr
) +
2657 OUTVEC_ALLOC_SIZE
- 1;
2659 SCVAL(info
->data
, 0, 0);
2663 * Note: Even if there is an error, continue to process the request.
2667 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
2671 struct smbd_smb2_send_oplock_break_state
{
2672 struct smbd_server_connection
*sconn
;
2673 uint8_t buf
[NBT_HDR_SIZE
+ SMB2_TF_HDR_SIZE
+ SMB2_HDR_BODY
+ 0x18];
2674 struct iovec vector
[1+SMBD_SMB2_NUM_IOV_PER_REQ
];
2677 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
);
2679 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
2680 struct smbXsrv_session
*session
,
2681 struct smbXsrv_tcon
*tcon
,
2682 struct smbXsrv_open
*op
,
2683 uint8_t oplock_level
)
2685 struct smbd_smb2_send_oplock_break_state
*state
;
2686 struct smbXsrv_connection
*conn
= sconn
->conn
;
2687 struct tevent_req
*subreq
;
2695 bool do_encryption
= session
->global
->encryption_required
;
2696 uint64_t nonce_high
= 0;
2697 uint64_t nonce_low
= 0;
2699 if (tcon
->global
->encryption_required
) {
2700 do_encryption
= true;
2703 state
= talloc(sconn
, struct smbd_smb2_send_oplock_break_state
);
2704 if (state
== NULL
) {
2705 return NT_STATUS_NO_MEMORY
;
2707 state
->sconn
= sconn
;
2709 tf
= state
->buf
+ NBT_HDR_SIZE
;
2710 tf_len
= SMB2_TF_HDR_SIZE
;
2712 body
= hdr
+ SMB2_HDR_BODY
;
2714 dyn
= body
+ body_len
;
2717 if (do_encryption
) {
2718 nonce_high
= session
->nonce_high
;
2719 nonce_low
= session
->nonce_low
;
2721 session
->nonce_low
+= 1;
2722 if (session
->nonce_low
== 0) {
2723 session
->nonce_low
+= 1;
2724 session
->nonce_high
+= 1;
2728 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
2729 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
2730 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
2731 SBVAL(tf
, SMB2_TF_SESSION_ID
, session
->global
->session_wire_id
);
2733 SIVAL(hdr
, 0, SMB2_MAGIC
);
2734 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
2735 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
2736 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
2737 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
2738 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
2739 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
2740 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
2741 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
2742 SIVAL(hdr
, SMB2_HDR_PID
, 0);
2743 SIVAL(hdr
, SMB2_HDR_TID
, 0);
2744 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
2745 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
2747 SSVAL(body
, 0x00, body_len
);
2749 SCVAL(body
, 0x02, oplock_level
);
2750 SCVAL(body
, 0x03, 0); /* reserved */
2751 SIVAL(body
, 0x04, 0); /* reserved */
2752 SBVAL(body
, 0x08, op
->global
->open_persistent_id
);
2753 SBVAL(body
, 0x10, op
->global
->open_volatile_id
);
2755 state
->vector
[0].iov_base
= (void *)state
->buf
;
2756 state
->vector
[0].iov_len
= NBT_HDR_SIZE
;
2758 if (do_encryption
) {
2759 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= tf
;
2760 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= tf_len
;
2762 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
2763 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
2766 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
2767 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
2769 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
2770 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_len
= body_len
;
2772 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
2773 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_len
= dyn_len
;
2775 smb2_setup_nbt_length(state
->vector
, 1 + SMBD_SMB2_NUM_IOV_PER_REQ
);
2777 if (do_encryption
) {
2779 DATA_BLOB encryption_key
= session
->global
->encryption_key
;
2781 status
= smb2_signing_encrypt_pdu(encryption_key
,
2783 &state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
],
2784 SMBD_SMB2_NUM_IOV_PER_REQ
);
2785 if (!NT_STATUS_IS_OK(status
)) {
2790 subreq
= tstream_writev_queue_send(state
,
2793 sconn
->smb2
.send_queue
,
2795 ARRAY_SIZE(state
->vector
));
2796 if (subreq
== NULL
) {
2797 return NT_STATUS_NO_MEMORY
;
2799 tevent_req_set_callback(subreq
,
2800 smbd_smb2_oplock_break_writev_done
,
2803 return NT_STATUS_OK
;
2806 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
)
2808 struct smbd_smb2_send_oplock_break_state
*state
=
2809 tevent_req_callback_data(subreq
,
2810 struct smbd_smb2_send_oplock_break_state
);
2811 struct smbd_server_connection
*sconn
= state
->sconn
;
2815 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
2816 TALLOC_FREE(subreq
);
2818 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
2819 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2826 struct smbd_smb2_request_read_state
{
2827 struct tevent_context
*ev
;
2828 struct smbd_server_connection
*sconn
;
2829 struct smbd_smb2_request
*smb2_req
;
2831 uint8_t nbt
[NBT_HDR_SIZE
];
2838 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2840 TALLOC_CTX
*mem_ctx
,
2841 struct iovec
**_vector
,
2843 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
);
2845 static struct tevent_req
*smbd_smb2_request_read_send(TALLOC_CTX
*mem_ctx
,
2846 struct tevent_context
*ev
,
2847 struct smbd_server_connection
*sconn
)
2849 struct tevent_req
*req
;
2850 struct smbd_smb2_request_read_state
*state
;
2851 struct tevent_req
*subreq
;
2853 req
= tevent_req_create(mem_ctx
, &state
,
2854 struct smbd_smb2_request_read_state
);
2859 state
->sconn
= sconn
;
2861 state
->smb2_req
= smbd_smb2_request_allocate(state
);
2862 if (tevent_req_nomem(state
->smb2_req
, req
)) {
2863 return tevent_req_post(req
, ev
);
2865 state
->smb2_req
->sconn
= sconn
;
2867 subreq
= tstream_readv_pdu_queue_send(state
->smb2_req
,
2869 state
->sconn
->smb2
.stream
,
2870 state
->sconn
->smb2
.recv_queue
,
2871 smbd_smb2_request_next_vector
,
2873 if (tevent_req_nomem(subreq
, req
)) {
2874 return tevent_req_post(req
, ev
);
2876 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
2881 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2883 TALLOC_CTX
*mem_ctx
,
2884 struct iovec
**_vector
,
2887 struct smbd_smb2_request_read_state
*state
=
2888 talloc_get_type_abort(private_data
,
2889 struct smbd_smb2_request_read_state
);
2890 struct iovec
*vector
;
2892 if (state
->pktlen
> 0) {
2893 /* if there're no remaining bytes, we're done */
2899 if (!state
->hdr
.done
) {
2901 * first we need to get the NBT header
2903 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2904 if (vector
== NULL
) {
2908 vector
[0].iov_base
= (void *)state
->hdr
.nbt
;
2909 vector
[0].iov_len
= NBT_HDR_SIZE
;
2914 state
->hdr
.done
= true;
2919 * Now we analyze the NBT header
2921 state
->pktlen
= smb2_len(state
->hdr
.nbt
);
2923 if (state
->pktlen
== 0) {
2924 /* if there're no remaining bytes, we're done */
2930 state
->pktbuf
= talloc_array(state
->smb2_req
, uint8_t, state
->pktlen
);
2931 if (state
->pktbuf
== NULL
) {
2935 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2936 if (vector
== NULL
) {
2940 vector
[0].iov_base
= (void *)state
->pktbuf
;
2941 vector
[0].iov_len
= state
->pktlen
;
2948 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
)
2950 struct tevent_req
*req
=
2951 tevent_req_callback_data(subreq
,
2953 struct smbd_smb2_request_read_state
*state
=
2954 tevent_req_data(req
,
2955 struct smbd_smb2_request_read_state
);
2961 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
2962 TALLOC_FREE(subreq
);
2964 status
= map_nt_error_from_unix(sys_errno
);
2965 tevent_req_nterror(req
, status
);
2969 if (state
->hdr
.nbt
[0] != 0x00) {
2970 DEBUG(1,("smbd_smb2_request_read_done: ignore NBT[0x%02X] msg\n",
2971 state
->hdr
.nbt
[0]));
2973 ZERO_STRUCT(state
->hdr
);
2974 TALLOC_FREE(state
->pktbuf
);
2977 subreq
= tstream_readv_pdu_queue_send(state
->smb2_req
,
2979 state
->sconn
->smb2
.stream
,
2980 state
->sconn
->smb2
.recv_queue
,
2981 smbd_smb2_request_next_vector
,
2983 if (tevent_req_nomem(subreq
, req
)) {
2986 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
2990 state
->smb2_req
->request_time
= timeval_current();
2991 now
= timeval_to_nttime(&state
->smb2_req
->request_time
);
2993 status
= smbd_smb2_inbuf_parse_compound(state
->smb2_req
->sconn
->conn
,
2998 &state
->smb2_req
->in
.vector
,
2999 &state
->smb2_req
->in
.vector_count
);
3000 if (tevent_req_nterror(req
, status
)) {
3004 state
->smb2_req
->current_idx
= 1;
3006 tevent_req_done(req
);
3009 static NTSTATUS
smbd_smb2_request_read_recv(struct tevent_req
*req
,
3010 TALLOC_CTX
*mem_ctx
,
3011 struct smbd_smb2_request
**_smb2_req
)
3013 struct smbd_smb2_request_read_state
*state
=
3014 tevent_req_data(req
,
3015 struct smbd_smb2_request_read_state
);
3018 if (tevent_req_is_nterror(req
, &status
)) {
3019 tevent_req_received(req
);
3023 *_smb2_req
= talloc_move(mem_ctx
, &state
->smb2_req
);
3024 tevent_req_received(req
);
3025 return NT_STATUS_OK
;
3028 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
);
3030 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
)
3032 size_t max_send_queue_len
;
3033 size_t cur_send_queue_len
;
3034 struct tevent_req
*subreq
;
3036 if (sconn
->smb2
.compound_related_in_progress
) {
3038 * Can't read another until the related
3041 return NT_STATUS_OK
;
3044 if (tevent_queue_length(sconn
->smb2
.recv_queue
) > 0) {
3046 * if there is already a smbd_smb2_request_read
3047 * pending, we are done.
3049 return NT_STATUS_OK
;
3052 max_send_queue_len
= MAX(1, sconn
->smb2
.max_credits
/16);
3053 cur_send_queue_len
= tevent_queue_length(sconn
->smb2
.send_queue
);
3055 if (cur_send_queue_len
> max_send_queue_len
) {
3057 * if we have a lot of requests to send,
3058 * we wait until they are on the wire until we
3059 * ask for the next request.
3061 return NT_STATUS_OK
;
3064 /* ask for the next request */
3065 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->ev_ctx
, sconn
);
3066 if (subreq
== NULL
) {
3067 return NT_STATUS_NO_MEMORY
;
3069 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);
3071 return NT_STATUS_OK
;
3074 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
3075 uint8_t *inbuf
, size_t size
)
3078 struct smbd_smb2_request
*req
= NULL
;
3080 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3081 (unsigned int)size
));
3083 status
= smbd_initialize_smb2(sconn
);
3084 if (!NT_STATUS_IS_OK(status
)) {
3085 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3089 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
3090 if (!NT_STATUS_IS_OK(status
)) {
3091 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3095 status
= smbd_smb2_request_validate(req
);
3096 if (!NT_STATUS_IS_OK(status
)) {
3097 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3101 status
= smbd_smb2_request_setup_out(req
);
3102 if (!NT_STATUS_IS_OK(status
)) {
3103 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3107 status
= smbd_smb2_request_dispatch(req
);
3108 if (!NT_STATUS_IS_OK(status
)) {
3109 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3113 status
= smbd_smb2_request_next_incoming(sconn
);
3114 if (!NT_STATUS_IS_OK(status
)) {
3115 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3119 sconn
->num_requests
++;
3122 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
)
3124 struct smbd_server_connection
*sconn
= tevent_req_callback_data(subreq
,
3125 struct smbd_server_connection
);
3127 struct smbd_smb2_request
*req
= NULL
;
3129 status
= smbd_smb2_request_read_recv(subreq
, sconn
, &req
);
3130 TALLOC_FREE(subreq
);
3131 if (!NT_STATUS_IS_OK(status
)) {
3132 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
3133 nt_errstr(status
)));
3134 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3138 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
3139 req
->current_idx
, req
->in
.vector_count
));
3141 status
= smbd_smb2_request_validate(req
);
3142 if (!NT_STATUS_IS_OK(status
)) {
3143 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3147 status
= smbd_smb2_request_setup_out(req
);
3148 if (!NT_STATUS_IS_OK(status
)) {
3149 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3153 status
= smbd_smb2_request_dispatch(req
);
3154 if (!NT_STATUS_IS_OK(status
)) {
3155 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3159 status
= smbd_smb2_request_next_incoming(sconn
);
3160 if (!NT_STATUS_IS_OK(status
)) {
3161 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3165 sconn
->num_requests
++;
3167 /* The timeout_processing function isn't run nearly
3168 often enough to implement 'max log size' without
3169 overrunning the size of the file by many megabytes.
3170 This is especially true if we are running at debug
3171 level 10. Checking every 50 SMB2s is a nice
3172 tradeoff of performance vs log file size overrun. */
3174 if ((sconn
->num_requests
% 50) == 0 &&
3175 need_to_check_log_size()) {
3176 change_to_root_user();