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 smbXsrv_connection
*xconn
);
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 smbXsrv_connection
*xconn
)
203 TALLOC_FREE(xconn
->transport
.fde
);
205 xconn
->smb2
.credits
.seq_low
= 0;
206 xconn
->smb2
.credits
.seq_range
= 1;
207 xconn
->smb2
.credits
.granted
= 1;
208 xconn
->smb2
.credits
.max
= lp_smb2_max_credits();
209 xconn
->smb2
.credits
.bitmap
= bitmap_talloc(xconn
,
210 xconn
->smb2
.credits
.max
);
211 if (xconn
->smb2
.credits
.bitmap
== NULL
) {
212 return NT_STATUS_NO_MEMORY
;
215 xconn
->transport
.fde
= tevent_add_fd(xconn
->ev_ctx
,
217 xconn
->transport
.sock
,
219 smbd_smb2_connection_handler
,
221 if (xconn
->transport
.fde
== NULL
) {
222 return NT_STATUS_NO_MEMORY
;
225 /* Ensure child is set to non-blocking mode */
226 set_blocking(xconn
->transport
.sock
, false);
230 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
231 #define _smb2_setlen(_buf,len) do { \
232 uint8_t *buf = (uint8_t *)_buf; \
234 buf[1] = ((len)&0xFF0000)>>16; \
235 buf[2] = ((len)&0xFF00)>>8; \
236 buf[3] = (len)&0xFF; \
239 static void smb2_setup_nbt_length(struct iovec
*vector
, int count
)
244 for (i
=1; i
< count
; i
++) {
245 len
+= vector
[i
].iov_len
;
248 _smb2_setlen(vector
[0].iov_base
, len
);
251 static int smbd_smb2_request_destructor(struct smbd_smb2_request
*req
)
253 if (req
->first_key
.length
> 0) {
254 data_blob_clear_free(&req
->first_key
);
256 if (req
->last_key
.length
> 0) {
257 data_blob_clear_free(&req
->last_key
);
262 static struct smbd_smb2_request
*smbd_smb2_request_allocate(TALLOC_CTX
*mem_ctx
)
264 TALLOC_CTX
*mem_pool
;
265 struct smbd_smb2_request
*req
;
268 /* Enable this to find subtle valgrind errors. */
269 mem_pool
= talloc_init("smbd_smb2_request_allocate");
271 mem_pool
= talloc_tos();
273 if (mem_pool
== NULL
) {
277 req
= talloc_zero(mem_pool
, struct smbd_smb2_request
);
279 talloc_free(mem_pool
);
282 talloc_reparent(mem_pool
, mem_ctx
, req
);
284 TALLOC_FREE(mem_pool
);
287 req
->last_session_id
= UINT64_MAX
;
288 req
->last_tid
= UINT32_MAX
;
290 talloc_set_destructor(req
, smbd_smb2_request_destructor
);
295 static NTSTATUS
smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection
*xconn
,
299 struct smbd_smb2_request
*req
,
303 TALLOC_CTX
*mem_ctx
= req
;
307 uint8_t *first_hdr
= buf
;
308 size_t verified_buflen
= 0;
313 * Note: index '0' is reserved for the transport protocol
315 iov
= req
->in
._vector
;
317 while (taken
< buflen
) {
318 size_t len
= buflen
- taken
;
319 uint8_t *hdr
= first_hdr
+ taken
;
322 size_t next_command_ofs
;
324 uint8_t *body
= NULL
;
327 struct iovec
*iov_alloc
= NULL
;
329 if (iov
!= req
->in
._vector
) {
333 if (verified_buflen
> taken
) {
334 len
= verified_buflen
- taken
;
341 DEBUG(10, ("%d bytes left, expected at least %d\n",
345 if (IVAL(hdr
, 0) == SMB2_TF_MAGIC
) {
346 struct smbXsrv_session
*s
= NULL
;
348 struct iovec tf_iov
[2];
352 if (xconn
->protocol
< PROTOCOL_SMB2_24
) {
353 DEBUG(10, ("Got SMB2_TRANSFORM header, "
354 "but dialect[0x%04X] is used\n",
355 xconn
->smb2
.server
.dialect
));
359 if (!(xconn
->smb2
.server
.capabilities
& SMB2_CAP_ENCRYPTION
)) {
360 DEBUG(10, ("Got SMB2_TRANSFORM header, "
361 "but not negotiated "
362 "client[0x%08X] server[0x%08X]\n",
363 xconn
->smb2
.client
.capabilities
,
364 xconn
->smb2
.server
.capabilities
));
368 if (len
< SMB2_TF_HDR_SIZE
) {
369 DEBUG(1, ("%d bytes left, expected at least %d\n",
370 (int)len
, SMB2_TF_HDR_SIZE
));
374 tf_len
= SMB2_TF_HDR_SIZE
;
377 hdr
= first_hdr
+ taken
;
378 enc_len
= IVAL(tf
, SMB2_TF_MSG_SIZE
);
379 uid
= BVAL(tf
, SMB2_TF_SESSION_ID
);
381 if (len
< SMB2_TF_HDR_SIZE
+ enc_len
) {
382 DEBUG(1, ("%d bytes left, expected at least %d\n",
384 (int)(SMB2_TF_HDR_SIZE
+ enc_len
)));
388 status
= smb2srv_session_lookup(xconn
, uid
, now
, &s
);
390 DEBUG(1, ("invalid session[%llu] in "
391 "SMB2_TRANSFORM header\n",
392 (unsigned long long)uid
));
393 TALLOC_FREE(iov_alloc
);
394 return NT_STATUS_USER_SESSION_DELETED
;
397 tf_iov
[0].iov_base
= (void *)tf
;
398 tf_iov
[0].iov_len
= tf_len
;
399 tf_iov
[1].iov_base
= (void *)hdr
;
400 tf_iov
[1].iov_len
= enc_len
;
402 status
= smb2_signing_decrypt_pdu(s
->global
->decryption_key
,
405 if (!NT_STATUS_IS_OK(status
)) {
406 TALLOC_FREE(iov_alloc
);
410 verified_buflen
= taken
+ enc_len
;
415 * We need the header plus the body length field
418 if (len
< SMB2_HDR_BODY
+ 2) {
419 DEBUG(10, ("%d bytes left, expected at least %d\n",
420 (int)len
, SMB2_HDR_BODY
));
423 if (IVAL(hdr
, 0) != SMB2_MAGIC
) {
424 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
428 if (SVAL(hdr
, 4) != SMB2_HDR_BODY
) {
429 DEBUG(10, ("Got HDR len %d, expected %d\n",
430 SVAL(hdr
, 4), SMB2_HDR_BODY
));
435 next_command_ofs
= IVAL(hdr
, SMB2_HDR_NEXT_COMMAND
);
436 body_size
= SVAL(hdr
, SMB2_HDR_BODY
);
438 if (next_command_ofs
!= 0) {
439 if (next_command_ofs
< (SMB2_HDR_BODY
+ 2)) {
442 if (next_command_ofs
> full_size
) {
445 full_size
= next_command_ofs
;
452 if (body_size
> (full_size
- SMB2_HDR_BODY
)) {
454 * let the caller handle the error
456 body_size
= full_size
- SMB2_HDR_BODY
;
458 body
= hdr
+ SMB2_HDR_BODY
;
459 dyn
= body
+ body_size
;
460 dyn_size
= full_size
- (SMB2_HDR_BODY
+ body_size
);
462 if (num_iov
>= ARRAY_SIZE(req
->in
._vector
)) {
463 struct iovec
*iov_tmp
= NULL
;
465 iov_tmp
= talloc_realloc(mem_ctx
, iov_alloc
,
468 SMBD_SMB2_NUM_IOV_PER_REQ
);
469 if (iov_tmp
== NULL
) {
470 TALLOC_FREE(iov_alloc
);
471 return NT_STATUS_NO_MEMORY
;
474 if (iov_alloc
== NULL
) {
477 sizeof(req
->in
._vector
));
483 num_iov
+= SMBD_SMB2_NUM_IOV_PER_REQ
;
485 cur
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= tf
;
486 cur
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= tf_len
;
487 cur
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
488 cur
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
489 cur
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
490 cur
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= body_size
;
491 cur
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
492 cur
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= dyn_size
;
502 if (iov
!= req
->in
._vector
) {
505 return NT_STATUS_INVALID_PARAMETER
;
508 static NTSTATUS
smbd_smb2_request_create(struct smbXsrv_connection
*xconn
,
509 uint8_t *inbuf
, size_t size
,
510 struct smbd_smb2_request
**_req
)
512 struct smbd_server_connection
*sconn
= xconn
->sconn
;
513 struct smbd_smb2_request
*req
;
514 uint32_t protocol_version
;
515 const uint8_t *inhdr
= NULL
;
517 uint32_t next_command_ofs
;
521 if (size
< (4 + SMB2_HDR_BODY
+ 2)) {
522 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size
));
523 return NT_STATUS_INVALID_PARAMETER
;
528 protocol_version
= IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
);
529 if (protocol_version
!= SMB2_MAGIC
) {
530 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
532 return NT_STATUS_INVALID_PARAMETER
;
535 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
536 if (cmd
!= SMB2_OP_NEGPROT
) {
537 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
539 return NT_STATUS_INVALID_PARAMETER
;
542 next_command_ofs
= IVAL(inhdr
, SMB2_HDR_NEXT_COMMAND
);
543 if (next_command_ofs
!= 0) {
544 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
546 return NT_STATUS_INVALID_PARAMETER
;
549 req
= smbd_smb2_request_allocate(xconn
);
551 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(xconn
,
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 smbXsrv_connection
*xconn
,
579 uint64_t message_id
, uint64_t seq_id
)
581 struct bitmap
*credits_bm
= xconn
->smb2
.credits
.bitmap
;
585 seq_tmp
= xconn
->smb2
.credits
.seq_low
;
586 if (seq_id
< seq_tmp
) {
587 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
588 "%llu (sequence id %llu) "
589 "(granted = %u, low = %llu, range = %u)\n",
590 (unsigned long long)message_id
,
591 (unsigned long long)seq_id
,
592 (unsigned int)xconn
->smb2
.credits
.granted
,
593 (unsigned long long)xconn
->smb2
.credits
.seq_low
,
594 (unsigned int)xconn
->smb2
.credits
.seq_range
));
598 seq_tmp
+= xconn
->smb2
.credits
.seq_range
;
599 if (seq_id
>= seq_tmp
) {
600 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
601 "%llu (sequence id %llu) "
602 "(granted = %u, low = %llu, range = %u)\n",
603 (unsigned long long)message_id
,
604 (unsigned long long)seq_id
,
605 (unsigned int)xconn
->smb2
.credits
.granted
,
606 (unsigned long long)xconn
->smb2
.credits
.seq_low
,
607 (unsigned int)xconn
->smb2
.credits
.seq_range
));
611 offset
= seq_id
% xconn
->smb2
.credits
.max
;
613 if (bitmap_query(credits_bm
, offset
)) {
614 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
615 "%llu (sequence id %llu) "
616 "(granted = %u, low = %llu, range = %u) "
618 (unsigned long long)message_id
,
619 (unsigned long long)seq_id
,
620 (unsigned int)xconn
->smb2
.credits
.granted
,
621 (unsigned long long)xconn
->smb2
.credits
.seq_low
,
622 (unsigned int)xconn
->smb2
.credits
.seq_range
,
627 /* Mark the message_ids as seen in the bitmap. */
628 bitmap_set(credits_bm
, offset
);
630 if (seq_id
!= xconn
->smb2
.credits
.seq_low
) {
635 * Move the window forward by all the message_id's
638 while (bitmap_query(credits_bm
, offset
)) {
639 DEBUG(10,("smb2_validate_sequence_number: clearing "
640 "id %llu (position %u) from bitmap\n",
641 (unsigned long long)(xconn
->smb2
.credits
.seq_low
),
643 bitmap_clear(credits_bm
, offset
);
645 xconn
->smb2
.credits
.seq_low
+= 1;
646 xconn
->smb2
.credits
.seq_range
-= 1;
647 offset
= xconn
->smb2
.credits
.seq_low
% xconn
->smb2
.credits
.max
;
653 static bool smb2_validate_message_id(struct smbXsrv_connection
*xconn
,
654 const uint8_t *inhdr
)
656 uint64_t message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
657 uint16_t opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
658 uint16_t credit_charge
= 1;
661 if (opcode
== SMB2_OP_CANCEL
) {
662 /* SMB2_CANCEL requests by definition resend messageids. */
666 if (xconn
->smb2
.credits
.multicredit
) {
667 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
668 credit_charge
= MAX(credit_charge
, 1);
671 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
672 "credits_granted %llu, "
673 "seqnum low/range: %llu/%llu\n",
674 (unsigned long long) message_id
,
675 (unsigned long long) credit_charge
,
676 (unsigned long long) xconn
->smb2
.credits
.granted
,
677 (unsigned long long) xconn
->smb2
.credits
.seq_low
,
678 (unsigned long long) xconn
->smb2
.credits
.seq_range
));
680 if (xconn
->smb2
.credits
.granted
< credit_charge
) {
681 DEBUG(0, ("smb2_validate_message_id: client used more "
682 "credits than granted, mid %llu, charge %llu, "
683 "credits_granted %llu, "
684 "seqnum low/range: %llu/%llu\n",
685 (unsigned long long) message_id
,
686 (unsigned long long) credit_charge
,
687 (unsigned long long) xconn
->smb2
.credits
.granted
,
688 (unsigned long long) xconn
->smb2
.credits
.seq_low
,
689 (unsigned long long) xconn
->smb2
.credits
.seq_range
));
694 * now check the message ids
696 * for multi-credit requests we need to check all current mid plus
697 * the implicit mids caused by the credit charge
698 * e.g. current mid = 15, charge 5 => mark 15-19 as used
701 for (i
= 0; i
<= (credit_charge
-1); i
++) {
702 uint64_t id
= message_id
+ i
;
705 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
706 (unsigned long long)message_id
,
708 (unsigned long long)id
));
710 ok
= smb2_validate_sequence_number(xconn
, message_id
, id
);
716 /* substract used credits */
717 xconn
->smb2
.credits
.granted
-= credit_charge
;
722 static NTSTATUS
smbd_smb2_request_validate(struct smbd_smb2_request
*req
)
727 count
= req
->in
.vector_count
;
729 if (count
< 1 + SMBD_SMB2_NUM_IOV_PER_REQ
) {
730 /* It's not a SMB2 request */
731 return NT_STATUS_INVALID_PARAMETER
;
734 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
735 struct iovec
*hdr
= SMBD_SMB2_IDX_HDR_IOV(req
,in
,idx
);
736 struct iovec
*body
= SMBD_SMB2_IDX_BODY_IOV(req
,in
,idx
);
737 const uint8_t *inhdr
= NULL
;
739 if (hdr
->iov_len
!= SMB2_HDR_BODY
) {
740 return NT_STATUS_INVALID_PARAMETER
;
743 if (body
->iov_len
< 2) {
744 return NT_STATUS_INVALID_PARAMETER
;
747 inhdr
= (const uint8_t *)hdr
->iov_base
;
749 /* Check the SMB2 header */
750 if (IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
) != SMB2_MAGIC
) {
751 return NT_STATUS_INVALID_PARAMETER
;
754 if (!smb2_validate_message_id(req
->xconn
, inhdr
)) {
755 return NT_STATUS_INVALID_PARAMETER
;
762 static void smb2_set_operation_credit(struct smbXsrv_connection
*xconn
,
763 const struct iovec
*in_vector
,
764 struct iovec
*out_vector
)
766 struct smbd_server_connection
*sconn
= xconn
->sconn
;
767 const uint8_t *inhdr
= (const uint8_t *)in_vector
->iov_base
;
768 uint8_t *outhdr
= (uint8_t *)out_vector
->iov_base
;
769 uint16_t credit_charge
= 1;
770 uint16_t credits_requested
;
774 uint16_t credits_granted
= 0;
775 uint64_t credits_possible
;
776 uint16_t current_max_credits
;
779 * first we grant only 1/16th of the max range.
781 * Windows also starts with the 1/16th and then grants
782 * more later. I was only able to trigger higher
783 * values, when using a very high credit charge.
785 * TODO: scale up depending on load, free memory
787 * Maybe also on the relationship between number
788 * of requests and the used sequence number.
789 * Which means we would grant more credits
790 * for client which use multi credit requests.
792 current_max_credits
= xconn
->smb2
.credits
.max
/ 16;
793 current_max_credits
= MAX(current_max_credits
, 1);
795 if (xconn
->smb2
.credits
.multicredit
) {
796 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
797 credit_charge
= MAX(credit_charge
, 1);
800 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
801 credits_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
802 out_flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
803 out_status
= NT_STATUS(IVAL(outhdr
, SMB2_HDR_STATUS
));
805 SMB_ASSERT(xconn
->smb2
.credits
.max
>= xconn
->smb2
.credits
.granted
);
807 if (xconn
->smb2
.credits
.max
< credit_charge
) {
808 smbd_server_connection_terminate(sconn
,
809 "client error: credit charge > max credits\n");
813 if (out_flags
& SMB2_HDR_FLAG_ASYNC
) {
815 * In case we already send an async interim
816 * response, we should not grant
817 * credits on the final response.
820 } else if (credits_requested
> 0) {
821 uint16_t additional_max
= 0;
822 uint16_t additional_credits
= credits_requested
- 1;
825 case SMB2_OP_NEGPROT
:
827 case SMB2_OP_SESSSETUP
:
829 * Windows 2012 RC1 starts to grant
831 * with a successful session setup
833 if (NT_STATUS_IS_OK(out_status
)) {
839 * We match windows and only grant additional credits
846 additional_credits
= MIN(additional_credits
, additional_max
);
848 credits_granted
= credit_charge
+ additional_credits
;
849 } else if (xconn
->smb2
.credits
.granted
== 0) {
851 * Make sure the client has always at least one credit
857 * sequence numbers should not wrap
859 * 1. calculate the possible credits until
860 * the sequence numbers start to wrap on 64-bit.
862 * 2. UINT64_MAX is used for Break Notifications.
864 * 2. truncate the possible credits to the maximum
865 * credits we want to grant to the client in total.
867 * 3. remove the range we'll already granted to the client
868 * this makes sure the client consumes the lowest sequence
869 * number, before we can grant additional credits.
871 credits_possible
= UINT64_MAX
- xconn
->smb2
.credits
.seq_low
;
872 if (credits_possible
> 0) {
873 /* remove UINT64_MAX */
874 credits_possible
-= 1;
876 credits_possible
= MIN(credits_possible
, current_max_credits
);
877 credits_possible
-= xconn
->smb2
.credits
.seq_range
;
879 credits_granted
= MIN(credits_granted
, credits_possible
);
881 SSVAL(outhdr
, SMB2_HDR_CREDIT
, credits_granted
);
882 xconn
->smb2
.credits
.granted
+= credits_granted
;
883 xconn
->smb2
.credits
.seq_range
+= credits_granted
;
885 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
886 "granted %u, current possible/max %u/%u, "
887 "total granted/max/low/range %u/%u/%llu/%u\n",
888 (unsigned int)credits_requested
,
889 (unsigned int)credit_charge
,
890 (unsigned int)credits_granted
,
891 (unsigned int)credits_possible
,
892 (unsigned int)current_max_credits
,
893 (unsigned int)xconn
->smb2
.credits
.granted
,
894 (unsigned int)xconn
->smb2
.credits
.max
,
895 (unsigned long long)xconn
->smb2
.credits
.seq_low
,
896 (unsigned int)xconn
->smb2
.credits
.seq_range
));
899 static void smb2_calculate_credits(const struct smbd_smb2_request
*inreq
,
900 struct smbd_smb2_request
*outreq
)
903 uint16_t total_credits
= 0;
905 count
= outreq
->out
.vector_count
;
907 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
908 struct iovec
*inhdr_v
= SMBD_SMB2_IDX_HDR_IOV(inreq
,in
,idx
);
909 struct iovec
*outhdr_v
= SMBD_SMB2_IDX_HDR_IOV(outreq
,out
,idx
);
910 uint8_t *outhdr
= (uint8_t *)outhdr_v
->iov_base
;
912 smb2_set_operation_credit(outreq
->xconn
, inhdr_v
, outhdr_v
);
914 /* To match Windows, count up what we
916 total_credits
+= SVAL(outhdr
, SMB2_HDR_CREDIT
);
917 /* Set to zero in all but the last reply. */
918 if (idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
< count
) {
919 SSVAL(outhdr
, SMB2_HDR_CREDIT
, 0);
921 SSVAL(outhdr
, SMB2_HDR_CREDIT
, total_credits
);
926 DATA_BLOB
smbd_smb2_generate_outbody(struct smbd_smb2_request
*req
, size_t size
)
928 if (req
->current_idx
<= 1) {
929 if (size
<= sizeof(req
->out
._body
)) {
930 return data_blob_const(req
->out
._body
, size
);
934 return data_blob_talloc(req
, NULL
, size
);
937 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
)
939 struct smbXsrv_connection
*xconn
= req
->xconn
;
941 struct iovec
*vector
;
945 count
= req
->in
.vector_count
;
946 if (count
<= ARRAY_SIZE(req
->out
._vector
)) {
948 vector
= req
->out
._vector
;
950 vector
= talloc_zero_array(req
, struct iovec
, count
);
951 if (vector
== NULL
) {
952 return NT_STATUS_NO_MEMORY
;
957 vector
[0].iov_base
= req
->out
.nbt_hdr
;
958 vector
[0].iov_len
= 4;
959 SIVAL(req
->out
.nbt_hdr
, 0, 0);
961 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
962 struct iovec
*inhdr_v
= SMBD_SMB2_IDX_HDR_IOV(req
,in
,idx
);
963 const uint8_t *inhdr
= (const uint8_t *)inhdr_v
->iov_base
;
964 uint8_t *outhdr
= NULL
;
965 uint8_t *outbody
= NULL
;
966 uint32_t next_command_ofs
= 0;
967 struct iovec
*current
= &vector
[idx
];
969 if ((idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
) < count
) {
970 /* we have a next command -
971 * setup for the error case. */
972 next_command_ofs
= SMB2_HDR_BODY
+ 9;
976 outhdr
= req
->out
._hdr
;
978 outhdr
= talloc_zero_array(mem_ctx
, uint8_t,
980 if (outhdr
== NULL
) {
981 return NT_STATUS_NO_MEMORY
;
985 outbody
= outhdr
+ SMB2_HDR_BODY
;
988 * SMBD_SMB2_TF_IOV_OFS might be used later
990 current
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
991 current
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
993 current
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= (void *)outhdr
;
994 current
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
996 current
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= (void *)outbody
;
997 current
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= 8;
999 current
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= NULL
;
1000 current
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= 0;
1002 /* setup the SMB2 header */
1003 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
1004 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1005 SSVAL(outhdr
, SMB2_HDR_CREDIT_CHARGE
,
1006 SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
));
1007 SIVAL(outhdr
, SMB2_HDR_STATUS
,
1008 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
1009 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
1010 SVAL(inhdr
, SMB2_HDR_OPCODE
));
1011 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
1012 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
1013 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
1014 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
1015 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
1016 SIVAL(outhdr
, SMB2_HDR_PID
,
1017 IVAL(inhdr
, SMB2_HDR_PID
));
1018 SIVAL(outhdr
, SMB2_HDR_TID
,
1019 IVAL(inhdr
, SMB2_HDR_TID
));
1020 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
1021 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
1022 memcpy(outhdr
+ SMB2_HDR_SIGNATURE
,
1023 inhdr
+ SMB2_HDR_SIGNATURE
, 16);
1025 /* setup error body header */
1026 SSVAL(outbody
, 0x00, 0x08 + 1);
1027 SSVAL(outbody
, 0x02, 0);
1028 SIVAL(outbody
, 0x04, 0);
1031 req
->out
.vector
= vector
;
1032 req
->out
.vector_count
= count
;
1034 /* setup the length of the NBT packet */
1035 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
1037 DLIST_ADD_END(xconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
1039 return NT_STATUS_OK
;
1042 void smbd_server_connection_terminate_ex(struct smbd_server_connection
*sconn
,
1044 const char *location
)
1046 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1048 exit_server_cleanly(reason
);
1051 static bool dup_smb2_vec4(TALLOC_CTX
*ctx
,
1052 struct iovec
*outvec
,
1053 const struct iovec
*srcvec
)
1055 const uint8_t *srctf
;
1057 const uint8_t *srchdr
;
1059 const uint8_t *srcbody
;
1061 const uint8_t *expected_srcbody
;
1062 const uint8_t *srcdyn
;
1064 const uint8_t *expected_srcdyn
;
1070 srctf
= (const uint8_t *)srcvec
[SMBD_SMB2_TF_IOV_OFS
].iov_base
;
1071 srctf_len
= srcvec
[SMBD_SMB2_TF_IOV_OFS
].iov_len
;
1072 srchdr
= (const uint8_t *)srcvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
;
1073 srchdr_len
= srcvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
;
1074 srcbody
= (const uint8_t *)srcvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
;
1075 srcbody_len
= srcvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
;
1076 expected_srcbody
= srchdr
+ SMB2_HDR_BODY
;
1077 srcdyn
= (const uint8_t *)srcvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
;
1078 srcdyn_len
= srcvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
;
1079 expected_srcdyn
= srcbody
+ 8;
1081 if ((srctf_len
!= SMB2_TF_HDR_SIZE
) && (srctf_len
!= 0)) {
1085 if (srchdr_len
!= SMB2_HDR_BODY
) {
1089 if (srctf_len
== SMB2_TF_HDR_SIZE
) {
1090 dsttf
= talloc_memdup(ctx
, srctf
, SMB2_TF_HDR_SIZE
);
1091 if (dsttf
== NULL
) {
1097 outvec
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= (void *)dsttf
;
1098 outvec
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= srctf_len
;
1100 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1101 * be allocated with size OUTVEC_ALLOC_SIZE. */
1103 dsthdr
= talloc_memdup(ctx
, srchdr
, OUTVEC_ALLOC_SIZE
);
1104 if (dsthdr
== NULL
) {
1107 outvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= (void *)dsthdr
;
1108 outvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
1111 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1112 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1113 * then duplicate this. Else use talloc_memdup().
1116 if ((srcbody
== expected_srcbody
) && (srcbody_len
== 8)) {
1117 dstbody
= dsthdr
+ SMB2_HDR_BODY
;
1119 dstbody
= talloc_memdup(ctx
, srcbody
, srcbody_len
);
1120 if (dstbody
== NULL
) {
1124 outvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= (void *)dstbody
;
1125 outvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= srcbody_len
;
1128 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1130 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1131 * then duplicate this. Else use talloc_memdup().
1134 if ((srcdyn
== expected_srcdyn
) && (srcdyn_len
== 1)) {
1135 dstdyn
= dsthdr
+ SMB2_HDR_BODY
+ 8;
1136 } else if (srcdyn
== NULL
) {
1139 dstdyn
= talloc_memdup(ctx
, srcdyn
, srcdyn_len
);
1140 if (dstdyn
== NULL
) {
1144 outvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= (void *)dstdyn
;
1145 outvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= srcdyn_len
;
1150 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
1152 struct smbd_smb2_request
*newreq
= NULL
;
1153 struct iovec
*outvec
= NULL
;
1154 int count
= req
->out
.vector_count
;
1157 newreq
= smbd_smb2_request_allocate(req
->xconn
);
1162 newreq
->sconn
= req
->sconn
;
1163 newreq
->xconn
= req
->xconn
;
1164 newreq
->session
= req
->session
;
1165 newreq
->do_encryption
= req
->do_encryption
;
1166 newreq
->do_signing
= req
->do_signing
;
1167 newreq
->current_idx
= req
->current_idx
;
1169 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
1171 TALLOC_FREE(newreq
);
1174 newreq
->out
.vector
= outvec
;
1175 newreq
->out
.vector_count
= count
;
1177 /* Setup the outvec's identically to req. */
1178 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
1179 outvec
[0].iov_len
= 4;
1180 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
1182 /* Setup the vectors identically to the ones in req. */
1183 for (i
= 1; i
< count
; i
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
1184 if (!dup_smb2_vec4(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
1191 TALLOC_FREE(newreq
);
1195 smb2_setup_nbt_length(newreq
->out
.vector
,
1196 newreq
->out
.vector_count
);
1201 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
1203 struct smbXsrv_connection
*xconn
= req
->xconn
;
1205 struct iovec
*firsttf
= NULL
;
1206 struct iovec
*outhdr_v
= NULL
;
1207 uint8_t *outhdr
= NULL
;
1208 struct smbd_smb2_request
*nreq
= NULL
;
1211 /* Create a new smb2 request we'll use
1212 for the interim return. */
1213 nreq
= dup_smb2_req(req
);
1215 return NT_STATUS_NO_MEMORY
;
1218 /* Lose the last X out vectors. They're the
1219 ones we'll be using for the async reply. */
1220 nreq
->out
.vector_count
-= SMBD_SMB2_NUM_IOV_PER_REQ
;
1222 smb2_setup_nbt_length(nreq
->out
.vector
,
1223 nreq
->out
.vector_count
);
1225 /* Step back to the previous reply. */
1226 nreq
->current_idx
-= SMBD_SMB2_NUM_IOV_PER_REQ
;
1227 firsttf
= SMBD_SMB2_IDX_TF_IOV(nreq
,out
,first_idx
);
1228 outhdr_v
= SMBD_SMB2_OUT_HDR_IOV(nreq
);
1229 outhdr
= SMBD_SMB2_OUT_HDR_PTR(nreq
);
1230 /* And end the chain. */
1231 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1233 /* Calculate outgoing credits */
1234 smb2_calculate_credits(req
, nreq
);
1236 if (DEBUGLEVEL
>= 10) {
1237 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1238 (unsigned int)nreq
->current_idx
);
1239 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1240 (unsigned int)nreq
->out
.vector_count
);
1241 print_req_vectors(nreq
);
1245 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1246 * we need to sign/encrypt here with the last/first key we remembered
1248 if (firsttf
->iov_len
== SMB2_TF_HDR_SIZE
) {
1249 status
= smb2_signing_encrypt_pdu(req
->first_key
,
1252 nreq
->out
.vector_count
- first_idx
);
1253 if (!NT_STATUS_IS_OK(status
)) {
1256 } else if (req
->last_key
.length
> 0) {
1257 status
= smb2_signing_sign_pdu(req
->last_key
,
1260 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
1261 if (!NT_STATUS_IS_OK(status
)) {
1266 nreq
->queue_entry
.mem_ctx
= nreq
;
1267 nreq
->queue_entry
.vector
= nreq
->out
.vector
;
1268 nreq
->queue_entry
.count
= nreq
->out
.vector_count
;
1269 DLIST_ADD_END(xconn
->smb2
.send_queue
, &nreq
->queue_entry
, NULL
);
1270 xconn
->smb2
.send_queue_len
++;
1272 status
= smbd_smb2_flush_send_queue(xconn
);
1273 if (!NT_STATUS_IS_OK(status
)) {
1277 return NT_STATUS_OK
;
1280 struct smbd_smb2_request_pending_state
{
1281 struct smbd_smb2_send_queue queue_entry
;
1282 uint8_t buf
[NBT_HDR_SIZE
+ SMB2_TF_HDR_SIZE
+ SMB2_HDR_BODY
+ 0x08 + 1];
1283 struct iovec vector
[1 + SMBD_SMB2_NUM_IOV_PER_REQ
];
1286 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
1287 struct tevent_timer
*te
,
1288 struct timeval current_time
,
1289 void *private_data
);
1291 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
1292 struct tevent_req
*subreq
,
1293 uint32_t defer_time
)
1296 struct timeval defer_endtime
;
1297 uint8_t *outhdr
= NULL
;
1300 if (!tevent_req_is_in_progress(subreq
)) {
1302 * This is a performance optimization,
1303 * it avoids one tevent_loop iteration,
1304 * which means we avoid one
1305 * talloc_stackframe_pool/talloc_free pair.
1307 tevent_req_notify_callback(subreq
);
1308 return NT_STATUS_OK
;
1311 req
->subreq
= subreq
;
1314 if (req
->async_te
) {
1315 /* We're already async. */
1316 return NT_STATUS_OK
;
1319 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1320 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1321 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1322 /* We're already async. */
1323 return NT_STATUS_OK
;
1326 if (req
->in
.vector_count
> req
->current_idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
) {
1328 * We're trying to go async in a compound
1330 * This is only allowed for opens that
1331 * cause an oplock break, otherwise it
1332 * is not allowed. See [MS-SMB2].pdf
1333 * note <194> on Section 3.3.5.2.7.
1335 const uint8_t *inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1337 if (SVAL(inhdr
, SMB2_HDR_OPCODE
) != SMB2_OP_CREATE
) {
1339 * Cancel the outstanding request.
1341 bool ok
= tevent_req_cancel(req
->subreq
);
1343 return NT_STATUS_OK
;
1345 TALLOC_FREE(req
->subreq
);
1346 return smbd_smb2_request_error(req
,
1347 NT_STATUS_INTERNAL_ERROR
);
1351 if (DEBUGLEVEL
>= 10) {
1352 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1353 (unsigned int)req
->current_idx
);
1354 print_req_vectors(req
);
1357 if (req
->current_idx
> 1) {
1359 * We're going async in a compound
1360 * chain after the first request has
1361 * already been processed. Send an
1362 * interim response containing the
1363 * set of replies already generated.
1365 int idx
= req
->current_idx
;
1367 status
= smb2_send_async_interim_response(req
);
1368 if (!NT_STATUS_IS_OK(status
)) {
1371 if (req
->first_key
.length
> 0) {
1372 data_blob_clear_free(&req
->first_key
);
1375 req
->current_idx
= 1;
1378 * Re-arrange the in.vectors to remove what
1381 memmove(&req
->in
.vector
[1],
1382 &req
->in
.vector
[idx
],
1383 sizeof(req
->in
.vector
[0])*(req
->in
.vector_count
- idx
));
1384 req
->in
.vector_count
= 1 + (req
->in
.vector_count
- idx
);
1386 /* Re-arrange the out.vectors to match. */
1387 memmove(&req
->out
.vector
[1],
1388 &req
->out
.vector
[idx
],
1389 sizeof(req
->out
.vector
[0])*(req
->out
.vector_count
- idx
));
1390 req
->out
.vector_count
= 1 + (req
->out
.vector_count
- idx
);
1392 if (req
->in
.vector_count
== 1 + SMBD_SMB2_NUM_IOV_PER_REQ
) {
1394 * We only have one remaining request as
1395 * we've processed everything else.
1396 * This is no longer a compound request.
1398 req
->compound_related
= false;
1399 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1400 flags
= (IVAL(outhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
1401 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
);
1404 if (req
->last_key
.length
> 0) {
1405 data_blob_clear_free(&req
->last_key
);
1408 defer_endtime
= timeval_current_ofs_usec(defer_time
);
1409 req
->async_te
= tevent_add_timer(req
->sconn
->ev_ctx
,
1411 smbd_smb2_request_pending_timer
,
1413 if (req
->async_te
== NULL
) {
1414 return NT_STATUS_NO_MEMORY
;
1417 return NT_STATUS_OK
;
1420 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
1421 struct tevent_timer
*te
,
1422 struct timeval current_time
,
1425 struct smbd_smb2_request
*req
=
1426 talloc_get_type_abort(private_data
,
1427 struct smbd_smb2_request
);
1428 struct smbXsrv_connection
*xconn
= req
->xconn
;
1429 struct smbd_smb2_request_pending_state
*state
= NULL
;
1430 uint8_t *outhdr
= NULL
;
1431 const uint8_t *inhdr
= NULL
;
1434 uint8_t *hdr
= NULL
;
1435 uint8_t *body
= NULL
;
1436 uint8_t *dyn
= NULL
;
1438 uint64_t session_id
= 0;
1439 uint64_t message_id
= 0;
1440 uint64_t nonce_high
= 0;
1441 uint64_t nonce_low
= 0;
1442 uint64_t async_id
= 0;
1445 TALLOC_FREE(req
->async_te
);
1447 /* Ensure our final reply matches the interim one. */
1448 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1449 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1450 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1451 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1452 session_id
= BVAL(outhdr
, SMB2_HDR_SESSION_ID
);
1454 async_id
= message_id
; /* keep it simple for now... */
1456 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1457 SBVAL(outhdr
, SMB2_HDR_ASYNC_ID
, async_id
);
1459 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1461 smb2_opcode_name(SVAL(inhdr
, SMB2_HDR_OPCODE
)),
1462 (unsigned long long)async_id
));
1465 * What we send is identical to a smbd_smb2_request_error
1466 * packet with an error status of STATUS_PENDING. Make use
1467 * of this fact sometime when refactoring. JRA.
1470 state
= talloc_zero(req
->xconn
, struct smbd_smb2_request_pending_state
);
1471 if (state
== NULL
) {
1472 smbd_server_connection_terminate(req
->sconn
,
1473 nt_errstr(NT_STATUS_NO_MEMORY
));
1477 tf
= state
->buf
+ NBT_HDR_SIZE
;
1478 tf_len
= SMB2_TF_HDR_SIZE
;
1480 hdr
= tf
+ SMB2_TF_HDR_SIZE
;
1481 body
= hdr
+ SMB2_HDR_BODY
;
1484 if (req
->do_encryption
) {
1485 struct smbXsrv_session
*x
= req
->session
;
1487 nonce_high
= x
->nonce_high
;
1488 nonce_low
= x
->nonce_low
;
1491 if (x
->nonce_low
== 0) {
1497 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
1498 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
1499 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
1500 SBVAL(tf
, SMB2_TF_SESSION_ID
, session_id
);
1502 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
1503 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1504 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1505 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
1506 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(outhdr
, SMB2_HDR_OPCODE
));
1508 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
);
1509 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1510 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
1511 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
1512 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
1513 BVAL(outhdr
, SMB2_HDR_SESSION_ID
));
1514 memcpy(hdr
+SMB2_HDR_SIGNATURE
,
1515 outhdr
+SMB2_HDR_SIGNATURE
, 16);
1517 SSVAL(body
, 0x00, 0x08 + 1);
1519 SCVAL(body
, 0x02, 0);
1520 SCVAL(body
, 0x03, 0);
1521 SIVAL(body
, 0x04, 0);
1522 /* Match W2K8R2... */
1523 SCVAL(dyn
, 0x00, 0x21);
1525 state
->vector
[0].iov_base
= (void *)state
->buf
;
1526 state
->vector
[0].iov_len
= NBT_HDR_SIZE
;
1528 if (req
->do_encryption
) {
1529 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= tf
;
1530 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= tf_len
;
1532 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
1533 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
1536 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
1537 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
1539 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
1540 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_len
= 8;
1542 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
1543 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_len
= 1;
1545 smb2_setup_nbt_length(state
->vector
, 1 + SMBD_SMB2_NUM_IOV_PER_REQ
);
1547 /* Ensure we correctly go through crediting. Grant
1548 the credits now, and zero credits on the final
1550 smb2_set_operation_credit(req
->xconn
,
1551 SMBD_SMB2_IN_HDR_IOV(req
),
1552 &state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
]);
1554 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1559 for (i
= 0; i
< ARRAY_SIZE(state
->vector
); i
++) {
1560 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1562 (unsigned int)ARRAY_SIZE(state
->vector
),
1563 (unsigned int)state
->vector
[i
].iov_len
);
1567 if (req
->do_encryption
) {
1568 struct smbXsrv_session
*x
= req
->session
;
1569 DATA_BLOB encryption_key
= x
->global
->encryption_key
;
1571 status
= smb2_signing_encrypt_pdu(encryption_key
,
1573 &state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
],
1574 SMBD_SMB2_NUM_IOV_PER_REQ
);
1575 if (!NT_STATUS_IS_OK(status
)) {
1576 smbd_server_connection_terminate(req
->sconn
,
1580 } else if (req
->do_signing
) {
1581 struct smbXsrv_session
*x
= req
->session
;
1582 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
1584 status
= smb2_signing_sign_pdu(signing_key
,
1586 &state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
],
1587 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
1588 if (!NT_STATUS_IS_OK(status
)) {
1589 smbd_server_connection_terminate(req
->sconn
,
1595 state
->queue_entry
.mem_ctx
= state
;
1596 state
->queue_entry
.vector
= state
->vector
;
1597 state
->queue_entry
.count
= ARRAY_SIZE(state
->vector
);
1598 DLIST_ADD_END(xconn
->smb2
.send_queue
, &state
->queue_entry
, NULL
);
1599 xconn
->smb2
.send_queue_len
++;
1601 status
= smbd_smb2_flush_send_queue(xconn
);
1602 if (!NT_STATUS_IS_OK(status
)) {
1603 smbd_server_connection_terminate(req
->sconn
,
1609 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
1611 struct smbXsrv_connection
*xconn
= req
->xconn
;
1612 struct smbd_smb2_request
*cur
;
1613 const uint8_t *inhdr
;
1615 uint64_t search_message_id
;
1616 uint64_t search_async_id
;
1619 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1621 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1622 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1623 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
1626 * we don't need the request anymore
1627 * cancel requests never have a response
1629 DLIST_REMOVE(xconn
->smb2
.requests
, req
);
1632 for (cur
= xconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
1633 const uint8_t *outhdr
;
1634 uint64_t message_id
;
1637 if (cur
->compound_related
) {
1639 * Never cancel anything in a compound request.
1640 * Way too hard to deal with the result.
1645 outhdr
= SMBD_SMB2_OUT_HDR_PTR(cur
);
1647 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1648 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
1650 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1651 if (search_async_id
== async_id
) {
1652 found_id
= async_id
;
1656 if (search_message_id
== message_id
) {
1657 found_id
= message_id
;
1663 if (cur
&& cur
->subreq
) {
1664 inhdr
= SMBD_SMB2_IN_HDR_PTR(cur
);
1665 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1666 "cancel opcode[%s] mid %llu\n",
1667 smb2_opcode_name(SVAL(inhdr
, SMB2_HDR_OPCODE
)),
1668 (unsigned long long)found_id
));
1669 tevent_req_cancel(cur
->subreq
);
1672 return NT_STATUS_OK
;
1675 /*************************************************************
1676 Ensure an incoming tid is a valid one for us to access.
1677 Change to the associated uid credentials and chdir to the
1678 valid tid directory.
1679 *************************************************************/
1681 static NTSTATUS
smbd_smb2_request_check_tcon(struct smbd_smb2_request
*req
)
1683 const uint8_t *inhdr
;
1686 struct smbXsrv_tcon
*tcon
;
1688 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1692 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1694 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1695 in_tid
= IVAL(inhdr
, SMB2_HDR_TID
);
1697 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1698 in_tid
= req
->last_tid
;
1703 status
= smb2srv_tcon_lookup(req
->session
,
1704 in_tid
, now
, &tcon
);
1705 if (!NT_STATUS_IS_OK(status
)) {
1709 if (!change_to_user(tcon
->compat
, req
->session
->compat
->vuid
)) {
1710 return NT_STATUS_ACCESS_DENIED
;
1713 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1714 if (!set_current_service(tcon
->compat
, 0, true)) {
1715 return NT_STATUS_ACCESS_DENIED
;
1719 req
->last_tid
= in_tid
;
1721 return NT_STATUS_OK
;
1724 /*************************************************************
1725 Ensure an incoming session_id is a valid one for us to access.
1726 *************************************************************/
1728 static NTSTATUS
smbd_smb2_request_check_session(struct smbd_smb2_request
*req
)
1730 const uint8_t *inhdr
;
1733 uint64_t in_session_id
;
1734 struct smbXsrv_session
*session
= NULL
;
1735 struct auth_session_info
*session_info
;
1737 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1739 req
->session
= NULL
;
1742 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1744 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1745 in_opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1746 in_session_id
= BVAL(inhdr
, SMB2_HDR_SESSION_ID
);
1748 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1749 in_session_id
= req
->last_session_id
;
1752 req
->last_session_id
= 0;
1754 /* lookup an existing session */
1755 status
= smb2srv_session_lookup(req
->xconn
,
1759 req
->session
= session
;
1760 req
->last_session_id
= in_session_id
;
1762 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
1763 switch (in_opcode
) {
1764 case SMB2_OP_SESSSETUP
:
1765 status
= NT_STATUS_OK
;
1771 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1772 switch (in_opcode
) {
1774 case SMB2_OP_CREATE
:
1775 case SMB2_OP_GETINFO
:
1776 case SMB2_OP_SETINFO
:
1777 return NT_STATUS_INVALID_HANDLE
;
1780 * Notice the check for
1781 * (session_info == NULL)
1784 status
= NT_STATUS_OK
;
1788 if (!NT_STATUS_IS_OK(status
)) {
1792 session_info
= session
->global
->auth_session_info
;
1793 if (session_info
== NULL
) {
1794 return NT_STATUS_INVALID_HANDLE
;
1797 if (in_session_id
!= req
->xconn
->last_session_id
) {
1798 req
->xconn
->last_session_id
= in_session_id
;
1799 set_current_user_info(session_info
->unix_info
->sanitized_username
,
1800 session_info
->unix_info
->unix_name
,
1801 session_info
->info
->domain_name
);
1804 return NT_STATUS_OK
;
1807 NTSTATUS
smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request
*req
,
1808 uint32_t data_length
)
1810 struct smbXsrv_connection
*xconn
= req
->xconn
;
1811 uint16_t needed_charge
;
1812 uint16_t credit_charge
= 1;
1813 const uint8_t *inhdr
;
1815 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1817 if (xconn
->smb2
.credits
.multicredit
) {
1818 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
1819 credit_charge
= MAX(credit_charge
, 1);
1822 needed_charge
= (data_length
- 1)/ 65536 + 1;
1824 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1825 (unsigned long long) BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
),
1826 credit_charge
, needed_charge
));
1828 if (needed_charge
> credit_charge
) {
1829 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1830 credit_charge
, needed_charge
));
1831 return NT_STATUS_INVALID_PARAMETER
;
1834 return NT_STATUS_OK
;
1837 NTSTATUS
smbd_smb2_request_verify_sizes(struct smbd_smb2_request
*req
,
1838 size_t expected_body_size
)
1840 struct iovec
*inhdr_v
;
1841 const uint8_t *inhdr
;
1843 const uint8_t *inbody
;
1845 size_t min_dyn_size
= expected_body_size
& 0x00000001;
1846 int max_idx
= req
->in
.vector_count
- SMBD_SMB2_NUM_IOV_PER_REQ
;
1849 * The following should be checked already.
1851 if (req
->in
.vector_count
< SMBD_SMB2_NUM_IOV_PER_REQ
) {
1852 return NT_STATUS_INTERNAL_ERROR
;
1854 if (req
->current_idx
> max_idx
) {
1855 return NT_STATUS_INTERNAL_ERROR
;
1858 inhdr_v
= SMBD_SMB2_IN_HDR_IOV(req
);
1859 if (inhdr_v
->iov_len
!= SMB2_HDR_BODY
) {
1860 return NT_STATUS_INTERNAL_ERROR
;
1862 if (SMBD_SMB2_IN_BODY_LEN(req
) < 2) {
1863 return NT_STATUS_INTERNAL_ERROR
;
1866 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1867 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1871 case SMB2_OP_GETINFO
:
1875 if (req
->smb1req
!= NULL
&& req
->smb1req
->unread_bytes
> 0) {
1876 if (req
->smb1req
->unread_bytes
< min_dyn_size
) {
1877 return NT_STATUS_INVALID_PARAMETER
;
1886 * Now check the expected body size,
1887 * where the last byte might be in the
1890 if (SMBD_SMB2_IN_BODY_LEN(req
) != (expected_body_size
& 0xFFFFFFFE)) {
1891 return NT_STATUS_INVALID_PARAMETER
;
1893 if (SMBD_SMB2_IN_DYN_LEN(req
) < min_dyn_size
) {
1894 return NT_STATUS_INVALID_PARAMETER
;
1897 inbody
= SMBD_SMB2_IN_BODY_PTR(req
);
1899 body_size
= SVAL(inbody
, 0x00);
1900 if (body_size
!= expected_body_size
) {
1901 return NT_STATUS_INVALID_PARAMETER
;
1904 return NT_STATUS_OK
;
1907 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
1909 struct smbXsrv_connection
*xconn
= req
->xconn
;
1910 const struct smbd_smb2_dispatch_table
*call
= NULL
;
1911 const struct iovec
*intf_v
= SMBD_SMB2_IN_TF_IOV(req
);
1912 const uint8_t *inhdr
;
1917 NTSTATUS session_status
;
1918 uint32_t allowed_flags
;
1919 NTSTATUS return_value
;
1920 struct smbXsrv_session
*x
= NULL
;
1921 bool signing_required
= false;
1922 bool encryption_required
= false;
1924 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1926 /* TODO: verify more things */
1928 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1929 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1930 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1931 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1932 smb2_opcode_name(opcode
),
1933 (unsigned long long)mid
));
1935 if (xconn
->protocol
>= PROTOCOL_SMB2_02
) {
1937 * once the protocol is negotiated
1938 * SMB2_OP_NEGPROT is not allowed anymore
1940 if (opcode
== SMB2_OP_NEGPROT
) {
1941 /* drop the connection */
1942 return NT_STATUS_INVALID_PARAMETER
;
1946 * if the protocol is not negotiated yet
1947 * only SMB2_OP_NEGPROT is allowed.
1949 if (opcode
!= SMB2_OP_NEGPROT
) {
1950 /* drop the connection */
1951 return NT_STATUS_INVALID_PARAMETER
;
1956 * Check if the client provided a valid session id,
1957 * if so smbd_smb2_request_check_session() calls
1958 * set_current_user_info().
1960 * As some command don't require a valid session id
1961 * we defer the check of the session_status
1963 session_status
= smbd_smb2_request_check_session(req
);
1966 signing_required
= x
->global
->signing_required
;
1967 encryption_required
= x
->global
->encryption_required
;
1969 if (opcode
== SMB2_OP_SESSSETUP
&&
1970 x
->global
->channels
[0].signing_key
.length
) {
1971 signing_required
= true;
1975 req
->do_signing
= false;
1976 req
->do_encryption
= false;
1977 if (intf_v
->iov_len
== SMB2_TF_HDR_SIZE
) {
1978 const uint8_t *intf
= SMBD_SMB2_IN_TF_PTR(req
);
1979 uint64_t tf_session_id
= BVAL(intf
, SMB2_TF_SESSION_ID
);
1981 if (x
!= NULL
&& x
->global
->session_wire_id
!= tf_session_id
) {
1982 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1983 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1984 (unsigned long long)x
->global
->session_wire_id
,
1985 (unsigned long long)tf_session_id
));
1987 * TODO: windows allows this...
1988 * should we drop the connection?
1990 * For now we just return ACCESS_DENIED
1991 * (Windows clients never trigger this)
1992 * and wait for an update of [MS-SMB2].
1994 return smbd_smb2_request_error(req
,
1995 NT_STATUS_ACCESS_DENIED
);
1998 req
->do_encryption
= true;
2001 if (encryption_required
&& !req
->do_encryption
) {
2002 return smbd_smb2_request_error(req
,
2003 NT_STATUS_ACCESS_DENIED
);
2006 call
= smbd_smb2_call(opcode
);
2008 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2011 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
2012 SMB2_HDR_FLAG_SIGNED
|
2014 if (opcode
== SMB2_OP_CANCEL
) {
2015 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
2017 if ((flags
& ~allowed_flags
) != 0) {
2018 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2021 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
2023 * This check is mostly for giving the correct error code
2024 * for compounded requests.
2026 if (!NT_STATUS_IS_OK(session_status
)) {
2027 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2030 req
->compat_chain_fsp
= NULL
;
2033 if (req
->do_encryption
) {
2034 signing_required
= false;
2035 } else if (signing_required
|| (flags
& SMB2_HDR_FLAG_SIGNED
)) {
2036 DATA_BLOB signing_key
;
2040 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2041 * If the SMB2 header of the SMB2 NEGOTIATE
2042 * request has the SMB2_FLAGS_SIGNED bit set in the
2043 * Flags field, the server MUST fail the request
2044 * with STATUS_INVALID_PARAMETER.
2046 * Microsoft test tool checks this.
2049 if ((opcode
== SMB2_OP_NEGPROT
) &&
2050 (flags
& SMB2_HDR_FLAG_SIGNED
)) {
2051 status
= NT_STATUS_INVALID_PARAMETER
;
2053 status
= NT_STATUS_USER_SESSION_DELETED
;
2055 return smbd_smb2_request_error(req
, status
);
2058 signing_key
= x
->global
->channels
[0].signing_key
;
2061 * If we have a signing key, we should
2064 if (signing_key
.length
> 0) {
2065 req
->do_signing
= true;
2068 status
= smb2_signing_check_pdu(signing_key
,
2070 SMBD_SMB2_IN_HDR_IOV(req
),
2071 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2072 if (!NT_STATUS_IS_OK(status
)) {
2073 return smbd_smb2_request_error(req
, status
);
2077 * Now that we know the request was correctly signed
2078 * we have to sign the response too.
2080 req
->do_signing
= true;
2082 if (!NT_STATUS_IS_OK(session_status
)) {
2083 return smbd_smb2_request_error(req
, session_status
);
2085 } else if (opcode
== SMB2_OP_CANCEL
) {
2086 /* Cancel requests are allowed to skip the signing */
2087 } else if (signing_required
) {
2089 * If signing is required we try to sign
2090 * a possible error response
2092 req
->do_signing
= true;
2093 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
2096 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
2097 req
->compound_related
= true;
2100 if (call
->need_session
) {
2101 if (!NT_STATUS_IS_OK(session_status
)) {
2102 return smbd_smb2_request_error(req
, session_status
);
2106 if (call
->need_tcon
) {
2107 SMB_ASSERT(call
->need_session
);
2110 * This call needs to be run as user.
2112 * smbd_smb2_request_check_tcon()
2113 * calls change_to_user() on success.
2115 status
= smbd_smb2_request_check_tcon(req
);
2116 if (!NT_STATUS_IS_OK(status
)) {
2117 return smbd_smb2_request_error(req
, status
);
2119 if (req
->tcon
->global
->encryption_required
) {
2120 encryption_required
= true;
2122 if (encryption_required
&& !req
->do_encryption
) {
2123 return smbd_smb2_request_error(req
,
2124 NT_STATUS_ACCESS_DENIED
);
2128 if (call
->fileid_ofs
!= 0) {
2129 size_t needed
= call
->fileid_ofs
+ 16;
2130 const uint8_t *body
= SMBD_SMB2_IN_BODY_PTR(req
);
2131 size_t body_size
= SMBD_SMB2_IN_BODY_LEN(req
);
2132 uint64_t file_id_persistent
;
2133 uint64_t file_id_volatile
;
2134 struct files_struct
*fsp
;
2136 SMB_ASSERT(call
->need_tcon
);
2138 if (needed
> body_size
) {
2139 return smbd_smb2_request_error(req
,
2140 NT_STATUS_INVALID_PARAMETER
);
2143 file_id_persistent
= BVAL(body
, call
->fileid_ofs
+ 0);
2144 file_id_volatile
= BVAL(body
, call
->fileid_ofs
+ 8);
2146 fsp
= file_fsp_smb2(req
, file_id_persistent
, file_id_volatile
);
2148 if (!call
->allow_invalid_fileid
) {
2149 return smbd_smb2_request_error(req
,
2150 NT_STATUS_FILE_CLOSED
);
2153 if (file_id_persistent
!= UINT64_MAX
) {
2154 return smbd_smb2_request_error(req
,
2155 NT_STATUS_FILE_CLOSED
);
2157 if (file_id_volatile
!= UINT64_MAX
) {
2158 return smbd_smb2_request_error(req
,
2159 NT_STATUS_FILE_CLOSED
);
2164 if (call
->as_root
) {
2165 SMB_ASSERT(call
->fileid_ofs
== 0);
2166 /* This call needs to be run as root */
2167 change_to_root_user();
2169 SMB_ASSERT(call
->need_tcon
);
2173 case SMB2_OP_NEGPROT
:
2175 START_PROFILE(smb2_negprot
);
2176 return_value
= smbd_smb2_request_process_negprot(req
);
2177 END_PROFILE(smb2_negprot
);
2181 case SMB2_OP_SESSSETUP
:
2183 START_PROFILE(smb2_sesssetup
);
2184 return_value
= smbd_smb2_request_process_sesssetup(req
);
2185 END_PROFILE(smb2_sesssetup
);
2189 case SMB2_OP_LOGOFF
:
2191 START_PROFILE(smb2_logoff
);
2192 return_value
= smbd_smb2_request_process_logoff(req
);
2193 END_PROFILE(smb2_logoff
);
2199 START_PROFILE(smb2_tcon
);
2200 return_value
= smbd_smb2_request_process_tcon(req
);
2201 END_PROFILE(smb2_tcon
);
2207 START_PROFILE(smb2_tdis
);
2208 return_value
= smbd_smb2_request_process_tdis(req
);
2209 END_PROFILE(smb2_tdis
);
2213 case SMB2_OP_CREATE
:
2215 START_PROFILE(smb2_create
);
2216 return_value
= smbd_smb2_request_process_create(req
);
2217 END_PROFILE(smb2_create
);
2223 START_PROFILE(smb2_close
);
2224 return_value
= smbd_smb2_request_process_close(req
);
2225 END_PROFILE(smb2_close
);
2231 START_PROFILE(smb2_flush
);
2232 return_value
= smbd_smb2_request_process_flush(req
);
2233 END_PROFILE(smb2_flush
);
2239 START_PROFILE(smb2_read
);
2240 return_value
= smbd_smb2_request_process_read(req
);
2241 END_PROFILE(smb2_read
);
2247 START_PROFILE(smb2_write
);
2248 return_value
= smbd_smb2_request_process_write(req
);
2249 END_PROFILE(smb2_write
);
2255 START_PROFILE(smb2_lock
);
2256 return_value
= smbd_smb2_request_process_lock(req
);
2257 END_PROFILE(smb2_lock
);
2263 START_PROFILE(smb2_ioctl
);
2264 return_value
= smbd_smb2_request_process_ioctl(req
);
2265 END_PROFILE(smb2_ioctl
);
2269 case SMB2_OP_CANCEL
:
2271 START_PROFILE(smb2_cancel
);
2272 return_value
= smbd_smb2_request_process_cancel(req
);
2273 END_PROFILE(smb2_cancel
);
2277 case SMB2_OP_KEEPALIVE
:
2279 START_PROFILE(smb2_keepalive
);
2280 return_value
= smbd_smb2_request_process_keepalive(req
);
2281 END_PROFILE(smb2_keepalive
);
2287 START_PROFILE(smb2_find
);
2288 return_value
= smbd_smb2_request_process_find(req
);
2289 END_PROFILE(smb2_find
);
2293 case SMB2_OP_NOTIFY
:
2295 START_PROFILE(smb2_notify
);
2296 return_value
= smbd_smb2_request_process_notify(req
);
2297 END_PROFILE(smb2_notify
);
2301 case SMB2_OP_GETINFO
:
2303 START_PROFILE(smb2_getinfo
);
2304 return_value
= smbd_smb2_request_process_getinfo(req
);
2305 END_PROFILE(smb2_getinfo
);
2309 case SMB2_OP_SETINFO
:
2311 START_PROFILE(smb2_setinfo
);
2312 return_value
= smbd_smb2_request_process_setinfo(req
);
2313 END_PROFILE(smb2_setinfo
);
2319 START_PROFILE(smb2_break
);
2320 return_value
= smbd_smb2_request_process_break(req
);
2321 END_PROFILE(smb2_break
);
2326 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2329 return return_value
;
2332 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
2334 struct smbXsrv_connection
*xconn
= req
->xconn
;
2336 struct iovec
*firsttf
= SMBD_SMB2_IDX_TF_IOV(req
,out
,first_idx
);
2337 struct iovec
*outhdr
= SMBD_SMB2_OUT_HDR_IOV(req
);
2338 struct iovec
*outdyn
= SMBD_SMB2_OUT_DYN_IOV(req
);
2342 TALLOC_FREE(req
->async_te
);
2344 if (req
->do_encryption
&&
2345 (firsttf
->iov_len
== 0) &&
2346 (req
->first_key
.length
== 0) &&
2347 (req
->session
!= NULL
) &&
2348 (req
->session
->global
->encryption_key
.length
!= 0))
2350 DATA_BLOB encryption_key
= req
->session
->global
->encryption_key
;
2352 uint64_t session_id
= req
->session
->global
->session_wire_id
;
2353 struct smbXsrv_session
*x
= req
->session
;
2354 uint64_t nonce_high
;
2357 nonce_high
= x
->nonce_high
;
2358 nonce_low
= x
->nonce_low
;
2361 if (x
->nonce_low
== 0) {
2367 * We need to place the SMB2_TRANSFORM header before the
2372 * we need to remember the encryption key
2373 * and defer the signing/encryption until
2374 * we are sure that we do not change
2377 req
->first_key
= data_blob_dup_talloc(req
, encryption_key
);
2378 if (req
->first_key
.data
== NULL
) {
2379 return NT_STATUS_NO_MEMORY
;
2382 tf
= talloc_zero_array(req
, uint8_t,
2385 return NT_STATUS_NO_MEMORY
;
2388 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
2389 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
2390 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
2391 SBVAL(tf
, SMB2_TF_SESSION_ID
, session_id
);
2393 firsttf
->iov_base
= (void *)tf
;
2394 firsttf
->iov_len
= SMB2_TF_HDR_SIZE
;
2397 if ((req
->current_idx
> SMBD_SMB2_NUM_IOV_PER_REQ
) &&
2398 (req
->last_key
.length
> 0) &&
2399 (firsttf
->iov_len
== 0))
2401 int last_idx
= req
->current_idx
- SMBD_SMB2_NUM_IOV_PER_REQ
;
2402 struct iovec
*lasthdr
= SMBD_SMB2_IDX_HDR_IOV(req
,out
,last_idx
);
2405 * As we are sure the header of the last request in the
2406 * compound chain will not change, we can to sign here
2407 * with the last signing key we remembered.
2409 status
= smb2_signing_sign_pdu(req
->last_key
,
2412 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2413 if (!NT_STATUS_IS_OK(status
)) {
2417 if (req
->last_key
.length
> 0) {
2418 data_blob_clear_free(&req
->last_key
);
2421 req
->current_idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
;
2423 if (req
->current_idx
< req
->out
.vector_count
) {
2425 * We must process the remaining compound
2426 * SMB2 requests before any new incoming SMB2
2427 * requests. This is because incoming SMB2
2428 * requests may include a cancel for a
2429 * compound request we haven't processed
2432 struct tevent_immediate
*im
= tevent_create_immediate(req
);
2434 return NT_STATUS_NO_MEMORY
;
2437 if (req
->do_signing
&& firsttf
->iov_len
== 0) {
2438 struct smbXsrv_session
*x
= req
->session
;
2439 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
2442 * we need to remember the signing key
2443 * and defer the signing until
2444 * we are sure that we do not change
2447 req
->last_key
= data_blob_dup_talloc(req
, signing_key
);
2448 if (req
->last_key
.data
== NULL
) {
2449 return NT_STATUS_NO_MEMORY
;
2453 tevent_schedule_immediate(im
,
2455 smbd_smb2_request_dispatch_immediate
,
2457 return NT_STATUS_OK
;
2460 if (req
->compound_related
) {
2461 req
->compound_related
= false;
2464 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
2466 /* Set credit for these operations (zero credits if this
2467 is a final reply for an async operation). */
2468 smb2_calculate_credits(req
, req
);
2471 * now check if we need to sign the current response
2473 if (firsttf
->iov_len
== SMB2_TF_HDR_SIZE
) {
2474 status
= smb2_signing_encrypt_pdu(req
->first_key
,
2477 req
->out
.vector_count
- first_idx
);
2478 if (!NT_STATUS_IS_OK(status
)) {
2481 } else if (req
->do_signing
) {
2482 struct smbXsrv_session
*x
= req
->session
;
2483 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
2485 status
= smb2_signing_sign_pdu(signing_key
,
2488 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2489 if (!NT_STATUS_IS_OK(status
)) {
2493 if (req
->first_key
.length
> 0) {
2494 data_blob_clear_free(&req
->first_key
);
2497 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2498 if (req
->out
.vector_count
< (2*SMBD_SMB2_NUM_IOV_PER_REQ
) &&
2499 outdyn
->iov_base
== NULL
&& outdyn
->iov_len
!= 0) {
2500 /* Dynamic part is NULL. Chop it off,
2501 We're going to send it via sendfile. */
2502 req
->out
.vector_count
-= 1;
2506 * We're done with this request -
2507 * move it off the "being processed" queue.
2509 DLIST_REMOVE(xconn
->smb2
.requests
, req
);
2511 req
->queue_entry
.mem_ctx
= req
;
2512 req
->queue_entry
.vector
= req
->out
.vector
;
2513 req
->queue_entry
.count
= req
->out
.vector_count
;
2514 DLIST_ADD_END(xconn
->smb2
.send_queue
, &req
->queue_entry
, NULL
);
2515 xconn
->smb2
.send_queue_len
++;
2517 status
= smbd_smb2_flush_send_queue(xconn
);
2518 if (!NT_STATUS_IS_OK(status
)) {
2522 return NT_STATUS_OK
;
2525 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbXsrv_connection
*xconn
);
2527 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
2528 struct tevent_immediate
*im
,
2531 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
2532 struct smbd_smb2_request
);
2533 struct smbd_server_connection
*sconn
= req
->sconn
;
2534 struct smbXsrv_connection
*xconn
= req
->xconn
;
2539 if (DEBUGLEVEL
>= 10) {
2540 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2541 req
->current_idx
, req
->in
.vector_count
));
2542 print_req_vectors(req
);
2545 status
= smbd_smb2_request_dispatch(req
);
2546 if (!NT_STATUS_IS_OK(status
)) {
2547 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2551 status
= smbd_smb2_request_next_incoming(xconn
);
2552 if (!NT_STATUS_IS_OK(status
)) {
2553 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2558 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
2560 DATA_BLOB body
, DATA_BLOB
*dyn
,
2561 const char *location
)
2564 struct iovec
*outbody_v
;
2565 struct iovec
*outdyn_v
;
2566 uint32_t next_command_ofs
;
2568 DEBUG(10,("smbd_smb2_request_done_ex: "
2569 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2570 req
->current_idx
, nt_errstr(status
), (unsigned int)body
.length
,
2572 (unsigned int)(dyn
? dyn
->length
: 0),
2575 if (body
.length
< 2) {
2576 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2579 if ((body
.length
% 2) != 0) {
2580 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2583 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
2584 outbody_v
= SMBD_SMB2_OUT_BODY_IOV(req
);
2585 outdyn_v
= SMBD_SMB2_OUT_DYN_IOV(req
);
2587 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
2588 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
2590 outbody_v
->iov_base
= (void *)body
.data
;
2591 outbody_v
->iov_len
= body
.length
;
2594 outdyn_v
->iov_base
= (void *)dyn
->data
;
2595 outdyn_v
->iov_len
= dyn
->length
;
2597 outdyn_v
->iov_base
= NULL
;
2598 outdyn_v
->iov_len
= 0;
2601 /* see if we need to recalculate the offset to the next response */
2602 if (next_command_ofs
> 0) {
2603 next_command_ofs
= SMB2_HDR_BODY
;
2604 next_command_ofs
+= SMBD_SMB2_OUT_BODY_LEN(req
);
2605 next_command_ofs
+= SMBD_SMB2_OUT_DYN_LEN(req
);
2608 if ((next_command_ofs
% 8) != 0) {
2609 size_t pad_size
= 8 - (next_command_ofs
% 8);
2610 if (SMBD_SMB2_OUT_DYN_LEN(req
) == 0) {
2612 * if the dyn buffer is empty
2613 * we can use it to add padding
2617 pad
= talloc_zero_array(req
,
2620 return smbd_smb2_request_error(req
,
2621 NT_STATUS_NO_MEMORY
);
2624 outdyn_v
->iov_base
= (void *)pad
;
2625 outdyn_v
->iov_len
= pad_size
;
2628 * For now we copy the dynamic buffer
2629 * and add the padding to the new buffer
2636 old_size
= SMBD_SMB2_OUT_DYN_LEN(req
);
2637 old_dyn
= SMBD_SMB2_OUT_DYN_PTR(req
);
2639 new_size
= old_size
+ pad_size
;
2640 new_dyn
= talloc_zero_array(req
,
2642 if (new_dyn
== NULL
) {
2643 return smbd_smb2_request_error(req
,
2644 NT_STATUS_NO_MEMORY
);
2647 memcpy(new_dyn
, old_dyn
, old_size
);
2648 memset(new_dyn
+ old_size
, 0, pad_size
);
2650 outdyn_v
->iov_base
= (void *)new_dyn
;
2651 outdyn_v
->iov_len
= new_size
;
2653 next_command_ofs
+= pad_size
;
2656 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
2658 return smbd_smb2_request_reply(req
);
2661 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
2664 const char *location
)
2666 struct smbXsrv_connection
*xconn
= req
->sconn
->conn
;
2669 uint8_t *outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
2670 size_t unread_bytes
= smbd_smb2_unread_bytes(req
);
2672 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2673 req
->current_idx
, nt_errstr(status
), info
? " +info" : "",
2677 /* Recvfile error. Drain incoming socket. */
2681 ret
= drain_socket(xconn
->transport
.sock
, unread_bytes
);
2682 if (ret
!= unread_bytes
) {
2686 error
= NT_STATUS_IO_DEVICE_ERROR
;
2688 error
= map_nt_error_from_unix_common(errno
);
2691 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2692 "ret[%u] errno[%d] => %s\n",
2693 (unsigned)unread_bytes
,
2694 (unsigned)ret
, errno
, nt_errstr(error
)));
2699 body
.data
= outhdr
+ SMB2_HDR_BODY
;
2701 SSVAL(body
.data
, 0, 9);
2704 SIVAL(body
.data
, 0x04, info
->length
);
2706 /* Allocated size of req->out.vector[i].iov_base
2707 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2708 * 1 byte without having to do an alloc.
2711 info
->data
= ((uint8_t *)outhdr
) +
2712 OUTVEC_ALLOC_SIZE
- 1;
2714 SCVAL(info
->data
, 0, 0);
2718 * Note: Even if there is an error, continue to process the request.
2722 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
2726 struct smbd_smb2_send_break_state
{
2727 struct smbd_server_connection
*sconn
;
2728 struct smbd_smb2_send_queue queue_entry
;
2729 uint8_t nbt_hdr
[NBT_HDR_SIZE
];
2730 uint8_t tf
[SMB2_TF_HDR_SIZE
];
2731 uint8_t hdr
[SMB2_HDR_BODY
];
2732 struct iovec vector
[1+SMBD_SMB2_NUM_IOV_PER_REQ
];
2736 static NTSTATUS
smbd_smb2_send_break(struct smbd_server_connection
*sconn
,
2737 struct smbXsrv_session
*session
,
2738 struct smbXsrv_tcon
*tcon
,
2739 const uint8_t *body
,
2742 struct smbd_smb2_send_break_state
*state
;
2743 struct smbXsrv_connection
*xconn
= sconn
->conn
;
2744 bool do_encryption
= session
->global
->encryption_required
;
2745 uint64_t nonce_high
= 0;
2746 uint64_t nonce_low
= 0;
2750 if (tcon
->global
->encryption_required
) {
2751 do_encryption
= true;
2754 statelen
= offsetof(struct smbd_smb2_send_break_state
, body
) +
2757 state
= talloc_zero_size(sconn
, statelen
);
2758 if (state
== NULL
) {
2759 return NT_STATUS_NO_MEMORY
;
2761 talloc_set_name_const(state
, "struct smbd_smb2_send_break_state");
2762 state
->sconn
= sconn
;
2764 if (do_encryption
) {
2765 nonce_high
= session
->nonce_high
;
2766 nonce_low
= session
->nonce_low
;
2768 session
->nonce_low
+= 1;
2769 if (session
->nonce_low
== 0) {
2770 session
->nonce_low
+= 1;
2771 session
->nonce_high
+= 1;
2775 SIVAL(state
->tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
2776 SBVAL(state
->tf
, SMB2_TF_NONCE
+0, nonce_low
);
2777 SBVAL(state
->tf
, SMB2_TF_NONCE
+8, nonce_high
);
2778 SBVAL(state
->tf
, SMB2_TF_SESSION_ID
, session
->global
->session_wire_id
);
2780 SIVAL(state
->hdr
, 0, SMB2_MAGIC
);
2781 SSVAL(state
->hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
2782 SSVAL(state
->hdr
, SMB2_HDR_EPOCH
, 0);
2783 SIVAL(state
->hdr
, SMB2_HDR_STATUS
, 0);
2784 SSVAL(state
->hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
2785 SSVAL(state
->hdr
, SMB2_HDR_CREDIT
, 0);
2786 SIVAL(state
->hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
2787 SIVAL(state
->hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
2788 SBVAL(state
->hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
2789 SIVAL(state
->hdr
, SMB2_HDR_PID
, 0);
2790 SIVAL(state
->hdr
, SMB2_HDR_TID
, 0);
2791 SBVAL(state
->hdr
, SMB2_HDR_SESSION_ID
, 0);
2792 memset(state
->hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
2794 state
->vector
[0] = (struct iovec
) {
2795 .iov_base
= state
->nbt_hdr
,
2796 .iov_len
= sizeof(state
->nbt_hdr
)
2799 if (do_encryption
) {
2800 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
] = (struct iovec
) {
2801 .iov_base
= state
->tf
,
2802 .iov_len
= sizeof(state
->tf
)
2805 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
] = (struct iovec
) {
2811 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
] = (struct iovec
) {
2812 .iov_base
= state
->hdr
,
2813 .iov_len
= sizeof(state
->hdr
)
2816 memcpy(state
->body
, body
, body_len
);
2818 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
] = (struct iovec
) {
2819 .iov_base
= state
->body
,
2820 .iov_len
= body_len
/* no sizeof(state->body) .. :-) */
2824 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
2827 smb2_setup_nbt_length(state
->vector
, 1 + SMBD_SMB2_NUM_IOV_PER_REQ
);
2829 if (do_encryption
) {
2830 DATA_BLOB encryption_key
= session
->global
->encryption_key
;
2832 status
= smb2_signing_encrypt_pdu(encryption_key
,
2834 &state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
],
2835 SMBD_SMB2_NUM_IOV_PER_REQ
);
2836 if (!NT_STATUS_IS_OK(status
)) {
2841 state
->queue_entry
.mem_ctx
= state
;
2842 state
->queue_entry
.vector
= state
->vector
;
2843 state
->queue_entry
.count
= ARRAY_SIZE(state
->vector
);
2844 DLIST_ADD_END(xconn
->smb2
.send_queue
, &state
->queue_entry
, NULL
);
2845 xconn
->smb2
.send_queue_len
++;
2847 status
= smbd_smb2_flush_send_queue(xconn
);
2848 if (!NT_STATUS_IS_OK(status
)) {
2852 return NT_STATUS_OK
;
2855 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
2856 struct smbXsrv_session
*session
,
2857 struct smbXsrv_tcon
*tcon
,
2858 struct smbXsrv_open
*op
,
2859 uint8_t oplock_level
)
2863 SSVAL(body
, 0x00, sizeof(body
));
2864 SCVAL(body
, 0x02, oplock_level
);
2865 SCVAL(body
, 0x03, 0); /* reserved */
2866 SIVAL(body
, 0x04, 0); /* reserved */
2867 SBVAL(body
, 0x08, op
->global
->open_persistent_id
);
2868 SBVAL(body
, 0x10, op
->global
->open_volatile_id
);
2870 return smbd_smb2_send_break(sconn
, session
, tcon
, body
, sizeof(body
));
2873 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state
*state
)
2877 uint64_t file_id_persistent
;
2878 uint64_t file_id_volatile
;
2879 struct smbXsrv_open
*op
= NULL
;
2880 struct files_struct
*fsp
= NULL
;
2881 const uint8_t *body
= NULL
;
2884 * This is only called with a pktbuf
2885 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
2889 if (IVAL(state
->pktbuf
, 0) == SMB2_TF_MAGIC
) {
2890 /* Transform header. Cannot recvfile. */
2893 if (IVAL(state
->pktbuf
, 0) != SMB2_MAGIC
) {
2894 /* Not SMB2. Normal error path will cope. */
2897 if (SVAL(state
->pktbuf
, 4) != SMB2_HDR_BODY
) {
2898 /* Not SMB2. Normal error path will cope. */
2901 if (SVAL(state
->pktbuf
, SMB2_HDR_OPCODE
) != SMB2_OP_WRITE
) {
2902 /* Needs to be a WRITE. */
2905 if (IVAL(state
->pktbuf
, SMB2_HDR_NEXT_COMMAND
) != 0) {
2906 /* Chained. Cannot recvfile. */
2909 flags
= IVAL(state
->pktbuf
, SMB2_HDR_FLAGS
);
2910 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
2911 /* Chained. Cannot recvfile. */
2914 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
2915 /* Signed. Cannot recvfile. */
2919 body
= &state
->pktbuf
[SMB2_HDR_BODY
];
2921 file_id_persistent
= BVAL(body
, 0x10);
2922 file_id_volatile
= BVAL(body
, 0x18);
2924 status
= smb2srv_open_lookup(state
->req
->sconn
->conn
,
2929 if (!NT_STATUS_IS_OK(status
)) {
2937 if (fsp
->conn
== NULL
) {
2941 if (IS_IPC(fsp
->conn
)) {
2944 if (IS_PRINT(fsp
->conn
)) {
2948 DEBUG(10,("Doing recvfile write len = %u\n",
2949 (unsigned int)(state
->pktfull
- state
->pktlen
)));
2954 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbXsrv_connection
*xconn
)
2956 struct smbd_server_connection
*sconn
= xconn
->sconn
;
2957 struct smbd_smb2_request_read_state
*state
= &xconn
->smb2
.request_read_state
;
2958 size_t max_send_queue_len
;
2959 size_t cur_send_queue_len
;
2961 if (!NT_STATUS_IS_OK(xconn
->transport
.status
)) {
2963 * we're not supposed to do any io
2965 return NT_STATUS_OK
;
2968 if (state
->req
!= NULL
) {
2970 * if there is already a tstream_readv_pdu
2971 * pending, we are done.
2973 return NT_STATUS_OK
;
2976 max_send_queue_len
= MAX(1, xconn
->smb2
.credits
.max
/16);
2977 cur_send_queue_len
= xconn
->smb2
.send_queue_len
;
2979 if (cur_send_queue_len
> max_send_queue_len
) {
2981 * if we have a lot of requests to send,
2982 * we wait until they are on the wire until we
2983 * ask for the next request.
2985 return NT_STATUS_OK
;
2988 /* ask for the next request */
2989 ZERO_STRUCTP(state
);
2990 state
->req
= smbd_smb2_request_allocate(xconn
);
2991 if (state
->req
== NULL
) {
2992 return NT_STATUS_NO_MEMORY
;
2994 state
->req
->sconn
= sconn
;
2995 state
->req
->xconn
= xconn
;
2996 state
->min_recv_size
= lp_min_receive_file_size();
2998 TEVENT_FD_READABLE(xconn
->transport
.fde
);
3000 return NT_STATUS_OK
;
3003 void smbd_smb2_first_negprot(struct smbXsrv_connection
*xconn
,
3004 uint8_t *inbuf
, size_t size
)
3006 struct smbd_server_connection
*sconn
= xconn
->sconn
;
3008 struct smbd_smb2_request
*req
= NULL
;
3010 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3011 (unsigned int)size
));
3013 status
= smbd_initialize_smb2(xconn
);
3014 if (!NT_STATUS_IS_OK(status
)) {
3015 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3019 status
= smbd_smb2_request_create(xconn
, inbuf
, size
, &req
);
3020 if (!NT_STATUS_IS_OK(status
)) {
3021 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3025 status
= smbd_smb2_request_validate(req
);
3026 if (!NT_STATUS_IS_OK(status
)) {
3027 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3031 status
= smbd_smb2_request_setup_out(req
);
3032 if (!NT_STATUS_IS_OK(status
)) {
3033 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3037 status
= smbd_smb2_request_dispatch(req
);
3038 if (!NT_STATUS_IS_OK(status
)) {
3039 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3043 status
= smbd_smb2_request_next_incoming(xconn
);
3044 if (!NT_STATUS_IS_OK(status
)) {
3045 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3049 sconn
->num_requests
++;
3052 static int socket_error_from_errno(int ret
,
3066 if (sys_errno
== 0) {
3070 if (sys_errno
== EINTR
) {
3075 if (sys_errno
== EINPROGRESS
) {
3080 if (sys_errno
== EAGAIN
) {
3085 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3086 if (sys_errno
== ENOMEM
) {
3092 #if EWOULDBLOCK != EAGAIN
3093 if (sys_errno
== EWOULDBLOCK
) {
3103 static NTSTATUS
smbd_smb2_flush_send_queue(struct smbXsrv_connection
*xconn
)
3109 if (xconn
->smb2
.send_queue
== NULL
) {
3110 TEVENT_FD_NOT_WRITEABLE(xconn
->transport
.fde
);
3111 return NT_STATUS_OK
;
3114 while (xconn
->smb2
.send_queue
!= NULL
) {
3115 struct smbd_smb2_send_queue
*e
= xconn
->smb2
.send_queue
;
3117 if (e
->sendfile_header
!= NULL
) {
3122 for (i
=0; i
< e
->count
; i
++) {
3123 size
+= e
->vector
[i
].iov_len
;
3126 if (size
<= e
->sendfile_header
->length
) {
3127 buf
= e
->sendfile_header
->data
;
3129 buf
= talloc_array(e
->mem_ctx
, uint8_t, size
);
3131 return NT_STATUS_NO_MEMORY
;
3136 for (i
=0; i
< e
->count
; i
++) {
3138 e
->vector
[i
].iov_base
,
3139 e
->vector
[i
].iov_len
);
3140 size
+= e
->vector
[i
].iov_len
;
3143 e
->sendfile_header
->data
= buf
;
3144 e
->sendfile_header
->length
= size
;
3147 xconn
->smb2
.send_queue_len
--;
3148 DLIST_REMOVE(xconn
->smb2
.send_queue
, e
);
3150 * This triggers the sendfile path via
3153 talloc_free(e
->mem_ctx
);
3157 ret
= writev(xconn
->transport
.sock
, e
->vector
, e
->count
);
3159 /* propagate end of file */
3160 return NT_STATUS_INTERNAL_ERROR
;
3162 err
= socket_error_from_errno(ret
, errno
, &retry
);
3165 TEVENT_FD_WRITEABLE(xconn
->transport
.fde
);
3166 return NT_STATUS_OK
;
3169 return map_nt_error_from_unix_common(err
);
3172 if (ret
< e
->vector
[0].iov_len
) {
3174 base
= (uint8_t *)e
->vector
[0].iov_base
;
3176 e
->vector
[0].iov_base
= (void *)base
;
3177 e
->vector
[0].iov_len
-= ret
;
3180 ret
-= e
->vector
[0].iov_len
;
3186 * there're maybe some empty vectors at the end
3187 * which we need to skip, otherwise we would get
3188 * ret == 0 from the readv() call and return EPIPE
3190 while (e
->count
> 0) {
3191 if (e
->vector
[0].iov_len
> 0) {
3199 /* we have more to write */
3200 TEVENT_FD_WRITEABLE(xconn
->transport
.fde
);
3201 return NT_STATUS_OK
;
3204 xconn
->smb2
.send_queue_len
--;
3205 DLIST_REMOVE(xconn
->smb2
.send_queue
, e
);
3206 talloc_free(e
->mem_ctx
);
3209 return NT_STATUS_OK
;
3212 static NTSTATUS
smbd_smb2_io_handler(struct smbXsrv_connection
*xconn
,
3215 struct smbd_server_connection
*sconn
= xconn
->sconn
;
3216 struct smbd_smb2_request_read_state
*state
= &xconn
->smb2
.request_read_state
;
3217 struct smbd_smb2_request
*req
= NULL
;
3218 size_t min_recvfile_size
= UINT32_MAX
;
3225 if (!NT_STATUS_IS_OK(xconn
->transport
.status
)) {
3227 * we're not supposed to do any io
3229 TEVENT_FD_NOT_READABLE(xconn
->transport
.fde
);
3230 TEVENT_FD_NOT_WRITEABLE(xconn
->transport
.fde
);
3231 return NT_STATUS_OK
;
3234 if (fde_flags
& TEVENT_FD_WRITE
) {
3235 status
= smbd_smb2_flush_send_queue(xconn
);
3236 if (!NT_STATUS_IS_OK(status
)) {
3241 if (!(fde_flags
& TEVENT_FD_READ
)) {
3242 return NT_STATUS_OK
;
3245 if (state
->req
== NULL
) {
3246 TEVENT_FD_NOT_READABLE(xconn
->transport
.fde
);
3247 return NT_STATUS_OK
;
3251 if (!state
->hdr
.done
) {
3252 state
->hdr
.done
= true;
3254 state
->vector
.iov_base
= (void *)state
->hdr
.nbt
;
3255 state
->vector
.iov_len
= NBT_HDR_SIZE
;
3258 ret
= readv(xconn
->transport
.sock
, &state
->vector
, 1);
3260 /* propagate end of file */
3261 return NT_STATUS_END_OF_FILE
;
3263 err
= socket_error_from_errno(ret
, errno
, &retry
);
3266 TEVENT_FD_READABLE(xconn
->transport
.fde
);
3267 return NT_STATUS_OK
;
3270 return map_nt_error_from_unix_common(err
);
3273 if (ret
< state
->vector
.iov_len
) {
3275 base
= (uint8_t *)state
->vector
.iov_base
;
3277 state
->vector
.iov_base
= (void *)base
;
3278 state
->vector
.iov_len
-= ret
;
3279 /* we have more to read */
3280 TEVENT_FD_READABLE(xconn
->transport
.fde
);
3281 return NT_STATUS_OK
;
3284 if (state
->pktlen
> 0) {
3285 if (state
->doing_receivefile
&& !is_smb2_recvfile_write(state
)) {
3287 * Not a possible receivefile write.
3288 * Read the rest of the data.
3290 state
->doing_receivefile
= false;
3292 state
->pktbuf
= talloc_realloc(state
->req
,
3296 if (state
->pktbuf
== NULL
) {
3297 return NT_STATUS_NO_MEMORY
;
3300 state
->vector
.iov_base
= (void *)(state
->pktbuf
+
3302 state
->vector
.iov_len
= (state
->pktfull
-
3305 state
->pktlen
= state
->pktfull
;
3310 * Either this is a receivefile write so we've
3311 * done a short read, or if not we have all the data.
3317 * Now we analyze the NBT header
3319 if (state
->hdr
.nbt
[0] != 0x00) {
3320 state
->min_recv_size
= 0;
3322 state
->pktfull
= smb2_len(state
->hdr
.nbt
);
3323 if (state
->pktfull
== 0) {
3327 if (state
->min_recv_size
!= 0) {
3328 min_recvfile_size
= SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
;
3329 min_recvfile_size
+= state
->min_recv_size
;
3332 if (state
->pktfull
> min_recvfile_size
) {
3334 * Might be a receivefile write. Read the SMB2 HEADER +
3335 * SMB2_WRITE header first. Set 'doing_receivefile'
3336 * as we're *attempting* receivefile write. If this
3337 * turns out not to be a SMB2_WRITE request or otherwise
3338 * not suitable then we'll just read the rest of the data
3339 * the next time this function is called.
3341 state
->pktlen
= SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
;
3342 state
->doing_receivefile
= true;
3344 state
->pktlen
= state
->pktfull
;
3347 state
->pktbuf
= talloc_array(state
->req
, uint8_t, state
->pktlen
);
3348 if (state
->pktbuf
== NULL
) {
3349 return NT_STATUS_NO_MEMORY
;
3352 state
->vector
.iov_base
= (void *)state
->pktbuf
;
3353 state
->vector
.iov_len
= state
->pktlen
;
3359 if (state
->hdr
.nbt
[0] != 0x00) {
3360 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3361 state
->hdr
.nbt
[0]));
3364 ZERO_STRUCTP(state
);
3366 state
->min_recv_size
= lp_min_receive_file_size();
3374 req
->request_time
= timeval_current();
3375 now
= timeval_to_nttime(&req
->request_time
);
3377 status
= smbd_smb2_inbuf_parse_compound(xconn
,
3383 &req
->in
.vector_count
);
3384 if (!NT_STATUS_IS_OK(status
)) {
3388 if (state
->doing_receivefile
) {
3389 req
->smb1req
= talloc_zero(req
, struct smb_request
);
3390 if (req
->smb1req
== NULL
) {
3391 return NT_STATUS_NO_MEMORY
;
3393 req
->smb1req
->unread_bytes
= state
->pktfull
- state
->pktlen
;
3396 ZERO_STRUCTP(state
);
3398 req
->current_idx
= 1;
3400 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3401 req
->current_idx
, req
->in
.vector_count
));
3403 status
= smbd_smb2_request_validate(req
);
3404 if (!NT_STATUS_IS_OK(status
)) {
3408 status
= smbd_smb2_request_setup_out(req
);
3409 if (!NT_STATUS_IS_OK(status
)) {
3413 status
= smbd_smb2_request_dispatch(req
);
3414 if (!NT_STATUS_IS_OK(status
)) {
3418 sconn
->num_requests
++;
3420 /* The timeout_processing function isn't run nearly
3421 often enough to implement 'max log size' without
3422 overrunning the size of the file by many megabytes.
3423 This is especially true if we are running at debug
3424 level 10. Checking every 50 SMB2s is a nice
3425 tradeoff of performance vs log file size overrun. */
3427 if ((sconn
->num_requests
% 50) == 0 &&
3428 need_to_check_log_size()) {
3429 change_to_root_user();
3433 status
= smbd_smb2_request_next_incoming(xconn
);
3434 if (!NT_STATUS_IS_OK(status
)) {
3438 return NT_STATUS_OK
;
3441 static void smbd_smb2_connection_handler(struct tevent_context
*ev
,
3442 struct tevent_fd
*fde
,
3446 struct smbXsrv_connection
*xconn
=
3447 talloc_get_type_abort(private_data
,
3448 struct smbXsrv_connection
);
3449 struct smbd_server_connection
*sconn
= xconn
->sconn
;
3452 status
= smbd_smb2_io_handler(xconn
, flags
);
3453 if (!NT_STATUS_IS_OK(status
)) {
3454 smbd_server_connection_terminate(sconn
, nt_errstr(status
));