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 credits_requested
;
531 uint16_t credits_granted
= 0;
532 uint64_t credits_possible
;
533 uint16_t current_max_credits
;
536 * first we grant only 1/16th of the max range.
538 * Windows also starts with the 1/16th and then grants
539 * more later. I was only able to trigger higher
540 * values, when using a verify high credit charge.
542 * TODO: scale up depending one load, free memory
544 * Maybe also on the relationship between number
545 * of requests and the used sequence number.
546 * Which means we would grant more credits
547 * for client which use multi credit requests.
549 current_max_credits
= sconn
->smb2
.max_credits
/ 16;
550 current_max_credits
= MAX(current_max_credits
, 1);
552 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
553 credits_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
554 out_flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
555 out_status
= NT_STATUS(IVAL(outhdr
, SMB2_HDR_STATUS
));
557 SMB_ASSERT(sconn
->smb2
.max_credits
>= sconn
->smb2
.credits_granted
);
559 if (out_flags
& SMB2_HDR_FLAG_ASYNC
) {
561 * In case we already send an async interim
562 * response, we should not grant
563 * credits on the final response.
566 } else if (credits_requested
> 0) {
567 uint16_t additional_max
= 0;
568 uint16_t additional_credits
= credits_requested
- 1;
571 case SMB2_OP_NEGPROT
:
573 case SMB2_OP_SESSSETUP
:
575 * Windows 2012 RC1 starts to grant
577 * with a successful session setup
579 if (NT_STATUS_IS_OK(out_status
)) {
585 * We match windows and only grant additional credits
592 additional_credits
= MIN(additional_credits
, additional_max
);
594 credits_granted
= 1 + additional_credits
;
595 } else if (sconn
->smb2
.credits_granted
== 0) {
597 * Make sure the client has always at least one credit
603 * sequence numbers should not wrap
605 * 1. calculate the possible credits until
606 * the sequence numbers start to wrap on 64-bit.
608 * 2. UINT64_MAX is used for Break Notifications.
610 * 2. truncate the possible credits to the maximum
611 * credits we want to grant to the client in total.
613 * 3. remove the range we'll already granted to the client
614 * this makes sure the client consumes the lowest sequence
615 * number, before we can grant additional credits.
617 credits_possible
= UINT64_MAX
- sconn
->smb2
.seqnum_low
;
618 if (credits_possible
> 0) {
619 /* remove UINT64_MAX */
620 credits_possible
-= 1;
622 credits_possible
= MIN(credits_possible
, current_max_credits
);
623 credits_possible
-= sconn
->smb2
.seqnum_range
;
625 credits_granted
= MIN(credits_granted
, credits_possible
);
627 SSVAL(outhdr
, SMB2_HDR_CREDIT
, credits_granted
);
628 sconn
->smb2
.credits_granted
+= credits_granted
;
629 sconn
->smb2
.seqnum_range
+= credits_granted
;
631 DEBUG(10,("smb2_set_operation_credit: requested %u, "
632 "granted %u, current possible/max %u/%u, "
633 "total granted/max/low/range %u/%u/%llu/%u\n",
634 (unsigned int)credits_requested
,
635 (unsigned int)credits_granted
,
636 (unsigned int)credits_possible
,
637 (unsigned int)current_max_credits
,
638 (unsigned int)sconn
->smb2
.credits_granted
,
639 (unsigned int)sconn
->smb2
.max_credits
,
640 (unsigned long long)sconn
->smb2
.seqnum_low
,
641 (unsigned int)sconn
->smb2
.seqnum_range
));
644 static void smb2_calculate_credits(const struct smbd_smb2_request
*inreq
,
645 struct smbd_smb2_request
*outreq
)
648 uint16_t total_credits
= 0;
650 count
= outreq
->out
.vector_count
;
652 for (idx
=1; idx
< count
; idx
+= 3) {
653 uint8_t *outhdr
= (uint8_t *)outreq
->out
.vector
[idx
].iov_base
;
654 smb2_set_operation_credit(outreq
->sconn
,
655 &inreq
->in
.vector
[idx
],
656 &outreq
->out
.vector
[idx
]);
657 /* To match Windows, count up what we
659 total_credits
+= SVAL(outhdr
, SMB2_HDR_CREDIT
);
660 /* Set to zero in all but the last reply. */
661 if (idx
+ 3 < count
) {
662 SSVAL(outhdr
, SMB2_HDR_CREDIT
, 0);
664 SSVAL(outhdr
, SMB2_HDR_CREDIT
, total_credits
);
669 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
)
671 struct iovec
*vector
;
675 req
->request_time
= timeval_current();
677 count
= req
->in
.vector_count
;
678 vector
= talloc_zero_array(req
, struct iovec
, count
);
679 if (vector
== NULL
) {
680 return NT_STATUS_NO_MEMORY
;
683 vector
[0].iov_base
= req
->out
.nbt_hdr
;
684 vector
[0].iov_len
= 4;
685 SIVAL(req
->out
.nbt_hdr
, 0, 0);
687 for (idx
=1; idx
< count
; idx
+= 3) {
688 const uint8_t *inhdr
= NULL
;
689 uint8_t *outhdr
= NULL
;
690 uint8_t *outbody
= NULL
;
691 uint32_t next_command_ofs
= 0;
692 struct iovec
*current
= &vector
[idx
];
694 if ((idx
+ 3) < count
) {
695 /* we have a next command -
696 * setup for the error case. */
697 next_command_ofs
= SMB2_HDR_BODY
+ 9;
700 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
702 outhdr
= talloc_zero_array(vector
, uint8_t,
704 if (outhdr
== NULL
) {
705 return NT_STATUS_NO_MEMORY
;
708 outbody
= outhdr
+ SMB2_HDR_BODY
;
710 current
[0].iov_base
= (void *)outhdr
;
711 current
[0].iov_len
= SMB2_HDR_BODY
;
713 current
[1].iov_base
= (void *)outbody
;
714 current
[1].iov_len
= 8;
716 current
[2].iov_base
= NULL
;
717 current
[2].iov_len
= 0;
719 /* setup the SMB2 header */
720 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
721 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
722 SSVAL(outhdr
, SMB2_HDR_CREDIT_CHARGE
,
723 SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
));
724 SIVAL(outhdr
, SMB2_HDR_STATUS
,
725 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
726 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
727 SVAL(inhdr
, SMB2_HDR_OPCODE
));
728 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
729 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
730 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
731 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
732 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
733 SIVAL(outhdr
, SMB2_HDR_PID
,
734 IVAL(inhdr
, SMB2_HDR_PID
));
735 SIVAL(outhdr
, SMB2_HDR_TID
,
736 IVAL(inhdr
, SMB2_HDR_TID
));
737 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
738 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
739 memcpy(outhdr
+ SMB2_HDR_SIGNATURE
,
740 inhdr
+ SMB2_HDR_SIGNATURE
, 16);
742 /* setup error body header */
743 SSVAL(outbody
, 0x00, 0x08 + 1);
744 SSVAL(outbody
, 0x02, 0);
745 SIVAL(outbody
, 0x04, 0);
748 req
->out
.vector
= vector
;
749 req
->out
.vector_count
= count
;
751 /* setup the length of the NBT packet */
752 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
754 DLIST_ADD_END(req
->sconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
759 void smbd_server_connection_terminate_ex(struct smbd_server_connection
*sconn
,
761 const char *location
)
763 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
765 exit_server_cleanly(reason
);
768 static bool dup_smb2_vec3(TALLOC_CTX
*ctx
,
769 struct iovec
*outvec
,
770 const struct iovec
*srcvec
)
772 /* vec[0] is always boilerplate and must
773 * be allocated with size OUTVEC_ALLOC_SIZE. */
775 outvec
[0].iov_base
= talloc_memdup(ctx
,
778 if (!outvec
[0].iov_base
) {
781 outvec
[0].iov_len
= SMB2_HDR_BODY
;
784 * If this is a "standard" vec[1] of length 8,
785 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
786 * then duplicate this. Else use talloc_memdup().
789 if (srcvec
[1].iov_len
== 8 &&
790 srcvec
[1].iov_base
==
791 ((uint8_t *)srcvec
[0].iov_base
) +
793 outvec
[1].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
795 outvec
[1].iov_len
= 8;
797 outvec
[1].iov_base
= talloc_memdup(ctx
,
800 if (!outvec
[1].iov_base
) {
803 outvec
[1].iov_len
= srcvec
[1].iov_len
;
807 * If this is a "standard" vec[2] of length 1,
808 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
809 * then duplicate this. Else use talloc_memdup().
812 if (srcvec
[2].iov_base
&&
814 if (srcvec
[2].iov_base
==
815 ((uint8_t *)srcvec
[0].iov_base
) +
816 (OUTVEC_ALLOC_SIZE
- 1) &&
817 srcvec
[2].iov_len
== 1) {
818 /* Common SMB2 error packet case. */
819 outvec
[2].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
820 (OUTVEC_ALLOC_SIZE
- 1);
822 outvec
[2].iov_base
= talloc_memdup(ctx
,
825 if (!outvec
[2].iov_base
) {
829 outvec
[2].iov_len
= srcvec
[2].iov_len
;
831 outvec
[2].iov_base
= NULL
;
832 outvec
[2].iov_len
= 0;
837 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
839 struct smbd_smb2_request
*newreq
= NULL
;
840 struct iovec
*outvec
= NULL
;
841 int count
= req
->out
.vector_count
;
844 newreq
= smbd_smb2_request_allocate(req
->sconn
);
849 newreq
->sconn
= req
->sconn
;
850 newreq
->session
= req
->session
;
851 newreq
->do_signing
= req
->do_signing
;
852 newreq
->current_idx
= req
->current_idx
;
854 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
859 newreq
->out
.vector
= outvec
;
860 newreq
->out
.vector_count
= count
;
862 /* Setup the outvec's identically to req. */
863 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
864 outvec
[0].iov_len
= 4;
865 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
867 /* Setup the vectors identically to the ones in req. */
868 for (i
= 1; i
< count
; i
+= 3) {
869 if (!dup_smb2_vec3(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
880 smb2_setup_nbt_length(newreq
->out
.vector
,
881 newreq
->out
.vector_count
);
886 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
);
888 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
891 uint8_t *outhdr
= NULL
;
892 struct smbd_smb2_request
*nreq
= NULL
;
894 /* Create a new smb2 request we'll use
895 for the interim return. */
896 nreq
= dup_smb2_req(req
);
898 return NT_STATUS_NO_MEMORY
;
901 /* Lose the last 3 out vectors. They're the
902 ones we'll be using for the async reply. */
903 nreq
->out
.vector_count
-= 3;
905 smb2_setup_nbt_length(nreq
->out
.vector
,
906 nreq
->out
.vector_count
);
908 /* Step back to the previous reply. */
909 i
= nreq
->current_idx
- 3;
910 outhdr
= (uint8_t *)nreq
->out
.vector
[i
].iov_base
;
911 /* And end the chain. */
912 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
914 /* Calculate outgoing credits */
915 smb2_calculate_credits(req
, nreq
);
917 /* Re-sign if needed. */
918 if (nreq
->do_signing
) {
920 struct smbXsrv_session
*x
= nreq
->session
;
921 struct smbXsrv_connection
*conn
= x
->connection
;
922 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
924 status
= smb2_signing_sign_pdu(signing_key
,
926 &nreq
->out
.vector
[i
], 3);
927 if (!NT_STATUS_IS_OK(status
)) {
931 if (DEBUGLEVEL
>= 10) {
932 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
933 (unsigned int)nreq
->current_idx
);
934 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
935 (unsigned int)nreq
->out
.vector_count
);
936 print_req_vectors(nreq
);
938 nreq
->subreq
= tstream_writev_queue_send(nreq
,
940 nreq
->sconn
->smb2
.stream
,
941 nreq
->sconn
->smb2
.send_queue
,
943 nreq
->out
.vector_count
);
945 if (nreq
->subreq
== NULL
) {
946 return NT_STATUS_NO_MEMORY
;
949 tevent_req_set_callback(nreq
->subreq
,
950 smbd_smb2_request_writev_done
,
956 struct smbd_smb2_request_pending_state
{
957 struct smbd_server_connection
*sconn
;
958 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x08 + 1];
959 struct iovec vector
[3];
962 static void smbd_smb2_request_pending_writev_done(struct tevent_req
*subreq
)
964 struct smbd_smb2_request_pending_state
*state
=
965 tevent_req_callback_data(subreq
,
966 struct smbd_smb2_request_pending_state
);
967 struct smbd_server_connection
*sconn
= state
->sconn
;
971 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
974 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
975 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
982 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
983 struct tevent_timer
*te
,
984 struct timeval current_time
,
987 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
988 struct tevent_req
*subreq
,
992 int i
= req
->current_idx
;
993 struct timeval defer_endtime
;
994 uint8_t *outhdr
= NULL
;
997 if (!tevent_req_is_in_progress(subreq
)) {
1001 req
->subreq
= subreq
;
1004 if (req
->async_te
) {
1005 /* We're already async. */
1006 return NT_STATUS_OK
;
1009 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
1010 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1011 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1012 /* We're already async. */
1013 return NT_STATUS_OK
;
1016 if (req
->in
.vector_count
> i
+ 3) {
1018 * We're trying to go async in a compound
1019 * request chain. This is not allowed.
1020 * Cancel the outstanding request.
1022 tevent_req_cancel(req
->subreq
);
1023 return smbd_smb2_request_error(req
,
1024 NT_STATUS_INSUFFICIENT_RESOURCES
);
1027 if (DEBUGLEVEL
>= 10) {
1028 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1029 (unsigned int)req
->current_idx
);
1030 print_req_vectors(req
);
1033 if (req
->out
.vector_count
> 4) {
1034 struct iovec
*outvec
= NULL
;
1036 /* This is a compound reply. We
1037 * must do an interim response
1038 * followed by the async response
1041 status
= smb2_send_async_interim_response(req
);
1042 if (!NT_STATUS_IS_OK(status
)) {
1047 * We're splitting off the last SMB2
1048 * request in a compound set, and the
1049 * smb2_send_async_interim_response()
1050 * call above just sent all the replies
1051 * for the previous SMB2 requests in
1052 * this compound set. So we're no longer
1053 * in the "compound_related_in_progress"
1054 * state, and this is no longer a compound
1057 req
->compound_related
= false;
1058 req
->sconn
->smb2
.compound_related_in_progress
= false;
1060 /* Re-arrange the in.vectors. */
1061 req
->in
.vector
[1] = req
->in
.vector
[i
];
1062 req
->in
.vector
[2] = req
->in
.vector
[i
+1];
1063 req
->in
.vector
[3] = req
->in
.vector
[i
+2];
1064 req
->in
.vector_count
= 4;
1066 /* Reset the new in size. */
1067 smb2_setup_nbt_length(req
->in
.vector
, 4);
1069 /* Now recreate the out.vectors. */
1070 outvec
= talloc_zero_array(req
, struct iovec
, 4);
1072 return NT_STATUS_NO_MEMORY
;
1075 /* 0 is always boilerplate and must
1076 * be of size 4 for the length field. */
1078 outvec
[0].iov_base
= req
->out
.nbt_hdr
;
1079 outvec
[0].iov_len
= 4;
1080 SIVAL(req
->out
.nbt_hdr
, 0, 0);
1082 if (!dup_smb2_vec3(outvec
, &outvec
[1], &req
->out
.vector
[i
])) {
1083 return NT_STATUS_NO_MEMORY
;
1086 TALLOC_FREE(req
->out
.vector
);
1088 req
->out
.vector
= outvec
;
1090 req
->current_idx
= 1;
1091 req
->out
.vector_count
= 4;
1093 outhdr
= (uint8_t *)req
->out
.vector
[1].iov_base
;
1094 flags
= (IVAL(outhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
1095 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
);
1098 defer_endtime
= timeval_current_ofs_usec(defer_time
);
1099 req
->async_te
= tevent_add_timer(req
->sconn
->ev_ctx
,
1101 smbd_smb2_request_pending_timer
,
1103 if (req
->async_te
== NULL
) {
1104 return NT_STATUS_NO_MEMORY
;
1107 return NT_STATUS_OK
;
1110 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
1111 struct tevent_timer
*te
,
1112 struct timeval current_time
,
1115 struct smbd_smb2_request
*req
=
1116 talloc_get_type_abort(private_data
,
1117 struct smbd_smb2_request
);
1118 struct smbd_smb2_request_pending_state
*state
= NULL
;
1119 int i
= req
->current_idx
;
1120 uint8_t *outhdr
= NULL
;
1121 const uint8_t *inhdr
= NULL
;
1122 uint8_t *hdr
= NULL
;
1123 uint8_t *body
= NULL
;
1125 uint64_t message_id
= 0;
1126 uint64_t async_id
= 0;
1127 struct tevent_req
*subreq
= NULL
;
1129 TALLOC_FREE(req
->async_te
);
1131 /* Ensure our final reply matches the interim one. */
1132 inhdr
= (const uint8_t *)req
->in
.vector
[1].iov_base
;
1133 outhdr
= (uint8_t *)req
->out
.vector
[1].iov_base
;
1134 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1135 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1137 async_id
= message_id
; /* keep it simple for now... */
1139 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1140 SBVAL(outhdr
, SMB2_HDR_ASYNC_ID
, async_id
);
1142 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1144 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1145 (unsigned long long)async_id
));
1148 * What we send is identical to a smbd_smb2_request_error
1149 * packet with an error status of STATUS_PENDING. Make use
1150 * of this fact sometime when refactoring. JRA.
1153 state
= talloc_zero(req
->sconn
, struct smbd_smb2_request_pending_state
);
1154 if (state
== NULL
) {
1155 smbd_server_connection_terminate(req
->sconn
,
1156 nt_errstr(NT_STATUS_NO_MEMORY
));
1159 state
->sconn
= req
->sconn
;
1161 state
->vector
[0].iov_base
= (void *)state
->buf
;
1162 state
->vector
[0].iov_len
= 4;
1164 state
->vector
[1].iov_base
= state
->buf
+ 4;
1165 state
->vector
[1].iov_len
= SMB2_HDR_BODY
;
1167 state
->vector
[2].iov_base
= state
->buf
+ 4 + SMB2_HDR_BODY
;
1168 state
->vector
[2].iov_len
= 9;
1170 smb2_setup_nbt_length(state
->vector
, 3);
1172 hdr
= (uint8_t *)state
->vector
[1].iov_base
;
1173 body
= (uint8_t *)state
->vector
[2].iov_base
;
1175 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
1176 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1177 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1178 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
1179 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(outhdr
, SMB2_HDR_OPCODE
));
1181 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
);
1182 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1183 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
1184 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
1185 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
1186 BVAL(outhdr
, SMB2_HDR_SESSION_ID
));
1187 memcpy(hdr
+SMB2_HDR_SIGNATURE
,
1188 outhdr
+SMB2_HDR_SIGNATURE
, 16);
1190 SSVAL(body
, 0x00, 0x08 + 1);
1192 SCVAL(body
, 0x02, 0);
1193 SCVAL(body
, 0x03, 0);
1194 SIVAL(body
, 0x04, 0);
1195 /* Match W2K8R2... */
1196 SCVAL(body
, 0x08, 0x21);
1198 /* Ensure we correctly go through crediting. Grant
1199 the credits now, and zero credits on the final
1201 smb2_set_operation_credit(req
->sconn
,
1205 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1207 if (req
->do_signing
) {
1209 struct smbXsrv_session
*x
= req
->session
;
1210 struct smbXsrv_connection
*conn
= x
->connection
;
1211 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
1213 status
= smb2_signing_sign_pdu(signing_key
,
1215 &state
->vector
[1], 2);
1216 if (!NT_STATUS_IS_OK(status
)) {
1217 smbd_server_connection_terminate(req
->sconn
,
1223 subreq
= tstream_writev_queue_send(state
,
1224 state
->sconn
->ev_ctx
,
1225 state
->sconn
->smb2
.stream
,
1226 state
->sconn
->smb2
.send_queue
,
1229 if (subreq
== NULL
) {
1230 smbd_server_connection_terminate(state
->sconn
,
1231 nt_errstr(NT_STATUS_NO_MEMORY
));
1234 tevent_req_set_callback(subreq
,
1235 smbd_smb2_request_pending_writev_done
,
1239 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
1241 struct smbd_server_connection
*sconn
= req
->sconn
;
1242 struct smbd_smb2_request
*cur
;
1243 const uint8_t *inhdr
;
1244 int i
= req
->current_idx
;
1246 uint64_t search_message_id
;
1247 uint64_t search_async_id
;
1250 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1252 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1253 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1254 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
1257 * we don't need the request anymore
1258 * cancel requests never have a response
1260 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1263 for (cur
= sconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
1264 const uint8_t *outhdr
;
1265 uint64_t message_id
;
1268 i
= cur
->current_idx
;
1270 outhdr
= (const uint8_t *)cur
->out
.vector
[i
].iov_base
;
1272 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1273 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
1275 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1276 if (search_async_id
== async_id
) {
1277 found_id
= async_id
;
1281 if (search_message_id
== message_id
) {
1282 found_id
= message_id
;
1288 if (cur
&& cur
->subreq
) {
1289 inhdr
= (const uint8_t *)cur
->in
.vector
[i
].iov_base
;
1290 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1291 "cancel opcode[%s] mid %llu\n",
1292 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1293 (unsigned long long)found_id
));
1294 tevent_req_cancel(cur
->subreq
);
1297 return NT_STATUS_OK
;
1300 /*************************************************************
1301 Ensure an incoming tid is a valid one for us to access.
1302 Change to the associated uid credentials and chdir to the
1303 valid tid directory.
1304 *************************************************************/
1306 static NTSTATUS
smbd_smb2_request_check_tcon(struct smbd_smb2_request
*req
)
1308 const uint8_t *inhdr
;
1309 int i
= req
->current_idx
;
1312 struct smbXsrv_tcon0
*tcon
;
1314 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1318 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1320 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1321 in_tid
= IVAL(inhdr
, SMB2_HDR_TID
);
1323 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1324 in_tid
= req
->last_tid
;
1327 status
= smb2srv_tcon_lookup(req
->session
,
1328 in_tid
, now
, &tcon
);
1329 if (!NT_STATUS_IS_OK(status
)) {
1333 if (!change_to_user(tcon
->compat
, req
->session
->compat
->vuid
)) {
1334 return NT_STATUS_ACCESS_DENIED
;
1337 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1338 if (!set_current_service(tcon
->compat
, 0, true)) {
1339 return NT_STATUS_ACCESS_DENIED
;
1343 req
->last_tid
= in_tid
;
1345 return NT_STATUS_OK
;
1348 /*************************************************************
1349 Ensure an incoming session_id is a valid one for us to access.
1350 *************************************************************/
1352 static NTSTATUS
smbd_smb2_request_check_session(struct smbd_smb2_request
*req
)
1354 const uint8_t *inhdr
;
1355 int i
= req
->current_idx
;
1358 uint64_t in_session_id
;
1359 struct smbXsrv_session
*session
= NULL
;
1360 struct auth_session_info
*session_info
;
1362 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1364 req
->session
= NULL
;
1367 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1369 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1370 in_opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1371 in_session_id
= BVAL(inhdr
, SMB2_HDR_SESSION_ID
);
1373 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1374 in_session_id
= req
->last_session_id
;
1377 /* lookup an existing session */
1378 status
= smb2srv_session_lookup(req
->sconn
->conn
,
1382 req
->session
= session
;
1383 req
->last_session_id
= in_session_id
;
1385 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
1386 switch (in_opcode
) {
1387 case SMB2_OP_SESSSETUP
:
1388 status
= NT_STATUS_OK
;
1394 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1395 switch (in_opcode
) {
1397 case SMB2_OP_CREATE
:
1398 case SMB2_OP_GETINFO
:
1399 case SMB2_OP_SETINFO
:
1400 return NT_STATUS_INVALID_HANDLE
;
1403 * Notice the check for
1404 * (session_info == NULL)
1407 status
= NT_STATUS_OK
;
1411 if (!NT_STATUS_IS_OK(status
)) {
1415 session_info
= session
->global
->auth_session_info
;
1416 if (session_info
== NULL
) {
1417 return NT_STATUS_INVALID_HANDLE
;
1420 set_current_user_info(session_info
->unix_info
->sanitized_username
,
1421 session_info
->unix_info
->unix_name
,
1422 session_info
->info
->domain_name
);
1424 return NT_STATUS_OK
;
1427 NTSTATUS
smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request
*req
,
1428 uint32_t data_length
)
1430 uint16_t needed_charge
;
1431 uint16_t credit_charge
;
1432 const uint8_t *inhdr
;
1433 int i
= req
->current_idx
;
1435 if (!req
->sconn
->smb2
.supports_multicredit
) {
1436 if (data_length
> 65536) {
1437 return NT_STATUS_INVALID_PARAMETER
;
1439 return NT_STATUS_OK
;
1442 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1443 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
1445 /* requests larger than 64 KB need credit charge */
1446 if (credit_charge
== 0 && data_length
> 65536) {
1447 DEBUG(2, ("Request larger than 64KB w/o creditcharge\n"));
1448 return NT_STATUS_INVALID_PARAMETER
;
1451 needed_charge
= (data_length
- 1)/ 65536 + 1;
1453 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1454 (unsigned long long) BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
),
1455 credit_charge
, needed_charge
));
1457 if (needed_charge
> credit_charge
) {
1458 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1459 credit_charge
, needed_charge
));
1460 return NT_STATUS_INVALID_PARAMETER
;
1463 return NT_STATUS_OK
;
1466 NTSTATUS
smbd_smb2_request_verify_sizes(struct smbd_smb2_request
*req
,
1467 size_t expected_body_size
)
1469 const uint8_t *inhdr
;
1471 const uint8_t *inbody
;
1472 int i
= req
->current_idx
;
1474 size_t min_dyn_size
= expected_body_size
& 0x00000001;
1477 * The following should be checked already.
1479 if ((i
+2) > req
->in
.vector_count
) {
1480 return NT_STATUS_INTERNAL_ERROR
;
1482 if (req
->in
.vector
[i
+0].iov_len
!= SMB2_HDR_BODY
) {
1483 return NT_STATUS_INTERNAL_ERROR
;
1485 if (req
->in
.vector
[i
+1].iov_len
< 2) {
1486 return NT_STATUS_INTERNAL_ERROR
;
1489 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1490 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1494 case SMB2_OP_GETINFO
:
1500 * Now check the expected body size,
1501 * where the last byte might be in the
1504 if (req
->in
.vector
[i
+1].iov_len
!= (expected_body_size
& 0xFFFFFFFE)) {
1505 return NT_STATUS_INVALID_PARAMETER
;
1507 if (req
->in
.vector
[i
+2].iov_len
< min_dyn_size
) {
1508 return NT_STATUS_INVALID_PARAMETER
;
1511 inbody
= (const uint8_t *)req
->in
.vector
[i
+1].iov_base
;
1513 body_size
= SVAL(inbody
, 0x00);
1514 if (body_size
!= expected_body_size
) {
1515 return NT_STATUS_INVALID_PARAMETER
;
1518 return NT_STATUS_OK
;
1521 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
1523 const uint8_t *inhdr
;
1524 int i
= req
->current_idx
;
1529 NTSTATUS session_status
;
1530 uint32_t allowed_flags
;
1531 NTSTATUS return_value
;
1532 struct smbXsrv_session
*x
= NULL
;
1533 bool signing_required
= false;
1535 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1537 /* TODO: verify more things */
1539 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1540 opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1541 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1542 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1543 smb2_opcode_name(opcode
),
1544 (unsigned long long)mid
));
1546 if (get_Protocol() >= PROTOCOL_SMB2_02
) {
1548 * once the protocol is negotiated
1549 * SMB2_OP_NEGPROT is not allowed anymore
1551 if (opcode
== SMB2_OP_NEGPROT
) {
1552 /* drop the connection */
1553 return NT_STATUS_INVALID_PARAMETER
;
1557 * if the protocol is not negotiated yet
1558 * only SMB2_OP_NEGPROT is allowed.
1560 if (opcode
!= SMB2_OP_NEGPROT
) {
1561 /* drop the connection */
1562 return NT_STATUS_INVALID_PARAMETER
;
1566 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
1567 SMB2_HDR_FLAG_SIGNED
|
1569 if (opcode
== SMB2_OP_CANCEL
) {
1570 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
1572 if ((flags
& ~allowed_flags
) != 0) {
1573 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1577 * Check if the client provided a valid session id,
1578 * if so smbd_smb2_request_check_session() calls
1579 * set_current_user_info().
1581 * As some command don't require a valid session id
1582 * we defer the check of the session_status
1584 session_status
= smbd_smb2_request_check_session(req
);
1588 signing_required
= x
->global
->signing_required
;
1590 if (opcode
== SMB2_OP_SESSSETUP
&&
1591 x
->global
->channels
[0].signing_key
.length
) {
1592 signing_required
= true;
1596 req
->do_signing
= false;
1597 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
1598 struct smbXsrv_connection
*conn
= x
->connection
;
1599 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
1601 if (!NT_STATUS_IS_OK(session_status
)) {
1602 return smbd_smb2_request_error(req
, session_status
);
1605 req
->do_signing
= true;
1606 status
= smb2_signing_check_pdu(signing_key
,
1608 &req
->in
.vector
[i
], 3);
1609 if (!NT_STATUS_IS_OK(status
)) {
1610 return smbd_smb2_request_error(req
, status
);
1612 } else if (opcode
== SMB2_OP_CANCEL
) {
1613 /* Cancel requests are allowed to skip the signing */
1614 } else if (signing_required
) {
1615 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
1618 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
1620 * This check is mostly for giving the correct error code
1621 * for compounded requests.
1623 * TODO: we may need to move this after the session
1626 if (!NT_STATUS_IS_OK(req
->next_status
)) {
1627 return smbd_smb2_request_error(req
, req
->next_status
);
1630 req
->compat_chain_fsp
= NULL
;
1633 if (req
->compound_related
) {
1634 req
->sconn
->smb2
.compound_related_in_progress
= true;
1638 case SMB2_OP_NEGPROT
:
1639 /* This call needs to be run as root */
1640 change_to_root_user();
1643 START_PROFILE(smb2_negprot
);
1644 return_value
= smbd_smb2_request_process_negprot(req
);
1645 END_PROFILE(smb2_negprot
);
1649 case SMB2_OP_SESSSETUP
:
1650 /* This call needs to be run as root */
1651 change_to_root_user();
1654 START_PROFILE(smb2_sesssetup
);
1655 return_value
= smbd_smb2_request_process_sesssetup(req
);
1656 END_PROFILE(smb2_sesssetup
);
1660 case SMB2_OP_LOGOFF
:
1661 if (!NT_STATUS_IS_OK(session_status
)) {
1662 return_value
= smbd_smb2_request_error(req
, session_status
);
1666 /* This call needs to be run as root */
1667 change_to_root_user();
1670 START_PROFILE(smb2_logoff
);
1671 return_value
= smbd_smb2_request_process_logoff(req
);
1672 END_PROFILE(smb2_logoff
);
1677 if (!NT_STATUS_IS_OK(session_status
)) {
1678 return_value
= smbd_smb2_request_error(req
, session_status
);
1683 * This call needs to be run as root.
1685 * smbd_smb2_request_process_tcon()
1686 * calls make_connection_snum(), which will call
1687 * change_to_user(), when needed.
1689 change_to_root_user();
1692 START_PROFILE(smb2_tcon
);
1693 return_value
= smbd_smb2_request_process_tcon(req
);
1694 END_PROFILE(smb2_tcon
);
1699 if (!NT_STATUS_IS_OK(session_status
)) {
1700 return_value
= smbd_smb2_request_error(req
, session_status
);
1704 * This call needs to be run as user.
1706 * smbd_smb2_request_check_tcon()
1707 * calls change_to_user() on success.
1709 status
= smbd_smb2_request_check_tcon(req
);
1710 if (!NT_STATUS_IS_OK(status
)) {
1711 return_value
= smbd_smb2_request_error(req
, status
);
1714 /* This call needs to be run as root */
1715 change_to_root_user();
1719 START_PROFILE(smb2_tdis
);
1720 return_value
= smbd_smb2_request_process_tdis(req
);
1721 END_PROFILE(smb2_tdis
);
1725 case SMB2_OP_CREATE
:
1726 if (!NT_STATUS_IS_OK(session_status
)) {
1727 return_value
= smbd_smb2_request_error(req
, session_status
);
1731 * This call needs to be run as user.
1733 * smbd_smb2_request_check_tcon()
1734 * calls change_to_user() on success.
1736 status
= smbd_smb2_request_check_tcon(req
);
1737 if (!NT_STATUS_IS_OK(status
)) {
1738 return_value
= smbd_smb2_request_error(req
, status
);
1743 START_PROFILE(smb2_create
);
1744 return_value
= smbd_smb2_request_process_create(req
);
1745 END_PROFILE(smb2_create
);
1750 if (!NT_STATUS_IS_OK(session_status
)) {
1751 return_value
= smbd_smb2_request_error(req
, session_status
);
1755 * This call needs to be run as user.
1757 * smbd_smb2_request_check_tcon()
1758 * calls change_to_user() on success.
1760 status
= smbd_smb2_request_check_tcon(req
);
1761 if (!NT_STATUS_IS_OK(status
)) {
1762 return_value
= smbd_smb2_request_error(req
, status
);
1767 START_PROFILE(smb2_close
);
1768 return_value
= smbd_smb2_request_process_close(req
);
1769 END_PROFILE(smb2_close
);
1774 if (!NT_STATUS_IS_OK(session_status
)) {
1775 return_value
= smbd_smb2_request_error(req
, session_status
);
1779 * This call needs to be run as user.
1781 * smbd_smb2_request_check_tcon()
1782 * calls change_to_user() on success.
1784 status
= smbd_smb2_request_check_tcon(req
);
1785 if (!NT_STATUS_IS_OK(status
)) {
1786 return_value
= smbd_smb2_request_error(req
, status
);
1791 START_PROFILE(smb2_flush
);
1792 return_value
= smbd_smb2_request_process_flush(req
);
1793 END_PROFILE(smb2_flush
);
1798 if (!NT_STATUS_IS_OK(session_status
)) {
1799 return_value
= smbd_smb2_request_error(req
, session_status
);
1803 * This call needs to be run as user.
1805 * smbd_smb2_request_check_tcon()
1806 * calls change_to_user() on success.
1808 status
= smbd_smb2_request_check_tcon(req
);
1809 if (!NT_STATUS_IS_OK(status
)) {
1810 return_value
= smbd_smb2_request_error(req
, status
);
1815 START_PROFILE(smb2_read
);
1816 return_value
= smbd_smb2_request_process_read(req
);
1817 END_PROFILE(smb2_read
);
1822 if (!NT_STATUS_IS_OK(session_status
)) {
1823 return_value
= smbd_smb2_request_error(req
, session_status
);
1827 * This call needs to be run as user.
1829 * smbd_smb2_request_check_tcon()
1830 * calls change_to_user() on success.
1832 status
= smbd_smb2_request_check_tcon(req
);
1833 if (!NT_STATUS_IS_OK(status
)) {
1834 return_value
= smbd_smb2_request_error(req
, status
);
1839 START_PROFILE(smb2_write
);
1840 return_value
= smbd_smb2_request_process_write(req
);
1841 END_PROFILE(smb2_write
);
1846 if (!NT_STATUS_IS_OK(session_status
)) {
1847 /* Too ugly to live ? JRA. */
1848 if (NT_STATUS_EQUAL(session_status
,NT_STATUS_USER_SESSION_DELETED
)) {
1849 session_status
= NT_STATUS_FILE_CLOSED
;
1851 return_value
= smbd_smb2_request_error(req
, session_status
);
1855 * This call needs to be run as user.
1857 * smbd_smb2_request_check_tcon()
1858 * calls change_to_user() on success.
1860 status
= smbd_smb2_request_check_tcon(req
);
1861 if (!NT_STATUS_IS_OK(status
)) {
1862 /* Too ugly to live ? JRA. */
1863 if (NT_STATUS_EQUAL(status
,NT_STATUS_NETWORK_NAME_DELETED
)) {
1864 status
= NT_STATUS_FILE_CLOSED
;
1866 return_value
= smbd_smb2_request_error(req
, status
);
1871 START_PROFILE(smb2_lock
);
1872 return_value
= smbd_smb2_request_process_lock(req
);
1873 END_PROFILE(smb2_lock
);
1878 if (!NT_STATUS_IS_OK(session_status
)) {
1879 return_value
= smbd_smb2_request_error(req
, session_status
);
1883 * This call needs to be run as user.
1885 * smbd_smb2_request_check_tcon()
1886 * calls change_to_user() on success.
1888 status
= smbd_smb2_request_check_tcon(req
);
1889 if (!NT_STATUS_IS_OK(status
)) {
1890 return_value
= smbd_smb2_request_error(req
, status
);
1895 START_PROFILE(smb2_ioctl
);
1896 return_value
= smbd_smb2_request_process_ioctl(req
);
1897 END_PROFILE(smb2_ioctl
);
1901 case SMB2_OP_CANCEL
:
1903 * This call needs to be run as root
1905 * That is what we also do in the SMB1 case.
1907 change_to_root_user();
1910 START_PROFILE(smb2_cancel
);
1911 return_value
= smbd_smb2_request_process_cancel(req
);
1912 END_PROFILE(smb2_cancel
);
1916 case SMB2_OP_KEEPALIVE
:
1917 /* This call needs to be run as root */
1918 change_to_root_user();
1921 START_PROFILE(smb2_keepalive
);
1922 return_value
= smbd_smb2_request_process_keepalive(req
);
1923 END_PROFILE(smb2_keepalive
);
1928 if (!NT_STATUS_IS_OK(session_status
)) {
1929 return_value
= smbd_smb2_request_error(req
, session_status
);
1933 * This call needs to be run as user.
1935 * smbd_smb2_request_check_tcon()
1936 * calls change_to_user() on success.
1938 status
= smbd_smb2_request_check_tcon(req
);
1939 if (!NT_STATUS_IS_OK(status
)) {
1940 return_value
= smbd_smb2_request_error(req
, status
);
1945 START_PROFILE(smb2_find
);
1946 return_value
= smbd_smb2_request_process_find(req
);
1947 END_PROFILE(smb2_find
);
1951 case SMB2_OP_NOTIFY
:
1952 if (!NT_STATUS_IS_OK(session_status
)) {
1953 return_value
= smbd_smb2_request_error(req
, session_status
);
1957 * This call needs to be run as user.
1959 * smbd_smb2_request_check_tcon()
1960 * calls change_to_user() on success.
1962 status
= smbd_smb2_request_check_tcon(req
);
1963 if (!NT_STATUS_IS_OK(status
)) {
1964 return_value
= smbd_smb2_request_error(req
, status
);
1969 START_PROFILE(smb2_notify
);
1970 return_value
= smbd_smb2_request_process_notify(req
);
1971 END_PROFILE(smb2_notify
);
1975 case SMB2_OP_GETINFO
:
1976 if (!NT_STATUS_IS_OK(session_status
)) {
1977 return_value
= smbd_smb2_request_error(req
, session_status
);
1981 * This call needs to be run as user.
1983 * smbd_smb2_request_check_tcon()
1984 * calls change_to_user() on success.
1986 status
= smbd_smb2_request_check_tcon(req
);
1987 if (!NT_STATUS_IS_OK(status
)) {
1988 return_value
= smbd_smb2_request_error(req
, status
);
1993 START_PROFILE(smb2_getinfo
);
1994 return_value
= smbd_smb2_request_process_getinfo(req
);
1995 END_PROFILE(smb2_getinfo
);
1999 case SMB2_OP_SETINFO
:
2000 if (!NT_STATUS_IS_OK(session_status
)) {
2001 return_value
= smbd_smb2_request_error(req
, session_status
);
2005 * This call needs to be run as user.
2007 * smbd_smb2_request_check_tcon()
2008 * calls change_to_user() on success.
2010 status
= smbd_smb2_request_check_tcon(req
);
2011 if (!NT_STATUS_IS_OK(status
)) {
2012 return_value
= smbd_smb2_request_error(req
, status
);
2017 START_PROFILE(smb2_setinfo
);
2018 return_value
= smbd_smb2_request_process_setinfo(req
);
2019 END_PROFILE(smb2_setinfo
);
2024 if (!NT_STATUS_IS_OK(session_status
)) {
2025 return_value
= smbd_smb2_request_error(req
, session_status
);
2029 * This call needs to be run as user.
2031 * smbd_smb2_request_check_tcon()
2032 * calls change_to_user() on success.
2034 status
= smbd_smb2_request_check_tcon(req
);
2035 if (!NT_STATUS_IS_OK(status
)) {
2036 return_value
= smbd_smb2_request_error(req
, status
);
2041 START_PROFILE(smb2_break
);
2042 return_value
= smbd_smb2_request_process_break(req
);
2043 END_PROFILE(smb2_break
);
2048 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
2051 return return_value
;
2054 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
2056 struct tevent_req
*subreq
;
2057 int i
= req
->current_idx
;
2060 TALLOC_FREE(req
->async_te
);
2062 req
->current_idx
+= 3;
2064 if (req
->current_idx
< req
->out
.vector_count
) {
2066 * We must process the remaining compound
2067 * SMB2 requests before any new incoming SMB2
2068 * requests. This is because incoming SMB2
2069 * requests may include a cancel for a
2070 * compound request we haven't processed
2073 struct tevent_immediate
*im
= tevent_create_immediate(req
);
2075 return NT_STATUS_NO_MEMORY
;
2077 tevent_schedule_immediate(im
,
2079 smbd_smb2_request_dispatch_immediate
,
2081 return NT_STATUS_OK
;
2084 if (req
->compound_related
) {
2085 req
->sconn
->smb2
.compound_related_in_progress
= false;
2088 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
2090 /* Set credit for these operations (zero credits if this
2091 is a final reply for an async operation). */
2092 smb2_calculate_credits(req
, req
);
2094 if (req
->do_signing
) {
2096 struct smbXsrv_session
*x
= req
->session
;
2097 struct smbXsrv_connection
*conn
= x
->connection
;
2098 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
2100 status
= smb2_signing_sign_pdu(signing_key
,
2102 &req
->out
.vector
[i
], 3);
2103 if (!NT_STATUS_IS_OK(status
)) {
2108 if (DEBUGLEVEL
>= 10) {
2109 dbgtext("smbd_smb2_request_reply: sending...\n");
2110 print_req_vectors(req
);
2113 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2114 if (req
->out
.vector_count
== 4 &&
2115 req
->out
.vector
[3].iov_base
== NULL
&&
2116 req
->out
.vector
[3].iov_len
!= 0) {
2117 /* Dynamic part is NULL. Chop it off,
2118 We're going to send it via sendfile. */
2119 req
->out
.vector_count
-= 1;
2122 subreq
= tstream_writev_queue_send(req
,
2124 req
->sconn
->smb2
.stream
,
2125 req
->sconn
->smb2
.send_queue
,
2127 req
->out
.vector_count
);
2128 if (subreq
== NULL
) {
2129 return NT_STATUS_NO_MEMORY
;
2131 tevent_req_set_callback(subreq
, smbd_smb2_request_writev_done
, req
);
2133 * We're done with this request -
2134 * move it off the "being processed" queue.
2136 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
2138 return NT_STATUS_OK
;
2141 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
);
2143 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
2144 struct tevent_immediate
*im
,
2147 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
2148 struct smbd_smb2_request
);
2149 struct smbd_server_connection
*sconn
= req
->sconn
;
2154 if (DEBUGLEVEL
>= 10) {
2155 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2156 req
->current_idx
, req
->in
.vector_count
));
2157 print_req_vectors(req
);
2160 status
= smbd_smb2_request_dispatch(req
);
2161 if (!NT_STATUS_IS_OK(status
)) {
2162 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2166 status
= smbd_smb2_request_next_incoming(sconn
);
2167 if (!NT_STATUS_IS_OK(status
)) {
2168 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2173 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
)
2175 struct smbd_smb2_request
*req
= tevent_req_callback_data(subreq
,
2176 struct smbd_smb2_request
);
2177 struct smbd_server_connection
*sconn
= req
->sconn
;
2182 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
2183 TALLOC_FREE(subreq
);
2186 status
= map_nt_error_from_unix(sys_errno
);
2187 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2188 nt_errstr(status
)));
2189 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2193 status
= smbd_smb2_request_next_incoming(sconn
);
2194 if (!NT_STATUS_IS_OK(status
)) {
2195 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2200 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
2202 DATA_BLOB body
, DATA_BLOB
*dyn
,
2203 const char *location
)
2206 int i
= req
->current_idx
;
2207 uint32_t next_command_ofs
;
2209 DEBUG(10,("smbd_smb2_request_done_ex: "
2210 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2211 i
, nt_errstr(status
), (unsigned int)body
.length
,
2213 (unsigned int)(dyn
? dyn
->length
: 0),
2216 if (body
.length
< 2) {
2217 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2220 if ((body
.length
% 2) != 0) {
2221 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2224 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
2226 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
2227 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
2229 req
->out
.vector
[i
+1].iov_base
= (void *)body
.data
;
2230 req
->out
.vector
[i
+1].iov_len
= body
.length
;
2233 req
->out
.vector
[i
+2].iov_base
= (void *)dyn
->data
;
2234 req
->out
.vector
[i
+2].iov_len
= dyn
->length
;
2236 req
->out
.vector
[i
+2].iov_base
= NULL
;
2237 req
->out
.vector
[i
+2].iov_len
= 0;
2240 /* see if we need to recalculate the offset to the next response */
2241 if (next_command_ofs
> 0) {
2242 next_command_ofs
= SMB2_HDR_BODY
;
2243 next_command_ofs
+= req
->out
.vector
[i
+1].iov_len
;
2244 next_command_ofs
+= req
->out
.vector
[i
+2].iov_len
;
2247 if ((next_command_ofs
% 8) != 0) {
2248 size_t pad_size
= 8 - (next_command_ofs
% 8);
2249 if (req
->out
.vector
[i
+2].iov_len
== 0) {
2251 * if the dyn buffer is empty
2252 * we can use it to add padding
2256 pad
= talloc_zero_array(req
->out
.vector
,
2259 return smbd_smb2_request_error(req
,
2260 NT_STATUS_NO_MEMORY
);
2263 req
->out
.vector
[i
+2].iov_base
= (void *)pad
;
2264 req
->out
.vector
[i
+2].iov_len
= pad_size
;
2267 * For now we copy the dynamic buffer
2268 * and add the padding to the new buffer
2275 old_size
= req
->out
.vector
[i
+2].iov_len
;
2276 old_dyn
= (uint8_t *)req
->out
.vector
[i
+2].iov_base
;
2278 new_size
= old_size
+ pad_size
;
2279 new_dyn
= talloc_zero_array(req
->out
.vector
,
2281 if (new_dyn
== NULL
) {
2282 return smbd_smb2_request_error(req
,
2283 NT_STATUS_NO_MEMORY
);
2286 memcpy(new_dyn
, old_dyn
, old_size
);
2287 memset(new_dyn
+ old_size
, 0, pad_size
);
2289 req
->out
.vector
[i
+2].iov_base
= (void *)new_dyn
;
2290 req
->out
.vector
[i
+2].iov_len
= new_size
;
2292 next_command_ofs
+= pad_size
;
2295 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
2297 return smbd_smb2_request_reply(req
);
2300 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
2303 const char *location
)
2306 int i
= req
->current_idx
;
2307 uint8_t *outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
2309 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2310 i
, nt_errstr(status
), info
? " +info" : "",
2313 body
.data
= outhdr
+ SMB2_HDR_BODY
;
2315 SSVAL(body
.data
, 0, 9);
2318 SIVAL(body
.data
, 0x04, info
->length
);
2320 /* Allocated size of req->out.vector[i].iov_base
2321 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2322 * 1 byte without having to do an alloc.
2324 info
= talloc_zero_array(req
->out
.vector
,
2328 return NT_STATUS_NO_MEMORY
;
2330 info
->data
= ((uint8_t *)outhdr
) +
2331 OUTVEC_ALLOC_SIZE
- 1;
2333 SCVAL(info
->data
, 0, 0);
2337 * if a request fails, all other remaining
2338 * compounded requests should fail too
2340 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
2342 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
2346 struct smbd_smb2_send_oplock_break_state
{
2347 struct smbd_server_connection
*sconn
;
2348 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x18];
2349 struct iovec vector
;
2352 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
);
2354 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
2355 uint64_t file_id_persistent
,
2356 uint64_t file_id_volatile
,
2357 uint8_t oplock_level
)
2359 struct smbd_smb2_send_oplock_break_state
*state
;
2360 struct tevent_req
*subreq
;
2364 state
= talloc(sconn
, struct smbd_smb2_send_oplock_break_state
);
2365 if (state
== NULL
) {
2366 return NT_STATUS_NO_MEMORY
;
2368 state
->sconn
= sconn
;
2370 state
->vector
.iov_base
= (void *)state
->buf
;
2371 state
->vector
.iov_len
= sizeof(state
->buf
);
2373 _smb2_setlen(state
->buf
, sizeof(state
->buf
) - 4);
2374 hdr
= state
->buf
+ 4;
2375 body
= hdr
+ SMB2_HDR_BODY
;
2377 SIVAL(hdr
, 0, SMB2_MAGIC
);
2378 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
2379 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
2380 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
2381 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
2382 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
2383 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
2384 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
2385 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
2386 SIVAL(hdr
, SMB2_HDR_PID
, 0);
2387 SIVAL(hdr
, SMB2_HDR_TID
, 0);
2388 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
2389 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
2391 SSVAL(body
, 0x00, 0x18);
2393 SCVAL(body
, 0x02, oplock_level
);
2394 SCVAL(body
, 0x03, 0); /* reserved */
2395 SIVAL(body
, 0x04, 0); /* reserved */
2396 SBVAL(body
, 0x08, file_id_persistent
);
2397 SBVAL(body
, 0x10, file_id_volatile
);
2399 subreq
= tstream_writev_queue_send(state
,
2402 sconn
->smb2
.send_queue
,
2404 if (subreq
== NULL
) {
2405 return NT_STATUS_NO_MEMORY
;
2407 tevent_req_set_callback(subreq
,
2408 smbd_smb2_oplock_break_writev_done
,
2411 return NT_STATUS_OK
;
2414 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
)
2416 struct smbd_smb2_send_oplock_break_state
*state
=
2417 tevent_req_callback_data(subreq
,
2418 struct smbd_smb2_send_oplock_break_state
);
2419 struct smbd_server_connection
*sconn
= state
->sconn
;
2423 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
2424 TALLOC_FREE(subreq
);
2426 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
2427 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2434 struct smbd_smb2_request_read_state
{
2436 bool asked_for_header
;
2437 struct smbd_smb2_request
*smb2_req
;
2440 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2442 TALLOC_CTX
*mem_ctx
,
2443 struct iovec
**_vector
,
2445 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
);
2447 static struct tevent_req
*smbd_smb2_request_read_send(TALLOC_CTX
*mem_ctx
,
2448 struct tevent_context
*ev
,
2449 struct smbd_server_connection
*sconn
)
2451 struct tevent_req
*req
;
2452 struct smbd_smb2_request_read_state
*state
;
2453 struct tevent_req
*subreq
;
2455 req
= tevent_req_create(mem_ctx
, &state
,
2456 struct smbd_smb2_request_read_state
);
2461 state
->asked_for_header
= false;
2463 state
->smb2_req
= smbd_smb2_request_allocate(state
);
2464 if (tevent_req_nomem(state
->smb2_req
, req
)) {
2465 return tevent_req_post(req
, ev
);
2467 state
->smb2_req
->sconn
= sconn
;
2469 subreq
= tstream_readv_pdu_queue_send(state
, ev
, sconn
->smb2
.stream
,
2470 sconn
->smb2
.recv_queue
,
2471 smbd_smb2_request_next_vector
,
2473 if (tevent_req_nomem(subreq
, req
)) {
2474 return tevent_req_post(req
, ev
);
2476 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
2481 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2483 TALLOC_CTX
*mem_ctx
,
2484 struct iovec
**_vector
,
2487 struct smbd_smb2_request_read_state
*state
=
2488 talloc_get_type_abort(private_data
,
2489 struct smbd_smb2_request_read_state
);
2490 struct smbd_smb2_request
*req
= state
->smb2_req
;
2491 struct iovec
*vector
;
2492 int idx
= req
->in
.vector_count
;
2494 uint8_t *buf
= NULL
;
2496 if (req
->in
.vector_count
== 0) {
2498 * first we need to get the NBT header
2500 req
->in
.vector
= talloc_array(req
, struct iovec
,
2501 req
->in
.vector_count
+ 1);
2502 if (req
->in
.vector
== NULL
) {
2505 req
->in
.vector_count
+= 1;
2507 req
->in
.vector
[idx
].iov_base
= (void *)req
->in
.nbt_hdr
;
2508 req
->in
.vector
[idx
].iov_len
= 4;
2510 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2511 if (vector
== NULL
) {
2515 vector
[0] = req
->in
.vector
[idx
];
2522 if (req
->in
.vector_count
== 1) {
2524 * Now we analyze the NBT header
2526 state
->missing
= smb2_len(req
->in
.vector
[0].iov_base
);
2528 if (state
->missing
== 0) {
2529 /* if there're no remaining bytes, we're done */
2535 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2537 req
->in
.vector_count
+ 1);
2538 if (req
->in
.vector
== NULL
) {
2541 req
->in
.vector_count
+= 1;
2543 if (CVAL(req
->in
.vector
[0].iov_base
, 0) != 0) {
2545 * it's a special NBT message,
2546 * so get all remaining bytes
2548 len
= state
->missing
;
2549 } else if (state
->missing
< (SMB2_HDR_BODY
+ 2)) {
2551 * it's an invalid message, just read what we can get
2552 * and let the caller handle the error
2554 len
= state
->missing
;
2557 * We assume it's a SMB2 request,
2558 * and we first get the header and the
2559 * first 2 bytes (the struct size) of the body
2561 len
= SMB2_HDR_BODY
+ 2;
2563 state
->asked_for_header
= true;
2566 state
->missing
-= len
;
2568 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2573 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2574 req
->in
.vector
[idx
].iov_len
= len
;
2576 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2577 if (vector
== NULL
) {
2581 vector
[0] = req
->in
.vector
[idx
];
2588 if (state
->missing
== 0) {
2589 /* if there're no remaining bytes, we're done */
2595 if (state
->asked_for_header
) {
2598 size_t next_command_ofs
;
2603 bool invalid
= false;
2605 state
->asked_for_header
= false;
2608 * We got the SMB2 header and the first 2 bytes
2609 * of the body. We fix the size to just the header
2610 * and manually copy the 2 first bytes to the body section
2612 req
->in
.vector
[idx
-1].iov_len
= SMB2_HDR_BODY
;
2613 hdr
= (const uint8_t *)req
->in
.vector
[idx
-1].iov_base
;
2615 /* allocate vectors for body and dynamic areas */
2616 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2618 req
->in
.vector_count
+ 2);
2619 if (req
->in
.vector
== NULL
) {
2622 req
->in
.vector_count
+= 2;
2624 full_size
= state
->missing
+ SMB2_HDR_BODY
+ 2;
2625 next_command_ofs
= IVAL(hdr
, SMB2_HDR_NEXT_COMMAND
);
2626 body_size
= SVAL(hdr
, SMB2_HDR_BODY
);
2628 if (next_command_ofs
!= 0) {
2629 if (next_command_ofs
< (SMB2_HDR_BODY
+ 2)) {
2631 * this is invalid, just return a zero
2632 * body and let the caller deal with the error
2635 } else if (next_command_ofs
> full_size
) {
2637 * this is invalid, just return a zero
2638 * body and let the caller deal with the error
2642 full_size
= next_command_ofs
;
2647 if (body_size
< 2) {
2649 * this is invalid, just return a zero
2650 * body and let the caller deal with the error
2656 * Mask out the lowest bit, the "dynamic" part
2661 if (body_size
> (full_size
- SMB2_HDR_BODY
)) {
2663 * this is invalid, just return a zero
2664 * body and let the caller deal with the error
2671 /* the caller should check this */
2675 dyn_size
= full_size
- (SMB2_HDR_BODY
+ body_size
);
2677 state
->missing
-= (body_size
- 2) + dyn_size
;
2679 body
= talloc_array(req
->in
.vector
, uint8_t, body_size
);
2684 dyn
= talloc_array(req
->in
.vector
, uint8_t, dyn_size
);
2689 req
->in
.vector
[idx
].iov_base
= (void *)body
;
2690 req
->in
.vector
[idx
].iov_len
= body_size
;
2691 req
->in
.vector
[idx
+1].iov_base
= (void *)dyn
;
2692 req
->in
.vector
[idx
+1].iov_len
= dyn_size
;
2694 vector
= talloc_array(mem_ctx
, struct iovec
, 2);
2695 if (vector
== NULL
) {
2700 * the first 2 bytes of the body were already fetched
2701 * together with the header
2703 memcpy(body
, hdr
+ SMB2_HDR_BODY
, 2);
2704 vector
[0].iov_base
= body
+ 2;
2705 vector
[0].iov_len
= body_size
- 2;
2707 vector
[1] = req
->in
.vector
[idx
+1];
2715 * when we endup here, we're looking for a new SMB2 request
2716 * next. And we ask for its header and the first 2 bytes of
2717 * the body (like we did for the first SMB2 request).
2720 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2722 req
->in
.vector_count
+ 1);
2723 if (req
->in
.vector
== NULL
) {
2726 req
->in
.vector_count
+= 1;
2729 * We assume it's a SMB2 request,
2730 * and we first get the header and the
2731 * first 2 bytes (the struct size) of the body
2733 len
= SMB2_HDR_BODY
+ 2;
2735 if (len
> state
->missing
) {
2736 /* let the caller handle the error */
2737 len
= state
->missing
;
2740 state
->missing
-= len
;
2741 state
->asked_for_header
= true;
2743 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2748 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2749 req
->in
.vector
[idx
].iov_len
= len
;
2751 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2752 if (vector
== NULL
) {
2756 vector
[0] = req
->in
.vector
[idx
];
2763 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
)
2765 struct tevent_req
*req
=
2766 tevent_req_callback_data(subreq
,
2772 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
2774 status
= map_nt_error_from_unix(sys_errno
);
2775 tevent_req_nterror(req
, status
);
2779 tevent_req_done(req
);
2782 static NTSTATUS
smbd_smb2_request_read_recv(struct tevent_req
*req
,
2783 TALLOC_CTX
*mem_ctx
,
2784 struct smbd_smb2_request
**_smb2_req
)
2786 struct smbd_smb2_request_read_state
*state
=
2787 tevent_req_data(req
,
2788 struct smbd_smb2_request_read_state
);
2791 if (tevent_req_is_nterror(req
, &status
)) {
2792 tevent_req_received(req
);
2796 talloc_steal(mem_ctx
, state
->smb2_req
->mem_pool
);
2797 *_smb2_req
= state
->smb2_req
;
2798 tevent_req_received(req
);
2799 return NT_STATUS_OK
;
2802 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
);
2804 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
)
2806 size_t max_send_queue_len
;
2807 size_t cur_send_queue_len
;
2808 struct tevent_req
*subreq
;
2810 if (sconn
->smb2
.compound_related_in_progress
) {
2812 * Can't read another until the related
2815 return NT_STATUS_OK
;
2818 if (tevent_queue_length(sconn
->smb2
.recv_queue
) > 0) {
2820 * if there is already a smbd_smb2_request_read
2821 * pending, we are done.
2823 return NT_STATUS_OK
;
2826 max_send_queue_len
= MAX(1, sconn
->smb2
.max_credits
/16);
2827 cur_send_queue_len
= tevent_queue_length(sconn
->smb2
.send_queue
);
2829 if (cur_send_queue_len
> max_send_queue_len
) {
2831 * if we have a lot of requests to send,
2832 * we wait until they are on the wire until we
2833 * ask for the next request.
2835 return NT_STATUS_OK
;
2838 /* ask for the next request */
2839 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->ev_ctx
, sconn
);
2840 if (subreq
== NULL
) {
2841 return NT_STATUS_NO_MEMORY
;
2843 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);
2845 return NT_STATUS_OK
;
2848 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
2849 const uint8_t *inbuf
, size_t size
)
2852 struct smbd_smb2_request
*req
= NULL
;
2854 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2855 (unsigned int)size
));
2857 status
= smbd_initialize_smb2(sconn
);
2858 if (!NT_STATUS_IS_OK(status
)) {
2859 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2863 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
2864 if (!NT_STATUS_IS_OK(status
)) {
2865 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2869 status
= smbd_smb2_request_validate(req
);
2870 if (!NT_STATUS_IS_OK(status
)) {
2871 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2875 status
= smbd_smb2_request_setup_out(req
);
2876 if (!NT_STATUS_IS_OK(status
)) {
2877 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2881 status
= smbd_smb2_request_dispatch(req
);
2882 if (!NT_STATUS_IS_OK(status
)) {
2883 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2887 status
= smbd_smb2_request_next_incoming(sconn
);
2888 if (!NT_STATUS_IS_OK(status
)) {
2889 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2893 sconn
->num_requests
++;
2896 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
)
2898 struct smbd_server_connection
*sconn
= tevent_req_callback_data(subreq
,
2899 struct smbd_server_connection
);
2901 struct smbd_smb2_request
*req
= NULL
;
2903 status
= smbd_smb2_request_read_recv(subreq
, sconn
, &req
);
2904 TALLOC_FREE(subreq
);
2905 if (!NT_STATUS_IS_OK(status
)) {
2906 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2907 nt_errstr(status
)));
2908 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2912 if (req
->in
.nbt_hdr
[0] != 0x00) {
2913 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2914 req
->in
.nbt_hdr
[0]));
2919 req
->current_idx
= 1;
2921 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2922 req
->current_idx
, req
->in
.vector_count
));
2924 status
= smbd_smb2_request_validate(req
);
2925 if (!NT_STATUS_IS_OK(status
)) {
2926 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2930 status
= smbd_smb2_request_setup_out(req
);
2931 if (!NT_STATUS_IS_OK(status
)) {
2932 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2936 status
= smbd_smb2_request_dispatch(req
);
2937 if (!NT_STATUS_IS_OK(status
)) {
2938 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2943 status
= smbd_smb2_request_next_incoming(sconn
);
2944 if (!NT_STATUS_IS_OK(status
)) {
2945 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2949 sconn
->num_requests
++;
2951 /* The timeout_processing function isn't run nearly
2952 often enough to implement 'max log size' without
2953 overrunning the size of the file by many megabytes.
2954 This is especially true if we are running at debug
2955 level 10. Checking every 50 SMB2s is a nice
2956 tradeoff of performance vs log file size overrun. */
2958 if ((sconn
->num_requests
% 50) == 0 &&
2959 need_to_check_log_size()) {
2960 change_to_root_user();