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_io_handler(struct smbd_server_connection
*sconn
,
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
),
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 smbd_server_connection
*sconn
)
204 TALLOC_FREE(sconn
->smb1
.fde
);
206 sconn
->smb2
.send_queue
= NULL
;
208 sconn
->smb2
.seqnum_low
= 0;
209 sconn
->smb2
.seqnum_range
= 1;
210 sconn
->smb2
.credits_granted
= 1;
211 sconn
->smb2
.max_credits
= lp_smb2_max_credits();
212 sconn
->smb2
.credits_bitmap
= bitmap_talloc(sconn
,
213 sconn
->smb2
.max_credits
);
214 if (sconn
->smb2
.credits_bitmap
== NULL
) {
215 return NT_STATUS_NO_MEMORY
;
218 sconn
->smb2
.fde
= tevent_add_fd(sconn
->ev_ctx
,
222 smbd_smb2_connection_handler
,
224 if (sconn
->smb2
.fde
== NULL
) {
225 return NT_STATUS_NO_MEMORY
;
228 /* Ensure child is set to non-blocking mode */
229 set_blocking(sconn
->sock
, false);
233 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
234 #define _smb2_setlen(_buf,len) do { \
235 uint8_t *buf = (uint8_t *)_buf; \
237 buf[1] = ((len)&0xFF0000)>>16; \
238 buf[2] = ((len)&0xFF00)>>8; \
239 buf[3] = (len)&0xFF; \
242 static void smb2_setup_nbt_length(struct iovec
*vector
, int count
)
247 for (i
=1; i
< count
; i
++) {
248 len
+= vector
[i
].iov_len
;
251 _smb2_setlen(vector
[0].iov_base
, len
);
254 static int smbd_smb2_request_destructor(struct smbd_smb2_request
*req
)
256 if (req
->first_key
.length
> 0) {
257 data_blob_clear_free(&req
->first_key
);
259 if (req
->last_key
.length
> 0) {
260 data_blob_clear_free(&req
->last_key
);
265 static struct smbd_smb2_request
*smbd_smb2_request_allocate(TALLOC_CTX
*mem_ctx
)
267 TALLOC_CTX
*mem_pool
;
268 struct smbd_smb2_request
*req
;
271 /* Enable this to find subtle valgrind errors. */
272 mem_pool
= talloc_init("smbd_smb2_request_allocate");
274 mem_pool
= talloc_tos();
276 if (mem_pool
== NULL
) {
280 req
= talloc_zero(mem_pool
, struct smbd_smb2_request
);
282 talloc_free(mem_pool
);
285 talloc_reparent(mem_pool
, mem_ctx
, req
);
287 TALLOC_FREE(mem_pool
);
290 req
->last_session_id
= UINT64_MAX
;
291 req
->last_tid
= UINT32_MAX
;
293 talloc_set_destructor(req
, smbd_smb2_request_destructor
);
298 static NTSTATUS
smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection
*conn
,
302 struct smbd_smb2_request
*req
,
306 TALLOC_CTX
*mem_ctx
= req
;
310 uint8_t *first_hdr
= buf
;
311 size_t verified_buflen
= 0;
316 * Note: index '0' is reserved for the transport protocol
318 iov
= req
->in
._vector
;
320 while (taken
< buflen
) {
321 size_t len
= buflen
- taken
;
322 uint8_t *hdr
= first_hdr
+ taken
;
325 size_t next_command_ofs
;
327 uint8_t *body
= NULL
;
331 if (verified_buflen
> taken
) {
332 len
= verified_buflen
- taken
;
339 DEBUG(10, ("%d bytes left, expected at least %d\n",
343 if (IVAL(hdr
, 0) == SMB2_TF_MAGIC
) {
344 struct smbXsrv_session
*s
= NULL
;
346 struct iovec tf_iov
[2];
350 if (conn
->protocol
< PROTOCOL_SMB2_24
) {
351 DEBUG(10, ("Got SMB2_TRANSFORM header, "
352 "but dialect[0x%04X] is used\n",
353 conn
->smb2
.server
.dialect
));
357 if (!(conn
->smb2
.server
.capabilities
& SMB2_CAP_ENCRYPTION
)) {
358 DEBUG(10, ("Got SMB2_TRANSFORM header, "
359 "but not negotiated "
360 "client[0x%08X] server[0x%08X]\n",
361 conn
->smb2
.client
.capabilities
,
362 conn
->smb2
.server
.capabilities
));
366 if (len
< SMB2_TF_HDR_SIZE
) {
367 DEBUG(1, ("%d bytes left, expected at least %d\n",
368 (int)len
, SMB2_TF_HDR_SIZE
));
372 tf_len
= SMB2_TF_HDR_SIZE
;
375 hdr
= first_hdr
+ taken
;
376 enc_len
= IVAL(tf
, SMB2_TF_MSG_SIZE
);
377 uid
= BVAL(tf
, SMB2_TF_SESSION_ID
);
379 if (len
< SMB2_TF_HDR_SIZE
+ enc_len
) {
380 DEBUG(1, ("%d bytes left, expected at least %d\n",
382 (int)(SMB2_TF_HDR_SIZE
+ enc_len
)));
386 status
= smb2srv_session_lookup(conn
, uid
, now
, &s
);
388 DEBUG(1, ("invalid session[%llu] in "
389 "SMB2_TRANSFORM header\n",
390 (unsigned long long)uid
));
392 return NT_STATUS_USER_SESSION_DELETED
;
395 tf_iov
[0].iov_base
= (void *)tf
;
396 tf_iov
[0].iov_len
= tf_len
;
397 tf_iov
[1].iov_base
= (void *)hdr
;
398 tf_iov
[1].iov_len
= enc_len
;
400 status
= smb2_signing_decrypt_pdu(s
->global
->decryption_key
,
403 if (!NT_STATUS_IS_OK(status
)) {
408 verified_buflen
= taken
+ enc_len
;
413 * We need the header plus the body length field
416 if (len
< SMB2_HDR_BODY
+ 2) {
417 DEBUG(10, ("%d bytes left, expected at least %d\n",
418 (int)len
, SMB2_HDR_BODY
));
421 if (IVAL(hdr
, 0) != SMB2_MAGIC
) {
422 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
426 if (SVAL(hdr
, 4) != SMB2_HDR_BODY
) {
427 DEBUG(10, ("Got HDR len %d, expected %d\n",
428 SVAL(hdr
, 4), SMB2_HDR_BODY
));
433 next_command_ofs
= IVAL(hdr
, SMB2_HDR_NEXT_COMMAND
);
434 body_size
= SVAL(hdr
, SMB2_HDR_BODY
);
436 if (next_command_ofs
!= 0) {
437 if (next_command_ofs
< (SMB2_HDR_BODY
+ 2)) {
440 if (next_command_ofs
> full_size
) {
443 full_size
= next_command_ofs
;
450 if (body_size
> (full_size
- SMB2_HDR_BODY
)) {
452 * let the caller handle the error
454 body_size
= full_size
- SMB2_HDR_BODY
;
456 body
= hdr
+ SMB2_HDR_BODY
;
457 dyn
= body
+ body_size
;
458 dyn_size
= full_size
- (SMB2_HDR_BODY
+ body_size
);
460 if (num_iov
>= ARRAY_SIZE(req
->in
._vector
)) {
461 struct iovec
*iov_tmp
= NULL
;
462 struct iovec
*iov_alloc
= NULL
;
464 if (iov
!= req
->in
._vector
) {
468 iov_tmp
= talloc_realloc(mem_ctx
, iov_alloc
,
471 SMBD_SMB2_NUM_IOV_PER_REQ
);
472 if (iov_tmp
== NULL
) {
473 TALLOC_FREE(iov_alloc
);
474 return NT_STATUS_NO_MEMORY
;
477 if (iov_alloc
== NULL
) {
480 sizeof(req
->in
._vector
));
486 num_iov
+= SMBD_SMB2_NUM_IOV_PER_REQ
;
488 cur
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= tf
;
489 cur
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= tf_len
;
490 cur
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
491 cur
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
492 cur
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
493 cur
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= body_size
;
494 cur
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
495 cur
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= dyn_size
;
505 if (iov
!= req
->in
._vector
) {
508 return NT_STATUS_INVALID_PARAMETER
;
511 static NTSTATUS
smbd_smb2_request_create(struct smbd_server_connection
*sconn
,
512 uint8_t *inbuf
, size_t size
,
513 struct smbd_smb2_request
**_req
)
515 struct smbd_smb2_request
*req
;
516 uint32_t protocol_version
;
517 const uint8_t *inhdr
= NULL
;
519 uint32_t next_command_ofs
;
523 if (size
< (4 + SMB2_HDR_BODY
+ 2)) {
524 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size
));
525 return NT_STATUS_INVALID_PARAMETER
;
530 protocol_version
= IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
);
531 if (protocol_version
!= SMB2_MAGIC
) {
532 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
534 return NT_STATUS_INVALID_PARAMETER
;
537 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
538 if (cmd
!= SMB2_OP_NEGPROT
) {
539 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
541 return NT_STATUS_INVALID_PARAMETER
;
544 next_command_ofs
= IVAL(inhdr
, SMB2_HDR_NEXT_COMMAND
);
545 if (next_command_ofs
!= 0) {
546 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
548 return NT_STATUS_INVALID_PARAMETER
;
551 req
= smbd_smb2_request_allocate(sconn
);
553 return NT_STATUS_NO_MEMORY
;
557 talloc_steal(req
, inbuf
);
559 req
->request_time
= timeval_current();
560 now
= timeval_to_nttime(&req
->request_time
);
562 status
= smbd_smb2_inbuf_parse_compound(sconn
->conn
,
564 inbuf
+ NBT_HDR_SIZE
,
566 req
, &req
->in
.vector
,
567 &req
->in
.vector_count
);
568 if (!NT_STATUS_IS_OK(status
)) {
573 req
->current_idx
= 1;
579 static bool smb2_validate_sequence_number(struct smbd_server_connection
*sconn
,
580 uint64_t message_id
, uint64_t seq_id
)
582 struct bitmap
*credits_bm
= sconn
->smb2
.credits_bitmap
;
585 if (seq_id
< sconn
->smb2
.seqnum_low
) {
586 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
587 "%llu (sequence id %llu) "
588 "(granted = %u, low = %llu, range = %u)\n",
589 (unsigned long long)message_id
,
590 (unsigned long long)seq_id
,
591 (unsigned int)sconn
->smb2
.credits_granted
,
592 (unsigned long long)sconn
->smb2
.seqnum_low
,
593 (unsigned int)sconn
->smb2
.seqnum_range
));
597 if (seq_id
>= sconn
->smb2
.seqnum_low
+ sconn
->smb2
.seqnum_range
) {
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)sconn
->smb2
.credits_granted
,
604 (unsigned long long)sconn
->smb2
.seqnum_low
,
605 (unsigned int)sconn
->smb2
.seqnum_range
));
609 offset
= seq_id
% sconn
->smb2
.max_credits
;
611 if (bitmap_query(credits_bm
, offset
)) {
612 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
613 "%llu (sequence id %llu) "
614 "(granted = %u, low = %llu, range = %u) "
616 (unsigned long long)message_id
,
617 (unsigned long long)seq_id
,
618 (unsigned int)sconn
->smb2
.credits_granted
,
619 (unsigned long long)sconn
->smb2
.seqnum_low
,
620 (unsigned int)sconn
->smb2
.seqnum_range
,
625 /* Mark the message_ids as seen in the bitmap. */
626 bitmap_set(credits_bm
, offset
);
628 if (seq_id
!= sconn
->smb2
.seqnum_low
) {
633 * Move the window forward by all the message_id's
636 while (bitmap_query(credits_bm
, offset
)) {
637 DEBUG(10,("smb2_validate_sequence_number: clearing "
638 "id %llu (position %u) from bitmap\n",
639 (unsigned long long)(sconn
->smb2
.seqnum_low
),
641 bitmap_clear(credits_bm
, offset
);
643 sconn
->smb2
.seqnum_low
+= 1;
644 sconn
->smb2
.seqnum_range
-= 1;
645 offset
= sconn
->smb2
.seqnum_low
% sconn
->smb2
.max_credits
;
651 static bool smb2_validate_message_id(struct smbd_server_connection
*sconn
,
652 const uint8_t *inhdr
)
654 uint64_t message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
655 uint16_t opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
656 uint16_t credit_charge
= 1;
659 if (opcode
== SMB2_OP_CANCEL
) {
660 /* SMB2_CANCEL requests by definition resend messageids. */
664 if (sconn
->smb2
.supports_multicredit
) {
665 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
666 credit_charge
= MAX(credit_charge
, 1);
669 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
670 "credits_granted %llu, "
671 "seqnum low/range: %llu/%llu\n",
672 (unsigned long long) message_id
,
673 (unsigned long long) credit_charge
,
674 (unsigned long long) sconn
->smb2
.credits_granted
,
675 (unsigned long long) sconn
->smb2
.seqnum_low
,
676 (unsigned long long) sconn
->smb2
.seqnum_range
));
678 if (sconn
->smb2
.credits_granted
< credit_charge
) {
679 DEBUG(0, ("smb2_validate_message_id: client used more "
680 "credits than granted, mid %llu, charge %llu, "
681 "credits_granted %llu, "
682 "seqnum low/range: %llu/%llu\n",
683 (unsigned long long) message_id
,
684 (unsigned long long) credit_charge
,
685 (unsigned long long) sconn
->smb2
.credits_granted
,
686 (unsigned long long) sconn
->smb2
.seqnum_low
,
687 (unsigned long long) sconn
->smb2
.seqnum_range
));
692 * now check the message ids
694 * for multi-credit requests we need to check all current mid plus
695 * the implicit mids caused by the credit charge
696 * e.g. current mid = 15, charge 5 => mark 15-19 as used
699 for (i
= 0; i
<= (credit_charge
-1); i
++) {
700 uint64_t id
= message_id
+ i
;
703 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
704 (unsigned long long)message_id
,
706 (unsigned long long)id
));
708 ok
= smb2_validate_sequence_number(sconn
, message_id
, id
);
714 /* substract used credits */
715 sconn
->smb2
.credits_granted
-= credit_charge
;
720 static NTSTATUS
smbd_smb2_request_validate(struct smbd_smb2_request
*req
)
725 count
= req
->in
.vector_count
;
727 if (count
< 1 + SMBD_SMB2_NUM_IOV_PER_REQ
) {
728 /* It's not a SMB2 request */
729 return NT_STATUS_INVALID_PARAMETER
;
732 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
733 struct iovec
*hdr
= SMBD_SMB2_IDX_HDR_IOV(req
,in
,idx
);
734 struct iovec
*body
= SMBD_SMB2_IDX_BODY_IOV(req
,in
,idx
);
735 const uint8_t *inhdr
= NULL
;
737 if (hdr
->iov_len
!= SMB2_HDR_BODY
) {
738 return NT_STATUS_INVALID_PARAMETER
;
741 if (body
->iov_len
< 2) {
742 return NT_STATUS_INVALID_PARAMETER
;
745 inhdr
= (const uint8_t *)hdr
->iov_base
;
747 /* Check the SMB2 header */
748 if (IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
) != SMB2_MAGIC
) {
749 return NT_STATUS_INVALID_PARAMETER
;
752 if (!smb2_validate_message_id(req
->sconn
, inhdr
)) {
753 return NT_STATUS_INVALID_PARAMETER
;
760 static void smb2_set_operation_credit(struct smbd_server_connection
*sconn
,
761 const struct iovec
*in_vector
,
762 struct iovec
*out_vector
)
764 const uint8_t *inhdr
= (const uint8_t *)in_vector
->iov_base
;
765 uint8_t *outhdr
= (uint8_t *)out_vector
->iov_base
;
766 uint16_t credit_charge
= 1;
767 uint16_t credits_requested
;
771 uint16_t credits_granted
= 0;
772 uint64_t credits_possible
;
773 uint16_t current_max_credits
;
776 * first we grant only 1/16th of the max range.
778 * Windows also starts with the 1/16th and then grants
779 * more later. I was only able to trigger higher
780 * values, when using a very high credit charge.
782 * TODO: scale up depending on load, free memory
784 * Maybe also on the relationship between number
785 * of requests and the used sequence number.
786 * Which means we would grant more credits
787 * for client which use multi credit requests.
789 current_max_credits
= sconn
->smb2
.max_credits
/ 16;
790 current_max_credits
= MAX(current_max_credits
, 1);
792 if (sconn
->smb2
.supports_multicredit
) {
793 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
794 credit_charge
= MAX(credit_charge
, 1);
797 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
798 credits_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
799 out_flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
800 out_status
= NT_STATUS(IVAL(outhdr
, SMB2_HDR_STATUS
));
802 SMB_ASSERT(sconn
->smb2
.max_credits
>= sconn
->smb2
.credits_granted
);
804 if (sconn
->smb2
.max_credits
< credit_charge
) {
805 smbd_server_connection_terminate(sconn
,
806 "client error: credit charge > max credits\n");
810 if (out_flags
& SMB2_HDR_FLAG_ASYNC
) {
812 * In case we already send an async interim
813 * response, we should not grant
814 * credits on the final response.
817 } else if (credits_requested
> 0) {
818 uint16_t additional_max
= 0;
819 uint16_t additional_credits
= credits_requested
- 1;
822 case SMB2_OP_NEGPROT
:
824 case SMB2_OP_SESSSETUP
:
826 * Windows 2012 RC1 starts to grant
828 * with a successful session setup
830 if (NT_STATUS_IS_OK(out_status
)) {
836 * We match windows and only grant additional credits
843 additional_credits
= MIN(additional_credits
, additional_max
);
845 credits_granted
= credit_charge
+ additional_credits
;
846 } else if (sconn
->smb2
.credits_granted
== 0) {
848 * Make sure the client has always at least one credit
854 * sequence numbers should not wrap
856 * 1. calculate the possible credits until
857 * the sequence numbers start to wrap on 64-bit.
859 * 2. UINT64_MAX is used for Break Notifications.
861 * 2. truncate the possible credits to the maximum
862 * credits we want to grant to the client in total.
864 * 3. remove the range we'll already granted to the client
865 * this makes sure the client consumes the lowest sequence
866 * number, before we can grant additional credits.
868 credits_possible
= UINT64_MAX
- sconn
->smb2
.seqnum_low
;
869 if (credits_possible
> 0) {
870 /* remove UINT64_MAX */
871 credits_possible
-= 1;
873 credits_possible
= MIN(credits_possible
, current_max_credits
);
874 credits_possible
-= sconn
->smb2
.seqnum_range
;
876 credits_granted
= MIN(credits_granted
, credits_possible
);
878 SSVAL(outhdr
, SMB2_HDR_CREDIT
, credits_granted
);
879 sconn
->smb2
.credits_granted
+= credits_granted
;
880 sconn
->smb2
.seqnum_range
+= credits_granted
;
882 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
883 "granted %u, current possible/max %u/%u, "
884 "total granted/max/low/range %u/%u/%llu/%u\n",
885 (unsigned int)credits_requested
,
886 (unsigned int)credit_charge
,
887 (unsigned int)credits_granted
,
888 (unsigned int)credits_possible
,
889 (unsigned int)current_max_credits
,
890 (unsigned int)sconn
->smb2
.credits_granted
,
891 (unsigned int)sconn
->smb2
.max_credits
,
892 (unsigned long long)sconn
->smb2
.seqnum_low
,
893 (unsigned int)sconn
->smb2
.seqnum_range
));
896 static void smb2_calculate_credits(const struct smbd_smb2_request
*inreq
,
897 struct smbd_smb2_request
*outreq
)
900 uint16_t total_credits
= 0;
902 count
= outreq
->out
.vector_count
;
904 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
905 struct iovec
*inhdr_v
= SMBD_SMB2_IDX_HDR_IOV(inreq
,in
,idx
);
906 struct iovec
*outhdr_v
= SMBD_SMB2_IDX_HDR_IOV(outreq
,out
,idx
);
907 uint8_t *outhdr
= (uint8_t *)outhdr_v
->iov_base
;
909 smb2_set_operation_credit(outreq
->sconn
, inhdr_v
, outhdr_v
);
911 /* To match Windows, count up what we
913 total_credits
+= SVAL(outhdr
, SMB2_HDR_CREDIT
);
914 /* Set to zero in all but the last reply. */
915 if (idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
< count
) {
916 SSVAL(outhdr
, SMB2_HDR_CREDIT
, 0);
918 SSVAL(outhdr
, SMB2_HDR_CREDIT
, total_credits
);
923 DATA_BLOB
smbd_smb2_generate_outbody(struct smbd_smb2_request
*req
, size_t size
)
925 if (req
->current_idx
<= 1) {
926 if (size
<= sizeof(req
->out
._body
)) {
927 return data_blob_const(req
->out
._body
, size
);
931 return data_blob_talloc(req
, NULL
, size
);
934 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
)
937 struct iovec
*vector
;
941 count
= req
->in
.vector_count
;
942 if (count
<= ARRAY_SIZE(req
->out
._vector
)) {
944 vector
= req
->out
._vector
;
946 vector
= talloc_zero_array(req
, struct iovec
, count
);
947 if (vector
== NULL
) {
948 return NT_STATUS_NO_MEMORY
;
953 vector
[0].iov_base
= req
->out
.nbt_hdr
;
954 vector
[0].iov_len
= 4;
955 SIVAL(req
->out
.nbt_hdr
, 0, 0);
957 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
958 struct iovec
*inhdr_v
= SMBD_SMB2_IDX_HDR_IOV(req
,in
,idx
);
959 const uint8_t *inhdr
= (const uint8_t *)inhdr_v
->iov_base
;
960 uint8_t *outhdr
= NULL
;
961 uint8_t *outbody
= NULL
;
962 uint32_t next_command_ofs
= 0;
963 struct iovec
*current
= &vector
[idx
];
965 if ((idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
) < count
) {
966 /* we have a next command -
967 * setup for the error case. */
968 next_command_ofs
= SMB2_HDR_BODY
+ 9;
972 outhdr
= req
->out
._hdr
;
974 outhdr
= talloc_zero_array(mem_ctx
, uint8_t,
976 if (outhdr
== NULL
) {
977 return NT_STATUS_NO_MEMORY
;
981 outbody
= outhdr
+ SMB2_HDR_BODY
;
984 * SMBD_SMB2_TF_IOV_OFS might be used later
986 current
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
987 current
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
989 current
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= (void *)outhdr
;
990 current
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
992 current
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= (void *)outbody
;
993 current
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= 8;
995 current
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= NULL
;
996 current
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= 0;
998 /* setup the SMB2 header */
999 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
1000 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1001 SSVAL(outhdr
, SMB2_HDR_CREDIT_CHARGE
,
1002 SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
));
1003 SIVAL(outhdr
, SMB2_HDR_STATUS
,
1004 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
1005 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
1006 SVAL(inhdr
, SMB2_HDR_OPCODE
));
1007 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
1008 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
1009 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
1010 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
1011 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
1012 SIVAL(outhdr
, SMB2_HDR_PID
,
1013 IVAL(inhdr
, SMB2_HDR_PID
));
1014 SIVAL(outhdr
, SMB2_HDR_TID
,
1015 IVAL(inhdr
, SMB2_HDR_TID
));
1016 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
1017 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
1018 memcpy(outhdr
+ SMB2_HDR_SIGNATURE
,
1019 inhdr
+ SMB2_HDR_SIGNATURE
, 16);
1021 /* setup error body header */
1022 SSVAL(outbody
, 0x00, 0x08 + 1);
1023 SSVAL(outbody
, 0x02, 0);
1024 SIVAL(outbody
, 0x04, 0);
1027 req
->out
.vector
= vector
;
1028 req
->out
.vector_count
= count
;
1030 /* setup the length of the NBT packet */
1031 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
1033 DLIST_ADD_END(req
->sconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
1035 return NT_STATUS_OK
;
1038 void smbd_server_connection_terminate_ex(struct smbd_server_connection
*sconn
,
1040 const char *location
)
1042 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1044 exit_server_cleanly(reason
);
1047 static bool dup_smb2_vec4(TALLOC_CTX
*ctx
,
1048 struct iovec
*outvec
,
1049 const struct iovec
*srcvec
)
1051 const uint8_t *srctf
;
1053 const uint8_t *srchdr
;
1055 const uint8_t *srcbody
;
1057 const uint8_t *expected_srcbody
;
1058 const uint8_t *srcdyn
;
1060 const uint8_t *expected_srcdyn
;
1066 srctf
= (const uint8_t *)srcvec
[SMBD_SMB2_TF_IOV_OFS
].iov_base
;
1067 srctf_len
= srcvec
[SMBD_SMB2_TF_IOV_OFS
].iov_len
;
1068 srchdr
= (const uint8_t *)srcvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
;
1069 srchdr_len
= srcvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
;
1070 srcbody
= (const uint8_t *)srcvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
;
1071 srcbody_len
= srcvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
;
1072 expected_srcbody
= srchdr
+ SMB2_HDR_BODY
;
1073 srcdyn
= (const uint8_t *)srcvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
;
1074 srcdyn_len
= srcvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
;
1075 expected_srcdyn
= srcbody
+ 8;
1077 if ((srctf_len
!= SMB2_TF_HDR_SIZE
) && (srctf_len
!= 0)) {
1081 if (srchdr_len
!= SMB2_HDR_BODY
) {
1085 if (srctf_len
== SMB2_TF_HDR_SIZE
) {
1086 dsttf
= talloc_memdup(ctx
, srctf
, SMB2_TF_HDR_SIZE
);
1087 if (dsttf
== NULL
) {
1093 outvec
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= (void *)dsttf
;
1094 outvec
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= srctf_len
;
1096 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1097 * be allocated with size OUTVEC_ALLOC_SIZE. */
1099 dsthdr
= talloc_memdup(ctx
, srchdr
, OUTVEC_ALLOC_SIZE
);
1100 if (dsthdr
== NULL
) {
1103 outvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= (void *)dsthdr
;
1104 outvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
1107 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1108 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1109 * then duplicate this. Else use talloc_memdup().
1112 if ((srcbody
== expected_srcbody
) && (srcbody_len
== 8)) {
1113 dstbody
= dsthdr
+ SMB2_HDR_BODY
;
1115 dstbody
= talloc_memdup(ctx
, srcbody
, srcbody_len
);
1116 if (dstbody
== NULL
) {
1120 outvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= (void *)dstbody
;
1121 outvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= srcbody_len
;
1124 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1126 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1127 * then duplicate this. Else use talloc_memdup().
1130 if ((srcdyn
== expected_srcdyn
) && (srcdyn_len
== 1)) {
1131 dstdyn
= dsthdr
+ SMB2_HDR_BODY
+ 8;
1132 } else if (srcdyn
== NULL
) {
1135 dstdyn
= talloc_memdup(ctx
, srcdyn
, srcdyn_len
);
1136 if (dstdyn
== NULL
) {
1140 outvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= (void *)dstdyn
;
1141 outvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= srcdyn_len
;
1146 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
1148 struct smbd_smb2_request
*newreq
= NULL
;
1149 struct iovec
*outvec
= NULL
;
1150 int count
= req
->out
.vector_count
;
1153 newreq
= smbd_smb2_request_allocate(req
->sconn
);
1158 newreq
->sconn
= req
->sconn
;
1159 newreq
->session
= req
->session
;
1160 newreq
->do_encryption
= req
->do_encryption
;
1161 newreq
->do_signing
= req
->do_signing
;
1162 newreq
->current_idx
= req
->current_idx
;
1164 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
1166 TALLOC_FREE(newreq
);
1169 newreq
->out
.vector
= outvec
;
1170 newreq
->out
.vector_count
= count
;
1172 /* Setup the outvec's identically to req. */
1173 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
1174 outvec
[0].iov_len
= 4;
1175 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
1177 /* Setup the vectors identically to the ones in req. */
1178 for (i
= 1; i
< count
; i
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
1179 if (!dup_smb2_vec4(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
1186 TALLOC_FREE(newreq
);
1190 smb2_setup_nbt_length(newreq
->out
.vector
,
1191 newreq
->out
.vector_count
);
1196 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
1198 struct smbd_server_connection
*sconn
= req
->sconn
;
1199 struct smbXsrv_connection
*conn
= req
->sconn
->conn
;
1201 struct iovec
*firsttf
= NULL
;
1202 struct iovec
*outhdr_v
= NULL
;
1203 uint8_t *outhdr
= NULL
;
1204 struct smbd_smb2_request
*nreq
= NULL
;
1207 /* Create a new smb2 request we'll use
1208 for the interim return. */
1209 nreq
= dup_smb2_req(req
);
1211 return NT_STATUS_NO_MEMORY
;
1214 /* Lose the last X out vectors. They're the
1215 ones we'll be using for the async reply. */
1216 nreq
->out
.vector_count
-= SMBD_SMB2_NUM_IOV_PER_REQ
;
1218 smb2_setup_nbt_length(nreq
->out
.vector
,
1219 nreq
->out
.vector_count
);
1221 /* Step back to the previous reply. */
1222 nreq
->current_idx
-= SMBD_SMB2_NUM_IOV_PER_REQ
;
1223 firsttf
= SMBD_SMB2_IDX_TF_IOV(nreq
,out
,first_idx
);
1224 outhdr_v
= SMBD_SMB2_OUT_HDR_IOV(nreq
);
1225 outhdr
= SMBD_SMB2_OUT_HDR_PTR(nreq
);
1226 /* And end the chain. */
1227 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1229 /* Calculate outgoing credits */
1230 smb2_calculate_credits(req
, nreq
);
1232 if (DEBUGLEVEL
>= 10) {
1233 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1234 (unsigned int)nreq
->current_idx
);
1235 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1236 (unsigned int)nreq
->out
.vector_count
);
1237 print_req_vectors(nreq
);
1241 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1242 * we need to sign/encrypt here with the last/first key we remembered
1244 if (firsttf
->iov_len
== SMB2_TF_HDR_SIZE
) {
1245 status
= smb2_signing_encrypt_pdu(req
->first_key
,
1248 nreq
->out
.vector_count
- first_idx
);
1249 if (!NT_STATUS_IS_OK(status
)) {
1252 } else if (req
->last_key
.length
> 0) {
1253 status
= smb2_signing_sign_pdu(req
->last_key
,
1256 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
1257 if (!NT_STATUS_IS_OK(status
)) {
1262 nreq
->queue_entry
.mem_ctx
= nreq
;
1263 nreq
->queue_entry
.vector
= nreq
->out
.vector
;
1264 nreq
->queue_entry
.count
= nreq
->out
.vector_count
;
1265 DLIST_ADD_END(nreq
->sconn
->smb2
.send_queue
, &nreq
->queue_entry
, NULL
);
1266 nreq
->sconn
->smb2
.send_queue_len
++;
1268 status
= smbd_smb2_io_handler(sconn
, TEVENT_FD_WRITE
);
1269 if (!NT_STATUS_IS_OK(status
)) {
1273 return NT_STATUS_OK
;
1276 struct smbd_smb2_request_pending_state
{
1277 struct smbd_server_connection
*sconn
;
1278 struct smbd_smb2_send_queue queue_entry
;
1279 uint8_t buf
[NBT_HDR_SIZE
+ SMB2_TF_HDR_SIZE
+ SMB2_HDR_BODY
+ 0x08 + 1];
1280 struct iovec vector
[1 + SMBD_SMB2_NUM_IOV_PER_REQ
];
1283 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
1284 struct tevent_timer
*te
,
1285 struct timeval current_time
,
1286 void *private_data
);
1288 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
1289 struct tevent_req
*subreq
,
1290 uint32_t defer_time
)
1293 struct timeval defer_endtime
;
1294 uint8_t *outhdr
= NULL
;
1297 if (!tevent_req_is_in_progress(subreq
)) {
1299 * This is a performance optimization,
1300 * it avoids one tevent_loop iteration,
1301 * which means we avoid one
1302 * talloc_stackframe_pool/talloc_free pair.
1304 tevent_req_notify_callback(subreq
);
1305 return NT_STATUS_OK
;
1308 req
->subreq
= subreq
;
1311 if (req
->async_te
) {
1312 /* We're already async. */
1313 return NT_STATUS_OK
;
1316 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1317 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1318 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1319 /* We're already async. */
1320 return NT_STATUS_OK
;
1323 if (req
->in
.vector_count
> req
->current_idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
) {
1325 * We're trying to go async in a compound
1327 * This is only allowed for opens that
1328 * cause an oplock break, otherwise it
1329 * is not allowed. See [MS-SMB2].pdf
1330 * note <194> on Section 3.3.5.2.7.
1332 const uint8_t *inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1334 if (SVAL(inhdr
, SMB2_HDR_OPCODE
) != SMB2_OP_CREATE
) {
1336 * Cancel the outstanding request.
1338 bool ok
= tevent_req_cancel(req
->subreq
);
1340 return NT_STATUS_OK
;
1342 TALLOC_FREE(req
->subreq
);
1343 return smbd_smb2_request_error(req
,
1344 NT_STATUS_INTERNAL_ERROR
);
1348 if (DEBUGLEVEL
>= 10) {
1349 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1350 (unsigned int)req
->current_idx
);
1351 print_req_vectors(req
);
1354 if (req
->current_idx
> 1) {
1356 * We're going async in a compound
1357 * chain after the first request has
1358 * already been processed. Send an
1359 * interim response containing the
1360 * set of replies already generated.
1362 int idx
= req
->current_idx
;
1364 status
= smb2_send_async_interim_response(req
);
1365 if (!NT_STATUS_IS_OK(status
)) {
1368 if (req
->first_key
.length
> 0) {
1369 data_blob_clear_free(&req
->first_key
);
1372 req
->current_idx
= 1;
1375 * Re-arrange the in.vectors to remove what
1378 memmove(&req
->in
.vector
[1],
1379 &req
->in
.vector
[idx
],
1380 sizeof(req
->in
.vector
[0])*(req
->in
.vector_count
- idx
));
1381 req
->in
.vector_count
= 1 + (req
->in
.vector_count
- idx
);
1383 /* Re-arrange the out.vectors to match. */
1384 memmove(&req
->out
.vector
[1],
1385 &req
->out
.vector
[idx
],
1386 sizeof(req
->out
.vector
[0])*(req
->out
.vector_count
- idx
));
1387 req
->out
.vector_count
= 1 + (req
->out
.vector_count
- idx
);
1389 if (req
->in
.vector_count
== 1 + SMBD_SMB2_NUM_IOV_PER_REQ
) {
1391 * We only have one remaining request as
1392 * we've processed everything else.
1393 * This is no longer a compound request.
1395 req
->compound_related
= false;
1396 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1397 flags
= (IVAL(outhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
1398 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
);
1401 if (req
->last_key
.length
> 0) {
1402 data_blob_clear_free(&req
->last_key
);
1405 defer_endtime
= timeval_current_ofs_usec(defer_time
);
1406 req
->async_te
= tevent_add_timer(req
->sconn
->ev_ctx
,
1408 smbd_smb2_request_pending_timer
,
1410 if (req
->async_te
== NULL
) {
1411 return NT_STATUS_NO_MEMORY
;
1414 return NT_STATUS_OK
;
1417 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
1418 struct tevent_timer
*te
,
1419 struct timeval current_time
,
1422 struct smbd_smb2_request
*req
=
1423 talloc_get_type_abort(private_data
,
1424 struct smbd_smb2_request
);
1425 struct smbd_server_connection
*sconn
= req
->sconn
;
1426 struct smbd_smb2_request_pending_state
*state
= NULL
;
1427 uint8_t *outhdr
= NULL
;
1428 const uint8_t *inhdr
= NULL
;
1431 uint8_t *hdr
= NULL
;
1432 uint8_t *body
= NULL
;
1433 uint8_t *dyn
= NULL
;
1435 uint64_t session_id
= 0;
1436 uint64_t message_id
= 0;
1437 uint64_t nonce_high
= 0;
1438 uint64_t nonce_low
= 0;
1439 uint64_t async_id
= 0;
1442 TALLOC_FREE(req
->async_te
);
1444 /* Ensure our final reply matches the interim one. */
1445 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1446 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1447 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1448 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1449 session_id
= BVAL(outhdr
, SMB2_HDR_SESSION_ID
);
1451 async_id
= message_id
; /* keep it simple for now... */
1453 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1454 SBVAL(outhdr
, SMB2_HDR_ASYNC_ID
, async_id
);
1456 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1458 smb2_opcode_name(SVAL(inhdr
, SMB2_HDR_OPCODE
)),
1459 (unsigned long long)async_id
));
1462 * What we send is identical to a smbd_smb2_request_error
1463 * packet with an error status of STATUS_PENDING. Make use
1464 * of this fact sometime when refactoring. JRA.
1467 state
= talloc_zero(req
->sconn
, struct smbd_smb2_request_pending_state
);
1468 if (state
== NULL
) {
1469 smbd_server_connection_terminate(req
->sconn
,
1470 nt_errstr(NT_STATUS_NO_MEMORY
));
1473 state
->sconn
= req
->sconn
;
1475 tf
= state
->buf
+ NBT_HDR_SIZE
;
1476 tf_len
= SMB2_TF_HDR_SIZE
;
1478 hdr
= tf
+ SMB2_TF_HDR_SIZE
;
1479 body
= hdr
+ SMB2_HDR_BODY
;
1482 if (req
->do_encryption
) {
1483 struct smbXsrv_session
*x
= req
->session
;
1485 nonce_high
= x
->nonce_high
;
1486 nonce_low
= x
->nonce_low
;
1489 if (x
->nonce_low
== 0) {
1495 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
1496 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
1497 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
1498 SBVAL(tf
, SMB2_TF_SESSION_ID
, session_id
);
1500 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
1501 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1502 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1503 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
1504 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(outhdr
, SMB2_HDR_OPCODE
));
1506 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
);
1507 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1508 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
1509 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
1510 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
1511 BVAL(outhdr
, SMB2_HDR_SESSION_ID
));
1512 memcpy(hdr
+SMB2_HDR_SIGNATURE
,
1513 outhdr
+SMB2_HDR_SIGNATURE
, 16);
1515 SSVAL(body
, 0x00, 0x08 + 1);
1517 SCVAL(body
, 0x02, 0);
1518 SCVAL(body
, 0x03, 0);
1519 SIVAL(body
, 0x04, 0);
1520 /* Match W2K8R2... */
1521 SCVAL(dyn
, 0x00, 0x21);
1523 state
->vector
[0].iov_base
= (void *)state
->buf
;
1524 state
->vector
[0].iov_len
= NBT_HDR_SIZE
;
1526 if (req
->do_encryption
) {
1527 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= tf
;
1528 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= tf_len
;
1530 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
1531 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
1534 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
1535 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
1537 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
1538 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_len
= 8;
1540 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
1541 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_len
= 1;
1543 smb2_setup_nbt_length(state
->vector
, 1 + SMBD_SMB2_NUM_IOV_PER_REQ
);
1545 /* Ensure we correctly go through crediting. Grant
1546 the credits now, and zero credits on the final
1548 smb2_set_operation_credit(req
->sconn
,
1549 SMBD_SMB2_IN_HDR_IOV(req
),
1550 &state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
]);
1552 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1557 for (i
= 0; i
< ARRAY_SIZE(state
->vector
); i
++) {
1558 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1560 (unsigned int)ARRAY_SIZE(state
->vector
),
1561 (unsigned int)state
->vector
[i
].iov_len
);
1565 if (req
->do_encryption
) {
1566 struct smbXsrv_session
*x
= req
->session
;
1567 struct smbXsrv_connection
*conn
= x
->connection
;
1568 DATA_BLOB encryption_key
= x
->global
->encryption_key
;
1570 status
= smb2_signing_encrypt_pdu(encryption_key
,
1572 &state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
],
1573 SMBD_SMB2_NUM_IOV_PER_REQ
);
1574 if (!NT_STATUS_IS_OK(status
)) {
1575 smbd_server_connection_terminate(req
->sconn
,
1579 } else if (req
->do_signing
) {
1580 struct smbXsrv_session
*x
= req
->session
;
1581 struct smbXsrv_connection
*conn
= x
->connection
;
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(sconn
->smb2
.send_queue
, &state
->queue_entry
, NULL
);
1599 sconn
->smb2
.send_queue_len
++;
1601 status
= smbd_smb2_io_handler(sconn
, TEVENT_FD_WRITE
);
1602 if (!NT_STATUS_IS_OK(status
)) {
1603 smbd_server_connection_terminate(sconn
,
1609 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
1611 struct smbd_server_connection
*sconn
= req
->sconn
;
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(req
->sconn
->smb2
.requests
, req
);
1632 for (cur
= sconn
->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
->sconn
->conn
,
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
->sconn
->conn
->last_session_id
) {
1798 req
->sconn
->conn
->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 uint16_t needed_charge
;
1811 uint16_t credit_charge
= 1;
1812 const uint8_t *inhdr
;
1814 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1816 if (req
->sconn
->smb2
.supports_multicredit
) {
1817 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
1818 credit_charge
= MAX(credit_charge
, 1);
1821 needed_charge
= (data_length
- 1)/ 65536 + 1;
1823 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1824 (unsigned long long) BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
),
1825 credit_charge
, needed_charge
));
1827 if (needed_charge
> credit_charge
) {
1828 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1829 credit_charge
, needed_charge
));
1830 return NT_STATUS_INVALID_PARAMETER
;
1833 return NT_STATUS_OK
;
1836 NTSTATUS
smbd_smb2_request_verify_sizes(struct smbd_smb2_request
*req
,
1837 size_t expected_body_size
)
1839 struct iovec
*inhdr_v
;
1840 const uint8_t *inhdr
;
1842 const uint8_t *inbody
;
1844 size_t min_dyn_size
= expected_body_size
& 0x00000001;
1845 int max_idx
= req
->in
.vector_count
- SMBD_SMB2_NUM_IOV_PER_REQ
;
1848 * The following should be checked already.
1850 if (req
->in
.vector_count
< SMBD_SMB2_NUM_IOV_PER_REQ
) {
1851 return NT_STATUS_INTERNAL_ERROR
;
1853 if (req
->current_idx
> max_idx
) {
1854 return NT_STATUS_INTERNAL_ERROR
;
1857 inhdr_v
= SMBD_SMB2_IN_HDR_IOV(req
);
1858 if (inhdr_v
->iov_len
!= SMB2_HDR_BODY
) {
1859 return NT_STATUS_INTERNAL_ERROR
;
1861 if (SMBD_SMB2_IN_BODY_LEN(req
) < 2) {
1862 return NT_STATUS_INTERNAL_ERROR
;
1865 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1866 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1870 case SMB2_OP_GETINFO
:
1874 if (req
->smb1req
!= NULL
&& req
->smb1req
->unread_bytes
> 0) {
1875 if (req
->smb1req
->unread_bytes
< min_dyn_size
) {
1876 return NT_STATUS_INVALID_PARAMETER
;
1885 * Now check the expected body size,
1886 * where the last byte might be in the
1889 if (SMBD_SMB2_IN_BODY_LEN(req
) != (expected_body_size
& 0xFFFFFFFE)) {
1890 return NT_STATUS_INVALID_PARAMETER
;
1892 if (SMBD_SMB2_IN_DYN_LEN(req
) < min_dyn_size
) {
1893 return NT_STATUS_INVALID_PARAMETER
;
1896 inbody
= SMBD_SMB2_IN_BODY_PTR(req
);
1898 body_size
= SVAL(inbody
, 0x00);
1899 if (body_size
!= expected_body_size
) {
1900 return NT_STATUS_INVALID_PARAMETER
;
1903 return NT_STATUS_OK
;
1906 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
1908 struct smbXsrv_connection
*conn
= req
->sconn
->conn
;
1909 const struct smbd_smb2_dispatch_table
*call
= NULL
;
1910 const struct iovec
*intf_v
= SMBD_SMB2_IN_TF_IOV(req
);
1911 const uint8_t *inhdr
;
1916 NTSTATUS session_status
;
1917 uint32_t allowed_flags
;
1918 NTSTATUS return_value
;
1919 struct smbXsrv_session
*x
= NULL
;
1920 bool signing_required
= false;
1921 bool encryption_required
= false;
1923 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1925 /* TODO: verify more things */
1927 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1928 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1929 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1930 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1931 smb2_opcode_name(opcode
),
1932 (unsigned long long)mid
));
1934 if (conn
->protocol
>= PROTOCOL_SMB2_02
) {
1936 * once the protocol is negotiated
1937 * SMB2_OP_NEGPROT is not allowed anymore
1939 if (opcode
== SMB2_OP_NEGPROT
) {
1940 /* drop the connection */
1941 return NT_STATUS_INVALID_PARAMETER
;
1945 * if the protocol is not negotiated yet
1946 * only SMB2_OP_NEGPROT is allowed.
1948 if (opcode
!= SMB2_OP_NEGPROT
) {
1949 /* drop the connection */
1950 return NT_STATUS_INVALID_PARAMETER
;
1955 * Check if the client provided a valid session id,
1956 * if so smbd_smb2_request_check_session() calls
1957 * set_current_user_info().
1959 * As some command don't require a valid session id
1960 * we defer the check of the session_status
1962 session_status
= smbd_smb2_request_check_session(req
);
1965 signing_required
= x
->global
->signing_required
;
1966 encryption_required
= x
->global
->encryption_required
;
1968 if (opcode
== SMB2_OP_SESSSETUP
&&
1969 x
->global
->channels
[0].signing_key
.length
) {
1970 signing_required
= true;
1974 req
->do_signing
= false;
1975 req
->do_encryption
= false;
1976 if (intf_v
->iov_len
== SMB2_TF_HDR_SIZE
) {
1977 const uint8_t *intf
= SMBD_SMB2_IN_TF_PTR(req
);
1978 uint64_t tf_session_id
= BVAL(intf
, SMB2_TF_SESSION_ID
);
1980 if (x
!= NULL
&& x
->global
->session_wire_id
!= tf_session_id
) {
1981 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1982 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1983 (unsigned long long)x
->global
->session_wire_id
,
1984 (unsigned long long)tf_session_id
));
1986 * TODO: windows allows this...
1987 * should we drop the connection?
1989 * For now we just return ACCESS_DENIED
1990 * (Windows clients never trigger this)
1991 * and wait for an update of [MS-SMB2].
1993 return smbd_smb2_request_error(req
,
1994 NT_STATUS_ACCESS_DENIED
);
1997 req
->do_encryption
= true;
2000 if (encryption_required
&& !req
->do_encryption
) {
2001 return smbd_smb2_request_error(req
,
2002 NT_STATUS_ACCESS_DENIED
);
2005 call
= smbd_smb2_call(opcode
);
2007 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2010 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
2011 SMB2_HDR_FLAG_SIGNED
|
2013 if (opcode
== SMB2_OP_CANCEL
) {
2014 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
2016 if ((flags
& ~allowed_flags
) != 0) {
2017 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2020 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
2022 * This check is mostly for giving the correct error code
2023 * for compounded requests.
2025 if (!NT_STATUS_IS_OK(session_status
)) {
2026 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2029 req
->compat_chain_fsp
= NULL
;
2032 if (req
->do_encryption
) {
2033 signing_required
= false;
2034 } else if (signing_required
|| (flags
& SMB2_HDR_FLAG_SIGNED
)) {
2035 DATA_BLOB signing_key
;
2038 return smbd_smb2_request_error(
2039 req
, NT_STATUS_USER_SESSION_DELETED
);
2042 signing_key
= x
->global
->channels
[0].signing_key
;
2045 * If we have a signing key, we should
2048 if (signing_key
.length
> 0) {
2049 req
->do_signing
= true;
2052 status
= smb2_signing_check_pdu(signing_key
,
2054 SMBD_SMB2_IN_HDR_IOV(req
),
2055 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2056 if (!NT_STATUS_IS_OK(status
)) {
2057 return smbd_smb2_request_error(req
, status
);
2061 * Now that we know the request was correctly signed
2062 * we have to sign the response too.
2064 req
->do_signing
= true;
2066 if (!NT_STATUS_IS_OK(session_status
)) {
2067 return smbd_smb2_request_error(req
, session_status
);
2069 } else if (opcode
== SMB2_OP_CANCEL
) {
2070 /* Cancel requests are allowed to skip the signing */
2071 } else if (signing_required
) {
2073 * If signing is required we try to sign
2074 * a possible error response
2076 req
->do_signing
= true;
2077 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
2080 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
2081 req
->compound_related
= true;
2084 if (call
->need_session
) {
2085 if (!NT_STATUS_IS_OK(session_status
)) {
2086 return smbd_smb2_request_error(req
, session_status
);
2090 if (call
->need_tcon
) {
2091 SMB_ASSERT(call
->need_session
);
2094 * This call needs to be run as user.
2096 * smbd_smb2_request_check_tcon()
2097 * calls change_to_user() on success.
2099 status
= smbd_smb2_request_check_tcon(req
);
2100 if (!NT_STATUS_IS_OK(status
)) {
2101 return smbd_smb2_request_error(req
, status
);
2103 if (req
->tcon
->global
->encryption_required
) {
2104 encryption_required
= true;
2106 if (encryption_required
&& !req
->do_encryption
) {
2107 return smbd_smb2_request_error(req
,
2108 NT_STATUS_ACCESS_DENIED
);
2112 if (call
->fileid_ofs
!= 0) {
2113 size_t needed
= call
->fileid_ofs
+ 16;
2114 const uint8_t *body
= SMBD_SMB2_IN_BODY_PTR(req
);
2115 size_t body_size
= SMBD_SMB2_IN_BODY_LEN(req
);
2116 uint64_t file_id_persistent
;
2117 uint64_t file_id_volatile
;
2118 struct files_struct
*fsp
;
2120 SMB_ASSERT(call
->need_tcon
);
2122 if (needed
> body_size
) {
2123 return smbd_smb2_request_error(req
,
2124 NT_STATUS_INVALID_PARAMETER
);
2127 file_id_persistent
= BVAL(body
, call
->fileid_ofs
+ 0);
2128 file_id_volatile
= BVAL(body
, call
->fileid_ofs
+ 8);
2130 fsp
= file_fsp_smb2(req
, file_id_persistent
, file_id_volatile
);
2132 if (!call
->allow_invalid_fileid
) {
2133 return smbd_smb2_request_error(req
,
2134 NT_STATUS_FILE_CLOSED
);
2137 if (file_id_persistent
!= UINT64_MAX
) {
2138 return smbd_smb2_request_error(req
,
2139 NT_STATUS_FILE_CLOSED
);
2141 if (file_id_volatile
!= UINT64_MAX
) {
2142 return smbd_smb2_request_error(req
,
2143 NT_STATUS_FILE_CLOSED
);
2148 if (call
->as_root
) {
2149 SMB_ASSERT(call
->fileid_ofs
== 0);
2150 /* This call needs to be run as root */
2151 change_to_root_user();
2153 SMB_ASSERT(call
->need_tcon
);
2157 case SMB2_OP_NEGPROT
:
2159 START_PROFILE(smb2_negprot
);
2160 return_value
= smbd_smb2_request_process_negprot(req
);
2161 END_PROFILE(smb2_negprot
);
2165 case SMB2_OP_SESSSETUP
:
2167 START_PROFILE(smb2_sesssetup
);
2168 return_value
= smbd_smb2_request_process_sesssetup(req
);
2169 END_PROFILE(smb2_sesssetup
);
2173 case SMB2_OP_LOGOFF
:
2175 START_PROFILE(smb2_logoff
);
2176 return_value
= smbd_smb2_request_process_logoff(req
);
2177 END_PROFILE(smb2_logoff
);
2183 START_PROFILE(smb2_tcon
);
2184 return_value
= smbd_smb2_request_process_tcon(req
);
2185 END_PROFILE(smb2_tcon
);
2191 START_PROFILE(smb2_tdis
);
2192 return_value
= smbd_smb2_request_process_tdis(req
);
2193 END_PROFILE(smb2_tdis
);
2197 case SMB2_OP_CREATE
:
2199 START_PROFILE(smb2_create
);
2200 return_value
= smbd_smb2_request_process_create(req
);
2201 END_PROFILE(smb2_create
);
2207 START_PROFILE(smb2_close
);
2208 return_value
= smbd_smb2_request_process_close(req
);
2209 END_PROFILE(smb2_close
);
2215 START_PROFILE(smb2_flush
);
2216 return_value
= smbd_smb2_request_process_flush(req
);
2217 END_PROFILE(smb2_flush
);
2223 START_PROFILE(smb2_read
);
2224 return_value
= smbd_smb2_request_process_read(req
);
2225 END_PROFILE(smb2_read
);
2231 START_PROFILE(smb2_write
);
2232 return_value
= smbd_smb2_request_process_write(req
);
2233 END_PROFILE(smb2_write
);
2239 START_PROFILE(smb2_lock
);
2240 return_value
= smbd_smb2_request_process_lock(req
);
2241 END_PROFILE(smb2_lock
);
2247 START_PROFILE(smb2_ioctl
);
2248 return_value
= smbd_smb2_request_process_ioctl(req
);
2249 END_PROFILE(smb2_ioctl
);
2253 case SMB2_OP_CANCEL
:
2255 START_PROFILE(smb2_cancel
);
2256 return_value
= smbd_smb2_request_process_cancel(req
);
2257 END_PROFILE(smb2_cancel
);
2261 case SMB2_OP_KEEPALIVE
:
2263 START_PROFILE(smb2_keepalive
);
2264 return_value
= smbd_smb2_request_process_keepalive(req
);
2265 END_PROFILE(smb2_keepalive
);
2271 START_PROFILE(smb2_find
);
2272 return_value
= smbd_smb2_request_process_find(req
);
2273 END_PROFILE(smb2_find
);
2277 case SMB2_OP_NOTIFY
:
2279 START_PROFILE(smb2_notify
);
2280 return_value
= smbd_smb2_request_process_notify(req
);
2281 END_PROFILE(smb2_notify
);
2285 case SMB2_OP_GETINFO
:
2287 START_PROFILE(smb2_getinfo
);
2288 return_value
= smbd_smb2_request_process_getinfo(req
);
2289 END_PROFILE(smb2_getinfo
);
2293 case SMB2_OP_SETINFO
:
2295 START_PROFILE(smb2_setinfo
);
2296 return_value
= smbd_smb2_request_process_setinfo(req
);
2297 END_PROFILE(smb2_setinfo
);
2303 START_PROFILE(smb2_break
);
2304 return_value
= smbd_smb2_request_process_break(req
);
2305 END_PROFILE(smb2_break
);
2310 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2313 return return_value
;
2316 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
2318 struct smbd_server_connection
*sconn
= req
->sconn
;
2319 struct smbXsrv_connection
*conn
= req
->sconn
->conn
;
2321 struct iovec
*firsttf
= SMBD_SMB2_IDX_TF_IOV(req
,out
,first_idx
);
2322 struct iovec
*outhdr
= SMBD_SMB2_OUT_HDR_IOV(req
);
2323 struct iovec
*outdyn
= SMBD_SMB2_OUT_DYN_IOV(req
);
2327 TALLOC_FREE(req
->async_te
);
2329 if (req
->do_encryption
&&
2330 (firsttf
->iov_len
== 0) &&
2331 (req
->first_key
.length
== 0) &&
2332 (req
->session
!= NULL
) &&
2333 (req
->session
->global
->encryption_key
.length
!= 0))
2335 DATA_BLOB encryption_key
= req
->session
->global
->encryption_key
;
2337 uint64_t session_id
= req
->session
->global
->session_wire_id
;
2338 struct smbXsrv_session
*x
= req
->session
;
2339 uint64_t nonce_high
;
2342 nonce_high
= x
->nonce_high
;
2343 nonce_low
= x
->nonce_low
;
2346 if (x
->nonce_low
== 0) {
2352 * We need to place the SMB2_TRANSFORM header before the
2357 * we need to remember the encryption key
2358 * and defer the signing/encryption until
2359 * we are sure that we do not change
2362 req
->first_key
= data_blob_dup_talloc(req
, encryption_key
);
2363 if (req
->first_key
.data
== NULL
) {
2364 return NT_STATUS_NO_MEMORY
;
2367 tf
= talloc_zero_array(req
, uint8_t,
2370 return NT_STATUS_NO_MEMORY
;
2373 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
2374 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
2375 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
2376 SBVAL(tf
, SMB2_TF_SESSION_ID
, session_id
);
2378 firsttf
->iov_base
= (void *)tf
;
2379 firsttf
->iov_len
= SMB2_TF_HDR_SIZE
;
2382 if ((req
->current_idx
> SMBD_SMB2_NUM_IOV_PER_REQ
) &&
2383 (req
->last_key
.length
> 0) &&
2384 (firsttf
->iov_len
== 0))
2386 int last_idx
= req
->current_idx
- SMBD_SMB2_NUM_IOV_PER_REQ
;
2387 struct iovec
*lasthdr
= SMBD_SMB2_IDX_HDR_IOV(req
,out
,last_idx
);
2390 * As we are sure the header of the last request in the
2391 * compound chain will not change, we can to sign here
2392 * with the last signing key we remembered.
2394 status
= smb2_signing_sign_pdu(req
->last_key
,
2397 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2398 if (!NT_STATUS_IS_OK(status
)) {
2402 if (req
->last_key
.length
> 0) {
2403 data_blob_clear_free(&req
->last_key
);
2406 req
->current_idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
;
2408 if (req
->current_idx
< req
->out
.vector_count
) {
2410 * We must process the remaining compound
2411 * SMB2 requests before any new incoming SMB2
2412 * requests. This is because incoming SMB2
2413 * requests may include a cancel for a
2414 * compound request we haven't processed
2417 struct tevent_immediate
*im
= tevent_create_immediate(req
);
2419 return NT_STATUS_NO_MEMORY
;
2422 if (req
->do_signing
&& firsttf
->iov_len
== 0) {
2423 struct smbXsrv_session
*x
= req
->session
;
2424 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
2427 * we need to remember the signing key
2428 * and defer the signing until
2429 * we are sure that we do not change
2432 req
->last_key
= data_blob_dup_talloc(req
, signing_key
);
2433 if (req
->last_key
.data
== NULL
) {
2434 return NT_STATUS_NO_MEMORY
;
2438 tevent_schedule_immediate(im
,
2440 smbd_smb2_request_dispatch_immediate
,
2442 return NT_STATUS_OK
;
2445 if (req
->compound_related
) {
2446 req
->compound_related
= false;
2449 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
2451 /* Set credit for these operations (zero credits if this
2452 is a final reply for an async operation). */
2453 smb2_calculate_credits(req
, req
);
2456 * now check if we need to sign the current response
2458 if (firsttf
->iov_len
== SMB2_TF_HDR_SIZE
) {
2459 status
= smb2_signing_encrypt_pdu(req
->first_key
,
2462 req
->out
.vector_count
- first_idx
);
2463 if (!NT_STATUS_IS_OK(status
)) {
2466 } else if (req
->do_signing
) {
2467 struct smbXsrv_session
*x
= req
->session
;
2468 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
2470 status
= smb2_signing_sign_pdu(signing_key
,
2473 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2474 if (!NT_STATUS_IS_OK(status
)) {
2478 if (req
->first_key
.length
> 0) {
2479 data_blob_clear_free(&req
->first_key
);
2482 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2483 if (req
->out
.vector_count
< (2*SMBD_SMB2_NUM_IOV_PER_REQ
) &&
2484 outdyn
->iov_base
== NULL
&& outdyn
->iov_len
!= 0) {
2485 /* Dynamic part is NULL. Chop it off,
2486 We're going to send it via sendfile. */
2487 req
->out
.vector_count
-= 1;
2491 * We're done with this request -
2492 * move it off the "being processed" queue.
2494 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
2496 req
->queue_entry
.mem_ctx
= req
;
2497 req
->queue_entry
.vector
= req
->out
.vector
;
2498 req
->queue_entry
.count
= req
->out
.vector_count
;
2499 DLIST_ADD_END(req
->sconn
->smb2
.send_queue
, &req
->queue_entry
, NULL
);
2500 req
->sconn
->smb2
.send_queue_len
++;
2502 status
= smbd_smb2_io_handler(sconn
, TEVENT_FD_WRITE
);
2503 if (!NT_STATUS_IS_OK(status
)) {
2507 return NT_STATUS_OK
;
2510 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
);
2512 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
2513 struct tevent_immediate
*im
,
2516 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
2517 struct smbd_smb2_request
);
2518 struct smbd_server_connection
*sconn
= req
->sconn
;
2523 if (DEBUGLEVEL
>= 10) {
2524 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2525 req
->current_idx
, req
->in
.vector_count
));
2526 print_req_vectors(req
);
2529 status
= smbd_smb2_request_dispatch(req
);
2530 if (!NT_STATUS_IS_OK(status
)) {
2531 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2535 status
= smbd_smb2_request_next_incoming(sconn
);
2536 if (!NT_STATUS_IS_OK(status
)) {
2537 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2542 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
2544 DATA_BLOB body
, DATA_BLOB
*dyn
,
2545 const char *location
)
2548 struct iovec
*outbody_v
;
2549 struct iovec
*outdyn_v
;
2550 uint32_t next_command_ofs
;
2552 DEBUG(10,("smbd_smb2_request_done_ex: "
2553 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2554 req
->current_idx
, nt_errstr(status
), (unsigned int)body
.length
,
2556 (unsigned int)(dyn
? dyn
->length
: 0),
2559 if (body
.length
< 2) {
2560 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2563 if ((body
.length
% 2) != 0) {
2564 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2567 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
2568 outbody_v
= SMBD_SMB2_OUT_BODY_IOV(req
);
2569 outdyn_v
= SMBD_SMB2_OUT_DYN_IOV(req
);
2571 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
2572 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
2574 outbody_v
->iov_base
= (void *)body
.data
;
2575 outbody_v
->iov_len
= body
.length
;
2578 outdyn_v
->iov_base
= (void *)dyn
->data
;
2579 outdyn_v
->iov_len
= dyn
->length
;
2581 outdyn_v
->iov_base
= NULL
;
2582 outdyn_v
->iov_len
= 0;
2585 /* see if we need to recalculate the offset to the next response */
2586 if (next_command_ofs
> 0) {
2587 next_command_ofs
= SMB2_HDR_BODY
;
2588 next_command_ofs
+= SMBD_SMB2_OUT_BODY_LEN(req
);
2589 next_command_ofs
+= SMBD_SMB2_OUT_DYN_LEN(req
);
2592 if ((next_command_ofs
% 8) != 0) {
2593 size_t pad_size
= 8 - (next_command_ofs
% 8);
2594 if (SMBD_SMB2_OUT_DYN_LEN(req
) == 0) {
2596 * if the dyn buffer is empty
2597 * we can use it to add padding
2601 pad
= talloc_zero_array(req
,
2604 return smbd_smb2_request_error(req
,
2605 NT_STATUS_NO_MEMORY
);
2608 outdyn_v
->iov_base
= (void *)pad
;
2609 outdyn_v
->iov_len
= pad_size
;
2612 * For now we copy the dynamic buffer
2613 * and add the padding to the new buffer
2620 old_size
= SMBD_SMB2_OUT_DYN_LEN(req
);
2621 old_dyn
= SMBD_SMB2_OUT_DYN_PTR(req
);
2623 new_size
= old_size
+ pad_size
;
2624 new_dyn
= talloc_zero_array(req
,
2626 if (new_dyn
== NULL
) {
2627 return smbd_smb2_request_error(req
,
2628 NT_STATUS_NO_MEMORY
);
2631 memcpy(new_dyn
, old_dyn
, old_size
);
2632 memset(new_dyn
+ old_size
, 0, pad_size
);
2634 outdyn_v
->iov_base
= (void *)new_dyn
;
2635 outdyn_v
->iov_len
= new_size
;
2637 next_command_ofs
+= pad_size
;
2640 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
2642 return smbd_smb2_request_reply(req
);
2645 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
2648 const char *location
)
2652 uint8_t *outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
2653 size_t unread_bytes
= smbd_smb2_unread_bytes(req
);
2655 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2656 req
->current_idx
, nt_errstr(status
), info
? " +info" : "",
2660 /* Recvfile error. Drain incoming socket. */
2664 ret
= drain_socket(req
->sconn
->sock
, unread_bytes
);
2665 if (ret
!= unread_bytes
) {
2669 error
= NT_STATUS_IO_DEVICE_ERROR
;
2671 error
= map_nt_error_from_unix_common(errno
);
2674 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2675 "ret[%u] errno[%d] => %s\n",
2676 (unsigned)unread_bytes
,
2677 (unsigned)ret
, errno
, nt_errstr(error
)));
2682 body
.data
= outhdr
+ SMB2_HDR_BODY
;
2684 SSVAL(body
.data
, 0, 9);
2687 SIVAL(body
.data
, 0x04, info
->length
);
2689 /* Allocated size of req->out.vector[i].iov_base
2690 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2691 * 1 byte without having to do an alloc.
2694 info
->data
= ((uint8_t *)outhdr
) +
2695 OUTVEC_ALLOC_SIZE
- 1;
2697 SCVAL(info
->data
, 0, 0);
2701 * Note: Even if there is an error, continue to process the request.
2705 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
2709 struct smbd_smb2_send_oplock_break_state
{
2710 struct smbd_server_connection
*sconn
;
2711 struct smbd_smb2_send_queue queue_entry
;
2712 uint8_t buf
[NBT_HDR_SIZE
+ SMB2_TF_HDR_SIZE
+ SMB2_HDR_BODY
+ 0x18];
2713 struct iovec vector
[1+SMBD_SMB2_NUM_IOV_PER_REQ
];
2716 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
2717 struct smbXsrv_session
*session
,
2718 struct smbXsrv_tcon
*tcon
,
2719 struct smbXsrv_open
*op
,
2720 uint8_t oplock_level
)
2722 struct smbd_smb2_send_oplock_break_state
*state
;
2723 struct smbXsrv_connection
*conn
= sconn
->conn
;
2731 bool do_encryption
= session
->global
->encryption_required
;
2732 uint64_t nonce_high
= 0;
2733 uint64_t nonce_low
= 0;
2736 if (tcon
->global
->encryption_required
) {
2737 do_encryption
= true;
2740 state
= talloc_zero(sconn
, struct smbd_smb2_send_oplock_break_state
);
2741 if (state
== NULL
) {
2742 return NT_STATUS_NO_MEMORY
;
2744 state
->sconn
= sconn
;
2746 tf
= state
->buf
+ NBT_HDR_SIZE
;
2747 tf_len
= SMB2_TF_HDR_SIZE
;
2749 body
= hdr
+ SMB2_HDR_BODY
;
2751 dyn
= body
+ body_len
;
2754 if (do_encryption
) {
2755 nonce_high
= session
->nonce_high
;
2756 nonce_low
= session
->nonce_low
;
2758 session
->nonce_low
+= 1;
2759 if (session
->nonce_low
== 0) {
2760 session
->nonce_low
+= 1;
2761 session
->nonce_high
+= 1;
2765 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
2766 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
2767 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
2768 SBVAL(tf
, SMB2_TF_SESSION_ID
, session
->global
->session_wire_id
);
2770 SIVAL(hdr
, 0, SMB2_MAGIC
);
2771 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
2772 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
2773 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
2774 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
2775 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
2776 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
2777 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
2778 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
2779 SIVAL(hdr
, SMB2_HDR_PID
, 0);
2780 SIVAL(hdr
, SMB2_HDR_TID
, 0);
2781 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
2782 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
2784 SSVAL(body
, 0x00, body_len
);
2786 SCVAL(body
, 0x02, oplock_level
);
2787 SCVAL(body
, 0x03, 0); /* reserved */
2788 SIVAL(body
, 0x04, 0); /* reserved */
2789 SBVAL(body
, 0x08, op
->global
->open_persistent_id
);
2790 SBVAL(body
, 0x10, op
->global
->open_volatile_id
);
2792 state
->vector
[0].iov_base
= (void *)state
->buf
;
2793 state
->vector
[0].iov_len
= NBT_HDR_SIZE
;
2795 if (do_encryption
) {
2796 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= tf
;
2797 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= tf_len
;
2799 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
2800 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
2803 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
2804 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
2806 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
2807 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_len
= body_len
;
2809 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
2810 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_len
= dyn_len
;
2812 smb2_setup_nbt_length(state
->vector
, 1 + SMBD_SMB2_NUM_IOV_PER_REQ
);
2814 if (do_encryption
) {
2815 DATA_BLOB encryption_key
= session
->global
->encryption_key
;
2817 status
= smb2_signing_encrypt_pdu(encryption_key
,
2819 &state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
],
2820 SMBD_SMB2_NUM_IOV_PER_REQ
);
2821 if (!NT_STATUS_IS_OK(status
)) {
2826 state
->queue_entry
.mem_ctx
= state
;
2827 state
->queue_entry
.vector
= state
->vector
;
2828 state
->queue_entry
.count
= ARRAY_SIZE(state
->vector
);
2829 DLIST_ADD_END(state
->sconn
->smb2
.send_queue
, &state
->queue_entry
, NULL
);
2830 state
->sconn
->smb2
.send_queue_len
++;
2832 status
= smbd_smb2_io_handler(sconn
, TEVENT_FD_WRITE
);
2833 if (!NT_STATUS_IS_OK(status
)) {
2837 return NT_STATUS_OK
;
2840 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state
*state
)
2844 uint64_t file_id_persistent
;
2845 uint64_t file_id_volatile
;
2846 struct smbXsrv_open
*op
= NULL
;
2847 struct files_struct
*fsp
= NULL
;
2848 const uint8_t *body
= NULL
;
2851 * This is only called with a pktbuf
2852 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
2856 if (IVAL(state
->pktbuf
, 0) == SMB2_TF_MAGIC
) {
2857 /* Transform header. Cannot recvfile. */
2860 if (IVAL(state
->pktbuf
, 0) != SMB2_MAGIC
) {
2861 /* Not SMB2. Normal error path will cope. */
2864 if (SVAL(state
->pktbuf
, 4) != SMB2_HDR_BODY
) {
2865 /* Not SMB2. Normal error path will cope. */
2868 if (SVAL(state
->pktbuf
, SMB2_HDR_OPCODE
) != SMB2_OP_WRITE
) {
2869 /* Needs to be a WRITE. */
2872 if (IVAL(state
->pktbuf
, SMB2_HDR_NEXT_COMMAND
) != 0) {
2873 /* Chained. Cannot recvfile. */
2876 flags
= IVAL(state
->pktbuf
, SMB2_HDR_FLAGS
);
2877 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
2878 /* Chained. Cannot recvfile. */
2881 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
2882 /* Signed. Cannot recvfile. */
2886 body
= &state
->pktbuf
[SMB2_HDR_BODY
];
2888 file_id_persistent
= BVAL(body
, 0x10);
2889 file_id_volatile
= BVAL(body
, 0x18);
2891 status
= smb2srv_open_lookup(state
->req
->sconn
->conn
,
2896 if (!NT_STATUS_IS_OK(status
)) {
2904 if (fsp
->conn
== NULL
) {
2908 if (IS_IPC(fsp
->conn
)) {
2911 if (IS_PRINT(fsp
->conn
)) {
2915 DEBUG(10,("Doing recvfile write len = %u\n",
2916 (unsigned int)(state
->pktfull
- state
->pktlen
)));
2921 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
)
2923 struct smbd_smb2_request_read_state
*state
= &sconn
->smb2
.request_read_state
;
2924 size_t max_send_queue_len
;
2925 size_t cur_send_queue_len
;
2927 if (!NT_STATUS_IS_OK(sconn
->status
)) {
2929 * we're not supposed to do any io
2931 return NT_STATUS_OK
;
2934 if (state
->req
!= NULL
) {
2936 * if there is already a tstream_readv_pdu
2937 * pending, we are done.
2939 return NT_STATUS_OK
;
2942 max_send_queue_len
= MAX(1, sconn
->smb2
.max_credits
/16);
2943 cur_send_queue_len
= sconn
->smb2
.send_queue_len
;
2945 if (cur_send_queue_len
> max_send_queue_len
) {
2947 * if we have a lot of requests to send,
2948 * we wait until they are on the wire until we
2949 * ask for the next request.
2951 return NT_STATUS_OK
;
2954 /* ask for the next request */
2955 ZERO_STRUCTP(state
);
2956 state
->req
= smbd_smb2_request_allocate(sconn
);
2957 if (state
->req
== NULL
) {
2958 return NT_STATUS_NO_MEMORY
;
2960 state
->req
->sconn
= sconn
;
2961 state
->min_recv_size
= lp_min_receive_file_size();
2963 TEVENT_FD_READABLE(sconn
->smb2
.fde
);
2965 return NT_STATUS_OK
;
2968 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
2969 uint8_t *inbuf
, size_t size
)
2972 struct smbd_smb2_request
*req
= NULL
;
2974 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2975 (unsigned int)size
));
2977 status
= smbd_initialize_smb2(sconn
);
2978 if (!NT_STATUS_IS_OK(status
)) {
2979 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2983 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
2984 if (!NT_STATUS_IS_OK(status
)) {
2985 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2989 status
= smbd_smb2_request_validate(req
);
2990 if (!NT_STATUS_IS_OK(status
)) {
2991 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2995 status
= smbd_smb2_request_setup_out(req
);
2996 if (!NT_STATUS_IS_OK(status
)) {
2997 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3001 status
= smbd_smb2_request_dispatch(req
);
3002 if (!NT_STATUS_IS_OK(status
)) {
3003 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3007 status
= smbd_smb2_request_next_incoming(sconn
);
3008 if (!NT_STATUS_IS_OK(status
)) {
3009 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
3013 sconn
->num_requests
++;
3016 static int socket_error_from_errno(int ret
,
3030 if (sys_errno
== 0) {
3034 if (sys_errno
== EINTR
) {
3039 if (sys_errno
== EINPROGRESS
) {
3044 if (sys_errno
== EAGAIN
) {
3049 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3050 if (sys_errno
== ENOMEM
) {
3056 #if EWOULDBLOCK != EAGAIN
3057 if (sys_errno
== EWOULDBLOCK
) {
3067 static NTSTATUS
smbd_smb2_flush_send_queue(struct smbd_server_connection
*sconn
)
3073 if (sconn
->smb2
.send_queue
== NULL
) {
3074 TEVENT_FD_NOT_WRITEABLE(sconn
->smb2
.fde
);
3075 return NT_STATUS_OK
;
3078 while (sconn
->smb2
.send_queue
!= NULL
) {
3079 struct smbd_smb2_send_queue
*e
= sconn
->smb2
.send_queue
;
3081 if (e
->sendfile_header
!= NULL
) {
3086 for (i
=0; i
< e
->count
; i
++) {
3087 size
+= e
->vector
[i
].iov_len
;
3090 if (size
<= e
->sendfile_header
->length
) {
3091 buf
= e
->sendfile_header
->data
;
3093 buf
= talloc_array(e
->mem_ctx
, uint8_t, size
);
3095 return NT_STATUS_NO_MEMORY
;
3100 for (i
=0; i
< e
->count
; i
++) {
3102 e
->vector
[i
].iov_base
,
3103 e
->vector
[i
].iov_len
);
3104 size
+= e
->vector
[i
].iov_len
;
3107 e
->sendfile_header
->data
= buf
;
3108 e
->sendfile_header
->length
= size
;
3111 sconn
->smb2
.send_queue_len
--;
3112 DLIST_REMOVE(sconn
->smb2
.send_queue
, e
);
3114 * This triggers the sendfile path via
3117 talloc_free(e
->mem_ctx
);
3121 ret
= writev(sconn
->sock
, e
->vector
, e
->count
);
3123 /* propagate end of file */
3124 return NT_STATUS_INTERNAL_ERROR
;
3126 err
= socket_error_from_errno(ret
, errno
, &retry
);
3129 TEVENT_FD_WRITEABLE(sconn
->smb2
.fde
);
3130 return NT_STATUS_OK
;
3133 return map_nt_error_from_unix_common(err
);
3136 if (ret
< e
->vector
[0].iov_len
) {
3138 base
= (uint8_t *)e
->vector
[0].iov_base
;
3140 e
->vector
[0].iov_base
= (void *)base
;
3141 e
->vector
[0].iov_len
-= ret
;
3144 ret
-= e
->vector
[0].iov_len
;
3150 * there're maybe some empty vectors at the end
3151 * which we need to skip, otherwise we would get
3152 * ret == 0 from the readv() call and return EPIPE
3154 while (e
->count
> 0) {
3155 if (e
->vector
[0].iov_len
> 0) {
3163 /* we have more to write */
3164 TEVENT_FD_WRITEABLE(sconn
->smb2
.fde
);
3165 return NT_STATUS_OK
;
3168 sconn
->smb2
.send_queue_len
--;
3169 DLIST_REMOVE(sconn
->smb2
.send_queue
, e
);
3170 talloc_free(e
->mem_ctx
);
3173 return NT_STATUS_OK
;
3176 static NTSTATUS
smbd_smb2_io_handler(struct smbd_server_connection
*sconn
,
3179 struct smbd_smb2_request_read_state
*state
= &sconn
->smb2
.request_read_state
;
3180 struct smbd_smb2_request
*req
= NULL
;
3181 size_t min_recvfile_size
= UINT32_MAX
;
3188 if (!NT_STATUS_IS_OK(sconn
->status
)) {
3190 * we're not supposed to do any io
3192 TEVENT_FD_NOT_READABLE(sconn
->smb2
.fde
);
3193 TEVENT_FD_NOT_WRITEABLE(sconn
->smb2
.fde
);
3194 return NT_STATUS_OK
;
3197 if (fde_flags
& TEVENT_FD_WRITE
) {
3198 status
= smbd_smb2_flush_send_queue(sconn
);
3199 if (!NT_STATUS_IS_OK(status
)) {
3204 if (!(fde_flags
& TEVENT_FD_READ
)) {
3205 return NT_STATUS_OK
;
3208 if (state
->req
== NULL
) {
3209 TEVENT_FD_NOT_READABLE(sconn
->smb2
.fde
);
3210 return NT_STATUS_OK
;
3214 if (!state
->hdr
.done
) {
3215 state
->hdr
.done
= true;
3217 state
->vector
.iov_base
= (void *)state
->hdr
.nbt
;
3218 state
->vector
.iov_len
= NBT_HDR_SIZE
;
3221 ret
= readv(sconn
->sock
, &state
->vector
, 1);
3223 /* propagate end of file */
3224 return NT_STATUS_END_OF_FILE
;
3226 err
= socket_error_from_errno(ret
, errno
, &retry
);
3229 TEVENT_FD_READABLE(sconn
->smb2
.fde
);
3230 return NT_STATUS_OK
;
3233 return map_nt_error_from_unix_common(err
);
3236 if (ret
< state
->vector
.iov_len
) {
3238 base
= (uint8_t *)state
->vector
.iov_base
;
3240 state
->vector
.iov_base
= (void *)base
;
3241 state
->vector
.iov_len
-= ret
;
3242 /* we have more to read */
3243 TEVENT_FD_READABLE(sconn
->smb2
.fde
);
3244 return NT_STATUS_OK
;
3247 if (state
->pktlen
> 0) {
3248 if (state
->doing_receivefile
&& !is_smb2_recvfile_write(state
)) {
3250 * Not a possible receivefile write.
3251 * Read the rest of the data.
3253 state
->doing_receivefile
= false;
3255 state
->pktbuf
= talloc_realloc(state
->req
,
3259 if (state
->pktbuf
== NULL
) {
3260 return NT_STATUS_NO_MEMORY
;
3263 state
->vector
.iov_base
= (void *)(state
->pktbuf
+
3265 state
->vector
.iov_len
= (state
->pktfull
-
3268 state
->pktlen
= state
->pktfull
;
3273 * Either this is a receivefile write so we've
3274 * done a short read, or if not we have all the data.
3280 * Now we analyze the NBT header
3282 if (state
->hdr
.nbt
[0] != 0x00) {
3283 state
->min_recv_size
= 0;
3285 state
->pktfull
= smb2_len(state
->hdr
.nbt
);
3286 if (state
->pktfull
== 0) {
3290 if (state
->min_recv_size
!= 0) {
3291 min_recvfile_size
= SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
;
3292 min_recvfile_size
+= state
->min_recv_size
;
3295 if (state
->pktfull
> min_recvfile_size
) {
3297 * Might be a receivefile write. Read the SMB2 HEADER +
3298 * SMB2_WRITE header first. Set 'doing_receivefile'
3299 * as we're *attempting* receivefile write. If this
3300 * turns out not to be a SMB2_WRITE request or otherwise
3301 * not suitable then we'll just read the rest of the data
3302 * the next time this function is called.
3304 state
->pktlen
= SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
;
3305 state
->doing_receivefile
= true;
3307 state
->pktlen
= state
->pktfull
;
3310 state
->pktbuf
= talloc_array(state
->req
, uint8_t, state
->pktlen
);
3311 if (state
->pktbuf
== NULL
) {
3312 return NT_STATUS_NO_MEMORY
;
3315 state
->vector
.iov_base
= (void *)state
->pktbuf
;
3316 state
->vector
.iov_len
= state
->pktlen
;
3322 if (state
->hdr
.nbt
[0] != 0x00) {
3323 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3324 state
->hdr
.nbt
[0]));
3327 ZERO_STRUCTP(state
);
3329 state
->min_recv_size
= lp_min_receive_file_size();
3337 req
->request_time
= timeval_current();
3338 now
= timeval_to_nttime(&req
->request_time
);
3340 status
= smbd_smb2_inbuf_parse_compound(req
->sconn
->conn
,
3346 &req
->in
.vector_count
);
3347 if (!NT_STATUS_IS_OK(status
)) {
3351 if (state
->doing_receivefile
) {
3352 req
->smb1req
= talloc_zero(req
, struct smb_request
);
3353 if (req
->smb1req
== NULL
) {
3354 return NT_STATUS_NO_MEMORY
;
3356 req
->smb1req
->unread_bytes
= state
->pktfull
- state
->pktlen
;
3359 ZERO_STRUCTP(state
);
3361 req
->current_idx
= 1;
3363 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3364 req
->current_idx
, req
->in
.vector_count
));
3366 status
= smbd_smb2_request_validate(req
);
3367 if (!NT_STATUS_IS_OK(status
)) {
3371 status
= smbd_smb2_request_setup_out(req
);
3372 if (!NT_STATUS_IS_OK(status
)) {
3376 status
= smbd_smb2_request_dispatch(req
);
3377 if (!NT_STATUS_IS_OK(status
)) {
3381 sconn
->num_requests
++;
3383 /* The timeout_processing function isn't run nearly
3384 often enough to implement 'max log size' without
3385 overrunning the size of the file by many megabytes.
3386 This is especially true if we are running at debug
3387 level 10. Checking every 50 SMB2s is a nice
3388 tradeoff of performance vs log file size overrun. */
3390 if ((sconn
->num_requests
% 50) == 0 &&
3391 need_to_check_log_size()) {
3392 change_to_root_user();
3396 status
= smbd_smb2_request_next_incoming(sconn
);
3397 if (!NT_STATUS_IS_OK(status
)) {
3401 return NT_STATUS_OK
;
3404 static void smbd_smb2_connection_handler(struct tevent_context
*ev
,
3405 struct tevent_fd
*fde
,
3409 struct smbd_server_connection
*sconn
=
3410 talloc_get_type_abort(private_data
,
3411 struct smbd_server_connection
);
3414 status
= smbd_smb2_io_handler(sconn
, flags
);
3415 if (!NT_STATUS_IS_OK(status
)) {
3416 smbd_server_connection_terminate(sconn
, nt_errstr(status
));