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"
31 #include "lib/util/iov_buf.h"
34 static void smbd_smb2_connection_handler(struct tevent_context
*ev
,
35 struct tevent_fd
*fde
,
38 static NTSTATUS
smbd_smb2_flush_send_queue(struct smbXsrv_connection
*xconn
);
40 static const struct smbd_smb2_dispatch_table
{
47 bool allow_invalid_fileid
;
48 } smbd_smb2_table
[] = {
49 #define _OP(o) .opcode = o, .name = #o
54 _OP(SMB2_OP_SESSSETUP
),
64 * This call needs to be run as root.
66 * smbd_smb2_request_process_tcon()
67 * calls make_connection_snum(), which will call
68 * change_to_user(), when needed.
102 .need_session
= true,
107 .need_session
= true,
110 .allow_invalid_fileid
= true,
115 _OP(SMB2_OP_KEEPALIVE
),
118 _OP(SMB2_OP_QUERY_DIRECTORY
),
119 .need_session
= true,
124 .need_session
= true,
128 _OP(SMB2_OP_GETINFO
),
129 .need_session
= true,
133 _OP(SMB2_OP_SETINFO
),
134 .need_session
= true,
139 .need_session
= true,
144 * as LEASE breaks does not
150 const char *smb2_opcode_name(uint16_t opcode
)
152 if (opcode
>= ARRAY_SIZE(smbd_smb2_table
)) {
153 return "Bad SMB2 opcode";
155 return smbd_smb2_table
[opcode
].name
;
158 static const struct smbd_smb2_dispatch_table
*smbd_smb2_call(uint16_t opcode
)
160 const struct smbd_smb2_dispatch_table
*ret
= NULL
;
162 if (opcode
>= ARRAY_SIZE(smbd_smb2_table
)) {
166 ret
= &smbd_smb2_table
[opcode
];
168 SMB_ASSERT(ret
->opcode
== opcode
);
173 static void print_req_vectors(const struct smbd_smb2_request
*req
)
177 for (i
= 0; i
< req
->in
.vector_count
; i
++) {
178 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
180 (unsigned int)req
->in
.vector
[i
].iov_len
);
182 for (i
= 0; i
< req
->out
.vector_count
; i
++) {
183 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
185 (unsigned int)req
->out
.vector
[i
].iov_len
);
189 bool smbd_is_smb2_header(const uint8_t *inbuf
, size_t size
)
191 if (size
< (4 + SMB2_HDR_BODY
)) {
195 if (IVAL(inbuf
, 4) != SMB2_MAGIC
) {
202 static NTSTATUS
smbd_initialize_smb2(struct smbXsrv_connection
*xconn
)
204 TALLOC_FREE(xconn
->transport
.fde
);
206 xconn
->smb2
.credits
.seq_low
= 0;
207 xconn
->smb2
.credits
.seq_range
= 1;
208 xconn
->smb2
.credits
.granted
= 1;
209 xconn
->smb2
.credits
.max
= lp_smb2_max_credits();
210 xconn
->smb2
.credits
.bitmap
= bitmap_talloc(xconn
,
211 xconn
->smb2
.credits
.max
);
212 if (xconn
->smb2
.credits
.bitmap
== NULL
) {
213 return NT_STATUS_NO_MEMORY
;
216 xconn
->transport
.fde
= tevent_add_fd(xconn
->ev_ctx
,
218 xconn
->transport
.sock
,
220 smbd_smb2_connection_handler
,
222 if (xconn
->transport
.fde
== NULL
) {
223 return NT_STATUS_NO_MEMORY
;
226 /* Ensure child is set to non-blocking mode */
227 set_blocking(xconn
->transport
.sock
, false);
231 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
232 #define _smb2_setlen(_buf,len) do { \
233 uint8_t *buf = (uint8_t *)_buf; \
235 buf[1] = ((len)&0xFF0000)>>16; \
236 buf[2] = ((len)&0xFF00)>>8; \
237 buf[3] = (len)&0xFF; \
240 static bool smb2_setup_nbt_length(struct iovec
*vector
, int count
)
248 len
= iov_buflen(vector
+1, count
-1);
250 if ((len
== -1) || (len
> 0xFFFFFF)) {
254 _smb2_setlen(vector
[0].iov_base
, len
);
258 static int smbd_smb2_request_destructor(struct smbd_smb2_request
*req
)
260 if (req
->first_key
.length
> 0) {
261 data_blob_clear_free(&req
->first_key
);
263 if (req
->last_key
.length
> 0) {
264 data_blob_clear_free(&req
->last_key
);
269 static struct smbd_smb2_request
*smbd_smb2_request_allocate(TALLOC_CTX
*mem_ctx
)
271 TALLOC_CTX
*mem_pool
;
272 struct smbd_smb2_request
*req
;
275 /* Enable this to find subtle valgrind errors. */
276 mem_pool
= talloc_init("smbd_smb2_request_allocate");
278 mem_pool
= talloc_tos();
280 if (mem_pool
== NULL
) {
284 req
= talloc_zero(mem_pool
, struct smbd_smb2_request
);
286 talloc_free(mem_pool
);
289 talloc_reparent(mem_pool
, mem_ctx
, req
);
291 TALLOC_FREE(mem_pool
);
294 req
->last_session_id
= UINT64_MAX
;
295 req
->last_tid
= UINT32_MAX
;
297 talloc_set_destructor(req
, smbd_smb2_request_destructor
);
302 static NTSTATUS
smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection
*xconn
,
306 struct smbd_smb2_request
*req
,
310 TALLOC_CTX
*mem_ctx
= req
;
314 uint8_t *first_hdr
= buf
;
315 size_t verified_buflen
= 0;
320 * Note: index '0' is reserved for the transport protocol
322 iov
= req
->in
._vector
;
324 while (taken
< buflen
) {
325 size_t len
= buflen
- taken
;
326 uint8_t *hdr
= first_hdr
+ taken
;
329 size_t next_command_ofs
;
331 uint8_t *body
= NULL
;
334 struct iovec
*iov_alloc
= NULL
;
336 if (iov
!= req
->in
._vector
) {
340 if (verified_buflen
> taken
) {
341 len
= verified_buflen
- taken
;
348 DEBUG(10, ("%d bytes left, expected at least %d\n",
352 if (IVAL(hdr
, 0) == SMB2_TF_MAGIC
) {
353 struct smbXsrv_session
*s
= NULL
;
355 struct iovec tf_iov
[2];
359 if (xconn
->protocol
< PROTOCOL_SMB2_24
) {
360 DEBUG(10, ("Got SMB2_TRANSFORM header, "
361 "but dialect[0x%04X] is used\n",
362 xconn
->smb2
.server
.dialect
));
366 if (xconn
->smb2
.server
.cipher
== 0) {
367 DEBUG(10, ("Got SMB2_TRANSFORM header, "
368 "but not negotiated "
369 "client[0x%08X] server[0x%08X]\n",
370 xconn
->smb2
.client
.capabilities
,
371 xconn
->smb2
.server
.capabilities
));
375 if (len
< SMB2_TF_HDR_SIZE
) {
376 DEBUG(1, ("%d bytes left, expected at least %d\n",
377 (int)len
, SMB2_TF_HDR_SIZE
));
381 tf_len
= SMB2_TF_HDR_SIZE
;
384 hdr
= first_hdr
+ taken
;
385 enc_len
= IVAL(tf
, SMB2_TF_MSG_SIZE
);
386 uid
= BVAL(tf
, SMB2_TF_SESSION_ID
);
388 if (len
< SMB2_TF_HDR_SIZE
+ enc_len
) {
389 DEBUG(1, ("%d bytes left, expected at least %d\n",
391 (int)(SMB2_TF_HDR_SIZE
+ enc_len
)));
395 status
= smb2srv_session_lookup(xconn
, uid
, now
, &s
);
397 DEBUG(1, ("invalid session[%llu] in "
398 "SMB2_TRANSFORM header\n",
399 (unsigned long long)uid
));
400 TALLOC_FREE(iov_alloc
);
401 return NT_STATUS_USER_SESSION_DELETED
;
404 tf_iov
[0].iov_base
= (void *)tf
;
405 tf_iov
[0].iov_len
= tf_len
;
406 tf_iov
[1].iov_base
= (void *)hdr
;
407 tf_iov
[1].iov_len
= enc_len
;
409 status
= smb2_signing_decrypt_pdu(s
->global
->decryption_key
,
410 xconn
->smb2
.server
.cipher
,
412 if (!NT_STATUS_IS_OK(status
)) {
413 TALLOC_FREE(iov_alloc
);
417 verified_buflen
= taken
+ enc_len
;
422 * We need the header plus the body length field
425 if (len
< SMB2_HDR_BODY
+ 2) {
426 DEBUG(10, ("%d bytes left, expected at least %d\n",
427 (int)len
, SMB2_HDR_BODY
));
430 if (IVAL(hdr
, 0) != SMB2_MAGIC
) {
431 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
435 if (SVAL(hdr
, 4) != SMB2_HDR_BODY
) {
436 DEBUG(10, ("Got HDR len %d, expected %d\n",
437 SVAL(hdr
, 4), SMB2_HDR_BODY
));
442 next_command_ofs
= IVAL(hdr
, SMB2_HDR_NEXT_COMMAND
);
443 body_size
= SVAL(hdr
, SMB2_HDR_BODY
);
445 if (next_command_ofs
!= 0) {
446 if (next_command_ofs
< (SMB2_HDR_BODY
+ 2)) {
449 if (next_command_ofs
> full_size
) {
452 full_size
= next_command_ofs
;
459 if (body_size
> (full_size
- SMB2_HDR_BODY
)) {
461 * let the caller handle the error
463 body_size
= full_size
- SMB2_HDR_BODY
;
465 body
= hdr
+ SMB2_HDR_BODY
;
466 dyn
= body
+ body_size
;
467 dyn_size
= full_size
- (SMB2_HDR_BODY
+ body_size
);
469 if (num_iov
>= ARRAY_SIZE(req
->in
._vector
)) {
470 struct iovec
*iov_tmp
= NULL
;
472 iov_tmp
= talloc_realloc(mem_ctx
, iov_alloc
,
475 SMBD_SMB2_NUM_IOV_PER_REQ
);
476 if (iov_tmp
== NULL
) {
477 TALLOC_FREE(iov_alloc
);
478 return NT_STATUS_NO_MEMORY
;
481 if (iov_alloc
== NULL
) {
484 sizeof(req
->in
._vector
));
490 num_iov
+= SMBD_SMB2_NUM_IOV_PER_REQ
;
492 cur
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= tf
;
493 cur
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= tf_len
;
494 cur
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
495 cur
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
496 cur
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
497 cur
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= body_size
;
498 cur
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
499 cur
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= dyn_size
;
509 if (iov
!= req
->in
._vector
) {
512 return NT_STATUS_INVALID_PARAMETER
;
515 static NTSTATUS
smbd_smb2_request_create(struct smbXsrv_connection
*xconn
,
516 const uint8_t *_inpdu
, size_t size
,
517 struct smbd_smb2_request
**_req
)
519 struct smbd_server_connection
*sconn
= xconn
->client
->sconn
;
520 struct smbd_smb2_request
*req
;
521 uint32_t protocol_version
;
522 uint8_t *inpdu
= NULL
;
523 const uint8_t *inhdr
= NULL
;
525 uint32_t next_command_ofs
;
529 if (size
< (SMB2_HDR_BODY
+ 2)) {
530 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size
));
531 return NT_STATUS_INVALID_PARAMETER
;
536 protocol_version
= IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
);
537 if (protocol_version
!= SMB2_MAGIC
) {
538 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
540 return NT_STATUS_INVALID_PARAMETER
;
543 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
544 if (cmd
!= SMB2_OP_NEGPROT
) {
545 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
547 return NT_STATUS_INVALID_PARAMETER
;
550 next_command_ofs
= IVAL(inhdr
, SMB2_HDR_NEXT_COMMAND
);
551 if (next_command_ofs
!= 0) {
552 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
554 return NT_STATUS_INVALID_PARAMETER
;
557 req
= smbd_smb2_request_allocate(xconn
);
559 return NT_STATUS_NO_MEMORY
;
564 inpdu
= talloc_memdup(req
, _inpdu
, size
);
566 return NT_STATUS_NO_MEMORY
;
569 req
->request_time
= timeval_current();
570 now
= timeval_to_nttime(&req
->request_time
);
572 status
= smbd_smb2_inbuf_parse_compound(xconn
,
576 req
, &req
->in
.vector
,
577 &req
->in
.vector_count
);
578 if (!NT_STATUS_IS_OK(status
)) {
583 req
->current_idx
= 1;
589 static bool smb2_validate_sequence_number(struct smbXsrv_connection
*xconn
,
590 uint64_t message_id
, uint64_t seq_id
)
592 struct bitmap
*credits_bm
= xconn
->smb2
.credits
.bitmap
;
596 seq_tmp
= xconn
->smb2
.credits
.seq_low
;
597 if (seq_id
< seq_tmp
) {
598 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
599 "%llu (sequence id %llu) "
600 "(granted = %u, low = %llu, range = %u)\n",
601 (unsigned long long)message_id
,
602 (unsigned long long)seq_id
,
603 (unsigned int)xconn
->smb2
.credits
.granted
,
604 (unsigned long long)xconn
->smb2
.credits
.seq_low
,
605 (unsigned int)xconn
->smb2
.credits
.seq_range
));
609 seq_tmp
+= xconn
->smb2
.credits
.seq_range
;
610 if (seq_id
>= seq_tmp
) {
611 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
612 "%llu (sequence id %llu) "
613 "(granted = %u, low = %llu, range = %u)\n",
614 (unsigned long long)message_id
,
615 (unsigned long long)seq_id
,
616 (unsigned int)xconn
->smb2
.credits
.granted
,
617 (unsigned long long)xconn
->smb2
.credits
.seq_low
,
618 (unsigned int)xconn
->smb2
.credits
.seq_range
));
622 offset
= seq_id
% xconn
->smb2
.credits
.max
;
624 if (bitmap_query(credits_bm
, offset
)) {
625 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
626 "%llu (sequence id %llu) "
627 "(granted = %u, low = %llu, range = %u) "
629 (unsigned long long)message_id
,
630 (unsigned long long)seq_id
,
631 (unsigned int)xconn
->smb2
.credits
.granted
,
632 (unsigned long long)xconn
->smb2
.credits
.seq_low
,
633 (unsigned int)xconn
->smb2
.credits
.seq_range
,
638 /* Mark the message_ids as seen in the bitmap. */
639 bitmap_set(credits_bm
, offset
);
641 if (seq_id
!= xconn
->smb2
.credits
.seq_low
) {
646 * Move the window forward by all the message_id's
649 while (bitmap_query(credits_bm
, offset
)) {
650 DEBUG(10,("smb2_validate_sequence_number: clearing "
651 "id %llu (position %u) from bitmap\n",
652 (unsigned long long)(xconn
->smb2
.credits
.seq_low
),
654 bitmap_clear(credits_bm
, offset
);
656 xconn
->smb2
.credits
.seq_low
+= 1;
657 xconn
->smb2
.credits
.seq_range
-= 1;
658 offset
= xconn
->smb2
.credits
.seq_low
% xconn
->smb2
.credits
.max
;
664 static bool smb2_validate_message_id(struct smbXsrv_connection
*xconn
,
665 const uint8_t *inhdr
)
667 uint64_t message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
668 uint16_t opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
669 uint16_t credit_charge
= 1;
672 if (opcode
== SMB2_OP_CANCEL
) {
673 /* SMB2_CANCEL requests by definition resend messageids. */
677 if (xconn
->smb2
.credits
.multicredit
) {
678 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
679 credit_charge
= MAX(credit_charge
, 1);
682 DEBUG(11, ("smb2_validate_message_id: 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
));
691 if (xconn
->smb2
.credits
.granted
< credit_charge
) {
692 DEBUG(0, ("smb2_validate_message_id: client used more "
693 "credits than granted, mid %llu, charge %llu, "
694 "credits_granted %llu, "
695 "seqnum low/range: %llu/%llu\n",
696 (unsigned long long) message_id
,
697 (unsigned long long) credit_charge
,
698 (unsigned long long) xconn
->smb2
.credits
.granted
,
699 (unsigned long long) xconn
->smb2
.credits
.seq_low
,
700 (unsigned long long) xconn
->smb2
.credits
.seq_range
));
705 * now check the message ids
707 * for multi-credit requests we need to check all current mid plus
708 * the implicit mids caused by the credit charge
709 * e.g. current mid = 15, charge 5 => mark 15-19 as used
712 for (i
= 0; i
<= (credit_charge
-1); i
++) {
713 uint64_t id
= message_id
+ i
;
716 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
717 (unsigned long long)message_id
,
719 (unsigned long long)id
));
721 ok
= smb2_validate_sequence_number(xconn
, message_id
, id
);
727 /* substract used credits */
728 xconn
->smb2
.credits
.granted
-= credit_charge
;
733 static NTSTATUS
smbd_smb2_request_validate(struct smbd_smb2_request
*req
)
738 count
= req
->in
.vector_count
;
740 if (count
< 1 + SMBD_SMB2_NUM_IOV_PER_REQ
) {
741 /* It's not a SMB2 request */
742 return NT_STATUS_INVALID_PARAMETER
;
745 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
746 struct iovec
*hdr
= SMBD_SMB2_IDX_HDR_IOV(req
,in
,idx
);
747 struct iovec
*body
= SMBD_SMB2_IDX_BODY_IOV(req
,in
,idx
);
748 const uint8_t *inhdr
= NULL
;
750 if (hdr
->iov_len
!= SMB2_HDR_BODY
) {
751 return NT_STATUS_INVALID_PARAMETER
;
754 if (body
->iov_len
< 2) {
755 return NT_STATUS_INVALID_PARAMETER
;
758 inhdr
= (const uint8_t *)hdr
->iov_base
;
760 /* Check the SMB2 header */
761 if (IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
) != SMB2_MAGIC
) {
762 return NT_STATUS_INVALID_PARAMETER
;
765 if (!smb2_validate_message_id(req
->xconn
, inhdr
)) {
766 return NT_STATUS_INVALID_PARAMETER
;
773 static void smb2_set_operation_credit(struct smbXsrv_connection
*xconn
,
774 const struct iovec
*in_vector
,
775 struct iovec
*out_vector
)
777 const uint8_t *inhdr
= (const uint8_t *)in_vector
->iov_base
;
778 uint8_t *outhdr
= (uint8_t *)out_vector
->iov_base
;
779 uint16_t credit_charge
= 1;
780 uint16_t credits_requested
;
784 uint16_t credits_granted
= 0;
785 uint64_t credits_possible
;
786 uint16_t current_max_credits
;
789 * first we grant only 1/16th of the max range.
791 * Windows also starts with the 1/16th and then grants
792 * more later. I was only able to trigger higher
793 * values, when using a very high credit charge.
795 * TODO: scale up depending on load, free memory
797 * Maybe also on the relationship between number
798 * of requests and the used sequence number.
799 * Which means we would grant more credits
800 * for client which use multi credit requests.
802 current_max_credits
= xconn
->smb2
.credits
.max
/ 16;
803 current_max_credits
= MAX(current_max_credits
, 1);
805 if (xconn
->smb2
.credits
.multicredit
) {
806 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
807 credit_charge
= MAX(credit_charge
, 1);
810 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
811 credits_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
812 credits_requested
= MAX(credits_requested
, 1);
813 out_flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
814 out_status
= NT_STATUS(IVAL(outhdr
, SMB2_HDR_STATUS
));
816 SMB_ASSERT(xconn
->smb2
.credits
.max
>= xconn
->smb2
.credits
.granted
);
818 if (xconn
->smb2
.credits
.max
< credit_charge
) {
819 smbd_server_connection_terminate(xconn
,
820 "client error: credit charge > max credits\n");
824 if (out_flags
& SMB2_HDR_FLAG_ASYNC
) {
826 * In case we already send an async interim
827 * response, we should not grant
828 * credits on the final response.
832 uint16_t additional_possible
=
833 xconn
->smb2
.credits
.max
- credit_charge
;
834 uint16_t additional_max
= 0;
835 uint16_t additional_credits
= credits_requested
- 1;
838 case SMB2_OP_NEGPROT
:
840 case SMB2_OP_SESSSETUP
:
842 * Windows 2012 RC1 starts to grant
844 * with a successful session setup
846 if (NT_STATUS_IS_OK(out_status
)) {
852 * We match windows and only grant additional credits
859 additional_max
= MIN(additional_max
, additional_possible
);
860 additional_credits
= MIN(additional_credits
, additional_max
);
862 credits_granted
= credit_charge
+ additional_credits
;
866 * sequence numbers should not wrap
868 * 1. calculate the possible credits until
869 * the sequence numbers start to wrap on 64-bit.
871 * 2. UINT64_MAX is used for Break Notifications.
873 * 2. truncate the possible credits to the maximum
874 * credits we want to grant to the client in total.
876 * 3. remove the range we'll already granted to the client
877 * this makes sure the client consumes the lowest sequence
878 * number, before we can grant additional credits.
880 credits_possible
= UINT64_MAX
- xconn
->smb2
.credits
.seq_low
;
881 if (credits_possible
> 0) {
882 /* remove UINT64_MAX */
883 credits_possible
-= 1;
885 credits_possible
= MIN(credits_possible
, current_max_credits
);
886 credits_possible
-= xconn
->smb2
.credits
.seq_range
;
888 credits_granted
= MIN(credits_granted
, credits_possible
);
890 SSVAL(outhdr
, SMB2_HDR_CREDIT
, credits_granted
);
891 xconn
->smb2
.credits
.granted
+= credits_granted
;
892 xconn
->smb2
.credits
.seq_range
+= credits_granted
;
894 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
895 "granted %u, current possible/max %u/%u, "
896 "total granted/max/low/range %u/%u/%llu/%u\n",
897 (unsigned int)credits_requested
,
898 (unsigned int)credit_charge
,
899 (unsigned int)credits_granted
,
900 (unsigned int)credits_possible
,
901 (unsigned int)current_max_credits
,
902 (unsigned int)xconn
->smb2
.credits
.granted
,
903 (unsigned int)xconn
->smb2
.credits
.max
,
904 (unsigned long long)xconn
->smb2
.credits
.seq_low
,
905 (unsigned int)xconn
->smb2
.credits
.seq_range
));
908 static void smb2_calculate_credits(const struct smbd_smb2_request
*inreq
,
909 struct smbd_smb2_request
*outreq
)
912 uint16_t total_credits
= 0;
914 count
= outreq
->out
.vector_count
;
916 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
917 struct iovec
*inhdr_v
= SMBD_SMB2_IDX_HDR_IOV(inreq
,in
,idx
);
918 struct iovec
*outhdr_v
= SMBD_SMB2_IDX_HDR_IOV(outreq
,out
,idx
);
919 uint8_t *outhdr
= (uint8_t *)outhdr_v
->iov_base
;
921 smb2_set_operation_credit(outreq
->xconn
, inhdr_v
, outhdr_v
);
923 /* To match Windows, count up what we
925 total_credits
+= SVAL(outhdr
, SMB2_HDR_CREDIT
);
926 /* Set to zero in all but the last reply. */
927 if (idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
< count
) {
928 SSVAL(outhdr
, SMB2_HDR_CREDIT
, 0);
930 SSVAL(outhdr
, SMB2_HDR_CREDIT
, total_credits
);
935 DATA_BLOB
smbd_smb2_generate_outbody(struct smbd_smb2_request
*req
, size_t size
)
937 if (req
->current_idx
<= 1) {
938 if (size
<= sizeof(req
->out
._body
)) {
939 return data_blob_const(req
->out
._body
, size
);
943 return data_blob_talloc(req
, NULL
, size
);
946 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
)
948 struct smbXsrv_connection
*xconn
= req
->xconn
;
950 struct iovec
*vector
;
955 count
= req
->in
.vector_count
;
956 if (count
<= ARRAY_SIZE(req
->out
._vector
)) {
958 vector
= req
->out
._vector
;
960 vector
= talloc_zero_array(req
, struct iovec
, count
);
961 if (vector
== NULL
) {
962 return NT_STATUS_NO_MEMORY
;
967 vector
[0].iov_base
= req
->out
.nbt_hdr
;
968 vector
[0].iov_len
= 4;
969 SIVAL(req
->out
.nbt_hdr
, 0, 0);
971 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
972 struct iovec
*inhdr_v
= SMBD_SMB2_IDX_HDR_IOV(req
,in
,idx
);
973 const uint8_t *inhdr
= (const uint8_t *)inhdr_v
->iov_base
;
974 uint8_t *outhdr
= NULL
;
975 uint8_t *outbody
= NULL
;
976 uint32_t next_command_ofs
= 0;
977 struct iovec
*current
= &vector
[idx
];
979 if ((idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
) < count
) {
980 /* we have a next command -
981 * setup for the error case. */
982 next_command_ofs
= SMB2_HDR_BODY
+ 9;
986 outhdr
= req
->out
._hdr
;
988 outhdr
= talloc_zero_array(mem_ctx
, uint8_t,
990 if (outhdr
== NULL
) {
991 return NT_STATUS_NO_MEMORY
;
995 outbody
= outhdr
+ SMB2_HDR_BODY
;
998 * SMBD_SMB2_TF_IOV_OFS might be used later
1000 current
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
1001 current
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
1003 current
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= (void *)outhdr
;
1004 current
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
1006 current
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= (void *)outbody
;
1007 current
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= 8;
1009 current
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= NULL
;
1010 current
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= 0;
1012 /* setup the SMB2 header */
1013 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
1014 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1015 SSVAL(outhdr
, SMB2_HDR_CREDIT_CHARGE
,
1016 SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
));
1017 SIVAL(outhdr
, SMB2_HDR_STATUS
,
1018 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
1019 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
1020 SVAL(inhdr
, SMB2_HDR_OPCODE
));
1021 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
1022 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
1023 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
1024 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
1025 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
1026 SIVAL(outhdr
, SMB2_HDR_PID
,
1027 IVAL(inhdr
, SMB2_HDR_PID
));
1028 SIVAL(outhdr
, SMB2_HDR_TID
,
1029 IVAL(inhdr
, SMB2_HDR_TID
));
1030 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
1031 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
1032 memcpy(outhdr
+ SMB2_HDR_SIGNATURE
,
1033 inhdr
+ SMB2_HDR_SIGNATURE
, 16);
1035 /* setup error body header */
1036 SSVAL(outbody
, 0x00, 0x08 + 1);
1037 SSVAL(outbody
, 0x02, 0);
1038 SIVAL(outbody
, 0x04, 0);
1041 req
->out
.vector
= vector
;
1042 req
->out
.vector_count
= count
;
1044 /* setup the length of the NBT packet */
1045 ok
= smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
1047 return NT_STATUS_INVALID_PARAMETER_MIX
;
1050 DLIST_ADD_END(xconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
1052 return NT_STATUS_OK
;
1055 void smbd_server_connection_terminate_ex(struct smbXsrv_connection
*xconn
,
1057 const char *location
)
1059 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1061 exit_server_cleanly(reason
);
1064 static bool dup_smb2_vec4(TALLOC_CTX
*ctx
,
1065 struct iovec
*outvec
,
1066 const struct iovec
*srcvec
)
1068 const uint8_t *srctf
;
1070 const uint8_t *srchdr
;
1072 const uint8_t *srcbody
;
1074 const uint8_t *expected_srcbody
;
1075 const uint8_t *srcdyn
;
1077 const uint8_t *expected_srcdyn
;
1083 srctf
= (const uint8_t *)srcvec
[SMBD_SMB2_TF_IOV_OFS
].iov_base
;
1084 srctf_len
= srcvec
[SMBD_SMB2_TF_IOV_OFS
].iov_len
;
1085 srchdr
= (const uint8_t *)srcvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
;
1086 srchdr_len
= srcvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
;
1087 srcbody
= (const uint8_t *)srcvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
;
1088 srcbody_len
= srcvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
;
1089 expected_srcbody
= srchdr
+ SMB2_HDR_BODY
;
1090 srcdyn
= (const uint8_t *)srcvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
;
1091 srcdyn_len
= srcvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
;
1092 expected_srcdyn
= srcbody
+ 8;
1094 if ((srctf_len
!= SMB2_TF_HDR_SIZE
) && (srctf_len
!= 0)) {
1098 if (srchdr_len
!= SMB2_HDR_BODY
) {
1102 if (srctf_len
== SMB2_TF_HDR_SIZE
) {
1103 dsttf
= talloc_memdup(ctx
, srctf
, SMB2_TF_HDR_SIZE
);
1104 if (dsttf
== NULL
) {
1110 outvec
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= (void *)dsttf
;
1111 outvec
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= srctf_len
;
1113 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1114 * be allocated with size OUTVEC_ALLOC_SIZE. */
1116 dsthdr
= talloc_memdup(ctx
, srchdr
, OUTVEC_ALLOC_SIZE
);
1117 if (dsthdr
== NULL
) {
1120 outvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= (void *)dsthdr
;
1121 outvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
1124 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1125 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1126 * then duplicate this. Else use talloc_memdup().
1129 if ((srcbody
== expected_srcbody
) && (srcbody_len
== 8)) {
1130 dstbody
= dsthdr
+ SMB2_HDR_BODY
;
1132 dstbody
= talloc_memdup(ctx
, srcbody
, srcbody_len
);
1133 if (dstbody
== NULL
) {
1137 outvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= (void *)dstbody
;
1138 outvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= srcbody_len
;
1141 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1143 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1144 * then duplicate this. Else use talloc_memdup().
1147 if ((srcdyn
== expected_srcdyn
) && (srcdyn_len
== 1)) {
1148 dstdyn
= dsthdr
+ SMB2_HDR_BODY
+ 8;
1149 } else if (srcdyn
== NULL
) {
1152 dstdyn
= talloc_memdup(ctx
, srcdyn
, srcdyn_len
);
1153 if (dstdyn
== NULL
) {
1157 outvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= (void *)dstdyn
;
1158 outvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= srcdyn_len
;
1163 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
1165 struct smbd_smb2_request
*newreq
= NULL
;
1166 struct iovec
*outvec
= NULL
;
1167 int count
= req
->out
.vector_count
;
1171 newreq
= smbd_smb2_request_allocate(req
->xconn
);
1176 newreq
->sconn
= req
->sconn
;
1177 newreq
->xconn
= req
->xconn
;
1178 newreq
->session
= req
->session
;
1179 newreq
->do_encryption
= req
->do_encryption
;
1180 newreq
->do_signing
= req
->do_signing
;
1181 newreq
->current_idx
= req
->current_idx
;
1183 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
1185 TALLOC_FREE(newreq
);
1188 newreq
->out
.vector
= outvec
;
1189 newreq
->out
.vector_count
= count
;
1191 /* Setup the outvec's identically to req. */
1192 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
1193 outvec
[0].iov_len
= 4;
1194 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
1196 /* Setup the vectors identically to the ones in req. */
1197 for (i
= 1; i
< count
; i
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
1198 if (!dup_smb2_vec4(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
1205 TALLOC_FREE(newreq
);
1209 ok
= smb2_setup_nbt_length(newreq
->out
.vector
,
1210 newreq
->out
.vector_count
);
1212 TALLOC_FREE(newreq
);
1219 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
1221 struct smbXsrv_connection
*xconn
= req
->xconn
;
1223 struct iovec
*firsttf
= NULL
;
1224 struct iovec
*outhdr_v
= NULL
;
1225 uint8_t *outhdr
= NULL
;
1226 struct smbd_smb2_request
*nreq
= NULL
;
1230 /* Create a new smb2 request we'll use
1231 for the interim return. */
1232 nreq
= dup_smb2_req(req
);
1234 return NT_STATUS_NO_MEMORY
;
1237 /* Lose the last X out vectors. They're the
1238 ones we'll be using for the async reply. */
1239 nreq
->out
.vector_count
-= SMBD_SMB2_NUM_IOV_PER_REQ
;
1241 ok
= smb2_setup_nbt_length(nreq
->out
.vector
,
1242 nreq
->out
.vector_count
);
1244 return NT_STATUS_INVALID_PARAMETER_MIX
;
1247 /* Step back to the previous reply. */
1248 nreq
->current_idx
-= SMBD_SMB2_NUM_IOV_PER_REQ
;
1249 firsttf
= SMBD_SMB2_IDX_TF_IOV(nreq
,out
,first_idx
);
1250 outhdr_v
= SMBD_SMB2_OUT_HDR_IOV(nreq
);
1251 outhdr
= SMBD_SMB2_OUT_HDR_PTR(nreq
);
1252 /* And end the chain. */
1253 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1255 /* Calculate outgoing credits */
1256 smb2_calculate_credits(req
, nreq
);
1258 if (DEBUGLEVEL
>= 10) {
1259 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1260 (unsigned int)nreq
->current_idx
);
1261 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1262 (unsigned int)nreq
->out
.vector_count
);
1263 print_req_vectors(nreq
);
1267 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1268 * we need to sign/encrypt here with the last/first key we remembered
1270 if (firsttf
->iov_len
== SMB2_TF_HDR_SIZE
) {
1271 status
= smb2_signing_encrypt_pdu(req
->first_key
,
1272 xconn
->smb2
.server
.cipher
,
1274 nreq
->out
.vector_count
- first_idx
);
1275 if (!NT_STATUS_IS_OK(status
)) {
1278 } else if (req
->last_key
.length
> 0) {
1279 status
= smb2_signing_sign_pdu(req
->last_key
,
1282 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
1283 if (!NT_STATUS_IS_OK(status
)) {
1288 nreq
->queue_entry
.mem_ctx
= nreq
;
1289 nreq
->queue_entry
.vector
= nreq
->out
.vector
;
1290 nreq
->queue_entry
.count
= nreq
->out
.vector_count
;
1291 DLIST_ADD_END(xconn
->smb2
.send_queue
, &nreq
->queue_entry
, NULL
);
1292 xconn
->smb2
.send_queue_len
++;
1294 status
= smbd_smb2_flush_send_queue(xconn
);
1295 if (!NT_STATUS_IS_OK(status
)) {
1299 return NT_STATUS_OK
;
1302 struct smbd_smb2_request_pending_state
{
1303 struct smbd_smb2_send_queue queue_entry
;
1304 uint8_t buf
[NBT_HDR_SIZE
+ SMB2_TF_HDR_SIZE
+ SMB2_HDR_BODY
+ 0x08 + 1];
1305 struct iovec vector
[1 + SMBD_SMB2_NUM_IOV_PER_REQ
];
1308 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
1309 struct tevent_timer
*te
,
1310 struct timeval current_time
,
1311 void *private_data
);
1313 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
1314 struct tevent_req
*subreq
,
1315 uint32_t defer_time
)
1318 struct timeval defer_endtime
;
1319 uint8_t *outhdr
= NULL
;
1322 if (!tevent_req_is_in_progress(subreq
)) {
1324 * This is a performance optimization,
1325 * it avoids one tevent_loop iteration,
1326 * which means we avoid one
1327 * talloc_stackframe_pool/talloc_free pair.
1329 tevent_req_notify_callback(subreq
);
1330 return NT_STATUS_OK
;
1333 req
->subreq
= subreq
;
1336 if (req
->async_te
) {
1337 /* We're already async. */
1338 return NT_STATUS_OK
;
1341 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1342 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1343 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1344 /* We're already async. */
1345 return NT_STATUS_OK
;
1348 if (req
->in
.vector_count
> req
->current_idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
) {
1350 * We're trying to go async in a compound request
1351 * chain. This is only allowed for opens that cause an
1352 * oplock break or for the last operation in the
1353 * chain, otherwise it is not allowed. See
1354 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
1356 const uint8_t *inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1358 if (SVAL(inhdr
, SMB2_HDR_OPCODE
) != SMB2_OP_CREATE
) {
1360 * Cancel the outstanding request.
1362 bool ok
= tevent_req_cancel(req
->subreq
);
1364 return NT_STATUS_OK
;
1366 TALLOC_FREE(req
->subreq
);
1367 return smbd_smb2_request_error(req
,
1368 NT_STATUS_INTERNAL_ERROR
);
1372 if (DEBUGLEVEL
>= 10) {
1373 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1374 (unsigned int)req
->current_idx
);
1375 print_req_vectors(req
);
1378 if (req
->current_idx
> 1) {
1380 * We're going async in a compound
1381 * chain after the first request has
1382 * already been processed. Send an
1383 * interim response containing the
1384 * set of replies already generated.
1386 int idx
= req
->current_idx
;
1388 status
= smb2_send_async_interim_response(req
);
1389 if (!NT_STATUS_IS_OK(status
)) {
1392 if (req
->first_key
.length
> 0) {
1393 data_blob_clear_free(&req
->first_key
);
1396 req
->current_idx
= 1;
1399 * Re-arrange the in.vectors to remove what
1402 memmove(&req
->in
.vector
[1],
1403 &req
->in
.vector
[idx
],
1404 sizeof(req
->in
.vector
[0])*(req
->in
.vector_count
- idx
));
1405 req
->in
.vector_count
= 1 + (req
->in
.vector_count
- idx
);
1407 /* Re-arrange the out.vectors to match. */
1408 memmove(&req
->out
.vector
[1],
1409 &req
->out
.vector
[idx
],
1410 sizeof(req
->out
.vector
[0])*(req
->out
.vector_count
- idx
));
1411 req
->out
.vector_count
= 1 + (req
->out
.vector_count
- idx
);
1413 if (req
->in
.vector_count
== 1 + SMBD_SMB2_NUM_IOV_PER_REQ
) {
1415 * We only have one remaining request as
1416 * we've processed everything else.
1417 * This is no longer a compound request.
1419 req
->compound_related
= false;
1420 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1421 flags
= (IVAL(outhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
1422 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
);
1425 if (req
->last_key
.length
> 0) {
1426 data_blob_clear_free(&req
->last_key
);
1429 defer_endtime
= timeval_current_ofs_usec(defer_time
);
1430 req
->async_te
= tevent_add_timer(req
->sconn
->ev_ctx
,
1432 smbd_smb2_request_pending_timer
,
1434 if (req
->async_te
== NULL
) {
1435 return NT_STATUS_NO_MEMORY
;
1438 return NT_STATUS_OK
;
1441 static DATA_BLOB
smbd_smb2_signing_key(struct smbXsrv_session
*session
,
1442 struct smbXsrv_connection
*xconn
)
1444 struct smbXsrv_channel_global0
*c
= NULL
;
1446 DATA_BLOB key
= data_blob_null
;
1448 status
= smbXsrv_session_find_channel(session
, xconn
, &c
);
1449 if (NT_STATUS_IS_OK(status
)) {
1450 key
= c
->signing_key
;
1453 if (key
.length
== 0) {
1454 key
= session
->global
->signing_key
;
1460 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
1461 struct tevent_timer
*te
,
1462 struct timeval current_time
,
1465 struct smbd_smb2_request
*req
=
1466 talloc_get_type_abort(private_data
,
1467 struct smbd_smb2_request
);
1468 struct smbXsrv_connection
*xconn
= req
->xconn
;
1469 struct smbd_smb2_request_pending_state
*state
= NULL
;
1470 uint8_t *outhdr
= NULL
;
1471 const uint8_t *inhdr
= NULL
;
1474 uint8_t *hdr
= NULL
;
1475 uint8_t *body
= NULL
;
1476 uint8_t *dyn
= NULL
;
1478 uint64_t session_id
= 0;
1479 uint64_t message_id
= 0;
1480 uint64_t nonce_high
= 0;
1481 uint64_t nonce_low
= 0;
1482 uint64_t async_id
= 0;
1486 TALLOC_FREE(req
->async_te
);
1488 /* Ensure our final reply matches the interim one. */
1489 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1490 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1491 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1492 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1493 session_id
= BVAL(outhdr
, SMB2_HDR_SESSION_ID
);
1495 async_id
= message_id
; /* keep it simple for now... */
1497 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1498 SBVAL(outhdr
, SMB2_HDR_ASYNC_ID
, async_id
);
1500 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1502 smb2_opcode_name(SVAL(inhdr
, SMB2_HDR_OPCODE
)),
1503 (unsigned long long)async_id
));
1506 * What we send is identical to a smbd_smb2_request_error
1507 * packet with an error status of STATUS_PENDING. Make use
1508 * of this fact sometime when refactoring. JRA.
1511 state
= talloc_zero(req
->xconn
, struct smbd_smb2_request_pending_state
);
1512 if (state
== NULL
) {
1513 smbd_server_connection_terminate(xconn
,
1514 nt_errstr(NT_STATUS_NO_MEMORY
));
1518 tf
= state
->buf
+ NBT_HDR_SIZE
;
1519 tf_len
= SMB2_TF_HDR_SIZE
;
1521 hdr
= tf
+ SMB2_TF_HDR_SIZE
;
1522 body
= hdr
+ SMB2_HDR_BODY
;
1525 if (req
->do_encryption
) {
1526 struct smbXsrv_session
*x
= req
->session
;
1528 nonce_high
= x
->nonce_high
;
1529 nonce_low
= x
->nonce_low
;
1532 if (x
->nonce_low
== 0) {
1538 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
1539 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
1540 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
1541 SBVAL(tf
, SMB2_TF_SESSION_ID
, session_id
);
1543 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
1544 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1545 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1546 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
1547 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(outhdr
, SMB2_HDR_OPCODE
));
1549 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
);
1550 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1551 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
1552 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
1553 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
1554 BVAL(outhdr
, SMB2_HDR_SESSION_ID
));
1555 memcpy(hdr
+SMB2_HDR_SIGNATURE
,
1556 outhdr
+SMB2_HDR_SIGNATURE
, 16);
1558 SSVAL(body
, 0x00, 0x08 + 1);
1560 SCVAL(body
, 0x02, 0);
1561 SCVAL(body
, 0x03, 0);
1562 SIVAL(body
, 0x04, 0);
1563 /* Match W2K8R2... */
1564 SCVAL(dyn
, 0x00, 0x21);
1566 state
->vector
[0].iov_base
= (void *)state
->buf
;
1567 state
->vector
[0].iov_len
= NBT_HDR_SIZE
;
1569 if (req
->do_encryption
) {
1570 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= tf
;
1571 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= tf_len
;
1573 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
1574 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
1577 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
1578 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
1580 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
1581 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_len
= 8;
1583 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
1584 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_len
= 1;
1586 ok
= smb2_setup_nbt_length(state
->vector
,
1587 1 + SMBD_SMB2_NUM_IOV_PER_REQ
);
1589 smbd_server_connection_terminate(
1590 xconn
, nt_errstr(NT_STATUS_INTERNAL_ERROR
));
1594 /* Ensure we correctly go through crediting. Grant
1595 the credits now, and zero credits on the final
1597 smb2_set_operation_credit(req
->xconn
,
1598 SMBD_SMB2_IN_HDR_IOV(req
),
1599 &state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
]);
1601 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1606 for (i
= 0; i
< ARRAY_SIZE(state
->vector
); i
++) {
1607 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1609 (unsigned int)ARRAY_SIZE(state
->vector
),
1610 (unsigned int)state
->vector
[i
].iov_len
);
1614 if (req
->do_encryption
) {
1615 struct smbXsrv_session
*x
= req
->session
;
1616 DATA_BLOB encryption_key
= x
->global
->encryption_key
;
1618 status
= smb2_signing_encrypt_pdu(encryption_key
,
1619 xconn
->smb2
.server
.cipher
,
1620 &state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
],
1621 SMBD_SMB2_NUM_IOV_PER_REQ
);
1622 if (!NT_STATUS_IS_OK(status
)) {
1623 smbd_server_connection_terminate(xconn
,
1627 } else if (req
->do_signing
) {
1628 struct smbXsrv_session
*x
= req
->session
;
1629 DATA_BLOB signing_key
= smbd_smb2_signing_key(x
, xconn
);
1631 status
= smb2_signing_sign_pdu(signing_key
,
1633 &state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
],
1634 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
1635 if (!NT_STATUS_IS_OK(status
)) {
1636 smbd_server_connection_terminate(xconn
,
1642 state
->queue_entry
.mem_ctx
= state
;
1643 state
->queue_entry
.vector
= state
->vector
;
1644 state
->queue_entry
.count
= ARRAY_SIZE(state
->vector
);
1645 DLIST_ADD_END(xconn
->smb2
.send_queue
, &state
->queue_entry
, NULL
);
1646 xconn
->smb2
.send_queue_len
++;
1648 status
= smbd_smb2_flush_send_queue(xconn
);
1649 if (!NT_STATUS_IS_OK(status
)) {
1650 smbd_server_connection_terminate(xconn
,
1656 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
1658 struct smbXsrv_connection
*xconn
= req
->xconn
;
1659 struct smbd_smb2_request
*cur
;
1660 const uint8_t *inhdr
;
1662 uint64_t search_message_id
;
1663 uint64_t search_async_id
;
1666 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1668 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1669 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1670 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
1673 * we don't need the request anymore
1674 * cancel requests never have a response
1676 DLIST_REMOVE(xconn
->smb2
.requests
, req
);
1679 for (cur
= xconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
1680 const uint8_t *outhdr
;
1681 uint64_t message_id
;
1684 if (cur
->compound_related
) {
1686 * Never cancel anything in a compound request.
1687 * Way too hard to deal with the result.
1692 outhdr
= SMBD_SMB2_OUT_HDR_PTR(cur
);
1694 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1695 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
1697 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1698 if (search_async_id
== async_id
) {
1699 found_id
= async_id
;
1703 if (search_message_id
== message_id
) {
1704 found_id
= message_id
;
1710 if (cur
&& cur
->subreq
) {
1711 inhdr
= SMBD_SMB2_IN_HDR_PTR(cur
);
1712 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1713 "cancel opcode[%s] mid %llu\n",
1714 smb2_opcode_name(SVAL(inhdr
, SMB2_HDR_OPCODE
)),
1715 (unsigned long long)found_id
));
1716 tevent_req_cancel(cur
->subreq
);
1719 return NT_STATUS_OK
;
1722 /*************************************************************
1723 Ensure an incoming tid is a valid one for us to access.
1724 Change to the associated uid credentials and chdir to the
1725 valid tid directory.
1726 *************************************************************/
1728 static NTSTATUS
smbd_smb2_request_check_tcon(struct smbd_smb2_request
*req
)
1730 const uint8_t *inhdr
;
1733 struct smbXsrv_tcon
*tcon
;
1735 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1739 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1741 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1742 in_tid
= IVAL(inhdr
, SMB2_HDR_TID
);
1744 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1745 in_tid
= req
->last_tid
;
1750 status
= smb2srv_tcon_lookup(req
->session
,
1751 in_tid
, now
, &tcon
);
1752 if (!NT_STATUS_IS_OK(status
)) {
1756 if (!change_to_user(tcon
->compat
, req
->session
->compat
->vuid
)) {
1757 return NT_STATUS_ACCESS_DENIED
;
1760 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1761 if (!set_current_service(tcon
->compat
, 0, true)) {
1762 return NT_STATUS_ACCESS_DENIED
;
1766 req
->last_tid
= in_tid
;
1768 return NT_STATUS_OK
;
1771 /*************************************************************
1772 Ensure an incoming session_id is a valid one for us to access.
1773 *************************************************************/
1775 static NTSTATUS
smbd_smb2_request_check_session(struct smbd_smb2_request
*req
)
1777 const uint8_t *inhdr
;
1780 uint64_t in_session_id
;
1781 struct smbXsrv_session
*session
= NULL
;
1782 struct auth_session_info
*session_info
;
1784 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1786 req
->session
= NULL
;
1789 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1791 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1792 in_opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1793 in_session_id
= BVAL(inhdr
, SMB2_HDR_SESSION_ID
);
1795 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1796 in_session_id
= req
->last_session_id
;
1799 req
->last_session_id
= 0;
1801 /* lookup an existing session */
1802 status
= smb2srv_session_lookup(req
->xconn
,
1806 req
->session
= session
;
1807 req
->last_session_id
= in_session_id
;
1809 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
1810 switch (in_opcode
) {
1811 case SMB2_OP_SESSSETUP
:
1812 status
= NT_STATUS_OK
;
1818 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1819 switch (in_opcode
) {
1821 case SMB2_OP_CREATE
:
1822 case SMB2_OP_GETINFO
:
1823 case SMB2_OP_SETINFO
:
1824 return NT_STATUS_INVALID_HANDLE
;
1827 * Notice the check for
1828 * (session_info == NULL)
1831 status
= NT_STATUS_OK
;
1835 if (!NT_STATUS_IS_OK(status
)) {
1839 session_info
= session
->global
->auth_session_info
;
1840 if (session_info
== NULL
) {
1841 return NT_STATUS_INVALID_HANDLE
;
1844 if (in_session_id
!= req
->xconn
->client
->last_session_id
) {
1845 req
->xconn
->client
->last_session_id
= in_session_id
;
1846 set_current_user_info(session_info
->unix_info
->sanitized_username
,
1847 session_info
->unix_info
->unix_name
,
1848 session_info
->info
->domain_name
);
1851 return NT_STATUS_OK
;
1854 NTSTATUS
smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request
*req
,
1855 uint32_t data_length
)
1857 struct smbXsrv_connection
*xconn
= req
->xconn
;
1858 uint16_t needed_charge
;
1859 uint16_t credit_charge
= 1;
1860 const uint8_t *inhdr
;
1862 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1864 if (xconn
->smb2
.credits
.multicredit
) {
1865 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
1866 credit_charge
= MAX(credit_charge
, 1);
1869 needed_charge
= (data_length
- 1)/ 65536 + 1;
1871 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1872 (unsigned long long) BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
),
1873 credit_charge
, needed_charge
));
1875 if (needed_charge
> credit_charge
) {
1876 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1877 credit_charge
, needed_charge
));
1878 return NT_STATUS_INVALID_PARAMETER
;
1881 return NT_STATUS_OK
;
1884 NTSTATUS
smbd_smb2_request_verify_sizes(struct smbd_smb2_request
*req
,
1885 size_t expected_body_size
)
1887 struct iovec
*inhdr_v
;
1888 const uint8_t *inhdr
;
1890 const uint8_t *inbody
;
1892 size_t min_dyn_size
= expected_body_size
& 0x00000001;
1893 int max_idx
= req
->in
.vector_count
- SMBD_SMB2_NUM_IOV_PER_REQ
;
1896 * The following should be checked already.
1898 if (req
->in
.vector_count
< SMBD_SMB2_NUM_IOV_PER_REQ
) {
1899 return NT_STATUS_INTERNAL_ERROR
;
1901 if (req
->current_idx
> max_idx
) {
1902 return NT_STATUS_INTERNAL_ERROR
;
1905 inhdr_v
= SMBD_SMB2_IN_HDR_IOV(req
);
1906 if (inhdr_v
->iov_len
!= SMB2_HDR_BODY
) {
1907 return NT_STATUS_INTERNAL_ERROR
;
1909 if (SMBD_SMB2_IN_BODY_LEN(req
) < 2) {
1910 return NT_STATUS_INTERNAL_ERROR
;
1913 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1914 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1918 case SMB2_OP_GETINFO
:
1922 if (req
->smb1req
!= NULL
&& req
->smb1req
->unread_bytes
> 0) {
1923 if (req
->smb1req
->unread_bytes
< min_dyn_size
) {
1924 return NT_STATUS_INVALID_PARAMETER
;
1933 * Now check the expected body size,
1934 * where the last byte might be in the
1937 if (SMBD_SMB2_IN_BODY_LEN(req
) != (expected_body_size
& 0xFFFFFFFE)) {
1938 return NT_STATUS_INVALID_PARAMETER
;
1940 if (SMBD_SMB2_IN_DYN_LEN(req
) < min_dyn_size
) {
1941 return NT_STATUS_INVALID_PARAMETER
;
1944 inbody
= SMBD_SMB2_IN_BODY_PTR(req
);
1946 body_size
= SVAL(inbody
, 0x00);
1947 if (body_size
!= expected_body_size
) {
1948 return NT_STATUS_INVALID_PARAMETER
;
1951 return NT_STATUS_OK
;
1954 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
1956 struct smbXsrv_connection
*xconn
= req
->xconn
;
1957 const struct smbd_smb2_dispatch_table
*call
= NULL
;
1958 const struct iovec
*intf_v
= SMBD_SMB2_IN_TF_IOV(req
);
1959 const uint8_t *inhdr
;
1964 NTSTATUS session_status
;
1965 uint32_t allowed_flags
;
1966 NTSTATUS return_value
;
1967 struct smbXsrv_session
*x
= NULL
;
1968 bool signing_required
= false;
1969 bool encryption_required
= false;
1971 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1973 DO_PROFILE_INC(request
);
1975 /* TODO: verify more things */
1977 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1978 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1979 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1980 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1981 smb2_opcode_name(opcode
),
1982 (unsigned long long)mid
));
1984 if (xconn
->protocol
>= PROTOCOL_SMB2_02
) {
1986 * once the protocol is negotiated
1987 * SMB2_OP_NEGPROT is not allowed anymore
1989 if (opcode
== SMB2_OP_NEGPROT
) {
1990 /* drop the connection */
1991 return NT_STATUS_INVALID_PARAMETER
;
1995 * if the protocol is not negotiated yet
1996 * only SMB2_OP_NEGPROT is allowed.
1998 if (opcode
!= SMB2_OP_NEGPROT
) {
1999 /* drop the connection */
2000 return NT_STATUS_INVALID_PARAMETER
;
2005 * Check if the client provided a valid session id,
2006 * if so smbd_smb2_request_check_session() calls
2007 * set_current_user_info().
2009 * As some command don't require a valid session id
2010 * we defer the check of the session_status
2012 session_status
= smbd_smb2_request_check_session(req
);
2015 signing_required
= x
->global
->signing_required
;
2016 encryption_required
= x
->global
->encryption_required
;
2019 req
->do_signing
= false;
2020 req
->do_encryption
= false;
2021 if (intf_v
->iov_len
== SMB2_TF_HDR_SIZE
) {
2022 const uint8_t *intf
= SMBD_SMB2_IN_TF_PTR(req
);
2023 uint64_t tf_session_id
= BVAL(intf
, SMB2_TF_SESSION_ID
);
2025 if (x
!= NULL
&& x
->global
->session_wire_id
!= tf_session_id
) {
2026 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2027 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
2028 (unsigned long long)x
->global
->session_wire_id
,
2029 (unsigned long long)tf_session_id
));
2031 * TODO: windows allows this...
2032 * should we drop the connection?
2034 * For now we just return ACCESS_DENIED
2035 * (Windows clients never trigger this)
2036 * and wait for an update of [MS-SMB2].
2038 return smbd_smb2_request_error(req
,
2039 NT_STATUS_ACCESS_DENIED
);
2042 req
->do_encryption
= true;
2045 if (encryption_required
&& !req
->do_encryption
) {
2046 return smbd_smb2_request_error(req
,
2047 NT_STATUS_ACCESS_DENIED
);
2050 call
= smbd_smb2_call(opcode
);
2052 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2055 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
2056 SMB2_HDR_FLAG_SIGNED
|
2058 if (xconn
->protocol
>= PROTOCOL_SMB3_11
) {
2059 allowed_flags
|= SMB2_HDR_FLAG_PRIORITY_MASK
;
2061 if (opcode
== SMB2_OP_NEGPROT
) {
2062 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11
) {
2063 allowed_flags
|= SMB2_HDR_FLAG_PRIORITY_MASK
;
2066 if (opcode
== SMB2_OP_CANCEL
) {
2067 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
2069 if ((flags
& ~allowed_flags
) != 0) {
2070 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2073 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
2075 * This check is mostly for giving the correct error code
2076 * for compounded requests.
2078 if (!NT_STATUS_IS_OK(session_status
)) {
2079 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2082 req
->compat_chain_fsp
= NULL
;
2085 if (req
->do_encryption
) {
2086 signing_required
= false;
2087 } else if (signing_required
|| (flags
& SMB2_HDR_FLAG_SIGNED
)) {
2088 DATA_BLOB signing_key
= data_blob_null
;
2092 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2093 * If the SMB2 header of the SMB2 NEGOTIATE
2094 * request has the SMB2_FLAGS_SIGNED bit set in the
2095 * Flags field, the server MUST fail the request
2096 * with STATUS_INVALID_PARAMETER.
2098 * Microsoft test tool checks this.
2101 if ((opcode
== SMB2_OP_NEGPROT
) &&
2102 (flags
& SMB2_HDR_FLAG_SIGNED
)) {
2103 status
= NT_STATUS_INVALID_PARAMETER
;
2105 status
= NT_STATUS_USER_SESSION_DELETED
;
2107 return smbd_smb2_request_error(req
, status
);
2110 signing_key
= smbd_smb2_signing_key(x
, xconn
);
2113 * If we have a signing key, we should
2116 if (signing_key
.length
> 0) {
2117 req
->do_signing
= true;
2120 status
= smb2_signing_check_pdu(signing_key
,
2122 SMBD_SMB2_IN_HDR_IOV(req
),
2123 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2124 if (!NT_STATUS_IS_OK(status
)) {
2125 return smbd_smb2_request_error(req
, status
);
2129 * Now that we know the request was correctly signed
2130 * we have to sign the response too.
2132 req
->do_signing
= true;
2134 if (!NT_STATUS_IS_OK(session_status
)) {
2135 return smbd_smb2_request_error(req
, session_status
);
2137 } else if (opcode
== SMB2_OP_CANCEL
) {
2138 /* Cancel requests are allowed to skip the signing */
2139 } else if (signing_required
) {
2141 * If signing is required we try to sign
2142 * a possible error response
2144 req
->do_signing
= true;
2145 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
2148 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
2149 req
->compound_related
= true;
2152 if (call
->need_session
) {
2153 if (!NT_STATUS_IS_OK(session_status
)) {
2154 return smbd_smb2_request_error(req
, session_status
);
2158 if (call
->need_tcon
) {
2159 SMB_ASSERT(call
->need_session
);
2162 * This call needs to be run as user.
2164 * smbd_smb2_request_check_tcon()
2165 * calls change_to_user() on success.
2167 status
= smbd_smb2_request_check_tcon(req
);
2168 if (!NT_STATUS_IS_OK(status
)) {
2169 return smbd_smb2_request_error(req
, status
);
2171 if (req
->tcon
->global
->encryption_required
) {
2172 encryption_required
= true;
2174 if (encryption_required
&& !req
->do_encryption
) {
2175 return smbd_smb2_request_error(req
,
2176 NT_STATUS_ACCESS_DENIED
);
2180 if (call
->fileid_ofs
!= 0) {
2181 size_t needed
= call
->fileid_ofs
+ 16;
2182 const uint8_t *body
= SMBD_SMB2_IN_BODY_PTR(req
);
2183 size_t body_size
= SMBD_SMB2_IN_BODY_LEN(req
);
2184 uint64_t file_id_persistent
;
2185 uint64_t file_id_volatile
;
2186 struct files_struct
*fsp
;
2188 SMB_ASSERT(call
->need_tcon
);
2190 if (needed
> body_size
) {
2191 return smbd_smb2_request_error(req
,
2192 NT_STATUS_INVALID_PARAMETER
);
2195 file_id_persistent
= BVAL(body
, call
->fileid_ofs
+ 0);
2196 file_id_volatile
= BVAL(body
, call
->fileid_ofs
+ 8);
2198 fsp
= file_fsp_smb2(req
, file_id_persistent
, file_id_volatile
);
2200 if (!call
->allow_invalid_fileid
) {
2201 return smbd_smb2_request_error(req
,
2202 NT_STATUS_FILE_CLOSED
);
2205 if (file_id_persistent
!= UINT64_MAX
) {
2206 return smbd_smb2_request_error(req
,
2207 NT_STATUS_FILE_CLOSED
);
2209 if (file_id_volatile
!= UINT64_MAX
) {
2210 return smbd_smb2_request_error(req
,
2211 NT_STATUS_FILE_CLOSED
);
2216 if (call
->as_root
) {
2217 SMB_ASSERT(call
->fileid_ofs
== 0);
2218 /* This call needs to be run as root */
2219 change_to_root_user();
2221 SMB_ASSERT(call
->need_tcon
);
2224 #define _INBYTES(_r) \
2225 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
2228 case SMB2_OP_NEGPROT
:
2229 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot
, profile_p
,
2230 req
->profile
, _INBYTES(req
));
2231 return_value
= smbd_smb2_request_process_negprot(req
);
2234 case SMB2_OP_SESSSETUP
:
2235 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup
, profile_p
,
2236 req
->profile
, _INBYTES(req
));
2237 return_value
= smbd_smb2_request_process_sesssetup(req
);
2240 case SMB2_OP_LOGOFF
:
2241 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff
, profile_p
,
2242 req
->profile
, _INBYTES(req
));
2243 return_value
= smbd_smb2_request_process_logoff(req
);
2247 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon
, profile_p
,
2248 req
->profile
, _INBYTES(req
));
2249 return_value
= smbd_smb2_request_process_tcon(req
);
2253 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis
, profile_p
,
2254 req
->profile
, _INBYTES(req
));
2255 return_value
= smbd_smb2_request_process_tdis(req
);
2258 case SMB2_OP_CREATE
:
2259 if (req
->subreq
== NULL
) {
2260 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create
, profile_p
,
2261 req
->profile
, _INBYTES(req
));
2263 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req
->profile
);
2265 return_value
= smbd_smb2_request_process_create(req
);
2269 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close
, profile_p
,
2270 req
->profile
, _INBYTES(req
));
2271 return_value
= smbd_smb2_request_process_close(req
);
2275 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush
, profile_p
,
2276 req
->profile
, _INBYTES(req
));
2277 return_value
= smbd_smb2_request_process_flush(req
);
2281 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read
, profile_p
,
2282 req
->profile
, _INBYTES(req
));
2283 return_value
= smbd_smb2_request_process_read(req
);
2287 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write
, profile_p
,
2288 req
->profile
, _INBYTES(req
));
2289 return_value
= smbd_smb2_request_process_write(req
);
2293 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock
, profile_p
,
2294 req
->profile
, _INBYTES(req
));
2295 return_value
= smbd_smb2_request_process_lock(req
);
2299 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl
, profile_p
,
2300 req
->profile
, _INBYTES(req
));
2301 return_value
= smbd_smb2_request_process_ioctl(req
);
2304 case SMB2_OP_CANCEL
:
2305 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel
, profile_p
,
2306 req
->profile
, _INBYTES(req
));
2307 return_value
= smbd_smb2_request_process_cancel(req
);
2308 SMBPROFILE_IOBYTES_ASYNC_END(req
->profile
, 0);
2311 case SMB2_OP_KEEPALIVE
:
2312 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive
, profile_p
,
2313 req
->profile
, _INBYTES(req
));
2314 return_value
= smbd_smb2_request_process_keepalive(req
);
2317 case SMB2_OP_QUERY_DIRECTORY
:
2318 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find
, profile_p
,
2319 req
->profile
, _INBYTES(req
));
2320 return_value
= smbd_smb2_request_process_query_directory(req
);
2323 case SMB2_OP_NOTIFY
:
2324 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify
, profile_p
,
2325 req
->profile
, _INBYTES(req
));
2326 return_value
= smbd_smb2_request_process_notify(req
);
2329 case SMB2_OP_GETINFO
:
2330 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo
, profile_p
,
2331 req
->profile
, _INBYTES(req
));
2332 return_value
= smbd_smb2_request_process_getinfo(req
);
2335 case SMB2_OP_SETINFO
:
2336 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo
, profile_p
,
2337 req
->profile
, _INBYTES(req
));
2338 return_value
= smbd_smb2_request_process_setinfo(req
);
2342 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break
, profile_p
,
2343 req
->profile
, _INBYTES(req
));
2344 return_value
= smbd_smb2_request_process_break(req
);
2348 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2351 return return_value
;
2354 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
2356 struct smbXsrv_connection
*xconn
= req
->xconn
;
2358 struct iovec
*firsttf
= SMBD_SMB2_IDX_TF_IOV(req
,out
,first_idx
);
2359 struct iovec
*outhdr
= SMBD_SMB2_OUT_HDR_IOV(req
);
2360 struct iovec
*outdyn
= SMBD_SMB2_OUT_DYN_IOV(req
);
2365 TALLOC_FREE(req
->async_te
);
2367 if (req
->do_encryption
&&
2368 (firsttf
->iov_len
== 0) &&
2369 (req
->first_key
.length
== 0) &&
2370 (req
->session
!= NULL
) &&
2371 (req
->session
->global
->encryption_key
.length
!= 0))
2373 DATA_BLOB encryption_key
= req
->session
->global
->encryption_key
;
2375 uint64_t session_id
= req
->session
->global
->session_wire_id
;
2376 struct smbXsrv_session
*x
= req
->session
;
2377 uint64_t nonce_high
;
2380 nonce_high
= x
->nonce_high
;
2381 nonce_low
= x
->nonce_low
;
2384 if (x
->nonce_low
== 0) {
2390 * We need to place the SMB2_TRANSFORM header before the
2395 * we need to remember the encryption key
2396 * and defer the signing/encryption until
2397 * we are sure that we do not change
2400 req
->first_key
= data_blob_dup_talloc(req
, encryption_key
);
2401 if (req
->first_key
.data
== NULL
) {
2402 return NT_STATUS_NO_MEMORY
;
2405 tf
= talloc_zero_array(req
, uint8_t,
2408 return NT_STATUS_NO_MEMORY
;
2411 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
2412 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
2413 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
2414 SBVAL(tf
, SMB2_TF_SESSION_ID
, session_id
);
2416 firsttf
->iov_base
= (void *)tf
;
2417 firsttf
->iov_len
= SMB2_TF_HDR_SIZE
;
2420 if ((req
->current_idx
> SMBD_SMB2_NUM_IOV_PER_REQ
) &&
2421 (req
->last_key
.length
> 0) &&
2422 (firsttf
->iov_len
== 0))
2424 int last_idx
= req
->current_idx
- SMBD_SMB2_NUM_IOV_PER_REQ
;
2425 struct iovec
*lasthdr
= SMBD_SMB2_IDX_HDR_IOV(req
,out
,last_idx
);
2428 * As we are sure the header of the last request in the
2429 * compound chain will not change, we can to sign here
2430 * with the last signing key we remembered.
2432 status
= smb2_signing_sign_pdu(req
->last_key
,
2435 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2436 if (!NT_STATUS_IS_OK(status
)) {
2440 if (req
->last_key
.length
> 0) {
2441 data_blob_clear_free(&req
->last_key
);
2444 SMBPROFILE_IOBYTES_ASYNC_END(req
->profile
,
2445 iov_buflen(outhdr
, SMBD_SMB2_NUM_IOV_PER_REQ
-1));
2447 req
->current_idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
;
2449 if (req
->current_idx
< req
->out
.vector_count
) {
2451 * We must process the remaining compound
2452 * SMB2 requests before any new incoming SMB2
2453 * requests. This is because incoming SMB2
2454 * requests may include a cancel for a
2455 * compound request we haven't processed
2458 struct tevent_immediate
*im
= tevent_create_immediate(req
);
2460 return NT_STATUS_NO_MEMORY
;
2463 if (req
->do_signing
&& firsttf
->iov_len
== 0) {
2464 struct smbXsrv_session
*x
= req
->session
;
2465 DATA_BLOB signing_key
= smbd_smb2_signing_key(x
, xconn
);
2468 * we need to remember the signing key
2469 * and defer the signing until
2470 * we are sure that we do not change
2473 req
->last_key
= data_blob_dup_talloc(req
, signing_key
);
2474 if (req
->last_key
.data
== NULL
) {
2475 return NT_STATUS_NO_MEMORY
;
2479 tevent_schedule_immediate(im
,
2481 smbd_smb2_request_dispatch_immediate
,
2483 return NT_STATUS_OK
;
2486 if (req
->compound_related
) {
2487 req
->compound_related
= false;
2490 ok
= smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
2492 return NT_STATUS_INVALID_PARAMETER_MIX
;
2495 /* Set credit for these operations (zero credits if this
2496 is a final reply for an async operation). */
2497 smb2_calculate_credits(req
, req
);
2500 * now check if we need to sign the current response
2502 if (firsttf
->iov_len
== SMB2_TF_HDR_SIZE
) {
2503 status
= smb2_signing_encrypt_pdu(req
->first_key
,
2504 xconn
->smb2
.server
.cipher
,
2506 req
->out
.vector_count
- first_idx
);
2507 if (!NT_STATUS_IS_OK(status
)) {
2510 } else if (req
->do_signing
) {
2511 struct smbXsrv_session
*x
= req
->session
;
2512 DATA_BLOB signing_key
= smbd_smb2_signing_key(x
, xconn
);
2514 status
= smb2_signing_sign_pdu(signing_key
,
2517 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2518 if (!NT_STATUS_IS_OK(status
)) {
2522 if (req
->first_key
.length
> 0) {
2523 data_blob_clear_free(&req
->first_key
);
2526 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2527 if (req
->out
.vector_count
< (2*SMBD_SMB2_NUM_IOV_PER_REQ
) &&
2528 outdyn
->iov_base
== NULL
&& outdyn
->iov_len
!= 0) {
2529 /* Dynamic part is NULL. Chop it off,
2530 We're going to send it via sendfile. */
2531 req
->out
.vector_count
-= 1;
2535 * We're done with this request -
2536 * move it off the "being processed" queue.
2538 DLIST_REMOVE(xconn
->smb2
.requests
, req
);
2540 req
->queue_entry
.mem_ctx
= req
;
2541 req
->queue_entry
.vector
= req
->out
.vector
;
2542 req
->queue_entry
.count
= req
->out
.vector_count
;
2543 DLIST_ADD_END(xconn
->smb2
.send_queue
, &req
->queue_entry
, NULL
);
2544 xconn
->smb2
.send_queue_len
++;
2546 status
= smbd_smb2_flush_send_queue(xconn
);
2547 if (!NT_STATUS_IS_OK(status
)) {
2551 return NT_STATUS_OK
;
2554 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbXsrv_connection
*xconn
);
2556 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
2557 struct tevent_immediate
*im
,
2560 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
2561 struct smbd_smb2_request
);
2562 struct smbXsrv_connection
*xconn
= req
->xconn
;
2567 if (DEBUGLEVEL
>= 10) {
2568 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2569 req
->current_idx
, req
->in
.vector_count
));
2570 print_req_vectors(req
);
2573 status
= smbd_smb2_request_dispatch(req
);
2574 if (!NT_STATUS_IS_OK(status
)) {
2575 smbd_server_connection_terminate(xconn
, nt_errstr(status
));
2579 status
= smbd_smb2_request_next_incoming(xconn
);
2580 if (!NT_STATUS_IS_OK(status
)) {
2581 smbd_server_connection_terminate(xconn
, nt_errstr(status
));
2586 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
2588 DATA_BLOB body
, DATA_BLOB
*dyn
,
2589 const char *location
)
2592 struct iovec
*outbody_v
;
2593 struct iovec
*outdyn_v
;
2594 uint32_t next_command_ofs
;
2596 DEBUG(10,("smbd_smb2_request_done_ex: "
2597 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2598 req
->current_idx
, nt_errstr(status
), (unsigned int)body
.length
,
2600 (unsigned int)(dyn
? dyn
->length
: 0),
2603 if (body
.length
< 2) {
2604 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2607 if ((body
.length
% 2) != 0) {
2608 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2611 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
2612 outbody_v
= SMBD_SMB2_OUT_BODY_IOV(req
);
2613 outdyn_v
= SMBD_SMB2_OUT_DYN_IOV(req
);
2615 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
2616 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
2618 outbody_v
->iov_base
= (void *)body
.data
;
2619 outbody_v
->iov_len
= body
.length
;
2622 outdyn_v
->iov_base
= (void *)dyn
->data
;
2623 outdyn_v
->iov_len
= dyn
->length
;
2625 outdyn_v
->iov_base
= NULL
;
2626 outdyn_v
->iov_len
= 0;
2629 /* see if we need to recalculate the offset to the next response */
2630 if (next_command_ofs
> 0) {
2631 next_command_ofs
= SMB2_HDR_BODY
;
2632 next_command_ofs
+= SMBD_SMB2_OUT_BODY_LEN(req
);
2633 next_command_ofs
+= SMBD_SMB2_OUT_DYN_LEN(req
);
2636 if ((next_command_ofs
% 8) != 0) {
2637 size_t pad_size
= 8 - (next_command_ofs
% 8);
2638 if (SMBD_SMB2_OUT_DYN_LEN(req
) == 0) {
2640 * if the dyn buffer is empty
2641 * we can use it to add padding
2645 pad
= talloc_zero_array(req
,
2648 return smbd_smb2_request_error(req
,
2649 NT_STATUS_NO_MEMORY
);
2652 outdyn_v
->iov_base
= (void *)pad
;
2653 outdyn_v
->iov_len
= pad_size
;
2656 * For now we copy the dynamic buffer
2657 * and add the padding to the new buffer
2664 old_size
= SMBD_SMB2_OUT_DYN_LEN(req
);
2665 old_dyn
= SMBD_SMB2_OUT_DYN_PTR(req
);
2667 new_size
= old_size
+ pad_size
;
2668 new_dyn
= talloc_zero_array(req
,
2670 if (new_dyn
== NULL
) {
2671 return smbd_smb2_request_error(req
,
2672 NT_STATUS_NO_MEMORY
);
2675 memcpy(new_dyn
, old_dyn
, old_size
);
2676 memset(new_dyn
+ old_size
, 0, pad_size
);
2678 outdyn_v
->iov_base
= (void *)new_dyn
;
2679 outdyn_v
->iov_len
= new_size
;
2681 next_command_ofs
+= pad_size
;
2684 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
2686 return smbd_smb2_request_reply(req
);
2689 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
2692 const char *location
)
2694 struct smbXsrv_connection
*xconn
= req
->xconn
;
2697 uint8_t *outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
2698 size_t unread_bytes
= smbd_smb2_unread_bytes(req
);
2700 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2701 req
->current_idx
, nt_errstr(status
), info
? " +info" : "",
2705 /* Recvfile error. Drain incoming socket. */
2709 ret
= drain_socket(xconn
->transport
.sock
, unread_bytes
);
2710 if (ret
!= unread_bytes
) {
2714 error
= NT_STATUS_IO_DEVICE_ERROR
;
2716 error
= map_nt_error_from_unix_common(errno
);
2719 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2720 "ret[%u] errno[%d] => %s\n",
2721 (unsigned)unread_bytes
,
2722 (unsigned)ret
, errno
, nt_errstr(error
)));
2727 body
.data
= outhdr
+ SMB2_HDR_BODY
;
2729 SSVAL(body
.data
, 0, 9);
2732 SIVAL(body
.data
, 0x04, info
->length
);
2734 /* Allocated size of req->out.vector[i].iov_base
2735 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2736 * 1 byte without having to do an alloc.
2739 info
->data
= ((uint8_t *)outhdr
) +
2740 OUTVEC_ALLOC_SIZE
- 1;
2742 SCVAL(info
->data
, 0, 0);
2746 * Note: Even if there is an error, continue to process the request.
2750 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
2754 struct smbd_smb2_send_break_state
{
2755 struct smbd_smb2_send_queue queue_entry
;
2756 uint8_t nbt_hdr
[NBT_HDR_SIZE
];
2757 uint8_t tf
[SMB2_TF_HDR_SIZE
];
2758 uint8_t hdr
[SMB2_HDR_BODY
];
2759 struct iovec vector
[1+SMBD_SMB2_NUM_IOV_PER_REQ
];
2763 static NTSTATUS
smbd_smb2_send_break(struct smbXsrv_connection
*xconn
,
2764 struct smbXsrv_session
*session
,
2765 struct smbXsrv_tcon
*tcon
,
2766 const uint8_t *body
,
2769 struct smbd_smb2_send_break_state
*state
;
2770 bool do_encryption
= false;
2771 uint64_t session_wire_id
= 0;
2772 uint64_t nonce_high
= 0;
2773 uint64_t nonce_low
= 0;
2778 if (session
!= NULL
) {
2779 session_wire_id
= session
->global
->session_wire_id
;
2780 do_encryption
= session
->global
->encryption_required
;
2781 if (tcon
->global
->encryption_required
) {
2782 do_encryption
= true;
2786 statelen
= offsetof(struct smbd_smb2_send_break_state
, body
) +
2789 state
= talloc_zero_size(xconn
, statelen
);
2790 if (state
== NULL
) {
2791 return NT_STATUS_NO_MEMORY
;
2793 talloc_set_name_const(state
, "struct smbd_smb2_send_break_state");
2795 if (do_encryption
) {
2796 nonce_high
= session
->nonce_high
;
2797 nonce_low
= session
->nonce_low
;
2799 session
->nonce_low
+= 1;
2800 if (session
->nonce_low
== 0) {
2801 session
->nonce_low
+= 1;
2802 session
->nonce_high
+= 1;
2806 SIVAL(state
->tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
2807 SBVAL(state
->tf
, SMB2_TF_NONCE
+0, nonce_low
);
2808 SBVAL(state
->tf
, SMB2_TF_NONCE
+8, nonce_high
);
2809 SBVAL(state
->tf
, SMB2_TF_SESSION_ID
, session_wire_id
);
2811 SIVAL(state
->hdr
, 0, SMB2_MAGIC
);
2812 SSVAL(state
->hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
2813 SSVAL(state
->hdr
, SMB2_HDR_EPOCH
, 0);
2814 SIVAL(state
->hdr
, SMB2_HDR_STATUS
, 0);
2815 SSVAL(state
->hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
2816 SSVAL(state
->hdr
, SMB2_HDR_CREDIT
, 0);
2817 SIVAL(state
->hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
2818 SIVAL(state
->hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
2819 SBVAL(state
->hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
2820 SIVAL(state
->hdr
, SMB2_HDR_PID
, 0);
2821 SIVAL(state
->hdr
, SMB2_HDR_TID
, 0);
2822 SBVAL(state
->hdr
, SMB2_HDR_SESSION_ID
, 0);
2823 memset(state
->hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
2825 state
->vector
[0] = (struct iovec
) {
2826 .iov_base
= state
->nbt_hdr
,
2827 .iov_len
= sizeof(state
->nbt_hdr
)
2830 if (do_encryption
) {
2831 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
] = (struct iovec
) {
2832 .iov_base
= state
->tf
,
2833 .iov_len
= sizeof(state
->tf
)
2836 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
] = (struct iovec
) {
2842 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
] = (struct iovec
) {
2843 .iov_base
= state
->hdr
,
2844 .iov_len
= sizeof(state
->hdr
)
2847 memcpy(state
->body
, body
, body_len
);
2849 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
] = (struct iovec
) {
2850 .iov_base
= state
->body
,
2851 .iov_len
= body_len
/* no sizeof(state->body) .. :-) */
2855 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
2858 ok
= smb2_setup_nbt_length(state
->vector
,
2859 1 + SMBD_SMB2_NUM_IOV_PER_REQ
);
2861 return NT_STATUS_INVALID_PARAMETER_MIX
;
2864 if (do_encryption
) {
2865 DATA_BLOB encryption_key
= session
->global
->encryption_key
;
2867 status
= smb2_signing_encrypt_pdu(encryption_key
,
2868 xconn
->smb2
.server
.cipher
,
2869 &state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
],
2870 SMBD_SMB2_NUM_IOV_PER_REQ
);
2871 if (!NT_STATUS_IS_OK(status
)) {
2876 state
->queue_entry
.mem_ctx
= state
;
2877 state
->queue_entry
.vector
= state
->vector
;
2878 state
->queue_entry
.count
= ARRAY_SIZE(state
->vector
);
2879 DLIST_ADD_END(xconn
->smb2
.send_queue
, &state
->queue_entry
, NULL
);
2880 xconn
->smb2
.send_queue_len
++;
2882 status
= smbd_smb2_flush_send_queue(xconn
);
2883 if (!NT_STATUS_IS_OK(status
)) {
2887 return NT_STATUS_OK
;
2890 NTSTATUS
smbd_smb2_send_oplock_break(struct smbXsrv_connection
*xconn
,
2891 struct smbXsrv_session
*session
,
2892 struct smbXsrv_tcon
*tcon
,
2893 struct smbXsrv_open
*op
,
2894 uint8_t oplock_level
)
2898 SSVAL(body
, 0x00, sizeof(body
));
2899 SCVAL(body
, 0x02, oplock_level
);
2900 SCVAL(body
, 0x03, 0); /* reserved */
2901 SIVAL(body
, 0x04, 0); /* reserved */
2902 SBVAL(body
, 0x08, op
->global
->open_persistent_id
);
2903 SBVAL(body
, 0x10, op
->global
->open_volatile_id
);
2905 return smbd_smb2_send_break(xconn
, session
, tcon
, body
, sizeof(body
));
2908 NTSTATUS
smbd_smb2_send_lease_break(struct smbXsrv_connection
*xconn
,
2910 uint32_t lease_flags
,
2911 struct smb2_lease_key
*lease_key
,
2912 uint32_t current_lease_state
,
2913 uint32_t new_lease_state
)
2917 SSVAL(body
, 0x00, sizeof(body
));
2918 SSVAL(body
, 0x02, new_epoch
);
2919 SIVAL(body
, 0x04, lease_flags
);
2920 SBVAL(body
, 0x08, lease_key
->data
[0]);
2921 SBVAL(body
, 0x10, lease_key
->data
[1]);
2922 SIVAL(body
, 0x18, current_lease_state
);
2923 SIVAL(body
, 0x1c, new_lease_state
);
2924 SIVAL(body
, 0x20, 0); /* BreakReason, MUST be 0 */
2925 SIVAL(body
, 0x24, 0); /* AccessMaskHint, MUST be 0 */
2926 SIVAL(body
, 0x28, 0); /* ShareMaskHint, MUST be 0 */
2928 return smbd_smb2_send_break(xconn
, NULL
, NULL
, body
, sizeof(body
));
2931 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state
*state
)
2935 uint64_t file_id_persistent
;
2936 uint64_t file_id_volatile
;
2937 struct smbXsrv_open
*op
= NULL
;
2938 struct files_struct
*fsp
= NULL
;
2939 const uint8_t *body
= NULL
;
2942 * This is only called with a pktbuf
2943 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
2947 if (IVAL(state
->pktbuf
, 0) == SMB2_TF_MAGIC
) {
2948 /* Transform header. Cannot recvfile. */
2951 if (IVAL(state
->pktbuf
, 0) != SMB2_MAGIC
) {
2952 /* Not SMB2. Normal error path will cope. */
2955 if (SVAL(state
->pktbuf
, 4) != SMB2_HDR_BODY
) {
2956 /* Not SMB2. Normal error path will cope. */
2959 if (SVAL(state
->pktbuf
, SMB2_HDR_OPCODE
) != SMB2_OP_WRITE
) {
2960 /* Needs to be a WRITE. */
2963 if (IVAL(state
->pktbuf
, SMB2_HDR_NEXT_COMMAND
) != 0) {
2964 /* Chained. Cannot recvfile. */
2967 flags
= IVAL(state
->pktbuf
, SMB2_HDR_FLAGS
);
2968 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
2969 /* Chained. Cannot recvfile. */
2972 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
2973 /* Signed. Cannot recvfile. */
2977 body
= &state
->pktbuf
[SMB2_HDR_BODY
];
2979 file_id_persistent
= BVAL(body
, 0x10);
2980 file_id_volatile
= BVAL(body
, 0x18);
2982 status
= smb2srv_open_lookup(state
->req
->xconn
,
2987 if (!NT_STATUS_IS_OK(status
)) {
2995 if (fsp
->conn
== NULL
) {
2999 if (IS_IPC(fsp
->conn
)) {
3002 if (IS_PRINT(fsp
->conn
)) {
3006 DEBUG(10,("Doing recvfile write len = %u\n",
3007 (unsigned int)(state
->pktfull
- state
->pktlen
)));
3012 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbXsrv_connection
*xconn
)
3014 struct smbd_server_connection
*sconn
= xconn
->client
->sconn
;
3015 struct smbd_smb2_request_read_state
*state
= &xconn
->smb2
.request_read_state
;
3016 size_t max_send_queue_len
;
3017 size_t cur_send_queue_len
;
3019 if (!NT_STATUS_IS_OK(xconn
->transport
.status
)) {
3021 * we're not supposed to do any io
3023 return NT_STATUS_OK
;
3026 if (state
->req
!= NULL
) {
3028 * if there is already a tstream_readv_pdu
3029 * pending, we are done.
3031 return NT_STATUS_OK
;
3034 max_send_queue_len
= MAX(1, xconn
->smb2
.credits
.max
/16);
3035 cur_send_queue_len
= xconn
->smb2
.send_queue_len
;
3037 if (cur_send_queue_len
> max_send_queue_len
) {
3039 * if we have a lot of requests to send,
3040 * we wait until they are on the wire until we
3041 * ask for the next request.
3043 return NT_STATUS_OK
;
3046 /* ask for the next request */
3047 ZERO_STRUCTP(state
);
3048 state
->req
= smbd_smb2_request_allocate(xconn
);
3049 if (state
->req
== NULL
) {
3050 return NT_STATUS_NO_MEMORY
;
3052 state
->req
->sconn
= sconn
;
3053 state
->req
->xconn
= xconn
;
3054 state
->min_recv_size
= lp_min_receive_file_size();
3056 TEVENT_FD_READABLE(xconn
->transport
.fde
);
3058 return NT_STATUS_OK
;
3061 void smbd_smb2_first_negprot(struct smbXsrv_connection
*xconn
,
3062 const uint8_t *inpdu
, size_t size
)
3064 struct smbd_server_connection
*sconn
= xconn
->client
->sconn
;
3066 struct smbd_smb2_request
*req
= NULL
;
3068 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3069 (unsigned int)size
));
3071 status
= smbd_initialize_smb2(xconn
);
3072 if (!NT_STATUS_IS_OK(status
)) {
3073 smbd_server_connection_terminate(xconn
, nt_errstr(status
));
3077 status
= smbd_smb2_request_create(xconn
, inpdu
, size
, &req
);
3078 if (!NT_STATUS_IS_OK(status
)) {
3079 smbd_server_connection_terminate(xconn
, nt_errstr(status
));
3083 status
= smbd_smb2_request_validate(req
);
3084 if (!NT_STATUS_IS_OK(status
)) {
3085 smbd_server_connection_terminate(xconn
, nt_errstr(status
));
3089 status
= smbd_smb2_request_setup_out(req
);
3090 if (!NT_STATUS_IS_OK(status
)) {
3091 smbd_server_connection_terminate(xconn
, nt_errstr(status
));
3097 * this was already counted at the SMB1 layer =>
3098 * smbd_smb2_request_dispatch() should not count it twice.
3100 if (profile_p
->values
.request_stats
.count
> 0) {
3101 profile_p
->values
.request_stats
.count
--;
3104 status
= smbd_smb2_request_dispatch(req
);
3105 if (!NT_STATUS_IS_OK(status
)) {
3106 smbd_server_connection_terminate(xconn
, nt_errstr(status
));
3110 status
= smbd_smb2_request_next_incoming(xconn
);
3111 if (!NT_STATUS_IS_OK(status
)) {
3112 smbd_server_connection_terminate(xconn
, nt_errstr(status
));
3116 sconn
->num_requests
++;
3119 static int socket_error_from_errno(int ret
,
3133 if (sys_errno
== 0) {
3137 if (sys_errno
== EINTR
) {
3142 if (sys_errno
== EINPROGRESS
) {
3147 if (sys_errno
== EAGAIN
) {
3152 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3153 if (sys_errno
== ENOMEM
) {
3159 #if EWOULDBLOCK != EAGAIN
3160 if (sys_errno
== EWOULDBLOCK
) {
3170 static NTSTATUS
smbd_smb2_flush_send_queue(struct smbXsrv_connection
*xconn
)
3176 if (xconn
->smb2
.send_queue
== NULL
) {
3177 TEVENT_FD_NOT_WRITEABLE(xconn
->transport
.fde
);
3178 return NT_STATUS_OK
;
3181 while (xconn
->smb2
.send_queue
!= NULL
) {
3182 struct smbd_smb2_send_queue
*e
= xconn
->smb2
.send_queue
;
3185 if (e
->sendfile_header
!= NULL
) {
3186 NTSTATUS status
= NT_STATUS_INTERNAL_ERROR
;
3191 for (i
=0; i
< e
->count
; i
++) {
3192 size
+= e
->vector
[i
].iov_len
;
3195 if (size
<= e
->sendfile_header
->length
) {
3196 buf
= e
->sendfile_header
->data
;
3198 buf
= talloc_array(e
->mem_ctx
, uint8_t, size
);
3200 return NT_STATUS_NO_MEMORY
;
3205 for (i
=0; i
< e
->count
; i
++) {
3207 e
->vector
[i
].iov_base
,
3208 e
->vector
[i
].iov_len
);
3209 size
+= e
->vector
[i
].iov_len
;
3212 e
->sendfile_header
->data
= buf
;
3213 e
->sendfile_header
->length
= size
;
3214 e
->sendfile_status
= &status
;
3217 xconn
->smb2
.send_queue_len
--;
3218 DLIST_REMOVE(xconn
->smb2
.send_queue
, e
);
3220 * This triggers the sendfile path via
3223 talloc_free(e
->mem_ctx
);
3225 if (!NT_STATUS_IS_OK(status
)) {
3231 ret
= writev(xconn
->transport
.sock
, e
->vector
, e
->count
);
3233 /* propagate end of file */
3234 return NT_STATUS_INTERNAL_ERROR
;
3236 err
= socket_error_from_errno(ret
, errno
, &retry
);
3239 TEVENT_FD_WRITEABLE(xconn
->transport
.fde
);
3240 return NT_STATUS_OK
;
3243 return map_nt_error_from_unix_common(err
);
3246 ok
= iov_advance(&e
->vector
, &e
->count
, ret
);
3248 return NT_STATUS_INTERNAL_ERROR
;
3252 /* we have more to write */
3253 TEVENT_FD_WRITEABLE(xconn
->transport
.fde
);
3254 return NT_STATUS_OK
;
3257 xconn
->smb2
.send_queue_len
--;
3258 DLIST_REMOVE(xconn
->smb2
.send_queue
, e
);
3259 talloc_free(e
->mem_ctx
);
3262 return NT_STATUS_OK
;
3265 static NTSTATUS
smbd_smb2_io_handler(struct smbXsrv_connection
*xconn
,
3268 struct smbd_server_connection
*sconn
= xconn
->client
->sconn
;
3269 struct smbd_smb2_request_read_state
*state
= &xconn
->smb2
.request_read_state
;
3270 struct smbd_smb2_request
*req
= NULL
;
3271 size_t min_recvfile_size
= UINT32_MAX
;
3278 if (!NT_STATUS_IS_OK(xconn
->transport
.status
)) {
3280 * we're not supposed to do any io
3282 TEVENT_FD_NOT_READABLE(xconn
->transport
.fde
);
3283 TEVENT_FD_NOT_WRITEABLE(xconn
->transport
.fde
);
3284 return NT_STATUS_OK
;
3287 if (fde_flags
& TEVENT_FD_WRITE
) {
3288 status
= smbd_smb2_flush_send_queue(xconn
);
3289 if (!NT_STATUS_IS_OK(status
)) {
3294 if (!(fde_flags
& TEVENT_FD_READ
)) {
3295 return NT_STATUS_OK
;
3298 if (state
->req
== NULL
) {
3299 TEVENT_FD_NOT_READABLE(xconn
->transport
.fde
);
3300 return NT_STATUS_OK
;
3304 if (!state
->hdr
.done
) {
3305 state
->hdr
.done
= true;
3307 state
->vector
.iov_base
= (void *)state
->hdr
.nbt
;
3308 state
->vector
.iov_len
= NBT_HDR_SIZE
;
3311 ret
= readv(xconn
->transport
.sock
, &state
->vector
, 1);
3313 /* propagate end of file */
3314 return NT_STATUS_END_OF_FILE
;
3316 err
= socket_error_from_errno(ret
, errno
, &retry
);
3319 TEVENT_FD_READABLE(xconn
->transport
.fde
);
3320 return NT_STATUS_OK
;
3323 return map_nt_error_from_unix_common(err
);
3326 if (ret
< state
->vector
.iov_len
) {
3328 base
= (uint8_t *)state
->vector
.iov_base
;
3330 state
->vector
.iov_base
= (void *)base
;
3331 state
->vector
.iov_len
-= ret
;
3332 /* we have more to read */
3333 TEVENT_FD_READABLE(xconn
->transport
.fde
);
3334 return NT_STATUS_OK
;
3337 if (state
->pktlen
> 0) {
3338 if (state
->doing_receivefile
&& !is_smb2_recvfile_write(state
)) {
3340 * Not a possible receivefile write.
3341 * Read the rest of the data.
3343 state
->doing_receivefile
= false;
3345 state
->pktbuf
= talloc_realloc(state
->req
,
3349 if (state
->pktbuf
== NULL
) {
3350 return NT_STATUS_NO_MEMORY
;
3353 state
->vector
.iov_base
= (void *)(state
->pktbuf
+
3355 state
->vector
.iov_len
= (state
->pktfull
-
3358 state
->pktlen
= state
->pktfull
;
3363 * Either this is a receivefile write so we've
3364 * done a short read, or if not we have all the data.
3370 * Now we analyze the NBT header
3372 if (state
->hdr
.nbt
[0] != 0x00) {
3373 state
->min_recv_size
= 0;
3375 state
->pktfull
= smb2_len(state
->hdr
.nbt
);
3376 if (state
->pktfull
== 0) {
3380 if (state
->min_recv_size
!= 0) {
3381 min_recvfile_size
= SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
;
3382 min_recvfile_size
+= state
->min_recv_size
;
3385 if (state
->pktfull
> min_recvfile_size
) {
3387 * Might be a receivefile write. Read the SMB2 HEADER +
3388 * SMB2_WRITE header first. Set 'doing_receivefile'
3389 * as we're *attempting* receivefile write. If this
3390 * turns out not to be a SMB2_WRITE request or otherwise
3391 * not suitable then we'll just read the rest of the data
3392 * the next time this function is called.
3394 state
->pktlen
= SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
;
3395 state
->doing_receivefile
= true;
3397 state
->pktlen
= state
->pktfull
;
3400 state
->pktbuf
= talloc_array(state
->req
, uint8_t, state
->pktlen
);
3401 if (state
->pktbuf
== NULL
) {
3402 return NT_STATUS_NO_MEMORY
;
3405 state
->vector
.iov_base
= (void *)state
->pktbuf
;
3406 state
->vector
.iov_len
= state
->pktlen
;
3412 if (state
->hdr
.nbt
[0] != 0x00) {
3413 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3414 state
->hdr
.nbt
[0]));
3417 ZERO_STRUCTP(state
);
3419 state
->min_recv_size
= lp_min_receive_file_size();
3427 req
->request_time
= timeval_current();
3428 now
= timeval_to_nttime(&req
->request_time
);
3430 status
= smbd_smb2_inbuf_parse_compound(xconn
,
3436 &req
->in
.vector_count
);
3437 if (!NT_STATUS_IS_OK(status
)) {
3441 if (state
->doing_receivefile
) {
3442 req
->smb1req
= talloc_zero(req
, struct smb_request
);
3443 if (req
->smb1req
== NULL
) {
3444 return NT_STATUS_NO_MEMORY
;
3446 req
->smb1req
->unread_bytes
= state
->pktfull
- state
->pktlen
;
3449 ZERO_STRUCTP(state
);
3451 req
->current_idx
= 1;
3453 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3454 req
->current_idx
, req
->in
.vector_count
));
3456 status
= smbd_smb2_request_validate(req
);
3457 if (!NT_STATUS_IS_OK(status
)) {
3461 status
= smbd_smb2_request_setup_out(req
);
3462 if (!NT_STATUS_IS_OK(status
)) {
3466 status
= smbd_smb2_request_dispatch(req
);
3467 if (!NT_STATUS_IS_OK(status
)) {
3471 sconn
->num_requests
++;
3473 /* The timeout_processing function isn't run nearly
3474 often enough to implement 'max log size' without
3475 overrunning the size of the file by many megabytes.
3476 This is especially true if we are running at debug
3477 level 10. Checking every 50 SMB2s is a nice
3478 tradeoff of performance vs log file size overrun. */
3480 if ((sconn
->num_requests
% 50) == 0 &&
3481 need_to_check_log_size()) {
3482 change_to_root_user();
3486 status
= smbd_smb2_request_next_incoming(xconn
);
3487 if (!NT_STATUS_IS_OK(status
)) {
3491 return NT_STATUS_OK
;
3494 static void smbd_smb2_connection_handler(struct tevent_context
*ev
,
3495 struct tevent_fd
*fde
,
3499 struct smbXsrv_connection
*xconn
=
3500 talloc_get_type_abort(private_data
,
3501 struct smbXsrv_connection
);
3504 status
= smbd_smb2_io_handler(xconn
, flags
);
3505 if (!NT_STATUS_IS_OK(status
)) {
3506 smbd_server_connection_terminate(xconn
, nt_errstr(status
));