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
;
718 if (hdr
->iov_len
!= SMB2_HDR_BODY
) {
719 return NT_STATUS_INVALID_PARAMETER
;
722 if (body
->iov_len
< 2) {
723 return NT_STATUS_INVALID_PARAMETER
;
726 inhdr
= (const uint8_t *)hdr
->iov_base
;
728 /* Check the SMB2 header */
729 if (IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
) != SMB2_MAGIC
) {
730 return NT_STATUS_INVALID_PARAMETER
;
733 if (!smb2_validate_message_id(req
->sconn
, inhdr
)) {
734 return NT_STATUS_INVALID_PARAMETER
;
737 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
738 if (idx
< SMBD_SMB2_NUM_IOV_PER_REQ
) {
740 * the 1st request should never have the
741 * SMB2_HDR_FLAG_CHAINED flag set
743 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
744 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
747 } else if (idx
< 2*SMBD_SMB2_NUM_IOV_PER_REQ
) {
749 * the 2nd request triggers related vs. unrelated
750 * compounded requests
752 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
753 req
->compound_related
= true;
758 * It seems the this tests are wrong
759 * see the SMB2-COMPOUND test
763 * all other requests should match the 2nd one
765 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
766 if (!req
->compound_related
) {
768 NT_STATUS_INVALID_PARAMETER
;
772 if (req
->compound_related
) {
774 NT_STATUS_INVALID_PARAMETER
;
785 static void smb2_set_operation_credit(struct smbd_server_connection
*sconn
,
786 const struct iovec
*in_vector
,
787 struct iovec
*out_vector
)
789 const uint8_t *inhdr
= (const uint8_t *)in_vector
->iov_base
;
790 uint8_t *outhdr
= (uint8_t *)out_vector
->iov_base
;
791 uint16_t credit_charge
= 1;
792 uint16_t credits_requested
;
796 uint16_t credits_granted
= 0;
797 uint64_t credits_possible
;
798 uint16_t current_max_credits
;
801 * first we grant only 1/16th of the max range.
803 * Windows also starts with the 1/16th and then grants
804 * more later. I was only able to trigger higher
805 * values, when using a verify high credit charge.
807 * TODO: scale up depending one load, free memory
809 * Maybe also on the relationship between number
810 * of requests and the used sequence number.
811 * Which means we would grant more credits
812 * for client which use multi credit requests.
814 current_max_credits
= sconn
->smb2
.max_credits
/ 16;
815 current_max_credits
= MAX(current_max_credits
, 1);
817 if (sconn
->smb2
.supports_multicredit
) {
818 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
819 credit_charge
= MAX(credit_charge
, 1);
822 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
823 credits_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
824 out_flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
825 out_status
= NT_STATUS(IVAL(outhdr
, SMB2_HDR_STATUS
));
827 SMB_ASSERT(sconn
->smb2
.max_credits
>= sconn
->smb2
.credits_granted
);
828 SMB_ASSERT(sconn
->smb2
.max_credits
>= credit_charge
);
830 if (out_flags
& SMB2_HDR_FLAG_ASYNC
) {
832 * In case we already send an async interim
833 * response, we should not grant
834 * credits on the final response.
837 } else if (credits_requested
> 0) {
838 uint16_t additional_max
= 0;
839 uint16_t additional_credits
= credits_requested
- 1;
842 case SMB2_OP_NEGPROT
:
844 case SMB2_OP_SESSSETUP
:
846 * Windows 2012 RC1 starts to grant
848 * with a successful session setup
850 if (NT_STATUS_IS_OK(out_status
)) {
856 * We match windows and only grant additional credits
863 additional_credits
= MIN(additional_credits
, additional_max
);
865 credits_granted
= credit_charge
+ additional_credits
;
866 } else if (sconn
->smb2
.credits_granted
== 0) {
868 * Make sure the client has always at least one credit
874 * sequence numbers should not wrap
876 * 1. calculate the possible credits until
877 * the sequence numbers start to wrap on 64-bit.
879 * 2. UINT64_MAX is used for Break Notifications.
881 * 2. truncate the possible credits to the maximum
882 * credits we want to grant to the client in total.
884 * 3. remove the range we'll already granted to the client
885 * this makes sure the client consumes the lowest sequence
886 * number, before we can grant additional credits.
888 credits_possible
= UINT64_MAX
- sconn
->smb2
.seqnum_low
;
889 if (credits_possible
> 0) {
890 /* remove UINT64_MAX */
891 credits_possible
-= 1;
893 credits_possible
= MIN(credits_possible
, current_max_credits
);
894 credits_possible
-= sconn
->smb2
.seqnum_range
;
896 credits_granted
= MIN(credits_granted
, credits_possible
);
898 SSVAL(outhdr
, SMB2_HDR_CREDIT
, credits_granted
);
899 sconn
->smb2
.credits_granted
+= credits_granted
;
900 sconn
->smb2
.seqnum_range
+= credits_granted
;
902 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
903 "granted %u, current possible/max %u/%u, "
904 "total granted/max/low/range %u/%u/%llu/%u\n",
905 (unsigned int)credits_requested
,
906 (unsigned int)credit_charge
,
907 (unsigned int)credits_granted
,
908 (unsigned int)credits_possible
,
909 (unsigned int)current_max_credits
,
910 (unsigned int)sconn
->smb2
.credits_granted
,
911 (unsigned int)sconn
->smb2
.max_credits
,
912 (unsigned long long)sconn
->smb2
.seqnum_low
,
913 (unsigned int)sconn
->smb2
.seqnum_range
));
916 static void smb2_calculate_credits(const struct smbd_smb2_request
*inreq
,
917 struct smbd_smb2_request
*outreq
)
920 uint16_t total_credits
= 0;
922 count
= outreq
->out
.vector_count
;
924 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
925 struct iovec
*inhdr_v
= SMBD_SMB2_IDX_HDR_IOV(inreq
,in
,idx
);
926 struct iovec
*outhdr_v
= SMBD_SMB2_IDX_HDR_IOV(outreq
,out
,idx
);
927 uint8_t *outhdr
= (uint8_t *)outhdr_v
->iov_base
;
929 smb2_set_operation_credit(outreq
->sconn
, inhdr_v
, outhdr_v
);
931 /* To match Windows, count up what we
933 total_credits
+= SVAL(outhdr
, SMB2_HDR_CREDIT
);
934 /* Set to zero in all but the last reply. */
935 if (idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
< count
) {
936 SSVAL(outhdr
, SMB2_HDR_CREDIT
, 0);
938 SSVAL(outhdr
, SMB2_HDR_CREDIT
, total_credits
);
943 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
)
945 struct iovec
*vector
;
949 count
= req
->in
.vector_count
;
950 vector
= talloc_zero_array(req
, struct iovec
, count
);
951 if (vector
== NULL
) {
952 return NT_STATUS_NO_MEMORY
;
955 vector
[0].iov_base
= req
->out
.nbt_hdr
;
956 vector
[0].iov_len
= 4;
957 SIVAL(req
->out
.nbt_hdr
, 0, 0);
959 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
960 struct iovec
*inhdr_v
= SMBD_SMB2_IDX_HDR_IOV(req
,in
,idx
);
961 const uint8_t *inhdr
= (const uint8_t *)inhdr_v
->iov_base
;
962 uint8_t *outhdr
= NULL
;
963 uint8_t *outbody
= NULL
;
964 uint32_t next_command_ofs
= 0;
965 struct iovec
*current
= &vector
[idx
];
967 if ((idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
) < count
) {
968 /* we have a next command -
969 * setup for the error case. */
970 next_command_ofs
= SMB2_HDR_BODY
+ 9;
973 outhdr
= talloc_zero_array(vector
, uint8_t,
975 if (outhdr
== NULL
) {
976 return NT_STATUS_NO_MEMORY
;
979 outbody
= outhdr
+ SMB2_HDR_BODY
;
982 * SMBD_SMB2_TF_IOV_OFS might be used later
984 current
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
985 current
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
987 current
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= (void *)outhdr
;
988 current
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
990 current
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= (void *)outbody
;
991 current
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= 8;
993 current
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= NULL
;
994 current
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= 0;
996 /* setup the SMB2 header */
997 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
998 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
999 SSVAL(outhdr
, SMB2_HDR_CREDIT_CHARGE
,
1000 SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
));
1001 SIVAL(outhdr
, SMB2_HDR_STATUS
,
1002 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
1003 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
1004 SVAL(inhdr
, SMB2_HDR_OPCODE
));
1005 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
1006 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
1007 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
1008 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
1009 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
1010 SIVAL(outhdr
, SMB2_HDR_PID
,
1011 IVAL(inhdr
, SMB2_HDR_PID
));
1012 SIVAL(outhdr
, SMB2_HDR_TID
,
1013 IVAL(inhdr
, SMB2_HDR_TID
));
1014 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
1015 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
1016 memcpy(outhdr
+ SMB2_HDR_SIGNATURE
,
1017 inhdr
+ SMB2_HDR_SIGNATURE
, 16);
1019 /* setup error body header */
1020 SSVAL(outbody
, 0x00, 0x08 + 1);
1021 SSVAL(outbody
, 0x02, 0);
1022 SIVAL(outbody
, 0x04, 0);
1025 req
->out
.vector
= vector
;
1026 req
->out
.vector_count
= count
;
1028 /* setup the length of the NBT packet */
1029 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
1031 DLIST_ADD_END(req
->sconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
1033 return NT_STATUS_OK
;
1036 void smbd_server_connection_terminate_ex(struct smbd_server_connection
*sconn
,
1038 const char *location
)
1040 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1042 exit_server_cleanly(reason
);
1045 static bool dup_smb2_vec4(TALLOC_CTX
*ctx
,
1046 struct iovec
*outvec
,
1047 const struct iovec
*srcvec
)
1049 const uint8_t *srctf
;
1051 const uint8_t *srchdr
;
1053 const uint8_t *srcbody
;
1055 const uint8_t *expected_srcbody
;
1056 const uint8_t *srcdyn
;
1058 const uint8_t *expected_srcdyn
;
1064 srctf
= (const uint8_t *)srcvec
[SMBD_SMB2_TF_IOV_OFS
].iov_base
;
1065 srctf_len
= srcvec
[SMBD_SMB2_TF_IOV_OFS
].iov_len
;
1066 srchdr
= (const uint8_t *)srcvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
;
1067 srchdr_len
= srcvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
;
1068 srcbody
= (const uint8_t *)srcvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
;
1069 srcbody_len
= srcvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
;
1070 expected_srcbody
= srchdr
+ SMB2_HDR_BODY
;
1071 srcdyn
= (const uint8_t *)srcvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
;
1072 srcdyn_len
= srcvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
;
1073 expected_srcdyn
= srcbody
+ 8;
1075 if ((srctf_len
!= SMB2_TF_HDR_SIZE
) && (srctf_len
!= 0)) {
1079 if (srchdr_len
!= SMB2_HDR_BODY
) {
1083 if (srctf_len
== SMB2_TF_HDR_SIZE
) {
1084 dsttf
= talloc_memdup(ctx
, srctf
, SMB2_TF_HDR_SIZE
);
1085 if (dsttf
== NULL
) {
1091 outvec
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= (void *)dsttf
;
1092 outvec
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= srctf_len
;
1094 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1095 * be allocated with size OUTVEC_ALLOC_SIZE. */
1097 dsthdr
= talloc_memdup(ctx
, srchdr
, OUTVEC_ALLOC_SIZE
);
1098 if (dsthdr
== NULL
) {
1101 outvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= (void *)dsthdr
;
1102 outvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
1105 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1106 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1107 * then duplicate this. Else use talloc_memdup().
1110 if ((srcbody
== expected_srcbody
) && (srcbody_len
== 8)) {
1111 dstbody
= dsthdr
+ SMB2_HDR_BODY
;
1113 dstbody
= talloc_memdup(ctx
, srcbody
, srcbody_len
);
1114 if (dstbody
== NULL
) {
1118 outvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= (void *)dstbody
;
1119 outvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= srcbody_len
;
1122 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1124 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1125 * then duplicate this. Else use talloc_memdup().
1128 if ((srcdyn
== expected_srcdyn
) && (srcdyn_len
== 1)) {
1129 dstdyn
= dsthdr
+ SMB2_HDR_BODY
+ 8;
1130 } else if (srcdyn
== NULL
) {
1133 dstdyn
= talloc_memdup(ctx
, srcdyn
, srcdyn_len
);
1134 if (dstdyn
== NULL
) {
1138 outvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= (void *)dstdyn
;
1139 outvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= srcdyn_len
;
1144 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
1146 struct smbd_smb2_request
*newreq
= NULL
;
1147 struct iovec
*outvec
= NULL
;
1148 int count
= req
->out
.vector_count
;
1151 newreq
= smbd_smb2_request_allocate(req
->sconn
);
1156 newreq
->sconn
= req
->sconn
;
1157 newreq
->session
= req
->session
;
1158 newreq
->do_encryption
= req
->do_encryption
;
1159 newreq
->do_signing
= req
->do_signing
;
1160 newreq
->current_idx
= req
->current_idx
;
1162 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
1164 TALLOC_FREE(newreq
);
1167 newreq
->out
.vector
= outvec
;
1168 newreq
->out
.vector_count
= count
;
1170 /* Setup the outvec's identically to req. */
1171 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
1172 outvec
[0].iov_len
= 4;
1173 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
1175 /* Setup the vectors identically to the ones in req. */
1176 for (i
= 1; i
< count
; i
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
1177 if (!dup_smb2_vec4(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
1184 TALLOC_FREE(newreq
);
1188 smb2_setup_nbt_length(newreq
->out
.vector
,
1189 newreq
->out
.vector_count
);
1194 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
);
1196 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
1198 struct smbXsrv_connection
*conn
= req
->sconn
->conn
;
1200 struct iovec
*firsttf
= NULL
;
1201 struct iovec
*outhdr_v
= NULL
;
1202 uint8_t *outhdr
= NULL
;
1203 struct smbd_smb2_request
*nreq
= NULL
;
1206 /* Create a new smb2 request we'll use
1207 for the interim return. */
1208 nreq
= dup_smb2_req(req
);
1210 return NT_STATUS_NO_MEMORY
;
1213 /* Lose the last X out vectors. They're the
1214 ones we'll be using for the async reply. */
1215 nreq
->out
.vector_count
-= SMBD_SMB2_NUM_IOV_PER_REQ
;
1217 smb2_setup_nbt_length(nreq
->out
.vector
,
1218 nreq
->out
.vector_count
);
1220 /* Step back to the previous reply. */
1221 nreq
->current_idx
-= SMBD_SMB2_NUM_IOV_PER_REQ
;
1222 firsttf
= SMBD_SMB2_IDX_TF_IOV(nreq
,out
,first_idx
);
1223 outhdr_v
= SMBD_SMB2_OUT_HDR_IOV(nreq
);
1224 outhdr
= SMBD_SMB2_OUT_HDR_PTR(nreq
);
1225 /* And end the chain. */
1226 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1228 /* Calculate outgoing credits */
1229 smb2_calculate_credits(req
, nreq
);
1231 if (DEBUGLEVEL
>= 10) {
1232 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1233 (unsigned int)nreq
->current_idx
);
1234 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1235 (unsigned int)nreq
->out
.vector_count
);
1236 print_req_vectors(nreq
);
1240 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1241 * we need to sign/encrypt here with the last/first key we remembered
1243 if (firsttf
->iov_len
== SMB2_TF_HDR_SIZE
) {
1244 status
= smb2_signing_encrypt_pdu(req
->first_key
,
1247 nreq
->out
.vector_count
- first_idx
);
1248 if (!NT_STATUS_IS_OK(status
)) {
1251 } else if (req
->last_key
.length
> 0) {
1252 status
= smb2_signing_sign_pdu(req
->last_key
,
1255 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
1256 if (!NT_STATUS_IS_OK(status
)) {
1261 nreq
->subreq
= tstream_writev_queue_send(nreq
,
1262 nreq
->sconn
->ev_ctx
,
1263 nreq
->sconn
->smb2
.stream
,
1264 nreq
->sconn
->smb2
.send_queue
,
1266 nreq
->out
.vector_count
);
1268 if (nreq
->subreq
== NULL
) {
1269 return NT_STATUS_NO_MEMORY
;
1272 tevent_req_set_callback(nreq
->subreq
,
1273 smbd_smb2_request_writev_done
,
1276 return NT_STATUS_OK
;
1279 struct smbd_smb2_request_pending_state
{
1280 struct smbd_server_connection
*sconn
;
1281 uint8_t buf
[NBT_HDR_SIZE
+ SMB2_TF_HDR_SIZE
+ SMB2_HDR_BODY
+ 0x08 + 1];
1282 struct iovec vector
[1 + SMBD_SMB2_NUM_IOV_PER_REQ
];
1285 static void smbd_smb2_request_pending_writev_done(struct tevent_req
*subreq
)
1287 struct smbd_smb2_request_pending_state
*state
=
1288 tevent_req_callback_data(subreq
,
1289 struct smbd_smb2_request_pending_state
);
1290 struct smbd_server_connection
*sconn
= state
->sconn
;
1294 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1295 TALLOC_FREE(subreq
);
1297 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
1298 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1305 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
1306 struct tevent_timer
*te
,
1307 struct timeval current_time
,
1308 void *private_data
);
1310 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
1311 struct tevent_req
*subreq
,
1312 uint32_t defer_time
)
1315 int idx
= req
->current_idx
;
1316 struct timeval defer_endtime
;
1317 uint8_t *outhdr
= NULL
;
1320 if (!tevent_req_is_in_progress(subreq
)) {
1321 return NT_STATUS_OK
;
1324 req
->subreq
= subreq
;
1327 if (req
->async_te
) {
1328 /* We're already async. */
1329 return NT_STATUS_OK
;
1332 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1333 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1334 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1335 /* We're already async. */
1336 return NT_STATUS_OK
;
1339 if (req
->in
.vector_count
> idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
) {
1341 * We're trying to go async in a compound
1342 * request chain. This is not allowed.
1343 * Cancel the outstanding request.
1345 tevent_req_cancel(req
->subreq
);
1346 return smbd_smb2_request_error(req
,
1347 NT_STATUS_INSUFFICIENT_RESOURCES
);
1350 if (DEBUGLEVEL
>= 10) {
1351 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1352 (unsigned int)req
->current_idx
);
1353 print_req_vectors(req
);
1356 if (req
->out
.vector_count
>= (2*SMBD_SMB2_NUM_IOV_PER_REQ
)) {
1358 * This is a compound reply. We
1359 * must do an interim response
1360 * followed by the async response
1363 status
= smb2_send_async_interim_response(req
);
1364 if (!NT_STATUS_IS_OK(status
)) {
1367 data_blob_clear_free(&req
->first_key
);
1370 * We're splitting off the last SMB2
1371 * request in a compound set, and the
1372 * smb2_send_async_interim_response()
1373 * call above just sent all the replies
1374 * for the previous SMB2 requests in
1375 * this compound set. So we're no longer
1376 * in the "compound_related_in_progress"
1377 * state, and this is no longer a compound
1380 req
->compound_related
= false;
1381 req
->sconn
->smb2
.compound_related_in_progress
= false;
1383 req
->current_idx
= 1;
1385 /* Re-arrange the in.vectors. */
1386 memmove(&req
->in
.vector
[req
->current_idx
],
1387 &req
->in
.vector
[idx
],
1388 sizeof(req
->in
.vector
[0])*SMBD_SMB2_NUM_IOV_PER_REQ
);
1389 req
->in
.vector_count
= req
->current_idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
;
1391 /* Re-arrange the out.vectors. */
1392 memmove(&req
->out
.vector
[req
->current_idx
],
1393 &req
->out
.vector
[idx
],
1394 sizeof(req
->out
.vector
[0])*SMBD_SMB2_NUM_IOV_PER_REQ
);
1395 req
->out
.vector_count
= req
->current_idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
;
1397 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1398 flags
= (IVAL(outhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
1399 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
);
1401 data_blob_clear_free(&req
->last_key
);
1403 defer_endtime
= timeval_current_ofs_usec(defer_time
);
1404 req
->async_te
= tevent_add_timer(req
->sconn
->ev_ctx
,
1406 smbd_smb2_request_pending_timer
,
1408 if (req
->async_te
== NULL
) {
1409 return NT_STATUS_NO_MEMORY
;
1412 return NT_STATUS_OK
;
1415 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
1416 struct tevent_timer
*te
,
1417 struct timeval current_time
,
1420 struct smbd_smb2_request
*req
=
1421 talloc_get_type_abort(private_data
,
1422 struct smbd_smb2_request
);
1423 struct smbd_smb2_request_pending_state
*state
= NULL
;
1424 uint8_t *outhdr
= NULL
;
1425 const uint8_t *inhdr
= NULL
;
1428 uint8_t *hdr
= NULL
;
1429 uint8_t *body
= NULL
;
1430 uint8_t *dyn
= NULL
;
1432 uint64_t session_id
= 0;
1433 uint64_t message_id
= 0;
1434 uint64_t nonce_high
;
1436 uint64_t async_id
= 0;
1437 struct tevent_req
*subreq
= NULL
;
1439 TALLOC_FREE(req
->async_te
);
1441 /* Ensure our final reply matches the interim one. */
1442 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1443 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1444 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1445 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1446 session_id
= BVAL(outhdr
, SMB2_HDR_SESSION_ID
);
1448 async_id
= message_id
; /* keep it simple for now... */
1450 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1451 SBVAL(outhdr
, SMB2_HDR_ASYNC_ID
, async_id
);
1453 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1455 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1456 (unsigned long long)async_id
));
1459 * What we send is identical to a smbd_smb2_request_error
1460 * packet with an error status of STATUS_PENDING. Make use
1461 * of this fact sometime when refactoring. JRA.
1464 state
= talloc_zero(req
->sconn
, struct smbd_smb2_request_pending_state
);
1465 if (state
== NULL
) {
1466 smbd_server_connection_terminate(req
->sconn
,
1467 nt_errstr(NT_STATUS_NO_MEMORY
));
1470 state
->sconn
= req
->sconn
;
1472 tf
= state
->buf
+ NBT_HDR_SIZE
;
1473 tf_len
= SMB2_TF_HDR_SIZE
;
1475 hdr
= tf
+ SMB2_TF_HDR_SIZE
;
1476 body
= hdr
+ SMB2_HDR_BODY
;
1480 * We may have 2 responses (PENDING, FINAL),
1481 * so alter the nonce.
1483 * The PENDING response has the SMB2_HDR_FLAG_ASYNC bit
1486 nonce_high
= session_id
| SMB2_HDR_FLAG_ASYNC
;
1487 nonce_low
= message_id
;
1489 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
1490 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
1491 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
1492 SBVAL(tf
, SMB2_TF_SESSION_ID
, session_id
);
1494 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
1495 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1496 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1497 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
1498 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(outhdr
, SMB2_HDR_OPCODE
));
1500 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
);
1501 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1502 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
1503 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
1504 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
1505 BVAL(outhdr
, SMB2_HDR_SESSION_ID
));
1506 memcpy(hdr
+SMB2_HDR_SIGNATURE
,
1507 outhdr
+SMB2_HDR_SIGNATURE
, 16);
1509 SSVAL(body
, 0x00, 0x08 + 1);
1511 SCVAL(body
, 0x02, 0);
1512 SCVAL(body
, 0x03, 0);
1513 SIVAL(body
, 0x04, 0);
1514 /* Match W2K8R2... */
1515 SCVAL(dyn
, 0x00, 0x21);
1517 state
->vector
[0].iov_base
= (void *)state
->buf
;
1518 state
->vector
[0].iov_len
= NBT_HDR_SIZE
;
1520 if (req
->do_encryption
) {
1521 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= tf
;
1522 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= tf_len
;
1524 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
1525 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
1528 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
1529 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
1531 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
1532 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_len
= 8;
1534 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
1535 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_len
= 1;
1537 smb2_setup_nbt_length(state
->vector
, 1 + SMBD_SMB2_NUM_IOV_PER_REQ
);
1539 /* Ensure we correctly go through crediting. Grant
1540 the credits now, and zero credits on the final
1542 smb2_set_operation_credit(req
->sconn
,
1543 SMBD_SMB2_IN_HDR_IOV(req
),
1544 &state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
]);
1546 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1551 for (i
= 0; i
< ARRAY_SIZE(state
->vector
); i
++) {
1552 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1554 (unsigned int)ARRAY_SIZE(state
->vector
),
1555 (unsigned int)state
->vector
[i
].iov_len
);
1556 dump_data(0, state
->vector
[i
].iov_base
, state
->vector
[i
].iov_len
);
1560 if (req
->do_encryption
) {
1562 struct smbXsrv_session
*x
= req
->session
;
1563 struct smbXsrv_connection
*conn
= x
->connection
;
1564 DATA_BLOB encryption_key
= x
->global
->encryption_key
;
1566 status
= smb2_signing_encrypt_pdu(encryption_key
,
1568 &state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
],
1569 SMBD_SMB2_NUM_IOV_PER_REQ
);
1570 if (!NT_STATUS_IS_OK(status
)) {
1571 smbd_server_connection_terminate(req
->sconn
,
1575 } else if (req
->do_signing
) {
1577 struct smbXsrv_session
*x
= req
->session
;
1578 struct smbXsrv_connection
*conn
= x
->connection
;
1579 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
1581 status
= smb2_signing_sign_pdu(signing_key
,
1583 &state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
],
1584 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
1585 if (!NT_STATUS_IS_OK(status
)) {
1586 smbd_server_connection_terminate(req
->sconn
,
1592 subreq
= tstream_writev_queue_send(state
,
1593 state
->sconn
->ev_ctx
,
1594 state
->sconn
->smb2
.stream
,
1595 state
->sconn
->smb2
.send_queue
,
1597 ARRAY_SIZE(state
->vector
));
1598 if (subreq
== NULL
) {
1599 smbd_server_connection_terminate(state
->sconn
,
1600 nt_errstr(NT_STATUS_NO_MEMORY
));
1603 tevent_req_set_callback(subreq
,
1604 smbd_smb2_request_pending_writev_done
,
1608 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
1610 struct smbd_server_connection
*sconn
= req
->sconn
;
1611 struct smbd_smb2_request
*cur
;
1612 const uint8_t *inhdr
;
1614 uint64_t search_message_id
;
1615 uint64_t search_async_id
;
1618 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1620 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1621 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1622 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
1625 * we don't need the request anymore
1626 * cancel requests never have a response
1628 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1631 for (cur
= sconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
1632 const uint8_t *outhdr
;
1633 uint64_t message_id
;
1636 outhdr
= SMBD_SMB2_OUT_HDR_PTR(cur
);
1638 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1639 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
1641 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1642 if (search_async_id
== async_id
) {
1643 found_id
= async_id
;
1647 if (search_message_id
== message_id
) {
1648 found_id
= message_id
;
1654 if (cur
&& cur
->subreq
) {
1655 inhdr
= SMBD_SMB2_IN_HDR_PTR(cur
);
1656 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1657 "cancel opcode[%s] mid %llu\n",
1658 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1659 (unsigned long long)found_id
));
1660 tevent_req_cancel(cur
->subreq
);
1663 return NT_STATUS_OK
;
1666 /*************************************************************
1667 Ensure an incoming tid is a valid one for us to access.
1668 Change to the associated uid credentials and chdir to the
1669 valid tid directory.
1670 *************************************************************/
1672 static NTSTATUS
smbd_smb2_request_check_tcon(struct smbd_smb2_request
*req
)
1674 const uint8_t *inhdr
;
1677 struct smbXsrv_tcon
*tcon
;
1679 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1683 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1685 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1686 in_tid
= IVAL(inhdr
, SMB2_HDR_TID
);
1688 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1689 in_tid
= req
->last_tid
;
1692 status
= smb2srv_tcon_lookup(req
->session
,
1693 in_tid
, now
, &tcon
);
1694 if (!NT_STATUS_IS_OK(status
)) {
1698 if (!change_to_user(tcon
->compat
, req
->session
->compat
->vuid
)) {
1699 return NT_STATUS_ACCESS_DENIED
;
1702 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1703 if (!set_current_service(tcon
->compat
, 0, true)) {
1704 return NT_STATUS_ACCESS_DENIED
;
1708 req
->last_tid
= in_tid
;
1710 return NT_STATUS_OK
;
1713 /*************************************************************
1714 Ensure an incoming session_id is a valid one for us to access.
1715 *************************************************************/
1717 static NTSTATUS
smbd_smb2_request_check_session(struct smbd_smb2_request
*req
)
1719 const uint8_t *inhdr
;
1722 uint64_t in_session_id
;
1723 struct smbXsrv_session
*session
= NULL
;
1724 struct auth_session_info
*session_info
;
1726 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1728 req
->session
= NULL
;
1731 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1733 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1734 in_opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1735 in_session_id
= BVAL(inhdr
, SMB2_HDR_SESSION_ID
);
1737 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1738 in_session_id
= req
->last_session_id
;
1741 /* lookup an existing session */
1742 status
= smb2srv_session_lookup(req
->sconn
->conn
,
1746 req
->session
= session
;
1747 req
->last_session_id
= in_session_id
;
1749 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
1750 switch (in_opcode
) {
1751 case SMB2_OP_SESSSETUP
:
1752 status
= NT_STATUS_OK
;
1758 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1759 switch (in_opcode
) {
1761 case SMB2_OP_CREATE
:
1762 case SMB2_OP_GETINFO
:
1763 case SMB2_OP_SETINFO
:
1764 return NT_STATUS_INVALID_HANDLE
;
1767 * Notice the check for
1768 * (session_info == NULL)
1771 status
= NT_STATUS_OK
;
1775 if (!NT_STATUS_IS_OK(status
)) {
1779 session_info
= session
->global
->auth_session_info
;
1780 if (session_info
== NULL
) {
1781 return NT_STATUS_INVALID_HANDLE
;
1784 set_current_user_info(session_info
->unix_info
->sanitized_username
,
1785 session_info
->unix_info
->unix_name
,
1786 session_info
->info
->domain_name
);
1788 return NT_STATUS_OK
;
1791 NTSTATUS
smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request
*req
,
1792 uint32_t data_length
)
1794 uint16_t needed_charge
;
1795 uint16_t credit_charge
= 1;
1796 const uint8_t *inhdr
;
1798 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1800 if (req
->sconn
->smb2
.supports_multicredit
) {
1801 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
1802 credit_charge
= MAX(credit_charge
, 1);
1805 needed_charge
= (data_length
- 1)/ 65536 + 1;
1807 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1808 (unsigned long long) BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
),
1809 credit_charge
, needed_charge
));
1811 if (needed_charge
> credit_charge
) {
1812 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1813 credit_charge
, needed_charge
));
1814 return NT_STATUS_INVALID_PARAMETER
;
1817 return NT_STATUS_OK
;
1820 NTSTATUS
smbd_smb2_request_verify_sizes(struct smbd_smb2_request
*req
,
1821 size_t expected_body_size
)
1823 struct iovec
*inhdr_v
;
1824 const uint8_t *inhdr
;
1826 const uint8_t *inbody
;
1828 size_t min_dyn_size
= expected_body_size
& 0x00000001;
1829 int max_idx
= req
->in
.vector_count
- SMBD_SMB2_NUM_IOV_PER_REQ
;
1832 * The following should be checked already.
1834 if (req
->in
.vector_count
< SMBD_SMB2_NUM_IOV_PER_REQ
) {
1835 return NT_STATUS_INTERNAL_ERROR
;
1837 if (req
->current_idx
> max_idx
) {
1838 return NT_STATUS_INTERNAL_ERROR
;
1841 inhdr_v
= SMBD_SMB2_IN_HDR_IOV(req
);
1842 if (inhdr_v
->iov_len
!= SMB2_HDR_BODY
) {
1843 return NT_STATUS_INTERNAL_ERROR
;
1845 if (SMBD_SMB2_IN_BODY_LEN(req
) < 2) {
1846 return NT_STATUS_INTERNAL_ERROR
;
1849 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1850 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1854 case SMB2_OP_GETINFO
:
1860 * Now check the expected body size,
1861 * where the last byte might be in the
1864 if (SMBD_SMB2_IN_BODY_LEN(req
) != (expected_body_size
& 0xFFFFFFFE)) {
1865 return NT_STATUS_INVALID_PARAMETER
;
1867 if (SMBD_SMB2_IN_DYN_LEN(req
) < min_dyn_size
) {
1868 return NT_STATUS_INVALID_PARAMETER
;
1871 inbody
= SMBD_SMB2_IN_BODY_PTR(req
);
1873 body_size
= SVAL(inbody
, 0x00);
1874 if (body_size
!= expected_body_size
) {
1875 return NT_STATUS_INVALID_PARAMETER
;
1878 return NT_STATUS_OK
;
1881 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
1883 struct smbXsrv_connection
*conn
= req
->sconn
->conn
;
1884 const struct smbd_smb2_dispatch_table
*call
= NULL
;
1885 const struct iovec
*intf_v
= SMBD_SMB2_IN_TF_IOV(req
);
1886 const uint8_t *inhdr
;
1891 NTSTATUS session_status
;
1892 uint32_t allowed_flags
;
1893 NTSTATUS return_value
;
1894 struct smbXsrv_session
*x
= NULL
;
1895 bool signing_required
= false;
1896 bool encryption_required
= false;
1898 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1900 /* TODO: verify more things */
1902 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1903 opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1904 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1905 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1906 smb2_opcode_name(opcode
),
1907 (unsigned long long)mid
));
1909 if (conn
->protocol
>= PROTOCOL_SMB2_02
) {
1911 * once the protocol is negotiated
1912 * SMB2_OP_NEGPROT is not allowed anymore
1914 if (opcode
== SMB2_OP_NEGPROT
) {
1915 /* drop the connection */
1916 return NT_STATUS_INVALID_PARAMETER
;
1920 * if the protocol is not negotiated yet
1921 * only SMB2_OP_NEGPROT is allowed.
1923 if (opcode
!= SMB2_OP_NEGPROT
) {
1924 /* drop the connection */
1925 return NT_STATUS_INVALID_PARAMETER
;
1930 * Check if the client provided a valid session id,
1931 * if so smbd_smb2_request_check_session() calls
1932 * set_current_user_info().
1934 * As some command don't require a valid session id
1935 * we defer the check of the session_status
1937 session_status
= smbd_smb2_request_check_session(req
);
1940 signing_required
= x
->global
->signing_required
;
1941 encryption_required
= x
->global
->encryption_required
;
1943 if (opcode
== SMB2_OP_SESSSETUP
&&
1944 x
->global
->channels
[0].signing_key
.length
) {
1945 signing_required
= true;
1949 req
->do_signing
= false;
1950 req
->do_encryption
= false;
1951 if (intf_v
->iov_len
== SMB2_TF_HDR_SIZE
) {
1952 const uint8_t *intf
= SMBD_SMB2_IN_TF_PTR(req
);
1953 uint64_t tf_session_id
= BVAL(intf
, SMB2_TF_SESSION_ID
);
1955 if (x
!= NULL
&& x
->global
->session_wire_id
!= tf_session_id
) {
1956 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1957 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1958 (unsigned long long)x
->global
->session_wire_id
,
1959 (unsigned long long)tf_session_id
));
1961 * TODO: windows allows this...
1962 * should we drop the connection?
1964 * For now we just return ACCESS_DENIED
1965 * (Windows clients never trigger this)
1966 * and wait for an update of [MS-SMB2].
1968 return smbd_smb2_request_error(req
,
1969 NT_STATUS_ACCESS_DENIED
);
1972 req
->do_encryption
= true;
1975 if (encryption_required
&& !req
->do_encryption
) {
1976 return smbd_smb2_request_error(req
,
1977 NT_STATUS_ACCESS_DENIED
);
1980 call
= smbd_smb2_call(opcode
);
1982 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1985 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
1986 SMB2_HDR_FLAG_SIGNED
|
1988 if (opcode
== SMB2_OP_CANCEL
) {
1989 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
1991 if ((flags
& ~allowed_flags
) != 0) {
1992 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1995 if (req
->do_encryption
) {
1996 signing_required
= false;
1997 } else if (flags
& SMB2_HDR_FLAG_SIGNED
) {
1998 DATA_BLOB signing_key
;
2001 return smbd_smb2_request_error(
2002 req
, NT_STATUS_ACCESS_DENIED
);
2005 signing_key
= x
->global
->channels
[0].signing_key
;
2008 * If we have a signing key, we should
2011 if (signing_key
.length
> 0) {
2012 req
->do_signing
= true;
2015 status
= smb2_signing_check_pdu(signing_key
,
2017 SMBD_SMB2_IN_HDR_IOV(req
),
2018 SMBD_SMB2_NUM_IOV_PER_REQ
);
2019 if (!NT_STATUS_IS_OK(status
)) {
2020 return smbd_smb2_request_error(req
, status
);
2024 * Now that we know the request was correctly signed
2025 * we have to sign the response too.
2027 req
->do_signing
= true;
2029 if (!NT_STATUS_IS_OK(session_status
)) {
2030 return smbd_smb2_request_error(req
, session_status
);
2032 } else if (opcode
== SMB2_OP_CANCEL
) {
2033 /* Cancel requests are allowed to skip the signing */
2034 } else if (signing_required
) {
2036 * If signing is required we try to sign
2037 * a possible error response
2039 req
->do_signing
= true;
2040 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
2043 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
2045 * This check is mostly for giving the correct error code
2046 * for compounded requests.
2048 * TODO: we may need to move this after the session
2051 if (!NT_STATUS_IS_OK(req
->next_status
)) {
2052 return smbd_smb2_request_error(req
, req
->next_status
);
2055 req
->compat_chain_fsp
= NULL
;
2058 if (req
->compound_related
) {
2059 req
->sconn
->smb2
.compound_related_in_progress
= true;
2062 if (call
->need_session
) {
2063 if (!NT_STATUS_IS_OK(session_status
)) {
2064 return smbd_smb2_request_error(req
, session_status
);
2068 if (call
->need_tcon
) {
2069 SMB_ASSERT(call
->need_session
);
2072 * This call needs to be run as user.
2074 * smbd_smb2_request_check_tcon()
2075 * calls change_to_user() on success.
2077 status
= smbd_smb2_request_check_tcon(req
);
2078 if (!NT_STATUS_IS_OK(status
)) {
2079 return smbd_smb2_request_error(req
, status
);
2081 if (req
->tcon
->global
->encryption_required
) {
2082 encryption_required
= true;
2084 if (encryption_required
&& !req
->do_encryption
) {
2085 return smbd_smb2_request_error(req
,
2086 NT_STATUS_ACCESS_DENIED
);
2090 if (call
->fileid_ofs
!= 0) {
2091 size_t needed
= call
->fileid_ofs
+ 16;
2092 const uint8_t *body
= SMBD_SMB2_IN_BODY_PTR(req
);
2093 size_t body_size
= SMBD_SMB2_IN_BODY_LEN(req
);
2094 uint64_t file_id_persistent
;
2095 uint64_t file_id_volatile
;
2096 struct files_struct
*fsp
;
2098 SMB_ASSERT(call
->need_tcon
);
2100 if (needed
> body_size
) {
2101 return smbd_smb2_request_error(req
,
2102 NT_STATUS_INVALID_PARAMETER
);
2105 file_id_persistent
= BVAL(body
, call
->fileid_ofs
+ 0);
2106 file_id_volatile
= BVAL(body
, call
->fileid_ofs
+ 8);
2108 fsp
= file_fsp_smb2(req
, file_id_persistent
, file_id_volatile
);
2110 if (!call
->allow_invalid_fileid
) {
2111 return smbd_smb2_request_error(req
,
2112 NT_STATUS_FILE_CLOSED
);
2115 if (file_id_persistent
!= UINT64_MAX
) {
2116 return smbd_smb2_request_error(req
,
2117 NT_STATUS_FILE_CLOSED
);
2119 if (file_id_volatile
!= UINT64_MAX
) {
2120 return smbd_smb2_request_error(req
,
2121 NT_STATUS_FILE_CLOSED
);
2126 if (call
->as_root
) {
2127 SMB_ASSERT(call
->fileid_ofs
== 0);
2128 /* This call needs to be run as root */
2129 change_to_root_user();
2131 SMB_ASSERT(call
->need_tcon
);
2135 case SMB2_OP_NEGPROT
:
2137 START_PROFILE(smb2_negprot
);
2138 return_value
= smbd_smb2_request_process_negprot(req
);
2139 END_PROFILE(smb2_negprot
);
2143 case SMB2_OP_SESSSETUP
:
2145 START_PROFILE(smb2_sesssetup
);
2146 return_value
= smbd_smb2_request_process_sesssetup(req
);
2147 END_PROFILE(smb2_sesssetup
);
2151 case SMB2_OP_LOGOFF
:
2153 START_PROFILE(smb2_logoff
);
2154 return_value
= smbd_smb2_request_process_logoff(req
);
2155 END_PROFILE(smb2_logoff
);
2161 START_PROFILE(smb2_tcon
);
2162 return_value
= smbd_smb2_request_process_tcon(req
);
2163 END_PROFILE(smb2_tcon
);
2169 START_PROFILE(smb2_tdis
);
2170 return_value
= smbd_smb2_request_process_tdis(req
);
2171 END_PROFILE(smb2_tdis
);
2175 case SMB2_OP_CREATE
:
2177 START_PROFILE(smb2_create
);
2178 return_value
= smbd_smb2_request_process_create(req
);
2179 END_PROFILE(smb2_create
);
2185 START_PROFILE(smb2_close
);
2186 return_value
= smbd_smb2_request_process_close(req
);
2187 END_PROFILE(smb2_close
);
2193 START_PROFILE(smb2_flush
);
2194 return_value
= smbd_smb2_request_process_flush(req
);
2195 END_PROFILE(smb2_flush
);
2201 START_PROFILE(smb2_read
);
2202 return_value
= smbd_smb2_request_process_read(req
);
2203 END_PROFILE(smb2_read
);
2209 START_PROFILE(smb2_write
);
2210 return_value
= smbd_smb2_request_process_write(req
);
2211 END_PROFILE(smb2_write
);
2217 START_PROFILE(smb2_lock
);
2218 return_value
= smbd_smb2_request_process_lock(req
);
2219 END_PROFILE(smb2_lock
);
2225 START_PROFILE(smb2_ioctl
);
2226 return_value
= smbd_smb2_request_process_ioctl(req
);
2227 END_PROFILE(smb2_ioctl
);
2231 case SMB2_OP_CANCEL
:
2233 START_PROFILE(smb2_cancel
);
2234 return_value
= smbd_smb2_request_process_cancel(req
);
2235 END_PROFILE(smb2_cancel
);
2239 case SMB2_OP_KEEPALIVE
:
2241 START_PROFILE(smb2_keepalive
);
2242 return_value
= smbd_smb2_request_process_keepalive(req
);
2243 END_PROFILE(smb2_keepalive
);
2249 START_PROFILE(smb2_find
);
2250 return_value
= smbd_smb2_request_process_find(req
);
2251 END_PROFILE(smb2_find
);
2255 case SMB2_OP_NOTIFY
:
2257 START_PROFILE(smb2_notify
);
2258 return_value
= smbd_smb2_request_process_notify(req
);
2259 END_PROFILE(smb2_notify
);
2263 case SMB2_OP_GETINFO
:
2265 START_PROFILE(smb2_getinfo
);
2266 return_value
= smbd_smb2_request_process_getinfo(req
);
2267 END_PROFILE(smb2_getinfo
);
2271 case SMB2_OP_SETINFO
:
2273 START_PROFILE(smb2_setinfo
);
2274 return_value
= smbd_smb2_request_process_setinfo(req
);
2275 END_PROFILE(smb2_setinfo
);
2281 START_PROFILE(smb2_break
);
2282 return_value
= smbd_smb2_request_process_break(req
);
2283 END_PROFILE(smb2_break
);
2288 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2291 return return_value
;
2294 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
2296 struct smbXsrv_connection
*conn
= req
->sconn
->conn
;
2297 struct tevent_req
*subreq
;
2299 struct iovec
*firsttf
= SMBD_SMB2_IDX_TF_IOV(req
,out
,first_idx
);
2300 struct iovec
*outhdr
= SMBD_SMB2_OUT_HDR_IOV(req
);
2301 struct iovec
*outdyn
= SMBD_SMB2_OUT_DYN_IOV(req
);
2304 TALLOC_FREE(req
->async_te
);
2306 if (req
->do_encryption
&&
2307 (firsttf
->iov_len
== 0) &&
2308 (req
->first_key
.length
== 0) &&
2309 (req
->session
!= NULL
) &&
2310 (req
->session
->global
->encryption_key
.length
!= 0))
2312 DATA_BLOB encryption_key
= req
->session
->global
->encryption_key
;
2314 const uint8_t *inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
2315 uint64_t session_id
= req
->session
->global
->session_wire_id
;
2316 uint64_t message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
2317 uint64_t async_id
= BVAL(inhdr
, SMB2_HDR_ASYNC_ID
);
2319 * We may have 2 responses (PENDING, FINAL),
2320 * so alter the nonce.
2322 * The FINAL response has the SMB2_HDR_FLAG_ASYNC bit
2325 uint64_t nonce_high
= session_id
& ~SMB2_HDR_FLAG_ASYNC
;
2326 uint64_t nonce_low
= message_id
;
2328 if (nonce_low
== 0) {
2329 nonce_low
= async_id
;
2333 * We need to place the SMB2_TRANSFORM header before the
2338 * we need to remember the encryption key
2339 * and defer the signing/encryption until
2340 * we are sure that we do not change
2343 req
->first_key
= data_blob_dup_talloc(req
, encryption_key
);
2344 if (req
->first_key
.data
== NULL
) {
2345 return NT_STATUS_NO_MEMORY
;
2348 tf
= talloc_zero_array(req
->out
.vector
, uint8_t,
2351 return NT_STATUS_NO_MEMORY
;
2354 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
2355 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
2356 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
2357 SBVAL(tf
, SMB2_TF_SESSION_ID
, session_id
);
2359 firsttf
->iov_base
= (void *)tf
;
2360 firsttf
->iov_len
= SMB2_TF_HDR_SIZE
;
2363 if ((req
->current_idx
> SMBD_SMB2_NUM_IOV_PER_REQ
) &&
2364 (req
->last_key
.length
> 0) &&
2365 (firsttf
->iov_len
== 0))
2367 int last_idx
= req
->current_idx
- SMBD_SMB2_NUM_IOV_PER_REQ
;
2368 struct iovec
*lasthdr
= SMBD_SMB2_IDX_HDR_IOV(req
,out
,last_idx
);
2372 * As we are sure the header of the last request in the
2373 * compound chain will not change, we can to sign here
2374 * with the last signing key we remembered.
2376 status
= smb2_signing_sign_pdu(req
->last_key
,
2379 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2380 if (!NT_STATUS_IS_OK(status
)) {
2384 data_blob_clear_free(&req
->last_key
);
2386 req
->current_idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
;
2388 if (req
->current_idx
< req
->out
.vector_count
) {
2390 * We must process the remaining compound
2391 * SMB2 requests before any new incoming SMB2
2392 * requests. This is because incoming SMB2
2393 * requests may include a cancel for a
2394 * compound request we haven't processed
2397 struct tevent_immediate
*im
= tevent_create_immediate(req
);
2399 return NT_STATUS_NO_MEMORY
;
2402 if (req
->do_signing
&& firsttf
->iov_len
== 0) {
2403 struct smbXsrv_session
*x
= req
->session
;
2404 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
2407 * we need to remember the signing key
2408 * and defer the signing until
2409 * we are sure that we do not change
2412 req
->last_key
= data_blob_dup_talloc(req
, signing_key
);
2413 if (req
->last_key
.data
== NULL
) {
2414 return NT_STATUS_NO_MEMORY
;
2418 tevent_schedule_immediate(im
,
2420 smbd_smb2_request_dispatch_immediate
,
2422 return NT_STATUS_OK
;
2425 if (req
->compound_related
) {
2426 req
->sconn
->smb2
.compound_related_in_progress
= false;
2429 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
2431 /* Set credit for these operations (zero credits if this
2432 is a final reply for an async operation). */
2433 smb2_calculate_credits(req
, req
);
2436 * now check if we need to sign the current response
2438 if (firsttf
->iov_len
== SMB2_TF_HDR_SIZE
) {
2441 status
= smb2_signing_encrypt_pdu(req
->first_key
,
2444 req
->out
.vector_count
- first_idx
);
2445 if (!NT_STATUS_IS_OK(status
)) {
2448 } else if (req
->do_signing
) {
2450 struct smbXsrv_session
*x
= req
->session
;
2451 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
2453 status
= smb2_signing_sign_pdu(signing_key
,
2456 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2457 if (!NT_STATUS_IS_OK(status
)) {
2461 data_blob_clear_free(&req
->first_key
);
2463 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2464 if (req
->out
.vector_count
< (2*SMBD_SMB2_NUM_IOV_PER_REQ
) &&
2465 outdyn
->iov_base
== NULL
&& outdyn
->iov_len
!= 0) {
2466 /* Dynamic part is NULL. Chop it off,
2467 We're going to send it via sendfile. */
2468 req
->out
.vector_count
-= 1;
2471 subreq
= tstream_writev_queue_send(req
,
2473 req
->sconn
->smb2
.stream
,
2474 req
->sconn
->smb2
.send_queue
,
2476 req
->out
.vector_count
);
2477 if (subreq
== NULL
) {
2478 return NT_STATUS_NO_MEMORY
;
2480 tevent_req_set_callback(subreq
, smbd_smb2_request_writev_done
, req
);
2482 * We're done with this request -
2483 * move it off the "being processed" queue.
2485 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
2487 return NT_STATUS_OK
;
2490 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
);
2492 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
2493 struct tevent_immediate
*im
,
2496 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
2497 struct smbd_smb2_request
);
2498 struct smbd_server_connection
*sconn
= req
->sconn
;
2503 if (DEBUGLEVEL
>= 10) {
2504 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2505 req
->current_idx
, req
->in
.vector_count
));
2506 print_req_vectors(req
);
2509 status
= smbd_smb2_request_dispatch(req
);
2510 if (!NT_STATUS_IS_OK(status
)) {
2511 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2515 status
= smbd_smb2_request_next_incoming(sconn
);
2516 if (!NT_STATUS_IS_OK(status
)) {
2517 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2522 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
)
2524 struct smbd_smb2_request
*req
= tevent_req_callback_data(subreq
,
2525 struct smbd_smb2_request
);
2526 struct smbd_server_connection
*sconn
= req
->sconn
;
2531 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
2532 TALLOC_FREE(subreq
);
2535 status
= map_nt_error_from_unix(sys_errno
);
2536 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2537 nt_errstr(status
)));
2538 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2542 status
= smbd_smb2_request_next_incoming(sconn
);
2543 if (!NT_STATUS_IS_OK(status
)) {
2544 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2549 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
2551 DATA_BLOB body
, DATA_BLOB
*dyn
,
2552 const char *location
)
2555 struct iovec
*outbody_v
;
2556 struct iovec
*outdyn_v
;
2557 uint32_t next_command_ofs
;
2559 DEBUG(10,("smbd_smb2_request_done_ex: "
2560 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2561 req
->current_idx
, nt_errstr(status
), (unsigned int)body
.length
,
2563 (unsigned int)(dyn
? dyn
->length
: 0),
2566 if (body
.length
< 2) {
2567 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2570 if ((body
.length
% 2) != 0) {
2571 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2574 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
2575 outbody_v
= SMBD_SMB2_OUT_BODY_IOV(req
);
2576 outdyn_v
= SMBD_SMB2_OUT_DYN_IOV(req
);
2578 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
2579 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
2581 outbody_v
->iov_base
= (void *)body
.data
;
2582 outbody_v
->iov_len
= body
.length
;
2585 outdyn_v
->iov_base
= (void *)dyn
->data
;
2586 outdyn_v
->iov_len
= dyn
->length
;
2588 outdyn_v
->iov_base
= NULL
;
2589 outdyn_v
->iov_len
= 0;
2592 /* see if we need to recalculate the offset to the next response */
2593 if (next_command_ofs
> 0) {
2594 next_command_ofs
= SMB2_HDR_BODY
;
2595 next_command_ofs
+= SMBD_SMB2_OUT_BODY_LEN(req
);
2596 next_command_ofs
+= SMBD_SMB2_OUT_DYN_LEN(req
);
2599 if ((next_command_ofs
% 8) != 0) {
2600 size_t pad_size
= 8 - (next_command_ofs
% 8);
2601 if (SMBD_SMB2_OUT_DYN_LEN(req
) == 0) {
2603 * if the dyn buffer is empty
2604 * we can use it to add padding
2608 pad
= talloc_zero_array(req
->out
.vector
,
2611 return smbd_smb2_request_error(req
,
2612 NT_STATUS_NO_MEMORY
);
2615 outdyn_v
->iov_base
= (void *)pad
;
2616 outdyn_v
->iov_len
= pad_size
;
2619 * For now we copy the dynamic buffer
2620 * and add the padding to the new buffer
2627 old_size
= SMBD_SMB2_OUT_DYN_LEN(req
);
2628 old_dyn
= SMBD_SMB2_OUT_DYN_PTR(req
);
2630 new_size
= old_size
+ pad_size
;
2631 new_dyn
= talloc_zero_array(req
->out
.vector
,
2633 if (new_dyn
== NULL
) {
2634 return smbd_smb2_request_error(req
,
2635 NT_STATUS_NO_MEMORY
);
2638 memcpy(new_dyn
, old_dyn
, old_size
);
2639 memset(new_dyn
+ old_size
, 0, pad_size
);
2641 outdyn_v
->iov_base
= (void *)new_dyn
;
2642 outdyn_v
->iov_len
= new_size
;
2644 next_command_ofs
+= pad_size
;
2647 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
2649 return smbd_smb2_request_reply(req
);
2652 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
2655 const char *location
)
2658 uint8_t *outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
2660 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2661 req
->current_idx
, nt_errstr(status
), info
? " +info" : "",
2664 body
.data
= outhdr
+ SMB2_HDR_BODY
;
2666 SSVAL(body
.data
, 0, 9);
2669 SIVAL(body
.data
, 0x04, info
->length
);
2671 /* Allocated size of req->out.vector[i].iov_base
2672 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2673 * 1 byte without having to do an alloc.
2675 info
= talloc_zero_array(req
->out
.vector
,
2679 return NT_STATUS_NO_MEMORY
;
2681 info
->data
= ((uint8_t *)outhdr
) +
2682 OUTVEC_ALLOC_SIZE
- 1;
2684 SCVAL(info
->data
, 0, 0);
2688 * if a request fails, all other remaining
2689 * compounded requests should fail too
2691 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
2693 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
2697 struct smbd_smb2_send_oplock_break_state
{
2698 struct smbd_server_connection
*sconn
;
2699 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x18];
2700 struct iovec vector
;
2703 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
);
2705 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
2706 uint64_t file_id_persistent
,
2707 uint64_t file_id_volatile
,
2708 uint8_t oplock_level
)
2710 struct smbd_smb2_send_oplock_break_state
*state
;
2711 struct tevent_req
*subreq
;
2715 state
= talloc(sconn
, struct smbd_smb2_send_oplock_break_state
);
2716 if (state
== NULL
) {
2717 return NT_STATUS_NO_MEMORY
;
2719 state
->sconn
= sconn
;
2721 state
->vector
.iov_base
= (void *)state
->buf
;
2722 state
->vector
.iov_len
= sizeof(state
->buf
);
2724 _smb2_setlen(state
->buf
, sizeof(state
->buf
) - 4);
2725 hdr
= state
->buf
+ 4;
2726 body
= hdr
+ SMB2_HDR_BODY
;
2728 SIVAL(hdr
, 0, SMB2_MAGIC
);
2729 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
2730 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
2731 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
2732 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
2733 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
2734 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
2735 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
2736 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
2737 SIVAL(hdr
, SMB2_HDR_PID
, 0);
2738 SIVAL(hdr
, SMB2_HDR_TID
, 0);
2739 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
2740 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
2742 SSVAL(body
, 0x00, 0x18);
2744 SCVAL(body
, 0x02, oplock_level
);
2745 SCVAL(body
, 0x03, 0); /* reserved */
2746 SIVAL(body
, 0x04, 0); /* reserved */
2747 SBVAL(body
, 0x08, file_id_persistent
);
2748 SBVAL(body
, 0x10, file_id_volatile
);
2750 subreq
= tstream_writev_queue_send(state
,
2753 sconn
->smb2
.send_queue
,
2755 if (subreq
== NULL
) {
2756 return NT_STATUS_NO_MEMORY
;
2758 tevent_req_set_callback(subreq
,
2759 smbd_smb2_oplock_break_writev_done
,
2762 return NT_STATUS_OK
;
2765 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
)
2767 struct smbd_smb2_send_oplock_break_state
*state
=
2768 tevent_req_callback_data(subreq
,
2769 struct smbd_smb2_send_oplock_break_state
);
2770 struct smbd_server_connection
*sconn
= state
->sconn
;
2774 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
2775 TALLOC_FREE(subreq
);
2777 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
2778 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2785 struct smbd_smb2_request_read_state
{
2786 struct tevent_context
*ev
;
2787 struct smbd_server_connection
*sconn
;
2788 struct smbd_smb2_request
*smb2_req
;
2790 uint8_t nbt
[NBT_HDR_SIZE
];
2797 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2799 TALLOC_CTX
*mem_ctx
,
2800 struct iovec
**_vector
,
2802 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
);
2804 static struct tevent_req
*smbd_smb2_request_read_send(TALLOC_CTX
*mem_ctx
,
2805 struct tevent_context
*ev
,
2806 struct smbd_server_connection
*sconn
)
2808 struct tevent_req
*req
;
2809 struct smbd_smb2_request_read_state
*state
;
2810 struct tevent_req
*subreq
;
2812 req
= tevent_req_create(mem_ctx
, &state
,
2813 struct smbd_smb2_request_read_state
);
2818 state
->sconn
= sconn
;
2820 state
->smb2_req
= smbd_smb2_request_allocate(state
);
2821 if (tevent_req_nomem(state
->smb2_req
, req
)) {
2822 return tevent_req_post(req
, ev
);
2824 state
->smb2_req
->sconn
= sconn
;
2826 subreq
= tstream_readv_pdu_queue_send(state
->smb2_req
,
2828 state
->sconn
->smb2
.stream
,
2829 state
->sconn
->smb2
.recv_queue
,
2830 smbd_smb2_request_next_vector
,
2832 if (tevent_req_nomem(subreq
, req
)) {
2833 return tevent_req_post(req
, ev
);
2835 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
2840 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2842 TALLOC_CTX
*mem_ctx
,
2843 struct iovec
**_vector
,
2846 struct smbd_smb2_request_read_state
*state
=
2847 talloc_get_type_abort(private_data
,
2848 struct smbd_smb2_request_read_state
);
2849 struct iovec
*vector
;
2851 if (state
->pktlen
> 0) {
2852 /* if there're no remaining bytes, we're done */
2858 if (!state
->hdr
.done
) {
2860 * first we need to get the NBT header
2862 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2863 if (vector
== NULL
) {
2867 vector
[0].iov_base
= (void *)state
->hdr
.nbt
;
2868 vector
[0].iov_len
= NBT_HDR_SIZE
;
2873 state
->hdr
.done
= true;
2878 * Now we analyze the NBT header
2880 state
->pktlen
= smb2_len(state
->hdr
.nbt
);
2882 if (state
->pktlen
== 0) {
2883 /* if there're no remaining bytes, we're done */
2889 state
->pktbuf
= talloc_array(state
->smb2_req
, uint8_t, state
->pktlen
);
2890 if (state
->pktbuf
== NULL
) {
2894 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2895 if (vector
== NULL
) {
2899 vector
[0].iov_base
= (void *)state
->pktbuf
;
2900 vector
[0].iov_len
= state
->pktlen
;
2907 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
)
2909 struct tevent_req
*req
=
2910 tevent_req_callback_data(subreq
,
2912 struct smbd_smb2_request_read_state
*state
=
2913 tevent_req_data(req
,
2914 struct smbd_smb2_request_read_state
);
2920 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
2921 TALLOC_FREE(subreq
);
2923 status
= map_nt_error_from_unix(sys_errno
);
2924 tevent_req_nterror(req
, status
);
2928 if (state
->hdr
.nbt
[0] != 0x00) {
2929 DEBUG(1,("smbd_smb2_request_read_done: ignore NBT[0x%02X] msg\n",
2930 state
->hdr
.nbt
[0]));
2932 ZERO_STRUCT(state
->hdr
);
2933 TALLOC_FREE(state
->pktbuf
);
2936 subreq
= tstream_readv_pdu_queue_send(state
->smb2_req
,
2938 state
->sconn
->smb2
.stream
,
2939 state
->sconn
->smb2
.recv_queue
,
2940 smbd_smb2_request_next_vector
,
2942 if (tevent_req_nomem(subreq
, req
)) {
2945 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
2949 state
->smb2_req
->request_time
= timeval_current();
2950 now
= timeval_to_nttime(&state
->smb2_req
->request_time
);
2952 status
= smbd_smb2_inbuf_parse_compound(state
->smb2_req
->sconn
->conn
,
2957 &state
->smb2_req
->in
.vector
,
2958 &state
->smb2_req
->in
.vector_count
);
2959 if (tevent_req_nterror(req
, status
)) {
2963 state
->smb2_req
->current_idx
= 1;
2965 tevent_req_done(req
);
2968 static NTSTATUS
smbd_smb2_request_read_recv(struct tevent_req
*req
,
2969 TALLOC_CTX
*mem_ctx
,
2970 struct smbd_smb2_request
**_smb2_req
)
2972 struct smbd_smb2_request_read_state
*state
=
2973 tevent_req_data(req
,
2974 struct smbd_smb2_request_read_state
);
2977 if (tevent_req_is_nterror(req
, &status
)) {
2978 tevent_req_received(req
);
2982 *_smb2_req
= talloc_move(mem_ctx
, &state
->smb2_req
);
2983 tevent_req_received(req
);
2984 return NT_STATUS_OK
;
2987 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
);
2989 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
)
2991 size_t max_send_queue_len
;
2992 size_t cur_send_queue_len
;
2993 struct tevent_req
*subreq
;
2995 if (sconn
->smb2
.compound_related_in_progress
) {
2997 * Can't read another until the related
3000 return NT_STATUS_OK
;
3003 if (tevent_queue_length(sconn
->smb2
.recv_queue
) > 0) {
3005 * if there is already a smbd_smb2_request_read
3006 * pending, we are done.
3008 return NT_STATUS_OK
;
3011 max_send_queue_len
= MAX(1, sconn
->smb2
.max_credits
/16);
3012 cur_send_queue_len
= tevent_queue_length(sconn
->smb2
.send_queue
);
3014 if (cur_send_queue_len
> max_send_queue_len
) {
3016 * if we have a lot of requests to send,
3017 * we wait until they are on the wire until we
3018 * ask for the next request.
3020 return NT_STATUS_OK
;
3023 /* ask for the next request */
3024 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->ev_ctx
, sconn
);
3025 if (subreq
== NULL
) {
3026 return NT_STATUS_NO_MEMORY
;
3028 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);
3030 return NT_STATUS_OK
;
3033 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
3034 uint8_t *inbuf
, size_t size
)
3037 struct smbd_smb2_request
*req
= NULL
;
3039 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3040 (unsigned int)size
));
3042 status
= smbd_initialize_smb2(sconn
);
3043 if (!NT_STATUS_IS_OK(status
)) {
3044 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3048 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
3049 if (!NT_STATUS_IS_OK(status
)) {
3050 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3054 status
= smbd_smb2_request_validate(req
);
3055 if (!NT_STATUS_IS_OK(status
)) {
3056 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3060 status
= smbd_smb2_request_setup_out(req
);
3061 if (!NT_STATUS_IS_OK(status
)) {
3062 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3066 status
= smbd_smb2_request_dispatch(req
);
3067 if (!NT_STATUS_IS_OK(status
)) {
3068 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3072 status
= smbd_smb2_request_next_incoming(sconn
);
3073 if (!NT_STATUS_IS_OK(status
)) {
3074 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3078 sconn
->num_requests
++;
3081 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
)
3083 struct smbd_server_connection
*sconn
= tevent_req_callback_data(subreq
,
3084 struct smbd_server_connection
);
3086 struct smbd_smb2_request
*req
= NULL
;
3088 status
= smbd_smb2_request_read_recv(subreq
, sconn
, &req
);
3089 TALLOC_FREE(subreq
);
3090 if (!NT_STATUS_IS_OK(status
)) {
3091 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
3092 nt_errstr(status
)));
3093 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3097 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
3098 req
->current_idx
, req
->in
.vector_count
));
3100 status
= smbd_smb2_request_validate(req
);
3101 if (!NT_STATUS_IS_OK(status
)) {
3102 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3106 status
= smbd_smb2_request_setup_out(req
);
3107 if (!NT_STATUS_IS_OK(status
)) {
3108 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3112 status
= smbd_smb2_request_dispatch(req
);
3113 if (!NT_STATUS_IS_OK(status
)) {
3114 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3118 status
= smbd_smb2_request_next_incoming(sconn
);
3119 if (!NT_STATUS_IS_OK(status
)) {
3120 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3124 sconn
->num_requests
++;
3126 /* The timeout_processing function isn't run nearly
3127 often enough to implement 'max log size' without
3128 overrunning the size of the file by many megabytes.
3129 This is especially true if we are running at debug
3130 level 10. Checking every 50 SMB2s is a nice
3131 tradeoff of performance vs log file size overrun. */
3133 if ((sconn
->num_requests
% 50) == 0 &&
3134 need_to_check_log_size()) {
3135 change_to_root_user();