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
= 0;
1435 uint64_t nonce_low
= 0;
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
;
1479 if (req
->do_encryption
) {
1480 struct smbXsrv_session
*x
= req
->session
;
1482 nonce_high
= x
->nonce_high
;
1483 nonce_low
= x
->nonce_low
;
1486 if (x
->nonce_low
== 0) {
1492 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
1493 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
1494 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
1495 SBVAL(tf
, SMB2_TF_SESSION_ID
, session_id
);
1497 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
1498 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1499 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1500 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
1501 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(outhdr
, SMB2_HDR_OPCODE
));
1503 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
);
1504 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1505 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
1506 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
1507 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
1508 BVAL(outhdr
, SMB2_HDR_SESSION_ID
));
1509 memcpy(hdr
+SMB2_HDR_SIGNATURE
,
1510 outhdr
+SMB2_HDR_SIGNATURE
, 16);
1512 SSVAL(body
, 0x00, 0x08 + 1);
1514 SCVAL(body
, 0x02, 0);
1515 SCVAL(body
, 0x03, 0);
1516 SIVAL(body
, 0x04, 0);
1517 /* Match W2K8R2... */
1518 SCVAL(dyn
, 0x00, 0x21);
1520 state
->vector
[0].iov_base
= (void *)state
->buf
;
1521 state
->vector
[0].iov_len
= NBT_HDR_SIZE
;
1523 if (req
->do_encryption
) {
1524 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= tf
;
1525 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= tf_len
;
1527 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
1528 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
1531 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
1532 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
1534 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
1535 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_len
= 8;
1537 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
1538 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_len
= 1;
1540 smb2_setup_nbt_length(state
->vector
, 1 + SMBD_SMB2_NUM_IOV_PER_REQ
);
1542 /* Ensure we correctly go through crediting. Grant
1543 the credits now, and zero credits on the final
1545 smb2_set_operation_credit(req
->sconn
,
1546 SMBD_SMB2_IN_HDR_IOV(req
),
1547 &state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
]);
1549 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1554 for (i
= 0; i
< ARRAY_SIZE(state
->vector
); i
++) {
1555 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1557 (unsigned int)ARRAY_SIZE(state
->vector
),
1558 (unsigned int)state
->vector
[i
].iov_len
);
1562 if (req
->do_encryption
) {
1564 struct smbXsrv_session
*x
= req
->session
;
1565 struct smbXsrv_connection
*conn
= x
->connection
;
1566 DATA_BLOB encryption_key
= x
->global
->encryption_key
;
1568 status
= smb2_signing_encrypt_pdu(encryption_key
,
1570 &state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
],
1571 SMBD_SMB2_NUM_IOV_PER_REQ
);
1572 if (!NT_STATUS_IS_OK(status
)) {
1573 smbd_server_connection_terminate(req
->sconn
,
1577 } else if (req
->do_signing
) {
1579 struct smbXsrv_session
*x
= req
->session
;
1580 struct smbXsrv_connection
*conn
= x
->connection
;
1581 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
1583 status
= smb2_signing_sign_pdu(signing_key
,
1585 &state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
],
1586 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
1587 if (!NT_STATUS_IS_OK(status
)) {
1588 smbd_server_connection_terminate(req
->sconn
,
1594 subreq
= tstream_writev_queue_send(state
,
1595 state
->sconn
->ev_ctx
,
1596 state
->sconn
->smb2
.stream
,
1597 state
->sconn
->smb2
.send_queue
,
1599 ARRAY_SIZE(state
->vector
));
1600 if (subreq
== NULL
) {
1601 smbd_server_connection_terminate(state
->sconn
,
1602 nt_errstr(NT_STATUS_NO_MEMORY
));
1605 tevent_req_set_callback(subreq
,
1606 smbd_smb2_request_pending_writev_done
,
1610 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
1612 struct smbd_server_connection
*sconn
= req
->sconn
;
1613 struct smbd_smb2_request
*cur
;
1614 const uint8_t *inhdr
;
1616 uint64_t search_message_id
;
1617 uint64_t search_async_id
;
1620 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1622 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1623 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1624 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
1627 * we don't need the request anymore
1628 * cancel requests never have a response
1630 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1633 for (cur
= sconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
1634 const uint8_t *outhdr
;
1635 uint64_t message_id
;
1638 outhdr
= SMBD_SMB2_OUT_HDR_PTR(cur
);
1640 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1641 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
1643 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1644 if (search_async_id
== async_id
) {
1645 found_id
= async_id
;
1649 if (search_message_id
== message_id
) {
1650 found_id
= message_id
;
1656 if (cur
&& cur
->subreq
) {
1657 inhdr
= SMBD_SMB2_IN_HDR_PTR(cur
);
1658 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1659 "cancel opcode[%s] mid %llu\n",
1660 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1661 (unsigned long long)found_id
));
1662 tevent_req_cancel(cur
->subreq
);
1665 return NT_STATUS_OK
;
1668 /*************************************************************
1669 Ensure an incoming tid is a valid one for us to access.
1670 Change to the associated uid credentials and chdir to the
1671 valid tid directory.
1672 *************************************************************/
1674 static NTSTATUS
smbd_smb2_request_check_tcon(struct smbd_smb2_request
*req
)
1676 const uint8_t *inhdr
;
1679 struct smbXsrv_tcon
*tcon
;
1681 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1685 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1687 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1688 in_tid
= IVAL(inhdr
, SMB2_HDR_TID
);
1690 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1691 in_tid
= req
->last_tid
;
1694 status
= smb2srv_tcon_lookup(req
->session
,
1695 in_tid
, now
, &tcon
);
1696 if (!NT_STATUS_IS_OK(status
)) {
1700 if (!change_to_user(tcon
->compat
, req
->session
->compat
->vuid
)) {
1701 return NT_STATUS_ACCESS_DENIED
;
1704 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1705 if (!set_current_service(tcon
->compat
, 0, true)) {
1706 return NT_STATUS_ACCESS_DENIED
;
1710 req
->last_tid
= in_tid
;
1712 return NT_STATUS_OK
;
1715 /*************************************************************
1716 Ensure an incoming session_id is a valid one for us to access.
1717 *************************************************************/
1719 static NTSTATUS
smbd_smb2_request_check_session(struct smbd_smb2_request
*req
)
1721 const uint8_t *inhdr
;
1724 uint64_t in_session_id
;
1725 struct smbXsrv_session
*session
= NULL
;
1726 struct auth_session_info
*session_info
;
1728 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1730 req
->session
= NULL
;
1733 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1735 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1736 in_opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1737 in_session_id
= BVAL(inhdr
, SMB2_HDR_SESSION_ID
);
1739 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1740 in_session_id
= req
->last_session_id
;
1743 /* lookup an existing session */
1744 status
= smb2srv_session_lookup(req
->sconn
->conn
,
1748 req
->session
= session
;
1749 req
->last_session_id
= in_session_id
;
1751 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
1752 switch (in_opcode
) {
1753 case SMB2_OP_SESSSETUP
:
1754 status
= NT_STATUS_OK
;
1760 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1761 switch (in_opcode
) {
1763 case SMB2_OP_CREATE
:
1764 case SMB2_OP_GETINFO
:
1765 case SMB2_OP_SETINFO
:
1766 return NT_STATUS_INVALID_HANDLE
;
1769 * Notice the check for
1770 * (session_info == NULL)
1773 status
= NT_STATUS_OK
;
1777 if (!NT_STATUS_IS_OK(status
)) {
1781 session_info
= session
->global
->auth_session_info
;
1782 if (session_info
== NULL
) {
1783 return NT_STATUS_INVALID_HANDLE
;
1786 set_current_user_info(session_info
->unix_info
->sanitized_username
,
1787 session_info
->unix_info
->unix_name
,
1788 session_info
->info
->domain_name
);
1790 return NT_STATUS_OK
;
1793 NTSTATUS
smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request
*req
,
1794 uint32_t data_length
)
1796 uint16_t needed_charge
;
1797 uint16_t credit_charge
= 1;
1798 const uint8_t *inhdr
;
1800 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1802 if (req
->sconn
->smb2
.supports_multicredit
) {
1803 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
1804 credit_charge
= MAX(credit_charge
, 1);
1807 needed_charge
= (data_length
- 1)/ 65536 + 1;
1809 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1810 (unsigned long long) BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
),
1811 credit_charge
, needed_charge
));
1813 if (needed_charge
> credit_charge
) {
1814 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1815 credit_charge
, needed_charge
));
1816 return NT_STATUS_INVALID_PARAMETER
;
1819 return NT_STATUS_OK
;
1822 NTSTATUS
smbd_smb2_request_verify_sizes(struct smbd_smb2_request
*req
,
1823 size_t expected_body_size
)
1825 struct iovec
*inhdr_v
;
1826 const uint8_t *inhdr
;
1828 const uint8_t *inbody
;
1830 size_t min_dyn_size
= expected_body_size
& 0x00000001;
1831 int max_idx
= req
->in
.vector_count
- SMBD_SMB2_NUM_IOV_PER_REQ
;
1834 * The following should be checked already.
1836 if (req
->in
.vector_count
< SMBD_SMB2_NUM_IOV_PER_REQ
) {
1837 return NT_STATUS_INTERNAL_ERROR
;
1839 if (req
->current_idx
> max_idx
) {
1840 return NT_STATUS_INTERNAL_ERROR
;
1843 inhdr_v
= SMBD_SMB2_IN_HDR_IOV(req
);
1844 if (inhdr_v
->iov_len
!= SMB2_HDR_BODY
) {
1845 return NT_STATUS_INTERNAL_ERROR
;
1847 if (SMBD_SMB2_IN_BODY_LEN(req
) < 2) {
1848 return NT_STATUS_INTERNAL_ERROR
;
1851 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1852 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1856 case SMB2_OP_GETINFO
:
1862 * Now check the expected body size,
1863 * where the last byte might be in the
1866 if (SMBD_SMB2_IN_BODY_LEN(req
) != (expected_body_size
& 0xFFFFFFFE)) {
1867 return NT_STATUS_INVALID_PARAMETER
;
1869 if (SMBD_SMB2_IN_DYN_LEN(req
) < min_dyn_size
) {
1870 return NT_STATUS_INVALID_PARAMETER
;
1873 inbody
= SMBD_SMB2_IN_BODY_PTR(req
);
1875 body_size
= SVAL(inbody
, 0x00);
1876 if (body_size
!= expected_body_size
) {
1877 return NT_STATUS_INVALID_PARAMETER
;
1880 return NT_STATUS_OK
;
1883 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
1885 struct smbXsrv_connection
*conn
= req
->sconn
->conn
;
1886 const struct smbd_smb2_dispatch_table
*call
= NULL
;
1887 const struct iovec
*intf_v
= SMBD_SMB2_IN_TF_IOV(req
);
1888 const uint8_t *inhdr
;
1893 NTSTATUS session_status
;
1894 uint32_t allowed_flags
;
1895 NTSTATUS return_value
;
1896 struct smbXsrv_session
*x
= NULL
;
1897 bool signing_required
= false;
1898 bool encryption_required
= false;
1900 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1902 /* TODO: verify more things */
1904 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1905 opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1906 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1907 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1908 smb2_opcode_name(opcode
),
1909 (unsigned long long)mid
));
1911 if (conn
->protocol
>= PROTOCOL_SMB2_02
) {
1913 * once the protocol is negotiated
1914 * SMB2_OP_NEGPROT is not allowed anymore
1916 if (opcode
== SMB2_OP_NEGPROT
) {
1917 /* drop the connection */
1918 return NT_STATUS_INVALID_PARAMETER
;
1922 * if the protocol is not negotiated yet
1923 * only SMB2_OP_NEGPROT is allowed.
1925 if (opcode
!= SMB2_OP_NEGPROT
) {
1926 /* drop the connection */
1927 return NT_STATUS_INVALID_PARAMETER
;
1932 * Check if the client provided a valid session id,
1933 * if so smbd_smb2_request_check_session() calls
1934 * set_current_user_info().
1936 * As some command don't require a valid session id
1937 * we defer the check of the session_status
1939 session_status
= smbd_smb2_request_check_session(req
);
1942 signing_required
= x
->global
->signing_required
;
1943 encryption_required
= x
->global
->encryption_required
;
1945 if (opcode
== SMB2_OP_SESSSETUP
&&
1946 x
->global
->channels
[0].signing_key
.length
) {
1947 signing_required
= true;
1951 req
->do_signing
= false;
1952 req
->do_encryption
= false;
1953 if (intf_v
->iov_len
== SMB2_TF_HDR_SIZE
) {
1954 const uint8_t *intf
= SMBD_SMB2_IN_TF_PTR(req
);
1955 uint64_t tf_session_id
= BVAL(intf
, SMB2_TF_SESSION_ID
);
1957 if (x
!= NULL
&& x
->global
->session_wire_id
!= tf_session_id
) {
1958 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1959 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1960 (unsigned long long)x
->global
->session_wire_id
,
1961 (unsigned long long)tf_session_id
));
1963 * TODO: windows allows this...
1964 * should we drop the connection?
1966 * For now we just return ACCESS_DENIED
1967 * (Windows clients never trigger this)
1968 * and wait for an update of [MS-SMB2].
1970 return smbd_smb2_request_error(req
,
1971 NT_STATUS_ACCESS_DENIED
);
1974 req
->do_encryption
= true;
1977 if (encryption_required
&& !req
->do_encryption
) {
1978 return smbd_smb2_request_error(req
,
1979 NT_STATUS_ACCESS_DENIED
);
1982 call
= smbd_smb2_call(opcode
);
1984 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1987 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
1988 SMB2_HDR_FLAG_SIGNED
|
1990 if (opcode
== SMB2_OP_CANCEL
) {
1991 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
1993 if ((flags
& ~allowed_flags
) != 0) {
1994 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1997 if (req
->do_encryption
) {
1998 signing_required
= false;
1999 } else if (flags
& SMB2_HDR_FLAG_SIGNED
) {
2000 DATA_BLOB signing_key
;
2003 return smbd_smb2_request_error(
2004 req
, NT_STATUS_ACCESS_DENIED
);
2007 signing_key
= x
->global
->channels
[0].signing_key
;
2010 * If we have a signing key, we should
2013 if (signing_key
.length
> 0) {
2014 req
->do_signing
= true;
2017 status
= smb2_signing_check_pdu(signing_key
,
2019 SMBD_SMB2_IN_HDR_IOV(req
),
2020 SMBD_SMB2_NUM_IOV_PER_REQ
);
2021 if (!NT_STATUS_IS_OK(status
)) {
2022 return smbd_smb2_request_error(req
, status
);
2026 * Now that we know the request was correctly signed
2027 * we have to sign the response too.
2029 req
->do_signing
= true;
2031 if (!NT_STATUS_IS_OK(session_status
)) {
2032 return smbd_smb2_request_error(req
, session_status
);
2034 } else if (opcode
== SMB2_OP_CANCEL
) {
2035 /* Cancel requests are allowed to skip the signing */
2036 } else if (signing_required
) {
2038 * If signing is required we try to sign
2039 * a possible error response
2041 req
->do_signing
= true;
2042 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
2045 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
2047 * This check is mostly for giving the correct error code
2048 * for compounded requests.
2050 * TODO: we may need to move this after the session
2053 if (!NT_STATUS_IS_OK(req
->next_status
)) {
2054 return smbd_smb2_request_error(req
, req
->next_status
);
2057 req
->compat_chain_fsp
= NULL
;
2060 if (req
->compound_related
) {
2061 req
->sconn
->smb2
.compound_related_in_progress
= true;
2064 if (call
->need_session
) {
2065 if (!NT_STATUS_IS_OK(session_status
)) {
2066 return smbd_smb2_request_error(req
, session_status
);
2070 if (call
->need_tcon
) {
2071 SMB_ASSERT(call
->need_session
);
2074 * This call needs to be run as user.
2076 * smbd_smb2_request_check_tcon()
2077 * calls change_to_user() on success.
2079 status
= smbd_smb2_request_check_tcon(req
);
2080 if (!NT_STATUS_IS_OK(status
)) {
2081 return smbd_smb2_request_error(req
, status
);
2083 if (req
->tcon
->global
->encryption_required
) {
2084 encryption_required
= true;
2086 if (encryption_required
&& !req
->do_encryption
) {
2087 return smbd_smb2_request_error(req
,
2088 NT_STATUS_ACCESS_DENIED
);
2092 if (call
->fileid_ofs
!= 0) {
2093 size_t needed
= call
->fileid_ofs
+ 16;
2094 const uint8_t *body
= SMBD_SMB2_IN_BODY_PTR(req
);
2095 size_t body_size
= SMBD_SMB2_IN_BODY_LEN(req
);
2096 uint64_t file_id_persistent
;
2097 uint64_t file_id_volatile
;
2098 struct files_struct
*fsp
;
2100 SMB_ASSERT(call
->need_tcon
);
2102 if (needed
> body_size
) {
2103 return smbd_smb2_request_error(req
,
2104 NT_STATUS_INVALID_PARAMETER
);
2107 file_id_persistent
= BVAL(body
, call
->fileid_ofs
+ 0);
2108 file_id_volatile
= BVAL(body
, call
->fileid_ofs
+ 8);
2110 fsp
= file_fsp_smb2(req
, file_id_persistent
, file_id_volatile
);
2112 if (!call
->allow_invalid_fileid
) {
2113 return smbd_smb2_request_error(req
,
2114 NT_STATUS_FILE_CLOSED
);
2117 if (file_id_persistent
!= UINT64_MAX
) {
2118 return smbd_smb2_request_error(req
,
2119 NT_STATUS_FILE_CLOSED
);
2121 if (file_id_volatile
!= UINT64_MAX
) {
2122 return smbd_smb2_request_error(req
,
2123 NT_STATUS_FILE_CLOSED
);
2128 if (call
->as_root
) {
2129 SMB_ASSERT(call
->fileid_ofs
== 0);
2130 /* This call needs to be run as root */
2131 change_to_root_user();
2133 SMB_ASSERT(call
->need_tcon
);
2137 case SMB2_OP_NEGPROT
:
2139 START_PROFILE(smb2_negprot
);
2140 return_value
= smbd_smb2_request_process_negprot(req
);
2141 END_PROFILE(smb2_negprot
);
2145 case SMB2_OP_SESSSETUP
:
2147 START_PROFILE(smb2_sesssetup
);
2148 return_value
= smbd_smb2_request_process_sesssetup(req
);
2149 END_PROFILE(smb2_sesssetup
);
2153 case SMB2_OP_LOGOFF
:
2155 START_PROFILE(smb2_logoff
);
2156 return_value
= smbd_smb2_request_process_logoff(req
);
2157 END_PROFILE(smb2_logoff
);
2163 START_PROFILE(smb2_tcon
);
2164 return_value
= smbd_smb2_request_process_tcon(req
);
2165 END_PROFILE(smb2_tcon
);
2171 START_PROFILE(smb2_tdis
);
2172 return_value
= smbd_smb2_request_process_tdis(req
);
2173 END_PROFILE(smb2_tdis
);
2177 case SMB2_OP_CREATE
:
2179 START_PROFILE(smb2_create
);
2180 return_value
= smbd_smb2_request_process_create(req
);
2181 END_PROFILE(smb2_create
);
2187 START_PROFILE(smb2_close
);
2188 return_value
= smbd_smb2_request_process_close(req
);
2189 END_PROFILE(smb2_close
);
2195 START_PROFILE(smb2_flush
);
2196 return_value
= smbd_smb2_request_process_flush(req
);
2197 END_PROFILE(smb2_flush
);
2203 START_PROFILE(smb2_read
);
2204 return_value
= smbd_smb2_request_process_read(req
);
2205 END_PROFILE(smb2_read
);
2211 START_PROFILE(smb2_write
);
2212 return_value
= smbd_smb2_request_process_write(req
);
2213 END_PROFILE(smb2_write
);
2219 START_PROFILE(smb2_lock
);
2220 return_value
= smbd_smb2_request_process_lock(req
);
2221 END_PROFILE(smb2_lock
);
2227 START_PROFILE(smb2_ioctl
);
2228 return_value
= smbd_smb2_request_process_ioctl(req
);
2229 END_PROFILE(smb2_ioctl
);
2233 case SMB2_OP_CANCEL
:
2235 START_PROFILE(smb2_cancel
);
2236 return_value
= smbd_smb2_request_process_cancel(req
);
2237 END_PROFILE(smb2_cancel
);
2241 case SMB2_OP_KEEPALIVE
:
2243 START_PROFILE(smb2_keepalive
);
2244 return_value
= smbd_smb2_request_process_keepalive(req
);
2245 END_PROFILE(smb2_keepalive
);
2251 START_PROFILE(smb2_find
);
2252 return_value
= smbd_smb2_request_process_find(req
);
2253 END_PROFILE(smb2_find
);
2257 case SMB2_OP_NOTIFY
:
2259 START_PROFILE(smb2_notify
);
2260 return_value
= smbd_smb2_request_process_notify(req
);
2261 END_PROFILE(smb2_notify
);
2265 case SMB2_OP_GETINFO
:
2267 START_PROFILE(smb2_getinfo
);
2268 return_value
= smbd_smb2_request_process_getinfo(req
);
2269 END_PROFILE(smb2_getinfo
);
2273 case SMB2_OP_SETINFO
:
2275 START_PROFILE(smb2_setinfo
);
2276 return_value
= smbd_smb2_request_process_setinfo(req
);
2277 END_PROFILE(smb2_setinfo
);
2283 START_PROFILE(smb2_break
);
2284 return_value
= smbd_smb2_request_process_break(req
);
2285 END_PROFILE(smb2_break
);
2290 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2293 return return_value
;
2296 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
2298 struct smbXsrv_connection
*conn
= req
->sconn
->conn
;
2299 struct tevent_req
*subreq
;
2301 struct iovec
*firsttf
= SMBD_SMB2_IDX_TF_IOV(req
,out
,first_idx
);
2302 struct iovec
*outhdr
= SMBD_SMB2_OUT_HDR_IOV(req
);
2303 struct iovec
*outdyn
= SMBD_SMB2_OUT_DYN_IOV(req
);
2306 TALLOC_FREE(req
->async_te
);
2308 if (req
->do_encryption
&&
2309 (firsttf
->iov_len
== 0) &&
2310 (req
->first_key
.length
== 0) &&
2311 (req
->session
!= NULL
) &&
2312 (req
->session
->global
->encryption_key
.length
!= 0))
2314 DATA_BLOB encryption_key
= req
->session
->global
->encryption_key
;
2316 uint64_t session_id
= req
->session
->global
->session_wire_id
;
2317 struct smbXsrv_session
*x
= req
->session
;
2318 uint64_t nonce_high
;
2321 nonce_high
= x
->nonce_high
;
2322 nonce_low
= x
->nonce_low
;
2325 if (x
->nonce_low
== 0) {
2331 * We need to place the SMB2_TRANSFORM header before the
2336 * we need to remember the encryption key
2337 * and defer the signing/encryption until
2338 * we are sure that we do not change
2341 req
->first_key
= data_blob_dup_talloc(req
, encryption_key
);
2342 if (req
->first_key
.data
== NULL
) {
2343 return NT_STATUS_NO_MEMORY
;
2346 tf
= talloc_zero_array(req
->out
.vector
, uint8_t,
2349 return NT_STATUS_NO_MEMORY
;
2352 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
2353 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
2354 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
2355 SBVAL(tf
, SMB2_TF_SESSION_ID
, session_id
);
2357 firsttf
->iov_base
= (void *)tf
;
2358 firsttf
->iov_len
= SMB2_TF_HDR_SIZE
;
2361 if ((req
->current_idx
> SMBD_SMB2_NUM_IOV_PER_REQ
) &&
2362 (req
->last_key
.length
> 0) &&
2363 (firsttf
->iov_len
== 0))
2365 int last_idx
= req
->current_idx
- SMBD_SMB2_NUM_IOV_PER_REQ
;
2366 struct iovec
*lasthdr
= SMBD_SMB2_IDX_HDR_IOV(req
,out
,last_idx
);
2370 * As we are sure the header of the last request in the
2371 * compound chain will not change, we can to sign here
2372 * with the last signing key we remembered.
2374 status
= smb2_signing_sign_pdu(req
->last_key
,
2377 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2378 if (!NT_STATUS_IS_OK(status
)) {
2382 data_blob_clear_free(&req
->last_key
);
2384 req
->current_idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
;
2386 if (req
->current_idx
< req
->out
.vector_count
) {
2388 * We must process the remaining compound
2389 * SMB2 requests before any new incoming SMB2
2390 * requests. This is because incoming SMB2
2391 * requests may include a cancel for a
2392 * compound request we haven't processed
2395 struct tevent_immediate
*im
= tevent_create_immediate(req
);
2397 return NT_STATUS_NO_MEMORY
;
2400 if (req
->do_signing
&& firsttf
->iov_len
== 0) {
2401 struct smbXsrv_session
*x
= req
->session
;
2402 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
2405 * we need to remember the signing key
2406 * and defer the signing until
2407 * we are sure that we do not change
2410 req
->last_key
= data_blob_dup_talloc(req
, signing_key
);
2411 if (req
->last_key
.data
== NULL
) {
2412 return NT_STATUS_NO_MEMORY
;
2416 tevent_schedule_immediate(im
,
2418 smbd_smb2_request_dispatch_immediate
,
2420 return NT_STATUS_OK
;
2423 if (req
->compound_related
) {
2424 req
->sconn
->smb2
.compound_related_in_progress
= false;
2427 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
2429 /* Set credit for these operations (zero credits if this
2430 is a final reply for an async operation). */
2431 smb2_calculate_credits(req
, req
);
2434 * now check if we need to sign the current response
2436 if (firsttf
->iov_len
== SMB2_TF_HDR_SIZE
) {
2439 status
= smb2_signing_encrypt_pdu(req
->first_key
,
2442 req
->out
.vector_count
- first_idx
);
2443 if (!NT_STATUS_IS_OK(status
)) {
2446 } else if (req
->do_signing
) {
2448 struct smbXsrv_session
*x
= req
->session
;
2449 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
2451 status
= smb2_signing_sign_pdu(signing_key
,
2454 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2455 if (!NT_STATUS_IS_OK(status
)) {
2459 data_blob_clear_free(&req
->first_key
);
2461 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2462 if (req
->out
.vector_count
< (2*SMBD_SMB2_NUM_IOV_PER_REQ
) &&
2463 outdyn
->iov_base
== NULL
&& outdyn
->iov_len
!= 0) {
2464 /* Dynamic part is NULL. Chop it off,
2465 We're going to send it via sendfile. */
2466 req
->out
.vector_count
-= 1;
2469 subreq
= tstream_writev_queue_send(req
,
2471 req
->sconn
->smb2
.stream
,
2472 req
->sconn
->smb2
.send_queue
,
2474 req
->out
.vector_count
);
2475 if (subreq
== NULL
) {
2476 return NT_STATUS_NO_MEMORY
;
2478 tevent_req_set_callback(subreq
, smbd_smb2_request_writev_done
, req
);
2480 * We're done with this request -
2481 * move it off the "being processed" queue.
2483 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
2485 return NT_STATUS_OK
;
2488 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
);
2490 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
2491 struct tevent_immediate
*im
,
2494 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
2495 struct smbd_smb2_request
);
2496 struct smbd_server_connection
*sconn
= req
->sconn
;
2501 if (DEBUGLEVEL
>= 10) {
2502 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2503 req
->current_idx
, req
->in
.vector_count
));
2504 print_req_vectors(req
);
2507 status
= smbd_smb2_request_dispatch(req
);
2508 if (!NT_STATUS_IS_OK(status
)) {
2509 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2513 status
= smbd_smb2_request_next_incoming(sconn
);
2514 if (!NT_STATUS_IS_OK(status
)) {
2515 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2520 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
)
2522 struct smbd_smb2_request
*req
= tevent_req_callback_data(subreq
,
2523 struct smbd_smb2_request
);
2524 struct smbd_server_connection
*sconn
= req
->sconn
;
2529 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
2530 TALLOC_FREE(subreq
);
2533 status
= map_nt_error_from_unix(sys_errno
);
2534 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2535 nt_errstr(status
)));
2536 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2540 status
= smbd_smb2_request_next_incoming(sconn
);
2541 if (!NT_STATUS_IS_OK(status
)) {
2542 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2547 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
2549 DATA_BLOB body
, DATA_BLOB
*dyn
,
2550 const char *location
)
2553 struct iovec
*outbody_v
;
2554 struct iovec
*outdyn_v
;
2555 uint32_t next_command_ofs
;
2557 DEBUG(10,("smbd_smb2_request_done_ex: "
2558 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2559 req
->current_idx
, nt_errstr(status
), (unsigned int)body
.length
,
2561 (unsigned int)(dyn
? dyn
->length
: 0),
2564 if (body
.length
< 2) {
2565 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2568 if ((body
.length
% 2) != 0) {
2569 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2572 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
2573 outbody_v
= SMBD_SMB2_OUT_BODY_IOV(req
);
2574 outdyn_v
= SMBD_SMB2_OUT_DYN_IOV(req
);
2576 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
2577 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
2579 outbody_v
->iov_base
= (void *)body
.data
;
2580 outbody_v
->iov_len
= body
.length
;
2583 outdyn_v
->iov_base
= (void *)dyn
->data
;
2584 outdyn_v
->iov_len
= dyn
->length
;
2586 outdyn_v
->iov_base
= NULL
;
2587 outdyn_v
->iov_len
= 0;
2590 /* see if we need to recalculate the offset to the next response */
2591 if (next_command_ofs
> 0) {
2592 next_command_ofs
= SMB2_HDR_BODY
;
2593 next_command_ofs
+= SMBD_SMB2_OUT_BODY_LEN(req
);
2594 next_command_ofs
+= SMBD_SMB2_OUT_DYN_LEN(req
);
2597 if ((next_command_ofs
% 8) != 0) {
2598 size_t pad_size
= 8 - (next_command_ofs
% 8);
2599 if (SMBD_SMB2_OUT_DYN_LEN(req
) == 0) {
2601 * if the dyn buffer is empty
2602 * we can use it to add padding
2606 pad
= talloc_zero_array(req
->out
.vector
,
2609 return smbd_smb2_request_error(req
,
2610 NT_STATUS_NO_MEMORY
);
2613 outdyn_v
->iov_base
= (void *)pad
;
2614 outdyn_v
->iov_len
= pad_size
;
2617 * For now we copy the dynamic buffer
2618 * and add the padding to the new buffer
2625 old_size
= SMBD_SMB2_OUT_DYN_LEN(req
);
2626 old_dyn
= SMBD_SMB2_OUT_DYN_PTR(req
);
2628 new_size
= old_size
+ pad_size
;
2629 new_dyn
= talloc_zero_array(req
->out
.vector
,
2631 if (new_dyn
== NULL
) {
2632 return smbd_smb2_request_error(req
,
2633 NT_STATUS_NO_MEMORY
);
2636 memcpy(new_dyn
, old_dyn
, old_size
);
2637 memset(new_dyn
+ old_size
, 0, pad_size
);
2639 outdyn_v
->iov_base
= (void *)new_dyn
;
2640 outdyn_v
->iov_len
= new_size
;
2642 next_command_ofs
+= pad_size
;
2645 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
2647 return smbd_smb2_request_reply(req
);
2650 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
2653 const char *location
)
2656 uint8_t *outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
2658 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2659 req
->current_idx
, nt_errstr(status
), info
? " +info" : "",
2662 body
.data
= outhdr
+ SMB2_HDR_BODY
;
2664 SSVAL(body
.data
, 0, 9);
2667 SIVAL(body
.data
, 0x04, info
->length
);
2669 /* Allocated size of req->out.vector[i].iov_base
2670 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2671 * 1 byte without having to do an alloc.
2673 info
= talloc_zero_array(req
->out
.vector
,
2677 return NT_STATUS_NO_MEMORY
;
2679 info
->data
= ((uint8_t *)outhdr
) +
2680 OUTVEC_ALLOC_SIZE
- 1;
2682 SCVAL(info
->data
, 0, 0);
2686 * if a request fails, all other remaining
2687 * compounded requests should fail too
2689 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
2691 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
2695 struct smbd_smb2_send_oplock_break_state
{
2696 struct smbd_server_connection
*sconn
;
2697 uint8_t buf
[NBT_HDR_SIZE
+ SMB2_TF_HDR_SIZE
+ SMB2_HDR_BODY
+ 0x18];
2698 struct iovec vector
[1+SMBD_SMB2_NUM_IOV_PER_REQ
];
2701 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
);
2703 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
2704 struct smbXsrv_session
*session
,
2705 struct smbXsrv_tcon
*tcon
,
2706 struct smbXsrv_open
*op
,
2707 uint8_t oplock_level
)
2709 struct smbd_smb2_send_oplock_break_state
*state
;
2710 struct smbXsrv_connection
*conn
= sconn
->conn
;
2711 struct tevent_req
*subreq
;
2719 bool do_encryption
= session
->global
->encryption_required
;
2720 uint64_t nonce_high
= 0;
2721 uint64_t nonce_low
= 0;
2723 if (tcon
->global
->encryption_required
) {
2724 do_encryption
= true;
2727 state
= talloc(sconn
, struct smbd_smb2_send_oplock_break_state
);
2728 if (state
== NULL
) {
2729 return NT_STATUS_NO_MEMORY
;
2731 state
->sconn
= sconn
;
2733 tf
= state
->buf
+ NBT_HDR_SIZE
;
2734 tf_len
= SMB2_TF_HDR_SIZE
;
2736 body
= hdr
+ SMB2_HDR_BODY
;
2738 dyn
= body
+ body_len
;
2741 if (do_encryption
) {
2742 nonce_high
= session
->nonce_high
;
2743 nonce_low
= session
->nonce_low
;
2745 session
->nonce_low
+= 1;
2746 if (session
->nonce_low
== 0) {
2747 session
->nonce_low
+= 1;
2748 session
->nonce_high
+= 1;
2752 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
2753 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
2754 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
2755 SBVAL(tf
, SMB2_TF_SESSION_ID
, session
->global
->session_wire_id
);
2757 SIVAL(hdr
, 0, SMB2_MAGIC
);
2758 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
2759 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
2760 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
2761 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
2762 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
2763 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
2764 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
2765 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
2766 SIVAL(hdr
, SMB2_HDR_PID
, 0);
2767 SIVAL(hdr
, SMB2_HDR_TID
, 0);
2768 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
2769 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
2771 SSVAL(body
, 0x00, body_len
);
2773 SCVAL(body
, 0x02, oplock_level
);
2774 SCVAL(body
, 0x03, 0); /* reserved */
2775 SIVAL(body
, 0x04, 0); /* reserved */
2776 SBVAL(body
, 0x08, op
->global
->open_persistent_id
);
2777 SBVAL(body
, 0x10, op
->global
->open_volatile_id
);
2779 state
->vector
[0].iov_base
= (void *)state
->buf
;
2780 state
->vector
[0].iov_len
= NBT_HDR_SIZE
;
2782 if (do_encryption
) {
2783 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= tf
;
2784 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= tf_len
;
2786 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
2787 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
2790 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
2791 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
2793 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
2794 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_len
= body_len
;
2796 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
2797 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_len
= dyn_len
;
2799 smb2_setup_nbt_length(state
->vector
, 1 + SMBD_SMB2_NUM_IOV_PER_REQ
);
2801 if (do_encryption
) {
2803 DATA_BLOB encryption_key
= session
->global
->encryption_key
;
2805 status
= smb2_signing_encrypt_pdu(encryption_key
,
2807 &state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
],
2808 SMBD_SMB2_NUM_IOV_PER_REQ
);
2809 if (!NT_STATUS_IS_OK(status
)) {
2814 subreq
= tstream_writev_queue_send(state
,
2817 sconn
->smb2
.send_queue
,
2819 ARRAY_SIZE(state
->vector
));
2820 if (subreq
== NULL
) {
2821 return NT_STATUS_NO_MEMORY
;
2823 tevent_req_set_callback(subreq
,
2824 smbd_smb2_oplock_break_writev_done
,
2827 return NT_STATUS_OK
;
2830 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
)
2832 struct smbd_smb2_send_oplock_break_state
*state
=
2833 tevent_req_callback_data(subreq
,
2834 struct smbd_smb2_send_oplock_break_state
);
2835 struct smbd_server_connection
*sconn
= state
->sconn
;
2839 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
2840 TALLOC_FREE(subreq
);
2842 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
2843 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2850 struct smbd_smb2_request_read_state
{
2851 struct tevent_context
*ev
;
2852 struct smbd_server_connection
*sconn
;
2853 struct smbd_smb2_request
*smb2_req
;
2855 uint8_t nbt
[NBT_HDR_SIZE
];
2862 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2864 TALLOC_CTX
*mem_ctx
,
2865 struct iovec
**_vector
,
2867 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
);
2869 static struct tevent_req
*smbd_smb2_request_read_send(TALLOC_CTX
*mem_ctx
,
2870 struct tevent_context
*ev
,
2871 struct smbd_server_connection
*sconn
)
2873 struct tevent_req
*req
;
2874 struct smbd_smb2_request_read_state
*state
;
2875 struct tevent_req
*subreq
;
2877 req
= tevent_req_create(mem_ctx
, &state
,
2878 struct smbd_smb2_request_read_state
);
2883 state
->sconn
= sconn
;
2885 state
->smb2_req
= smbd_smb2_request_allocate(state
);
2886 if (tevent_req_nomem(state
->smb2_req
, req
)) {
2887 return tevent_req_post(req
, ev
);
2889 state
->smb2_req
->sconn
= sconn
;
2891 subreq
= tstream_readv_pdu_queue_send(state
->smb2_req
,
2893 state
->sconn
->smb2
.stream
,
2894 state
->sconn
->smb2
.recv_queue
,
2895 smbd_smb2_request_next_vector
,
2897 if (tevent_req_nomem(subreq
, req
)) {
2898 return tevent_req_post(req
, ev
);
2900 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
2905 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2907 TALLOC_CTX
*mem_ctx
,
2908 struct iovec
**_vector
,
2911 struct smbd_smb2_request_read_state
*state
=
2912 talloc_get_type_abort(private_data
,
2913 struct smbd_smb2_request_read_state
);
2914 struct iovec
*vector
;
2916 if (state
->pktlen
> 0) {
2917 /* if there're no remaining bytes, we're done */
2923 if (!state
->hdr
.done
) {
2925 * first we need to get the NBT header
2927 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2928 if (vector
== NULL
) {
2932 vector
[0].iov_base
= (void *)state
->hdr
.nbt
;
2933 vector
[0].iov_len
= NBT_HDR_SIZE
;
2938 state
->hdr
.done
= true;
2943 * Now we analyze the NBT header
2945 state
->pktlen
= smb2_len(state
->hdr
.nbt
);
2947 if (state
->pktlen
== 0) {
2948 /* if there're no remaining bytes, we're done */
2954 state
->pktbuf
= talloc_array(state
->smb2_req
, uint8_t, state
->pktlen
);
2955 if (state
->pktbuf
== NULL
) {
2959 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2960 if (vector
== NULL
) {
2964 vector
[0].iov_base
= (void *)state
->pktbuf
;
2965 vector
[0].iov_len
= state
->pktlen
;
2972 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
)
2974 struct tevent_req
*req
=
2975 tevent_req_callback_data(subreq
,
2977 struct smbd_smb2_request_read_state
*state
=
2978 tevent_req_data(req
,
2979 struct smbd_smb2_request_read_state
);
2985 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
2986 TALLOC_FREE(subreq
);
2988 status
= map_nt_error_from_unix(sys_errno
);
2989 tevent_req_nterror(req
, status
);
2993 if (state
->hdr
.nbt
[0] != 0x00) {
2994 DEBUG(1,("smbd_smb2_request_read_done: ignore NBT[0x%02X] msg\n",
2995 state
->hdr
.nbt
[0]));
2997 ZERO_STRUCT(state
->hdr
);
2998 TALLOC_FREE(state
->pktbuf
);
3001 subreq
= tstream_readv_pdu_queue_send(state
->smb2_req
,
3003 state
->sconn
->smb2
.stream
,
3004 state
->sconn
->smb2
.recv_queue
,
3005 smbd_smb2_request_next_vector
,
3007 if (tevent_req_nomem(subreq
, req
)) {
3010 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
3014 state
->smb2_req
->request_time
= timeval_current();
3015 now
= timeval_to_nttime(&state
->smb2_req
->request_time
);
3017 status
= smbd_smb2_inbuf_parse_compound(state
->smb2_req
->sconn
->conn
,
3022 &state
->smb2_req
->in
.vector
,
3023 &state
->smb2_req
->in
.vector_count
);
3024 if (tevent_req_nterror(req
, status
)) {
3028 state
->smb2_req
->current_idx
= 1;
3030 tevent_req_done(req
);
3033 static NTSTATUS
smbd_smb2_request_read_recv(struct tevent_req
*req
,
3034 TALLOC_CTX
*mem_ctx
,
3035 struct smbd_smb2_request
**_smb2_req
)
3037 struct smbd_smb2_request_read_state
*state
=
3038 tevent_req_data(req
,
3039 struct smbd_smb2_request_read_state
);
3042 if (tevent_req_is_nterror(req
, &status
)) {
3043 tevent_req_received(req
);
3047 *_smb2_req
= talloc_move(mem_ctx
, &state
->smb2_req
);
3048 tevent_req_received(req
);
3049 return NT_STATUS_OK
;
3052 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
);
3054 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
)
3056 size_t max_send_queue_len
;
3057 size_t cur_send_queue_len
;
3058 struct tevent_req
*subreq
;
3060 if (sconn
->smb2
.compound_related_in_progress
) {
3062 * Can't read another until the related
3065 return NT_STATUS_OK
;
3068 if (tevent_queue_length(sconn
->smb2
.recv_queue
) > 0) {
3070 * if there is already a smbd_smb2_request_read
3071 * pending, we are done.
3073 return NT_STATUS_OK
;
3076 max_send_queue_len
= MAX(1, sconn
->smb2
.max_credits
/16);
3077 cur_send_queue_len
= tevent_queue_length(sconn
->smb2
.send_queue
);
3079 if (cur_send_queue_len
> max_send_queue_len
) {
3081 * if we have a lot of requests to send,
3082 * we wait until they are on the wire until we
3083 * ask for the next request.
3085 return NT_STATUS_OK
;
3088 /* ask for the next request */
3089 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->ev_ctx
, sconn
);
3090 if (subreq
== NULL
) {
3091 return NT_STATUS_NO_MEMORY
;
3093 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);
3095 return NT_STATUS_OK
;
3098 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
3099 uint8_t *inbuf
, size_t size
)
3102 struct smbd_smb2_request
*req
= NULL
;
3104 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3105 (unsigned int)size
));
3107 status
= smbd_initialize_smb2(sconn
);
3108 if (!NT_STATUS_IS_OK(status
)) {
3109 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3113 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
3114 if (!NT_STATUS_IS_OK(status
)) {
3115 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3119 status
= smbd_smb2_request_validate(req
);
3120 if (!NT_STATUS_IS_OK(status
)) {
3121 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3125 status
= smbd_smb2_request_setup_out(req
);
3126 if (!NT_STATUS_IS_OK(status
)) {
3127 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3131 status
= smbd_smb2_request_dispatch(req
);
3132 if (!NT_STATUS_IS_OK(status
)) {
3133 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3137 status
= smbd_smb2_request_next_incoming(sconn
);
3138 if (!NT_STATUS_IS_OK(status
)) {
3139 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3143 sconn
->num_requests
++;
3146 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
)
3148 struct smbd_server_connection
*sconn
= tevent_req_callback_data(subreq
,
3149 struct smbd_server_connection
);
3151 struct smbd_smb2_request
*req
= NULL
;
3153 status
= smbd_smb2_request_read_recv(subreq
, sconn
, &req
);
3154 TALLOC_FREE(subreq
);
3155 if (!NT_STATUS_IS_OK(status
)) {
3156 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
3157 nt_errstr(status
)));
3158 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3162 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
3163 req
->current_idx
, req
->in
.vector_count
));
3165 status
= smbd_smb2_request_validate(req
);
3166 if (!NT_STATUS_IS_OK(status
)) {
3167 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3171 status
= smbd_smb2_request_setup_out(req
);
3172 if (!NT_STATUS_IS_OK(status
)) {
3173 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3177 status
= smbd_smb2_request_dispatch(req
);
3178 if (!NT_STATUS_IS_OK(status
)) {
3179 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3183 status
= smbd_smb2_request_next_incoming(sconn
);
3184 if (!NT_STATUS_IS_OK(status
)) {
3185 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3189 sconn
->num_requests
++;
3191 /* The timeout_processing function isn't run nearly
3192 often enough to implement 'max log size' without
3193 overrunning the size of the file by many megabytes.
3194 This is especially true if we are running at debug
3195 level 10. Checking every 50 SMB2s is a nice
3196 tradeoff of performance vs log file size overrun. */
3198 if ((sconn
->num_requests
% 50) == 0 &&
3199 need_to_check_log_size()) {
3200 change_to_root_user();