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 char *smb2_names
[] = {
57 const char *smb2_opcode_name(uint16_t opcode
)
60 return "Bad SMB2 opcode";
62 return smb2_names
[opcode
];
65 static void print_req_vectors(struct smbd_smb2_request
*req
)
69 for (i
= 0; i
< req
->in
.vector_count
; i
++) {
70 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
72 (unsigned int)req
->in
.vector
[i
].iov_len
);
74 for (i
= 0; i
< req
->out
.vector_count
; i
++) {
75 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
77 (unsigned int)req
->out
.vector
[i
].iov_len
);
81 bool smbd_is_smb2_header(const uint8_t *inbuf
, size_t size
)
83 if (size
< (4 + SMB2_HDR_BODY
)) {
87 if (IVAL(inbuf
, 4) != SMB2_MAGIC
) {
94 static NTSTATUS
smbd_initialize_smb2(struct smbd_server_connection
*sconn
)
99 TALLOC_FREE(sconn
->smb1
.fde
);
101 sconn
->smb2
.recv_queue
= tevent_queue_create(sconn
, "smb2 recv queue");
102 if (sconn
->smb2
.recv_queue
== NULL
) {
103 return NT_STATUS_NO_MEMORY
;
106 sconn
->smb2
.send_queue
= tevent_queue_create(sconn
, "smb2 send queue");
107 if (sconn
->smb2
.send_queue
== NULL
) {
108 return NT_STATUS_NO_MEMORY
;
111 sconn
->smb2
.seqnum_low
= 0;
112 sconn
->smb2
.seqnum_range
= 1;
113 sconn
->smb2
.credits_granted
= 1;
114 sconn
->smb2
.max_credits
= lp_smb2_max_credits();
115 sconn
->smb2
.credits_bitmap
= bitmap_talloc(sconn
,
116 sconn
->smb2
.max_credits
);
117 if (sconn
->smb2
.credits_bitmap
== NULL
) {
118 return NT_STATUS_NO_MEMORY
;
121 ret
= tstream_bsd_existing_socket(sconn
, sconn
->sock
,
122 &sconn
->smb2
.stream
);
124 status
= map_nt_error_from_unix(errno
);
128 /* Ensure child is set to non-blocking mode */
129 set_blocking(sconn
->sock
, false);
133 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
134 #define _smb2_setlen(_buf,len) do { \
135 uint8_t *buf = (uint8_t *)_buf; \
137 buf[1] = ((len)&0xFF0000)>>16; \
138 buf[2] = ((len)&0xFF00)>>8; \
139 buf[3] = (len)&0xFF; \
142 static void smb2_setup_nbt_length(struct iovec
*vector
, int count
)
147 for (i
=1; i
< count
; i
++) {
148 len
+= vector
[i
].iov_len
;
151 _smb2_setlen(vector
[0].iov_base
, len
);
154 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request
**req
)
157 (*req
)->parent
= NULL
;
158 (*req
)->mem_pool
= NULL
;
164 static int smbd_smb2_request_destructor(struct smbd_smb2_request
*req
)
168 talloc_free(req
->mem_pool
);
174 static struct smbd_smb2_request
*smbd_smb2_request_allocate(TALLOC_CTX
*mem_ctx
)
176 TALLOC_CTX
*mem_pool
;
177 struct smbd_smb2_request
**parent
;
178 struct smbd_smb2_request
*req
;
181 /* Enable this to find subtle valgrind errors. */
182 mem_pool
= talloc_init("smbd_smb2_request_allocate");
184 mem_pool
= talloc_pool(mem_ctx
, 8192);
186 if (mem_pool
== NULL
) {
190 parent
= talloc(mem_pool
, struct smbd_smb2_request
*);
191 if (parent
== NULL
) {
192 talloc_free(mem_pool
);
196 req
= talloc_zero(parent
, struct smbd_smb2_request
);
198 talloc_free(mem_pool
);
202 req
->mem_pool
= mem_pool
;
203 req
->parent
= parent
;
205 req
->last_session_id
= UINT64_MAX
;
206 req
->last_tid
= UINT32_MAX
;
208 talloc_set_destructor(parent
, smbd_smb2_request_parent_destructor
);
209 talloc_set_destructor(req
, smbd_smb2_request_destructor
);
214 static NTSTATUS
smbd_smb2_request_create(struct smbd_server_connection
*sconn
,
215 const uint8_t *inbuf
, size_t size
,
216 struct smbd_smb2_request
**_req
)
218 struct smbd_smb2_request
*req
;
219 uint32_t protocol_version
;
220 const uint8_t *inhdr
= NULL
;
223 uint32_t next_command_ofs
;
225 if (size
< (4 + SMB2_HDR_BODY
+ 2)) {
226 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size
));
227 return NT_STATUS_INVALID_PARAMETER
;
232 protocol_version
= IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
);
233 if (protocol_version
!= SMB2_MAGIC
) {
234 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
236 return NT_STATUS_INVALID_PARAMETER
;
239 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
240 if (cmd
!= SMB2_OP_NEGPROT
) {
241 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
243 return NT_STATUS_INVALID_PARAMETER
;
246 next_command_ofs
= IVAL(inhdr
, SMB2_HDR_NEXT_COMMAND
);
247 if (next_command_ofs
!= 0) {
248 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
250 return NT_STATUS_INVALID_PARAMETER
;
253 req
= smbd_smb2_request_allocate(sconn
);
255 return NT_STATUS_NO_MEMORY
;
259 talloc_steal(req
, inbuf
);
261 req
->in
.vector
= talloc_array(req
, struct iovec
, 4);
262 if (req
->in
.vector
== NULL
) {
264 return NT_STATUS_NO_MEMORY
;
266 req
->in
.vector_count
= 4;
268 memcpy(req
->in
.nbt_hdr
, inbuf
, 4);
271 req
->in
.vector
[0].iov_base
= discard_const_p(void, req
->in
.nbt_hdr
);
272 req
->in
.vector
[0].iov_len
= 4;
273 ofs
+= req
->in
.vector
[0].iov_len
;
275 req
->in
.vector
[1].iov_base
= discard_const_p(void, (inbuf
+ ofs
));
276 req
->in
.vector
[1].iov_len
= SMB2_HDR_BODY
;
277 ofs
+= req
->in
.vector
[1].iov_len
;
279 req
->in
.vector
[2].iov_base
= discard_const_p(void, (inbuf
+ ofs
));
280 req
->in
.vector
[2].iov_len
= SVAL(inbuf
, ofs
) & 0xFFFE;
281 ofs
+= req
->in
.vector
[2].iov_len
;
284 return NT_STATUS_INVALID_PARAMETER
;
287 req
->in
.vector
[3].iov_base
= discard_const_p(void, (inbuf
+ ofs
));
288 req
->in
.vector
[3].iov_len
= size
- ofs
;
289 ofs
+= req
->in
.vector
[3].iov_len
;
291 req
->current_idx
= 1;
297 static bool smb2_validate_sequence_number(struct smbd_server_connection
*sconn
,
298 uint64_t message_id
, uint64_t seq_id
)
300 struct bitmap
*credits_bm
= sconn
->smb2
.credits_bitmap
;
303 if (seq_id
< sconn
->smb2
.seqnum_low
) {
304 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
305 "%llu (sequence id %llu) "
306 "(granted = %u, low = %llu, range = %u)\n",
307 (unsigned long long)message_id
,
308 (unsigned long long)seq_id
,
309 (unsigned int)sconn
->smb2
.credits_granted
,
310 (unsigned long long)sconn
->smb2
.seqnum_low
,
311 (unsigned int)sconn
->smb2
.seqnum_range
));
315 if (seq_id
>= sconn
->smb2
.seqnum_low
+ sconn
->smb2
.seqnum_range
) {
316 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
317 "%llu (sequence id %llu) "
318 "(granted = %u, low = %llu, range = %u)\n",
319 (unsigned long long)message_id
,
320 (unsigned long long)seq_id
,
321 (unsigned int)sconn
->smb2
.credits_granted
,
322 (unsigned long long)sconn
->smb2
.seqnum_low
,
323 (unsigned int)sconn
->smb2
.seqnum_range
));
327 offset
= seq_id
% sconn
->smb2
.max_credits
;
329 if (bitmap_query(credits_bm
, offset
)) {
330 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
331 "%llu (sequence id %llu) "
332 "(granted = %u, low = %llu, range = %u) "
334 (unsigned long long)message_id
,
335 (unsigned long long)seq_id
,
336 (unsigned int)sconn
->smb2
.credits_granted
,
337 (unsigned long long)sconn
->smb2
.seqnum_low
,
338 (unsigned int)sconn
->smb2
.seqnum_range
,
343 /* Mark the message_ids as seen in the bitmap. */
344 bitmap_set(credits_bm
, offset
);
346 if (seq_id
!= sconn
->smb2
.seqnum_low
) {
351 * Move the window forward by all the message_id's
354 while (bitmap_query(credits_bm
, offset
)) {
355 DEBUG(10,("smb2_validate_sequence_number: clearing "
356 "id %llu (position %u) from bitmap\n",
357 (unsigned long long)(sconn
->smb2
.seqnum_low
),
359 bitmap_clear(credits_bm
, offset
);
361 sconn
->smb2
.seqnum_low
+= 1;
362 sconn
->smb2
.seqnum_range
-= 1;
363 offset
= sconn
->smb2
.seqnum_low
% sconn
->smb2
.max_credits
;
369 static bool smb2_validate_message_id(struct smbd_server_connection
*sconn
,
370 const uint8_t *inhdr
)
372 uint64_t message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
373 uint16_t opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
374 uint16_t credit_charge
= 1;
377 if (opcode
== SMB2_OP_CANCEL
) {
378 /* SMB2_CANCEL requests by definition resend messageids. */
382 if (sconn
->smb2
.supports_multicredit
) {
383 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
384 credit_charge
= MAX(credit_charge
, 1);
387 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
388 "credits_granted %llu, "
389 "seqnum low/range: %llu/%llu\n",
390 (unsigned long long) message_id
,
391 (unsigned long long) credit_charge
,
392 (unsigned long long) sconn
->smb2
.credits_granted
,
393 (unsigned long long) sconn
->smb2
.seqnum_low
,
394 (unsigned long long) sconn
->smb2
.seqnum_range
));
396 if (sconn
->smb2
.credits_granted
< credit_charge
) {
397 DEBUG(0, ("smb2_validate_message_id: client used more "
398 "credits than granted, mid %llu, charge %llu, "
399 "credits_granted %llu, "
400 "seqnum low/range: %llu/%llu\n",
401 (unsigned long long) message_id
,
402 (unsigned long long) credit_charge
,
403 (unsigned long long) sconn
->smb2
.credits_granted
,
404 (unsigned long long) sconn
->smb2
.seqnum_low
,
405 (unsigned long long) sconn
->smb2
.seqnum_range
));
410 * now check the message ids
412 * for multi-credit requests we need to check all current mid plus
413 * the implicit mids caused by the credit charge
414 * e.g. current mid = 15, charge 5 => mark 15-19 as used
417 for (i
= 0; i
<= (credit_charge
-1); i
++) {
418 uint64_t id
= message_id
+ i
;
421 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
422 (unsigned long long)message_id
,
424 (unsigned long long)id
));
426 ok
= smb2_validate_sequence_number(sconn
, message_id
, id
);
432 /* substract used credits */
433 sconn
->smb2
.credits_granted
-= credit_charge
;
438 static NTSTATUS
smbd_smb2_request_validate(struct smbd_smb2_request
*req
)
443 count
= req
->in
.vector_count
;
446 /* It's not a SMB2 request */
447 return NT_STATUS_INVALID_PARAMETER
;
450 for (idx
=1; idx
< count
; idx
+= 3) {
451 const uint8_t *inhdr
= NULL
;
454 if (req
->in
.vector
[idx
].iov_len
!= SMB2_HDR_BODY
) {
455 return NT_STATUS_INVALID_PARAMETER
;
458 if (req
->in
.vector
[idx
+1].iov_len
< 2) {
459 return NT_STATUS_INVALID_PARAMETER
;
462 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
464 /* Check the SMB2 header */
465 if (IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
) != SMB2_MAGIC
) {
466 return NT_STATUS_INVALID_PARAMETER
;
469 if (!smb2_validate_message_id(req
->sconn
, inhdr
)) {
470 return NT_STATUS_INVALID_PARAMETER
;
473 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
476 * the 1st request should never have the
477 * SMB2_HDR_FLAG_CHAINED flag set
479 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
480 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
483 } else if (idx
== 4) {
485 * the 2nd request triggers related vs. unrelated
486 * compounded requests
488 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
489 req
->compound_related
= true;
491 } else if (idx
> 4) {
494 * It seems the this tests are wrong
495 * see the SMB2-COMPOUND test
499 * all other requests should match the 2nd one
501 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
502 if (!req
->compound_related
) {
504 NT_STATUS_INVALID_PARAMETER
;
508 if (req
->compound_related
) {
510 NT_STATUS_INVALID_PARAMETER
;
521 static void smb2_set_operation_credit(struct smbd_server_connection
*sconn
,
522 const struct iovec
*in_vector
,
523 struct iovec
*out_vector
)
525 const uint8_t *inhdr
= (const uint8_t *)in_vector
->iov_base
;
526 uint8_t *outhdr
= (uint8_t *)out_vector
->iov_base
;
527 uint16_t credit_charge
= 1;
528 uint16_t credits_requested
;
532 uint16_t credits_granted
= 0;
533 uint64_t credits_possible
;
534 uint16_t current_max_credits
;
537 * first we grant only 1/16th of the max range.
539 * Windows also starts with the 1/16th and then grants
540 * more later. I was only able to trigger higher
541 * values, when using a verify high credit charge.
543 * TODO: scale up depending one load, free memory
545 * Maybe also on the relationship between number
546 * of requests and the used sequence number.
547 * Which means we would grant more credits
548 * for client which use multi credit requests.
550 current_max_credits
= sconn
->smb2
.max_credits
/ 16;
551 current_max_credits
= MAX(current_max_credits
, 1);
553 if (sconn
->smb2
.supports_multicredit
) {
554 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
555 credit_charge
= MAX(credit_charge
, 1);
558 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
559 credits_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
560 out_flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
561 out_status
= NT_STATUS(IVAL(outhdr
, SMB2_HDR_STATUS
));
563 SMB_ASSERT(sconn
->smb2
.max_credits
>= sconn
->smb2
.credits_granted
);
564 SMB_ASSERT(sconn
->smb2
.max_credits
>= credit_charge
);
566 if (out_flags
& SMB2_HDR_FLAG_ASYNC
) {
568 * In case we already send an async interim
569 * response, we should not grant
570 * credits on the final response.
573 } else if (credits_requested
> 0) {
574 uint16_t additional_max
= 0;
575 uint16_t additional_credits
= credits_requested
- 1;
578 case SMB2_OP_NEGPROT
:
580 case SMB2_OP_SESSSETUP
:
582 * Windows 2012 RC1 starts to grant
584 * with a successful session setup
586 if (NT_STATUS_IS_OK(out_status
)) {
592 * We match windows and only grant additional credits
599 additional_credits
= MIN(additional_credits
, additional_max
);
601 credits_granted
= credit_charge
+ additional_credits
;
602 } else if (sconn
->smb2
.credits_granted
== 0) {
604 * Make sure the client has always at least one credit
610 * sequence numbers should not wrap
612 * 1. calculate the possible credits until
613 * the sequence numbers start to wrap on 64-bit.
615 * 2. UINT64_MAX is used for Break Notifications.
617 * 2. truncate the possible credits to the maximum
618 * credits we want to grant to the client in total.
620 * 3. remove the range we'll already granted to the client
621 * this makes sure the client consumes the lowest sequence
622 * number, before we can grant additional credits.
624 credits_possible
= UINT64_MAX
- sconn
->smb2
.seqnum_low
;
625 if (credits_possible
> 0) {
626 /* remove UINT64_MAX */
627 credits_possible
-= 1;
629 credits_possible
= MIN(credits_possible
, current_max_credits
);
630 credits_possible
-= sconn
->smb2
.seqnum_range
;
632 credits_granted
= MIN(credits_granted
, credits_possible
);
634 SSVAL(outhdr
, SMB2_HDR_CREDIT
, credits_granted
);
635 sconn
->smb2
.credits_granted
+= credits_granted
;
636 sconn
->smb2
.seqnum_range
+= credits_granted
;
638 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
639 "granted %u, current possible/max %u/%u, "
640 "total granted/max/low/range %u/%u/%llu/%u\n",
641 (unsigned int)credits_requested
,
642 (unsigned int)credit_charge
,
643 (unsigned int)credits_granted
,
644 (unsigned int)credits_possible
,
645 (unsigned int)current_max_credits
,
646 (unsigned int)sconn
->smb2
.credits_granted
,
647 (unsigned int)sconn
->smb2
.max_credits
,
648 (unsigned long long)sconn
->smb2
.seqnum_low
,
649 (unsigned int)sconn
->smb2
.seqnum_range
));
652 static void smb2_calculate_credits(const struct smbd_smb2_request
*inreq
,
653 struct smbd_smb2_request
*outreq
)
656 uint16_t total_credits
= 0;
658 count
= outreq
->out
.vector_count
;
660 for (idx
=1; idx
< count
; idx
+= 3) {
661 uint8_t *outhdr
= (uint8_t *)outreq
->out
.vector
[idx
].iov_base
;
662 smb2_set_operation_credit(outreq
->sconn
,
663 &inreq
->in
.vector
[idx
],
664 &outreq
->out
.vector
[idx
]);
665 /* To match Windows, count up what we
667 total_credits
+= SVAL(outhdr
, SMB2_HDR_CREDIT
);
668 /* Set to zero in all but the last reply. */
669 if (idx
+ 3 < count
) {
670 SSVAL(outhdr
, SMB2_HDR_CREDIT
, 0);
672 SSVAL(outhdr
, SMB2_HDR_CREDIT
, total_credits
);
677 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
)
679 struct iovec
*vector
;
683 req
->request_time
= timeval_current();
685 count
= req
->in
.vector_count
;
686 vector
= talloc_zero_array(req
, struct iovec
, count
);
687 if (vector
== NULL
) {
688 return NT_STATUS_NO_MEMORY
;
691 vector
[0].iov_base
= req
->out
.nbt_hdr
;
692 vector
[0].iov_len
= 4;
693 SIVAL(req
->out
.nbt_hdr
, 0, 0);
695 for (idx
=1; idx
< count
; idx
+= 3) {
696 const uint8_t *inhdr
= NULL
;
697 uint8_t *outhdr
= NULL
;
698 uint8_t *outbody
= NULL
;
699 uint32_t next_command_ofs
= 0;
700 struct iovec
*current
= &vector
[idx
];
702 if ((idx
+ 3) < count
) {
703 /* we have a next command -
704 * setup for the error case. */
705 next_command_ofs
= SMB2_HDR_BODY
+ 9;
708 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
710 outhdr
= talloc_zero_array(vector
, uint8_t,
712 if (outhdr
== NULL
) {
713 return NT_STATUS_NO_MEMORY
;
716 outbody
= outhdr
+ SMB2_HDR_BODY
;
718 current
[0].iov_base
= (void *)outhdr
;
719 current
[0].iov_len
= SMB2_HDR_BODY
;
721 current
[1].iov_base
= (void *)outbody
;
722 current
[1].iov_len
= 8;
724 current
[2].iov_base
= NULL
;
725 current
[2].iov_len
= 0;
727 /* setup the SMB2 header */
728 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
729 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
730 SSVAL(outhdr
, SMB2_HDR_CREDIT_CHARGE
,
731 SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
));
732 SIVAL(outhdr
, SMB2_HDR_STATUS
,
733 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
734 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
735 SVAL(inhdr
, SMB2_HDR_OPCODE
));
736 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
737 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
738 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
739 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
740 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
741 SIVAL(outhdr
, SMB2_HDR_PID
,
742 IVAL(inhdr
, SMB2_HDR_PID
));
743 SIVAL(outhdr
, SMB2_HDR_TID
,
744 IVAL(inhdr
, SMB2_HDR_TID
));
745 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
746 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
747 memcpy(outhdr
+ SMB2_HDR_SIGNATURE
,
748 inhdr
+ SMB2_HDR_SIGNATURE
, 16);
750 /* setup error body header */
751 SSVAL(outbody
, 0x00, 0x08 + 1);
752 SSVAL(outbody
, 0x02, 0);
753 SIVAL(outbody
, 0x04, 0);
756 req
->out
.vector
= vector
;
757 req
->out
.vector_count
= count
;
759 /* setup the length of the NBT packet */
760 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
762 DLIST_ADD_END(req
->sconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
767 void smbd_server_connection_terminate_ex(struct smbd_server_connection
*sconn
,
769 const char *location
)
771 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
773 exit_server_cleanly(reason
);
776 static bool dup_smb2_vec3(TALLOC_CTX
*ctx
,
777 struct iovec
*outvec
,
778 const struct iovec
*srcvec
)
780 /* vec[0] is always boilerplate and must
781 * be allocated with size OUTVEC_ALLOC_SIZE. */
783 outvec
[0].iov_base
= talloc_memdup(ctx
,
786 if (!outvec
[0].iov_base
) {
789 outvec
[0].iov_len
= SMB2_HDR_BODY
;
792 * If this is a "standard" vec[1] of length 8,
793 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
794 * then duplicate this. Else use talloc_memdup().
797 if (srcvec
[1].iov_len
== 8 &&
798 srcvec
[1].iov_base
==
799 ((uint8_t *)srcvec
[0].iov_base
) +
801 outvec
[1].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
803 outvec
[1].iov_len
= 8;
805 outvec
[1].iov_base
= talloc_memdup(ctx
,
808 if (!outvec
[1].iov_base
) {
811 outvec
[1].iov_len
= srcvec
[1].iov_len
;
815 * If this is a "standard" vec[2] of length 1,
816 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
817 * then duplicate this. Else use talloc_memdup().
820 if (srcvec
[2].iov_base
&&
822 if (srcvec
[2].iov_base
==
823 ((uint8_t *)srcvec
[0].iov_base
) +
824 (OUTVEC_ALLOC_SIZE
- 1) &&
825 srcvec
[2].iov_len
== 1) {
826 /* Common SMB2 error packet case. */
827 outvec
[2].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
828 (OUTVEC_ALLOC_SIZE
- 1);
830 outvec
[2].iov_base
= talloc_memdup(ctx
,
833 if (!outvec
[2].iov_base
) {
837 outvec
[2].iov_len
= srcvec
[2].iov_len
;
839 outvec
[2].iov_base
= NULL
;
840 outvec
[2].iov_len
= 0;
845 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
847 struct smbd_smb2_request
*newreq
= NULL
;
848 struct iovec
*outvec
= NULL
;
849 int count
= req
->out
.vector_count
;
852 newreq
= smbd_smb2_request_allocate(req
->sconn
);
857 newreq
->sconn
= req
->sconn
;
858 newreq
->session
= req
->session
;
859 newreq
->do_signing
= req
->do_signing
;
860 newreq
->current_idx
= req
->current_idx
;
862 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
867 newreq
->out
.vector
= outvec
;
868 newreq
->out
.vector_count
= count
;
870 /* Setup the outvec's identically to req. */
871 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
872 outvec
[0].iov_len
= 4;
873 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
875 /* Setup the vectors identically to the ones in req. */
876 for (i
= 1; i
< count
; i
+= 3) {
877 if (!dup_smb2_vec3(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
888 smb2_setup_nbt_length(newreq
->out
.vector
,
889 newreq
->out
.vector_count
);
894 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
);
896 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
899 uint8_t *outhdr
= NULL
;
900 struct smbd_smb2_request
*nreq
= NULL
;
902 /* Create a new smb2 request we'll use
903 for the interim return. */
904 nreq
= dup_smb2_req(req
);
906 return NT_STATUS_NO_MEMORY
;
909 /* Lose the last 3 out vectors. They're the
910 ones we'll be using for the async reply. */
911 nreq
->out
.vector_count
-= 3;
913 smb2_setup_nbt_length(nreq
->out
.vector
,
914 nreq
->out
.vector_count
);
916 /* Step back to the previous reply. */
917 i
= nreq
->current_idx
- 3;
918 outhdr
= (uint8_t *)nreq
->out
.vector
[i
].iov_base
;
919 /* And end the chain. */
920 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
922 /* Calculate outgoing credits */
923 smb2_calculate_credits(req
, nreq
);
925 /* Re-sign if needed. */
926 if (nreq
->do_signing
) {
928 struct smbXsrv_session
*x
= nreq
->session
;
929 struct smbXsrv_connection
*conn
= x
->connection
;
930 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
932 status
= smb2_signing_sign_pdu(signing_key
,
934 &nreq
->out
.vector
[i
], 3);
935 if (!NT_STATUS_IS_OK(status
)) {
939 if (DEBUGLEVEL
>= 10) {
940 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
941 (unsigned int)nreq
->current_idx
);
942 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
943 (unsigned int)nreq
->out
.vector_count
);
944 print_req_vectors(nreq
);
946 nreq
->subreq
= tstream_writev_queue_send(nreq
,
948 nreq
->sconn
->smb2
.stream
,
949 nreq
->sconn
->smb2
.send_queue
,
951 nreq
->out
.vector_count
);
953 if (nreq
->subreq
== NULL
) {
954 return NT_STATUS_NO_MEMORY
;
957 tevent_req_set_callback(nreq
->subreq
,
958 smbd_smb2_request_writev_done
,
964 struct smbd_smb2_request_pending_state
{
965 struct smbd_server_connection
*sconn
;
966 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x08 + 1];
967 struct iovec vector
[3];
970 static void smbd_smb2_request_pending_writev_done(struct tevent_req
*subreq
)
972 struct smbd_smb2_request_pending_state
*state
=
973 tevent_req_callback_data(subreq
,
974 struct smbd_smb2_request_pending_state
);
975 struct smbd_server_connection
*sconn
= state
->sconn
;
979 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
982 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
983 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
990 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
991 struct tevent_timer
*te
,
992 struct timeval current_time
,
995 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
996 struct tevent_req
*subreq
,
1000 int i
= req
->current_idx
;
1001 struct timeval defer_endtime
;
1002 uint8_t *outhdr
= NULL
;
1005 if (!tevent_req_is_in_progress(subreq
)) {
1006 return NT_STATUS_OK
;
1009 req
->subreq
= subreq
;
1012 if (req
->async_te
) {
1013 /* We're already async. */
1014 return NT_STATUS_OK
;
1017 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
1018 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1019 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1020 /* We're already async. */
1021 return NT_STATUS_OK
;
1024 if (req
->in
.vector_count
> i
+ 3) {
1026 * We're trying to go async in a compound
1027 * request chain. This is not allowed.
1028 * Cancel the outstanding request.
1030 tevent_req_cancel(req
->subreq
);
1031 return smbd_smb2_request_error(req
,
1032 NT_STATUS_INSUFFICIENT_RESOURCES
);
1035 if (DEBUGLEVEL
>= 10) {
1036 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1037 (unsigned int)req
->current_idx
);
1038 print_req_vectors(req
);
1041 if (req
->out
.vector_count
> 4) {
1042 struct iovec
*outvec
= NULL
;
1044 /* This is a compound reply. We
1045 * must do an interim response
1046 * followed by the async response
1049 status
= smb2_send_async_interim_response(req
);
1050 if (!NT_STATUS_IS_OK(status
)) {
1055 * We're splitting off the last SMB2
1056 * request in a compound set, and the
1057 * smb2_send_async_interim_response()
1058 * call above just sent all the replies
1059 * for the previous SMB2 requests in
1060 * this compound set. So we're no longer
1061 * in the "compound_related_in_progress"
1062 * state, and this is no longer a compound
1065 req
->compound_related
= false;
1066 req
->sconn
->smb2
.compound_related_in_progress
= false;
1068 /* Re-arrange the in.vectors. */
1069 req
->in
.vector
[1] = req
->in
.vector
[i
];
1070 req
->in
.vector
[2] = req
->in
.vector
[i
+1];
1071 req
->in
.vector
[3] = req
->in
.vector
[i
+2];
1072 req
->in
.vector_count
= 4;
1074 /* Reset the new in size. */
1075 smb2_setup_nbt_length(req
->in
.vector
, 4);
1077 /* Now recreate the out.vectors. */
1078 outvec
= talloc_zero_array(req
, struct iovec
, 4);
1080 return NT_STATUS_NO_MEMORY
;
1083 /* 0 is always boilerplate and must
1084 * be of size 4 for the length field. */
1086 outvec
[0].iov_base
= req
->out
.nbt_hdr
;
1087 outvec
[0].iov_len
= 4;
1088 SIVAL(req
->out
.nbt_hdr
, 0, 0);
1090 if (!dup_smb2_vec3(outvec
, &outvec
[1], &req
->out
.vector
[i
])) {
1091 return NT_STATUS_NO_MEMORY
;
1094 TALLOC_FREE(req
->out
.vector
);
1096 req
->out
.vector
= outvec
;
1098 req
->current_idx
= 1;
1099 req
->out
.vector_count
= 4;
1101 outhdr
= (uint8_t *)req
->out
.vector
[1].iov_base
;
1102 flags
= (IVAL(outhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
1103 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
);
1106 defer_endtime
= timeval_current_ofs_usec(defer_time
);
1107 req
->async_te
= tevent_add_timer(req
->sconn
->ev_ctx
,
1109 smbd_smb2_request_pending_timer
,
1111 if (req
->async_te
== NULL
) {
1112 return NT_STATUS_NO_MEMORY
;
1115 return NT_STATUS_OK
;
1118 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
1119 struct tevent_timer
*te
,
1120 struct timeval current_time
,
1123 struct smbd_smb2_request
*req
=
1124 talloc_get_type_abort(private_data
,
1125 struct smbd_smb2_request
);
1126 struct smbd_smb2_request_pending_state
*state
= NULL
;
1127 int i
= req
->current_idx
;
1128 uint8_t *outhdr
= NULL
;
1129 const uint8_t *inhdr
= NULL
;
1130 uint8_t *hdr
= NULL
;
1131 uint8_t *body
= NULL
;
1133 uint64_t message_id
= 0;
1134 uint64_t async_id
= 0;
1135 struct tevent_req
*subreq
= NULL
;
1137 TALLOC_FREE(req
->async_te
);
1139 /* Ensure our final reply matches the interim one. */
1140 inhdr
= (const uint8_t *)req
->in
.vector
[1].iov_base
;
1141 outhdr
= (uint8_t *)req
->out
.vector
[1].iov_base
;
1142 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1143 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1145 async_id
= message_id
; /* keep it simple for now... */
1147 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1148 SBVAL(outhdr
, SMB2_HDR_ASYNC_ID
, async_id
);
1150 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1152 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1153 (unsigned long long)async_id
));
1156 * What we send is identical to a smbd_smb2_request_error
1157 * packet with an error status of STATUS_PENDING. Make use
1158 * of this fact sometime when refactoring. JRA.
1161 state
= talloc_zero(req
->sconn
, struct smbd_smb2_request_pending_state
);
1162 if (state
== NULL
) {
1163 smbd_server_connection_terminate(req
->sconn
,
1164 nt_errstr(NT_STATUS_NO_MEMORY
));
1167 state
->sconn
= req
->sconn
;
1169 state
->vector
[0].iov_base
= (void *)state
->buf
;
1170 state
->vector
[0].iov_len
= 4;
1172 state
->vector
[1].iov_base
= state
->buf
+ 4;
1173 state
->vector
[1].iov_len
= SMB2_HDR_BODY
;
1175 state
->vector
[2].iov_base
= state
->buf
+ 4 + SMB2_HDR_BODY
;
1176 state
->vector
[2].iov_len
= 9;
1178 smb2_setup_nbt_length(state
->vector
, 3);
1180 hdr
= (uint8_t *)state
->vector
[1].iov_base
;
1181 body
= (uint8_t *)state
->vector
[2].iov_base
;
1183 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
1184 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1185 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1186 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
1187 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(outhdr
, SMB2_HDR_OPCODE
));
1189 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
);
1190 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1191 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
1192 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
1193 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
1194 BVAL(outhdr
, SMB2_HDR_SESSION_ID
));
1195 memcpy(hdr
+SMB2_HDR_SIGNATURE
,
1196 outhdr
+SMB2_HDR_SIGNATURE
, 16);
1198 SSVAL(body
, 0x00, 0x08 + 1);
1200 SCVAL(body
, 0x02, 0);
1201 SCVAL(body
, 0x03, 0);
1202 SIVAL(body
, 0x04, 0);
1203 /* Match W2K8R2... */
1204 SCVAL(body
, 0x08, 0x21);
1206 /* Ensure we correctly go through crediting. Grant
1207 the credits now, and zero credits on the final
1209 smb2_set_operation_credit(req
->sconn
,
1213 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1215 if (req
->do_signing
) {
1217 struct smbXsrv_session
*x
= req
->session
;
1218 struct smbXsrv_connection
*conn
= x
->connection
;
1219 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
1221 status
= smb2_signing_sign_pdu(signing_key
,
1223 &state
->vector
[1], 2);
1224 if (!NT_STATUS_IS_OK(status
)) {
1225 smbd_server_connection_terminate(req
->sconn
,
1231 subreq
= tstream_writev_queue_send(state
,
1232 state
->sconn
->ev_ctx
,
1233 state
->sconn
->smb2
.stream
,
1234 state
->sconn
->smb2
.send_queue
,
1237 if (subreq
== NULL
) {
1238 smbd_server_connection_terminate(state
->sconn
,
1239 nt_errstr(NT_STATUS_NO_MEMORY
));
1242 tevent_req_set_callback(subreq
,
1243 smbd_smb2_request_pending_writev_done
,
1247 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
1249 struct smbd_server_connection
*sconn
= req
->sconn
;
1250 struct smbd_smb2_request
*cur
;
1251 const uint8_t *inhdr
;
1252 int i
= req
->current_idx
;
1254 uint64_t search_message_id
;
1255 uint64_t search_async_id
;
1258 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1260 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1261 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1262 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
1265 * we don't need the request anymore
1266 * cancel requests never have a response
1268 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1271 for (cur
= sconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
1272 const uint8_t *outhdr
;
1273 uint64_t message_id
;
1276 i
= cur
->current_idx
;
1278 outhdr
= (const uint8_t *)cur
->out
.vector
[i
].iov_base
;
1280 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1281 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
1283 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1284 if (search_async_id
== async_id
) {
1285 found_id
= async_id
;
1289 if (search_message_id
== message_id
) {
1290 found_id
= message_id
;
1296 if (cur
&& cur
->subreq
) {
1297 inhdr
= (const uint8_t *)cur
->in
.vector
[i
].iov_base
;
1298 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1299 "cancel opcode[%s] mid %llu\n",
1300 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1301 (unsigned long long)found_id
));
1302 tevent_req_cancel(cur
->subreq
);
1305 return NT_STATUS_OK
;
1308 /*************************************************************
1309 Ensure an incoming tid is a valid one for us to access.
1310 Change to the associated uid credentials and chdir to the
1311 valid tid directory.
1312 *************************************************************/
1314 static NTSTATUS
smbd_smb2_request_check_tcon(struct smbd_smb2_request
*req
)
1316 const uint8_t *inhdr
;
1317 int i
= req
->current_idx
;
1320 struct smbXsrv_tcon0
*tcon
;
1322 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1326 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1328 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1329 in_tid
= IVAL(inhdr
, SMB2_HDR_TID
);
1331 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1332 in_tid
= req
->last_tid
;
1335 status
= smb2srv_tcon_lookup(req
->session
,
1336 in_tid
, now
, &tcon
);
1337 if (!NT_STATUS_IS_OK(status
)) {
1341 if (!change_to_user(tcon
->compat
, req
->session
->compat
->vuid
)) {
1342 return NT_STATUS_ACCESS_DENIED
;
1345 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1346 if (!set_current_service(tcon
->compat
, 0, true)) {
1347 return NT_STATUS_ACCESS_DENIED
;
1351 req
->last_tid
= in_tid
;
1353 return NT_STATUS_OK
;
1356 /*************************************************************
1357 Ensure an incoming session_id is a valid one for us to access.
1358 *************************************************************/
1360 static NTSTATUS
smbd_smb2_request_check_session(struct smbd_smb2_request
*req
)
1362 const uint8_t *inhdr
;
1363 int i
= req
->current_idx
;
1366 uint64_t in_session_id
;
1367 struct smbXsrv_session
*session
= NULL
;
1368 struct auth_session_info
*session_info
;
1370 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1372 req
->session
= NULL
;
1375 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1377 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1378 in_opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1379 in_session_id
= BVAL(inhdr
, SMB2_HDR_SESSION_ID
);
1381 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1382 in_session_id
= req
->last_session_id
;
1385 /* lookup an existing session */
1386 status
= smb2srv_session_lookup(req
->sconn
->conn
,
1390 req
->session
= session
;
1391 req
->last_session_id
= in_session_id
;
1393 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
1394 switch (in_opcode
) {
1395 case SMB2_OP_SESSSETUP
:
1396 status
= NT_STATUS_OK
;
1402 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1403 switch (in_opcode
) {
1405 case SMB2_OP_CREATE
:
1406 case SMB2_OP_GETINFO
:
1407 case SMB2_OP_SETINFO
:
1408 return NT_STATUS_INVALID_HANDLE
;
1411 * Notice the check for
1412 * (session_info == NULL)
1415 status
= NT_STATUS_OK
;
1419 if (!NT_STATUS_IS_OK(status
)) {
1423 session_info
= session
->global
->auth_session_info
;
1424 if (session_info
== NULL
) {
1425 return NT_STATUS_INVALID_HANDLE
;
1428 set_current_user_info(session_info
->unix_info
->sanitized_username
,
1429 session_info
->unix_info
->unix_name
,
1430 session_info
->info
->domain_name
);
1432 return NT_STATUS_OK
;
1435 NTSTATUS
smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request
*req
,
1436 uint32_t data_length
)
1438 uint16_t needed_charge
;
1439 uint16_t credit_charge
;
1440 const uint8_t *inhdr
;
1441 int i
= req
->current_idx
;
1443 if (!req
->sconn
->smb2
.supports_multicredit
) {
1444 if (data_length
> 65536) {
1445 return NT_STATUS_INVALID_PARAMETER
;
1447 return NT_STATUS_OK
;
1450 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1451 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
1452 credit_charge
= MAX(credit_charge
, 1);
1454 needed_charge
= (data_length
- 1)/ 65536 + 1;
1456 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1457 (unsigned long long) BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
),
1458 credit_charge
, needed_charge
));
1460 if (needed_charge
> credit_charge
) {
1461 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1462 credit_charge
, needed_charge
));
1463 return NT_STATUS_INVALID_PARAMETER
;
1466 return NT_STATUS_OK
;
1469 NTSTATUS
smbd_smb2_request_verify_sizes(struct smbd_smb2_request
*req
,
1470 size_t expected_body_size
)
1472 const uint8_t *inhdr
;
1474 const uint8_t *inbody
;
1475 int i
= req
->current_idx
;
1477 size_t min_dyn_size
= expected_body_size
& 0x00000001;
1480 * The following should be checked already.
1482 if ((i
+2) > req
->in
.vector_count
) {
1483 return NT_STATUS_INTERNAL_ERROR
;
1485 if (req
->in
.vector
[i
+0].iov_len
!= SMB2_HDR_BODY
) {
1486 return NT_STATUS_INTERNAL_ERROR
;
1488 if (req
->in
.vector
[i
+1].iov_len
< 2) {
1489 return NT_STATUS_INTERNAL_ERROR
;
1492 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1493 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1497 case SMB2_OP_GETINFO
:
1503 * Now check the expected body size,
1504 * where the last byte might be in the
1507 if (req
->in
.vector
[i
+1].iov_len
!= (expected_body_size
& 0xFFFFFFFE)) {
1508 return NT_STATUS_INVALID_PARAMETER
;
1510 if (req
->in
.vector
[i
+2].iov_len
< min_dyn_size
) {
1511 return NT_STATUS_INVALID_PARAMETER
;
1514 inbody
= (const uint8_t *)req
->in
.vector
[i
+1].iov_base
;
1516 body_size
= SVAL(inbody
, 0x00);
1517 if (body_size
!= expected_body_size
) {
1518 return NT_STATUS_INVALID_PARAMETER
;
1521 return NT_STATUS_OK
;
1524 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
1526 const uint8_t *inhdr
;
1527 int i
= req
->current_idx
;
1532 NTSTATUS session_status
;
1533 uint32_t allowed_flags
;
1534 NTSTATUS return_value
;
1535 struct smbXsrv_session
*x
= NULL
;
1536 bool signing_required
= false;
1538 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1540 /* TODO: verify more things */
1542 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1543 opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1544 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1545 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1546 smb2_opcode_name(opcode
),
1547 (unsigned long long)mid
));
1549 if (get_Protocol() >= PROTOCOL_SMB2_02
) {
1551 * once the protocol is negotiated
1552 * SMB2_OP_NEGPROT is not allowed anymore
1554 if (opcode
== SMB2_OP_NEGPROT
) {
1555 /* drop the connection */
1556 return NT_STATUS_INVALID_PARAMETER
;
1560 * if the protocol is not negotiated yet
1561 * only SMB2_OP_NEGPROT is allowed.
1563 if (opcode
!= SMB2_OP_NEGPROT
) {
1564 /* drop the connection */
1565 return NT_STATUS_INVALID_PARAMETER
;
1569 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
1570 SMB2_HDR_FLAG_SIGNED
|
1572 if (opcode
== SMB2_OP_CANCEL
) {
1573 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
1575 if ((flags
& ~allowed_flags
) != 0) {
1576 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1580 * Check if the client provided a valid session id,
1581 * if so smbd_smb2_request_check_session() calls
1582 * set_current_user_info().
1584 * As some command don't require a valid session id
1585 * we defer the check of the session_status
1587 session_status
= smbd_smb2_request_check_session(req
);
1591 signing_required
= x
->global
->signing_required
;
1593 if (opcode
== SMB2_OP_SESSSETUP
&&
1594 x
->global
->channels
[0].signing_key
.length
) {
1595 signing_required
= true;
1599 req
->do_signing
= false;
1600 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
1601 struct smbXsrv_connection
*conn
= x
->connection
;
1602 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
1604 if (!NT_STATUS_IS_OK(session_status
)) {
1605 return smbd_smb2_request_error(req
, session_status
);
1608 req
->do_signing
= true;
1609 status
= smb2_signing_check_pdu(signing_key
,
1611 &req
->in
.vector
[i
], 3);
1612 if (!NT_STATUS_IS_OK(status
)) {
1613 return smbd_smb2_request_error(req
, status
);
1615 } else if (opcode
== SMB2_OP_CANCEL
) {
1616 /* Cancel requests are allowed to skip the signing */
1617 } else if (signing_required
) {
1618 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
1621 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
1623 * This check is mostly for giving the correct error code
1624 * for compounded requests.
1626 * TODO: we may need to move this after the session
1629 if (!NT_STATUS_IS_OK(req
->next_status
)) {
1630 return smbd_smb2_request_error(req
, req
->next_status
);
1633 req
->compat_chain_fsp
= NULL
;
1636 if (req
->compound_related
) {
1637 req
->sconn
->smb2
.compound_related_in_progress
= true;
1641 case SMB2_OP_NEGPROT
:
1642 /* This call needs to be run as root */
1643 change_to_root_user();
1646 START_PROFILE(smb2_negprot
);
1647 return_value
= smbd_smb2_request_process_negprot(req
);
1648 END_PROFILE(smb2_negprot
);
1652 case SMB2_OP_SESSSETUP
:
1653 /* This call needs to be run as root */
1654 change_to_root_user();
1657 START_PROFILE(smb2_sesssetup
);
1658 return_value
= smbd_smb2_request_process_sesssetup(req
);
1659 END_PROFILE(smb2_sesssetup
);
1663 case SMB2_OP_LOGOFF
:
1664 if (!NT_STATUS_IS_OK(session_status
)) {
1665 return_value
= smbd_smb2_request_error(req
, session_status
);
1669 /* This call needs to be run as root */
1670 change_to_root_user();
1673 START_PROFILE(smb2_logoff
);
1674 return_value
= smbd_smb2_request_process_logoff(req
);
1675 END_PROFILE(smb2_logoff
);
1680 if (!NT_STATUS_IS_OK(session_status
)) {
1681 return_value
= smbd_smb2_request_error(req
, session_status
);
1686 * This call needs to be run as root.
1688 * smbd_smb2_request_process_tcon()
1689 * calls make_connection_snum(), which will call
1690 * change_to_user(), when needed.
1692 change_to_root_user();
1695 START_PROFILE(smb2_tcon
);
1696 return_value
= smbd_smb2_request_process_tcon(req
);
1697 END_PROFILE(smb2_tcon
);
1702 if (!NT_STATUS_IS_OK(session_status
)) {
1703 return_value
= smbd_smb2_request_error(req
, session_status
);
1707 * This call needs to be run as user.
1709 * smbd_smb2_request_check_tcon()
1710 * calls change_to_user() on success.
1712 status
= smbd_smb2_request_check_tcon(req
);
1713 if (!NT_STATUS_IS_OK(status
)) {
1714 return_value
= smbd_smb2_request_error(req
, status
);
1717 /* This call needs to be run as root */
1718 change_to_root_user();
1722 START_PROFILE(smb2_tdis
);
1723 return_value
= smbd_smb2_request_process_tdis(req
);
1724 END_PROFILE(smb2_tdis
);
1728 case SMB2_OP_CREATE
:
1729 if (!NT_STATUS_IS_OK(session_status
)) {
1730 return_value
= smbd_smb2_request_error(req
, session_status
);
1734 * This call needs to be run as user.
1736 * smbd_smb2_request_check_tcon()
1737 * calls change_to_user() on success.
1739 status
= smbd_smb2_request_check_tcon(req
);
1740 if (!NT_STATUS_IS_OK(status
)) {
1741 return_value
= smbd_smb2_request_error(req
, status
);
1746 START_PROFILE(smb2_create
);
1747 return_value
= smbd_smb2_request_process_create(req
);
1748 END_PROFILE(smb2_create
);
1753 if (!NT_STATUS_IS_OK(session_status
)) {
1754 return_value
= smbd_smb2_request_error(req
, session_status
);
1758 * This call needs to be run as user.
1760 * smbd_smb2_request_check_tcon()
1761 * calls change_to_user() on success.
1763 status
= smbd_smb2_request_check_tcon(req
);
1764 if (!NT_STATUS_IS_OK(status
)) {
1765 return_value
= smbd_smb2_request_error(req
, status
);
1770 START_PROFILE(smb2_close
);
1771 return_value
= smbd_smb2_request_process_close(req
);
1772 END_PROFILE(smb2_close
);
1777 if (!NT_STATUS_IS_OK(session_status
)) {
1778 return_value
= smbd_smb2_request_error(req
, session_status
);
1782 * This call needs to be run as user.
1784 * smbd_smb2_request_check_tcon()
1785 * calls change_to_user() on success.
1787 status
= smbd_smb2_request_check_tcon(req
);
1788 if (!NT_STATUS_IS_OK(status
)) {
1789 return_value
= smbd_smb2_request_error(req
, status
);
1794 START_PROFILE(smb2_flush
);
1795 return_value
= smbd_smb2_request_process_flush(req
);
1796 END_PROFILE(smb2_flush
);
1801 if (!NT_STATUS_IS_OK(session_status
)) {
1802 return_value
= smbd_smb2_request_error(req
, session_status
);
1806 * This call needs to be run as user.
1808 * smbd_smb2_request_check_tcon()
1809 * calls change_to_user() on success.
1811 status
= smbd_smb2_request_check_tcon(req
);
1812 if (!NT_STATUS_IS_OK(status
)) {
1813 return_value
= smbd_smb2_request_error(req
, status
);
1818 START_PROFILE(smb2_read
);
1819 return_value
= smbd_smb2_request_process_read(req
);
1820 END_PROFILE(smb2_read
);
1825 if (!NT_STATUS_IS_OK(session_status
)) {
1826 return_value
= smbd_smb2_request_error(req
, session_status
);
1830 * This call needs to be run as user.
1832 * smbd_smb2_request_check_tcon()
1833 * calls change_to_user() on success.
1835 status
= smbd_smb2_request_check_tcon(req
);
1836 if (!NT_STATUS_IS_OK(status
)) {
1837 return_value
= smbd_smb2_request_error(req
, status
);
1842 START_PROFILE(smb2_write
);
1843 return_value
= smbd_smb2_request_process_write(req
);
1844 END_PROFILE(smb2_write
);
1849 if (!NT_STATUS_IS_OK(session_status
)) {
1850 /* Too ugly to live ? JRA. */
1851 if (NT_STATUS_EQUAL(session_status
,NT_STATUS_USER_SESSION_DELETED
)) {
1852 session_status
= NT_STATUS_FILE_CLOSED
;
1854 return_value
= smbd_smb2_request_error(req
, session_status
);
1858 * This call needs to be run as user.
1860 * smbd_smb2_request_check_tcon()
1861 * calls change_to_user() on success.
1863 status
= smbd_smb2_request_check_tcon(req
);
1864 if (!NT_STATUS_IS_OK(status
)) {
1865 /* Too ugly to live ? JRA. */
1866 if (NT_STATUS_EQUAL(status
,NT_STATUS_NETWORK_NAME_DELETED
)) {
1867 status
= NT_STATUS_FILE_CLOSED
;
1869 return_value
= smbd_smb2_request_error(req
, status
);
1874 START_PROFILE(smb2_lock
);
1875 return_value
= smbd_smb2_request_process_lock(req
);
1876 END_PROFILE(smb2_lock
);
1881 if (!NT_STATUS_IS_OK(session_status
)) {
1882 return_value
= smbd_smb2_request_error(req
, session_status
);
1886 * This call needs to be run as user.
1888 * smbd_smb2_request_check_tcon()
1889 * calls change_to_user() on success.
1891 status
= smbd_smb2_request_check_tcon(req
);
1892 if (!NT_STATUS_IS_OK(status
)) {
1893 return_value
= smbd_smb2_request_error(req
, status
);
1898 START_PROFILE(smb2_ioctl
);
1899 return_value
= smbd_smb2_request_process_ioctl(req
);
1900 END_PROFILE(smb2_ioctl
);
1904 case SMB2_OP_CANCEL
:
1906 * This call needs to be run as root
1908 * That is what we also do in the SMB1 case.
1910 change_to_root_user();
1913 START_PROFILE(smb2_cancel
);
1914 return_value
= smbd_smb2_request_process_cancel(req
);
1915 END_PROFILE(smb2_cancel
);
1919 case SMB2_OP_KEEPALIVE
:
1920 /* This call needs to be run as root */
1921 change_to_root_user();
1924 START_PROFILE(smb2_keepalive
);
1925 return_value
= smbd_smb2_request_process_keepalive(req
);
1926 END_PROFILE(smb2_keepalive
);
1931 if (!NT_STATUS_IS_OK(session_status
)) {
1932 return_value
= smbd_smb2_request_error(req
, session_status
);
1936 * This call needs to be run as user.
1938 * smbd_smb2_request_check_tcon()
1939 * calls change_to_user() on success.
1941 status
= smbd_smb2_request_check_tcon(req
);
1942 if (!NT_STATUS_IS_OK(status
)) {
1943 return_value
= smbd_smb2_request_error(req
, status
);
1948 START_PROFILE(smb2_find
);
1949 return_value
= smbd_smb2_request_process_find(req
);
1950 END_PROFILE(smb2_find
);
1954 case SMB2_OP_NOTIFY
:
1955 if (!NT_STATUS_IS_OK(session_status
)) {
1956 return_value
= smbd_smb2_request_error(req
, session_status
);
1960 * This call needs to be run as user.
1962 * smbd_smb2_request_check_tcon()
1963 * calls change_to_user() on success.
1965 status
= smbd_smb2_request_check_tcon(req
);
1966 if (!NT_STATUS_IS_OK(status
)) {
1967 return_value
= smbd_smb2_request_error(req
, status
);
1972 START_PROFILE(smb2_notify
);
1973 return_value
= smbd_smb2_request_process_notify(req
);
1974 END_PROFILE(smb2_notify
);
1978 case SMB2_OP_GETINFO
:
1979 if (!NT_STATUS_IS_OK(session_status
)) {
1980 return_value
= smbd_smb2_request_error(req
, session_status
);
1984 * This call needs to be run as user.
1986 * smbd_smb2_request_check_tcon()
1987 * calls change_to_user() on success.
1989 status
= smbd_smb2_request_check_tcon(req
);
1990 if (!NT_STATUS_IS_OK(status
)) {
1991 return_value
= smbd_smb2_request_error(req
, status
);
1996 START_PROFILE(smb2_getinfo
);
1997 return_value
= smbd_smb2_request_process_getinfo(req
);
1998 END_PROFILE(smb2_getinfo
);
2002 case SMB2_OP_SETINFO
:
2003 if (!NT_STATUS_IS_OK(session_status
)) {
2004 return_value
= smbd_smb2_request_error(req
, session_status
);
2008 * This call needs to be run as user.
2010 * smbd_smb2_request_check_tcon()
2011 * calls change_to_user() on success.
2013 status
= smbd_smb2_request_check_tcon(req
);
2014 if (!NT_STATUS_IS_OK(status
)) {
2015 return_value
= smbd_smb2_request_error(req
, status
);
2020 START_PROFILE(smb2_setinfo
);
2021 return_value
= smbd_smb2_request_process_setinfo(req
);
2022 END_PROFILE(smb2_setinfo
);
2027 if (!NT_STATUS_IS_OK(session_status
)) {
2028 return_value
= smbd_smb2_request_error(req
, session_status
);
2032 * This call needs to be run as user.
2034 * smbd_smb2_request_check_tcon()
2035 * calls change_to_user() on success.
2037 status
= smbd_smb2_request_check_tcon(req
);
2038 if (!NT_STATUS_IS_OK(status
)) {
2039 return_value
= smbd_smb2_request_error(req
, status
);
2044 START_PROFILE(smb2_break
);
2045 return_value
= smbd_smb2_request_process_break(req
);
2046 END_PROFILE(smb2_break
);
2051 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2054 return return_value
;
2057 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
2059 struct tevent_req
*subreq
;
2060 int i
= req
->current_idx
;
2063 TALLOC_FREE(req
->async_te
);
2065 req
->current_idx
+= 3;
2067 if (req
->current_idx
< req
->out
.vector_count
) {
2069 * We must process the remaining compound
2070 * SMB2 requests before any new incoming SMB2
2071 * requests. This is because incoming SMB2
2072 * requests may include a cancel for a
2073 * compound request we haven't processed
2076 struct tevent_immediate
*im
= tevent_create_immediate(req
);
2078 return NT_STATUS_NO_MEMORY
;
2080 tevent_schedule_immediate(im
,
2082 smbd_smb2_request_dispatch_immediate
,
2084 return NT_STATUS_OK
;
2087 if (req
->compound_related
) {
2088 req
->sconn
->smb2
.compound_related_in_progress
= false;
2091 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
2093 /* Set credit for these operations (zero credits if this
2094 is a final reply for an async operation). */
2095 smb2_calculate_credits(req
, req
);
2097 if (req
->do_signing
) {
2099 struct smbXsrv_session
*x
= req
->session
;
2100 struct smbXsrv_connection
*conn
= x
->connection
;
2101 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
2103 status
= smb2_signing_sign_pdu(signing_key
,
2105 &req
->out
.vector
[i
], 3);
2106 if (!NT_STATUS_IS_OK(status
)) {
2111 if (DEBUGLEVEL
>= 10) {
2112 dbgtext("smbd_smb2_request_reply: sending...\n");
2113 print_req_vectors(req
);
2116 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2117 if (req
->out
.vector_count
== 4 &&
2118 req
->out
.vector
[3].iov_base
== NULL
&&
2119 req
->out
.vector
[3].iov_len
!= 0) {
2120 /* Dynamic part is NULL. Chop it off,
2121 We're going to send it via sendfile. */
2122 req
->out
.vector_count
-= 1;
2125 subreq
= tstream_writev_queue_send(req
,
2127 req
->sconn
->smb2
.stream
,
2128 req
->sconn
->smb2
.send_queue
,
2130 req
->out
.vector_count
);
2131 if (subreq
== NULL
) {
2132 return NT_STATUS_NO_MEMORY
;
2134 tevent_req_set_callback(subreq
, smbd_smb2_request_writev_done
, req
);
2136 * We're done with this request -
2137 * move it off the "being processed" queue.
2139 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
2141 return NT_STATUS_OK
;
2144 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
);
2146 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
2147 struct tevent_immediate
*im
,
2150 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
2151 struct smbd_smb2_request
);
2152 struct smbd_server_connection
*sconn
= req
->sconn
;
2157 if (DEBUGLEVEL
>= 10) {
2158 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2159 req
->current_idx
, req
->in
.vector_count
));
2160 print_req_vectors(req
);
2163 status
= smbd_smb2_request_dispatch(req
);
2164 if (!NT_STATUS_IS_OK(status
)) {
2165 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2169 status
= smbd_smb2_request_next_incoming(sconn
);
2170 if (!NT_STATUS_IS_OK(status
)) {
2171 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2176 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
)
2178 struct smbd_smb2_request
*req
= tevent_req_callback_data(subreq
,
2179 struct smbd_smb2_request
);
2180 struct smbd_server_connection
*sconn
= req
->sconn
;
2185 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
2186 TALLOC_FREE(subreq
);
2189 status
= map_nt_error_from_unix(sys_errno
);
2190 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2191 nt_errstr(status
)));
2192 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2196 status
= smbd_smb2_request_next_incoming(sconn
);
2197 if (!NT_STATUS_IS_OK(status
)) {
2198 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2203 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
2205 DATA_BLOB body
, DATA_BLOB
*dyn
,
2206 const char *location
)
2209 int i
= req
->current_idx
;
2210 uint32_t next_command_ofs
;
2212 DEBUG(10,("smbd_smb2_request_done_ex: "
2213 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2214 i
, nt_errstr(status
), (unsigned int)body
.length
,
2216 (unsigned int)(dyn
? dyn
->length
: 0),
2219 if (body
.length
< 2) {
2220 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2223 if ((body
.length
% 2) != 0) {
2224 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2227 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
2229 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
2230 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
2232 req
->out
.vector
[i
+1].iov_base
= (void *)body
.data
;
2233 req
->out
.vector
[i
+1].iov_len
= body
.length
;
2236 req
->out
.vector
[i
+2].iov_base
= (void *)dyn
->data
;
2237 req
->out
.vector
[i
+2].iov_len
= dyn
->length
;
2239 req
->out
.vector
[i
+2].iov_base
= NULL
;
2240 req
->out
.vector
[i
+2].iov_len
= 0;
2243 /* see if we need to recalculate the offset to the next response */
2244 if (next_command_ofs
> 0) {
2245 next_command_ofs
= SMB2_HDR_BODY
;
2246 next_command_ofs
+= req
->out
.vector
[i
+1].iov_len
;
2247 next_command_ofs
+= req
->out
.vector
[i
+2].iov_len
;
2250 if ((next_command_ofs
% 8) != 0) {
2251 size_t pad_size
= 8 - (next_command_ofs
% 8);
2252 if (req
->out
.vector
[i
+2].iov_len
== 0) {
2254 * if the dyn buffer is empty
2255 * we can use it to add padding
2259 pad
= talloc_zero_array(req
->out
.vector
,
2262 return smbd_smb2_request_error(req
,
2263 NT_STATUS_NO_MEMORY
);
2266 req
->out
.vector
[i
+2].iov_base
= (void *)pad
;
2267 req
->out
.vector
[i
+2].iov_len
= pad_size
;
2270 * For now we copy the dynamic buffer
2271 * and add the padding to the new buffer
2278 old_size
= req
->out
.vector
[i
+2].iov_len
;
2279 old_dyn
= (uint8_t *)req
->out
.vector
[i
+2].iov_base
;
2281 new_size
= old_size
+ pad_size
;
2282 new_dyn
= talloc_zero_array(req
->out
.vector
,
2284 if (new_dyn
== NULL
) {
2285 return smbd_smb2_request_error(req
,
2286 NT_STATUS_NO_MEMORY
);
2289 memcpy(new_dyn
, old_dyn
, old_size
);
2290 memset(new_dyn
+ old_size
, 0, pad_size
);
2292 req
->out
.vector
[i
+2].iov_base
= (void *)new_dyn
;
2293 req
->out
.vector
[i
+2].iov_len
= new_size
;
2295 next_command_ofs
+= pad_size
;
2298 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
2300 return smbd_smb2_request_reply(req
);
2303 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
2306 const char *location
)
2309 int i
= req
->current_idx
;
2310 uint8_t *outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
2312 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2313 i
, nt_errstr(status
), info
? " +info" : "",
2316 body
.data
= outhdr
+ SMB2_HDR_BODY
;
2318 SSVAL(body
.data
, 0, 9);
2321 SIVAL(body
.data
, 0x04, info
->length
);
2323 /* Allocated size of req->out.vector[i].iov_base
2324 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2325 * 1 byte without having to do an alloc.
2327 info
= talloc_zero_array(req
->out
.vector
,
2331 return NT_STATUS_NO_MEMORY
;
2333 info
->data
= ((uint8_t *)outhdr
) +
2334 OUTVEC_ALLOC_SIZE
- 1;
2336 SCVAL(info
->data
, 0, 0);
2340 * if a request fails, all other remaining
2341 * compounded requests should fail too
2343 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
2345 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
2349 struct smbd_smb2_send_oplock_break_state
{
2350 struct smbd_server_connection
*sconn
;
2351 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x18];
2352 struct iovec vector
;
2355 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
);
2357 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
2358 uint64_t file_id_persistent
,
2359 uint64_t file_id_volatile
,
2360 uint8_t oplock_level
)
2362 struct smbd_smb2_send_oplock_break_state
*state
;
2363 struct tevent_req
*subreq
;
2367 state
= talloc(sconn
, struct smbd_smb2_send_oplock_break_state
);
2368 if (state
== NULL
) {
2369 return NT_STATUS_NO_MEMORY
;
2371 state
->sconn
= sconn
;
2373 state
->vector
.iov_base
= (void *)state
->buf
;
2374 state
->vector
.iov_len
= sizeof(state
->buf
);
2376 _smb2_setlen(state
->buf
, sizeof(state
->buf
) - 4);
2377 hdr
= state
->buf
+ 4;
2378 body
= hdr
+ SMB2_HDR_BODY
;
2380 SIVAL(hdr
, 0, SMB2_MAGIC
);
2381 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
2382 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
2383 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
2384 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
2385 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
2386 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
2387 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
2388 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
2389 SIVAL(hdr
, SMB2_HDR_PID
, 0);
2390 SIVAL(hdr
, SMB2_HDR_TID
, 0);
2391 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
2392 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
2394 SSVAL(body
, 0x00, 0x18);
2396 SCVAL(body
, 0x02, oplock_level
);
2397 SCVAL(body
, 0x03, 0); /* reserved */
2398 SIVAL(body
, 0x04, 0); /* reserved */
2399 SBVAL(body
, 0x08, file_id_persistent
);
2400 SBVAL(body
, 0x10, file_id_volatile
);
2402 subreq
= tstream_writev_queue_send(state
,
2405 sconn
->smb2
.send_queue
,
2407 if (subreq
== NULL
) {
2408 return NT_STATUS_NO_MEMORY
;
2410 tevent_req_set_callback(subreq
,
2411 smbd_smb2_oplock_break_writev_done
,
2414 return NT_STATUS_OK
;
2417 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
)
2419 struct smbd_smb2_send_oplock_break_state
*state
=
2420 tevent_req_callback_data(subreq
,
2421 struct smbd_smb2_send_oplock_break_state
);
2422 struct smbd_server_connection
*sconn
= state
->sconn
;
2426 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
2427 TALLOC_FREE(subreq
);
2429 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
2430 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2437 struct smbd_smb2_request_read_state
{
2439 bool asked_for_header
;
2440 struct smbd_smb2_request
*smb2_req
;
2443 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2445 TALLOC_CTX
*mem_ctx
,
2446 struct iovec
**_vector
,
2448 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
);
2450 static struct tevent_req
*smbd_smb2_request_read_send(TALLOC_CTX
*mem_ctx
,
2451 struct tevent_context
*ev
,
2452 struct smbd_server_connection
*sconn
)
2454 struct tevent_req
*req
;
2455 struct smbd_smb2_request_read_state
*state
;
2456 struct tevent_req
*subreq
;
2458 req
= tevent_req_create(mem_ctx
, &state
,
2459 struct smbd_smb2_request_read_state
);
2464 state
->asked_for_header
= false;
2466 state
->smb2_req
= smbd_smb2_request_allocate(state
);
2467 if (tevent_req_nomem(state
->smb2_req
, req
)) {
2468 return tevent_req_post(req
, ev
);
2470 state
->smb2_req
->sconn
= sconn
;
2472 subreq
= tstream_readv_pdu_queue_send(state
, ev
, sconn
->smb2
.stream
,
2473 sconn
->smb2
.recv_queue
,
2474 smbd_smb2_request_next_vector
,
2476 if (tevent_req_nomem(subreq
, req
)) {
2477 return tevent_req_post(req
, ev
);
2479 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
2484 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2486 TALLOC_CTX
*mem_ctx
,
2487 struct iovec
**_vector
,
2490 struct smbd_smb2_request_read_state
*state
=
2491 talloc_get_type_abort(private_data
,
2492 struct smbd_smb2_request_read_state
);
2493 struct smbd_smb2_request
*req
= state
->smb2_req
;
2494 struct iovec
*vector
;
2495 int idx
= req
->in
.vector_count
;
2497 uint8_t *buf
= NULL
;
2499 if (req
->in
.vector_count
== 0) {
2501 * first we need to get the NBT header
2503 req
->in
.vector
= talloc_array(req
, struct iovec
,
2504 req
->in
.vector_count
+ 1);
2505 if (req
->in
.vector
== NULL
) {
2508 req
->in
.vector_count
+= 1;
2510 req
->in
.vector
[idx
].iov_base
= (void *)req
->in
.nbt_hdr
;
2511 req
->in
.vector
[idx
].iov_len
= 4;
2513 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2514 if (vector
== NULL
) {
2518 vector
[0] = req
->in
.vector
[idx
];
2525 if (req
->in
.vector_count
== 1) {
2527 * Now we analyze the NBT header
2529 state
->missing
= smb2_len(req
->in
.vector
[0].iov_base
);
2531 if (state
->missing
== 0) {
2532 /* if there're no remaining bytes, we're done */
2538 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2540 req
->in
.vector_count
+ 1);
2541 if (req
->in
.vector
== NULL
) {
2544 req
->in
.vector_count
+= 1;
2546 if (CVAL(req
->in
.vector
[0].iov_base
, 0) != 0) {
2548 * it's a special NBT message,
2549 * so get all remaining bytes
2551 len
= state
->missing
;
2552 } else if (state
->missing
< (SMB2_HDR_BODY
+ 2)) {
2554 * it's an invalid message, just read what we can get
2555 * and let the caller handle the error
2557 len
= state
->missing
;
2560 * We assume it's a SMB2 request,
2561 * and we first get the header and the
2562 * first 2 bytes (the struct size) of the body
2564 len
= SMB2_HDR_BODY
+ 2;
2566 state
->asked_for_header
= true;
2569 state
->missing
-= len
;
2571 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2576 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2577 req
->in
.vector
[idx
].iov_len
= len
;
2579 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2580 if (vector
== NULL
) {
2584 vector
[0] = req
->in
.vector
[idx
];
2591 if (state
->missing
== 0) {
2592 /* if there're no remaining bytes, we're done */
2598 if (state
->asked_for_header
) {
2601 size_t next_command_ofs
;
2606 bool invalid
= false;
2608 state
->asked_for_header
= false;
2611 * We got the SMB2 header and the first 2 bytes
2612 * of the body. We fix the size to just the header
2613 * and manually copy the 2 first bytes to the body section
2615 req
->in
.vector
[idx
-1].iov_len
= SMB2_HDR_BODY
;
2616 hdr
= (const uint8_t *)req
->in
.vector
[idx
-1].iov_base
;
2618 /* allocate vectors for body and dynamic areas */
2619 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2621 req
->in
.vector_count
+ 2);
2622 if (req
->in
.vector
== NULL
) {
2625 req
->in
.vector_count
+= 2;
2627 full_size
= state
->missing
+ SMB2_HDR_BODY
+ 2;
2628 next_command_ofs
= IVAL(hdr
, SMB2_HDR_NEXT_COMMAND
);
2629 body_size
= SVAL(hdr
, SMB2_HDR_BODY
);
2631 if (next_command_ofs
!= 0) {
2632 if (next_command_ofs
< (SMB2_HDR_BODY
+ 2)) {
2634 * this is invalid, just return a zero
2635 * body and let the caller deal with the error
2638 } else if (next_command_ofs
> full_size
) {
2640 * this is invalid, just return a zero
2641 * body and let the caller deal with the error
2645 full_size
= next_command_ofs
;
2650 if (body_size
< 2) {
2652 * this is invalid, just return a zero
2653 * body and let the caller deal with the error
2659 * Mask out the lowest bit, the "dynamic" part
2664 if (body_size
> (full_size
- SMB2_HDR_BODY
)) {
2666 * this is invalid, just return a zero
2667 * body and let the caller deal with the error
2674 /* the caller should check this */
2678 dyn_size
= full_size
- (SMB2_HDR_BODY
+ body_size
);
2680 state
->missing
-= (body_size
- 2) + dyn_size
;
2682 body
= talloc_array(req
->in
.vector
, uint8_t, body_size
);
2687 dyn
= talloc_array(req
->in
.vector
, uint8_t, dyn_size
);
2692 req
->in
.vector
[idx
].iov_base
= (void *)body
;
2693 req
->in
.vector
[idx
].iov_len
= body_size
;
2694 req
->in
.vector
[idx
+1].iov_base
= (void *)dyn
;
2695 req
->in
.vector
[idx
+1].iov_len
= dyn_size
;
2697 vector
= talloc_array(mem_ctx
, struct iovec
, 2);
2698 if (vector
== NULL
) {
2703 * the first 2 bytes of the body were already fetched
2704 * together with the header
2706 memcpy(body
, hdr
+ SMB2_HDR_BODY
, 2);
2707 vector
[0].iov_base
= body
+ 2;
2708 vector
[0].iov_len
= body_size
- 2;
2710 vector
[1] = req
->in
.vector
[idx
+1];
2718 * when we endup here, we're looking for a new SMB2 request
2719 * next. And we ask for its header and the first 2 bytes of
2720 * the body (like we did for the first SMB2 request).
2723 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2725 req
->in
.vector_count
+ 1);
2726 if (req
->in
.vector
== NULL
) {
2729 req
->in
.vector_count
+= 1;
2732 * We assume it's a SMB2 request,
2733 * and we first get the header and the
2734 * first 2 bytes (the struct size) of the body
2736 len
= SMB2_HDR_BODY
+ 2;
2738 if (len
> state
->missing
) {
2739 /* let the caller handle the error */
2740 len
= state
->missing
;
2743 state
->missing
-= len
;
2744 state
->asked_for_header
= true;
2746 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2751 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2752 req
->in
.vector
[idx
].iov_len
= len
;
2754 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2755 if (vector
== NULL
) {
2759 vector
[0] = req
->in
.vector
[idx
];
2766 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
)
2768 struct tevent_req
*req
=
2769 tevent_req_callback_data(subreq
,
2775 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
2777 status
= map_nt_error_from_unix(sys_errno
);
2778 tevent_req_nterror(req
, status
);
2782 tevent_req_done(req
);
2785 static NTSTATUS
smbd_smb2_request_read_recv(struct tevent_req
*req
,
2786 TALLOC_CTX
*mem_ctx
,
2787 struct smbd_smb2_request
**_smb2_req
)
2789 struct smbd_smb2_request_read_state
*state
=
2790 tevent_req_data(req
,
2791 struct smbd_smb2_request_read_state
);
2794 if (tevent_req_is_nterror(req
, &status
)) {
2795 tevent_req_received(req
);
2799 talloc_steal(mem_ctx
, state
->smb2_req
->mem_pool
);
2800 *_smb2_req
= state
->smb2_req
;
2801 tevent_req_received(req
);
2802 return NT_STATUS_OK
;
2805 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
);
2807 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
)
2809 size_t max_send_queue_len
;
2810 size_t cur_send_queue_len
;
2811 struct tevent_req
*subreq
;
2813 if (sconn
->smb2
.compound_related_in_progress
) {
2815 * Can't read another until the related
2818 return NT_STATUS_OK
;
2821 if (tevent_queue_length(sconn
->smb2
.recv_queue
) > 0) {
2823 * if there is already a smbd_smb2_request_read
2824 * pending, we are done.
2826 return NT_STATUS_OK
;
2829 max_send_queue_len
= MAX(1, sconn
->smb2
.max_credits
/16);
2830 cur_send_queue_len
= tevent_queue_length(sconn
->smb2
.send_queue
);
2832 if (cur_send_queue_len
> max_send_queue_len
) {
2834 * if we have a lot of requests to send,
2835 * we wait until they are on the wire until we
2836 * ask for the next request.
2838 return NT_STATUS_OK
;
2841 /* ask for the next request */
2842 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->ev_ctx
, sconn
);
2843 if (subreq
== NULL
) {
2844 return NT_STATUS_NO_MEMORY
;
2846 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);
2848 return NT_STATUS_OK
;
2851 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
2852 const uint8_t *inbuf
, size_t size
)
2855 struct smbd_smb2_request
*req
= NULL
;
2857 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2858 (unsigned int)size
));
2860 status
= smbd_initialize_smb2(sconn
);
2861 if (!NT_STATUS_IS_OK(status
)) {
2862 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2866 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
2867 if (!NT_STATUS_IS_OK(status
)) {
2868 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2872 status
= smbd_smb2_request_validate(req
);
2873 if (!NT_STATUS_IS_OK(status
)) {
2874 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2878 status
= smbd_smb2_request_setup_out(req
);
2879 if (!NT_STATUS_IS_OK(status
)) {
2880 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2884 status
= smbd_smb2_request_dispatch(req
);
2885 if (!NT_STATUS_IS_OK(status
)) {
2886 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2890 status
= smbd_smb2_request_next_incoming(sconn
);
2891 if (!NT_STATUS_IS_OK(status
)) {
2892 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2896 sconn
->num_requests
++;
2899 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
)
2901 struct smbd_server_connection
*sconn
= tevent_req_callback_data(subreq
,
2902 struct smbd_server_connection
);
2904 struct smbd_smb2_request
*req
= NULL
;
2906 status
= smbd_smb2_request_read_recv(subreq
, sconn
, &req
);
2907 TALLOC_FREE(subreq
);
2908 if (!NT_STATUS_IS_OK(status
)) {
2909 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2910 nt_errstr(status
)));
2911 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2915 if (req
->in
.nbt_hdr
[0] != 0x00) {
2916 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2917 req
->in
.nbt_hdr
[0]));
2922 req
->current_idx
= 1;
2924 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2925 req
->current_idx
, req
->in
.vector_count
));
2927 status
= smbd_smb2_request_validate(req
);
2928 if (!NT_STATUS_IS_OK(status
)) {
2929 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2933 status
= smbd_smb2_request_setup_out(req
);
2934 if (!NT_STATUS_IS_OK(status
)) {
2935 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2939 status
= smbd_smb2_request_dispatch(req
);
2940 if (!NT_STATUS_IS_OK(status
)) {
2941 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2946 status
= smbd_smb2_request_next_incoming(sconn
);
2947 if (!NT_STATUS_IS_OK(status
)) {
2948 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2952 sconn
->num_requests
++;
2954 /* The timeout_processing function isn't run nearly
2955 often enough to implement 'max log size' without
2956 overrunning the size of the file by many megabytes.
2957 This is especially true if we are running at debug
2958 level 10. Checking every 50 SMB2s is a nice
2959 tradeoff of performance vs log file size overrun. */
2961 if ((sconn
->num_requests
% 50) == 0 &&
2962 need_to_check_log_size()) {
2963 change_to_root_user();