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
;
2038 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2039 * If the SMB2 header of the SMB2 NEGOTIATE
2040 * request has the SMB2_FLAGS_SIGNED bit set in the
2041 * Flags field, the server MUST fail the request
2042 * with STATUS_INVALID_PARAMETER.
2044 * Microsoft test tool checks this.
2047 if ((opcode
== SMB2_OP_NEGPROT
) &&
2048 (flags
& SMB2_HDR_FLAG_SIGNED
)) {
2049 status
= NT_STATUS_INVALID_PARAMETER
;
2051 status
= NT_STATUS_USER_SESSION_DELETED
;
2053 return smbd_smb2_request_error(req
, status
);
2056 signing_key
= x
->global
->channels
[0].signing_key
;
2059 * If we have a signing key, we should
2062 if (signing_key
.length
> 0) {
2063 req
->do_signing
= true;
2066 status
= smb2_signing_check_pdu(signing_key
,
2068 SMBD_SMB2_IN_HDR_IOV(req
),
2069 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2070 if (!NT_STATUS_IS_OK(status
)) {
2071 return smbd_smb2_request_error(req
, status
);
2075 * Now that we know the request was correctly signed
2076 * we have to sign the response too.
2078 req
->do_signing
= true;
2080 if (!NT_STATUS_IS_OK(session_status
)) {
2081 return smbd_smb2_request_error(req
, session_status
);
2083 } else if (opcode
== SMB2_OP_CANCEL
) {
2084 /* Cancel requests are allowed to skip the signing */
2085 } else if (signing_required
) {
2087 * If signing is required we try to sign
2088 * a possible error response
2090 req
->do_signing
= true;
2091 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
2094 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
2095 req
->compound_related
= true;
2098 if (call
->need_session
) {
2099 if (!NT_STATUS_IS_OK(session_status
)) {
2100 return smbd_smb2_request_error(req
, session_status
);
2104 if (call
->need_tcon
) {
2105 SMB_ASSERT(call
->need_session
);
2108 * This call needs to be run as user.
2110 * smbd_smb2_request_check_tcon()
2111 * calls change_to_user() on success.
2113 status
= smbd_smb2_request_check_tcon(req
);
2114 if (!NT_STATUS_IS_OK(status
)) {
2115 return smbd_smb2_request_error(req
, status
);
2117 if (req
->tcon
->global
->encryption_required
) {
2118 encryption_required
= true;
2120 if (encryption_required
&& !req
->do_encryption
) {
2121 return smbd_smb2_request_error(req
,
2122 NT_STATUS_ACCESS_DENIED
);
2126 if (call
->fileid_ofs
!= 0) {
2127 size_t needed
= call
->fileid_ofs
+ 16;
2128 const uint8_t *body
= SMBD_SMB2_IN_BODY_PTR(req
);
2129 size_t body_size
= SMBD_SMB2_IN_BODY_LEN(req
);
2130 uint64_t file_id_persistent
;
2131 uint64_t file_id_volatile
;
2132 struct files_struct
*fsp
;
2134 SMB_ASSERT(call
->need_tcon
);
2136 if (needed
> body_size
) {
2137 return smbd_smb2_request_error(req
,
2138 NT_STATUS_INVALID_PARAMETER
);
2141 file_id_persistent
= BVAL(body
, call
->fileid_ofs
+ 0);
2142 file_id_volatile
= BVAL(body
, call
->fileid_ofs
+ 8);
2144 fsp
= file_fsp_smb2(req
, file_id_persistent
, file_id_volatile
);
2146 if (!call
->allow_invalid_fileid
) {
2147 return smbd_smb2_request_error(req
,
2148 NT_STATUS_FILE_CLOSED
);
2151 if (file_id_persistent
!= UINT64_MAX
) {
2152 return smbd_smb2_request_error(req
,
2153 NT_STATUS_FILE_CLOSED
);
2155 if (file_id_volatile
!= UINT64_MAX
) {
2156 return smbd_smb2_request_error(req
,
2157 NT_STATUS_FILE_CLOSED
);
2162 if (call
->as_root
) {
2163 SMB_ASSERT(call
->fileid_ofs
== 0);
2164 /* This call needs to be run as root */
2165 change_to_root_user();
2167 SMB_ASSERT(call
->need_tcon
);
2171 case SMB2_OP_NEGPROT
:
2173 START_PROFILE(smb2_negprot
);
2174 return_value
= smbd_smb2_request_process_negprot(req
);
2175 END_PROFILE(smb2_negprot
);
2179 case SMB2_OP_SESSSETUP
:
2181 START_PROFILE(smb2_sesssetup
);
2182 return_value
= smbd_smb2_request_process_sesssetup(req
);
2183 END_PROFILE(smb2_sesssetup
);
2187 case SMB2_OP_LOGOFF
:
2189 START_PROFILE(smb2_logoff
);
2190 return_value
= smbd_smb2_request_process_logoff(req
);
2191 END_PROFILE(smb2_logoff
);
2197 START_PROFILE(smb2_tcon
);
2198 return_value
= smbd_smb2_request_process_tcon(req
);
2199 END_PROFILE(smb2_tcon
);
2205 START_PROFILE(smb2_tdis
);
2206 return_value
= smbd_smb2_request_process_tdis(req
);
2207 END_PROFILE(smb2_tdis
);
2211 case SMB2_OP_CREATE
:
2213 START_PROFILE(smb2_create
);
2214 return_value
= smbd_smb2_request_process_create(req
);
2215 END_PROFILE(smb2_create
);
2221 START_PROFILE(smb2_close
);
2222 return_value
= smbd_smb2_request_process_close(req
);
2223 END_PROFILE(smb2_close
);
2229 START_PROFILE(smb2_flush
);
2230 return_value
= smbd_smb2_request_process_flush(req
);
2231 END_PROFILE(smb2_flush
);
2237 START_PROFILE(smb2_read
);
2238 return_value
= smbd_smb2_request_process_read(req
);
2239 END_PROFILE(smb2_read
);
2245 START_PROFILE(smb2_write
);
2246 return_value
= smbd_smb2_request_process_write(req
);
2247 END_PROFILE(smb2_write
);
2253 START_PROFILE(smb2_lock
);
2254 return_value
= smbd_smb2_request_process_lock(req
);
2255 END_PROFILE(smb2_lock
);
2261 START_PROFILE(smb2_ioctl
);
2262 return_value
= smbd_smb2_request_process_ioctl(req
);
2263 END_PROFILE(smb2_ioctl
);
2267 case SMB2_OP_CANCEL
:
2269 START_PROFILE(smb2_cancel
);
2270 return_value
= smbd_smb2_request_process_cancel(req
);
2271 END_PROFILE(smb2_cancel
);
2275 case SMB2_OP_KEEPALIVE
:
2277 START_PROFILE(smb2_keepalive
);
2278 return_value
= smbd_smb2_request_process_keepalive(req
);
2279 END_PROFILE(smb2_keepalive
);
2285 START_PROFILE(smb2_find
);
2286 return_value
= smbd_smb2_request_process_find(req
);
2287 END_PROFILE(smb2_find
);
2291 case SMB2_OP_NOTIFY
:
2293 START_PROFILE(smb2_notify
);
2294 return_value
= smbd_smb2_request_process_notify(req
);
2295 END_PROFILE(smb2_notify
);
2299 case SMB2_OP_GETINFO
:
2301 START_PROFILE(smb2_getinfo
);
2302 return_value
= smbd_smb2_request_process_getinfo(req
);
2303 END_PROFILE(smb2_getinfo
);
2307 case SMB2_OP_SETINFO
:
2309 START_PROFILE(smb2_setinfo
);
2310 return_value
= smbd_smb2_request_process_setinfo(req
);
2311 END_PROFILE(smb2_setinfo
);
2317 START_PROFILE(smb2_break
);
2318 return_value
= smbd_smb2_request_process_break(req
);
2319 END_PROFILE(smb2_break
);
2324 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2327 return return_value
;
2330 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
2332 struct smbd_server_connection
*sconn
= req
->sconn
;
2333 struct smbXsrv_connection
*conn
= req
->sconn
->conn
;
2335 struct iovec
*firsttf
= SMBD_SMB2_IDX_TF_IOV(req
,out
,first_idx
);
2336 struct iovec
*outhdr
= SMBD_SMB2_OUT_HDR_IOV(req
);
2337 struct iovec
*outdyn
= SMBD_SMB2_OUT_DYN_IOV(req
);
2341 TALLOC_FREE(req
->async_te
);
2343 if (req
->do_encryption
&&
2344 (firsttf
->iov_len
== 0) &&
2345 (req
->first_key
.length
== 0) &&
2346 (req
->session
!= NULL
) &&
2347 (req
->session
->global
->encryption_key
.length
!= 0))
2349 DATA_BLOB encryption_key
= req
->session
->global
->encryption_key
;
2351 uint64_t session_id
= req
->session
->global
->session_wire_id
;
2352 struct smbXsrv_session
*x
= req
->session
;
2353 uint64_t nonce_high
;
2356 nonce_high
= x
->nonce_high
;
2357 nonce_low
= x
->nonce_low
;
2360 if (x
->nonce_low
== 0) {
2366 * We need to place the SMB2_TRANSFORM header before the
2371 * we need to remember the encryption key
2372 * and defer the signing/encryption until
2373 * we are sure that we do not change
2376 req
->first_key
= data_blob_dup_talloc(req
, encryption_key
);
2377 if (req
->first_key
.data
== NULL
) {
2378 return NT_STATUS_NO_MEMORY
;
2381 tf
= talloc_zero_array(req
, uint8_t,
2384 return NT_STATUS_NO_MEMORY
;
2387 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
2388 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
2389 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
2390 SBVAL(tf
, SMB2_TF_SESSION_ID
, session_id
);
2392 firsttf
->iov_base
= (void *)tf
;
2393 firsttf
->iov_len
= SMB2_TF_HDR_SIZE
;
2396 if ((req
->current_idx
> SMBD_SMB2_NUM_IOV_PER_REQ
) &&
2397 (req
->last_key
.length
> 0) &&
2398 (firsttf
->iov_len
== 0))
2400 int last_idx
= req
->current_idx
- SMBD_SMB2_NUM_IOV_PER_REQ
;
2401 struct iovec
*lasthdr
= SMBD_SMB2_IDX_HDR_IOV(req
,out
,last_idx
);
2404 * As we are sure the header of the last request in the
2405 * compound chain will not change, we can to sign here
2406 * with the last signing key we remembered.
2408 status
= smb2_signing_sign_pdu(req
->last_key
,
2411 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2412 if (!NT_STATUS_IS_OK(status
)) {
2416 if (req
->last_key
.length
> 0) {
2417 data_blob_clear_free(&req
->last_key
);
2420 req
->current_idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
;
2422 if (req
->current_idx
< req
->out
.vector_count
) {
2424 * We must process the remaining compound
2425 * SMB2 requests before any new incoming SMB2
2426 * requests. This is because incoming SMB2
2427 * requests may include a cancel for a
2428 * compound request we haven't processed
2431 struct tevent_immediate
*im
= tevent_create_immediate(req
);
2433 return NT_STATUS_NO_MEMORY
;
2436 if (req
->do_signing
&& firsttf
->iov_len
== 0) {
2437 struct smbXsrv_session
*x
= req
->session
;
2438 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
2441 * we need to remember the signing key
2442 * and defer the signing until
2443 * we are sure that we do not change
2446 req
->last_key
= data_blob_dup_talloc(req
, signing_key
);
2447 if (req
->last_key
.data
== NULL
) {
2448 return NT_STATUS_NO_MEMORY
;
2452 tevent_schedule_immediate(im
,
2454 smbd_smb2_request_dispatch_immediate
,
2456 return NT_STATUS_OK
;
2459 if (req
->compound_related
) {
2460 req
->compound_related
= false;
2463 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
2465 /* Set credit for these operations (zero credits if this
2466 is a final reply for an async operation). */
2467 smb2_calculate_credits(req
, req
);
2470 * now check if we need to sign the current response
2472 if (firsttf
->iov_len
== SMB2_TF_HDR_SIZE
) {
2473 status
= smb2_signing_encrypt_pdu(req
->first_key
,
2476 req
->out
.vector_count
- first_idx
);
2477 if (!NT_STATUS_IS_OK(status
)) {
2480 } else if (req
->do_signing
) {
2481 struct smbXsrv_session
*x
= req
->session
;
2482 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
2484 status
= smb2_signing_sign_pdu(signing_key
,
2487 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2488 if (!NT_STATUS_IS_OK(status
)) {
2492 if (req
->first_key
.length
> 0) {
2493 data_blob_clear_free(&req
->first_key
);
2496 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2497 if (req
->out
.vector_count
< (2*SMBD_SMB2_NUM_IOV_PER_REQ
) &&
2498 outdyn
->iov_base
== NULL
&& outdyn
->iov_len
!= 0) {
2499 /* Dynamic part is NULL. Chop it off,
2500 We're going to send it via sendfile. */
2501 req
->out
.vector_count
-= 1;
2505 * We're done with this request -
2506 * move it off the "being processed" queue.
2508 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
2510 req
->queue_entry
.mem_ctx
= req
;
2511 req
->queue_entry
.vector
= req
->out
.vector
;
2512 req
->queue_entry
.count
= req
->out
.vector_count
;
2513 DLIST_ADD_END(req
->sconn
->smb2
.send_queue
, &req
->queue_entry
, NULL
);
2514 req
->sconn
->smb2
.send_queue_len
++;
2516 status
= smbd_smb2_flush_send_queue(sconn
);
2517 if (!NT_STATUS_IS_OK(status
)) {
2521 return NT_STATUS_OK
;
2524 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
);
2526 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
2527 struct tevent_immediate
*im
,
2530 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
2531 struct smbd_smb2_request
);
2532 struct smbd_server_connection
*sconn
= req
->sconn
;
2537 if (DEBUGLEVEL
>= 10) {
2538 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2539 req
->current_idx
, req
->in
.vector_count
));
2540 print_req_vectors(req
);
2543 status
= smbd_smb2_request_dispatch(req
);
2544 if (!NT_STATUS_IS_OK(status
)) {
2545 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2549 status
= smbd_smb2_request_next_incoming(sconn
);
2550 if (!NT_STATUS_IS_OK(status
)) {
2551 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2556 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
2558 DATA_BLOB body
, DATA_BLOB
*dyn
,
2559 const char *location
)
2562 struct iovec
*outbody_v
;
2563 struct iovec
*outdyn_v
;
2564 uint32_t next_command_ofs
;
2566 DEBUG(10,("smbd_smb2_request_done_ex: "
2567 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2568 req
->current_idx
, nt_errstr(status
), (unsigned int)body
.length
,
2570 (unsigned int)(dyn
? dyn
->length
: 0),
2573 if (body
.length
< 2) {
2574 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2577 if ((body
.length
% 2) != 0) {
2578 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2581 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
2582 outbody_v
= SMBD_SMB2_OUT_BODY_IOV(req
);
2583 outdyn_v
= SMBD_SMB2_OUT_DYN_IOV(req
);
2585 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
2586 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
2588 outbody_v
->iov_base
= (void *)body
.data
;
2589 outbody_v
->iov_len
= body
.length
;
2592 outdyn_v
->iov_base
= (void *)dyn
->data
;
2593 outdyn_v
->iov_len
= dyn
->length
;
2595 outdyn_v
->iov_base
= NULL
;
2596 outdyn_v
->iov_len
= 0;
2599 /* see if we need to recalculate the offset to the next response */
2600 if (next_command_ofs
> 0) {
2601 next_command_ofs
= SMB2_HDR_BODY
;
2602 next_command_ofs
+= SMBD_SMB2_OUT_BODY_LEN(req
);
2603 next_command_ofs
+= SMBD_SMB2_OUT_DYN_LEN(req
);
2606 if ((next_command_ofs
% 8) != 0) {
2607 size_t pad_size
= 8 - (next_command_ofs
% 8);
2608 if (SMBD_SMB2_OUT_DYN_LEN(req
) == 0) {
2610 * if the dyn buffer is empty
2611 * we can use it to add padding
2615 pad
= talloc_zero_array(req
,
2618 return smbd_smb2_request_error(req
,
2619 NT_STATUS_NO_MEMORY
);
2622 outdyn_v
->iov_base
= (void *)pad
;
2623 outdyn_v
->iov_len
= pad_size
;
2626 * For now we copy the dynamic buffer
2627 * and add the padding to the new buffer
2634 old_size
= SMBD_SMB2_OUT_DYN_LEN(req
);
2635 old_dyn
= SMBD_SMB2_OUT_DYN_PTR(req
);
2637 new_size
= old_size
+ pad_size
;
2638 new_dyn
= talloc_zero_array(req
,
2640 if (new_dyn
== NULL
) {
2641 return smbd_smb2_request_error(req
,
2642 NT_STATUS_NO_MEMORY
);
2645 memcpy(new_dyn
, old_dyn
, old_size
);
2646 memset(new_dyn
+ old_size
, 0, pad_size
);
2648 outdyn_v
->iov_base
= (void *)new_dyn
;
2649 outdyn_v
->iov_len
= new_size
;
2651 next_command_ofs
+= pad_size
;
2654 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
2656 return smbd_smb2_request_reply(req
);
2659 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
2662 const char *location
)
2666 uint8_t *outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
2667 size_t unread_bytes
= smbd_smb2_unread_bytes(req
);
2669 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2670 req
->current_idx
, nt_errstr(status
), info
? " +info" : "",
2674 /* Recvfile error. Drain incoming socket. */
2678 ret
= drain_socket(req
->sconn
->sock
, unread_bytes
);
2679 if (ret
!= unread_bytes
) {
2683 error
= NT_STATUS_IO_DEVICE_ERROR
;
2685 error
= map_nt_error_from_unix_common(errno
);
2688 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2689 "ret[%u] errno[%d] => %s\n",
2690 (unsigned)unread_bytes
,
2691 (unsigned)ret
, errno
, nt_errstr(error
)));
2696 body
.data
= outhdr
+ SMB2_HDR_BODY
;
2698 SSVAL(body
.data
, 0, 9);
2701 SIVAL(body
.data
, 0x04, info
->length
);
2703 /* Allocated size of req->out.vector[i].iov_base
2704 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2705 * 1 byte without having to do an alloc.
2708 info
->data
= ((uint8_t *)outhdr
) +
2709 OUTVEC_ALLOC_SIZE
- 1;
2711 SCVAL(info
->data
, 0, 0);
2715 * Note: Even if there is an error, continue to process the request.
2719 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
2723 struct smbd_smb2_send_break_state
{
2724 struct smbd_server_connection
*sconn
;
2725 struct smbd_smb2_send_queue queue_entry
;
2726 uint8_t nbt_hdr
[NBT_HDR_SIZE
];
2727 uint8_t tf
[SMB2_TF_HDR_SIZE
];
2728 uint8_t hdr
[SMB2_HDR_BODY
];
2729 struct iovec vector
[1+SMBD_SMB2_NUM_IOV_PER_REQ
];
2733 static NTSTATUS
smbd_smb2_send_break(struct smbd_server_connection
*sconn
,
2734 struct smbXsrv_session
*session
,
2735 struct smbXsrv_tcon
*tcon
,
2736 const uint8_t *body
,
2739 struct smbd_smb2_send_break_state
*state
;
2740 struct smbXsrv_connection
*conn
= sconn
->conn
;
2741 bool do_encryption
= session
->global
->encryption_required
;
2742 uint64_t nonce_high
= 0;
2743 uint64_t nonce_low
= 0;
2747 if (tcon
->global
->encryption_required
) {
2748 do_encryption
= true;
2751 statelen
= offsetof(struct smbd_smb2_send_break_state
, body
) +
2754 state
= talloc_zero_size(sconn
, statelen
);
2755 if (state
== NULL
) {
2756 return NT_STATUS_NO_MEMORY
;
2758 talloc_set_name_const(state
, "struct smbd_smb2_send_break_state");
2759 state
->sconn
= sconn
;
2761 if (do_encryption
) {
2762 nonce_high
= session
->nonce_high
;
2763 nonce_low
= session
->nonce_low
;
2765 session
->nonce_low
+= 1;
2766 if (session
->nonce_low
== 0) {
2767 session
->nonce_low
+= 1;
2768 session
->nonce_high
+= 1;
2772 SIVAL(state
->tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
2773 SBVAL(state
->tf
, SMB2_TF_NONCE
+0, nonce_low
);
2774 SBVAL(state
->tf
, SMB2_TF_NONCE
+8, nonce_high
);
2775 SBVAL(state
->tf
, SMB2_TF_SESSION_ID
, session
->global
->session_wire_id
);
2777 SIVAL(state
->hdr
, 0, SMB2_MAGIC
);
2778 SSVAL(state
->hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
2779 SSVAL(state
->hdr
, SMB2_HDR_EPOCH
, 0);
2780 SIVAL(state
->hdr
, SMB2_HDR_STATUS
, 0);
2781 SSVAL(state
->hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
2782 SSVAL(state
->hdr
, SMB2_HDR_CREDIT
, 0);
2783 SIVAL(state
->hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
2784 SIVAL(state
->hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
2785 SBVAL(state
->hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
2786 SIVAL(state
->hdr
, SMB2_HDR_PID
, 0);
2787 SIVAL(state
->hdr
, SMB2_HDR_TID
, 0);
2788 SBVAL(state
->hdr
, SMB2_HDR_SESSION_ID
, 0);
2789 memset(state
->hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
2791 state
->vector
[0] = (struct iovec
) {
2792 .iov_base
= state
->nbt_hdr
,
2793 .iov_len
= sizeof(state
->nbt_hdr
)
2796 if (do_encryption
) {
2797 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
] = (struct iovec
) {
2798 .iov_base
= state
->tf
,
2799 .iov_len
= sizeof(state
->tf
)
2802 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
] = (struct iovec
) {
2808 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
] = (struct iovec
) {
2809 .iov_base
= state
->hdr
,
2810 .iov_len
= sizeof(state
->hdr
)
2813 memcpy(state
->body
, body
, body_len
);
2815 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
] = (struct iovec
) {
2816 .iov_base
= state
->body
,
2817 .iov_len
= body_len
/* no sizeof(state->body) .. :-) */
2821 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
2824 smb2_setup_nbt_length(state
->vector
, 1 + SMBD_SMB2_NUM_IOV_PER_REQ
);
2826 if (do_encryption
) {
2827 DATA_BLOB encryption_key
= session
->global
->encryption_key
;
2829 status
= smb2_signing_encrypt_pdu(encryption_key
,
2831 &state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
],
2832 SMBD_SMB2_NUM_IOV_PER_REQ
);
2833 if (!NT_STATUS_IS_OK(status
)) {
2838 state
->queue_entry
.mem_ctx
= state
;
2839 state
->queue_entry
.vector
= state
->vector
;
2840 state
->queue_entry
.count
= ARRAY_SIZE(state
->vector
);
2841 DLIST_ADD_END(state
->sconn
->smb2
.send_queue
, &state
->queue_entry
, NULL
);
2842 state
->sconn
->smb2
.send_queue_len
++;
2844 status
= smbd_smb2_flush_send_queue(sconn
);
2845 if (!NT_STATUS_IS_OK(status
)) {
2849 return NT_STATUS_OK
;
2852 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
2853 struct smbXsrv_session
*session
,
2854 struct smbXsrv_tcon
*tcon
,
2855 struct smbXsrv_open
*op
,
2856 uint8_t oplock_level
)
2860 SSVAL(body
, 0x00, sizeof(body
));
2861 SCVAL(body
, 0x02, oplock_level
);
2862 SCVAL(body
, 0x03, 0); /* reserved */
2863 SIVAL(body
, 0x04, 0); /* reserved */
2864 SBVAL(body
, 0x08, op
->global
->open_persistent_id
);
2865 SBVAL(body
, 0x10, op
->global
->open_volatile_id
);
2867 return smbd_smb2_send_break(sconn
, session
, tcon
, body
, sizeof(body
));
2870 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state
*state
)
2874 uint64_t file_id_persistent
;
2875 uint64_t file_id_volatile
;
2876 struct smbXsrv_open
*op
= NULL
;
2877 struct files_struct
*fsp
= NULL
;
2878 const uint8_t *body
= NULL
;
2881 * This is only called with a pktbuf
2882 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
2886 if (IVAL(state
->pktbuf
, 0) == SMB2_TF_MAGIC
) {
2887 /* Transform header. Cannot recvfile. */
2890 if (IVAL(state
->pktbuf
, 0) != SMB2_MAGIC
) {
2891 /* Not SMB2. Normal error path will cope. */
2894 if (SVAL(state
->pktbuf
, 4) != SMB2_HDR_BODY
) {
2895 /* Not SMB2. Normal error path will cope. */
2898 if (SVAL(state
->pktbuf
, SMB2_HDR_OPCODE
) != SMB2_OP_WRITE
) {
2899 /* Needs to be a WRITE. */
2902 if (IVAL(state
->pktbuf
, SMB2_HDR_NEXT_COMMAND
) != 0) {
2903 /* Chained. Cannot recvfile. */
2906 flags
= IVAL(state
->pktbuf
, SMB2_HDR_FLAGS
);
2907 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
2908 /* Chained. Cannot recvfile. */
2911 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
2912 /* Signed. Cannot recvfile. */
2916 body
= &state
->pktbuf
[SMB2_HDR_BODY
];
2918 file_id_persistent
= BVAL(body
, 0x10);
2919 file_id_volatile
= BVAL(body
, 0x18);
2921 status
= smb2srv_open_lookup(state
->req
->sconn
->conn
,
2926 if (!NT_STATUS_IS_OK(status
)) {
2934 if (fsp
->conn
== NULL
) {
2938 if (IS_IPC(fsp
->conn
)) {
2941 if (IS_PRINT(fsp
->conn
)) {
2945 DEBUG(10,("Doing recvfile write len = %u\n",
2946 (unsigned int)(state
->pktfull
- state
->pktlen
)));
2951 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
)
2953 struct smbd_smb2_request_read_state
*state
= &sconn
->smb2
.request_read_state
;
2954 size_t max_send_queue_len
;
2955 size_t cur_send_queue_len
;
2957 if (!NT_STATUS_IS_OK(sconn
->status
)) {
2959 * we're not supposed to do any io
2961 return NT_STATUS_OK
;
2964 if (state
->req
!= NULL
) {
2966 * if there is already a tstream_readv_pdu
2967 * pending, we are done.
2969 return NT_STATUS_OK
;
2972 max_send_queue_len
= MAX(1, sconn
->smb2
.max_credits
/16);
2973 cur_send_queue_len
= sconn
->smb2
.send_queue_len
;
2975 if (cur_send_queue_len
> max_send_queue_len
) {
2977 * if we have a lot of requests to send,
2978 * we wait until they are on the wire until we
2979 * ask for the next request.
2981 return NT_STATUS_OK
;
2984 /* ask for the next request */
2985 ZERO_STRUCTP(state
);
2986 state
->req
= smbd_smb2_request_allocate(sconn
);
2987 if (state
->req
== NULL
) {
2988 return NT_STATUS_NO_MEMORY
;
2990 state
->req
->sconn
= sconn
;
2991 state
->min_recv_size
= lp_min_receive_file_size();
2993 TEVENT_FD_READABLE(sconn
->smb2
.fde
);
2995 return NT_STATUS_OK
;
2998 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
2999 uint8_t *inbuf
, size_t size
)
3002 struct smbd_smb2_request
*req
= NULL
;
3004 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3005 (unsigned int)size
));
3007 status
= smbd_initialize_smb2(sconn
);
3008 if (!NT_STATUS_IS_OK(status
)) {
3009 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3013 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
3014 if (!NT_STATUS_IS_OK(status
)) {
3015 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3019 status
= smbd_smb2_request_validate(req
);
3020 if (!NT_STATUS_IS_OK(status
)) {
3021 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3025 status
= smbd_smb2_request_setup_out(req
);
3026 if (!NT_STATUS_IS_OK(status
)) {
3027 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3031 status
= smbd_smb2_request_dispatch(req
);
3032 if (!NT_STATUS_IS_OK(status
)) {
3033 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3037 status
= smbd_smb2_request_next_incoming(sconn
);
3038 if (!NT_STATUS_IS_OK(status
)) {
3039 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3043 sconn
->num_requests
++;
3046 static int socket_error_from_errno(int ret
,
3060 if (sys_errno
== 0) {
3064 if (sys_errno
== EINTR
) {
3069 if (sys_errno
== EINPROGRESS
) {
3074 if (sys_errno
== EAGAIN
) {
3079 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3080 if (sys_errno
== ENOMEM
) {
3086 #if EWOULDBLOCK != EAGAIN
3087 if (sys_errno
== EWOULDBLOCK
) {
3097 static NTSTATUS
smbd_smb2_flush_send_queue(struct smbd_server_connection
*sconn
)
3103 if (sconn
->smb2
.send_queue
== NULL
) {
3104 TEVENT_FD_NOT_WRITEABLE(sconn
->smb2
.fde
);
3105 return NT_STATUS_OK
;
3108 while (sconn
->smb2
.send_queue
!= NULL
) {
3109 struct smbd_smb2_send_queue
*e
= sconn
->smb2
.send_queue
;
3111 if (e
->sendfile_header
!= NULL
) {
3116 for (i
=0; i
< e
->count
; i
++) {
3117 size
+= e
->vector
[i
].iov_len
;
3120 if (size
<= e
->sendfile_header
->length
) {
3121 buf
= e
->sendfile_header
->data
;
3123 buf
= talloc_array(e
->mem_ctx
, uint8_t, size
);
3125 return NT_STATUS_NO_MEMORY
;
3130 for (i
=0; i
< e
->count
; i
++) {
3132 e
->vector
[i
].iov_base
,
3133 e
->vector
[i
].iov_len
);
3134 size
+= e
->vector
[i
].iov_len
;
3137 e
->sendfile_header
->data
= buf
;
3138 e
->sendfile_header
->length
= size
;
3141 sconn
->smb2
.send_queue_len
--;
3142 DLIST_REMOVE(sconn
->smb2
.send_queue
, e
);
3144 * This triggers the sendfile path via
3147 talloc_free(e
->mem_ctx
);
3151 ret
= writev(sconn
->sock
, e
->vector
, e
->count
);
3153 /* propagate end of file */
3154 return NT_STATUS_INTERNAL_ERROR
;
3156 err
= socket_error_from_errno(ret
, errno
, &retry
);
3159 TEVENT_FD_WRITEABLE(sconn
->smb2
.fde
);
3160 return NT_STATUS_OK
;
3163 return map_nt_error_from_unix_common(err
);
3166 if (ret
< e
->vector
[0].iov_len
) {
3168 base
= (uint8_t *)e
->vector
[0].iov_base
;
3170 e
->vector
[0].iov_base
= (void *)base
;
3171 e
->vector
[0].iov_len
-= ret
;
3174 ret
-= e
->vector
[0].iov_len
;
3180 * there're maybe some empty vectors at the end
3181 * which we need to skip, otherwise we would get
3182 * ret == 0 from the readv() call and return EPIPE
3184 while (e
->count
> 0) {
3185 if (e
->vector
[0].iov_len
> 0) {
3193 /* we have more to write */
3194 TEVENT_FD_WRITEABLE(sconn
->smb2
.fde
);
3195 return NT_STATUS_OK
;
3198 sconn
->smb2
.send_queue_len
--;
3199 DLIST_REMOVE(sconn
->smb2
.send_queue
, e
);
3200 talloc_free(e
->mem_ctx
);
3203 return NT_STATUS_OK
;
3206 static NTSTATUS
smbd_smb2_io_handler(struct smbd_server_connection
*sconn
,
3209 struct smbd_smb2_request_read_state
*state
= &sconn
->smb2
.request_read_state
;
3210 struct smbd_smb2_request
*req
= NULL
;
3211 size_t min_recvfile_size
= UINT32_MAX
;
3218 if (!NT_STATUS_IS_OK(sconn
->status
)) {
3220 * we're not supposed to do any io
3222 TEVENT_FD_NOT_READABLE(sconn
->smb2
.fde
);
3223 TEVENT_FD_NOT_WRITEABLE(sconn
->smb2
.fde
);
3224 return NT_STATUS_OK
;
3227 if (fde_flags
& TEVENT_FD_WRITE
) {
3228 status
= smbd_smb2_flush_send_queue(sconn
);
3229 if (!NT_STATUS_IS_OK(status
)) {
3234 if (!(fde_flags
& TEVENT_FD_READ
)) {
3235 return NT_STATUS_OK
;
3238 if (state
->req
== NULL
) {
3239 TEVENT_FD_NOT_READABLE(sconn
->smb2
.fde
);
3240 return NT_STATUS_OK
;
3244 if (!state
->hdr
.done
) {
3245 state
->hdr
.done
= true;
3247 state
->vector
.iov_base
= (void *)state
->hdr
.nbt
;
3248 state
->vector
.iov_len
= NBT_HDR_SIZE
;
3251 ret
= readv(sconn
->sock
, &state
->vector
, 1);
3253 /* propagate end of file */
3254 return NT_STATUS_END_OF_FILE
;
3256 err
= socket_error_from_errno(ret
, errno
, &retry
);
3259 TEVENT_FD_READABLE(sconn
->smb2
.fde
);
3260 return NT_STATUS_OK
;
3263 return map_nt_error_from_unix_common(err
);
3266 if (ret
< state
->vector
.iov_len
) {
3268 base
= (uint8_t *)state
->vector
.iov_base
;
3270 state
->vector
.iov_base
= (void *)base
;
3271 state
->vector
.iov_len
-= ret
;
3272 /* we have more to read */
3273 TEVENT_FD_READABLE(sconn
->smb2
.fde
);
3274 return NT_STATUS_OK
;
3277 if (state
->pktlen
> 0) {
3278 if (state
->doing_receivefile
&& !is_smb2_recvfile_write(state
)) {
3280 * Not a possible receivefile write.
3281 * Read the rest of the data.
3283 state
->doing_receivefile
= false;
3285 state
->pktbuf
= talloc_realloc(state
->req
,
3289 if (state
->pktbuf
== NULL
) {
3290 return NT_STATUS_NO_MEMORY
;
3293 state
->vector
.iov_base
= (void *)(state
->pktbuf
+
3295 state
->vector
.iov_len
= (state
->pktfull
-
3298 state
->pktlen
= state
->pktfull
;
3303 * Either this is a receivefile write so we've
3304 * done a short read, or if not we have all the data.
3310 * Now we analyze the NBT header
3312 if (state
->hdr
.nbt
[0] != 0x00) {
3313 state
->min_recv_size
= 0;
3315 state
->pktfull
= smb2_len(state
->hdr
.nbt
);
3316 if (state
->pktfull
== 0) {
3320 if (state
->min_recv_size
!= 0) {
3321 min_recvfile_size
= SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
;
3322 min_recvfile_size
+= state
->min_recv_size
;
3325 if (state
->pktfull
> min_recvfile_size
) {
3327 * Might be a receivefile write. Read the SMB2 HEADER +
3328 * SMB2_WRITE header first. Set 'doing_receivefile'
3329 * as we're *attempting* receivefile write. If this
3330 * turns out not to be a SMB2_WRITE request or otherwise
3331 * not suitable then we'll just read the rest of the data
3332 * the next time this function is called.
3334 state
->pktlen
= SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
;
3335 state
->doing_receivefile
= true;
3337 state
->pktlen
= state
->pktfull
;
3340 state
->pktbuf
= talloc_array(state
->req
, uint8_t, state
->pktlen
);
3341 if (state
->pktbuf
== NULL
) {
3342 return NT_STATUS_NO_MEMORY
;
3345 state
->vector
.iov_base
= (void *)state
->pktbuf
;
3346 state
->vector
.iov_len
= state
->pktlen
;
3352 if (state
->hdr
.nbt
[0] != 0x00) {
3353 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3354 state
->hdr
.nbt
[0]));
3357 ZERO_STRUCTP(state
);
3359 state
->min_recv_size
= lp_min_receive_file_size();
3367 req
->request_time
= timeval_current();
3368 now
= timeval_to_nttime(&req
->request_time
);
3370 status
= smbd_smb2_inbuf_parse_compound(req
->sconn
->conn
,
3376 &req
->in
.vector_count
);
3377 if (!NT_STATUS_IS_OK(status
)) {
3381 if (state
->doing_receivefile
) {
3382 req
->smb1req
= talloc_zero(req
, struct smb_request
);
3383 if (req
->smb1req
== NULL
) {
3384 return NT_STATUS_NO_MEMORY
;
3386 req
->smb1req
->unread_bytes
= state
->pktfull
- state
->pktlen
;
3389 ZERO_STRUCTP(state
);
3391 req
->current_idx
= 1;
3393 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3394 req
->current_idx
, req
->in
.vector_count
));
3396 status
= smbd_smb2_request_validate(req
);
3397 if (!NT_STATUS_IS_OK(status
)) {
3401 status
= smbd_smb2_request_setup_out(req
);
3402 if (!NT_STATUS_IS_OK(status
)) {
3406 status
= smbd_smb2_request_dispatch(req
);
3407 if (!NT_STATUS_IS_OK(status
)) {
3411 sconn
->num_requests
++;
3413 /* The timeout_processing function isn't run nearly
3414 often enough to implement 'max log size' without
3415 overrunning the size of the file by many megabytes.
3416 This is especially true if we are running at debug
3417 level 10. Checking every 50 SMB2s is a nice
3418 tradeoff of performance vs log file size overrun. */
3420 if ((sconn
->num_requests
% 50) == 0 &&
3421 need_to_check_log_size()) {
3422 change_to_root_user();
3426 status
= smbd_smb2_request_next_incoming(sconn
);
3427 if (!NT_STATUS_IS_OK(status
)) {
3431 return NT_STATUS_OK
;
3434 static void smbd_smb2_connection_handler(struct tevent_context
*ev
,
3435 struct tevent_fd
*fde
,
3439 struct smbd_server_connection
*sconn
=
3440 talloc_get_type_abort(private_data
,
3441 struct smbd_server_connection
);
3444 status
= smbd_smb2_io_handler(sconn
, flags
);
3445 if (!NT_STATUS_IS_OK(status
)) {
3446 smbd_server_connection_terminate(sconn
, nt_errstr(status
));