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 #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9)
35 static const struct smbd_smb2_dispatch_table
{
41 } smbd_smb2_table
[] = {
42 #define _OP(o) .opcode = o, .name = #o
47 _OP(SMB2_OP_SESSSETUP
),
57 * This call needs to be run as root.
59 * smbd_smb2_request_process_tcon()
60 * calls make_connection_snum(), which will call
61 * change_to_user(), when needed.
101 _OP(SMB2_OP_KEEPALIVE
),
105 .need_session
= true,
109 .need_session
= true,
112 _OP(SMB2_OP_GETINFO
),
113 .need_session
= true,
116 _OP(SMB2_OP_SETINFO
),
117 .need_session
= true,
121 .need_session
= true,
126 const char *smb2_opcode_name(uint16_t opcode
)
128 if (opcode
>= ARRAY_SIZE(smbd_smb2_table
)) {
129 return "Bad SMB2 opcode";
131 return smbd_smb2_table
[opcode
].name
;
134 static const struct smbd_smb2_dispatch_table
*smbd_smb2_call(uint16_t opcode
)
136 const struct smbd_smb2_dispatch_table
*ret
= NULL
;
138 if (opcode
>= ARRAY_SIZE(smbd_smb2_table
)) {
142 ret
= &smbd_smb2_table
[opcode
];
144 SMB_ASSERT(ret
->opcode
== opcode
);
149 static void print_req_vectors(struct smbd_smb2_request
*req
)
153 for (i
= 0; i
< req
->in
.vector_count
; i
++) {
154 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
156 (unsigned int)req
->in
.vector
[i
].iov_len
);
158 for (i
= 0; i
< req
->out
.vector_count
; i
++) {
159 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
161 (unsigned int)req
->out
.vector
[i
].iov_len
);
165 bool smbd_is_smb2_header(const uint8_t *inbuf
, size_t size
)
167 if (size
< (4 + SMB2_HDR_BODY
)) {
171 if (IVAL(inbuf
, 4) != SMB2_MAGIC
) {
178 static NTSTATUS
smbd_initialize_smb2(struct smbd_server_connection
*sconn
)
183 TALLOC_FREE(sconn
->smb1
.fde
);
185 sconn
->smb2
.recv_queue
= tevent_queue_create(sconn
, "smb2 recv queue");
186 if (sconn
->smb2
.recv_queue
== NULL
) {
187 return NT_STATUS_NO_MEMORY
;
190 sconn
->smb2
.send_queue
= tevent_queue_create(sconn
, "smb2 send queue");
191 if (sconn
->smb2
.send_queue
== NULL
) {
192 return NT_STATUS_NO_MEMORY
;
195 sconn
->smb2
.seqnum_low
= 0;
196 sconn
->smb2
.seqnum_range
= 1;
197 sconn
->smb2
.credits_granted
= 1;
198 sconn
->smb2
.max_credits
= lp_smb2_max_credits();
199 sconn
->smb2
.credits_bitmap
= bitmap_talloc(sconn
,
200 sconn
->smb2
.max_credits
);
201 if (sconn
->smb2
.credits_bitmap
== NULL
) {
202 return NT_STATUS_NO_MEMORY
;
205 ret
= tstream_bsd_existing_socket(sconn
, sconn
->sock
,
206 &sconn
->smb2
.stream
);
208 status
= map_nt_error_from_unix(errno
);
212 /* Ensure child is set to non-blocking mode */
213 set_blocking(sconn
->sock
, false);
217 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
218 #define _smb2_setlen(_buf,len) do { \
219 uint8_t *buf = (uint8_t *)_buf; \
221 buf[1] = ((len)&0xFF0000)>>16; \
222 buf[2] = ((len)&0xFF00)>>8; \
223 buf[3] = (len)&0xFF; \
226 static void smb2_setup_nbt_length(struct iovec
*vector
, int count
)
231 for (i
=1; i
< count
; i
++) {
232 len
+= vector
[i
].iov_len
;
235 _smb2_setlen(vector
[0].iov_base
, len
);
238 static struct smbd_smb2_request
*smbd_smb2_request_allocate(TALLOC_CTX
*mem_ctx
)
240 TALLOC_CTX
*mem_pool
;
241 struct smbd_smb2_request
*req
;
244 /* Enable this to find subtle valgrind errors. */
245 mem_pool
= talloc_init("smbd_smb2_request_allocate");
247 mem_pool
= talloc_pool(mem_ctx
, 8192);
249 if (mem_pool
== NULL
) {
253 req
= talloc_zero(mem_pool
, struct smbd_smb2_request
);
255 talloc_free(mem_pool
);
258 talloc_reparent(mem_pool
, mem_ctx
, req
);
259 TALLOC_FREE(mem_pool
);
261 req
->last_session_id
= UINT64_MAX
;
262 req
->last_tid
= UINT32_MAX
;
267 static NTSTATUS
smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection
*conn
,
278 uint8_t *first_hdr
= buf
;
281 * Note: index '0' is reserved for the transport protocol
283 iov
= talloc_zero_array(mem_ctx
, struct iovec
, num_iov
);
285 return NT_STATUS_NO_MEMORY
;
288 while (taken
< buflen
) {
289 size_t len
= buflen
- taken
;
290 uint8_t *hdr
= first_hdr
+ taken
;
293 size_t next_command_ofs
;
295 uint8_t *body
= NULL
;
298 struct iovec
*iov_tmp
;
301 * We need the header plus the body length field
304 if (len
< SMB2_HDR_BODY
+ 2) {
305 DEBUG(10, ("%d bytes left, expected at least %d\n",
306 (int)len
, SMB2_HDR_BODY
));
309 if (IVAL(hdr
, 0) != SMB2_MAGIC
) {
310 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
314 if (SVAL(hdr
, 4) != SMB2_HDR_BODY
) {
315 DEBUG(10, ("Got HDR len %d, expected %d\n",
316 SVAL(hdr
, 4), SMB2_HDR_BODY
));
321 next_command_ofs
= IVAL(hdr
, SMB2_HDR_NEXT_COMMAND
);
322 body_size
= SVAL(hdr
, SMB2_HDR_BODY
);
324 if (next_command_ofs
!= 0) {
325 if (next_command_ofs
< (SMB2_HDR_BODY
+ 2)) {
328 if (next_command_ofs
> full_size
) {
331 full_size
= next_command_ofs
;
338 if (body_size
> (full_size
- SMB2_HDR_BODY
)) {
340 * let the caller handle the error
342 body_size
= full_size
- SMB2_HDR_BODY
;
344 body
= hdr
+ SMB2_HDR_BODY
;
345 dyn
= body
+ body_size
;
346 dyn_size
= full_size
- (SMB2_HDR_BODY
+ body_size
);
348 iov_tmp
= talloc_realloc(mem_ctx
, iov
, struct iovec
,
349 num_iov
+ SMBD_SMB2_NUM_IOV_PER_REQ
);
350 if (iov_tmp
== NULL
) {
352 return NT_STATUS_NO_MEMORY
;
356 num_iov
+= SMBD_SMB2_NUM_IOV_PER_REQ
;
358 cur
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= hdr
;
359 cur
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
360 cur
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= body
;
361 cur
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= body_size
;
362 cur
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= dyn
;
363 cur
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= dyn_size
;
374 return NT_STATUS_INVALID_PARAMETER
;
377 static NTSTATUS
smbd_smb2_request_create(struct smbd_server_connection
*sconn
,
378 uint8_t *inbuf
, size_t size
,
379 struct smbd_smb2_request
**_req
)
381 struct smbd_smb2_request
*req
;
382 uint32_t protocol_version
;
383 const uint8_t *inhdr
= NULL
;
385 uint32_t next_command_ofs
;
389 if (size
< (4 + SMB2_HDR_BODY
+ 2)) {
390 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size
));
391 return NT_STATUS_INVALID_PARAMETER
;
396 protocol_version
= IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
);
397 if (protocol_version
!= SMB2_MAGIC
) {
398 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
400 return NT_STATUS_INVALID_PARAMETER
;
403 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
404 if (cmd
!= SMB2_OP_NEGPROT
) {
405 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
407 return NT_STATUS_INVALID_PARAMETER
;
410 next_command_ofs
= IVAL(inhdr
, SMB2_HDR_NEXT_COMMAND
);
411 if (next_command_ofs
!= 0) {
412 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
414 return NT_STATUS_INVALID_PARAMETER
;
417 req
= smbd_smb2_request_allocate(sconn
);
419 return NT_STATUS_NO_MEMORY
;
423 talloc_steal(req
, inbuf
);
425 req
->request_time
= timeval_current();
426 now
= timeval_to_nttime(&req
->request_time
);
428 status
= smbd_smb2_inbuf_parse_compound(sconn
->conn
,
430 inbuf
+ NBT_HDR_SIZE
,
432 req
, &req
->in
.vector
,
433 &req
->in
.vector_count
);
434 if (!NT_STATUS_IS_OK(status
)) {
439 req
->current_idx
= 1;
445 static bool smb2_validate_sequence_number(struct smbd_server_connection
*sconn
,
446 uint64_t message_id
, uint64_t seq_id
)
448 struct bitmap
*credits_bm
= sconn
->smb2
.credits_bitmap
;
451 if (seq_id
< sconn
->smb2
.seqnum_low
) {
452 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
453 "%llu (sequence id %llu) "
454 "(granted = %u, low = %llu, range = %u)\n",
455 (unsigned long long)message_id
,
456 (unsigned long long)seq_id
,
457 (unsigned int)sconn
->smb2
.credits_granted
,
458 (unsigned long long)sconn
->smb2
.seqnum_low
,
459 (unsigned int)sconn
->smb2
.seqnum_range
));
463 if (seq_id
>= sconn
->smb2
.seqnum_low
+ sconn
->smb2
.seqnum_range
) {
464 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
465 "%llu (sequence id %llu) "
466 "(granted = %u, low = %llu, range = %u)\n",
467 (unsigned long long)message_id
,
468 (unsigned long long)seq_id
,
469 (unsigned int)sconn
->smb2
.credits_granted
,
470 (unsigned long long)sconn
->smb2
.seqnum_low
,
471 (unsigned int)sconn
->smb2
.seqnum_range
));
475 offset
= seq_id
% sconn
->smb2
.max_credits
;
477 if (bitmap_query(credits_bm
, offset
)) {
478 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
479 "%llu (sequence id %llu) "
480 "(granted = %u, low = %llu, range = %u) "
482 (unsigned long long)message_id
,
483 (unsigned long long)seq_id
,
484 (unsigned int)sconn
->smb2
.credits_granted
,
485 (unsigned long long)sconn
->smb2
.seqnum_low
,
486 (unsigned int)sconn
->smb2
.seqnum_range
,
491 /* Mark the message_ids as seen in the bitmap. */
492 bitmap_set(credits_bm
, offset
);
494 if (seq_id
!= sconn
->smb2
.seqnum_low
) {
499 * Move the window forward by all the message_id's
502 while (bitmap_query(credits_bm
, offset
)) {
503 DEBUG(10,("smb2_validate_sequence_number: clearing "
504 "id %llu (position %u) from bitmap\n",
505 (unsigned long long)(sconn
->smb2
.seqnum_low
),
507 bitmap_clear(credits_bm
, offset
);
509 sconn
->smb2
.seqnum_low
+= 1;
510 sconn
->smb2
.seqnum_range
-= 1;
511 offset
= sconn
->smb2
.seqnum_low
% sconn
->smb2
.max_credits
;
517 static bool smb2_validate_message_id(struct smbd_server_connection
*sconn
,
518 const uint8_t *inhdr
)
520 uint64_t message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
521 uint16_t opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
522 uint16_t credit_charge
= 1;
525 if (opcode
== SMB2_OP_CANCEL
) {
526 /* SMB2_CANCEL requests by definition resend messageids. */
530 if (sconn
->smb2
.supports_multicredit
) {
531 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
532 credit_charge
= MAX(credit_charge
, 1);
535 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
536 "credits_granted %llu, "
537 "seqnum low/range: %llu/%llu\n",
538 (unsigned long long) message_id
,
539 (unsigned long long) credit_charge
,
540 (unsigned long long) sconn
->smb2
.credits_granted
,
541 (unsigned long long) sconn
->smb2
.seqnum_low
,
542 (unsigned long long) sconn
->smb2
.seqnum_range
));
544 if (sconn
->smb2
.credits_granted
< credit_charge
) {
545 DEBUG(0, ("smb2_validate_message_id: client used more "
546 "credits than granted, mid %llu, charge %llu, "
547 "credits_granted %llu, "
548 "seqnum low/range: %llu/%llu\n",
549 (unsigned long long) message_id
,
550 (unsigned long long) credit_charge
,
551 (unsigned long long) sconn
->smb2
.credits_granted
,
552 (unsigned long long) sconn
->smb2
.seqnum_low
,
553 (unsigned long long) sconn
->smb2
.seqnum_range
));
558 * now check the message ids
560 * for multi-credit requests we need to check all current mid plus
561 * the implicit mids caused by the credit charge
562 * e.g. current mid = 15, charge 5 => mark 15-19 as used
565 for (i
= 0; i
<= (credit_charge
-1); i
++) {
566 uint64_t id
= message_id
+ i
;
569 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
570 (unsigned long long)message_id
,
572 (unsigned long long)id
));
574 ok
= smb2_validate_sequence_number(sconn
, message_id
, id
);
580 /* substract used credits */
581 sconn
->smb2
.credits_granted
-= credit_charge
;
586 static NTSTATUS
smbd_smb2_request_validate(struct smbd_smb2_request
*req
)
591 count
= req
->in
.vector_count
;
593 if (count
< 1 + SMBD_SMB2_NUM_IOV_PER_REQ
) {
594 /* It's not a SMB2 request */
595 return NT_STATUS_INVALID_PARAMETER
;
598 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
599 struct iovec
*hdr
= SMBD_SMB2_IDX_HDR_IOV(req
,in
,idx
);
600 struct iovec
*body
= SMBD_SMB2_IDX_BODY_IOV(req
,in
,idx
);
601 const uint8_t *inhdr
= NULL
;
604 if (hdr
->iov_len
!= SMB2_HDR_BODY
) {
605 return NT_STATUS_INVALID_PARAMETER
;
608 if (body
->iov_len
< 2) {
609 return NT_STATUS_INVALID_PARAMETER
;
612 inhdr
= (const uint8_t *)hdr
->iov_base
;
614 /* Check the SMB2 header */
615 if (IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
) != SMB2_MAGIC
) {
616 return NT_STATUS_INVALID_PARAMETER
;
619 if (!smb2_validate_message_id(req
->sconn
, inhdr
)) {
620 return NT_STATUS_INVALID_PARAMETER
;
623 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
626 * the 1st request should never have the
627 * SMB2_HDR_FLAG_CHAINED flag set
629 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
630 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
633 } else if (idx
== 4) {
635 * the 2nd request triggers related vs. unrelated
636 * compounded requests
638 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
639 req
->compound_related
= true;
641 } else if (idx
> 4) {
644 * It seems the this tests are wrong
645 * see the SMB2-COMPOUND test
649 * all other requests should match the 2nd one
651 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
652 if (!req
->compound_related
) {
654 NT_STATUS_INVALID_PARAMETER
;
658 if (req
->compound_related
) {
660 NT_STATUS_INVALID_PARAMETER
;
671 static void smb2_set_operation_credit(struct smbd_server_connection
*sconn
,
672 const struct iovec
*in_vector
,
673 struct iovec
*out_vector
)
675 const uint8_t *inhdr
= (const uint8_t *)in_vector
->iov_base
;
676 uint8_t *outhdr
= (uint8_t *)out_vector
->iov_base
;
677 uint16_t credit_charge
= 1;
678 uint16_t credits_requested
;
682 uint16_t credits_granted
= 0;
683 uint64_t credits_possible
;
684 uint16_t current_max_credits
;
687 * first we grant only 1/16th of the max range.
689 * Windows also starts with the 1/16th and then grants
690 * more later. I was only able to trigger higher
691 * values, when using a verify high credit charge.
693 * TODO: scale up depending one load, free memory
695 * Maybe also on the relationship between number
696 * of requests and the used sequence number.
697 * Which means we would grant more credits
698 * for client which use multi credit requests.
700 current_max_credits
= sconn
->smb2
.max_credits
/ 16;
701 current_max_credits
= MAX(current_max_credits
, 1);
703 if (sconn
->smb2
.supports_multicredit
) {
704 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
705 credit_charge
= MAX(credit_charge
, 1);
708 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
709 credits_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
710 out_flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
711 out_status
= NT_STATUS(IVAL(outhdr
, SMB2_HDR_STATUS
));
713 SMB_ASSERT(sconn
->smb2
.max_credits
>= sconn
->smb2
.credits_granted
);
714 SMB_ASSERT(sconn
->smb2
.max_credits
>= credit_charge
);
716 if (out_flags
& SMB2_HDR_FLAG_ASYNC
) {
718 * In case we already send an async interim
719 * response, we should not grant
720 * credits on the final response.
723 } else if (credits_requested
> 0) {
724 uint16_t additional_max
= 0;
725 uint16_t additional_credits
= credits_requested
- 1;
728 case SMB2_OP_NEGPROT
:
730 case SMB2_OP_SESSSETUP
:
732 * Windows 2012 RC1 starts to grant
734 * with a successful session setup
736 if (NT_STATUS_IS_OK(out_status
)) {
742 * We match windows and only grant additional credits
749 additional_credits
= MIN(additional_credits
, additional_max
);
751 credits_granted
= credit_charge
+ additional_credits
;
752 } else if (sconn
->smb2
.credits_granted
== 0) {
754 * Make sure the client has always at least one credit
760 * sequence numbers should not wrap
762 * 1. calculate the possible credits until
763 * the sequence numbers start to wrap on 64-bit.
765 * 2. UINT64_MAX is used for Break Notifications.
767 * 2. truncate the possible credits to the maximum
768 * credits we want to grant to the client in total.
770 * 3. remove the range we'll already granted to the client
771 * this makes sure the client consumes the lowest sequence
772 * number, before we can grant additional credits.
774 credits_possible
= UINT64_MAX
- sconn
->smb2
.seqnum_low
;
775 if (credits_possible
> 0) {
776 /* remove UINT64_MAX */
777 credits_possible
-= 1;
779 credits_possible
= MIN(credits_possible
, current_max_credits
);
780 credits_possible
-= sconn
->smb2
.seqnum_range
;
782 credits_granted
= MIN(credits_granted
, credits_possible
);
784 SSVAL(outhdr
, SMB2_HDR_CREDIT
, credits_granted
);
785 sconn
->smb2
.credits_granted
+= credits_granted
;
786 sconn
->smb2
.seqnum_range
+= credits_granted
;
788 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
789 "granted %u, current possible/max %u/%u, "
790 "total granted/max/low/range %u/%u/%llu/%u\n",
791 (unsigned int)credits_requested
,
792 (unsigned int)credit_charge
,
793 (unsigned int)credits_granted
,
794 (unsigned int)credits_possible
,
795 (unsigned int)current_max_credits
,
796 (unsigned int)sconn
->smb2
.credits_granted
,
797 (unsigned int)sconn
->smb2
.max_credits
,
798 (unsigned long long)sconn
->smb2
.seqnum_low
,
799 (unsigned int)sconn
->smb2
.seqnum_range
));
802 static void smb2_calculate_credits(const struct smbd_smb2_request
*inreq
,
803 struct smbd_smb2_request
*outreq
)
806 uint16_t total_credits
= 0;
808 count
= outreq
->out
.vector_count
;
810 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
811 struct iovec
*inhdr_v
= SMBD_SMB2_IDX_HDR_IOV(inreq
,in
,idx
);
812 struct iovec
*outhdr_v
= SMBD_SMB2_IDX_HDR_IOV(outreq
,out
,idx
);
813 uint8_t *outhdr
= (uint8_t *)outhdr_v
->iov_base
;
815 smb2_set_operation_credit(outreq
->sconn
, inhdr_v
, outhdr_v
);
817 /* To match Windows, count up what we
819 total_credits
+= SVAL(outhdr
, SMB2_HDR_CREDIT
);
820 /* Set to zero in all but the last reply. */
821 if (idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
< count
) {
822 SSVAL(outhdr
, SMB2_HDR_CREDIT
, 0);
824 SSVAL(outhdr
, SMB2_HDR_CREDIT
, total_credits
);
829 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
)
831 struct iovec
*vector
;
835 count
= req
->in
.vector_count
;
836 vector
= talloc_zero_array(req
, struct iovec
, count
);
837 if (vector
== NULL
) {
838 return NT_STATUS_NO_MEMORY
;
841 vector
[0].iov_base
= req
->out
.nbt_hdr
;
842 vector
[0].iov_len
= 4;
843 SIVAL(req
->out
.nbt_hdr
, 0, 0);
845 for (idx
=1; idx
< count
; idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
846 struct iovec
*inhdr_v
= SMBD_SMB2_IDX_HDR_IOV(req
,in
,idx
);
847 const uint8_t *inhdr
= (const uint8_t *)inhdr_v
->iov_base
;
848 uint8_t *outhdr
= NULL
;
849 uint8_t *outbody
= NULL
;
850 uint32_t next_command_ofs
= 0;
851 struct iovec
*current
= &vector
[idx
];
853 if ((idx
+ SMBD_SMB2_NUM_IOV_PER_REQ
) < count
) {
854 /* we have a next command -
855 * setup for the error case. */
856 next_command_ofs
= SMB2_HDR_BODY
+ 9;
859 outhdr
= talloc_zero_array(vector
, uint8_t,
861 if (outhdr
== NULL
) {
862 return NT_STATUS_NO_MEMORY
;
865 outbody
= outhdr
+ SMB2_HDR_BODY
;
867 current
[SMBD_SMB2_HDR_IOV_OFS
].iov_base
= (void *)outhdr
;
868 current
[SMBD_SMB2_HDR_IOV_OFS
].iov_len
= SMB2_HDR_BODY
;
870 current
[SMBD_SMB2_BODY_IOV_OFS
].iov_base
= (void *)outbody
;
871 current
[SMBD_SMB2_BODY_IOV_OFS
].iov_len
= 8;
873 current
[SMBD_SMB2_DYN_IOV_OFS
].iov_base
= NULL
;
874 current
[SMBD_SMB2_DYN_IOV_OFS
].iov_len
= 0;
876 /* setup the SMB2 header */
877 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
878 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
879 SSVAL(outhdr
, SMB2_HDR_CREDIT_CHARGE
,
880 SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
));
881 SIVAL(outhdr
, SMB2_HDR_STATUS
,
882 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
883 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
884 SVAL(inhdr
, SMB2_HDR_OPCODE
));
885 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
886 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
887 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
888 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
889 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
890 SIVAL(outhdr
, SMB2_HDR_PID
,
891 IVAL(inhdr
, SMB2_HDR_PID
));
892 SIVAL(outhdr
, SMB2_HDR_TID
,
893 IVAL(inhdr
, SMB2_HDR_TID
));
894 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
895 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
896 memcpy(outhdr
+ SMB2_HDR_SIGNATURE
,
897 inhdr
+ SMB2_HDR_SIGNATURE
, 16);
899 /* setup error body header */
900 SSVAL(outbody
, 0x00, 0x08 + 1);
901 SSVAL(outbody
, 0x02, 0);
902 SIVAL(outbody
, 0x04, 0);
905 req
->out
.vector
= vector
;
906 req
->out
.vector_count
= count
;
908 /* setup the length of the NBT packet */
909 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
911 DLIST_ADD_END(req
->sconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
916 void smbd_server_connection_terminate_ex(struct smbd_server_connection
*sconn
,
918 const char *location
)
920 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
922 exit_server_cleanly(reason
);
925 static bool dup_smb2_vec3(TALLOC_CTX
*ctx
,
926 struct iovec
*outvec
,
927 const struct iovec
*srcvec
)
929 /* vec[0] is always boilerplate and must
930 * be allocated with size OUTVEC_ALLOC_SIZE. */
932 outvec
[0].iov_base
= talloc_memdup(ctx
,
935 if (!outvec
[0].iov_base
) {
938 outvec
[0].iov_len
= SMB2_HDR_BODY
;
941 * If this is a "standard" vec[1] of length 8,
942 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
943 * then duplicate this. Else use talloc_memdup().
946 if (srcvec
[1].iov_len
== 8 &&
947 srcvec
[1].iov_base
==
948 ((uint8_t *)srcvec
[0].iov_base
) +
950 outvec
[1].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
952 outvec
[1].iov_len
= 8;
954 outvec
[1].iov_base
= talloc_memdup(ctx
,
957 if (!outvec
[1].iov_base
) {
960 outvec
[1].iov_len
= srcvec
[1].iov_len
;
964 * If this is a "standard" vec[2] of length 1,
965 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
966 * then duplicate this. Else use talloc_memdup().
969 if (srcvec
[2].iov_base
&&
971 if (srcvec
[2].iov_base
==
972 ((uint8_t *)srcvec
[0].iov_base
) +
973 (OUTVEC_ALLOC_SIZE
- 1) &&
974 srcvec
[2].iov_len
== 1) {
975 /* Common SMB2 error packet case. */
976 outvec
[2].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
977 (OUTVEC_ALLOC_SIZE
- 1);
979 outvec
[2].iov_base
= talloc_memdup(ctx
,
982 if (!outvec
[2].iov_base
) {
986 outvec
[2].iov_len
= srcvec
[2].iov_len
;
988 outvec
[2].iov_base
= NULL
;
989 outvec
[2].iov_len
= 0;
994 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
996 struct smbd_smb2_request
*newreq
= NULL
;
997 struct iovec
*outvec
= NULL
;
998 int count
= req
->out
.vector_count
;
1001 newreq
= smbd_smb2_request_allocate(req
->sconn
);
1006 newreq
->sconn
= req
->sconn
;
1007 newreq
->session
= req
->session
;
1008 newreq
->do_signing
= req
->do_signing
;
1009 newreq
->current_idx
= req
->current_idx
;
1011 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
1013 TALLOC_FREE(newreq
);
1016 newreq
->out
.vector
= outvec
;
1017 newreq
->out
.vector_count
= count
;
1019 /* Setup the outvec's identically to req. */
1020 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
1021 outvec
[0].iov_len
= 4;
1022 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
1024 /* Setup the vectors identically to the ones in req. */
1025 for (i
= 1; i
< count
; i
+= SMBD_SMB2_NUM_IOV_PER_REQ
) {
1026 if (!dup_smb2_vec3(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
1033 TALLOC_FREE(newreq
);
1037 smb2_setup_nbt_length(newreq
->out
.vector
,
1038 newreq
->out
.vector_count
);
1043 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
);
1045 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
1048 uint8_t *outhdr
= NULL
;
1049 struct smbd_smb2_request
*nreq
= NULL
;
1051 /* Create a new smb2 request we'll use
1052 for the interim return. */
1053 nreq
= dup_smb2_req(req
);
1055 return NT_STATUS_NO_MEMORY
;
1058 /* Lose the last X out vectors. They're the
1059 ones we'll be using for the async reply. */
1060 nreq
->out
.vector_count
-= SMBD_SMB2_NUM_IOV_PER_REQ
;
1062 smb2_setup_nbt_length(nreq
->out
.vector
,
1063 nreq
->out
.vector_count
);
1065 /* Step back to the previous reply. */
1066 i
= nreq
->current_idx
- SMBD_SMB2_NUM_IOV_PER_REQ
;
1067 outhdr
= (uint8_t *)nreq
->out
.vector
[i
].iov_base
;
1068 /* And end the chain. */
1069 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1071 /* Calculate outgoing credits */
1072 smb2_calculate_credits(req
, nreq
);
1074 /* Re-sign if needed. */
1075 if (nreq
->do_signing
) {
1077 struct smbXsrv_session
*x
= nreq
->session
;
1078 struct smbXsrv_connection
*conn
= x
->connection
;
1079 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
1081 status
= smb2_signing_sign_pdu(signing_key
,
1083 &nreq
->out
.vector
[i
],
1084 SMBD_SMB2_NUM_IOV_PER_REQ
);
1085 if (!NT_STATUS_IS_OK(status
)) {
1089 if (DEBUGLEVEL
>= 10) {
1090 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1091 (unsigned int)nreq
->current_idx
);
1092 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1093 (unsigned int)nreq
->out
.vector_count
);
1094 print_req_vectors(nreq
);
1096 nreq
->subreq
= tstream_writev_queue_send(nreq
,
1097 nreq
->sconn
->ev_ctx
,
1098 nreq
->sconn
->smb2
.stream
,
1099 nreq
->sconn
->smb2
.send_queue
,
1101 nreq
->out
.vector_count
);
1103 if (nreq
->subreq
== NULL
) {
1104 return NT_STATUS_NO_MEMORY
;
1107 tevent_req_set_callback(nreq
->subreq
,
1108 smbd_smb2_request_writev_done
,
1111 return NT_STATUS_OK
;
1114 struct smbd_smb2_request_pending_state
{
1115 struct smbd_server_connection
*sconn
;
1116 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x08 + 1];
1117 struct iovec vector
[3];
1120 static void smbd_smb2_request_pending_writev_done(struct tevent_req
*subreq
)
1122 struct smbd_smb2_request_pending_state
*state
=
1123 tevent_req_callback_data(subreq
,
1124 struct smbd_smb2_request_pending_state
);
1125 struct smbd_server_connection
*sconn
= state
->sconn
;
1129 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1130 TALLOC_FREE(subreq
);
1132 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
1133 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1140 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
1141 struct tevent_timer
*te
,
1142 struct timeval current_time
,
1143 void *private_data
);
1145 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
1146 struct tevent_req
*subreq
,
1147 uint32_t defer_time
)
1150 int i
= req
->current_idx
;
1151 struct timeval defer_endtime
;
1152 uint8_t *outhdr
= NULL
;
1155 if (!tevent_req_is_in_progress(subreq
)) {
1156 return NT_STATUS_OK
;
1159 req
->subreq
= subreq
;
1162 if (req
->async_te
) {
1163 /* We're already async. */
1164 return NT_STATUS_OK
;
1167 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
1168 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1169 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1170 /* We're already async. */
1171 return NT_STATUS_OK
;
1174 if (req
->in
.vector_count
> i
+ SMBD_SMB2_NUM_IOV_PER_REQ
) {
1176 * We're trying to go async in a compound
1177 * request chain. This is not allowed.
1178 * Cancel the outstanding request.
1180 tevent_req_cancel(req
->subreq
);
1181 return smbd_smb2_request_error(req
,
1182 NT_STATUS_INSUFFICIENT_RESOURCES
);
1185 if (DEBUGLEVEL
>= 10) {
1186 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1187 (unsigned int)req
->current_idx
);
1188 print_req_vectors(req
);
1191 if (req
->out
.vector_count
>= (2*SMBD_SMB2_NUM_IOV_PER_REQ
)) {
1193 * This is a compound reply. We
1194 * must do an interim response
1195 * followed by the async response
1198 status
= smb2_send_async_interim_response(req
);
1199 if (!NT_STATUS_IS_OK(status
)) {
1204 * We're splitting off the last SMB2
1205 * request in a compound set, and the
1206 * smb2_send_async_interim_response()
1207 * call above just sent all the replies
1208 * for the previous SMB2 requests in
1209 * this compound set. So we're no longer
1210 * in the "compound_related_in_progress"
1211 * state, and this is no longer a compound
1214 req
->compound_related
= false;
1215 req
->sconn
->smb2
.compound_related_in_progress
= false;
1217 /* Re-arrange the in.vectors. */
1218 req
->in
.vector
[1] = req
->in
.vector
[i
];
1219 req
->in
.vector
[2] = req
->in
.vector
[i
+1];
1220 req
->in
.vector
[3] = req
->in
.vector
[i
+2];
1221 req
->in
.vector_count
= 4;
1223 /* Reset the new in size. */
1224 smb2_setup_nbt_length(req
->in
.vector
, 4);
1226 /* Now recreate the out.vectors. */
1227 outvec
= talloc_zero_array(req
, struct iovec
, 4);
1229 return NT_STATUS_NO_MEMORY
;
1232 /* 0 is always boilerplate and must
1233 * be of size 4 for the length field. */
1235 outvec
[0].iov_base
= req
->out
.nbt_hdr
;
1236 outvec
[0].iov_len
= 4;
1237 SIVAL(req
->out
.nbt_hdr
, 0, 0);
1239 if (!dup_smb2_vec3(outvec
, &outvec
[1], &req
->out
.vector
[i
])) {
1240 return NT_STATUS_NO_MEMORY
;
1243 TALLOC_FREE(req
->out
.vector
);
1245 req
->out
.vector
= outvec
;
1247 req
->current_idx
= 1;
1248 req
->out
.vector_count
= 4;
1250 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1251 flags
= (IVAL(outhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
1252 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
);
1255 defer_endtime
= timeval_current_ofs_usec(defer_time
);
1256 req
->async_te
= tevent_add_timer(req
->sconn
->ev_ctx
,
1258 smbd_smb2_request_pending_timer
,
1260 if (req
->async_te
== NULL
) {
1261 return NT_STATUS_NO_MEMORY
;
1264 return NT_STATUS_OK
;
1267 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
1268 struct tevent_timer
*te
,
1269 struct timeval current_time
,
1272 struct smbd_smb2_request
*req
=
1273 talloc_get_type_abort(private_data
,
1274 struct smbd_smb2_request
);
1275 struct smbd_smb2_request_pending_state
*state
= NULL
;
1276 uint8_t *outhdr
= NULL
;
1277 const uint8_t *inhdr
= NULL
;
1278 uint8_t *hdr
= NULL
;
1279 uint8_t *body
= NULL
;
1281 uint64_t message_id
= 0;
1282 uint64_t async_id
= 0;
1283 struct tevent_req
*subreq
= NULL
;
1285 TALLOC_FREE(req
->async_te
);
1287 /* Ensure our final reply matches the interim one. */
1288 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1289 outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
1290 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1291 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1293 async_id
= message_id
; /* keep it simple for now... */
1295 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1296 SBVAL(outhdr
, SMB2_HDR_ASYNC_ID
, async_id
);
1298 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1300 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1301 (unsigned long long)async_id
));
1304 * What we send is identical to a smbd_smb2_request_error
1305 * packet with an error status of STATUS_PENDING. Make use
1306 * of this fact sometime when refactoring. JRA.
1309 state
= talloc_zero(req
->sconn
, struct smbd_smb2_request_pending_state
);
1310 if (state
== NULL
) {
1311 smbd_server_connection_terminate(req
->sconn
,
1312 nt_errstr(NT_STATUS_NO_MEMORY
));
1315 state
->sconn
= req
->sconn
;
1317 state
->vector
[0].iov_base
= (void *)state
->buf
;
1318 state
->vector
[0].iov_len
= 4;
1320 state
->vector
[1].iov_base
= state
->buf
+ 4;
1321 state
->vector
[1].iov_len
= SMB2_HDR_BODY
;
1323 state
->vector
[2].iov_base
= state
->buf
+ 4 + SMB2_HDR_BODY
;
1324 state
->vector
[2].iov_len
= 9;
1326 smb2_setup_nbt_length(state
->vector
, 3);
1328 hdr
= (uint8_t *)state
->vector
[1].iov_base
;
1329 body
= (uint8_t *)state
->vector
[2].iov_base
;
1331 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
1332 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1333 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1334 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
1335 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(outhdr
, SMB2_HDR_OPCODE
));
1337 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
);
1338 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1339 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
1340 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
1341 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
1342 BVAL(outhdr
, SMB2_HDR_SESSION_ID
));
1343 memcpy(hdr
+SMB2_HDR_SIGNATURE
,
1344 outhdr
+SMB2_HDR_SIGNATURE
, 16);
1346 SSVAL(body
, 0x00, 0x08 + 1);
1348 SCVAL(body
, 0x02, 0);
1349 SCVAL(body
, 0x03, 0);
1350 SIVAL(body
, 0x04, 0);
1351 /* Match W2K8R2... */
1352 SCVAL(body
, 0x08, 0x21);
1354 /* Ensure we correctly go through crediting. Grant
1355 the credits now, and zero credits on the final
1357 smb2_set_operation_credit(req
->sconn
,
1358 SMBD_SMB2_IN_HDR_IOV(req
),
1361 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1363 if (req
->do_signing
) {
1365 struct smbXsrv_session
*x
= req
->session
;
1366 struct smbXsrv_connection
*conn
= x
->connection
;
1367 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
1369 status
= smb2_signing_sign_pdu(signing_key
,
1371 &state
->vector
[1], 2);
1372 if (!NT_STATUS_IS_OK(status
)) {
1373 smbd_server_connection_terminate(req
->sconn
,
1379 subreq
= tstream_writev_queue_send(state
,
1380 state
->sconn
->ev_ctx
,
1381 state
->sconn
->smb2
.stream
,
1382 state
->sconn
->smb2
.send_queue
,
1385 if (subreq
== NULL
) {
1386 smbd_server_connection_terminate(state
->sconn
,
1387 nt_errstr(NT_STATUS_NO_MEMORY
));
1390 tevent_req_set_callback(subreq
,
1391 smbd_smb2_request_pending_writev_done
,
1395 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
1397 struct smbd_server_connection
*sconn
= req
->sconn
;
1398 struct smbd_smb2_request
*cur
;
1399 const uint8_t *inhdr
;
1401 uint64_t search_message_id
;
1402 uint64_t search_async_id
;
1405 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1407 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1408 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1409 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
1412 * we don't need the request anymore
1413 * cancel requests never have a response
1415 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1418 for (cur
= sconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
1419 const uint8_t *outhdr
;
1420 uint64_t message_id
;
1423 outhdr
= SMBD_SMB2_OUT_HDR_PTR(cur
);
1425 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1426 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
1428 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1429 if (search_async_id
== async_id
) {
1430 found_id
= async_id
;
1434 if (search_message_id
== message_id
) {
1435 found_id
= message_id
;
1441 if (cur
&& cur
->subreq
) {
1442 inhdr
= SMBD_SMB2_IN_HDR_PTR(cur
);
1443 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1444 "cancel opcode[%s] mid %llu\n",
1445 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1446 (unsigned long long)found_id
));
1447 tevent_req_cancel(cur
->subreq
);
1450 return NT_STATUS_OK
;
1453 /*************************************************************
1454 Ensure an incoming tid is a valid one for us to access.
1455 Change to the associated uid credentials and chdir to the
1456 valid tid directory.
1457 *************************************************************/
1459 static NTSTATUS
smbd_smb2_request_check_tcon(struct smbd_smb2_request
*req
)
1461 const uint8_t *inhdr
;
1464 struct smbXsrv_tcon
*tcon
;
1466 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1470 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1472 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1473 in_tid
= IVAL(inhdr
, SMB2_HDR_TID
);
1475 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1476 in_tid
= req
->last_tid
;
1479 status
= smb2srv_tcon_lookup(req
->session
,
1480 in_tid
, now
, &tcon
);
1481 if (!NT_STATUS_IS_OK(status
)) {
1485 if (!change_to_user(tcon
->compat
, req
->session
->compat
->vuid
)) {
1486 return NT_STATUS_ACCESS_DENIED
;
1489 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1490 if (!set_current_service(tcon
->compat
, 0, true)) {
1491 return NT_STATUS_ACCESS_DENIED
;
1495 req
->last_tid
= in_tid
;
1497 return NT_STATUS_OK
;
1500 /*************************************************************
1501 Ensure an incoming session_id is a valid one for us to access.
1502 *************************************************************/
1504 static NTSTATUS
smbd_smb2_request_check_session(struct smbd_smb2_request
*req
)
1506 const uint8_t *inhdr
;
1509 uint64_t in_session_id
;
1510 struct smbXsrv_session
*session
= NULL
;
1511 struct auth_session_info
*session_info
;
1513 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1515 req
->session
= NULL
;
1518 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1520 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1521 in_opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1522 in_session_id
= BVAL(inhdr
, SMB2_HDR_SESSION_ID
);
1524 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1525 in_session_id
= req
->last_session_id
;
1528 /* lookup an existing session */
1529 status
= smb2srv_session_lookup(req
->sconn
->conn
,
1533 req
->session
= session
;
1534 req
->last_session_id
= in_session_id
;
1536 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
1537 switch (in_opcode
) {
1538 case SMB2_OP_SESSSETUP
:
1539 status
= NT_STATUS_OK
;
1545 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1546 switch (in_opcode
) {
1548 case SMB2_OP_CREATE
:
1549 case SMB2_OP_GETINFO
:
1550 case SMB2_OP_SETINFO
:
1551 return NT_STATUS_INVALID_HANDLE
;
1554 * Notice the check for
1555 * (session_info == NULL)
1558 status
= NT_STATUS_OK
;
1562 if (!NT_STATUS_IS_OK(status
)) {
1566 session_info
= session
->global
->auth_session_info
;
1567 if (session_info
== NULL
) {
1568 return NT_STATUS_INVALID_HANDLE
;
1571 set_current_user_info(session_info
->unix_info
->sanitized_username
,
1572 session_info
->unix_info
->unix_name
,
1573 session_info
->info
->domain_name
);
1575 return NT_STATUS_OK
;
1578 NTSTATUS
smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request
*req
,
1579 uint32_t data_length
)
1581 uint16_t needed_charge
;
1582 uint16_t credit_charge
= 1;
1583 const uint8_t *inhdr
;
1585 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1587 if (req
->sconn
->smb2
.supports_multicredit
) {
1588 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
1589 credit_charge
= MAX(credit_charge
, 1);
1592 needed_charge
= (data_length
- 1)/ 65536 + 1;
1594 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1595 (unsigned long long) BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
),
1596 credit_charge
, needed_charge
));
1598 if (needed_charge
> credit_charge
) {
1599 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1600 credit_charge
, needed_charge
));
1601 return NT_STATUS_INVALID_PARAMETER
;
1604 return NT_STATUS_OK
;
1607 NTSTATUS
smbd_smb2_request_verify_sizes(struct smbd_smb2_request
*req
,
1608 size_t expected_body_size
)
1610 const uint8_t *inhdr
;
1612 const uint8_t *inbody
;
1613 int i
= req
->current_idx
;
1615 size_t min_dyn_size
= expected_body_size
& 0x00000001;
1618 * The following should be checked already.
1620 if ((i
+2) > req
->in
.vector_count
) {
1621 return NT_STATUS_INTERNAL_ERROR
;
1623 if (req
->in
.vector
[i
+0].iov_len
!= SMB2_HDR_BODY
) {
1624 return NT_STATUS_INTERNAL_ERROR
;
1626 if (req
->in
.vector
[i
+1].iov_len
< 2) {
1627 return NT_STATUS_INTERNAL_ERROR
;
1630 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1631 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1635 case SMB2_OP_GETINFO
:
1641 * Now check the expected body size,
1642 * where the last byte might be in the
1645 if (req
->in
.vector
[i
+1].iov_len
!= (expected_body_size
& 0xFFFFFFFE)) {
1646 return NT_STATUS_INVALID_PARAMETER
;
1648 if (req
->in
.vector
[i
+2].iov_len
< min_dyn_size
) {
1649 return NT_STATUS_INVALID_PARAMETER
;
1652 inbody
= (const uint8_t *)req
->in
.vector
[i
+1].iov_base
;
1654 body_size
= SVAL(inbody
, 0x00);
1655 if (body_size
!= expected_body_size
) {
1656 return NT_STATUS_INVALID_PARAMETER
;
1659 return NT_STATUS_OK
;
1662 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
1664 struct smbXsrv_connection
*conn
= req
->sconn
->conn
;
1665 const struct smbd_smb2_dispatch_table
*call
= NULL
;
1666 const uint8_t *inhdr
;
1671 NTSTATUS session_status
;
1672 uint32_t allowed_flags
;
1673 NTSTATUS return_value
;
1674 struct smbXsrv_session
*x
= NULL
;
1675 bool signing_required
= false;
1677 inhdr
= SMBD_SMB2_IN_HDR_PTR(req
);
1679 /* TODO: verify more things */
1681 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1682 opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1683 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1684 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1685 smb2_opcode_name(opcode
),
1686 (unsigned long long)mid
));
1688 if (conn
->protocol
>= PROTOCOL_SMB2_02
) {
1690 * once the protocol is negotiated
1691 * SMB2_OP_NEGPROT is not allowed anymore
1693 if (opcode
== SMB2_OP_NEGPROT
) {
1694 /* drop the connection */
1695 return NT_STATUS_INVALID_PARAMETER
;
1699 * if the protocol is not negotiated yet
1700 * only SMB2_OP_NEGPROT is allowed.
1702 if (opcode
!= SMB2_OP_NEGPROT
) {
1703 /* drop the connection */
1704 return NT_STATUS_INVALID_PARAMETER
;
1708 call
= smbd_smb2_call(opcode
);
1710 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1713 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
1714 SMB2_HDR_FLAG_SIGNED
|
1716 if (opcode
== SMB2_OP_CANCEL
) {
1717 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
1719 if ((flags
& ~allowed_flags
) != 0) {
1720 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1724 * Check if the client provided a valid session id,
1725 * if so smbd_smb2_request_check_session() calls
1726 * set_current_user_info().
1728 * As some command don't require a valid session id
1729 * we defer the check of the session_status
1731 session_status
= smbd_smb2_request_check_session(req
);
1735 signing_required
= x
->global
->signing_required
;
1737 if (opcode
== SMB2_OP_SESSSETUP
&&
1738 x
->global
->channels
[0].signing_key
.length
) {
1739 signing_required
= true;
1743 req
->do_signing
= false;
1744 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
1745 DATA_BLOB signing_key
;
1748 return smbd_smb2_request_error(
1749 req
, NT_STATUS_ACCESS_DENIED
);
1752 signing_key
= x
->global
->channels
[0].signing_key
;
1754 if (!NT_STATUS_IS_OK(session_status
)) {
1755 return smbd_smb2_request_error(req
, session_status
);
1758 req
->do_signing
= true;
1759 status
= smb2_signing_check_pdu(signing_key
,
1761 SMBD_SMB2_IN_HDR_IOV(req
),
1762 SMBD_SMB2_NUM_IOV_PER_REQ
);
1763 if (!NT_STATUS_IS_OK(status
)) {
1764 return smbd_smb2_request_error(req
, status
);
1766 } else if (opcode
== SMB2_OP_CANCEL
) {
1767 /* Cancel requests are allowed to skip the signing */
1768 } else if (signing_required
) {
1769 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
1772 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
1774 * This check is mostly for giving the correct error code
1775 * for compounded requests.
1777 * TODO: we may need to move this after the session
1780 if (!NT_STATUS_IS_OK(req
->next_status
)) {
1781 return smbd_smb2_request_error(req
, req
->next_status
);
1784 req
->compat_chain_fsp
= NULL
;
1787 if (req
->compound_related
) {
1788 req
->sconn
->smb2
.compound_related_in_progress
= true;
1791 if (call
->need_session
) {
1792 if (!NT_STATUS_IS_OK(session_status
)) {
1793 return smbd_smb2_request_error(req
, session_status
);
1797 if (call
->need_tcon
) {
1798 SMB_ASSERT(call
->need_session
);
1801 * This call needs to be run as user.
1803 * smbd_smb2_request_check_tcon()
1804 * calls change_to_user() on success.
1806 status
= smbd_smb2_request_check_tcon(req
);
1807 if (!NT_STATUS_IS_OK(status
)) {
1808 return smbd_smb2_request_error(req
, status
);
1812 if (call
->as_root
) {
1813 /* This call needs to be run as root */
1814 change_to_root_user();
1816 SMB_ASSERT(call
->need_tcon
);
1820 case SMB2_OP_NEGPROT
:
1822 START_PROFILE(smb2_negprot
);
1823 return_value
= smbd_smb2_request_process_negprot(req
);
1824 END_PROFILE(smb2_negprot
);
1828 case SMB2_OP_SESSSETUP
:
1830 START_PROFILE(smb2_sesssetup
);
1831 return_value
= smbd_smb2_request_process_sesssetup(req
);
1832 END_PROFILE(smb2_sesssetup
);
1836 case SMB2_OP_LOGOFF
:
1838 START_PROFILE(smb2_logoff
);
1839 return_value
= smbd_smb2_request_process_logoff(req
);
1840 END_PROFILE(smb2_logoff
);
1846 START_PROFILE(smb2_tcon
);
1847 return_value
= smbd_smb2_request_process_tcon(req
);
1848 END_PROFILE(smb2_tcon
);
1854 START_PROFILE(smb2_tdis
);
1855 return_value
= smbd_smb2_request_process_tdis(req
);
1856 END_PROFILE(smb2_tdis
);
1860 case SMB2_OP_CREATE
:
1862 START_PROFILE(smb2_create
);
1863 return_value
= smbd_smb2_request_process_create(req
);
1864 END_PROFILE(smb2_create
);
1870 START_PROFILE(smb2_close
);
1871 return_value
= smbd_smb2_request_process_close(req
);
1872 END_PROFILE(smb2_close
);
1878 START_PROFILE(smb2_flush
);
1879 return_value
= smbd_smb2_request_process_flush(req
);
1880 END_PROFILE(smb2_flush
);
1886 START_PROFILE(smb2_read
);
1887 return_value
= smbd_smb2_request_process_read(req
);
1888 END_PROFILE(smb2_read
);
1894 START_PROFILE(smb2_write
);
1895 return_value
= smbd_smb2_request_process_write(req
);
1896 END_PROFILE(smb2_write
);
1902 START_PROFILE(smb2_lock
);
1903 return_value
= smbd_smb2_request_process_lock(req
);
1904 END_PROFILE(smb2_lock
);
1910 START_PROFILE(smb2_ioctl
);
1911 return_value
= smbd_smb2_request_process_ioctl(req
);
1912 END_PROFILE(smb2_ioctl
);
1916 case SMB2_OP_CANCEL
:
1918 START_PROFILE(smb2_cancel
);
1919 return_value
= smbd_smb2_request_process_cancel(req
);
1920 END_PROFILE(smb2_cancel
);
1924 case SMB2_OP_KEEPALIVE
:
1926 START_PROFILE(smb2_keepalive
);
1927 return_value
= smbd_smb2_request_process_keepalive(req
);
1928 END_PROFILE(smb2_keepalive
);
1934 START_PROFILE(smb2_find
);
1935 return_value
= smbd_smb2_request_process_find(req
);
1936 END_PROFILE(smb2_find
);
1940 case SMB2_OP_NOTIFY
:
1942 START_PROFILE(smb2_notify
);
1943 return_value
= smbd_smb2_request_process_notify(req
);
1944 END_PROFILE(smb2_notify
);
1948 case SMB2_OP_GETINFO
:
1950 START_PROFILE(smb2_getinfo
);
1951 return_value
= smbd_smb2_request_process_getinfo(req
);
1952 END_PROFILE(smb2_getinfo
);
1956 case SMB2_OP_SETINFO
:
1958 START_PROFILE(smb2_setinfo
);
1959 return_value
= smbd_smb2_request_process_setinfo(req
);
1960 END_PROFILE(smb2_setinfo
);
1966 START_PROFILE(smb2_break
);
1967 return_value
= smbd_smb2_request_process_break(req
);
1968 END_PROFILE(smb2_break
);
1973 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1976 return return_value
;
1979 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
1981 struct tevent_req
*subreq
;
1982 struct iovec
*outhdr
= SMBD_SMB2_OUT_HDR_IOV(req
);
1983 struct iovec
*outdyn
= SMBD_SMB2_OUT_DYN_IOV(req
);
1986 TALLOC_FREE(req
->async_te
);
1988 req
->current_idx
+= SMBD_SMB2_NUM_IOV_PER_REQ
;
1990 if (req
->current_idx
< req
->out
.vector_count
) {
1992 * We must process the remaining compound
1993 * SMB2 requests before any new incoming SMB2
1994 * requests. This is because incoming SMB2
1995 * requests may include a cancel for a
1996 * compound request we haven't processed
1999 struct tevent_immediate
*im
= tevent_create_immediate(req
);
2001 return NT_STATUS_NO_MEMORY
;
2003 tevent_schedule_immediate(im
,
2005 smbd_smb2_request_dispatch_immediate
,
2007 return NT_STATUS_OK
;
2010 if (req
->compound_related
) {
2011 req
->sconn
->smb2
.compound_related_in_progress
= false;
2014 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
2016 /* Set credit for these operations (zero credits if this
2017 is a final reply for an async operation). */
2018 smb2_calculate_credits(req
, req
);
2020 if (req
->do_signing
) {
2022 struct smbXsrv_session
*x
= req
->session
;
2023 struct smbXsrv_connection
*conn
= x
->connection
;
2024 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
2026 status
= smb2_signing_sign_pdu(signing_key
,
2029 SMBD_SMB2_NUM_IOV_PER_REQ
);
2030 if (!NT_STATUS_IS_OK(status
)) {
2035 if (DEBUGLEVEL
>= 10) {
2036 dbgtext("smbd_smb2_request_reply: sending...\n");
2037 print_req_vectors(req
);
2040 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2041 if (req
->out
.vector_count
< (2*SMBD_SMB2_NUM_IOV_PER_REQ
) &&
2042 outdyn
->iov_base
== NULL
&& outdyn
->iov_len
!= 0) {
2043 /* Dynamic part is NULL. Chop it off,
2044 We're going to send it via sendfile. */
2045 req
->out
.vector_count
-= 1;
2048 subreq
= tstream_writev_queue_send(req
,
2050 req
->sconn
->smb2
.stream
,
2051 req
->sconn
->smb2
.send_queue
,
2053 req
->out
.vector_count
);
2054 if (subreq
== NULL
) {
2055 return NT_STATUS_NO_MEMORY
;
2057 tevent_req_set_callback(subreq
, smbd_smb2_request_writev_done
, req
);
2059 * We're done with this request -
2060 * move it off the "being processed" queue.
2062 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
2064 return NT_STATUS_OK
;
2067 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
);
2069 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
2070 struct tevent_immediate
*im
,
2073 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
2074 struct smbd_smb2_request
);
2075 struct smbd_server_connection
*sconn
= req
->sconn
;
2080 if (DEBUGLEVEL
>= 10) {
2081 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2082 req
->current_idx
, req
->in
.vector_count
));
2083 print_req_vectors(req
);
2086 status
= smbd_smb2_request_dispatch(req
);
2087 if (!NT_STATUS_IS_OK(status
)) {
2088 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2092 status
= smbd_smb2_request_next_incoming(sconn
);
2093 if (!NT_STATUS_IS_OK(status
)) {
2094 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2099 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
)
2101 struct smbd_smb2_request
*req
= tevent_req_callback_data(subreq
,
2102 struct smbd_smb2_request
);
2103 struct smbd_server_connection
*sconn
= req
->sconn
;
2108 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
2109 TALLOC_FREE(subreq
);
2112 status
= map_nt_error_from_unix(sys_errno
);
2113 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2114 nt_errstr(status
)));
2115 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2119 status
= smbd_smb2_request_next_incoming(sconn
);
2120 if (!NT_STATUS_IS_OK(status
)) {
2121 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2126 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
2128 DATA_BLOB body
, DATA_BLOB
*dyn
,
2129 const char *location
)
2132 int i
= req
->current_idx
;
2133 uint32_t next_command_ofs
;
2135 DEBUG(10,("smbd_smb2_request_done_ex: "
2136 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2137 i
, nt_errstr(status
), (unsigned int)body
.length
,
2139 (unsigned int)(dyn
? dyn
->length
: 0),
2142 if (body
.length
< 2) {
2143 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2146 if ((body
.length
% 2) != 0) {
2147 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2150 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
2152 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
2153 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
2155 req
->out
.vector
[i
+1].iov_base
= (void *)body
.data
;
2156 req
->out
.vector
[i
+1].iov_len
= body
.length
;
2159 req
->out
.vector
[i
+2].iov_base
= (void *)dyn
->data
;
2160 req
->out
.vector
[i
+2].iov_len
= dyn
->length
;
2162 req
->out
.vector
[i
+2].iov_base
= NULL
;
2163 req
->out
.vector
[i
+2].iov_len
= 0;
2166 /* see if we need to recalculate the offset to the next response */
2167 if (next_command_ofs
> 0) {
2168 next_command_ofs
= SMB2_HDR_BODY
;
2169 next_command_ofs
+= req
->out
.vector
[i
+1].iov_len
;
2170 next_command_ofs
+= req
->out
.vector
[i
+2].iov_len
;
2173 if ((next_command_ofs
% 8) != 0) {
2174 size_t pad_size
= 8 - (next_command_ofs
% 8);
2175 if (req
->out
.vector
[i
+2].iov_len
== 0) {
2177 * if the dyn buffer is empty
2178 * we can use it to add padding
2182 pad
= talloc_zero_array(req
->out
.vector
,
2185 return smbd_smb2_request_error(req
,
2186 NT_STATUS_NO_MEMORY
);
2189 req
->out
.vector
[i
+2].iov_base
= (void *)pad
;
2190 req
->out
.vector
[i
+2].iov_len
= pad_size
;
2193 * For now we copy the dynamic buffer
2194 * and add the padding to the new buffer
2201 old_size
= req
->out
.vector
[i
+2].iov_len
;
2202 old_dyn
= (uint8_t *)req
->out
.vector
[i
+2].iov_base
;
2204 new_size
= old_size
+ pad_size
;
2205 new_dyn
= talloc_zero_array(req
->out
.vector
,
2207 if (new_dyn
== NULL
) {
2208 return smbd_smb2_request_error(req
,
2209 NT_STATUS_NO_MEMORY
);
2212 memcpy(new_dyn
, old_dyn
, old_size
);
2213 memset(new_dyn
+ old_size
, 0, pad_size
);
2215 req
->out
.vector
[i
+2].iov_base
= (void *)new_dyn
;
2216 req
->out
.vector
[i
+2].iov_len
= new_size
;
2218 next_command_ofs
+= pad_size
;
2221 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
2223 return smbd_smb2_request_reply(req
);
2226 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
2229 const char *location
)
2232 int i
= req
->current_idx
;
2233 uint8_t *outhdr
= SMBD_SMB2_OUT_HDR_PTR(req
);
2235 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2236 i
, nt_errstr(status
), info
? " +info" : "",
2239 body
.data
= outhdr
+ SMB2_HDR_BODY
;
2241 SSVAL(body
.data
, 0, 9);
2244 SIVAL(body
.data
, 0x04, info
->length
);
2246 /* Allocated size of req->out.vector[i].iov_base
2247 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2248 * 1 byte without having to do an alloc.
2250 info
= talloc_zero_array(req
->out
.vector
,
2254 return NT_STATUS_NO_MEMORY
;
2256 info
->data
= ((uint8_t *)outhdr
) +
2257 OUTVEC_ALLOC_SIZE
- 1;
2259 SCVAL(info
->data
, 0, 0);
2263 * if a request fails, all other remaining
2264 * compounded requests should fail too
2266 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
2268 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
2272 struct smbd_smb2_send_oplock_break_state
{
2273 struct smbd_server_connection
*sconn
;
2274 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x18];
2275 struct iovec vector
;
2278 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
);
2280 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
2281 uint64_t file_id_persistent
,
2282 uint64_t file_id_volatile
,
2283 uint8_t oplock_level
)
2285 struct smbd_smb2_send_oplock_break_state
*state
;
2286 struct tevent_req
*subreq
;
2290 state
= talloc(sconn
, struct smbd_smb2_send_oplock_break_state
);
2291 if (state
== NULL
) {
2292 return NT_STATUS_NO_MEMORY
;
2294 state
->sconn
= sconn
;
2296 state
->vector
.iov_base
= (void *)state
->buf
;
2297 state
->vector
.iov_len
= sizeof(state
->buf
);
2299 _smb2_setlen(state
->buf
, sizeof(state
->buf
) - 4);
2300 hdr
= state
->buf
+ 4;
2301 body
= hdr
+ SMB2_HDR_BODY
;
2303 SIVAL(hdr
, 0, SMB2_MAGIC
);
2304 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
2305 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
2306 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
2307 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
2308 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
2309 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
2310 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
2311 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
2312 SIVAL(hdr
, SMB2_HDR_PID
, 0);
2313 SIVAL(hdr
, SMB2_HDR_TID
, 0);
2314 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
2315 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
2317 SSVAL(body
, 0x00, 0x18);
2319 SCVAL(body
, 0x02, oplock_level
);
2320 SCVAL(body
, 0x03, 0); /* reserved */
2321 SIVAL(body
, 0x04, 0); /* reserved */
2322 SBVAL(body
, 0x08, file_id_persistent
);
2323 SBVAL(body
, 0x10, file_id_volatile
);
2325 subreq
= tstream_writev_queue_send(state
,
2328 sconn
->smb2
.send_queue
,
2330 if (subreq
== NULL
) {
2331 return NT_STATUS_NO_MEMORY
;
2333 tevent_req_set_callback(subreq
,
2334 smbd_smb2_oplock_break_writev_done
,
2337 return NT_STATUS_OK
;
2340 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
)
2342 struct smbd_smb2_send_oplock_break_state
*state
=
2343 tevent_req_callback_data(subreq
,
2344 struct smbd_smb2_send_oplock_break_state
);
2345 struct smbd_server_connection
*sconn
= state
->sconn
;
2349 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
2350 TALLOC_FREE(subreq
);
2352 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
2353 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2360 struct smbd_smb2_request_read_state
{
2361 struct tevent_context
*ev
;
2362 struct smbd_server_connection
*sconn
;
2363 struct smbd_smb2_request
*smb2_req
;
2365 uint8_t nbt
[NBT_HDR_SIZE
];
2372 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2374 TALLOC_CTX
*mem_ctx
,
2375 struct iovec
**_vector
,
2377 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
);
2379 static struct tevent_req
*smbd_smb2_request_read_send(TALLOC_CTX
*mem_ctx
,
2380 struct tevent_context
*ev
,
2381 struct smbd_server_connection
*sconn
)
2383 struct tevent_req
*req
;
2384 struct smbd_smb2_request_read_state
*state
;
2385 struct tevent_req
*subreq
;
2387 req
= tevent_req_create(mem_ctx
, &state
,
2388 struct smbd_smb2_request_read_state
);
2393 state
->sconn
= sconn
;
2395 state
->smb2_req
= smbd_smb2_request_allocate(state
);
2396 if (tevent_req_nomem(state
->smb2_req
, req
)) {
2397 return tevent_req_post(req
, ev
);
2399 state
->smb2_req
->sconn
= sconn
;
2401 subreq
= tstream_readv_pdu_queue_send(state
->smb2_req
,
2403 state
->sconn
->smb2
.stream
,
2404 state
->sconn
->smb2
.recv_queue
,
2405 smbd_smb2_request_next_vector
,
2407 if (tevent_req_nomem(subreq
, req
)) {
2408 return tevent_req_post(req
, ev
);
2410 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
2415 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2417 TALLOC_CTX
*mem_ctx
,
2418 struct iovec
**_vector
,
2421 struct smbd_smb2_request_read_state
*state
=
2422 talloc_get_type_abort(private_data
,
2423 struct smbd_smb2_request_read_state
);
2424 struct iovec
*vector
;
2426 if (state
->pktlen
> 0) {
2427 /* if there're no remaining bytes, we're done */
2433 if (!state
->hdr
.done
) {
2435 * first we need to get the NBT header
2437 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2438 if (vector
== NULL
) {
2442 vector
[0].iov_base
= (void *)state
->hdr
.nbt
;
2443 vector
[0].iov_len
= NBT_HDR_SIZE
;
2448 state
->hdr
.done
= true;
2453 * Now we analyze the NBT header
2455 state
->pktlen
= smb2_len(state
->hdr
.nbt
);
2457 if (state
->pktlen
== 0) {
2458 /* if there're no remaining bytes, we're done */
2464 state
->pktbuf
= talloc_array(state
->smb2_req
, uint8_t, state
->pktlen
);
2465 if (state
->pktbuf
== NULL
) {
2469 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2470 if (vector
== NULL
) {
2474 vector
[0].iov_base
= (void *)state
->pktbuf
;
2475 vector
[0].iov_len
= state
->pktlen
;
2482 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
)
2484 struct tevent_req
*req
=
2485 tevent_req_callback_data(subreq
,
2487 struct smbd_smb2_request_read_state
*state
=
2488 tevent_req_data(req
,
2489 struct smbd_smb2_request_read_state
);
2495 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
2496 TALLOC_FREE(subreq
);
2498 status
= map_nt_error_from_unix(sys_errno
);
2499 tevent_req_nterror(req
, status
);
2503 if (state
->hdr
.nbt
[0] != 0x00) {
2504 DEBUG(1,("smbd_smb2_request_read_done: ignore NBT[0x%02X] msg\n",
2505 state
->hdr
.nbt
[0]));
2507 ZERO_STRUCT(state
->hdr
);
2508 TALLOC_FREE(state
->pktbuf
);
2511 subreq
= tstream_readv_pdu_queue_send(state
->smb2_req
,
2513 state
->sconn
->smb2
.stream
,
2514 state
->sconn
->smb2
.recv_queue
,
2515 smbd_smb2_request_next_vector
,
2517 if (tevent_req_nomem(subreq
, req
)) {
2520 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
2524 state
->smb2_req
->request_time
= timeval_current();
2525 now
= timeval_to_nttime(&state
->smb2_req
->request_time
);
2527 status
= smbd_smb2_inbuf_parse_compound(state
->smb2_req
->sconn
->conn
,
2532 &state
->smb2_req
->in
.vector
,
2533 &state
->smb2_req
->in
.vector_count
);
2534 if (tevent_req_nterror(req
, status
)) {
2538 state
->smb2_req
->current_idx
= 1;
2540 tevent_req_done(req
);
2543 static NTSTATUS
smbd_smb2_request_read_recv(struct tevent_req
*req
,
2544 TALLOC_CTX
*mem_ctx
,
2545 struct smbd_smb2_request
**_smb2_req
)
2547 struct smbd_smb2_request_read_state
*state
=
2548 tevent_req_data(req
,
2549 struct smbd_smb2_request_read_state
);
2552 if (tevent_req_is_nterror(req
, &status
)) {
2553 tevent_req_received(req
);
2557 *_smb2_req
= talloc_move(mem_ctx
, &state
->smb2_req
);
2558 tevent_req_received(req
);
2559 return NT_STATUS_OK
;
2562 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
);
2564 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
)
2566 size_t max_send_queue_len
;
2567 size_t cur_send_queue_len
;
2568 struct tevent_req
*subreq
;
2570 if (sconn
->smb2
.compound_related_in_progress
) {
2572 * Can't read another until the related
2575 return NT_STATUS_OK
;
2578 if (tevent_queue_length(sconn
->smb2
.recv_queue
) > 0) {
2580 * if there is already a smbd_smb2_request_read
2581 * pending, we are done.
2583 return NT_STATUS_OK
;
2586 max_send_queue_len
= MAX(1, sconn
->smb2
.max_credits
/16);
2587 cur_send_queue_len
= tevent_queue_length(sconn
->smb2
.send_queue
);
2589 if (cur_send_queue_len
> max_send_queue_len
) {
2591 * if we have a lot of requests to send,
2592 * we wait until they are on the wire until we
2593 * ask for the next request.
2595 return NT_STATUS_OK
;
2598 /* ask for the next request */
2599 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->ev_ctx
, sconn
);
2600 if (subreq
== NULL
) {
2601 return NT_STATUS_NO_MEMORY
;
2603 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);
2605 return NT_STATUS_OK
;
2608 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
2609 uint8_t *inbuf
, size_t size
)
2612 struct smbd_smb2_request
*req
= NULL
;
2614 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2615 (unsigned int)size
));
2617 status
= smbd_initialize_smb2(sconn
);
2618 if (!NT_STATUS_IS_OK(status
)) {
2619 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2623 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
2624 if (!NT_STATUS_IS_OK(status
)) {
2625 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2629 status
= smbd_smb2_request_validate(req
);
2630 if (!NT_STATUS_IS_OK(status
)) {
2631 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2635 status
= smbd_smb2_request_setup_out(req
);
2636 if (!NT_STATUS_IS_OK(status
)) {
2637 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2641 status
= smbd_smb2_request_dispatch(req
);
2642 if (!NT_STATUS_IS_OK(status
)) {
2643 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2647 status
= smbd_smb2_request_next_incoming(sconn
);
2648 if (!NT_STATUS_IS_OK(status
)) {
2649 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2653 sconn
->num_requests
++;
2656 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
)
2658 struct smbd_server_connection
*sconn
= tevent_req_callback_data(subreq
,
2659 struct smbd_server_connection
);
2661 struct smbd_smb2_request
*req
= NULL
;
2663 status
= smbd_smb2_request_read_recv(subreq
, sconn
, &req
);
2664 TALLOC_FREE(subreq
);
2665 if (!NT_STATUS_IS_OK(status
)) {
2666 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2667 nt_errstr(status
)));
2668 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2672 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2673 req
->current_idx
, req
->in
.vector_count
));
2675 status
= smbd_smb2_request_validate(req
);
2676 if (!NT_STATUS_IS_OK(status
)) {
2677 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2681 status
= smbd_smb2_request_setup_out(req
);
2682 if (!NT_STATUS_IS_OK(status
)) {
2683 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2687 status
= smbd_smb2_request_dispatch(req
);
2688 if (!NT_STATUS_IS_OK(status
)) {
2689 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2693 status
= smbd_smb2_request_next_incoming(sconn
);
2694 if (!NT_STATUS_IS_OK(status
)) {
2695 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2699 sconn
->num_requests
++;
2701 /* The timeout_processing function isn't run nearly
2702 often enough to implement 'max log size' without
2703 overrunning the size of the file by many megabytes.
2704 This is especially true if we are running at debug
2705 level 10. Checking every 50 SMB2s is a nice
2706 tradeoff of performance vs log file size overrun. */
2708 if ((sconn
->num_requests
% 50) == 0 &&
2709 need_to_check_log_size()) {
2710 change_to_root_user();