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 #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9)
42 static const struct smbd_smb2_dispatch_table
{
49 bool allow_invalid_fileid
;
50 } smbd_smb2_table
[] = {
51 #define _OP(o) .opcode = o, .name = #o
56 _OP(SMB2_OP_SESSSETUP
),
66 * This call needs to be run as root.
68 * smbd_smb2_request_process_tcon()
69 * calls make_connection_snum(), which will call
70 * change_to_user(), when needed.
104 .need_session
= true,
109 .need_session
= true,
112 .allow_invalid_fileid
= true,
117 _OP(SMB2_OP_KEEPALIVE
),
121 .need_session
= true,
126 .need_session
= true,
130 _OP(SMB2_OP_GETINFO
),
131 .need_session
= true,
135 _OP(SMB2_OP_SETINFO
),
136 .need_session
= true,
141 .need_session
= true,
146 * as LEASE breaks does not
152 const char *smb2_opcode_name(uint16_t opcode
)
154 if (opcode
>= ARRAY_SIZE(smbd_smb2_table
)) {
155 return "Bad SMB2 opcode";
157 return smbd_smb2_table
[opcode
].name
;
160 static const struct smbd_smb2_dispatch_table
*smbd_smb2_call(uint16_t opcode
)
162 const struct smbd_smb2_dispatch_table
*ret
= NULL
;
164 if (opcode
>= ARRAY_SIZE(smbd_smb2_table
)) {
168 ret
= &smbd_smb2_table
[opcode
];
170 SMB_ASSERT(ret
->opcode
== opcode
);
175 static void print_req_vectors(const struct smbd_smb2_request
*req
)
179 for (i
= 0; i
< req
->in
.vector_count
; i
++) {
180 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
182 (unsigned int)req
->in
.vector
[i
].iov_len
);
184 for (i
= 0; i
< req
->out
.vector_count
; i
++) {
185 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
187 (unsigned int)req
->out
.vector
[i
].iov_len
);
191 bool smbd_is_smb2_header(const uint8_t *inbuf
, size_t size
)
193 if (size
< (4 + SMB2_HDR_BODY
)) {
197 if (IVAL(inbuf
, 4) != SMB2_MAGIC
) {
204 static NTSTATUS
smbd_initialize_smb2(struct smbd_server_connection
*sconn
)
206 TALLOC_FREE(sconn
->smb1
.fde
);
208 sconn
->smb2
.send_queue
= NULL
;
210 sconn
->smb2
.seqnum_low
= 0;
211 sconn
->smb2
.seqnum_range
= 1;
212 sconn
->smb2
.credits_granted
= 1;
213 sconn
->smb2
.max_credits
= lp_smb2_max_credits();
214 sconn
->smb2
.credits_bitmap
= bitmap_talloc(sconn
,
215 sconn
->smb2
.max_credits
);
216 if (sconn
->smb2
.credits_bitmap
== NULL
) {
217 return NT_STATUS_NO_MEMORY
;
220 sconn
->smb2
.fde
= tevent_add_fd(sconn
->ev_ctx
,
224 smbd_smb2_connection_handler
,
226 if (sconn
->smb2
.fde
== NULL
) {
227 return NT_STATUS_NO_MEMORY
;
230 /* Ensure child is set to non-blocking mode */
231 set_blocking(sconn
->sock
, false);
235 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
236 #define _smb2_setlen(_buf,len) do { \
237 uint8_t *buf = (uint8_t *)_buf; \
239 buf[1] = ((len)&0xFF0000)>>16; \
240 buf[2] = ((len)&0xFF00)>>8; \
241 buf[3] = (len)&0xFF; \
244 static void smb2_setup_nbt_length(struct iovec
*vector
, int count
)
249 for (i
=1; i
< count
; i
++) {
250 len
+= vector
[i
].iov_len
;
253 _smb2_setlen(vector
[0].iov_base
, len
);
256 static int smbd_smb2_request_destructor(struct smbd_smb2_request
*req
)
258 data_blob_clear_free(&req
->first_key
);
259 data_blob_clear_free(&req
->last_key
);
263 static struct smbd_smb2_request
*smbd_smb2_request_allocate(TALLOC_CTX
*mem_ctx
)
265 TALLOC_CTX
*mem_pool
;
266 struct smbd_smb2_request
*req
;
269 /* Enable this to find subtle valgrind errors. */
270 mem_pool
= talloc_init("smbd_smb2_request_allocate");
272 mem_pool
= talloc_pool(mem_ctx
, 8192);
274 if (mem_pool
== NULL
) {
278 req
= talloc_zero(mem_pool
, struct smbd_smb2_request
);
280 talloc_free(mem_pool
);
283 talloc_reparent(mem_pool
, mem_ctx
, req
);
284 TALLOC_FREE(mem_pool
);
286 req
->last_session_id
= UINT64_MAX
;
287 req
->last_tid
= UINT32_MAX
;
289 talloc_set_destructor(req
, smbd_smb2_request_destructor
);
294 static NTSTATUS
smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection
*conn
,
305 uint8_t *first_hdr
= buf
;
306 size_t verified_buflen
= 0;
311 * Note: index '0' is reserved for the transport protocol
313 iov
= talloc_zero_array(mem_ctx
, struct iovec
, num_iov
);
315 return NT_STATUS_NO_MEMORY
;
318 while (taken
< buflen
) {
319 size_t len
= buflen
- taken
;
320 uint8_t *hdr
= first_hdr
+ taken
;
323 size_t next_command_ofs
;
325 uint8_t *body
= NULL
;
328 struct iovec
*iov_tmp
;
330 if (verified_buflen
> taken
) {
331 len
= verified_buflen
- taken
;
338 DEBUG(10, ("%d bytes left, expected at least %d\n",
342 if (IVAL(hdr
, 0) == SMB2_TF_MAGIC
) {
343 struct smbXsrv_session
*s
= NULL
;
345 struct iovec tf_iov
[2];
349 if (conn
->protocol
< PROTOCOL_SMB2_24
) {
350 DEBUG(10, ("Got SMB2_TRANSFORM header, "
351 "but dialect[0x%04X] is used\n",
352 conn
->smb2
.server
.dialect
));
356 if (!(conn
->smb2
.server
.capabilities
& SMB2_CAP_ENCRYPTION
)) {
357 DEBUG(10, ("Got SMB2_TRANSFORM header, "
358 "but not negotiated "
359 "client[0x%08X] server[0x%08X]\n",
360 conn
->smb2
.client
.capabilities
,
361 conn
->smb2
.server
.capabilities
));
365 if (len
< SMB2_TF_HDR_SIZE
) {
366 DEBUG(1, ("%d bytes left, expected at least %d\n",
367 (int)len
, SMB2_TF_HDR_SIZE
));
371 tf_len
= SMB2_TF_HDR_SIZE
;
374 hdr
= first_hdr
+ taken
;
375 enc_len
= IVAL(tf
, SMB2_TF_MSG_SIZE
);
376 uid
= BVAL(tf
, SMB2_TF_SESSION_ID
);
378 if (len
< SMB2_TF_HDR_SIZE
+ enc_len
) {
379 DEBUG(1, ("%d bytes left, expected at least %d\n",
381 (int)(SMB2_TF_HDR_SIZE
+ enc_len
)));
385 status
= smb2srv_session_lookup(conn
, uid
, now
, &s
);
387 DEBUG(1, ("invalid session[%llu] in "
388 "SMB2_TRANSFORM header\n",
389 (unsigned long long)uid
));
391 return NT_STATUS_USER_SESSION_DELETED
;
394 tf_iov
[0].iov_base
= (void *)tf
;
395 tf_iov
[0].iov_len
= tf_len
;
396 tf_iov
[1].iov_base
= (void *)hdr
;
397 tf_iov
[1].iov_len
= enc_len
;
399 status
= smb2_signing_decrypt_pdu(s
->global
->decryption_key
,
402 if (!NT_STATUS_IS_OK(status
)) {
407 verified_buflen
= taken
+ enc_len
;
412 * We need the header plus the body length field
415 if (len
< SMB2_HDR_BODY
+ 2) {
416 DEBUG(10, ("%d bytes left, expected at least %d\n",
417 (int)len
, SMB2_HDR_BODY
));
420 if (IVAL(hdr
, 0) != SMB2_MAGIC
) {
421 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
425 if (SVAL(hdr
, 4) != SMB2_HDR_BODY
) {
426 DEBUG(10, ("Got HDR len %d, expected %d\n",
427 SVAL(hdr
, 4), SMB2_HDR_BODY
));
432 next_command_ofs
= IVAL(hdr
, SMB2_HDR_NEXT_COMMAND
);
433 body_size
= SVAL(hdr
, SMB2_HDR_BODY
);
435 if (next_command_ofs
!= 0) {
436 if (next_command_ofs
< (SMB2_HDR_BODY
+ 2)) {
439 if (next_command_ofs
> full_size
) {
442 full_size
= next_command_ofs
;
449 if (body_size
> (full_size
- SMB2_HDR_BODY
)) {
451 * let the caller handle the error
453 body_size
= full_size
- SMB2_HDR_BODY
;
455 body
= hdr
+ SMB2_HDR_BODY
;
456 dyn
= body
+ body_size
;
457 dyn_size
= full_size
- (SMB2_HDR_BODY
+ body_size
);
459 iov_tmp
= talloc_realloc(mem_ctx
, iov
, struct iovec
,
460 num_iov
+ SMBD_SMB2_NUM_IOV_PER_REQ
);
461 if (iov_tmp
== NULL
) {
463 return NT_STATUS_NO_MEMORY
;
467 num_iov
+= SMBD_SMB2_NUM_IOV_PER_REQ
;
469 cur
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= tf
;
470 cur
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= tf_len
;
471 cur
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
472 cur
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
473 cur
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
474 cur
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= body_size
;
475 cur
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
476 cur
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= dyn_size
;
487 return NT_STATUS_INVALID_PARAMETER
;
490 static NTSTATUS
smbd_smb2_request_create(struct smbd_server_connection
*sconn
,
491 uint8_t *inbuf
, size_t size
,
492 struct smbd_smb2_request
**_req
)
494 struct smbd_smb2_request
*req
;
495 uint32_t protocol_version
;
496 const uint8_t *inhdr
= NULL
;
498 uint32_t next_command_ofs
;
502 if (size
< (4 + SMB2_HDR_BODY
+ 2)) {
503 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size
));
504 return NT_STATUS_INVALID_PARAMETER
;
509 protocol_version
= IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
);
510 if (protocol_version
!= SMB2_MAGIC
) {
511 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
513 return NT_STATUS_INVALID_PARAMETER
;
516 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
517 if (cmd
!= SMB2_OP_NEGPROT
) {
518 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
520 return NT_STATUS_INVALID_PARAMETER
;
523 next_command_ofs
= IVAL(inhdr
, SMB2_HDR_NEXT_COMMAND
);
524 if (next_command_ofs
!= 0) {
525 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
527 return NT_STATUS_INVALID_PARAMETER
;
530 req
= smbd_smb2_request_allocate(sconn
);
532 return NT_STATUS_NO_MEMORY
;
536 talloc_steal(req
, inbuf
);
538 req
->request_time
= timeval_current();
539 now
= timeval_to_nttime(&req
->request_time
);
541 status
= smbd_smb2_inbuf_parse_compound(sconn
->conn
,
543 inbuf
+ NBT_HDR_SIZE
,
545 req
, &req
->in
.vector
,
546 &req
->in
.vector_count
);
547 if (!NT_STATUS_IS_OK(status
)) {
552 req
->current_idx
= 1;
558 static bool smb2_validate_sequence_number(struct smbd_server_connection
*sconn
,
559 uint64_t message_id
, uint64_t seq_id
)
561 struct bitmap
*credits_bm
= sconn
->smb2
.credits_bitmap
;
564 if (seq_id
< sconn
->smb2
.seqnum_low
) {
565 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
566 "%llu (sequence id %llu) "
567 "(granted = %u, low = %llu, range = %u)\n",
568 (unsigned long long)message_id
,
569 (unsigned long long)seq_id
,
570 (unsigned int)sconn
->smb2
.credits_granted
,
571 (unsigned long long)sconn
->smb2
.seqnum_low
,
572 (unsigned int)sconn
->smb2
.seqnum_range
));
576 if (seq_id
>= sconn
->smb2
.seqnum_low
+ sconn
->smb2
.seqnum_range
) {
577 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
578 "%llu (sequence id %llu) "
579 "(granted = %u, low = %llu, range = %u)\n",
580 (unsigned long long)message_id
,
581 (unsigned long long)seq_id
,
582 (unsigned int)sconn
->smb2
.credits_granted
,
583 (unsigned long long)sconn
->smb2
.seqnum_low
,
584 (unsigned int)sconn
->smb2
.seqnum_range
));
588 offset
= seq_id
% sconn
->smb2
.max_credits
;
590 if (bitmap_query(credits_bm
, offset
)) {
591 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
592 "%llu (sequence id %llu) "
593 "(granted = %u, low = %llu, range = %u) "
595 (unsigned long long)message_id
,
596 (unsigned long long)seq_id
,
597 (unsigned int)sconn
->smb2
.credits_granted
,
598 (unsigned long long)sconn
->smb2
.seqnum_low
,
599 (unsigned int)sconn
->smb2
.seqnum_range
,
604 /* Mark the message_ids as seen in the bitmap. */
605 bitmap_set(credits_bm
, offset
);
607 if (seq_id
!= sconn
->smb2
.seqnum_low
) {
612 * Move the window forward by all the message_id's
615 while (bitmap_query(credits_bm
, offset
)) {
616 DEBUG(10,("smb2_validate_sequence_number: clearing "
617 "id %llu (position %u) from bitmap\n",
618 (unsigned long long)(sconn
->smb2
.seqnum_low
),
620 bitmap_clear(credits_bm
, offset
);
622 sconn
->smb2
.seqnum_low
+= 1;
623 sconn
->smb2
.seqnum_range
-= 1;
624 offset
= sconn
->smb2
.seqnum_low
% sconn
->smb2
.max_credits
;
630 static bool smb2_validate_message_id(struct smbd_server_connection
*sconn
,
631 const uint8_t *inhdr
)
633 uint64_t message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
634 uint16_t opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
635 uint16_t credit_charge
= 1;
638 if (opcode
== SMB2_OP_CANCEL
) {
639 /* SMB2_CANCEL requests by definition resend messageids. */
643 if (sconn
->smb2
.supports_multicredit
) {
644 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
645 credit_charge
= MAX(credit_charge
, 1);
648 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
649 "credits_granted %llu, "
650 "seqnum low/range: %llu/%llu\n",
651 (unsigned long long) message_id
,
652 (unsigned long long) credit_charge
,
653 (unsigned long long) sconn
->smb2
.credits_granted
,
654 (unsigned long long) sconn
->smb2
.seqnum_low
,
655 (unsigned long long) sconn
->smb2
.seqnum_range
));
657 if (sconn
->smb2
.credits_granted
< credit_charge
) {
658 DEBUG(0, ("smb2_validate_message_id: client used more "
659 "credits than granted, mid %llu, charge %llu, "
660 "credits_granted %llu, "
661 "seqnum low/range: %llu/%llu\n",
662 (unsigned long long) message_id
,
663 (unsigned long long) credit_charge
,
664 (unsigned long long) sconn
->smb2
.credits_granted
,
665 (unsigned long long) sconn
->smb2
.seqnum_low
,
666 (unsigned long long) sconn
->smb2
.seqnum_range
));
671 * now check the message ids
673 * for multi-credit requests we need to check all current mid plus
674 * the implicit mids caused by the credit charge
675 * e.g. current mid = 15, charge 5 => mark 15-19 as used
678 for (i
= 0; i
<= (credit_charge
-1); i
++) {
679 uint64_t id
= message_id
+ i
;
682 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
683 (unsigned long long)message_id
,
685 (unsigned long long)id
));
687 ok
= smb2_validate_sequence_number(sconn
, message_id
, id
);
693 /* substract used credits */
694 sconn
->smb2
.credits_granted
-= credit_charge
;
699 static NTSTATUS
smbd_smb2_request_validate(struct smbd_smb2_request
*req
)
704 count
= req
->in
.vector_count
;
706 if (count
< 1 + SMBD_SMB2_NUM_IOV_PER_REQ
) {
707 /* It's not a SMB2 request */
708 return NT_STATUS_INVALID_PARAMETER
;
711 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
712 struct iovec
*hdr
= SMBD_SMB2_IDX_HDR_IOV(req
,in
,idx
);
713 struct iovec
*body
= SMBD_SMB2_IDX_BODY_IOV(req
,in
,idx
);
714 const uint8_t *inhdr
= NULL
;
716 if (hdr
->iov_len
!= SMB2_HDR_BODY
) {
717 return NT_STATUS_INVALID_PARAMETER
;
720 if (body
->iov_len
< 2) {
721 return NT_STATUS_INVALID_PARAMETER
;
724 inhdr
= (const uint8_t *)hdr
->iov_base
;
726 /* Check the SMB2 header */
727 if (IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
) != SMB2_MAGIC
) {
728 return NT_STATUS_INVALID_PARAMETER
;
731 if (!smb2_validate_message_id(req
->sconn
, inhdr
)) {
732 return NT_STATUS_INVALID_PARAMETER
;
739 static void smb2_set_operation_credit(struct smbd_server_connection
*sconn
,
740 const struct iovec
*in_vector
,
741 struct iovec
*out_vector
)
743 const uint8_t *inhdr
= (const uint8_t *)in_vector
->iov_base
;
744 uint8_t *outhdr
= (uint8_t *)out_vector
->iov_base
;
745 uint16_t credit_charge
= 1;
746 uint16_t credits_requested
;
750 uint16_t credits_granted
= 0;
751 uint64_t credits_possible
;
752 uint16_t current_max_credits
;
755 * first we grant only 1/16th of the max range.
757 * Windows also starts with the 1/16th and then grants
758 * more later. I was only able to trigger higher
759 * values, when using a very high credit charge.
761 * TODO: scale up depending on load, free memory
763 * Maybe also on the relationship between number
764 * of requests and the used sequence number.
765 * Which means we would grant more credits
766 * for client which use multi credit requests.
768 current_max_credits
= sconn
->smb2
.max_credits
/ 16;
769 current_max_credits
= MAX(current_max_credits
, 1);
771 if (sconn
->smb2
.supports_multicredit
) {
772 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
773 credit_charge
= MAX(credit_charge
, 1);
776 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
777 credits_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
778 out_flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
779 out_status
= NT_STATUS(IVAL(outhdr
, SMB2_HDR_STATUS
));
781 SMB_ASSERT(sconn
->smb2
.max_credits
>= sconn
->smb2
.credits_granted
);
783 if (sconn
->smb2
.max_credits
< credit_charge
) {
784 smbd_server_connection_terminate(sconn
,
785 "client error: credit charge > max credits\n");
789 if (out_flags
& SMB2_HDR_FLAG_ASYNC
) {
791 * In case we already send an async interim
792 * response, we should not grant
793 * credits on the final response.
796 } else if (credits_requested
> 0) {
797 uint16_t additional_max
= 0;
798 uint16_t additional_credits
= credits_requested
- 1;
801 case SMB2_OP_NEGPROT
:
803 case SMB2_OP_SESSSETUP
:
805 * Windows 2012 RC1 starts to grant
807 * with a successful session setup
809 if (NT_STATUS_IS_OK(out_status
)) {
815 * We match windows and only grant additional credits
822 additional_credits
= MIN(additional_credits
, additional_max
);
824 credits_granted
= credit_charge
+ additional_credits
;
825 } else if (sconn
->smb2
.credits_granted
== 0) {
827 * Make sure the client has always at least one credit
833 * sequence numbers should not wrap
835 * 1. calculate the possible credits until
836 * the sequence numbers start to wrap on 64-bit.
838 * 2. UINT64_MAX is used for Break Notifications.
840 * 2. truncate the possible credits to the maximum
841 * credits we want to grant to the client in total.
843 * 3. remove the range we'll already granted to the client
844 * this makes sure the client consumes the lowest sequence
845 * number, before we can grant additional credits.
847 credits_possible
= UINT64_MAX
- sconn
->smb2
.seqnum_low
;
848 if (credits_possible
> 0) {
849 /* remove UINT64_MAX */
850 credits_possible
-= 1;
852 credits_possible
= MIN(credits_possible
, current_max_credits
);
853 credits_possible
-= sconn
->smb2
.seqnum_range
;
855 credits_granted
= MIN(credits_granted
, credits_possible
);
857 SSVAL(outhdr
, SMB2_HDR_CREDIT
, credits_granted
);
858 sconn
->smb2
.credits_granted
+= credits_granted
;
859 sconn
->smb2
.seqnum_range
+= credits_granted
;
861 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
862 "granted %u, current possible/max %u/%u, "
863 "total granted/max/low/range %u/%u/%llu/%u\n",
864 (unsigned int)credits_requested
,
865 (unsigned int)credit_charge
,
866 (unsigned int)credits_granted
,
867 (unsigned int)credits_possible
,
868 (unsigned int)current_max_credits
,
869 (unsigned int)sconn
->smb2
.credits_granted
,
870 (unsigned int)sconn
->smb2
.max_credits
,
871 (unsigned long long)sconn
->smb2
.seqnum_low
,
872 (unsigned int)sconn
->smb2
.seqnum_range
));
875 static void smb2_calculate_credits(const struct smbd_smb2_request
*inreq
,
876 struct smbd_smb2_request
*outreq
)
879 uint16_t total_credits
= 0;
881 count
= outreq
->out
.vector_count
;
883 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
884 struct iovec
*inhdr_v
= SMBD_SMB2_IDX_HDR_IOV(inreq
,in
,idx
);
885 struct iovec
*outhdr_v
= SMBD_SMB2_IDX_HDR_IOV(outreq
,out
,idx
);
886 uint8_t *outhdr
= (uint8_t *)outhdr_v
->iov_base
;
888 smb2_set_operation_credit(outreq
->sconn
, inhdr_v
, outhdr_v
);
890 /* To match Windows, count up what we
892 total_credits
+= SVAL(outhdr
, SMB2_HDR_CREDIT
);
893 /* Set to zero in all but the last reply. */
894 if (idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
< count
) {
895 SSVAL(outhdr
, SMB2_HDR_CREDIT
, 0);
897 SSVAL(outhdr
, SMB2_HDR_CREDIT
, total_credits
);
902 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
)
904 struct iovec
*vector
;
908 count
= req
->in
.vector_count
;
909 vector
= talloc_zero_array(req
, struct iovec
, count
);
910 if (vector
== NULL
) {
911 return NT_STATUS_NO_MEMORY
;
914 vector
[0].iov_base
= req
->out
.nbt_hdr
;
915 vector
[0].iov_len
= 4;
916 SIVAL(req
->out
.nbt_hdr
, 0, 0);
918 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
919 struct iovec
*inhdr_v
= SMBD_SMB2_IDX_HDR_IOV(req
,in
,idx
);
920 const uint8_t *inhdr
= (const uint8_t *)inhdr_v
->iov_base
;
921 uint8_t *outhdr
= NULL
;
922 uint8_t *outbody
= NULL
;
923 uint32_t next_command_ofs
= 0;
924 struct iovec
*current
= &vector
[idx
];
926 if ((idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
) < count
) {
927 /* we have a next command -
928 * setup for the error case. */
929 next_command_ofs
= SMB2_HDR_BODY
+ 9;
932 outhdr
= talloc_zero_array(vector
, uint8_t,
934 if (outhdr
== NULL
) {
935 return NT_STATUS_NO_MEMORY
;
938 outbody
= outhdr
+ SMB2_HDR_BODY
;
941 * SMBD_SMB2_TF_IOV_OFS might be used later
943 current
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
944 current
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
946 current
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= (void *)outhdr
;
947 current
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
949 current
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= (void *)outbody
;
950 current
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= 8;
952 current
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= NULL
;
953 current
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= 0;
955 /* setup the SMB2 header */
956 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
957 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
958 SSVAL(outhdr
, SMB2_HDR_CREDIT_CHARGE
,
959 SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
));
960 SIVAL(outhdr
, SMB2_HDR_STATUS
,
961 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
962 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
963 SVAL(inhdr
, SMB2_HDR_OPCODE
));
964 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
965 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
966 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
967 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
968 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
969 SIVAL(outhdr
, SMB2_HDR_PID
,
970 IVAL(inhdr
, SMB2_HDR_PID
));
971 SIVAL(outhdr
, SMB2_HDR_TID
,
972 IVAL(inhdr
, SMB2_HDR_TID
));
973 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
974 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
975 memcpy(outhdr
+ SMB2_HDR_SIGNATURE
,
976 inhdr
+ SMB2_HDR_SIGNATURE
, 16);
978 /* setup error body header */
979 SSVAL(outbody
, 0x00, 0x08 + 1);
980 SSVAL(outbody
, 0x02, 0);
981 SIVAL(outbody
, 0x04, 0);
984 req
->out
.vector
= vector
;
985 req
->out
.vector_count
= count
;
987 /* setup the length of the NBT packet */
988 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
990 DLIST_ADD_END(req
->sconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
995 void smbd_server_connection_terminate_ex(struct smbd_server_connection
*sconn
,
997 const char *location
)
999 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1001 exit_server_cleanly(reason
);
1004 static bool dup_smb2_vec4(TALLOC_CTX
*ctx
,
1005 struct iovec
*outvec
,
1006 const struct iovec
*srcvec
)
1008 const uint8_t *srctf
;
1010 const uint8_t *srchdr
;
1012 const uint8_t *srcbody
;
1014 const uint8_t *expected_srcbody
;
1015 const uint8_t *srcdyn
;
1017 const uint8_t *expected_srcdyn
;
1023 srctf
= (const uint8_t *)srcvec
[SMBD_SMB2_TF_IOV_OFS
].iov_base
;
1024 srctf_len
= srcvec
[SMBD_SMB2_TF_IOV_OFS
].iov_len
;
1025 srchdr
= (const uint8_t *)srcvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
;
1026 srchdr_len
= srcvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
;
1027 srcbody
= (const uint8_t *)srcvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
;
1028 srcbody_len
= srcvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
;
1029 expected_srcbody
= srchdr
+ SMB2_HDR_BODY
;
1030 srcdyn
= (const uint8_t *)srcvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
;
1031 srcdyn_len
= srcvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
;
1032 expected_srcdyn
= srcbody
+ 8;
1034 if ((srctf_len
!= SMB2_TF_HDR_SIZE
) && (srctf_len
!= 0)) {
1038 if (srchdr_len
!= SMB2_HDR_BODY
) {
1042 if (srctf_len
== SMB2_TF_HDR_SIZE
) {
1043 dsttf
= talloc_memdup(ctx
, srctf
, SMB2_TF_HDR_SIZE
);
1044 if (dsttf
== NULL
) {
1050 outvec
[SMBD_SMB2_TF_IOV_OFS
].iov_base
= (void *)dsttf
;
1051 outvec
[SMBD_SMB2_TF_IOV_OFS
].iov_len
= srctf_len
;
1053 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1054 * be allocated with size OUTVEC_ALLOC_SIZE. */
1056 dsthdr
= talloc_memdup(ctx
, srchdr
, OUTVEC_ALLOC_SIZE
);
1057 if (dsthdr
== NULL
) {
1060 outvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= (void *)dsthdr
;
1061 outvec
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
1064 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1065 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1066 * then duplicate this. Else use talloc_memdup().
1069 if ((srcbody
== expected_srcbody
) && (srcbody_len
== 8)) {
1070 dstbody
= dsthdr
+ SMB2_HDR_BODY
;
1072 dstbody
= talloc_memdup(ctx
, srcbody
, srcbody_len
);
1073 if (dstbody
== NULL
) {
1077 outvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= (void *)dstbody
;
1078 outvec
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= srcbody_len
;
1081 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1083 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1084 * then duplicate this. Else use talloc_memdup().
1087 if ((srcdyn
== expected_srcdyn
) && (srcdyn_len
== 1)) {
1088 dstdyn
= dsthdr
+ SMB2_HDR_BODY
+ 8;
1089 } else if (srcdyn
== NULL
) {
1092 dstdyn
= talloc_memdup(ctx
, srcdyn
, srcdyn_len
);
1093 if (dstdyn
== NULL
) {
1097 outvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= (void *)dstdyn
;
1098 outvec
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= srcdyn_len
;
1103 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
1105 struct smbd_smb2_request
*newreq
= NULL
;
1106 struct iovec
*outvec
= NULL
;
1107 int count
= req
->out
.vector_count
;
1110 newreq
= smbd_smb2_request_allocate(req
->sconn
);
1115 newreq
->sconn
= req
->sconn
;
1116 newreq
->session
= req
->session
;
1117 newreq
->do_encryption
= req
->do_encryption
;
1118 newreq
->do_signing
= req
->do_signing
;
1119 newreq
->current_idx
= req
->current_idx
;
1121 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
1123 TALLOC_FREE(newreq
);
1126 newreq
->out
.vector
= outvec
;
1127 newreq
->out
.vector_count
= count
;
1129 /* Setup the outvec's identically to req. */
1130 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
1131 outvec
[0].iov_len
= 4;
1132 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
1134 /* Setup the vectors identically to the ones in req. */
1135 for (i
= 1; i
< count
; i
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
1136 if (!dup_smb2_vec4(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
1143 TALLOC_FREE(newreq
);
1147 smb2_setup_nbt_length(newreq
->out
.vector
,
1148 newreq
->out
.vector_count
);
1153 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
1155 struct smbd_server_connection
*sconn
= req
->sconn
;
1156 struct smbXsrv_connection
*conn
= req
->sconn
->conn
;
1158 struct iovec
*firsttf
= NULL
;
1159 struct iovec
*outhdr_v
= NULL
;
1160 uint8_t *outhdr
= NULL
;
1161 struct smbd_smb2_request
*nreq
= NULL
;
1164 /* Create a new smb2 request we'll use
1165 for the interim return. */
1166 nreq
= dup_smb2_req(req
);
1168 return NT_STATUS_NO_MEMORY
;
1171 /* Lose the last X out vectors. They're the
1172 ones we'll be using for the async reply. */
1173 nreq
->out
.vector_count
-= SMBD_SMB2_NUM_IOV_PER_REQ
;
1175 smb2_setup_nbt_length(nreq
->out
.vector
,
1176 nreq
->out
.vector_count
);
1178 /* Step back to the previous reply. */
1179 nreq
->current_idx
-= SMBD_SMB2_NUM_IOV_PER_REQ
;
1180 firsttf
= SMBD_SMB2_IDX_TF_IOV(nreq
,out
,first_idx
);
1181 outhdr_v
= SMBD_SMB2_OUT_HDR_IOV(nreq
);
1182 outhdr
= SMBD_SMB2_OUT_HDR_PTR(nreq
);
1183 /* And end the chain. */
1184 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1186 /* Calculate outgoing credits */
1187 smb2_calculate_credits(req
, nreq
);
1189 if (DEBUGLEVEL
>= 10) {
1190 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1191 (unsigned int)nreq
->current_idx
);
1192 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1193 (unsigned int)nreq
->out
.vector_count
);
1194 print_req_vectors(nreq
);
1198 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1199 * we need to sign/encrypt here with the last/first key we remembered
1201 if (firsttf
->iov_len
== SMB2_TF_HDR_SIZE
) {
1202 status
= smb2_signing_encrypt_pdu(req
->first_key
,
1205 nreq
->out
.vector_count
- first_idx
);
1206 if (!NT_STATUS_IS_OK(status
)) {
1209 } else if (req
->last_key
.length
> 0) {
1210 status
= smb2_signing_sign_pdu(req
->last_key
,
1213 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
1214 if (!NT_STATUS_IS_OK(status
)) {
1219 nreq
->queue_entry
.mem_ctx
= nreq
;
1220 nreq
->queue_entry
.vector
= nreq
->out
.vector
;
1221 nreq
->queue_entry
.count
= nreq
->out
.vector_count
;
1222 DLIST_ADD_END(nreq
->sconn
->smb2
.send_queue
, &nreq
->queue_entry
, NULL
);
1223 nreq
->sconn
->smb2
.send_queue_len
++;
1225 status
= smbd_smb2_io_handler(sconn
, TEVENT_FD_WRITE
);
1226 if (!NT_STATUS_IS_OK(status
)) {
1230 return NT_STATUS_OK
;
1233 struct smbd_smb2_request_pending_state
{
1234 struct smbd_server_connection
*sconn
;
1235 struct smbd_smb2_send_queue queue_entry
;
1236 uint8_t buf
[NBT_HDR_SIZE
+ SMB2_TF_HDR_SIZE
+ SMB2_HDR_BODY
+ 0x08 + 1];
1237 struct iovec vector
[1 + SMBD_SMB2_NUM_IOV_PER_REQ
];
1240 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
1241 struct tevent_timer
*te
,
1242 struct timeval current_time
,
1243 void *private_data
);
1245 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
1246 struct tevent_req
*subreq
,
1247 uint32_t defer_time
)
1250 struct timeval defer_endtime
;
1251 uint8_t *outhdr
= NULL
;
1254 if (!tevent_req_is_in_progress(subreq
)) {
1255 return NT_STATUS_OK
;
1258 req
->subreq
= subreq
;
1261 if (req
->async_te
) {
1262 /* We're already async. */
1263 return NT_STATUS_OK
;
1266 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1267 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1268 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1269 /* We're already async. */
1270 return NT_STATUS_OK
;
1273 if (req
->in
.vector_count
> req
->current_idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
) {
1275 * We're trying to go async in a compound
1277 * This is only allowed for opens that
1278 * cause an oplock break, otherwise it
1279 * is not allowed. See [MS-SMB2].pdf
1280 * note <194> on Section 3.3.5.2.7.
1282 const uint8_t *inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1284 if (SVAL(inhdr
, SMB2_HDR_OPCODE
) != SMB2_OP_CREATE
) {
1286 * Cancel the outstanding request.
1288 bool ok
= tevent_req_cancel(req
->subreq
);
1290 return NT_STATUS_OK
;
1292 TALLOC_FREE(req
->subreq
);
1293 return smbd_smb2_request_error(req
,
1294 NT_STATUS_INTERNAL_ERROR
);
1298 if (DEBUGLEVEL
>= 10) {
1299 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1300 (unsigned int)req
->current_idx
);
1301 print_req_vectors(req
);
1304 if (req
->current_idx
> 1) {
1306 * We're going async in a compound
1307 * chain after the first request has
1308 * already been processed. Send an
1309 * interim response containing the
1310 * set of replies already generated.
1312 int idx
= req
->current_idx
;
1314 status
= smb2_send_async_interim_response(req
);
1315 if (!NT_STATUS_IS_OK(status
)) {
1318 data_blob_clear_free(&req
->first_key
);
1320 req
->current_idx
= 1;
1323 * Re-arrange the in.vectors to remove what
1326 memmove(&req
->in
.vector
[1],
1327 &req
->in
.vector
[idx
],
1328 sizeof(req
->in
.vector
[0])*(req
->in
.vector_count
- idx
));
1329 req
->in
.vector_count
= 1 + (req
->in
.vector_count
- idx
);
1331 /* Re-arrange the out.vectors to match. */
1332 memmove(&req
->out
.vector
[1],
1333 &req
->out
.vector
[idx
],
1334 sizeof(req
->out
.vector
[0])*(req
->out
.vector_count
- idx
));
1335 req
->out
.vector_count
= 1 + (req
->out
.vector_count
- idx
);
1337 if (req
->in
.vector_count
== 1 + SMBD_SMB2_NUM_IOV_PER_REQ
) {
1339 * We only have one remaining request as
1340 * we've processed everything else.
1341 * This is no longer a compound request.
1343 req
->compound_related
= false;
1344 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1345 flags
= (IVAL(outhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
1346 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
);
1349 data_blob_clear_free(&req
->last_key
);
1351 defer_endtime
= timeval_current_ofs_usec(defer_time
);
1352 req
->async_te
= tevent_add_timer(req
->sconn
->ev_ctx
,
1354 smbd_smb2_request_pending_timer
,
1356 if (req
->async_te
== NULL
) {
1357 return NT_STATUS_NO_MEMORY
;
1360 return NT_STATUS_OK
;
1363 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
1364 struct tevent_timer
*te
,
1365 struct timeval current_time
,
1368 struct smbd_smb2_request
*req
=
1369 talloc_get_type_abort(private_data
,
1370 struct smbd_smb2_request
);
1371 struct smbd_server_connection
*sconn
= req
->sconn
;
1372 struct smbd_smb2_request_pending_state
*state
= NULL
;
1373 uint8_t *outhdr
= NULL
;
1374 const uint8_t *inhdr
= NULL
;
1377 uint8_t *hdr
= NULL
;
1378 uint8_t *body
= NULL
;
1379 uint8_t *dyn
= NULL
;
1381 uint64_t session_id
= 0;
1382 uint64_t message_id
= 0;
1383 uint64_t nonce_high
= 0;
1384 uint64_t nonce_low
= 0;
1385 uint64_t async_id
= 0;
1388 TALLOC_FREE(req
->async_te
);
1390 /* Ensure our final reply matches the interim one. */
1391 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1392 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1393 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1394 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1395 session_id
= BVAL(outhdr
, SMB2_HDR_SESSION_ID
);
1397 async_id
= message_id
; /* keep it simple for now... */
1399 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1400 SBVAL(outhdr
, SMB2_HDR_ASYNC_ID
, async_id
);
1402 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1404 smb2_opcode_name(SVAL(inhdr
, SMB2_HDR_OPCODE
)),
1405 (unsigned long long)async_id
));
1408 * What we send is identical to a smbd_smb2_request_error
1409 * packet with an error status of STATUS_PENDING. Make use
1410 * of this fact sometime when refactoring. JRA.
1413 state
= talloc_zero(req
->sconn
, struct smbd_smb2_request_pending_state
);
1414 if (state
== NULL
) {
1415 smbd_server_connection_terminate(req
->sconn
,
1416 nt_errstr(NT_STATUS_NO_MEMORY
));
1419 state
->sconn
= req
->sconn
;
1421 tf
= state
->buf
+ NBT_HDR_SIZE
;
1422 tf_len
= SMB2_TF_HDR_SIZE
;
1424 hdr
= tf
+ SMB2_TF_HDR_SIZE
;
1425 body
= hdr
+ SMB2_HDR_BODY
;
1428 if (req
->do_encryption
) {
1429 struct smbXsrv_session
*x
= req
->session
;
1431 nonce_high
= x
->nonce_high
;
1432 nonce_low
= x
->nonce_low
;
1435 if (x
->nonce_low
== 0) {
1441 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
1442 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
1443 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
1444 SBVAL(tf
, SMB2_TF_SESSION_ID
, session_id
);
1446 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
1447 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1448 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1449 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
1450 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(outhdr
, SMB2_HDR_OPCODE
));
1452 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
);
1453 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1454 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
1455 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
1456 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
1457 BVAL(outhdr
, SMB2_HDR_SESSION_ID
));
1458 memcpy(hdr
+SMB2_HDR_SIGNATURE
,
1459 outhdr
+SMB2_HDR_SIGNATURE
, 16);
1461 SSVAL(body
, 0x00, 0x08 + 1);
1463 SCVAL(body
, 0x02, 0);
1464 SCVAL(body
, 0x03, 0);
1465 SIVAL(body
, 0x04, 0);
1466 /* Match W2K8R2... */
1467 SCVAL(dyn
, 0x00, 0x21);
1469 state
->vector
[0].iov_base
= (void *)state
->buf
;
1470 state
->vector
[0].iov_len
= NBT_HDR_SIZE
;
1472 if (req
->do_encryption
) {
1473 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= tf
;
1474 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= tf_len
;
1476 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
1477 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
1480 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
1481 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
1483 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
1484 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_len
= 8;
1486 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
1487 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_len
= 1;
1489 smb2_setup_nbt_length(state
->vector
, 1 + SMBD_SMB2_NUM_IOV_PER_REQ
);
1491 /* Ensure we correctly go through crediting. Grant
1492 the credits now, and zero credits on the final
1494 smb2_set_operation_credit(req
->sconn
,
1495 SMBD_SMB2_IN_HDR_IOV(req
),
1496 &state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
]);
1498 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1503 for (i
= 0; i
< ARRAY_SIZE(state
->vector
); i
++) {
1504 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1506 (unsigned int)ARRAY_SIZE(state
->vector
),
1507 (unsigned int)state
->vector
[i
].iov_len
);
1511 if (req
->do_encryption
) {
1512 struct smbXsrv_session
*x
= req
->session
;
1513 struct smbXsrv_connection
*conn
= x
->connection
;
1514 DATA_BLOB encryption_key
= x
->global
->encryption_key
;
1516 status
= smb2_signing_encrypt_pdu(encryption_key
,
1518 &state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
],
1519 SMBD_SMB2_NUM_IOV_PER_REQ
);
1520 if (!NT_STATUS_IS_OK(status
)) {
1521 smbd_server_connection_terminate(req
->sconn
,
1525 } else if (req
->do_signing
) {
1526 struct smbXsrv_session
*x
= req
->session
;
1527 struct smbXsrv_connection
*conn
= x
->connection
;
1528 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
1530 status
= smb2_signing_sign_pdu(signing_key
,
1532 &state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
],
1533 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
1534 if (!NT_STATUS_IS_OK(status
)) {
1535 smbd_server_connection_terminate(req
->sconn
,
1541 state
->queue_entry
.mem_ctx
= state
;
1542 state
->queue_entry
.vector
= state
->vector
;
1543 state
->queue_entry
.count
= ARRAY_SIZE(state
->vector
);
1544 DLIST_ADD_END(sconn
->smb2
.send_queue
, &state
->queue_entry
, NULL
);
1545 sconn
->smb2
.send_queue_len
++;
1547 status
= smbd_smb2_io_handler(sconn
, TEVENT_FD_WRITE
);
1548 if (!NT_STATUS_IS_OK(status
)) {
1549 smbd_server_connection_terminate(sconn
,
1555 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
1557 struct smbd_server_connection
*sconn
= req
->sconn
;
1558 struct smbd_smb2_request
*cur
;
1559 const uint8_t *inhdr
;
1561 uint64_t search_message_id
;
1562 uint64_t search_async_id
;
1565 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1567 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1568 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1569 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
1572 * we don't need the request anymore
1573 * cancel requests never have a response
1575 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1578 for (cur
= sconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
1579 const uint8_t *outhdr
;
1580 uint64_t message_id
;
1583 if (cur
->compound_related
) {
1585 * Never cancel anything in a compound request.
1586 * Way too hard to deal with the result.
1591 outhdr
= SMBD_SMB2_OUT_HDR_PTR(cur
);
1593 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1594 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
1596 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1597 if (search_async_id
== async_id
) {
1598 found_id
= async_id
;
1602 if (search_message_id
== message_id
) {
1603 found_id
= message_id
;
1609 if (cur
&& cur
->subreq
) {
1610 inhdr
= SMBD_SMB2_IN_HDR_PTR(cur
);
1611 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1612 "cancel opcode[%s] mid %llu\n",
1613 smb2_opcode_name(SVAL(inhdr
, SMB2_HDR_OPCODE
)),
1614 (unsigned long long)found_id
));
1615 tevent_req_cancel(cur
->subreq
);
1618 return NT_STATUS_OK
;
1621 /*************************************************************
1622 Ensure an incoming tid is a valid one for us to access.
1623 Change to the associated uid credentials and chdir to the
1624 valid tid directory.
1625 *************************************************************/
1627 static NTSTATUS
smbd_smb2_request_check_tcon(struct smbd_smb2_request
*req
)
1629 const uint8_t *inhdr
;
1632 struct smbXsrv_tcon
*tcon
;
1634 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1638 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1640 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1641 in_tid
= IVAL(inhdr
, SMB2_HDR_TID
);
1643 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1644 in_tid
= req
->last_tid
;
1649 status
= smb2srv_tcon_lookup(req
->session
,
1650 in_tid
, now
, &tcon
);
1651 if (!NT_STATUS_IS_OK(status
)) {
1655 if (!change_to_user(tcon
->compat
, req
->session
->compat
->vuid
)) {
1656 return NT_STATUS_ACCESS_DENIED
;
1659 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1660 if (!set_current_service(tcon
->compat
, 0, true)) {
1661 return NT_STATUS_ACCESS_DENIED
;
1665 req
->last_tid
= in_tid
;
1667 return NT_STATUS_OK
;
1670 /*************************************************************
1671 Ensure an incoming session_id is a valid one for us to access.
1672 *************************************************************/
1674 static NTSTATUS
smbd_smb2_request_check_session(struct smbd_smb2_request
*req
)
1676 const uint8_t *inhdr
;
1679 uint64_t in_session_id
;
1680 struct smbXsrv_session
*session
= NULL
;
1681 struct auth_session_info
*session_info
;
1683 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1685 req
->session
= NULL
;
1688 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1690 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1691 in_opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1692 in_session_id
= BVAL(inhdr
, SMB2_HDR_SESSION_ID
);
1694 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1695 in_session_id
= req
->last_session_id
;
1698 req
->last_session_id
= 0;
1700 /* lookup an existing session */
1701 status
= smb2srv_session_lookup(req
->sconn
->conn
,
1705 req
->session
= session
;
1706 req
->last_session_id
= in_session_id
;
1708 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
1709 switch (in_opcode
) {
1710 case SMB2_OP_SESSSETUP
:
1711 status
= NT_STATUS_OK
;
1717 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1718 switch (in_opcode
) {
1720 case SMB2_OP_CREATE
:
1721 case SMB2_OP_GETINFO
:
1722 case SMB2_OP_SETINFO
:
1723 return NT_STATUS_INVALID_HANDLE
;
1726 * Notice the check for
1727 * (session_info == NULL)
1730 status
= NT_STATUS_OK
;
1734 if (!NT_STATUS_IS_OK(status
)) {
1738 session_info
= session
->global
->auth_session_info
;
1739 if (session_info
== NULL
) {
1740 return NT_STATUS_INVALID_HANDLE
;
1743 set_current_user_info(session_info
->unix_info
->sanitized_username
,
1744 session_info
->unix_info
->unix_name
,
1745 session_info
->info
->domain_name
);
1747 return NT_STATUS_OK
;
1750 NTSTATUS
smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request
*req
,
1751 uint32_t data_length
)
1753 uint16_t needed_charge
;
1754 uint16_t credit_charge
= 1;
1755 const uint8_t *inhdr
;
1757 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1759 if (req
->sconn
->smb2
.supports_multicredit
) {
1760 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
1761 credit_charge
= MAX(credit_charge
, 1);
1764 needed_charge
= (data_length
- 1)/ 65536 + 1;
1766 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1767 (unsigned long long) BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
),
1768 credit_charge
, needed_charge
));
1770 if (needed_charge
> credit_charge
) {
1771 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1772 credit_charge
, needed_charge
));
1773 return NT_STATUS_INVALID_PARAMETER
;
1776 return NT_STATUS_OK
;
1779 NTSTATUS
smbd_smb2_request_verify_sizes(struct smbd_smb2_request
*req
,
1780 size_t expected_body_size
)
1782 struct iovec
*inhdr_v
;
1783 const uint8_t *inhdr
;
1785 const uint8_t *inbody
;
1787 size_t min_dyn_size
= expected_body_size
& 0x00000001;
1788 int max_idx
= req
->in
.vector_count
- SMBD_SMB2_NUM_IOV_PER_REQ
;
1791 * The following should be checked already.
1793 if (req
->in
.vector_count
< SMBD_SMB2_NUM_IOV_PER_REQ
) {
1794 return NT_STATUS_INTERNAL_ERROR
;
1796 if (req
->current_idx
> max_idx
) {
1797 return NT_STATUS_INTERNAL_ERROR
;
1800 inhdr_v
= SMBD_SMB2_IN_HDR_IOV(req
);
1801 if (inhdr_v
->iov_len
!= SMB2_HDR_BODY
) {
1802 return NT_STATUS_INTERNAL_ERROR
;
1804 if (SMBD_SMB2_IN_BODY_LEN(req
) < 2) {
1805 return NT_STATUS_INTERNAL_ERROR
;
1808 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1809 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1813 case SMB2_OP_GETINFO
:
1819 * Now check the expected body size,
1820 * where the last byte might be in the
1823 if (SMBD_SMB2_IN_BODY_LEN(req
) != (expected_body_size
& 0xFFFFFFFE)) {
1824 return NT_STATUS_INVALID_PARAMETER
;
1826 if (SMBD_SMB2_IN_DYN_LEN(req
) < min_dyn_size
) {
1827 return NT_STATUS_INVALID_PARAMETER
;
1830 inbody
= SMBD_SMB2_IN_BODY_PTR(req
);
1832 body_size
= SVAL(inbody
, 0x00);
1833 if (body_size
!= expected_body_size
) {
1834 return NT_STATUS_INVALID_PARAMETER
;
1837 return NT_STATUS_OK
;
1840 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
1842 struct smbXsrv_connection
*conn
= req
->sconn
->conn
;
1843 const struct smbd_smb2_dispatch_table
*call
= NULL
;
1844 const struct iovec
*intf_v
= SMBD_SMB2_IN_TF_IOV(req
);
1845 const uint8_t *inhdr
;
1850 NTSTATUS session_status
;
1851 uint32_t allowed_flags
;
1852 NTSTATUS return_value
;
1853 struct smbXsrv_session
*x
= NULL
;
1854 bool signing_required
= false;
1855 bool encryption_required
= false;
1857 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1859 /* TODO: verify more things */
1861 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1862 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1863 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1864 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1865 smb2_opcode_name(opcode
),
1866 (unsigned long long)mid
));
1868 if (conn
->protocol
>= PROTOCOL_SMB2_02
) {
1870 * once the protocol is negotiated
1871 * SMB2_OP_NEGPROT is not allowed anymore
1873 if (opcode
== SMB2_OP_NEGPROT
) {
1874 /* drop the connection */
1875 return NT_STATUS_INVALID_PARAMETER
;
1879 * if the protocol is not negotiated yet
1880 * only SMB2_OP_NEGPROT is allowed.
1882 if (opcode
!= SMB2_OP_NEGPROT
) {
1883 /* drop the connection */
1884 return NT_STATUS_INVALID_PARAMETER
;
1889 * Check if the client provided a valid session id,
1890 * if so smbd_smb2_request_check_session() calls
1891 * set_current_user_info().
1893 * As some command don't require a valid session id
1894 * we defer the check of the session_status
1896 session_status
= smbd_smb2_request_check_session(req
);
1899 signing_required
= x
->global
->signing_required
;
1900 encryption_required
= x
->global
->encryption_required
;
1902 if (opcode
== SMB2_OP_SESSSETUP
&&
1903 x
->global
->channels
[0].signing_key
.length
) {
1904 signing_required
= true;
1908 req
->do_signing
= false;
1909 req
->do_encryption
= false;
1910 if (intf_v
->iov_len
== SMB2_TF_HDR_SIZE
) {
1911 const uint8_t *intf
= SMBD_SMB2_IN_TF_PTR(req
);
1912 uint64_t tf_session_id
= BVAL(intf
, SMB2_TF_SESSION_ID
);
1914 if (x
!= NULL
&& x
->global
->session_wire_id
!= tf_session_id
) {
1915 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1916 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1917 (unsigned long long)x
->global
->session_wire_id
,
1918 (unsigned long long)tf_session_id
));
1920 * TODO: windows allows this...
1921 * should we drop the connection?
1923 * For now we just return ACCESS_DENIED
1924 * (Windows clients never trigger this)
1925 * and wait for an update of [MS-SMB2].
1927 return smbd_smb2_request_error(req
,
1928 NT_STATUS_ACCESS_DENIED
);
1931 req
->do_encryption
= true;
1934 if (encryption_required
&& !req
->do_encryption
) {
1935 return smbd_smb2_request_error(req
,
1936 NT_STATUS_ACCESS_DENIED
);
1939 call
= smbd_smb2_call(opcode
);
1941 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1944 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
1945 SMB2_HDR_FLAG_SIGNED
|
1947 if (opcode
== SMB2_OP_CANCEL
) {
1948 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
1950 if ((flags
& ~allowed_flags
) != 0) {
1951 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1954 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
1956 * This check is mostly for giving the correct error code
1957 * for compounded requests.
1959 if (!NT_STATUS_IS_OK(session_status
)) {
1960 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1963 req
->compat_chain_fsp
= NULL
;
1966 if (req
->do_encryption
) {
1967 signing_required
= false;
1968 } else if (flags
& SMB2_HDR_FLAG_SIGNED
) {
1969 DATA_BLOB signing_key
;
1972 return smbd_smb2_request_error(
1973 req
, NT_STATUS_ACCESS_DENIED
);
1976 signing_key
= x
->global
->channels
[0].signing_key
;
1979 * If we have a signing key, we should
1982 if (signing_key
.length
> 0) {
1983 req
->do_signing
= true;
1986 status
= smb2_signing_check_pdu(signing_key
,
1988 SMBD_SMB2_IN_HDR_IOV(req
),
1989 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
1990 if (!NT_STATUS_IS_OK(status
)) {
1991 return smbd_smb2_request_error(req
, status
);
1995 * Now that we know the request was correctly signed
1996 * we have to sign the response too.
1998 req
->do_signing
= true;
2000 if (!NT_STATUS_IS_OK(session_status
)) {
2001 return smbd_smb2_request_error(req
, session_status
);
2003 } else if (opcode
== SMB2_OP_CANCEL
) {
2004 /* Cancel requests are allowed to skip the signing */
2005 } else if (signing_required
) {
2007 * If signing is required we try to sign
2008 * a possible error response
2010 req
->do_signing
= true;
2011 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
2014 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
2015 req
->compound_related
= true;
2018 if (call
->need_session
) {
2019 if (!NT_STATUS_IS_OK(session_status
)) {
2020 return smbd_smb2_request_error(req
, session_status
);
2024 if (call
->need_tcon
) {
2025 SMB_ASSERT(call
->need_session
);
2028 * This call needs to be run as user.
2030 * smbd_smb2_request_check_tcon()
2031 * calls change_to_user() on success.
2033 status
= smbd_smb2_request_check_tcon(req
);
2034 if (!NT_STATUS_IS_OK(status
)) {
2035 return smbd_smb2_request_error(req
, status
);
2037 if (req
->tcon
->global
->encryption_required
) {
2038 encryption_required
= true;
2040 if (encryption_required
&& !req
->do_encryption
) {
2041 return smbd_smb2_request_error(req
,
2042 NT_STATUS_ACCESS_DENIED
);
2046 if (call
->fileid_ofs
!= 0) {
2047 size_t needed
= call
->fileid_ofs
+ 16;
2048 const uint8_t *body
= SMBD_SMB2_IN_BODY_PTR(req
);
2049 size_t body_size
= SMBD_SMB2_IN_BODY_LEN(req
);
2050 uint64_t file_id_persistent
;
2051 uint64_t file_id_volatile
;
2052 struct files_struct
*fsp
;
2054 SMB_ASSERT(call
->need_tcon
);
2056 if (needed
> body_size
) {
2057 return smbd_smb2_request_error(req
,
2058 NT_STATUS_INVALID_PARAMETER
);
2061 file_id_persistent
= BVAL(body
, call
->fileid_ofs
+ 0);
2062 file_id_volatile
= BVAL(body
, call
->fileid_ofs
+ 8);
2064 fsp
= file_fsp_smb2(req
, file_id_persistent
, file_id_volatile
);
2066 if (!call
->allow_invalid_fileid
) {
2067 return smbd_smb2_request_error(req
,
2068 NT_STATUS_FILE_CLOSED
);
2071 if (file_id_persistent
!= UINT64_MAX
) {
2072 return smbd_smb2_request_error(req
,
2073 NT_STATUS_FILE_CLOSED
);
2075 if (file_id_volatile
!= UINT64_MAX
) {
2076 return smbd_smb2_request_error(req
,
2077 NT_STATUS_FILE_CLOSED
);
2082 if (call
->as_root
) {
2083 SMB_ASSERT(call
->fileid_ofs
== 0);
2084 /* This call needs to be run as root */
2085 change_to_root_user();
2087 SMB_ASSERT(call
->need_tcon
);
2091 case SMB2_OP_NEGPROT
:
2093 START_PROFILE(smb2_negprot
);
2094 return_value
= smbd_smb2_request_process_negprot(req
);
2095 END_PROFILE(smb2_negprot
);
2099 case SMB2_OP_SESSSETUP
:
2101 START_PROFILE(smb2_sesssetup
);
2102 return_value
= smbd_smb2_request_process_sesssetup(req
);
2103 END_PROFILE(smb2_sesssetup
);
2107 case SMB2_OP_LOGOFF
:
2109 START_PROFILE(smb2_logoff
);
2110 return_value
= smbd_smb2_request_process_logoff(req
);
2111 END_PROFILE(smb2_logoff
);
2117 START_PROFILE(smb2_tcon
);
2118 return_value
= smbd_smb2_request_process_tcon(req
);
2119 END_PROFILE(smb2_tcon
);
2125 START_PROFILE(smb2_tdis
);
2126 return_value
= smbd_smb2_request_process_tdis(req
);
2127 END_PROFILE(smb2_tdis
);
2131 case SMB2_OP_CREATE
:
2133 START_PROFILE(smb2_create
);
2134 return_value
= smbd_smb2_request_process_create(req
);
2135 END_PROFILE(smb2_create
);
2141 START_PROFILE(smb2_close
);
2142 return_value
= smbd_smb2_request_process_close(req
);
2143 END_PROFILE(smb2_close
);
2149 START_PROFILE(smb2_flush
);
2150 return_value
= smbd_smb2_request_process_flush(req
);
2151 END_PROFILE(smb2_flush
);
2157 START_PROFILE(smb2_read
);
2158 return_value
= smbd_smb2_request_process_read(req
);
2159 END_PROFILE(smb2_read
);
2165 START_PROFILE(smb2_write
);
2166 return_value
= smbd_smb2_request_process_write(req
);
2167 END_PROFILE(smb2_write
);
2173 START_PROFILE(smb2_lock
);
2174 return_value
= smbd_smb2_request_process_lock(req
);
2175 END_PROFILE(smb2_lock
);
2181 START_PROFILE(smb2_ioctl
);
2182 return_value
= smbd_smb2_request_process_ioctl(req
);
2183 END_PROFILE(smb2_ioctl
);
2187 case SMB2_OP_CANCEL
:
2189 START_PROFILE(smb2_cancel
);
2190 return_value
= smbd_smb2_request_process_cancel(req
);
2191 END_PROFILE(smb2_cancel
);
2195 case SMB2_OP_KEEPALIVE
:
2197 START_PROFILE(smb2_keepalive
);
2198 return_value
= smbd_smb2_request_process_keepalive(req
);
2199 END_PROFILE(smb2_keepalive
);
2205 START_PROFILE(smb2_find
);
2206 return_value
= smbd_smb2_request_process_find(req
);
2207 END_PROFILE(smb2_find
);
2211 case SMB2_OP_NOTIFY
:
2213 START_PROFILE(smb2_notify
);
2214 return_value
= smbd_smb2_request_process_notify(req
);
2215 END_PROFILE(smb2_notify
);
2219 case SMB2_OP_GETINFO
:
2221 START_PROFILE(smb2_getinfo
);
2222 return_value
= smbd_smb2_request_process_getinfo(req
);
2223 END_PROFILE(smb2_getinfo
);
2227 case SMB2_OP_SETINFO
:
2229 START_PROFILE(smb2_setinfo
);
2230 return_value
= smbd_smb2_request_process_setinfo(req
);
2231 END_PROFILE(smb2_setinfo
);
2237 START_PROFILE(smb2_break
);
2238 return_value
= smbd_smb2_request_process_break(req
);
2239 END_PROFILE(smb2_break
);
2244 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2247 return return_value
;
2250 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
2252 struct smbd_server_connection
*sconn
= req
->sconn
;
2253 struct smbXsrv_connection
*conn
= req
->sconn
->conn
;
2255 struct iovec
*firsttf
= SMBD_SMB2_IDX_TF_IOV(req
,out
,first_idx
);
2256 struct iovec
*outhdr
= SMBD_SMB2_OUT_HDR_IOV(req
);
2257 struct iovec
*outdyn
= SMBD_SMB2_OUT_DYN_IOV(req
);
2261 TALLOC_FREE(req
->async_te
);
2263 if (req
->do_encryption
&&
2264 (firsttf
->iov_len
== 0) &&
2265 (req
->first_key
.length
== 0) &&
2266 (req
->session
!= NULL
) &&
2267 (req
->session
->global
->encryption_key
.length
!= 0))
2269 DATA_BLOB encryption_key
= req
->session
->global
->encryption_key
;
2271 uint64_t session_id
= req
->session
->global
->session_wire_id
;
2272 struct smbXsrv_session
*x
= req
->session
;
2273 uint64_t nonce_high
;
2276 nonce_high
= x
->nonce_high
;
2277 nonce_low
= x
->nonce_low
;
2280 if (x
->nonce_low
== 0) {
2286 * We need to place the SMB2_TRANSFORM header before the
2291 * we need to remember the encryption key
2292 * and defer the signing/encryption until
2293 * we are sure that we do not change
2296 req
->first_key
= data_blob_dup_talloc(req
, encryption_key
);
2297 if (req
->first_key
.data
== NULL
) {
2298 return NT_STATUS_NO_MEMORY
;
2301 tf
= talloc_zero_array(req
->out
.vector
, uint8_t,
2304 return NT_STATUS_NO_MEMORY
;
2307 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
2308 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
2309 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
2310 SBVAL(tf
, SMB2_TF_SESSION_ID
, session_id
);
2312 firsttf
->iov_base
= (void *)tf
;
2313 firsttf
->iov_len
= SMB2_TF_HDR_SIZE
;
2316 if ((req
->current_idx
> SMBD_SMB2_NUM_IOV_PER_REQ
) &&
2317 (req
->last_key
.length
> 0) &&
2318 (firsttf
->iov_len
== 0))
2320 int last_idx
= req
->current_idx
- SMBD_SMB2_NUM_IOV_PER_REQ
;
2321 struct iovec
*lasthdr
= SMBD_SMB2_IDX_HDR_IOV(req
,out
,last_idx
);
2324 * As we are sure the header of the last request in the
2325 * compound chain will not change, we can to sign here
2326 * with the last signing key we remembered.
2328 status
= smb2_signing_sign_pdu(req
->last_key
,
2331 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2332 if (!NT_STATUS_IS_OK(status
)) {
2336 data_blob_clear_free(&req
->last_key
);
2338 req
->current_idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
;
2340 if (req
->current_idx
< req
->out
.vector_count
) {
2342 * We must process the remaining compound
2343 * SMB2 requests before any new incoming SMB2
2344 * requests. This is because incoming SMB2
2345 * requests may include a cancel for a
2346 * compound request we haven't processed
2349 struct tevent_immediate
*im
= tevent_create_immediate(req
);
2351 return NT_STATUS_NO_MEMORY
;
2354 if (req
->do_signing
&& firsttf
->iov_len
== 0) {
2355 struct smbXsrv_session
*x
= req
->session
;
2356 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
2359 * we need to remember the signing key
2360 * and defer the signing until
2361 * we are sure that we do not change
2364 req
->last_key
= data_blob_dup_talloc(req
, signing_key
);
2365 if (req
->last_key
.data
== NULL
) {
2366 return NT_STATUS_NO_MEMORY
;
2370 tevent_schedule_immediate(im
,
2372 smbd_smb2_request_dispatch_immediate
,
2374 return NT_STATUS_OK
;
2377 if (req
->compound_related
) {
2378 req
->compound_related
= false;
2381 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
2383 /* Set credit for these operations (zero credits if this
2384 is a final reply for an async operation). */
2385 smb2_calculate_credits(req
, req
);
2388 * now check if we need to sign the current response
2390 if (firsttf
->iov_len
== SMB2_TF_HDR_SIZE
) {
2391 status
= smb2_signing_encrypt_pdu(req
->first_key
,
2394 req
->out
.vector_count
- first_idx
);
2395 if (!NT_STATUS_IS_OK(status
)) {
2398 } else if (req
->do_signing
) {
2399 struct smbXsrv_session
*x
= req
->session
;
2400 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
2402 status
= smb2_signing_sign_pdu(signing_key
,
2405 SMBD_SMB2_NUM_IOV_PER_REQ
- 1);
2406 if (!NT_STATUS_IS_OK(status
)) {
2410 data_blob_clear_free(&req
->first_key
);
2412 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2413 if (req
->out
.vector_count
< (2*SMBD_SMB2_NUM_IOV_PER_REQ
) &&
2414 outdyn
->iov_base
== NULL
&& outdyn
->iov_len
!= 0) {
2415 /* Dynamic part is NULL. Chop it off,
2416 We're going to send it via sendfile. */
2417 req
->out
.vector_count
-= 1;
2421 * We're done with this request -
2422 * move it off the "being processed" queue.
2424 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
2426 req
->queue_entry
.mem_ctx
= req
;
2427 req
->queue_entry
.vector
= req
->out
.vector
;
2428 req
->queue_entry
.count
= req
->out
.vector_count
;
2429 DLIST_ADD_END(req
->sconn
->smb2
.send_queue
, &req
->queue_entry
, NULL
);
2430 req
->sconn
->smb2
.send_queue_len
++;
2432 status
= smbd_smb2_io_handler(sconn
, TEVENT_FD_WRITE
);
2433 if (!NT_STATUS_IS_OK(status
)) {
2437 return NT_STATUS_OK
;
2440 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
);
2442 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
2443 struct tevent_immediate
*im
,
2446 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
2447 struct smbd_smb2_request
);
2448 struct smbd_server_connection
*sconn
= req
->sconn
;
2453 if (DEBUGLEVEL
>= 10) {
2454 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2455 req
->current_idx
, req
->in
.vector_count
));
2456 print_req_vectors(req
);
2459 status
= smbd_smb2_request_dispatch(req
);
2460 if (!NT_STATUS_IS_OK(status
)) {
2461 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2465 status
= smbd_smb2_request_next_incoming(sconn
);
2466 if (!NT_STATUS_IS_OK(status
)) {
2467 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2472 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
2474 DATA_BLOB body
, DATA_BLOB
*dyn
,
2475 const char *location
)
2478 struct iovec
*outbody_v
;
2479 struct iovec
*outdyn_v
;
2480 uint32_t next_command_ofs
;
2482 DEBUG(10,("smbd_smb2_request_done_ex: "
2483 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2484 req
->current_idx
, nt_errstr(status
), (unsigned int)body
.length
,
2486 (unsigned int)(dyn
? dyn
->length
: 0),
2489 if (body
.length
< 2) {
2490 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2493 if ((body
.length
% 2) != 0) {
2494 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2497 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
2498 outbody_v
= SMBD_SMB2_OUT_BODY_IOV(req
);
2499 outdyn_v
= SMBD_SMB2_OUT_DYN_IOV(req
);
2501 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
2502 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
2504 outbody_v
->iov_base
= (void *)body
.data
;
2505 outbody_v
->iov_len
= body
.length
;
2508 outdyn_v
->iov_base
= (void *)dyn
->data
;
2509 outdyn_v
->iov_len
= dyn
->length
;
2511 outdyn_v
->iov_base
= NULL
;
2512 outdyn_v
->iov_len
= 0;
2515 /* see if we need to recalculate the offset to the next response */
2516 if (next_command_ofs
> 0) {
2517 next_command_ofs
= SMB2_HDR_BODY
;
2518 next_command_ofs
+= SMBD_SMB2_OUT_BODY_LEN(req
);
2519 next_command_ofs
+= SMBD_SMB2_OUT_DYN_LEN(req
);
2522 if ((next_command_ofs
% 8) != 0) {
2523 size_t pad_size
= 8 - (next_command_ofs
% 8);
2524 if (SMBD_SMB2_OUT_DYN_LEN(req
) == 0) {
2526 * if the dyn buffer is empty
2527 * we can use it to add padding
2531 pad
= talloc_zero_array(req
->out
.vector
,
2534 return smbd_smb2_request_error(req
,
2535 NT_STATUS_NO_MEMORY
);
2538 outdyn_v
->iov_base
= (void *)pad
;
2539 outdyn_v
->iov_len
= pad_size
;
2542 * For now we copy the dynamic buffer
2543 * and add the padding to the new buffer
2550 old_size
= SMBD_SMB2_OUT_DYN_LEN(req
);
2551 old_dyn
= SMBD_SMB2_OUT_DYN_PTR(req
);
2553 new_size
= old_size
+ pad_size
;
2554 new_dyn
= talloc_zero_array(req
->out
.vector
,
2556 if (new_dyn
== NULL
) {
2557 return smbd_smb2_request_error(req
,
2558 NT_STATUS_NO_MEMORY
);
2561 memcpy(new_dyn
, old_dyn
, old_size
);
2562 memset(new_dyn
+ old_size
, 0, pad_size
);
2564 outdyn_v
->iov_base
= (void *)new_dyn
;
2565 outdyn_v
->iov_len
= new_size
;
2567 next_command_ofs
+= pad_size
;
2570 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
2572 return smbd_smb2_request_reply(req
);
2575 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
2578 const char *location
)
2581 uint8_t *outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
2582 size_t unread_bytes
= smbd_smb2_unread_bytes(req
);
2584 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2585 req
->current_idx
, nt_errstr(status
), info
? " +info" : "",
2589 /* Recvfile error. Drain incoming socket. */
2593 ret
= drain_socket(req
->sconn
->sock
, unread_bytes
);
2594 if (ret
!= unread_bytes
) {
2598 error
= NT_STATUS_IO_DEVICE_ERROR
;
2600 error
= map_nt_error_from_unix_common(errno
);
2603 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2604 "ret[%u] errno[%d] => %s\n",
2605 (unsigned)unread_bytes
,
2606 (unsigned)ret
, errno
, nt_errstr(error
)));
2611 body
.data
= outhdr
+ SMB2_HDR_BODY
;
2613 SSVAL(body
.data
, 0, 9);
2616 SIVAL(body
.data
, 0x04, info
->length
);
2618 /* Allocated size of req->out.vector[i].iov_base
2619 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2620 * 1 byte without having to do an alloc.
2622 info
= talloc_zero_array(req
->out
.vector
,
2626 return NT_STATUS_NO_MEMORY
;
2628 info
->data
= ((uint8_t *)outhdr
) +
2629 OUTVEC_ALLOC_SIZE
- 1;
2631 SCVAL(info
->data
, 0, 0);
2635 * Note: Even if there is an error, continue to process the request.
2639 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
2643 struct smbd_smb2_send_oplock_break_state
{
2644 struct smbd_server_connection
*sconn
;
2645 struct smbd_smb2_send_queue queue_entry
;
2646 uint8_t buf
[NBT_HDR_SIZE
+ SMB2_TF_HDR_SIZE
+ SMB2_HDR_BODY
+ 0x18];
2647 struct iovec vector
[1+SMBD_SMB2_NUM_IOV_PER_REQ
];
2650 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
2651 struct smbXsrv_session
*session
,
2652 struct smbXsrv_tcon
*tcon
,
2653 struct smbXsrv_open
*op
,
2654 uint8_t oplock_level
)
2656 struct smbd_smb2_send_oplock_break_state
*state
;
2657 struct smbXsrv_connection
*conn
= sconn
->conn
;
2665 bool do_encryption
= session
->global
->encryption_required
;
2666 uint64_t nonce_high
= 0;
2667 uint64_t nonce_low
= 0;
2670 if (tcon
->global
->encryption_required
) {
2671 do_encryption
= true;
2674 state
= talloc(sconn
, struct smbd_smb2_send_oplock_break_state
);
2675 if (state
== NULL
) {
2676 return NT_STATUS_NO_MEMORY
;
2678 state
->sconn
= sconn
;
2680 tf
= state
->buf
+ NBT_HDR_SIZE
;
2681 tf_len
= SMB2_TF_HDR_SIZE
;
2683 body
= hdr
+ SMB2_HDR_BODY
;
2685 dyn
= body
+ body_len
;
2688 if (do_encryption
) {
2689 nonce_high
= session
->nonce_high
;
2690 nonce_low
= session
->nonce_low
;
2692 session
->nonce_low
+= 1;
2693 if (session
->nonce_low
== 0) {
2694 session
->nonce_low
+= 1;
2695 session
->nonce_high
+= 1;
2699 SIVAL(tf
, SMB2_TF_PROTOCOL_ID
, SMB2_TF_MAGIC
);
2700 SBVAL(tf
, SMB2_TF_NONCE
+0, nonce_low
);
2701 SBVAL(tf
, SMB2_TF_NONCE
+8, nonce_high
);
2702 SBVAL(tf
, SMB2_TF_SESSION_ID
, session
->global
->session_wire_id
);
2704 SIVAL(hdr
, 0, SMB2_MAGIC
);
2705 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
2706 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
2707 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
2708 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
2709 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
2710 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
2711 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
2712 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
2713 SIVAL(hdr
, SMB2_HDR_PID
, 0);
2714 SIVAL(hdr
, SMB2_HDR_TID
, 0);
2715 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
2716 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
2718 SSVAL(body
, 0x00, body_len
);
2720 SCVAL(body
, 0x02, oplock_level
);
2721 SCVAL(body
, 0x03, 0); /* reserved */
2722 SIVAL(body
, 0x04, 0); /* reserved */
2723 SBVAL(body
, 0x08, op
->global
->open_persistent_id
);
2724 SBVAL(body
, 0x10, op
->global
->open_volatile_id
);
2726 state
->vector
[0].iov_base
= (void *)state
->buf
;
2727 state
->vector
[0].iov_len
= NBT_HDR_SIZE
;
2729 if (do_encryption
) {
2730 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= tf
;
2731 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= tf_len
;
2733 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_base
= NULL
;
2734 state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
].iov_len
= 0;
2737 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
2738 state
->vector
[1+SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
2740 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
2741 state
->vector
[1+SMBD_SMB2_BODY_IOV_OFS
].iov_len
= body_len
;
2743 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
2744 state
->vector
[1+SMBD_SMB2_DYN_IOV_OFS
].iov_len
= dyn_len
;
2746 smb2_setup_nbt_length(state
->vector
, 1 + SMBD_SMB2_NUM_IOV_PER_REQ
);
2748 if (do_encryption
) {
2749 DATA_BLOB encryption_key
= session
->global
->encryption_key
;
2751 status
= smb2_signing_encrypt_pdu(encryption_key
,
2753 &state
->vector
[1+SMBD_SMB2_TF_IOV_OFS
],
2754 SMBD_SMB2_NUM_IOV_PER_REQ
);
2755 if (!NT_STATUS_IS_OK(status
)) {
2760 state
->queue_entry
.mem_ctx
= state
;
2761 state
->queue_entry
.vector
= state
->vector
;
2762 state
->queue_entry
.count
= ARRAY_SIZE(state
->vector
);
2763 DLIST_ADD_END(state
->sconn
->smb2
.send_queue
, &state
->queue_entry
, NULL
);
2764 state
->sconn
->smb2
.send_queue_len
++;
2766 status
= smbd_smb2_io_handler(sconn
, TEVENT_FD_WRITE
);
2767 if (!NT_STATUS_IS_OK(status
)) {
2771 return NT_STATUS_OK
;
2774 static size_t get_min_receive_file_size(struct smbd_smb2_request
*smb2_req
)
2776 if (smb2_req
->do_signing
) {
2779 if (smb2_req
->do_encryption
) {
2782 return (size_t)lp_min_receive_file_size();
2785 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state
*state
)
2789 if (IVAL(state
->pktbuf
, 0) == SMB2_TF_MAGIC
) {
2790 /* Transform header. Cannot recvfile. */
2793 if (IVAL(state
->pktbuf
, 0) != SMB2_MAGIC
) {
2794 /* Not SMB2. Normal error path will cope. */
2797 if (SVAL(state
->pktbuf
, 4) != SMB2_HDR_BODY
) {
2798 /* Not SMB2. Normal error path will cope. */
2801 if (SVAL(state
->pktbuf
, SMB2_HDR_OPCODE
) != SMB2_OP_WRITE
) {
2802 /* Needs to be a WRITE. */
2805 if (IVAL(state
->pktbuf
, SMB2_HDR_NEXT_COMMAND
) != 0) {
2806 /* Chained. Cannot recvfile. */
2809 flags
= IVAL(state
->pktbuf
, SMB2_HDR_FLAGS
);
2810 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
2811 /* Chained. Cannot recvfile. */
2814 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
2815 /* Signed. Cannot recvfile. */
2819 DEBUG(10,("Doing recvfile write len = %u\n",
2820 (unsigned int)(state
->pktlen
-
2821 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
)));
2826 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
)
2828 struct smbd_smb2_request_read_state
*state
= &sconn
->smb2
.request_read_state
;
2829 size_t max_send_queue_len
;
2830 size_t cur_send_queue_len
;
2832 if (state
->req
!= NULL
) {
2834 * if there is already a tstream_readv_pdu
2835 * pending, we are done.
2837 return NT_STATUS_OK
;
2840 max_send_queue_len
= MAX(1, sconn
->smb2
.max_credits
/16);
2841 cur_send_queue_len
= sconn
->smb2
.send_queue_len
;
2843 if (cur_send_queue_len
> max_send_queue_len
) {
2845 * if we have a lot of requests to send,
2846 * we wait until they are on the wire until we
2847 * ask for the next request.
2849 return NT_STATUS_OK
;
2852 /* ask for the next request */
2853 ZERO_STRUCTP(state
);
2854 state
->req
= smbd_smb2_request_allocate(sconn
);
2855 if (state
->req
== NULL
) {
2856 return NT_STATUS_NO_MEMORY
;
2858 state
->req
->sconn
= sconn
;
2859 state
->min_recv_size
= get_min_receive_file_size(state
->req
);
2861 TEVENT_FD_READABLE(sconn
->smb2
.fde
);
2863 return NT_STATUS_OK
;
2866 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
2867 uint8_t *inbuf
, size_t size
)
2870 struct smbd_smb2_request
*req
= NULL
;
2872 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2873 (unsigned int)size
));
2875 status
= smbd_initialize_smb2(sconn
);
2876 if (!NT_STATUS_IS_OK(status
)) {
2877 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2881 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
2882 if (!NT_STATUS_IS_OK(status
)) {
2883 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2887 status
= smbd_smb2_request_validate(req
);
2888 if (!NT_STATUS_IS_OK(status
)) {
2889 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2893 status
= smbd_smb2_request_setup_out(req
);
2894 if (!NT_STATUS_IS_OK(status
)) {
2895 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2899 status
= smbd_smb2_request_dispatch(req
);
2900 if (!NT_STATUS_IS_OK(status
)) {
2901 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2905 status
= smbd_smb2_request_next_incoming(sconn
);
2906 if (!NT_STATUS_IS_OK(status
)) {
2907 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2911 sconn
->num_requests
++;
2914 static int socket_error_from_errno(int ret
,
2928 if (sys_errno
== 0) {
2932 if (sys_errno
== EINTR
) {
2937 if (sys_errno
== EINPROGRESS
) {
2942 if (sys_errno
== EAGAIN
) {
2947 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
2948 if (sys_errno
== ENOMEM
) {
2954 if (sys_errno
== EWOULDBLOCK
) {
2963 static NTSTATUS
smbd_smb2_flush_send_queue(struct smbd_server_connection
*sconn
)
2969 if (sconn
->smb2
.send_queue
== NULL
) {
2970 TEVENT_FD_NOT_WRITEABLE(sconn
->smb2
.fde
);
2971 return NT_STATUS_OK
;
2974 while (sconn
->smb2
.send_queue
!= NULL
) {
2975 struct smbd_smb2_send_queue
*e
= sconn
->smb2
.send_queue
;
2977 ret
= writev(sconn
->sock
, e
->vector
, e
->count
);
2979 /* propagate end of file */
2980 return NT_STATUS_INTERNAL_ERROR
;
2982 err
= socket_error_from_errno(ret
, errno
, &retry
);
2985 TEVENT_FD_WRITEABLE(sconn
->smb2
.fde
);
2986 return NT_STATUS_OK
;
2989 return map_nt_error_from_unix_common(err
);
2992 if (ret
< e
->vector
[0].iov_len
) {
2994 base
= (uint8_t *)e
->vector
[0].iov_base
;
2996 e
->vector
[0].iov_base
= (void *)base
;
2997 e
->vector
[0].iov_len
-= ret
;
3000 ret
-= e
->vector
[0].iov_len
;
3006 * there're maybe some empty vectors at the end
3007 * which we need to skip, otherwise we would get
3008 * ret == 0 from the readv() call and return EPIPE
3010 while (e
->count
> 0) {
3011 if (e
->vector
[0].iov_len
> 0) {
3019 /* we have more to write */
3020 TEVENT_FD_WRITEABLE(sconn
->smb2
.fde
);
3021 return NT_STATUS_OK
;
3024 sconn
->smb2
.send_queue_len
--;
3025 DLIST_REMOVE(sconn
->smb2
.send_queue
, e
);
3026 talloc_free(e
->mem_ctx
);
3029 return NT_STATUS_OK
;
3032 static NTSTATUS
smbd_smb2_io_handler(struct smbd_server_connection
*sconn
,
3035 struct smbd_smb2_request_read_state
*state
= &sconn
->smb2
.request_read_state
;
3036 struct smbd_smb2_request
*req
= NULL
;
3037 size_t min_recvfile_size
= UINT32_MAX
;
3044 if (fde_flags
& TEVENT_FD_WRITE
) {
3045 status
= smbd_smb2_flush_send_queue(sconn
);
3046 if (!NT_STATUS_IS_OK(status
)) {
3051 if (!(fde_flags
& TEVENT_FD_READ
)) {
3052 return NT_STATUS_OK
;
3055 if (state
->req
== NULL
) {
3056 TEVENT_FD_NOT_READABLE(sconn
->smb2
.fde
);
3057 return NT_STATUS_OK
;
3061 if (!state
->hdr
.done
) {
3062 state
->hdr
.done
= true;
3064 state
->vector
.iov_base
= (void *)state
->hdr
.nbt
;
3065 state
->vector
.iov_len
= NBT_HDR_SIZE
;
3068 ret
= readv(sconn
->sock
, &state
->vector
, 1);
3070 /* propagate end of file */
3071 return NT_STATUS_END_OF_FILE
;
3073 err
= socket_error_from_errno(ret
, errno
, &retry
);
3076 TEVENT_FD_READABLE(sconn
->smb2
.fde
);
3077 return NT_STATUS_OK
;
3080 return map_nt_error_from_unix_common(err
);
3083 if (ret
< state
->vector
.iov_len
) {
3085 base
= (uint8_t *)state
->vector
.iov_base
;
3087 state
->vector
.iov_base
= (void *)base
;
3088 state
->vector
.iov_len
-= ret
;
3089 /* we have more to read */
3090 TEVENT_FD_READABLE(sconn
->smb2
.fde
);
3091 return NT_STATUS_OK
;
3094 if (state
->pktlen
> 0) {
3095 if (state
->doing_receivefile
&& !is_smb2_recvfile_write(state
)) {
3097 * Not a possible receivefile write.
3098 * Read the rest of the data.
3100 state
->doing_receivefile
= false;
3101 state
->vector
.iov_base
= (void *)(state
->pktbuf
+
3102 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
);
3103 state
->vector
.iov_len
= (state
->pktlen
-
3104 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
);
3109 * Either this is a receivefile write so we've
3110 * done a short read, or if not we have all the data.
3116 * Now we analyze the NBT header
3118 state
->pktlen
= smb2_len(state
->hdr
.nbt
);
3119 if (state
->pktlen
== 0) {
3123 state
->pktbuf
= talloc_array(state
->req
, uint8_t, state
->pktlen
);
3124 if (state
->pktbuf
== NULL
) {
3125 return NT_STATUS_NO_MEMORY
;
3128 state
->vector
.iov_base
= (void *)state
->pktbuf
;
3130 if (state
->min_recv_size
!= 0) {
3131 min_recvfile_size
= SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
;
3132 min_recvfile_size
+= state
->min_recv_size
;
3135 if (state
->pktlen
> min_recvfile_size
) {
3137 * Might be a receivefile write. Read the SMB2 HEADER +
3138 * SMB2_WRITE header first. Set 'doing_receivefile'
3139 * as we're *attempting* receivefile write. If this
3140 * turns out not to be a SMB2_WRITE request or otherwise
3141 * not suitable then we'll just read the rest of the data
3142 * the next time this function is called.
3144 state
->vector
.iov_len
= SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
;
3145 state
->doing_receivefile
= true;
3147 state
->vector
.iov_len
= state
->pktlen
;
3154 if (state
->hdr
.nbt
[0] != 0x00) {
3155 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3156 state
->hdr
.nbt
[0]));
3159 ZERO_STRUCTP(state
);
3161 state
->min_recv_size
= get_min_receive_file_size(state
->req
);
3169 req
->request_time
= timeval_current();
3170 now
= timeval_to_nttime(&req
->request_time
);
3172 status
= smbd_smb2_inbuf_parse_compound(req
->sconn
->conn
,
3178 &req
->in
.vector_count
);
3179 if (!NT_STATUS_IS_OK(status
)) {
3183 if (state
->doing_receivefile
) {
3184 req
->smb1req
= talloc_zero(req
, struct smb_request
);
3185 if (req
->smb1req
== NULL
) {
3186 return NT_STATUS_NO_MEMORY
;
3188 req
->smb1req
->unread_bytes
=
3189 state
->pktlen
- SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
;
3192 ZERO_STRUCTP(state
);
3194 req
->current_idx
= 1;
3196 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3197 req
->current_idx
, req
->in
.vector_count
));
3199 status
= smbd_smb2_request_validate(req
);
3200 if (!NT_STATUS_IS_OK(status
)) {
3204 status
= smbd_smb2_request_setup_out(req
);
3205 if (!NT_STATUS_IS_OK(status
)) {
3209 status
= smbd_smb2_request_dispatch(req
);
3210 if (!NT_STATUS_IS_OK(status
)) {
3214 sconn
->num_requests
++;
3216 /* The timeout_processing function isn't run nearly
3217 often enough to implement 'max log size' without
3218 overrunning the size of the file by many megabytes.
3219 This is especially true if we are running at debug
3220 level 10. Checking every 50 SMB2s is a nice
3221 tradeoff of performance vs log file size overrun. */
3223 if ((sconn
->num_requests
% 50) == 0 &&
3224 need_to_check_log_size()) {
3225 change_to_root_user();
3229 status
= smbd_smb2_request_next_incoming(sconn
);
3230 if (!NT_STATUS_IS_OK(status
)) {
3234 return NT_STATUS_OK
;
3237 static void smbd_smb2_connection_handler(struct tevent_context
*ev
,
3238 struct tevent_fd
*fde
,
3242 struct smbd_server_connection
*sconn
=
3243 talloc_get_type_abort(private_data
,
3244 struct smbd_server_connection
);
3247 status
= smbd_smb2_io_handler(sconn
, flags
);
3248 if (!NT_STATUS_IS_OK(status
)) {
3249 smbd_server_connection_terminate(sconn
, nt_errstr(status
));