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 static void smbd_smb2_connection_handler(struct tevent_context
*ev
,
34 struct tevent_fd
*fde
,
37 static NTSTATUS
smbd_smb2_flush_send_queue(struct smbd_server_connection
*sconn
);
39 static const struct smbd_smb2_dispatch_table
{
46 bool allow_invalid_fileid
;
47 } smbd_smb2_table
[] = {
48 #define _OP(o) .opcode = o, .name = #o
53 _OP(SMB2_OP_SESSSETUP
),
63 * This call needs to be run as root.
65 * smbd_smb2_request_process_tcon()
66 * calls make_connection_snum(), which will call
67 * change_to_user(), when needed.
101 .need_session
= true,
106 .need_session
= true,
109 .allow_invalid_fileid
= true,
114 _OP(SMB2_OP_KEEPALIVE
),
118 .need_session
= true,
123 .need_session
= true,
127 _OP(SMB2_OP_GETINFO
),
128 .need_session
= true,
132 _OP(SMB2_OP_SETINFO
),
133 .need_session
= true,
138 .need_session
= true,
143 * as LEASE breaks does not
149 const char *smb2_opcode_name(uint16_t opcode
)
151 if (opcode
>= ARRAY_SIZE(smbd_smb2_table
)) {
152 return "Bad SMB2 opcode";
154 return smbd_smb2_table
[opcode
].name
;
157 static const struct smbd_smb2_dispatch_table
*smbd_smb2_call(uint16_t opcode
)
159 const struct smbd_smb2_dispatch_table
*ret
= NULL
;
161 if (opcode
>= ARRAY_SIZE(smbd_smb2_table
)) {
165 ret
= &smbd_smb2_table
[opcode
];
167 SMB_ASSERT(ret
->opcode
== opcode
);
172 static void print_req_vectors(const struct smbd_smb2_request
*req
)
176 for (i
= 0; i
< req
->in
.vector_count
; i
++) {
177 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
179 (unsigned int)req
->in
.vector
[i
].iov_len
);
181 for (i
= 0; i
< req
->out
.vector_count
; i
++) {
182 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
184 (unsigned int)req
->out
.vector
[i
].iov_len
);
188 bool smbd_is_smb2_header(const uint8_t *inbuf
, size_t size
)
190 if (size
< (4 + SMB2_HDR_BODY
)) {
194 if (IVAL(inbuf
, 4) != SMB2_MAGIC
) {
201 static NTSTATUS
smbd_initialize_smb2(struct smbd_server_connection
*sconn
)
203 TALLOC_FREE(sconn
->smb1
.fde
);
205 sconn
->smb2
.send_queue
= NULL
;
207 sconn
->smb2
.seqnum_low
= 0;
208 sconn
->smb2
.seqnum_range
= 1;
209 sconn
->smb2
.credits_granted
= 1;
210 sconn
->smb2
.max_credits
= lp_smb2_max_credits();
211 sconn
->smb2
.credits_bitmap
= bitmap_talloc(sconn
,
212 sconn
->smb2
.max_credits
);
213 if (sconn
->smb2
.credits_bitmap
== NULL
) {
214 return NT_STATUS_NO_MEMORY
;
217 sconn
->smb2
.fde
= tevent_add_fd(sconn
->ev_ctx
,
221 smbd_smb2_connection_handler
,
223 if (sconn
->smb2
.fde
== NULL
) {
224 return NT_STATUS_NO_MEMORY
;
227 /* Ensure child is set to non-blocking mode */
228 set_blocking(sconn
->sock
, false);
232 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
233 #define _smb2_setlen(_buf,len) do { \
234 uint8_t *buf = (uint8_t *)_buf; \
236 buf[1] = ((len)&0xFF0000)>>16; \
237 buf[2] = ((len)&0xFF00)>>8; \
238 buf[3] = (len)&0xFF; \
241 static void smb2_setup_nbt_length(struct iovec
*vector
, int count
)
246 for (i
=1; i
< count
; i
++) {
247 len
+= vector
[i
].iov_len
;
250 _smb2_setlen(vector
[0].iov_base
, len
);
253 static int smbd_smb2_request_destructor(struct smbd_smb2_request
*req
)
255 if (req
->first_key
.length
> 0) {
256 data_blob_clear_free(&req
->first_key
);
258 if (req
->last_key
.length
> 0) {
259 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_tos();
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
);
286 TALLOC_FREE(mem_pool
);
289 req
->last_session_id
= UINT64_MAX
;
290 req
->last_tid
= UINT32_MAX
;
292 talloc_set_destructor(req
, smbd_smb2_request_destructor
);
297 static NTSTATUS
smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection
*conn
,
301 struct smbd_smb2_request
*req
,
305 TALLOC_CTX
*mem_ctx
= req
;
309 uint8_t *first_hdr
= buf
;
310 size_t verified_buflen
= 0;
315 * Note: index '0' is reserved for the transport protocol
317 iov
= req
->in
._vector
;
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_alloc
= NULL
;
331 if (iov
!= req
->in
._vector
) {
335 if (verified_buflen
> taken
) {
336 len
= verified_buflen
- taken
;
343 DEBUG(10, ("%d bytes left, expected at least %d\n",
347 if (IVAL(hdr
, 0) == SMB2_TF_MAGIC
) {
348 struct smbXsrv_session
*s
= NULL
;
350 struct iovec tf_iov
[2];
354 if (conn
->protocol
< PROTOCOL_SMB2_24
) {
355 DEBUG(10, ("Got SMB2_TRANSFORM header, "
356 "but dialect[0x%04X] is used\n",
357 conn
->smb2
.server
.dialect
));
361 if (!(conn
->smb2
.server
.capabilities
& SMB2_CAP_ENCRYPTION
)) {
362 DEBUG(10, ("Got SMB2_TRANSFORM header, "
363 "but not negotiated "
364 "client[0x%08X] server[0x%08X]\n",
365 conn
->smb2
.client
.capabilities
,
366 conn
->smb2
.server
.capabilities
));
370 if (len
< SMB2_TF_HDR_SIZE
) {
371 DEBUG(1, ("%d bytes left, expected at least %d\n",
372 (int)len
, SMB2_TF_HDR_SIZE
));
376 tf_len
= SMB2_TF_HDR_SIZE
;
379 hdr
= first_hdr
+ taken
;
380 enc_len
= IVAL(tf
, SMB2_TF_MSG_SIZE
);
381 uid
= BVAL(tf
, SMB2_TF_SESSION_ID
);
383 if (len
< SMB2_TF_HDR_SIZE
+ enc_len
) {
384 DEBUG(1, ("%d bytes left, expected at least %d\n",
386 (int)(SMB2_TF_HDR_SIZE
+ enc_len
)));
390 status
= smb2srv_session_lookup(conn
, uid
, now
, &s
);
392 DEBUG(1, ("invalid session[%llu] in "
393 "SMB2_TRANSFORM header\n",
394 (unsigned long long)uid
));
395 TALLOC_FREE(iov_alloc
);
396 return NT_STATUS_USER_SESSION_DELETED
;
399 tf_iov
[0].iov_base
= (void *)tf
;
400 tf_iov
[0].iov_len
= tf_len
;
401 tf_iov
[1].iov_base
= (void *)hdr
;
402 tf_iov
[1].iov_len
= enc_len
;
404 status
= smb2_signing_decrypt_pdu(s
->global
->decryption_key
,
407 if (!NT_STATUS_IS_OK(status
)) {
408 TALLOC_FREE(iov_alloc
);
412 verified_buflen
= taken
+ enc_len
;
417 * We need the header plus the body length field
420 if (len
< SMB2_HDR_BODY
+ 2) {
421 DEBUG(10, ("%d bytes left, expected at least %d\n",
422 (int)len
, SMB2_HDR_BODY
));
425 if (IVAL(hdr
, 0) != SMB2_MAGIC
) {
426 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
430 if (SVAL(hdr
, 4) != SMB2_HDR_BODY
) {
431 DEBUG(10, ("Got HDR len %d, expected %d\n",
432 SVAL(hdr
, 4), SMB2_HDR_BODY
));
437 next_command_ofs
= IVAL(hdr
, SMB2_HDR_NEXT_COMMAND
);
438 body_size
= SVAL(hdr
, SMB2_HDR_BODY
);
440 if (next_command_ofs
!= 0) {
441 if (next_command_ofs
< (SMB2_HDR_BODY
+ 2)) {
444 if (next_command_ofs
> full_size
) {
447 full_size
= next_command_ofs
;
454 if (body_size
> (full_size
- SMB2_HDR_BODY
)) {
456 * let the caller handle the error
458 body_size
= full_size
- SMB2_HDR_BODY
;
460 body
= hdr
+ SMB2_HDR_BODY
;
461 dyn
= body
+ body_size
;
462 dyn_size
= full_size
- (SMB2_HDR_BODY
+ body_size
);
464 if (num_iov
>= ARRAY_SIZE(req
->in
._vector
)) {
465 struct iovec
*iov_tmp
= NULL
;
467 iov_tmp
= talloc_realloc(mem_ctx
, iov_alloc
,
470 SMBD_SMB2_NUM_IOV_PER_REQ
);
471 if (iov_tmp
== NULL
) {
472 TALLOC_FREE(iov_alloc
);
473 return NT_STATUS_NO_MEMORY
;
476 if (iov_alloc
== NULL
) {
479 sizeof(req
->in
._vector
));
485 num_iov
+= SMBD_SMB2_NUM_IOV_PER_REQ
;
487 cur
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= tf
;
488 cur
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= tf_len
;
489 cur
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
490 cur
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
491 cur
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
492 cur
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= body_size
;
493 cur
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
494 cur
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= dyn_size
;
504 if (iov
!= req
->in
._vector
) {
507 return NT_STATUS_INVALID_PARAMETER
;
510 static NTSTATUS
smbd_smb2_request_create(struct smbd_server_connection
*sconn
,
511 uint8_t *inbuf
, size_t size
,
512 struct smbd_smb2_request
**_req
)
514 struct smbd_smb2_request
*req
;
515 uint32_t protocol_version
;
516 const uint8_t *inhdr
= NULL
;
518 uint32_t next_command_ofs
;
522 if (size
< (4 + SMB2_HDR_BODY
+ 2)) {
523 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size
));
524 return NT_STATUS_INVALID_PARAMETER
;
529 protocol_version
= IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
);
530 if (protocol_version
!= SMB2_MAGIC
) {
531 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
533 return NT_STATUS_INVALID_PARAMETER
;
536 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
537 if (cmd
!= SMB2_OP_NEGPROT
) {
538 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
540 return NT_STATUS_INVALID_PARAMETER
;
543 next_command_ofs
= IVAL(inhdr
, SMB2_HDR_NEXT_COMMAND
);
544 if (next_command_ofs
!= 0) {
545 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
547 return NT_STATUS_INVALID_PARAMETER
;
550 req
= smbd_smb2_request_allocate(sconn
);
552 return NT_STATUS_NO_MEMORY
;
556 talloc_steal(req
, inbuf
);
558 req
->request_time
= timeval_current();
559 now
= timeval_to_nttime(&req
->request_time
);
561 status
= smbd_smb2_inbuf_parse_compound(sconn
->conn
,
563 inbuf
+ NBT_HDR_SIZE
,
565 req
, &req
->in
.vector
,
566 &req
->in
.vector_count
);
567 if (!NT_STATUS_IS_OK(status
)) {
572 req
->current_idx
= 1;
578 static bool smb2_validate_sequence_number(struct smbd_server_connection
*sconn
,
579 uint64_t message_id
, uint64_t seq_id
)
581 struct bitmap
*credits_bm
= sconn
->smb2
.credits_bitmap
;
584 if (seq_id
< sconn
->smb2
.seqnum_low
) {
585 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
586 "%llu (sequence id %llu) "
587 "(granted = %u, low = %llu, range = %u)\n",
588 (unsigned long long)message_id
,
589 (unsigned long long)seq_id
,
590 (unsigned int)sconn
->smb2
.credits_granted
,
591 (unsigned long long)sconn
->smb2
.seqnum_low
,
592 (unsigned int)sconn
->smb2
.seqnum_range
));
596 if (seq_id
>= sconn
->smb2
.seqnum_low
+ sconn
->smb2
.seqnum_range
) {
597 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
598 "%llu (sequence id %llu) "
599 "(granted = %u, low = %llu, range = %u)\n",
600 (unsigned long long)message_id
,
601 (unsigned long long)seq_id
,
602 (unsigned int)sconn
->smb2
.credits_granted
,
603 (unsigned long long)sconn
->smb2
.seqnum_low
,
604 (unsigned int)sconn
->smb2
.seqnum_range
));
608 offset
= seq_id
% sconn
->smb2
.max_credits
;
610 if (bitmap_query(credits_bm
, offset
)) {
611 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
612 "%llu (sequence id %llu) "
613 "(granted = %u, low = %llu, range = %u) "
615 (unsigned long long)message_id
,
616 (unsigned long long)seq_id
,
617 (unsigned int)sconn
->smb2
.credits_granted
,
618 (unsigned long long)sconn
->smb2
.seqnum_low
,
619 (unsigned int)sconn
->smb2
.seqnum_range
,
624 /* Mark the message_ids as seen in the bitmap. */
625 bitmap_set(credits_bm
, offset
);
627 if (seq_id
!= sconn
->smb2
.seqnum_low
) {
632 * Move the window forward by all the message_id's
635 while (bitmap_query(credits_bm
, offset
)) {
636 DEBUG(10,("smb2_validate_sequence_number: clearing "
637 "id %llu (position %u) from bitmap\n",
638 (unsigned long long)(sconn
->smb2
.seqnum_low
),
640 bitmap_clear(credits_bm
, offset
);
642 sconn
->smb2
.seqnum_low
+= 1;
643 sconn
->smb2
.seqnum_range
-= 1;
644 offset
= sconn
->smb2
.seqnum_low
% sconn
->smb2
.max_credits
;
650 static bool smb2_validate_message_id(struct smbd_server_connection
*sconn
,
651 const uint8_t *inhdr
)
653 uint64_t message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
654 uint16_t opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
655 uint16_t credit_charge
= 1;
658 if (opcode
== SMB2_OP_CANCEL
) {
659 /* SMB2_CANCEL requests by definition resend messageids. */
663 if (sconn
->smb2
.supports_multicredit
) {
664 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
665 credit_charge
= MAX(credit_charge
, 1);
668 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
669 "credits_granted %llu, "
670 "seqnum low/range: %llu/%llu\n",
671 (unsigned long long) message_id
,
672 (unsigned long long) credit_charge
,
673 (unsigned long long) sconn
->smb2
.credits_granted
,
674 (unsigned long long) sconn
->smb2
.seqnum_low
,
675 (unsigned long long) sconn
->smb2
.seqnum_range
));
677 if (sconn
->smb2
.credits_granted
< credit_charge
) {
678 DEBUG(0, ("smb2_validate_message_id: client used more "
679 "credits than granted, mid %llu, charge %llu, "
680 "credits_granted %llu, "
681 "seqnum low/range: %llu/%llu\n",
682 (unsigned long long) message_id
,
683 (unsigned long long) credit_charge
,
684 (unsigned long long) sconn
->smb2
.credits_granted
,
685 (unsigned long long) sconn
->smb2
.seqnum_low
,
686 (unsigned long long) sconn
->smb2
.seqnum_range
));
691 * now check the message ids
693 * for multi-credit requests we need to check all current mid plus
694 * the implicit mids caused by the credit charge
695 * e.g. current mid = 15, charge 5 => mark 15-19 as used
698 for (i
= 0; i
<= (credit_charge
-1); i
++) {
699 uint64_t id
= message_id
+ i
;
702 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
703 (unsigned long long)message_id
,
705 (unsigned long long)id
));
707 ok
= smb2_validate_sequence_number(sconn
, message_id
, id
);
713 /* substract used credits */
714 sconn
->smb2
.credits_granted
-= credit_charge
;
719 static NTSTATUS
smbd_smb2_request_validate(struct smbd_smb2_request
*req
)
724 count
= req
->in
.vector_count
;
726 if (count
< 1 + SMBD_SMB2_NUM_IOV_PER_REQ
) {
727 /* It's not a SMB2 request */
728 return NT_STATUS_INVALID_PARAMETER
;
731 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
732 struct iovec
*hdr
= SMBD_SMB2_IDX_HDR_IOV(req
,in
,idx
);
733 struct iovec
*body
= SMBD_SMB2_IDX_BODY_IOV(req
,in
,idx
);
734 const uint8_t *inhdr
= NULL
;
736 if (hdr
->iov_len
!= SMB2_HDR_BODY
) {
737 return NT_STATUS_INVALID_PARAMETER
;
740 if (body
->iov_len
< 2) {
741 return NT_STATUS_INVALID_PARAMETER
;
744 inhdr
= (const uint8_t *)hdr
->iov_base
;
746 /* Check the SMB2 header */
747 if (IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
) != SMB2_MAGIC
) {
748 return NT_STATUS_INVALID_PARAMETER
;
751 if (!smb2_validate_message_id(req
->sconn
, inhdr
)) {
752 return NT_STATUS_INVALID_PARAMETER
;
759 static void smb2_set_operation_credit(struct smbd_server_connection
*sconn
,
760 const struct iovec
*in_vector
,
761 struct iovec
*out_vector
)
763 const uint8_t *inhdr
= (const uint8_t *)in_vector
->iov_base
;
764 uint8_t *outhdr
= (uint8_t *)out_vector
->iov_base
;
765 uint16_t credit_charge
= 1;
766 uint16_t credits_requested
;
770 uint16_t credits_granted
= 0;
771 uint64_t credits_possible
;
772 uint16_t current_max_credits
;
775 * first we grant only 1/16th of the max range.
777 * Windows also starts with the 1/16th and then grants
778 * more later. I was only able to trigger higher
779 * values, when using a very high credit charge.
781 * TODO: scale up depending on load, free memory
783 * Maybe also on the relationship between number
784 * of requests and the used sequence number.
785 * Which means we would grant more credits
786 * for client which use multi credit requests.
788 current_max_credits
= sconn
->smb2
.max_credits
/ 16;
789 current_max_credits
= MAX(current_max_credits
, 1);
791 if (sconn
->smb2
.supports_multicredit
) {
792 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
793 credit_charge
= MAX(credit_charge
, 1);
796 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
797 credits_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
798 out_flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
799 out_status
= NT_STATUS(IVAL(outhdr
, SMB2_HDR_STATUS
));
801 SMB_ASSERT(sconn
->smb2
.max_credits
>= sconn
->smb2
.credits_granted
);
803 if (sconn
->smb2
.max_credits
< credit_charge
) {
804 smbd_server_connection_terminate(sconn
,
805 "client error: credit charge > max credits\n");
809 if (out_flags
& SMB2_HDR_FLAG_ASYNC
) {
811 * In case we already send an async interim
812 * response, we should not grant
813 * credits on the final response.
816 } else if (credits_requested
> 0) {
817 uint16_t additional_max
= 0;
818 uint16_t additional_credits
= credits_requested
- 1;
821 case SMB2_OP_NEGPROT
:
823 case SMB2_OP_SESSSETUP
:
825 * Windows 2012 RC1 starts to grant
827 * with a successful session setup
829 if (NT_STATUS_IS_OK(out_status
)) {
835 * We match windows and only grant additional credits
842 additional_credits
= MIN(additional_credits
, additional_max
);
844 credits_granted
= credit_charge
+ additional_credits
;
845 } else if (sconn
->smb2
.credits_granted
== 0) {
847 * Make sure the client has always at least one credit
853 * sequence numbers should not wrap
855 * 1. calculate the possible credits until
856 * the sequence numbers start to wrap on 64-bit.
858 * 2. UINT64_MAX is used for Break Notifications.
860 * 2. truncate the possible credits to the maximum
861 * credits we want to grant to the client in total.
863 * 3. remove the range we'll already granted to the client
864 * this makes sure the client consumes the lowest sequence
865 * number, before we can grant additional credits.
867 credits_possible
= UINT64_MAX
- sconn
->smb2
.seqnum_low
;
868 if (credits_possible
> 0) {
869 /* remove UINT64_MAX */
870 credits_possible
-= 1;
872 credits_possible
= MIN(credits_possible
, current_max_credits
);
873 credits_possible
-= sconn
->smb2
.seqnum_range
;
875 credits_granted
= MIN(credits_granted
, credits_possible
);
877 SSVAL(outhdr
, SMB2_HDR_CREDIT
, credits_granted
);
878 sconn
->smb2
.credits_granted
+= credits_granted
;
879 sconn
->smb2
.seqnum_range
+= credits_granted
;
881 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
882 "granted %u, current possible/max %u/%u, "
883 "total granted/max/low/range %u/%u/%llu/%u\n",
884 (unsigned int)credits_requested
,
885 (unsigned int)credit_charge
,
886 (unsigned int)credits_granted
,
887 (unsigned int)credits_possible
,
888 (unsigned int)current_max_credits
,
889 (unsigned int)sconn
->smb2
.credits_granted
,
890 (unsigned int)sconn
->smb2
.max_credits
,
891 (unsigned long long)sconn
->smb2
.seqnum_low
,
892 (unsigned int)sconn
->smb2
.seqnum_range
));
895 static void smb2_calculate_credits(const struct smbd_smb2_request
*inreq
,
896 struct smbd_smb2_request
*outreq
)
899 uint16_t total_credits
= 0;
901 count
= outreq
->out
.vector_count
;
903 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
904 struct iovec
*inhdr_v
= SMBD_SMB2_IDX_HDR_IOV(inreq
,in
,idx
);
905 struct iovec
*outhdr_v
= SMBD_SMB2_IDX_HDR_IOV(outreq
,out
,idx
);
906 uint8_t *outhdr
= (uint8_t *)outhdr_v
->iov_base
;
908 smb2_set_operation_credit(outreq
->sconn
, inhdr_v
, outhdr_v
);
910 /* To match Windows, count up what we
912 total_credits
+= SVAL(outhdr
, SMB2_HDR_CREDIT
);
913 /* Set to zero in all but the last reply. */
914 if (idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
< count
) {
915 SSVAL(outhdr
, SMB2_HDR_CREDIT
, 0);
917 SSVAL(outhdr
, SMB2_HDR_CREDIT
, total_credits
);
922 DATA_BLOB
smbd_smb2_generate_outbody(struct smbd_smb2_request
*req
, size_t size
)
924 if (req
->current_idx
<= 1) {
925 if (size
<= sizeof(req
->out
._body
)) {
926 return data_blob_const(req
->out
._body
, size
);
930 return data_blob_talloc(req
, NULL
, size
);
933 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
)
936 struct iovec
*vector
;
940 count
= req
->in
.vector_count
;
941 if (count
<= ARRAY_SIZE(req
->out
._vector
)) {
943 vector
= req
->out
._vector
;
945 vector
= talloc_zero_array(req
, struct iovec
, count
);
946 if (vector
== NULL
) {
947 return NT_STATUS_NO_MEMORY
;
952 vector
[0].iov_base
= req
->out
.nbt_hdr
;
953 vector
[0].iov_len
= 4;
954 SIVAL(req
->out
.nbt_hdr
, 0, 0);
956 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
957 struct iovec
*inhdr_v
= SMBD_SMB2_IDX_HDR_IOV(req
,in
,idx
);
958 const uint8_t *inhdr
= (const uint8_t *)inhdr_v
->iov_base
;
959 uint8_t *outhdr
= NULL
;
960 uint8_t *outbody
= NULL
;
961 uint32_t next_command_ofs
= 0;
962 struct iovec
*current
= &vector
[idx
];
964 if ((idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
) < count
) {
965 /* we have a next command -
966 * setup for the error case. */
967 next_command_ofs
= SMB2_HDR_BODY
+ 9;
971 outhdr
= req
->out
._hdr
;
973 outhdr
= talloc_zero_array(mem_ctx
, uint8_t,
975 if (outhdr
== NULL
) {
976 return NT_STATUS_NO_MEMORY
;
980 outbody
= outhdr
+ SMB2_HDR_BODY
;
983 * SMBD_SMB2_TF_IOV_OFS might be used later
985 current
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
986 current
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
988 current
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= (void *)outhdr
;
989 current
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
991 current
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= (void *)outbody
;
992 current
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= 8;
994 current
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= NULL
;
995 current
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= 0;
997 /* setup the SMB2 header */
998 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
999 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1000 SSVAL(outhdr
, SMB2_HDR_CREDIT_CHARGE
,
1001 SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
));
1002 SIVAL(outhdr
, SMB2_HDR_STATUS
,
1003 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
1004 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
1005 SVAL(inhdr
, SMB2_HDR_OPCODE
));
1006 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
1007 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
1008 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
1009 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
1010 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
1011 SIVAL(outhdr
, SMB2_HDR_PID
,
1012 IVAL(inhdr
, SMB2_HDR_PID
));
1013 SIVAL(outhdr
, SMB2_HDR_TID
,
1014 IVAL(inhdr
, SMB2_HDR_TID
));
1015 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
1016 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
1017 memcpy(outhdr
+ SMB2_HDR_SIGNATURE
,
1018 inhdr
+ SMB2_HDR_SIGNATURE
, 16);
1020 /* setup error body header */
1021 SSVAL(outbody
, 0x00, 0x08 + 1);
1022 SSVAL(outbody
, 0x02, 0);
1023 SIVAL(outbody
, 0x04, 0);
1026 req
->out
.vector
= vector
;
1027 req
->out
.vector_count
= count
;
1029 /* setup the length of the NBT packet */
1030 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
1032 DLIST_ADD_END(req
->sconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
1034 return NT_STATUS_OK
;
1037 void smbd_server_connection_terminate_ex(struct smbd_server_connection
*sconn
,
1039 const char *location
)
1041 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1043 exit_server_cleanly(reason
);
1046 static bool dup_smb2_vec4(TALLOC_CTX
*ctx
,
1047 struct iovec
*outvec
,
1048 const struct iovec
*srcvec
)
1050 const uint8_t *srctf
;
1052 const uint8_t *srchdr
;
1054 const uint8_t *srcbody
;
1056 const uint8_t *expected_srcbody
;
1057 const uint8_t *srcdyn
;
1059 const uint8_t *expected_srcdyn
;
1065 srctf
= (const uint8_t *)srcvec
[SMBD_SMB2_TF_IOV_OFS
].iov_base
;
1066 srctf_len
= srcvec
[SMBD_SMB2_TF_IOV_OFS
].iov_len
;
1067 srchdr
= (const uint8_t *)srcvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
;
1068 srchdr_len
= srcvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
;
1069 srcbody
= (const uint8_t *)srcvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
;
1070 srcbody_len
= srcvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
;
1071 expected_srcbody
= srchdr
+ SMB2_HDR_BODY
;
1072 srcdyn
= (const uint8_t *)srcvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
;
1073 srcdyn_len
= srcvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
;
1074 expected_srcdyn
= srcbody
+ 8;
1076 if ((srctf_len
!= SMB2_TF_HDR_SIZE
) && (srctf_len
!= 0)) {
1080 if (srchdr_len
!= SMB2_HDR_BODY
) {
1084 if (srctf_len
== SMB2_TF_HDR_SIZE
) {
1085 dsttf
= talloc_memdup(ctx
, srctf
, SMB2_TF_HDR_SIZE
);
1086 if (dsttf
== NULL
) {
1092 outvec
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= (void *)dsttf
;
1093 outvec
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= srctf_len
;
1095 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1096 * be allocated with size OUTVEC_ALLOC_SIZE. */
1098 dsthdr
= talloc_memdup(ctx
, srchdr
, OUTVEC_ALLOC_SIZE
);
1099 if (dsthdr
== NULL
) {
1102 outvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= (void *)dsthdr
;
1103 outvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
1106 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1107 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1108 * then duplicate this. Else use talloc_memdup().
1111 if ((srcbody
== expected_srcbody
) && (srcbody_len
== 8)) {
1112 dstbody
= dsthdr
+ SMB2_HDR_BODY
;
1114 dstbody
= talloc_memdup(ctx
, srcbody
, srcbody_len
);
1115 if (dstbody
== NULL
) {
1119 outvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= (void *)dstbody
;
1120 outvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= srcbody_len
;
1123 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1125 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1126 * then duplicate this. Else use talloc_memdup().
1129 if ((srcdyn
== expected_srcdyn
) && (srcdyn_len
== 1)) {
1130 dstdyn
= dsthdr
+ SMB2_HDR_BODY
+ 8;
1131 } else if (srcdyn
== NULL
) {
1134 dstdyn
= talloc_memdup(ctx
, srcdyn
, srcdyn_len
);
1135 if (dstdyn
== NULL
) {
1139 outvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= (void *)dstdyn
;
1140 outvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= srcdyn_len
;
1145 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
1147 struct smbd_smb2_request
*newreq
= NULL
;
1148 struct iovec
*outvec
= NULL
;
1149 int count
= req
->out
.vector_count
;
1152 newreq
= smbd_smb2_request_allocate(req
->sconn
);
1157 newreq
->sconn
= req
->sconn
;
1158 newreq
->session
= req
->session
;
1159 newreq
->do_encryption
= req
->do_encryption
;
1160 newreq
->do_signing
= req
->do_signing
;
1161 newreq
->current_idx
= req
->current_idx
;
1163 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
1165 TALLOC_FREE(newreq
);
1168 newreq
->out
.vector
= outvec
;
1169 newreq
->out
.vector_count
= count
;
1171 /* Setup the outvec's identically to req. */
1172 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
1173 outvec
[0].iov_len
= 4;
1174 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
1176 /* Setup the vectors identically to the ones in req. */
1177 for (i
= 1; i
< count
; i
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
1178 if (!dup_smb2_vec4(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
1185 TALLOC_FREE(newreq
);
1189 smb2_setup_nbt_length(newreq
->out
.vector
,
1190 newreq
->out
.vector_count
);
1195 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
1197 struct smbd_server_connection
*sconn
= req
->sconn
;
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
->queue_entry
.mem_ctx
= nreq
;
1262 nreq
->queue_entry
.vector
= nreq
->out
.vector
;
1263 nreq
->queue_entry
.count
= nreq
->out
.vector_count
;
1264 DLIST_ADD_END(nreq
->sconn
->smb2
.send_queue
, &nreq
->queue_entry
, NULL
);
1265 nreq
->sconn
->smb2
.send_queue_len
++;
1267 status
= smbd_smb2_flush_send_queue(sconn
);
1268 if (!NT_STATUS_IS_OK(status
)) {
1272 return NT_STATUS_OK
;
1275 struct smbd_smb2_request_pending_state
{
1276 struct smbd_server_connection
*sconn
;
1277 struct smbd_smb2_send_queue queue_entry
;
1278 uint8_t buf
[NBT_HDR_SIZE
+ SMB2_TF_HDR_SIZE
+ SMB2_HDR_BODY
+ 0x08 + 1];
1279 struct iovec vector
[1 + SMBD_SMB2_NUM_IOV_PER_REQ
];
1282 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
1283 struct tevent_timer
*te
,
1284 struct timeval current_time
,
1285 void *private_data
);
1287 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
1288 struct tevent_req
*subreq
,
1289 uint32_t defer_time
)
1292 struct timeval defer_endtime
;
1293 uint8_t *outhdr
= NULL
;
1296 if (!tevent_req_is_in_progress(subreq
)) {
1298 * This is a performance optimization,
1299 * it avoids one tevent_loop iteration,
1300 * which means we avoid one
1301 * talloc_stackframe_pool/talloc_free pair.
1303 tevent_req_notify_callback(subreq
);
1304 return NT_STATUS_OK
;
1307 req
->subreq
= subreq
;
1310 if (req
->async_te
) {
1311 /* We're already async. */
1312 return NT_STATUS_OK
;
1315 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1316 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1317 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1318 /* We're already async. */
1319 return NT_STATUS_OK
;
1322 if (req
->in
.vector_count
> req
->current_idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
) {
1324 * We're trying to go async in a compound
1326 * This is only allowed for opens that
1327 * cause an oplock break, otherwise it
1328 * is not allowed. See [MS-SMB2].pdf
1329 * note <194> on Section 3.3.5.2.7.
1331 const uint8_t *inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1333 if (SVAL(inhdr
, SMB2_HDR_OPCODE
) != SMB2_OP_CREATE
) {
1335 * Cancel the outstanding request.
1337 bool ok
= tevent_req_cancel(req
->subreq
);
1339 return NT_STATUS_OK
;
1341 TALLOC_FREE(req
->subreq
);
1342 return smbd_smb2_request_error(req
,
1343 NT_STATUS_INTERNAL_ERROR
);
1347 if (DEBUGLEVEL
>= 10) {
1348 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1349 (unsigned int)req
->current_idx
);
1350 print_req_vectors(req
);
1353 if (req
->current_idx
> 1) {
1355 * We're going async in a compound
1356 * chain after the first request has
1357 * already been processed. Send an
1358 * interim response containing the
1359 * set of replies already generated.
1361 int idx
= req
->current_idx
;
1363 status
= smb2_send_async_interim_response(req
);
1364 if (!NT_STATUS_IS_OK(status
)) {
1367 if (req
->first_key
.length
> 0) {
1368 data_blob_clear_free(&req
->first_key
);
1371 req
->current_idx
= 1;
1374 * Re-arrange the in.vectors to remove what
1377 memmove(&req
->in
.vector
[1],
1378 &req
->in
.vector
[idx
],
1379 sizeof(req
->in
.vector
[0])*(req
->in
.vector_count
- idx
));
1380 req
->in
.vector_count
= 1 + (req
->in
.vector_count
- idx
);
1382 /* Re-arrange the out.vectors to match. */
1383 memmove(&req
->out
.vector
[1],
1384 &req
->out
.vector
[idx
],
1385 sizeof(req
->out
.vector
[0])*(req
->out
.vector_count
- idx
));
1386 req
->out
.vector_count
= 1 + (req
->out
.vector_count
- idx
);
1388 if (req
->in
.vector_count
== 1 + SMBD_SMB2_NUM_IOV_PER_REQ
) {
1390 * We only have one remaining request as
1391 * we've processed everything else.
1392 * This is no longer a compound request.
1394 req
->compound_related
= false;
1395 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1396 flags
= (IVAL(outhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
1397 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
);
1400 if (req
->last_key
.length
> 0) {
1401 data_blob_clear_free(&req
->last_key
);
1404 defer_endtime
= timeval_current_ofs_usec(defer_time
);
1405 req
->async_te
= tevent_add_timer(req
->sconn
->ev_ctx
,
1407 smbd_smb2_request_pending_timer
,
1409 if (req
->async_te
== NULL
) {
1410 return NT_STATUS_NO_MEMORY
;
1413 return NT_STATUS_OK
;
1416 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
1417 struct tevent_timer
*te
,
1418 struct timeval current_time
,
1421 struct smbd_smb2_request
*req
=
1422 talloc_get_type_abort(private_data
,
1423 struct smbd_smb2_request
);
1424 struct smbd_server_connection
*sconn
= req
->sconn
;
1425 struct smbd_smb2_request_pending_state
*state
= NULL
;
1426 uint8_t *outhdr
= NULL
;
1427 const uint8_t *inhdr
= NULL
;
1430 uint8_t *hdr
= NULL
;
1431 uint8_t *body
= NULL
;
1432 uint8_t *dyn
= NULL
;
1434 uint64_t session_id
= 0;
1435 uint64_t message_id
= 0;
1436 uint64_t nonce_high
= 0;
1437 uint64_t nonce_low
= 0;
1438 uint64_t async_id
= 0;
1441 TALLOC_FREE(req
->async_te
);
1443 /* Ensure our final reply matches the interim one. */
1444 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1445 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1446 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1447 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1448 session_id
= BVAL(outhdr
, SMB2_HDR_SESSION_ID
);
1450 async_id
= message_id
; /* keep it simple for now... */
1452 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1453 SBVAL(outhdr
, SMB2_HDR_ASYNC_ID
, async_id
);
1455 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1457 smb2_opcode_name(SVAL(inhdr
, SMB2_HDR_OPCODE
)),
1458 (unsigned long long)async_id
));
1461 * What we send is identical to a smbd_smb2_request_error
1462 * packet with an error status of STATUS_PENDING. Make use
1463 * of this fact sometime when refactoring. JRA.
1466 state
= talloc_zero(req
->sconn
, struct smbd_smb2_request_pending_state
);
1467 if (state
== NULL
) {
1468 smbd_server_connection_terminate(req
->sconn
,
1469 nt_errstr(NT_STATUS_NO_MEMORY
));
1472 state
->sconn
= req
->sconn
;
1474 tf
= state
->buf
+ NBT_HDR_SIZE
;
1475 tf_len
= SMB2_TF_HDR_SIZE
;
1477 hdr
= tf
+ SMB2_TF_HDR_SIZE
;
1478 body
= hdr
+ SMB2_HDR_BODY
;
1481 if (req
->do_encryption
) {
1482 struct smbXsrv_session
*x
= req
->session
;
1484 nonce_high
= x
->nonce_high
;
1485 nonce_low
= x
->nonce_low
;
1488 if (x
->nonce_low
== 0) {
1494 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
1495 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
1496 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
1497 SBVAL(tf
, SMB2_TF_SESSION_ID
, session_id
);
1499 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
1500 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1501 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1502 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
1503 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(outhdr
, SMB2_HDR_OPCODE
));
1505 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
);
1506 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1507 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
1508 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
1509 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
1510 BVAL(outhdr
, SMB2_HDR_SESSION_ID
));
1511 memcpy(hdr
+SMB2_HDR_SIGNATURE
,
1512 outhdr
+SMB2_HDR_SIGNATURE
, 16);
1514 SSVAL(body
, 0x00, 0x08 + 1);
1516 SCVAL(body
, 0x02, 0);
1517 SCVAL(body
, 0x03, 0);
1518 SIVAL(body
, 0x04, 0);
1519 /* Match W2K8R2... */
1520 SCVAL(dyn
, 0x00, 0x21);
1522 state
->vector
[0].iov_base
= (void *)state
->buf
;
1523 state
->vector
[0].iov_len
= NBT_HDR_SIZE
;
1525 if (req
->do_encryption
) {
1526 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= tf
;
1527 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= tf_len
;
1529 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
1530 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
1533 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
1534 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
1536 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
1537 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_len
= 8;
1539 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
1540 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_len
= 1;
1542 smb2_setup_nbt_length(state
->vector
, 1 + SMBD_SMB2_NUM_IOV_PER_REQ
);
1544 /* Ensure we correctly go through crediting. Grant
1545 the credits now, and zero credits on the final
1547 smb2_set_operation_credit(req
->sconn
,
1548 SMBD_SMB2_IN_HDR_IOV(req
),
1549 &state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
]);
1551 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1556 for (i
= 0; i
< ARRAY_SIZE(state
->vector
); i
++) {
1557 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1559 (unsigned int)ARRAY_SIZE(state
->vector
),
1560 (unsigned int)state
->vector
[i
].iov_len
);
1564 if (req
->do_encryption
) {
1565 struct smbXsrv_session
*x
= req
->session
;
1566 struct smbXsrv_connection
*conn
= x
->connection
;
1567 DATA_BLOB encryption_key
= x
->global
->encryption_key
;
1569 status
= smb2_signing_encrypt_pdu(encryption_key
,
1571 &state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
],
1572 SMBD_SMB2_NUM_IOV_PER_REQ
);
1573 if (!NT_STATUS_IS_OK(status
)) {
1574 smbd_server_connection_terminate(req
->sconn
,
1578 } 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 state
->queue_entry
.mem_ctx
= state
;
1595 state
->queue_entry
.vector
= state
->vector
;
1596 state
->queue_entry
.count
= ARRAY_SIZE(state
->vector
);
1597 DLIST_ADD_END(sconn
->smb2
.send_queue
, &state
->queue_entry
, NULL
);
1598 sconn
->smb2
.send_queue_len
++;
1600 status
= smbd_smb2_flush_send_queue(sconn
);
1601 if (!NT_STATUS_IS_OK(status
)) {
1602 smbd_server_connection_terminate(sconn
,
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 if (cur
->compound_related
) {
1638 * Never cancel anything in a compound request.
1639 * Way too hard to deal with the result.
1644 outhdr
= SMBD_SMB2_OUT_HDR_PTR(cur
);
1646 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1647 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
1649 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1650 if (search_async_id
== async_id
) {
1651 found_id
= async_id
;
1655 if (search_message_id
== message_id
) {
1656 found_id
= message_id
;
1662 if (cur
&& cur
->subreq
) {
1663 inhdr
= SMBD_SMB2_IN_HDR_PTR(cur
);
1664 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1665 "cancel opcode[%s] mid %llu\n",
1666 smb2_opcode_name(SVAL(inhdr
, SMB2_HDR_OPCODE
)),
1667 (unsigned long long)found_id
));
1668 tevent_req_cancel(cur
->subreq
);
1671 return NT_STATUS_OK
;
1674 /*************************************************************
1675 Ensure an incoming tid is a valid one for us to access.
1676 Change to the associated uid credentials and chdir to the
1677 valid tid directory.
1678 *************************************************************/
1680 static NTSTATUS
smbd_smb2_request_check_tcon(struct smbd_smb2_request
*req
)
1682 const uint8_t *inhdr
;
1685 struct smbXsrv_tcon
*tcon
;
1687 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1691 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1693 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1694 in_tid
= IVAL(inhdr
, SMB2_HDR_TID
);
1696 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1697 in_tid
= req
->last_tid
;
1702 status
= smb2srv_tcon_lookup(req
->session
,
1703 in_tid
, now
, &tcon
);
1704 if (!NT_STATUS_IS_OK(status
)) {
1708 if (!change_to_user(tcon
->compat
, req
->session
->compat
->vuid
)) {
1709 return NT_STATUS_ACCESS_DENIED
;
1712 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1713 if (!set_current_service(tcon
->compat
, 0, true)) {
1714 return NT_STATUS_ACCESS_DENIED
;
1718 req
->last_tid
= in_tid
;
1720 return NT_STATUS_OK
;
1723 /*************************************************************
1724 Ensure an incoming session_id is a valid one for us to access.
1725 *************************************************************/
1727 static NTSTATUS
smbd_smb2_request_check_session(struct smbd_smb2_request
*req
)
1729 const uint8_t *inhdr
;
1732 uint64_t in_session_id
;
1733 struct smbXsrv_session
*session
= NULL
;
1734 struct auth_session_info
*session_info
;
1736 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1738 req
->session
= NULL
;
1741 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1743 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1744 in_opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1745 in_session_id
= BVAL(inhdr
, SMB2_HDR_SESSION_ID
);
1747 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1748 in_session_id
= req
->last_session_id
;
1751 req
->last_session_id
= 0;
1753 /* lookup an existing session */
1754 status
= smb2srv_session_lookup(req
->sconn
->conn
,
1758 req
->session
= session
;
1759 req
->last_session_id
= in_session_id
;
1761 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
1762 switch (in_opcode
) {
1763 case SMB2_OP_SESSSETUP
:
1764 status
= NT_STATUS_OK
;
1770 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1771 switch (in_opcode
) {
1773 case SMB2_OP_CREATE
:
1774 case SMB2_OP_GETINFO
:
1775 case SMB2_OP_SETINFO
:
1776 return NT_STATUS_INVALID_HANDLE
;
1779 * Notice the check for
1780 * (session_info == NULL)
1783 status
= NT_STATUS_OK
;
1787 if (!NT_STATUS_IS_OK(status
)) {
1791 session_info
= session
->global
->auth_session_info
;
1792 if (session_info
== NULL
) {
1793 return NT_STATUS_INVALID_HANDLE
;
1796 if (in_session_id
!= req
->sconn
->conn
->last_session_id
) {
1797 req
->sconn
->conn
->last_session_id
= in_session_id
;
1798 set_current_user_info(session_info
->unix_info
->sanitized_username
,
1799 session_info
->unix_info
->unix_name
,
1800 session_info
->info
->domain_name
);
1803 return NT_STATUS_OK
;
1806 NTSTATUS
smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request
*req
,
1807 uint32_t data_length
)
1809 uint16_t needed_charge
;
1810 uint16_t credit_charge
= 1;
1811 const uint8_t *inhdr
;
1813 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1815 if (req
->sconn
->smb2
.supports_multicredit
) {
1816 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
1817 credit_charge
= MAX(credit_charge
, 1);
1820 needed_charge
= (data_length
- 1)/ 65536 + 1;
1822 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1823 (unsigned long long) BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
),
1824 credit_charge
, needed_charge
));
1826 if (needed_charge
> credit_charge
) {
1827 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1828 credit_charge
, needed_charge
));
1829 return NT_STATUS_INVALID_PARAMETER
;
1832 return NT_STATUS_OK
;
1835 NTSTATUS
smbd_smb2_request_verify_sizes(struct smbd_smb2_request
*req
,
1836 size_t expected_body_size
)
1838 struct iovec
*inhdr_v
;
1839 const uint8_t *inhdr
;
1841 const uint8_t *inbody
;
1843 size_t min_dyn_size
= expected_body_size
& 0x00000001;
1844 int max_idx
= req
->in
.vector_count
- SMBD_SMB2_NUM_IOV_PER_REQ
;
1847 * The following should be checked already.
1849 if (req
->in
.vector_count
< SMBD_SMB2_NUM_IOV_PER_REQ
) {
1850 return NT_STATUS_INTERNAL_ERROR
;
1852 if (req
->current_idx
> max_idx
) {
1853 return NT_STATUS_INTERNAL_ERROR
;
1856 inhdr_v
= SMBD_SMB2_IN_HDR_IOV(req
);
1857 if (inhdr_v
->iov_len
!= SMB2_HDR_BODY
) {
1858 return NT_STATUS_INTERNAL_ERROR
;
1860 if (SMBD_SMB2_IN_BODY_LEN(req
) < 2) {
1861 return NT_STATUS_INTERNAL_ERROR
;
1864 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1865 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1869 case SMB2_OP_GETINFO
:
1873 if (req
->smb1req
!= NULL
&& req
->smb1req
->unread_bytes
> 0) {
1874 if (req
->smb1req
->unread_bytes
< min_dyn_size
) {
1875 return NT_STATUS_INVALID_PARAMETER
;
1884 * Now check the expected body size,
1885 * where the last byte might be in the
1888 if (SMBD_SMB2_IN_BODY_LEN(req
) != (expected_body_size
& 0xFFFFFFFE)) {
1889 return NT_STATUS_INVALID_PARAMETER
;
1891 if (SMBD_SMB2_IN_DYN_LEN(req
) < min_dyn_size
) {
1892 return NT_STATUS_INVALID_PARAMETER
;
1895 inbody
= SMBD_SMB2_IN_BODY_PTR(req
);
1897 body_size
= SVAL(inbody
, 0x00);
1898 if (body_size
!= expected_body_size
) {
1899 return NT_STATUS_INVALID_PARAMETER
;
1902 return NT_STATUS_OK
;
1905 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
1907 struct smbXsrv_connection
*conn
= req
->sconn
->conn
;
1908 const struct smbd_smb2_dispatch_table
*call
= NULL
;
1909 const struct iovec
*intf_v
= SMBD_SMB2_IN_TF_IOV(req
);
1910 const uint8_t *inhdr
;
1915 NTSTATUS session_status
;
1916 uint32_t allowed_flags
;
1917 NTSTATUS return_value
;
1918 struct smbXsrv_session
*x
= NULL
;
1919 bool signing_required
= false;
1920 bool encryption_required
= false;
1922 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1924 /* TODO: verify more things */
1926 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1927 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1928 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1929 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1930 smb2_opcode_name(opcode
),
1931 (unsigned long long)mid
));
1933 if (conn
->protocol
>= PROTOCOL_SMB2_02
) {
1935 * once the protocol is negotiated
1936 * SMB2_OP_NEGPROT is not allowed anymore
1938 if (opcode
== SMB2_OP_NEGPROT
) {
1939 /* drop the connection */
1940 return NT_STATUS_INVALID_PARAMETER
;
1944 * if the protocol is not negotiated yet
1945 * only SMB2_OP_NEGPROT is allowed.
1947 if (opcode
!= SMB2_OP_NEGPROT
) {
1948 /* drop the connection */
1949 return NT_STATUS_INVALID_PARAMETER
;
1954 * Check if the client provided a valid session id,
1955 * if so smbd_smb2_request_check_session() calls
1956 * set_current_user_info().
1958 * As some command don't require a valid session id
1959 * we defer the check of the session_status
1961 session_status
= smbd_smb2_request_check_session(req
);
1964 signing_required
= x
->global
->signing_required
;
1965 encryption_required
= x
->global
->encryption_required
;
1967 if (opcode
== SMB2_OP_SESSSETUP
&&
1968 x
->global
->channels
[0].signing_key
.length
) {
1969 signing_required
= true;
1973 req
->do_signing
= false;
1974 req
->do_encryption
= false;
1975 if (intf_v
->iov_len
== SMB2_TF_HDR_SIZE
) {
1976 const uint8_t *intf
= SMBD_SMB2_IN_TF_PTR(req
);
1977 uint64_t tf_session_id
= BVAL(intf
, SMB2_TF_SESSION_ID
);
1979 if (x
!= NULL
&& x
->global
->session_wire_id
!= tf_session_id
) {
1980 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1981 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1982 (unsigned long long)x
->global
->session_wire_id
,
1983 (unsigned long long)tf_session_id
));
1985 * TODO: windows allows this...
1986 * should we drop the connection?
1988 * For now we just return ACCESS_DENIED
1989 * (Windows clients never trigger this)
1990 * and wait for an update of [MS-SMB2].
1992 return smbd_smb2_request_error(req
,
1993 NT_STATUS_ACCESS_DENIED
);
1996 req
->do_encryption
= true;
1999 if (encryption_required
&& !req
->do_encryption
) {
2000 return smbd_smb2_request_error(req
,
2001 NT_STATUS_ACCESS_DENIED
);
2004 call
= smbd_smb2_call(opcode
);
2006 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2009 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
2010 SMB2_HDR_FLAG_SIGNED
|
2012 if (opcode
== SMB2_OP_CANCEL
) {
2013 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
2015 if ((flags
& ~allowed_flags
) != 0) {
2016 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2019 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
2021 * This check is mostly for giving the correct error code
2022 * for compounded requests.
2024 if (!NT_STATUS_IS_OK(session_status
)) {
2025 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2028 req
->compat_chain_fsp
= NULL
;
2031 if (req
->do_encryption
) {
2032 signing_required
= false;
2033 } else if (signing_required
|| (flags
& SMB2_HDR_FLAG_SIGNED
)) {
2034 DATA_BLOB signing_key
;
2037 return smbd_smb2_request_error(
2038 req
, NT_STATUS_USER_SESSION_DELETED
);
2041 signing_key
= x
->global
->channels
[0].signing_key
;
2044 * If we have a signing key, we should
2047 if (signing_key
.length
> 0) {
2048 req
->do_signing
= true;
2051 status
= smb2_signing_check_pdu(signing_key
,
2053 SMBD_SMB2_IN_HDR_IOV(req
),
2054 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2055 if (!NT_STATUS_IS_OK(status
)) {
2056 return smbd_smb2_request_error(req
, status
);
2060 * Now that we know the request was correctly signed
2061 * we have to sign the response too.
2063 req
->do_signing
= true;
2065 if (!NT_STATUS_IS_OK(session_status
)) {
2066 return smbd_smb2_request_error(req
, session_status
);
2068 } else if (opcode
== SMB2_OP_CANCEL
) {
2069 /* Cancel requests are allowed to skip the signing */
2070 } else if (signing_required
) {
2072 * If signing is required we try to sign
2073 * a possible error response
2075 req
->do_signing
= true;
2076 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
2079 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
2080 req
->compound_related
= true;
2083 if (call
->need_session
) {
2084 if (!NT_STATUS_IS_OK(session_status
)) {
2085 return smbd_smb2_request_error(req
, session_status
);
2089 if (call
->need_tcon
) {
2090 SMB_ASSERT(call
->need_session
);
2093 * This call needs to be run as user.
2095 * smbd_smb2_request_check_tcon()
2096 * calls change_to_user() on success.
2098 status
= smbd_smb2_request_check_tcon(req
);
2099 if (!NT_STATUS_IS_OK(status
)) {
2100 return smbd_smb2_request_error(req
, status
);
2102 if (req
->tcon
->global
->encryption_required
) {
2103 encryption_required
= true;
2105 if (encryption_required
&& !req
->do_encryption
) {
2106 return smbd_smb2_request_error(req
,
2107 NT_STATUS_ACCESS_DENIED
);
2111 if (call
->fileid_ofs
!= 0) {
2112 size_t needed
= call
->fileid_ofs
+ 16;
2113 const uint8_t *body
= SMBD_SMB2_IN_BODY_PTR(req
);
2114 size_t body_size
= SMBD_SMB2_IN_BODY_LEN(req
);
2115 uint64_t file_id_persistent
;
2116 uint64_t file_id_volatile
;
2117 struct files_struct
*fsp
;
2119 SMB_ASSERT(call
->need_tcon
);
2121 if (needed
> body_size
) {
2122 return smbd_smb2_request_error(req
,
2123 NT_STATUS_INVALID_PARAMETER
);
2126 file_id_persistent
= BVAL(body
, call
->fileid_ofs
+ 0);
2127 file_id_volatile
= BVAL(body
, call
->fileid_ofs
+ 8);
2129 fsp
= file_fsp_smb2(req
, file_id_persistent
, file_id_volatile
);
2131 if (!call
->allow_invalid_fileid
) {
2132 return smbd_smb2_request_error(req
,
2133 NT_STATUS_FILE_CLOSED
);
2136 if (file_id_persistent
!= UINT64_MAX
) {
2137 return smbd_smb2_request_error(req
,
2138 NT_STATUS_FILE_CLOSED
);
2140 if (file_id_volatile
!= UINT64_MAX
) {
2141 return smbd_smb2_request_error(req
,
2142 NT_STATUS_FILE_CLOSED
);
2147 if (call
->as_root
) {
2148 SMB_ASSERT(call
->fileid_ofs
== 0);
2149 /* This call needs to be run as root */
2150 change_to_root_user();
2152 SMB_ASSERT(call
->need_tcon
);
2156 case SMB2_OP_NEGPROT
:
2158 START_PROFILE(smb2_negprot
);
2159 return_value
= smbd_smb2_request_process_negprot(req
);
2160 END_PROFILE(smb2_negprot
);
2164 case SMB2_OP_SESSSETUP
:
2166 START_PROFILE(smb2_sesssetup
);
2167 return_value
= smbd_smb2_request_process_sesssetup(req
);
2168 END_PROFILE(smb2_sesssetup
);
2172 case SMB2_OP_LOGOFF
:
2174 START_PROFILE(smb2_logoff
);
2175 return_value
= smbd_smb2_request_process_logoff(req
);
2176 END_PROFILE(smb2_logoff
);
2182 START_PROFILE(smb2_tcon
);
2183 return_value
= smbd_smb2_request_process_tcon(req
);
2184 END_PROFILE(smb2_tcon
);
2190 START_PROFILE(smb2_tdis
);
2191 return_value
= smbd_smb2_request_process_tdis(req
);
2192 END_PROFILE(smb2_tdis
);
2196 case SMB2_OP_CREATE
:
2198 START_PROFILE(smb2_create
);
2199 return_value
= smbd_smb2_request_process_create(req
);
2200 END_PROFILE(smb2_create
);
2206 START_PROFILE(smb2_close
);
2207 return_value
= smbd_smb2_request_process_close(req
);
2208 END_PROFILE(smb2_close
);
2214 START_PROFILE(smb2_flush
);
2215 return_value
= smbd_smb2_request_process_flush(req
);
2216 END_PROFILE(smb2_flush
);
2222 START_PROFILE(smb2_read
);
2223 return_value
= smbd_smb2_request_process_read(req
);
2224 END_PROFILE(smb2_read
);
2230 START_PROFILE(smb2_write
);
2231 return_value
= smbd_smb2_request_process_write(req
);
2232 END_PROFILE(smb2_write
);
2238 START_PROFILE(smb2_lock
);
2239 return_value
= smbd_smb2_request_process_lock(req
);
2240 END_PROFILE(smb2_lock
);
2246 START_PROFILE(smb2_ioctl
);
2247 return_value
= smbd_smb2_request_process_ioctl(req
);
2248 END_PROFILE(smb2_ioctl
);
2252 case SMB2_OP_CANCEL
:
2254 START_PROFILE(smb2_cancel
);
2255 return_value
= smbd_smb2_request_process_cancel(req
);
2256 END_PROFILE(smb2_cancel
);
2260 case SMB2_OP_KEEPALIVE
:
2262 START_PROFILE(smb2_keepalive
);
2263 return_value
= smbd_smb2_request_process_keepalive(req
);
2264 END_PROFILE(smb2_keepalive
);
2270 START_PROFILE(smb2_find
);
2271 return_value
= smbd_smb2_request_process_find(req
);
2272 END_PROFILE(smb2_find
);
2276 case SMB2_OP_NOTIFY
:
2278 START_PROFILE(smb2_notify
);
2279 return_value
= smbd_smb2_request_process_notify(req
);
2280 END_PROFILE(smb2_notify
);
2284 case SMB2_OP_GETINFO
:
2286 START_PROFILE(smb2_getinfo
);
2287 return_value
= smbd_smb2_request_process_getinfo(req
);
2288 END_PROFILE(smb2_getinfo
);
2292 case SMB2_OP_SETINFO
:
2294 START_PROFILE(smb2_setinfo
);
2295 return_value
= smbd_smb2_request_process_setinfo(req
);
2296 END_PROFILE(smb2_setinfo
);
2302 START_PROFILE(smb2_break
);
2303 return_value
= smbd_smb2_request_process_break(req
);
2304 END_PROFILE(smb2_break
);
2309 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2312 return return_value
;
2315 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
2317 struct smbd_server_connection
*sconn
= req
->sconn
;
2318 struct smbXsrv_connection
*conn
= req
->sconn
->conn
;
2320 struct iovec
*firsttf
= SMBD_SMB2_IDX_TF_IOV(req
,out
,first_idx
);
2321 struct iovec
*outhdr
= SMBD_SMB2_OUT_HDR_IOV(req
);
2322 struct iovec
*outdyn
= SMBD_SMB2_OUT_DYN_IOV(req
);
2326 TALLOC_FREE(req
->async_te
);
2328 if (req
->do_encryption
&&
2329 (firsttf
->iov_len
== 0) &&
2330 (req
->first_key
.length
== 0) &&
2331 (req
->session
!= NULL
) &&
2332 (req
->session
->global
->encryption_key
.length
!= 0))
2334 DATA_BLOB encryption_key
= req
->session
->global
->encryption_key
;
2336 uint64_t session_id
= req
->session
->global
->session_wire_id
;
2337 struct smbXsrv_session
*x
= req
->session
;
2338 uint64_t nonce_high
;
2341 nonce_high
= x
->nonce_high
;
2342 nonce_low
= x
->nonce_low
;
2345 if (x
->nonce_low
== 0) {
2351 * We need to place the SMB2_TRANSFORM header before the
2356 * we need to remember the encryption key
2357 * and defer the signing/encryption until
2358 * we are sure that we do not change
2361 req
->first_key
= data_blob_dup_talloc(req
, encryption_key
);
2362 if (req
->first_key
.data
== NULL
) {
2363 return NT_STATUS_NO_MEMORY
;
2366 tf
= talloc_zero_array(req
, uint8_t,
2369 return NT_STATUS_NO_MEMORY
;
2372 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
2373 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
2374 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
2375 SBVAL(tf
, SMB2_TF_SESSION_ID
, session_id
);
2377 firsttf
->iov_base
= (void *)tf
;
2378 firsttf
->iov_len
= SMB2_TF_HDR_SIZE
;
2381 if ((req
->current_idx
> SMBD_SMB2_NUM_IOV_PER_REQ
) &&
2382 (req
->last_key
.length
> 0) &&
2383 (firsttf
->iov_len
== 0))
2385 int last_idx
= req
->current_idx
- SMBD_SMB2_NUM_IOV_PER_REQ
;
2386 struct iovec
*lasthdr
= SMBD_SMB2_IDX_HDR_IOV(req
,out
,last_idx
);
2389 * As we are sure the header of the last request in the
2390 * compound chain will not change, we can to sign here
2391 * with the last signing key we remembered.
2393 status
= smb2_signing_sign_pdu(req
->last_key
,
2396 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2397 if (!NT_STATUS_IS_OK(status
)) {
2401 if (req
->last_key
.length
> 0) {
2402 data_blob_clear_free(&req
->last_key
);
2405 req
->current_idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
;
2407 if (req
->current_idx
< req
->out
.vector_count
) {
2409 * We must process the remaining compound
2410 * SMB2 requests before any new incoming SMB2
2411 * requests. This is because incoming SMB2
2412 * requests may include a cancel for a
2413 * compound request we haven't processed
2416 struct tevent_immediate
*im
= tevent_create_immediate(req
);
2418 return NT_STATUS_NO_MEMORY
;
2421 if (req
->do_signing
&& firsttf
->iov_len
== 0) {
2422 struct smbXsrv_session
*x
= req
->session
;
2423 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
2426 * we need to remember the signing key
2427 * and defer the signing until
2428 * we are sure that we do not change
2431 req
->last_key
= data_blob_dup_talloc(req
, signing_key
);
2432 if (req
->last_key
.data
== NULL
) {
2433 return NT_STATUS_NO_MEMORY
;
2437 tevent_schedule_immediate(im
,
2439 smbd_smb2_request_dispatch_immediate
,
2441 return NT_STATUS_OK
;
2444 if (req
->compound_related
) {
2445 req
->compound_related
= false;
2448 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
2450 /* Set credit for these operations (zero credits if this
2451 is a final reply for an async operation). */
2452 smb2_calculate_credits(req
, req
);
2455 * now check if we need to sign the current response
2457 if (firsttf
->iov_len
== SMB2_TF_HDR_SIZE
) {
2458 status
= smb2_signing_encrypt_pdu(req
->first_key
,
2461 req
->out
.vector_count
- first_idx
);
2462 if (!NT_STATUS_IS_OK(status
)) {
2465 } else if (req
->do_signing
) {
2466 struct smbXsrv_session
*x
= req
->session
;
2467 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
2469 status
= smb2_signing_sign_pdu(signing_key
,
2472 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2473 if (!NT_STATUS_IS_OK(status
)) {
2477 if (req
->first_key
.length
> 0) {
2478 data_blob_clear_free(&req
->first_key
);
2481 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2482 if (req
->out
.vector_count
< (2*SMBD_SMB2_NUM_IOV_PER_REQ
) &&
2483 outdyn
->iov_base
== NULL
&& outdyn
->iov_len
!= 0) {
2484 /* Dynamic part is NULL. Chop it off,
2485 We're going to send it via sendfile. */
2486 req
->out
.vector_count
-= 1;
2490 * We're done with this request -
2491 * move it off the "being processed" queue.
2493 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
2495 req
->queue_entry
.mem_ctx
= req
;
2496 req
->queue_entry
.vector
= req
->out
.vector
;
2497 req
->queue_entry
.count
= req
->out
.vector_count
;
2498 DLIST_ADD_END(req
->sconn
->smb2
.send_queue
, &req
->queue_entry
, NULL
);
2499 req
->sconn
->smb2
.send_queue_len
++;
2501 status
= smbd_smb2_flush_send_queue(sconn
);
2502 if (!NT_STATUS_IS_OK(status
)) {
2506 return NT_STATUS_OK
;
2509 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
);
2511 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
2512 struct tevent_immediate
*im
,
2515 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
2516 struct smbd_smb2_request
);
2517 struct smbd_server_connection
*sconn
= req
->sconn
;
2522 if (DEBUGLEVEL
>= 10) {
2523 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2524 req
->current_idx
, req
->in
.vector_count
));
2525 print_req_vectors(req
);
2528 status
= smbd_smb2_request_dispatch(req
);
2529 if (!NT_STATUS_IS_OK(status
)) {
2530 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2534 status
= smbd_smb2_request_next_incoming(sconn
);
2535 if (!NT_STATUS_IS_OK(status
)) {
2536 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2541 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
2543 DATA_BLOB body
, DATA_BLOB
*dyn
,
2544 const char *location
)
2547 struct iovec
*outbody_v
;
2548 struct iovec
*outdyn_v
;
2549 uint32_t next_command_ofs
;
2551 DEBUG(10,("smbd_smb2_request_done_ex: "
2552 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2553 req
->current_idx
, nt_errstr(status
), (unsigned int)body
.length
,
2555 (unsigned int)(dyn
? dyn
->length
: 0),
2558 if (body
.length
< 2) {
2559 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2562 if ((body
.length
% 2) != 0) {
2563 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2566 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
2567 outbody_v
= SMBD_SMB2_OUT_BODY_IOV(req
);
2568 outdyn_v
= SMBD_SMB2_OUT_DYN_IOV(req
);
2570 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
2571 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
2573 outbody_v
->iov_base
= (void *)body
.data
;
2574 outbody_v
->iov_len
= body
.length
;
2577 outdyn_v
->iov_base
= (void *)dyn
->data
;
2578 outdyn_v
->iov_len
= dyn
->length
;
2580 outdyn_v
->iov_base
= NULL
;
2581 outdyn_v
->iov_len
= 0;
2584 /* see if we need to recalculate the offset to the next response */
2585 if (next_command_ofs
> 0) {
2586 next_command_ofs
= SMB2_HDR_BODY
;
2587 next_command_ofs
+= SMBD_SMB2_OUT_BODY_LEN(req
);
2588 next_command_ofs
+= SMBD_SMB2_OUT_DYN_LEN(req
);
2591 if ((next_command_ofs
% 8) != 0) {
2592 size_t pad_size
= 8 - (next_command_ofs
% 8);
2593 if (SMBD_SMB2_OUT_DYN_LEN(req
) == 0) {
2595 * if the dyn buffer is empty
2596 * we can use it to add padding
2600 pad
= talloc_zero_array(req
,
2603 return smbd_smb2_request_error(req
,
2604 NT_STATUS_NO_MEMORY
);
2607 outdyn_v
->iov_base
= (void *)pad
;
2608 outdyn_v
->iov_len
= pad_size
;
2611 * For now we copy the dynamic buffer
2612 * and add the padding to the new buffer
2619 old_size
= SMBD_SMB2_OUT_DYN_LEN(req
);
2620 old_dyn
= SMBD_SMB2_OUT_DYN_PTR(req
);
2622 new_size
= old_size
+ pad_size
;
2623 new_dyn
= talloc_zero_array(req
,
2625 if (new_dyn
== NULL
) {
2626 return smbd_smb2_request_error(req
,
2627 NT_STATUS_NO_MEMORY
);
2630 memcpy(new_dyn
, old_dyn
, old_size
);
2631 memset(new_dyn
+ old_size
, 0, pad_size
);
2633 outdyn_v
->iov_base
= (void *)new_dyn
;
2634 outdyn_v
->iov_len
= new_size
;
2636 next_command_ofs
+= pad_size
;
2639 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
2641 return smbd_smb2_request_reply(req
);
2644 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
2647 const char *location
)
2651 uint8_t *outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
2652 size_t unread_bytes
= smbd_smb2_unread_bytes(req
);
2654 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2655 req
->current_idx
, nt_errstr(status
), info
? " +info" : "",
2659 /* Recvfile error. Drain incoming socket. */
2663 ret
= drain_socket(req
->sconn
->sock
, unread_bytes
);
2664 if (ret
!= unread_bytes
) {
2668 error
= NT_STATUS_IO_DEVICE_ERROR
;
2670 error
= map_nt_error_from_unix_common(errno
);
2673 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2674 "ret[%u] errno[%d] => %s\n",
2675 (unsigned)unread_bytes
,
2676 (unsigned)ret
, errno
, nt_errstr(error
)));
2681 body
.data
= outhdr
+ SMB2_HDR_BODY
;
2683 SSVAL(body
.data
, 0, 9);
2686 SIVAL(body
.data
, 0x04, info
->length
);
2688 /* Allocated size of req->out.vector[i].iov_base
2689 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2690 * 1 byte without having to do an alloc.
2693 info
->data
= ((uint8_t *)outhdr
) +
2694 OUTVEC_ALLOC_SIZE
- 1;
2696 SCVAL(info
->data
, 0, 0);
2700 * Note: Even if there is an error, continue to process the request.
2704 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
2708 struct smbd_smb2_send_oplock_break_state
{
2709 struct smbd_server_connection
*sconn
;
2710 struct smbd_smb2_send_queue queue_entry
;
2711 uint8_t buf
[NBT_HDR_SIZE
+ SMB2_TF_HDR_SIZE
+ SMB2_HDR_BODY
+ 0x18];
2712 struct iovec vector
[1+SMBD_SMB2_NUM_IOV_PER_REQ
];
2715 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
2716 struct smbXsrv_session
*session
,
2717 struct smbXsrv_tcon
*tcon
,
2718 struct smbXsrv_open
*op
,
2719 uint8_t oplock_level
)
2721 struct smbd_smb2_send_oplock_break_state
*state
;
2722 struct smbXsrv_connection
*conn
= sconn
->conn
;
2730 bool do_encryption
= session
->global
->encryption_required
;
2731 uint64_t nonce_high
= 0;
2732 uint64_t nonce_low
= 0;
2735 if (tcon
->global
->encryption_required
) {
2736 do_encryption
= true;
2739 state
= talloc_zero(sconn
, struct smbd_smb2_send_oplock_break_state
);
2740 if (state
== NULL
) {
2741 return NT_STATUS_NO_MEMORY
;
2743 state
->sconn
= sconn
;
2745 tf
= state
->buf
+ NBT_HDR_SIZE
;
2746 tf_len
= SMB2_TF_HDR_SIZE
;
2748 body
= hdr
+ SMB2_HDR_BODY
;
2750 dyn
= body
+ body_len
;
2753 if (do_encryption
) {
2754 nonce_high
= session
->nonce_high
;
2755 nonce_low
= session
->nonce_low
;
2757 session
->nonce_low
+= 1;
2758 if (session
->nonce_low
== 0) {
2759 session
->nonce_low
+= 1;
2760 session
->nonce_high
+= 1;
2764 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
2765 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
2766 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
2767 SBVAL(tf
, SMB2_TF_SESSION_ID
, session
->global
->session_wire_id
);
2769 SIVAL(hdr
, 0, SMB2_MAGIC
);
2770 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
2771 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
2772 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
2773 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
2774 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
2775 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
2776 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
2777 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
2778 SIVAL(hdr
, SMB2_HDR_PID
, 0);
2779 SIVAL(hdr
, SMB2_HDR_TID
, 0);
2780 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
2781 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
2783 SSVAL(body
, 0x00, body_len
);
2785 SCVAL(body
, 0x02, oplock_level
);
2786 SCVAL(body
, 0x03, 0); /* reserved */
2787 SIVAL(body
, 0x04, 0); /* reserved */
2788 SBVAL(body
, 0x08, op
->global
->open_persistent_id
);
2789 SBVAL(body
, 0x10, op
->global
->open_volatile_id
);
2791 state
->vector
[0].iov_base
= (void *)state
->buf
;
2792 state
->vector
[0].iov_len
= NBT_HDR_SIZE
;
2794 if (do_encryption
) {
2795 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= tf
;
2796 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= tf_len
;
2798 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
2799 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
2802 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
2803 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
2805 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
2806 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_len
= body_len
;
2808 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
2809 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_len
= dyn_len
;
2811 smb2_setup_nbt_length(state
->vector
, 1 + SMBD_SMB2_NUM_IOV_PER_REQ
);
2813 if (do_encryption
) {
2814 DATA_BLOB encryption_key
= session
->global
->encryption_key
;
2816 status
= smb2_signing_encrypt_pdu(encryption_key
,
2818 &state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
],
2819 SMBD_SMB2_NUM_IOV_PER_REQ
);
2820 if (!NT_STATUS_IS_OK(status
)) {
2825 state
->queue_entry
.mem_ctx
= state
;
2826 state
->queue_entry
.vector
= state
->vector
;
2827 state
->queue_entry
.count
= ARRAY_SIZE(state
->vector
);
2828 DLIST_ADD_END(state
->sconn
->smb2
.send_queue
, &state
->queue_entry
, NULL
);
2829 state
->sconn
->smb2
.send_queue_len
++;
2831 status
= smbd_smb2_flush_send_queue(sconn
);
2832 if (!NT_STATUS_IS_OK(status
)) {
2836 return NT_STATUS_OK
;
2839 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state
*state
)
2843 uint64_t file_id_persistent
;
2844 uint64_t file_id_volatile
;
2845 struct smbXsrv_open
*op
= NULL
;
2846 struct files_struct
*fsp
= NULL
;
2847 const uint8_t *body
= NULL
;
2850 * This is only called with a pktbuf
2851 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
2855 if (IVAL(state
->pktbuf
, 0) == SMB2_TF_MAGIC
) {
2856 /* Transform header. Cannot recvfile. */
2859 if (IVAL(state
->pktbuf
, 0) != SMB2_MAGIC
) {
2860 /* Not SMB2. Normal error path will cope. */
2863 if (SVAL(state
->pktbuf
, 4) != SMB2_HDR_BODY
) {
2864 /* Not SMB2. Normal error path will cope. */
2867 if (SVAL(state
->pktbuf
, SMB2_HDR_OPCODE
) != SMB2_OP_WRITE
) {
2868 /* Needs to be a WRITE. */
2871 if (IVAL(state
->pktbuf
, SMB2_HDR_NEXT_COMMAND
) != 0) {
2872 /* Chained. Cannot recvfile. */
2875 flags
= IVAL(state
->pktbuf
, SMB2_HDR_FLAGS
);
2876 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
2877 /* Chained. Cannot recvfile. */
2880 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
2881 /* Signed. Cannot recvfile. */
2885 body
= &state
->pktbuf
[SMB2_HDR_BODY
];
2887 file_id_persistent
= BVAL(body
, 0x10);
2888 file_id_volatile
= BVAL(body
, 0x18);
2890 status
= smb2srv_open_lookup(state
->req
->sconn
->conn
,
2895 if (!NT_STATUS_IS_OK(status
)) {
2903 if (fsp
->conn
== NULL
) {
2907 if (IS_IPC(fsp
->conn
)) {
2910 if (IS_PRINT(fsp
->conn
)) {
2914 DEBUG(10,("Doing recvfile write len = %u\n",
2915 (unsigned int)(state
->pktfull
- state
->pktlen
)));
2920 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
)
2922 struct smbd_smb2_request_read_state
*state
= &sconn
->smb2
.request_read_state
;
2923 size_t max_send_queue_len
;
2924 size_t cur_send_queue_len
;
2926 if (!NT_STATUS_IS_OK(sconn
->status
)) {
2928 * we're not supposed to do any io
2930 return NT_STATUS_OK
;
2933 if (state
->req
!= NULL
) {
2935 * if there is already a tstream_readv_pdu
2936 * pending, we are done.
2938 return NT_STATUS_OK
;
2941 max_send_queue_len
= MAX(1, sconn
->smb2
.max_credits
/16);
2942 cur_send_queue_len
= sconn
->smb2
.send_queue_len
;
2944 if (cur_send_queue_len
> max_send_queue_len
) {
2946 * if we have a lot of requests to send,
2947 * we wait until they are on the wire until we
2948 * ask for the next request.
2950 return NT_STATUS_OK
;
2953 /* ask for the next request */
2954 ZERO_STRUCTP(state
);
2955 state
->req
= smbd_smb2_request_allocate(sconn
);
2956 if (state
->req
== NULL
) {
2957 return NT_STATUS_NO_MEMORY
;
2959 state
->req
->sconn
= sconn
;
2960 state
->min_recv_size
= lp_min_receive_file_size();
2962 TEVENT_FD_READABLE(sconn
->smb2
.fde
);
2964 return NT_STATUS_OK
;
2967 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
2968 uint8_t *inbuf
, size_t size
)
2971 struct smbd_smb2_request
*req
= NULL
;
2973 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2974 (unsigned int)size
));
2976 status
= smbd_initialize_smb2(sconn
);
2977 if (!NT_STATUS_IS_OK(status
)) {
2978 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2982 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
2983 if (!NT_STATUS_IS_OK(status
)) {
2984 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2988 status
= smbd_smb2_request_validate(req
);
2989 if (!NT_STATUS_IS_OK(status
)) {
2990 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2994 status
= smbd_smb2_request_setup_out(req
);
2995 if (!NT_STATUS_IS_OK(status
)) {
2996 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3000 status
= smbd_smb2_request_dispatch(req
);
3001 if (!NT_STATUS_IS_OK(status
)) {
3002 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3006 status
= smbd_smb2_request_next_incoming(sconn
);
3007 if (!NT_STATUS_IS_OK(status
)) {
3008 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3012 sconn
->num_requests
++;
3015 static int socket_error_from_errno(int ret
,
3029 if (sys_errno
== 0) {
3033 if (sys_errno
== EINTR
) {
3038 if (sys_errno
== EINPROGRESS
) {
3043 if (sys_errno
== EAGAIN
) {
3048 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3049 if (sys_errno
== ENOMEM
) {
3055 #if EWOULDBLOCK != EAGAIN
3056 if (sys_errno
== EWOULDBLOCK
) {
3066 static NTSTATUS
smbd_smb2_flush_send_queue(struct smbd_server_connection
*sconn
)
3072 if (sconn
->smb2
.send_queue
== NULL
) {
3073 TEVENT_FD_NOT_WRITEABLE(sconn
->smb2
.fde
);
3074 return NT_STATUS_OK
;
3077 while (sconn
->smb2
.send_queue
!= NULL
) {
3078 struct smbd_smb2_send_queue
*e
= sconn
->smb2
.send_queue
;
3080 if (e
->sendfile_header
!= NULL
) {
3085 for (i
=0; i
< e
->count
; i
++) {
3086 size
+= e
->vector
[i
].iov_len
;
3089 if (size
<= e
->sendfile_header
->length
) {
3090 buf
= e
->sendfile_header
->data
;
3092 buf
= talloc_array(e
->mem_ctx
, uint8_t, size
);
3094 return NT_STATUS_NO_MEMORY
;
3099 for (i
=0; i
< e
->count
; i
++) {
3101 e
->vector
[i
].iov_base
,
3102 e
->vector
[i
].iov_len
);
3103 size
+= e
->vector
[i
].iov_len
;
3106 e
->sendfile_header
->data
= buf
;
3107 e
->sendfile_header
->length
= size
;
3110 sconn
->smb2
.send_queue_len
--;
3111 DLIST_REMOVE(sconn
->smb2
.send_queue
, e
);
3113 * This triggers the sendfile path via
3116 talloc_free(e
->mem_ctx
);
3120 ret
= writev(sconn
->sock
, e
->vector
, e
->count
);
3122 /* propagate end of file */
3123 return NT_STATUS_INTERNAL_ERROR
;
3125 err
= socket_error_from_errno(ret
, errno
, &retry
);
3128 TEVENT_FD_WRITEABLE(sconn
->smb2
.fde
);
3129 return NT_STATUS_OK
;
3132 return map_nt_error_from_unix_common(err
);
3135 if (ret
< e
->vector
[0].iov_len
) {
3137 base
= (uint8_t *)e
->vector
[0].iov_base
;
3139 e
->vector
[0].iov_base
= (void *)base
;
3140 e
->vector
[0].iov_len
-= ret
;
3143 ret
-= e
->vector
[0].iov_len
;
3149 * there're maybe some empty vectors at the end
3150 * which we need to skip, otherwise we would get
3151 * ret == 0 from the readv() call and return EPIPE
3153 while (e
->count
> 0) {
3154 if (e
->vector
[0].iov_len
> 0) {
3162 /* we have more to write */
3163 TEVENT_FD_WRITEABLE(sconn
->smb2
.fde
);
3164 return NT_STATUS_OK
;
3167 sconn
->smb2
.send_queue_len
--;
3168 DLIST_REMOVE(sconn
->smb2
.send_queue
, e
);
3169 talloc_free(e
->mem_ctx
);
3172 return NT_STATUS_OK
;
3175 static NTSTATUS
smbd_smb2_io_handler(struct smbd_server_connection
*sconn
,
3178 struct smbd_smb2_request_read_state
*state
= &sconn
->smb2
.request_read_state
;
3179 struct smbd_smb2_request
*req
= NULL
;
3180 size_t min_recvfile_size
= UINT32_MAX
;
3187 if (!NT_STATUS_IS_OK(sconn
->status
)) {
3189 * we're not supposed to do any io
3191 TEVENT_FD_NOT_READABLE(sconn
->smb2
.fde
);
3192 TEVENT_FD_NOT_WRITEABLE(sconn
->smb2
.fde
);
3193 return NT_STATUS_OK
;
3196 if (fde_flags
& TEVENT_FD_WRITE
) {
3197 status
= smbd_smb2_flush_send_queue(sconn
);
3198 if (!NT_STATUS_IS_OK(status
)) {
3203 if (!(fde_flags
& TEVENT_FD_READ
)) {
3204 return NT_STATUS_OK
;
3207 if (state
->req
== NULL
) {
3208 TEVENT_FD_NOT_READABLE(sconn
->smb2
.fde
);
3209 return NT_STATUS_OK
;
3213 if (!state
->hdr
.done
) {
3214 state
->hdr
.done
= true;
3216 state
->vector
.iov_base
= (void *)state
->hdr
.nbt
;
3217 state
->vector
.iov_len
= NBT_HDR_SIZE
;
3220 ret
= readv(sconn
->sock
, &state
->vector
, 1);
3222 /* propagate end of file */
3223 return NT_STATUS_END_OF_FILE
;
3225 err
= socket_error_from_errno(ret
, errno
, &retry
);
3228 TEVENT_FD_READABLE(sconn
->smb2
.fde
);
3229 return NT_STATUS_OK
;
3232 return map_nt_error_from_unix_common(err
);
3235 if (ret
< state
->vector
.iov_len
) {
3237 base
= (uint8_t *)state
->vector
.iov_base
;
3239 state
->vector
.iov_base
= (void *)base
;
3240 state
->vector
.iov_len
-= ret
;
3241 /* we have more to read */
3242 TEVENT_FD_READABLE(sconn
->smb2
.fde
);
3243 return NT_STATUS_OK
;
3246 if (state
->pktlen
> 0) {
3247 if (state
->doing_receivefile
&& !is_smb2_recvfile_write(state
)) {
3249 * Not a possible receivefile write.
3250 * Read the rest of the data.
3252 state
->doing_receivefile
= false;
3254 state
->pktbuf
= talloc_realloc(state
->req
,
3258 if (state
->pktbuf
== NULL
) {
3259 return NT_STATUS_NO_MEMORY
;
3262 state
->vector
.iov_base
= (void *)(state
->pktbuf
+
3264 state
->vector
.iov_len
= (state
->pktfull
-
3267 state
->pktlen
= state
->pktfull
;
3272 * Either this is a receivefile write so we've
3273 * done a short read, or if not we have all the data.
3279 * Now we analyze the NBT header
3281 if (state
->hdr
.nbt
[0] != 0x00) {
3282 state
->min_recv_size
= 0;
3284 state
->pktfull
= smb2_len(state
->hdr
.nbt
);
3285 if (state
->pktfull
== 0) {
3289 if (state
->min_recv_size
!= 0) {
3290 min_recvfile_size
= SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
;
3291 min_recvfile_size
+= state
->min_recv_size
;
3294 if (state
->pktfull
> min_recvfile_size
) {
3296 * Might be a receivefile write. Read the SMB2 HEADER +
3297 * SMB2_WRITE header first. Set 'doing_receivefile'
3298 * as we're *attempting* receivefile write. If this
3299 * turns out not to be a SMB2_WRITE request or otherwise
3300 * not suitable then we'll just read the rest of the data
3301 * the next time this function is called.
3303 state
->pktlen
= SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
;
3304 state
->doing_receivefile
= true;
3306 state
->pktlen
= state
->pktfull
;
3309 state
->pktbuf
= talloc_array(state
->req
, uint8_t, state
->pktlen
);
3310 if (state
->pktbuf
== NULL
) {
3311 return NT_STATUS_NO_MEMORY
;
3314 state
->vector
.iov_base
= (void *)state
->pktbuf
;
3315 state
->vector
.iov_len
= state
->pktlen
;
3321 if (state
->hdr
.nbt
[0] != 0x00) {
3322 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3323 state
->hdr
.nbt
[0]));
3326 ZERO_STRUCTP(state
);
3328 state
->min_recv_size
= lp_min_receive_file_size();
3336 req
->request_time
= timeval_current();
3337 now
= timeval_to_nttime(&req
->request_time
);
3339 status
= smbd_smb2_inbuf_parse_compound(req
->sconn
->conn
,
3345 &req
->in
.vector_count
);
3346 if (!NT_STATUS_IS_OK(status
)) {
3350 if (state
->doing_receivefile
) {
3351 req
->smb1req
= talloc_zero(req
, struct smb_request
);
3352 if (req
->smb1req
== NULL
) {
3353 return NT_STATUS_NO_MEMORY
;
3355 req
->smb1req
->unread_bytes
= state
->pktfull
- state
->pktlen
;
3358 ZERO_STRUCTP(state
);
3360 req
->current_idx
= 1;
3362 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3363 req
->current_idx
, req
->in
.vector_count
));
3365 status
= smbd_smb2_request_validate(req
);
3366 if (!NT_STATUS_IS_OK(status
)) {
3370 status
= smbd_smb2_request_setup_out(req
);
3371 if (!NT_STATUS_IS_OK(status
)) {
3375 status
= smbd_smb2_request_dispatch(req
);
3376 if (!NT_STATUS_IS_OK(status
)) {
3380 sconn
->num_requests
++;
3382 /* The timeout_processing function isn't run nearly
3383 often enough to implement 'max log size' without
3384 overrunning the size of the file by many megabytes.
3385 This is especially true if we are running at debug
3386 level 10. Checking every 50 SMB2s is a nice
3387 tradeoff of performance vs log file size overrun. */
3389 if ((sconn
->num_requests
% 50) == 0 &&
3390 need_to_check_log_size()) {
3391 change_to_root_user();
3395 status
= smbd_smb2_request_next_incoming(sconn
);
3396 if (!NT_STATUS_IS_OK(status
)) {
3400 return NT_STATUS_OK
;
3403 static void smbd_smb2_connection_handler(struct tevent_context
*ev
,
3404 struct tevent_fd
*fde
,
3408 struct smbd_server_connection
*sconn
=
3409 talloc_get_type_abort(private_data
,
3410 struct smbd_server_connection
);
3413 status
= smbd_smb2_io_handler(sconn
, flags
);
3414 if (!NT_STATUS_IS_OK(status
)) {
3415 smbd_server_connection_terminate(sconn
, nt_errstr(status
));