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"
30 #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9)
32 static const char *smb2_names
[] = {
54 const char *smb2_opcode_name(uint16_t opcode
)
57 return "Bad SMB2 opcode";
59 return smb2_names
[opcode
];
62 static void print_req_vectors(struct smbd_smb2_request
*req
)
66 for (i
= 0; i
< req
->in
.vector_count
; i
++) {
67 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
69 (unsigned int)req
->in
.vector
[i
].iov_len
);
71 for (i
= 0; i
< req
->out
.vector_count
; i
++) {
72 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
74 (unsigned int)req
->out
.vector
[i
].iov_len
);
78 bool smbd_is_smb2_header(const uint8_t *inbuf
, size_t size
)
80 if (size
< (4 + SMB2_HDR_BODY
)) {
84 if (IVAL(inbuf
, 4) != SMB2_MAGIC
) {
91 static NTSTATUS
smbd_initialize_smb2(struct smbd_server_connection
*sconn
)
96 TALLOC_FREE(sconn
->smb1
.fde
);
98 sconn
->smb2
.event_ctx
= smbd_event_context();
100 sconn
->smb2
.recv_queue
= tevent_queue_create(sconn
, "smb2 recv queue");
101 if (sconn
->smb2
.recv_queue
== NULL
) {
102 return NT_STATUS_NO_MEMORY
;
105 sconn
->smb2
.send_queue
= tevent_queue_create(sconn
, "smb2 send queue");
106 if (sconn
->smb2
.send_queue
== NULL
) {
107 return NT_STATUS_NO_MEMORY
;
110 sconn
->smb2
.sessions
.idtree
= idr_init(sconn
);
111 if (sconn
->smb2
.sessions
.idtree
== NULL
) {
112 return NT_STATUS_NO_MEMORY
;
114 sconn
->smb2
.sessions
.limit
= 0x0000FFFE;
115 sconn
->smb2
.sessions
.list
= NULL
;
116 sconn
->smb2
.seqnum_low
= 0;
117 sconn
->smb2
.seqnum_range
= 1;
118 sconn
->smb2
.credits_granted
= 1;
119 sconn
->smb2
.max_credits
= lp_smb2_max_credits();
120 sconn
->smb2
.credits_bitmap
= bitmap_talloc(sconn
,
121 sconn
->smb2
.max_credits
);
122 if (sconn
->smb2
.credits_bitmap
== NULL
) {
123 return NT_STATUS_NO_MEMORY
;
126 ret
= tstream_bsd_existing_socket(sconn
, sconn
->sock
,
127 &sconn
->smb2
.stream
);
129 status
= map_nt_error_from_unix(errno
);
133 /* Ensure child is set to non-blocking mode */
134 set_blocking(sconn
->sock
, false);
138 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
139 #define _smb2_setlen(_buf,len) do { \
140 uint8_t *buf = (uint8_t *)_buf; \
142 buf[1] = ((len)&0xFF0000)>>16; \
143 buf[2] = ((len)&0xFF00)>>8; \
144 buf[3] = (len)&0xFF; \
147 static void smb2_setup_nbt_length(struct iovec
*vector
, int count
)
152 for (i
=1; i
< count
; i
++) {
153 len
+= vector
[i
].iov_len
;
156 _smb2_setlen(vector
[0].iov_base
, len
);
159 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request
**req
)
162 (*req
)->parent
= NULL
;
163 (*req
)->mem_pool
= NULL
;
169 static int smbd_smb2_request_destructor(struct smbd_smb2_request
*req
)
173 talloc_free(req
->mem_pool
);
179 static struct smbd_smb2_request
*smbd_smb2_request_allocate(TALLOC_CTX
*mem_ctx
)
181 TALLOC_CTX
*mem_pool
;
182 struct smbd_smb2_request
**parent
;
183 struct smbd_smb2_request
*req
;
186 /* Enable this to find subtle valgrind errors. */
187 mem_pool
= talloc_init("smbd_smb2_request_allocate");
189 mem_pool
= talloc_pool(mem_ctx
, 8192);
191 if (mem_pool
== NULL
) {
195 parent
= talloc(mem_pool
, struct smbd_smb2_request
*);
196 if (parent
== NULL
) {
197 talloc_free(mem_pool
);
201 req
= talloc_zero(parent
, struct smbd_smb2_request
);
203 talloc_free(mem_pool
);
207 req
->mem_pool
= mem_pool
;
208 req
->parent
= parent
;
210 req
->last_session_id
= UINT64_MAX
;
211 req
->last_tid
= UINT32_MAX
;
213 talloc_set_destructor(parent
, smbd_smb2_request_parent_destructor
);
214 talloc_set_destructor(req
, smbd_smb2_request_destructor
);
219 static NTSTATUS
smbd_smb2_request_create(struct smbd_server_connection
*sconn
,
220 const uint8_t *inbuf
, size_t size
,
221 struct smbd_smb2_request
**_req
)
223 struct smbd_smb2_request
*req
;
224 uint32_t protocol_version
;
225 const uint8_t *inhdr
= NULL
;
228 uint32_t next_command_ofs
;
230 if (size
< (4 + SMB2_HDR_BODY
+ 2)) {
231 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size
));
232 return NT_STATUS_INVALID_PARAMETER
;
237 protocol_version
= IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
);
238 if (protocol_version
!= SMB2_MAGIC
) {
239 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
241 return NT_STATUS_INVALID_PARAMETER
;
244 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
245 if (cmd
!= SMB2_OP_NEGPROT
) {
246 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
248 return NT_STATUS_INVALID_PARAMETER
;
251 next_command_ofs
= IVAL(inhdr
, SMB2_HDR_NEXT_COMMAND
);
252 if (next_command_ofs
!= 0) {
253 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
255 return NT_STATUS_INVALID_PARAMETER
;
258 req
= smbd_smb2_request_allocate(sconn
);
260 return NT_STATUS_NO_MEMORY
;
264 talloc_steal(req
, inbuf
);
266 req
->in
.vector
= talloc_array(req
, struct iovec
, 4);
267 if (req
->in
.vector
== NULL
) {
269 return NT_STATUS_NO_MEMORY
;
271 req
->in
.vector_count
= 4;
273 memcpy(req
->in
.nbt_hdr
, inbuf
, 4);
276 req
->in
.vector
[0].iov_base
= (void *)req
->in
.nbt_hdr
;
277 req
->in
.vector
[0].iov_len
= 4;
278 ofs
+= req
->in
.vector
[0].iov_len
;
280 req
->in
.vector
[1].iov_base
= (void *)(inbuf
+ ofs
);
281 req
->in
.vector
[1].iov_len
= SMB2_HDR_BODY
;
282 ofs
+= req
->in
.vector
[1].iov_len
;
284 req
->in
.vector
[2].iov_base
= (void *)(inbuf
+ ofs
);
285 req
->in
.vector
[2].iov_len
= SVAL(inbuf
, ofs
) & 0xFFFE;
286 ofs
+= req
->in
.vector
[2].iov_len
;
289 return NT_STATUS_INVALID_PARAMETER
;
292 req
->in
.vector
[3].iov_base
= (void *)(inbuf
+ ofs
);
293 req
->in
.vector
[3].iov_len
= size
- ofs
;
294 ofs
+= req
->in
.vector
[3].iov_len
;
296 req
->current_idx
= 1;
302 static bool smb2_validate_sequence_number(struct smbd_server_connection
*sconn
,
303 uint64_t message_id
, uint64_t seq_id
)
305 struct bitmap
*credits_bm
= sconn
->smb2
.credits_bitmap
;
308 if (seq_id
< sconn
->smb2
.seqnum_low
) {
309 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
310 "%llu (sequence id %llu) "
311 "(granted = %u, low = %llu, range = %u)\n",
312 (unsigned long long)message_id
,
313 (unsigned long long)seq_id
,
314 (unsigned int)sconn
->smb2
.credits_granted
,
315 (unsigned long long)sconn
->smb2
.seqnum_low
,
316 (unsigned int)sconn
->smb2
.seqnum_range
));
320 if (seq_id
>= sconn
->smb2
.seqnum_low
+ sconn
->smb2
.seqnum_range
) {
321 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
322 "%llu (sequence id %llu) "
323 "(granted = %u, low = %llu, range = %u)\n",
324 (unsigned long long)message_id
,
325 (unsigned long long)seq_id
,
326 (unsigned int)sconn
->smb2
.credits_granted
,
327 (unsigned long long)sconn
->smb2
.seqnum_low
,
328 (unsigned int)sconn
->smb2
.seqnum_range
));
332 offset
= seq_id
% sconn
->smb2
.max_credits
;
334 if (bitmap_query(credits_bm
, offset
)) {
335 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
336 "%llu (sequence id %llu) "
337 "(granted = %u, low = %llu, range = %u) "
339 (unsigned long long)message_id
,
340 (unsigned long long)seq_id
,
341 (unsigned int)sconn
->smb2
.credits_granted
,
342 (unsigned long long)sconn
->smb2
.seqnum_low
,
343 (unsigned int)sconn
->smb2
.seqnum_range
,
348 /* Mark the message_ids as seen in the bitmap. */
349 bitmap_set(credits_bm
, offset
);
351 if (seq_id
!= sconn
->smb2
.seqnum_low
) {
356 * Move the window forward by all the message_id's
359 while (bitmap_query(credits_bm
, offset
)) {
360 DEBUG(10,("smb2_validate_sequence_number: clearing "
361 "id %llu (position %u) from bitmap\n",
362 (unsigned long long)(sconn
->smb2
.seqnum_low
),
364 bitmap_clear(credits_bm
, offset
);
366 sconn
->smb2
.seqnum_low
+= 1;
367 sconn
->smb2
.seqnum_range
-= 1;
368 offset
= sconn
->smb2
.seqnum_low
% sconn
->smb2
.max_credits
;
374 static bool smb2_validate_message_id(struct smbd_server_connection
*sconn
,
375 const uint8_t *inhdr
)
377 uint64_t message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
378 uint16_t opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
381 if (opcode
== SMB2_OP_CANCEL
) {
382 /* SMB2_CANCEL requests by definition resend messageids. */
386 DEBUG(11, ("smb2_validate_message_id: mid %llu, credits_granted %llu, "
387 "seqnum low/range: %llu/%llu\n",
388 (unsigned long long) message_id
,
389 (unsigned long long) sconn
->smb2
.credits_granted
,
390 (unsigned long long) sconn
->smb2
.seqnum_low
,
391 (unsigned long long) sconn
->smb2
.seqnum_range
));
393 if (sconn
->smb2
.credits_granted
< 1) {
394 DEBUG(0, ("smb2_validate_message_id: client used more "
395 "credits than granted, mid %llu, credits_granted %llu, "
396 "seqnum low/range: %llu/%llu\n",
397 (unsigned long long) message_id
,
398 (unsigned long long) sconn
->smb2
.credits_granted
,
399 (unsigned long long) sconn
->smb2
.seqnum_low
,
400 (unsigned long long) sconn
->smb2
.seqnum_range
));
404 ok
= smb2_validate_sequence_number(sconn
, message_id
, message_id
);
409 /* substract used credits */
410 sconn
->smb2
.credits_granted
-= 1;
415 static NTSTATUS
smbd_smb2_request_validate(struct smbd_smb2_request
*req
)
420 count
= req
->in
.vector_count
;
423 /* It's not a SMB2 request */
424 return NT_STATUS_INVALID_PARAMETER
;
427 for (idx
=1; idx
< count
; idx
+= 3) {
428 const uint8_t *inhdr
= NULL
;
431 if (req
->in
.vector
[idx
].iov_len
!= SMB2_HDR_BODY
) {
432 return NT_STATUS_INVALID_PARAMETER
;
435 if (req
->in
.vector
[idx
+1].iov_len
< 2) {
436 return NT_STATUS_INVALID_PARAMETER
;
439 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
441 /* Check the SMB2 header */
442 if (IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
) != SMB2_MAGIC
) {
443 return NT_STATUS_INVALID_PARAMETER
;
446 if (!smb2_validate_message_id(req
->sconn
, inhdr
)) {
447 return NT_STATUS_INVALID_PARAMETER
;
450 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
453 * the 1st request should never have the
454 * SMB2_HDR_FLAG_CHAINED flag set
456 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
457 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
460 } else if (idx
== 4) {
462 * the 2nd request triggers related vs. unrelated
463 * compounded requests
465 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
466 req
->compound_related
= true;
468 } else if (idx
> 4) {
471 * It seems the this tests are wrong
472 * see the SMB2-COMPOUND test
476 * all other requests should match the 2nd one
478 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
479 if (!req
->compound_related
) {
481 NT_STATUS_INVALID_PARAMETER
;
485 if (req
->compound_related
) {
487 NT_STATUS_INVALID_PARAMETER
;
498 static void smb2_set_operation_credit(struct smbd_server_connection
*sconn
,
499 const struct iovec
*in_vector
,
500 struct iovec
*out_vector
)
502 const uint8_t *inhdr
= (const uint8_t *)in_vector
->iov_base
;
503 uint8_t *outhdr
= (uint8_t *)out_vector
->iov_base
;
504 uint16_t credits_requested
;
508 uint16_t credits_granted
= 0;
509 uint64_t credits_possible
;
510 uint16_t current_max_credits
;
513 * first we grant only 1/16th of the max range.
515 * Windows also starts with the 1/16th and then grants
516 * more later. I was only able to trigger higher
517 * values, when using a verify high credit charge.
519 * TODO: scale up depending one load, free memory
521 * Maybe also on the relationship between number
522 * of requests and the used sequence number.
523 * Which means we would grant more credits
524 * for client which use multi credit requests.
526 current_max_credits
= sconn
->smb2
.max_credits
/ 16;
527 current_max_credits
= MAX(current_max_credits
, 1);
529 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
530 credits_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
531 out_flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
532 out_status
= NT_STATUS(IVAL(outhdr
, SMB2_HDR_STATUS
));
534 SMB_ASSERT(sconn
->smb2
.max_credits
>= sconn
->smb2
.credits_granted
);
536 if (out_flags
& SMB2_HDR_FLAG_ASYNC
) {
538 * In case we already send an async interim
539 * response, we should not grant
540 * credits on the final response.
543 } else if (credits_requested
> 0) {
544 uint16_t additional_max
= 0;
545 uint16_t additional_credits
= credits_requested
- 1;
548 case SMB2_OP_NEGPROT
:
550 case SMB2_OP_SESSSETUP
:
552 * Windows 2012 RC1 starts to grant
554 * with a successful session setup
556 if (NT_STATUS_IS_OK(out_status
)) {
562 * We match windows and only grant additional credits
569 additional_credits
= MIN(additional_credits
, additional_max
);
571 credits_granted
= 1 + additional_credits
;
572 } else if (sconn
->smb2
.credits_granted
== 0) {
574 * Make sure the client has always at least one credit
580 * sequence numbers should not wrap
582 * 1. calculate the possible credits until
583 * the sequence numbers start to wrap on 64-bit.
585 * 2. UINT64_MAX is used for Break Notifications.
587 * 2. truncate the possible credits to the maximum
588 * credits we want to grant to the client in total.
590 * 3. remove the range we'll already granted to the client
591 * this makes sure the client consumes the lowest sequence
592 * number, before we can grant additional credits.
594 credits_possible
= UINT64_MAX
- sconn
->smb2
.seqnum_low
;
595 if (credits_possible
> 0) {
596 /* remove UINT64_MAX */
597 credits_possible
-= 1;
599 credits_possible
= MIN(credits_possible
, current_max_credits
);
600 credits_possible
-= sconn
->smb2
.seqnum_range
;
602 credits_granted
= MIN(credits_granted
, credits_possible
);
604 SSVAL(outhdr
, SMB2_HDR_CREDIT
, credits_granted
);
605 sconn
->smb2
.credits_granted
+= credits_granted
;
606 sconn
->smb2
.seqnum_range
+= credits_granted
;
608 DEBUG(10,("smb2_set_operation_credit: requested %u, "
609 "granted %u, current possible/max %u/%u, "
610 "total granted/max/low/range %u/%u/%llu/%u\n",
611 (unsigned int)credits_requested
,
612 (unsigned int)credits_granted
,
613 (unsigned int)credits_possible
,
614 (unsigned int)current_max_credits
,
615 (unsigned int)sconn
->smb2
.credits_granted
,
616 (unsigned int)sconn
->smb2
.max_credits
,
617 (unsigned long long)sconn
->smb2
.seqnum_low
,
618 (unsigned int)sconn
->smb2
.seqnum_range
));
621 static void smb2_calculate_credits(const struct smbd_smb2_request
*inreq
,
622 struct smbd_smb2_request
*outreq
)
625 uint16_t total_credits
= 0;
627 count
= outreq
->out
.vector_count
;
629 for (idx
=1; idx
< count
; idx
+= 3) {
630 uint8_t *outhdr
= (uint8_t *)outreq
->out
.vector
[idx
].iov_base
;
631 smb2_set_operation_credit(outreq
->sconn
,
632 &inreq
->in
.vector
[idx
],
633 &outreq
->out
.vector
[idx
]);
634 /* To match Windows, count up what we
636 total_credits
+= SVAL(outhdr
, SMB2_HDR_CREDIT
);
637 /* Set to zero in all but the last reply. */
638 if (idx
+ 3 < count
) {
639 SSVAL(outhdr
, SMB2_HDR_CREDIT
, 0);
641 SSVAL(outhdr
, SMB2_HDR_CREDIT
, total_credits
);
646 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
)
648 struct iovec
*vector
;
652 count
= req
->in
.vector_count
;
653 vector
= talloc_zero_array(req
, struct iovec
, count
);
654 if (vector
== NULL
) {
655 return NT_STATUS_NO_MEMORY
;
658 vector
[0].iov_base
= req
->out
.nbt_hdr
;
659 vector
[0].iov_len
= 4;
660 SIVAL(req
->out
.nbt_hdr
, 0, 0);
662 for (idx
=1; idx
< count
; idx
+= 3) {
663 const uint8_t *inhdr
= NULL
;
665 uint8_t *outhdr
= NULL
;
666 uint8_t *outbody
= NULL
;
667 uint32_t next_command_ofs
= 0;
668 struct iovec
*current
= &vector
[idx
];
670 if ((idx
+ 3) < count
) {
671 /* we have a next command -
672 * setup for the error case. */
673 next_command_ofs
= SMB2_HDR_BODY
+ 9;
676 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
677 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
679 outhdr
= talloc_zero_array(vector
, uint8_t,
681 if (outhdr
== NULL
) {
682 return NT_STATUS_NO_MEMORY
;
685 outbody
= outhdr
+ SMB2_HDR_BODY
;
687 current
[0].iov_base
= (void *)outhdr
;
688 current
[0].iov_len
= SMB2_HDR_BODY
;
690 current
[1].iov_base
= (void *)outbody
;
691 current
[1].iov_len
= 8;
693 current
[2].iov_base
= NULL
;
694 current
[2].iov_len
= 0;
696 /* setup the SMB2 header */
697 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
698 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
699 SSVAL(outhdr
, SMB2_HDR_CREDIT_CHARGE
,
700 SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
));
701 SIVAL(outhdr
, SMB2_HDR_STATUS
,
702 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
703 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
704 SVAL(inhdr
, SMB2_HDR_OPCODE
));
705 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
706 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
707 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
708 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
709 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
710 SIVAL(outhdr
, SMB2_HDR_PID
,
711 IVAL(inhdr
, SMB2_HDR_PID
));
712 SIVAL(outhdr
, SMB2_HDR_TID
,
713 IVAL(inhdr
, SMB2_HDR_TID
));
714 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
715 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
716 memcpy(outhdr
+ SMB2_HDR_SIGNATURE
,
717 inhdr
+ SMB2_HDR_SIGNATURE
, 16);
719 /* setup error body header */
720 SSVAL(outbody
, 0x00, 0x08 + 1);
721 SSVAL(outbody
, 0x02, 0);
722 SIVAL(outbody
, 0x04, 0);
725 req
->out
.vector
= vector
;
726 req
->out
.vector_count
= count
;
728 /* setup the length of the NBT packet */
729 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
731 DLIST_ADD_END(req
->sconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
736 void smbd_server_connection_terminate_ex(struct smbd_server_connection
*sconn
,
738 const char *location
)
740 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
742 exit_server_cleanly(reason
);
745 static bool dup_smb2_vec3(TALLOC_CTX
*ctx
,
746 struct iovec
*outvec
,
747 const struct iovec
*srcvec
)
749 /* vec[0] is always boilerplate and must
750 * be allocated with size OUTVEC_ALLOC_SIZE. */
752 outvec
[0].iov_base
= talloc_memdup(ctx
,
755 if (!outvec
[0].iov_base
) {
758 outvec
[0].iov_len
= SMB2_HDR_BODY
;
761 * If this is a "standard" vec[1] of length 8,
762 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
763 * then duplicate this. Else use talloc_memdup().
766 if (srcvec
[1].iov_len
== 8 &&
767 srcvec
[1].iov_base
==
768 ((uint8_t *)srcvec
[0].iov_base
) +
770 outvec
[1].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
772 outvec
[1].iov_len
= 8;
774 outvec
[1].iov_base
= talloc_memdup(ctx
,
777 if (!outvec
[1].iov_base
) {
780 outvec
[1].iov_len
= srcvec
[1].iov_len
;
784 * If this is a "standard" vec[2] of length 1,
785 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
786 * then duplicate this. Else use talloc_memdup().
789 if (srcvec
[2].iov_base
&&
791 if (srcvec
[2].iov_base
==
792 ((uint8_t *)srcvec
[0].iov_base
) +
793 (OUTVEC_ALLOC_SIZE
- 1) &&
794 srcvec
[2].iov_len
== 1) {
795 /* Common SMB2 error packet case. */
796 outvec
[2].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
797 (OUTVEC_ALLOC_SIZE
- 1);
799 outvec
[2].iov_base
= talloc_memdup(ctx
,
802 if (!outvec
[2].iov_base
) {
806 outvec
[2].iov_len
= srcvec
[2].iov_len
;
808 outvec
[2].iov_base
= NULL
;
809 outvec
[2].iov_len
= 0;
814 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
816 struct smbd_smb2_request
*newreq
= NULL
;
817 struct iovec
*outvec
= NULL
;
818 int count
= req
->out
.vector_count
;
821 newreq
= smbd_smb2_request_allocate(req
->sconn
);
826 newreq
->sconn
= req
->sconn
;
827 newreq
->session
= req
->session
;
828 newreq
->do_signing
= req
->do_signing
;
829 newreq
->current_idx
= req
->current_idx
;
830 newreq
->async
= false;
831 newreq
->cancelled
= false;
832 /* Note we are leaving:
836 uninitialized as NULL here as
837 they're not used in the interim
838 response code. JRA. */
840 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
845 newreq
->out
.vector
= outvec
;
846 newreq
->out
.vector_count
= count
;
848 /* Setup the outvec's identically to req. */
849 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
850 outvec
[0].iov_len
= 4;
851 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
853 /* Setup the vectors identically to the ones in req. */
854 for (i
= 1; i
< count
; i
+= 3) {
855 if (!dup_smb2_vec3(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
866 smb2_setup_nbt_length(newreq
->out
.vector
,
867 newreq
->out
.vector_count
);
872 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
);
874 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
877 uint8_t *outhdr
= NULL
;
878 struct smbd_smb2_request
*nreq
= NULL
;
880 /* Create a new smb2 request we'll use
881 for the interim return. */
882 nreq
= dup_smb2_req(req
);
884 return NT_STATUS_NO_MEMORY
;
887 /* Lose the last 3 out vectors. They're the
888 ones we'll be using for the async reply. */
889 nreq
->out
.vector_count
-= 3;
891 smb2_setup_nbt_length(nreq
->out
.vector
,
892 nreq
->out
.vector_count
);
894 /* Step back to the previous reply. */
895 i
= nreq
->current_idx
- 3;
896 outhdr
= (uint8_t *)nreq
->out
.vector
[i
].iov_base
;
897 /* And end the chain. */
898 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
900 /* Calculate outgoing credits */
901 smb2_calculate_credits(req
, nreq
);
903 /* Re-sign if needed. */
904 if (nreq
->do_signing
) {
906 status
= smb2_signing_sign_pdu(nreq
->session
->session_key
,
907 &nreq
->out
.vector
[i
], 3);
908 if (!NT_STATUS_IS_OK(status
)) {
912 if (DEBUGLEVEL
>= 10) {
913 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
914 (unsigned int)nreq
->current_idx
);
915 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
916 (unsigned int)nreq
->out
.vector_count
);
917 print_req_vectors(nreq
);
919 nreq
->subreq
= tstream_writev_queue_send(nreq
,
920 nreq
->sconn
->smb2
.event_ctx
,
921 nreq
->sconn
->smb2
.stream
,
922 nreq
->sconn
->smb2
.send_queue
,
924 nreq
->out
.vector_count
);
926 if (nreq
->subreq
== NULL
) {
927 return NT_STATUS_NO_MEMORY
;
930 tevent_req_set_callback(nreq
->subreq
,
931 smbd_smb2_request_writev_done
,
937 struct smbd_smb2_request_pending_state
{
938 struct smbd_server_connection
*sconn
;
939 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x08 + 1];
940 struct iovec vector
[3];
943 static void smbd_smb2_request_pending_writev_done(struct tevent_req
*subreq
)
945 struct smbd_smb2_request_pending_state
*state
=
946 tevent_req_callback_data(subreq
,
947 struct smbd_smb2_request_pending_state
);
948 struct smbd_server_connection
*sconn
= state
->sconn
;
952 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
955 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
956 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
963 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
964 struct tevent_req
*subreq
)
967 struct smbd_smb2_request_pending_state
*state
= NULL
;
968 int i
= req
->current_idx
;
969 uint8_t *reqhdr
= NULL
;
971 uint8_t *body
= NULL
;
973 uint64_t message_id
= 0;
974 uint64_t async_id
= 0;
975 struct iovec
*outvec
= NULL
;
977 if (!tevent_req_is_in_progress(subreq
)) {
981 req
->subreq
= subreq
;
985 /* We're already async. */
989 if (req
->in
.vector_count
> i
+ 3) {
991 * We're trying to go async in a compound
992 * request chain. This is not allowed.
993 * Cancel the outstanding request.
995 tevent_req_cancel(req
->subreq
);
996 return smbd_smb2_request_error(req
,
997 NT_STATUS_INSUFFICIENT_RESOURCES
);
1000 if (DEBUGLEVEL
>= 10) {
1001 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1002 (unsigned int)req
->current_idx
);
1003 print_req_vectors(req
);
1006 if (req
->out
.vector_count
> 4) {
1007 /* This is a compound reply. We
1008 * must do an interim response
1009 * followed by the async response
1012 status
= smb2_send_async_interim_response(req
);
1013 if (!NT_STATUS_IS_OK(status
)) {
1018 * We're splitting off the last SMB2
1019 * request in a compound set, and the
1020 * smb2_send_async_interim_response()
1021 * call above just sent all the replies
1022 * for the previous SMB2 requests in
1023 * this compound set. So we're no longer
1024 * in the "compound_related_in_progress"
1025 * state, and this is no longer a compound
1028 req
->compound_related
= false;
1029 req
->sconn
->smb2
.compound_related_in_progress
= false;
1032 /* Don't return an intermediate packet on a pipe read/write. */
1033 if (req
->tcon
&& req
->tcon
->compat_conn
&& IS_IPC(req
->tcon
->compat_conn
)) {
1037 reqhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
1038 flags
= (IVAL(reqhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
1039 message_id
= BVAL(reqhdr
, SMB2_HDR_MESSAGE_ID
);
1040 async_id
= message_id
; /* keep it simple for now... */
1043 * What we send is identical to a smbd_smb2_request_error
1044 * packet with an error status of STATUS_PENDING. Make use
1045 * of this fact sometime when refactoring. JRA.
1048 state
= talloc_zero(req
->sconn
, struct smbd_smb2_request_pending_state
);
1049 if (state
== NULL
) {
1050 return NT_STATUS_NO_MEMORY
;
1052 state
->sconn
= req
->sconn
;
1054 state
->vector
[0].iov_base
= (void *)state
->buf
;
1055 state
->vector
[0].iov_len
= 4;
1057 state
->vector
[1].iov_base
= state
->buf
+ 4;
1058 state
->vector
[1].iov_len
= SMB2_HDR_BODY
;
1060 state
->vector
[2].iov_base
= state
->buf
+ 4 + SMB2_HDR_BODY
;
1061 state
->vector
[2].iov_len
= 9;
1063 smb2_setup_nbt_length(state
->vector
, 3);
1065 hdr
= (uint8_t *)state
->vector
[1].iov_base
;
1066 body
= (uint8_t *)state
->vector
[2].iov_base
;
1068 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
1069 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1070 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1071 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
1072 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(reqhdr
, SMB2_HDR_OPCODE
));
1074 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
);
1075 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1076 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
1077 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
1078 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
1079 BVAL(reqhdr
, SMB2_HDR_SESSION_ID
));
1080 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
1082 SSVAL(body
, 0x00, 0x08 + 1);
1084 SCVAL(body
, 0x02, 0);
1085 SCVAL(body
, 0x03, 0);
1086 SIVAL(body
, 0x04, 0);
1087 /* Match W2K8R2... */
1088 SCVAL(body
, 0x08, 0x21);
1090 /* Ensure we correctly go through crediting. Grant
1091 the credits now, and zero credits on the final
1093 smb2_set_operation_credit(req
->sconn
,
1097 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1099 if (req
->do_signing
) {
1100 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
1101 &state
->vector
[1], 2);
1102 if (!NT_STATUS_IS_OK(status
)) {
1107 subreq
= tstream_writev_queue_send(state
,
1108 req
->sconn
->smb2
.event_ctx
,
1109 req
->sconn
->smb2
.stream
,
1110 req
->sconn
->smb2
.send_queue
,
1114 if (subreq
== NULL
) {
1115 return NT_STATUS_NO_MEMORY
;
1118 tevent_req_set_callback(subreq
,
1119 smbd_smb2_request_pending_writev_done
,
1122 /* Note we're going async with this request. */
1128 * Now manipulate req so that the outstanding async request
1129 * is the only one left in the struct smbd_smb2_request.
1132 if (req
->current_idx
== 1) {
1133 /* There was only one. */
1137 /* Re-arrange the in.vectors. */
1138 req
->in
.vector
[1] = req
->in
.vector
[i
];
1139 req
->in
.vector
[2] = req
->in
.vector
[i
+1];
1140 req
->in
.vector
[3] = req
->in
.vector
[i
+2];
1141 req
->in
.vector_count
= 4;
1142 /* Reset the new in size. */
1143 smb2_setup_nbt_length(req
->in
.vector
, 4);
1145 /* Now recreate the out.vectors. */
1146 outvec
= talloc_zero_array(req
, struct iovec
, 4);
1148 return NT_STATUS_NO_MEMORY
;
1151 /* 0 is always boilerplate and must
1152 * be of size 4 for the length field. */
1154 outvec
[0].iov_base
= req
->out
.nbt_hdr
;
1155 outvec
[0].iov_len
= 4;
1156 SIVAL(req
->out
.nbt_hdr
, 0, 0);
1158 if (!dup_smb2_vec3(outvec
, &outvec
[1], &req
->out
.vector
[i
])) {
1159 return NT_STATUS_NO_MEMORY
;
1162 TALLOC_FREE(req
->out
.vector
);
1164 req
->out
.vector
= outvec
;
1166 req
->current_idx
= 1;
1167 req
->out
.vector_count
= 4;
1171 smb2_setup_nbt_length(req
->out
.vector
,
1172 req
->out
.vector_count
);
1175 /* Ensure our final reply matches the interim one. */
1176 reqhdr
= (uint8_t *)req
->out
.vector
[1].iov_base
;
1177 SIVAL(reqhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1178 SBVAL(reqhdr
, SMB2_HDR_PID
, async_id
);
1181 const uint8_t *inhdr
=
1182 (const uint8_t *)req
->in
.vector
[1].iov_base
;
1183 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1185 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1186 (unsigned long long)async_id
));
1190 return NT_STATUS_OK
;
1193 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
1195 struct smbd_server_connection
*sconn
= req
->sconn
;
1196 struct smbd_smb2_request
*cur
;
1197 const uint8_t *inhdr
;
1198 int i
= req
->current_idx
;
1200 uint64_t search_message_id
;
1201 uint64_t search_async_id
;
1204 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1206 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1207 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1208 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
1211 * we don't need the request anymore
1212 * cancel requests never have a response
1214 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1217 for (cur
= sconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
1218 const uint8_t *outhdr
;
1219 uint64_t message_id
;
1222 i
= cur
->current_idx
;
1224 outhdr
= (const uint8_t *)cur
->out
.vector
[i
].iov_base
;
1226 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1227 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
1229 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1230 if (search_async_id
== async_id
) {
1231 found_id
= async_id
;
1235 if (search_message_id
== message_id
) {
1236 found_id
= message_id
;
1242 if (cur
&& cur
->subreq
) {
1243 inhdr
= (const uint8_t *)cur
->in
.vector
[i
].iov_base
;
1244 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1245 "cancel opcode[%s] mid %llu\n",
1246 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1247 (unsigned long long)found_id
));
1248 tevent_req_cancel(cur
->subreq
);
1251 return NT_STATUS_OK
;
1254 NTSTATUS
smbd_smb2_request_verify_sizes(struct smbd_smb2_request
*req
,
1255 size_t expected_body_size
)
1257 const uint8_t *inhdr
;
1259 const uint8_t *inbody
;
1260 int i
= req
->current_idx
;
1262 size_t min_dyn_size
= expected_body_size
& 0x00000001;
1265 * The following should be checked already.
1267 if ((i
+2) > req
->in
.vector_count
) {
1268 return NT_STATUS_INTERNAL_ERROR
;
1270 if (req
->in
.vector
[i
+0].iov_len
!= SMB2_HDR_BODY
) {
1271 return NT_STATUS_INTERNAL_ERROR
;
1273 if (req
->in
.vector
[i
+1].iov_len
< 2) {
1274 return NT_STATUS_INTERNAL_ERROR
;
1277 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1278 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1282 case SMB2_OP_GETINFO
:
1288 * Now check the expected body size,
1289 * where the last byte might be in the
1290 * dynnamic section..
1292 if (req
->in
.vector
[i
+1].iov_len
!= (expected_body_size
& 0xFFFFFFFE)) {
1293 return NT_STATUS_INVALID_PARAMETER
;
1295 if (req
->in
.vector
[i
+2].iov_len
< min_dyn_size
) {
1296 return NT_STATUS_INVALID_PARAMETER
;
1299 inbody
= (const uint8_t *)req
->in
.vector
[i
+1].iov_base
;
1301 body_size
= SVAL(inbody
, 0x00);
1302 if (body_size
!= expected_body_size
) {
1303 return NT_STATUS_INVALID_PARAMETER
;
1306 return NT_STATUS_OK
;
1309 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
1311 const uint8_t *inhdr
;
1312 int i
= req
->current_idx
;
1317 NTSTATUS session_status
;
1318 uint32_t allowed_flags
;
1319 NTSTATUS return_value
;
1321 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1323 /* TODO: verify more things */
1325 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1326 opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1327 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1328 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1329 smb2_opcode_name(opcode
),
1330 (unsigned long long)mid
));
1332 if (get_Protocol() >= PROTOCOL_SMB2
) {
1334 * once the protocol is negotiated
1335 * SMB2_OP_NEGPROT is not allowed anymore
1337 if (opcode
== SMB2_OP_NEGPROT
) {
1338 /* drop the connection */
1339 return NT_STATUS_INVALID_PARAMETER
;
1343 * if the protocol is not negotiated yet
1344 * only SMB2_OP_NEGPROT is allowed.
1346 if (opcode
!= SMB2_OP_NEGPROT
) {
1347 /* drop the connection */
1348 return NT_STATUS_INVALID_PARAMETER
;
1352 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
1353 SMB2_HDR_FLAG_SIGNED
|
1355 if (opcode
== SMB2_OP_CANCEL
) {
1356 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
1358 if ((flags
& ~allowed_flags
) != 0) {
1359 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1363 * Check if the client provided a valid session id,
1364 * if so smbd_smb2_request_check_session() calls
1365 * set_current_user_info().
1367 * As some command don't require a valid session id
1368 * we defer the check of the session_status
1370 session_status
= smbd_smb2_request_check_session(req
);
1372 req
->do_signing
= false;
1373 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
1374 if (!NT_STATUS_IS_OK(session_status
)) {
1375 return smbd_smb2_request_error(req
, session_status
);
1378 req
->do_signing
= true;
1379 status
= smb2_signing_check_pdu(req
->session
->session_key
,
1380 &req
->in
.vector
[i
], 3);
1381 if (!NT_STATUS_IS_OK(status
)) {
1382 return smbd_smb2_request_error(req
, status
);
1384 } else if (opcode
== SMB2_OP_CANCEL
) {
1385 /* Cancel requests are allowed to skip the signing */
1386 } else if (req
->session
&& req
->session
->do_signing
) {
1387 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
1390 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
1392 * This check is mostly for giving the correct error code
1393 * for compounded requests.
1395 * TODO: we may need to move this after the session
1398 if (!NT_STATUS_IS_OK(req
->next_status
)) {
1399 return smbd_smb2_request_error(req
, req
->next_status
);
1402 req
->compat_chain_fsp
= NULL
;
1405 if (req
->compound_related
) {
1406 req
->sconn
->smb2
.compound_related_in_progress
= true;
1410 case SMB2_OP_NEGPROT
:
1411 /* This call needs to be run as root */
1412 change_to_root_user();
1415 START_PROFILE(smb2_negprot
);
1416 return_value
= smbd_smb2_request_process_negprot(req
);
1417 END_PROFILE(smb2_negprot
);
1421 case SMB2_OP_SESSSETUP
:
1422 /* This call needs to be run as root */
1423 change_to_root_user();
1426 START_PROFILE(smb2_sesssetup
);
1427 return_value
= smbd_smb2_request_process_sesssetup(req
);
1428 END_PROFILE(smb2_sesssetup
);
1432 case SMB2_OP_LOGOFF
:
1433 if (!NT_STATUS_IS_OK(session_status
)) {
1434 return_value
= smbd_smb2_request_error(req
, session_status
);
1438 /* This call needs to be run as root */
1439 change_to_root_user();
1442 START_PROFILE(smb2_logoff
);
1443 return_value
= smbd_smb2_request_process_logoff(req
);
1444 END_PROFILE(smb2_logoff
);
1449 if (!NT_STATUS_IS_OK(session_status
)) {
1450 return_value
= smbd_smb2_request_error(req
, session_status
);
1455 * This call needs to be run as root.
1457 * smbd_smb2_request_process_tcon()
1458 * calls make_connection_snum(), which will call
1459 * change_to_user(), when needed.
1461 change_to_root_user();
1464 START_PROFILE(smb2_tcon
);
1465 return_value
= smbd_smb2_request_process_tcon(req
);
1466 END_PROFILE(smb2_tcon
);
1471 if (!NT_STATUS_IS_OK(session_status
)) {
1472 return_value
= smbd_smb2_request_error(req
, session_status
);
1476 * This call needs to be run as user.
1478 * smbd_smb2_request_check_tcon()
1479 * calls change_to_user() on success.
1481 status
= smbd_smb2_request_check_tcon(req
);
1482 if (!NT_STATUS_IS_OK(status
)) {
1483 return_value
= smbd_smb2_request_error(req
, status
);
1486 /* This call needs to be run as root */
1487 change_to_root_user();
1491 START_PROFILE(smb2_tdis
);
1492 return_value
= smbd_smb2_request_process_tdis(req
);
1493 END_PROFILE(smb2_tdis
);
1497 case SMB2_OP_CREATE
:
1498 if (!NT_STATUS_IS_OK(session_status
)) {
1499 return_value
= smbd_smb2_request_error(req
, session_status
);
1503 * This call needs to be run as user.
1505 * smbd_smb2_request_check_tcon()
1506 * calls change_to_user() on success.
1508 status
= smbd_smb2_request_check_tcon(req
);
1509 if (!NT_STATUS_IS_OK(status
)) {
1510 return_value
= smbd_smb2_request_error(req
, status
);
1515 START_PROFILE(smb2_create
);
1516 return_value
= smbd_smb2_request_process_create(req
);
1517 END_PROFILE(smb2_create
);
1522 if (!NT_STATUS_IS_OK(session_status
)) {
1523 return_value
= smbd_smb2_request_error(req
, session_status
);
1527 * This call needs to be run as user.
1529 * smbd_smb2_request_check_tcon()
1530 * calls change_to_user() on success.
1532 status
= smbd_smb2_request_check_tcon(req
);
1533 if (!NT_STATUS_IS_OK(status
)) {
1534 return_value
= smbd_smb2_request_error(req
, status
);
1539 START_PROFILE(smb2_close
);
1540 return_value
= smbd_smb2_request_process_close(req
);
1541 END_PROFILE(smb2_close
);
1546 if (!NT_STATUS_IS_OK(session_status
)) {
1547 return_value
= smbd_smb2_request_error(req
, session_status
);
1551 * This call needs to be run as user.
1553 * smbd_smb2_request_check_tcon()
1554 * calls change_to_user() on success.
1556 status
= smbd_smb2_request_check_tcon(req
);
1557 if (!NT_STATUS_IS_OK(status
)) {
1558 return_value
= smbd_smb2_request_error(req
, status
);
1563 START_PROFILE(smb2_flush
);
1564 return_value
= smbd_smb2_request_process_flush(req
);
1565 END_PROFILE(smb2_flush
);
1570 if (!NT_STATUS_IS_OK(session_status
)) {
1571 return_value
= smbd_smb2_request_error(req
, session_status
);
1575 * This call needs to be run as user.
1577 * smbd_smb2_request_check_tcon()
1578 * calls change_to_user() on success.
1580 status
= smbd_smb2_request_check_tcon(req
);
1581 if (!NT_STATUS_IS_OK(status
)) {
1582 return_value
= smbd_smb2_request_error(req
, status
);
1587 START_PROFILE(smb2_read
);
1588 return_value
= smbd_smb2_request_process_read(req
);
1589 END_PROFILE(smb2_read
);
1594 if (!NT_STATUS_IS_OK(session_status
)) {
1595 return_value
= smbd_smb2_request_error(req
, session_status
);
1599 * This call needs to be run as user.
1601 * smbd_smb2_request_check_tcon()
1602 * calls change_to_user() on success.
1604 status
= smbd_smb2_request_check_tcon(req
);
1605 if (!NT_STATUS_IS_OK(status
)) {
1606 return_value
= smbd_smb2_request_error(req
, status
);
1611 START_PROFILE(smb2_write
);
1612 return_value
= smbd_smb2_request_process_write(req
);
1613 END_PROFILE(smb2_write
);
1618 if (!NT_STATUS_IS_OK(session_status
)) {
1619 /* Too ugly to live ? JRA. */
1620 if (NT_STATUS_EQUAL(session_status
,NT_STATUS_USER_SESSION_DELETED
)) {
1621 session_status
= NT_STATUS_FILE_CLOSED
;
1623 return_value
= smbd_smb2_request_error(req
, session_status
);
1627 * This call needs to be run as user.
1629 * smbd_smb2_request_check_tcon()
1630 * calls change_to_user() on success.
1632 status
= smbd_smb2_request_check_tcon(req
);
1633 if (!NT_STATUS_IS_OK(status
)) {
1634 /* Too ugly to live ? JRA. */
1635 if (NT_STATUS_EQUAL(status
,NT_STATUS_NETWORK_NAME_DELETED
)) {
1636 status
= NT_STATUS_FILE_CLOSED
;
1638 return_value
= smbd_smb2_request_error(req
, status
);
1643 START_PROFILE(smb2_lock
);
1644 return_value
= smbd_smb2_request_process_lock(req
);
1645 END_PROFILE(smb2_lock
);
1650 if (!NT_STATUS_IS_OK(session_status
)) {
1651 return_value
= smbd_smb2_request_error(req
, session_status
);
1655 * This call needs to be run as user.
1657 * smbd_smb2_request_check_tcon()
1658 * calls change_to_user() on success.
1660 status
= smbd_smb2_request_check_tcon(req
);
1661 if (!NT_STATUS_IS_OK(status
)) {
1662 return_value
= smbd_smb2_request_error(req
, status
);
1667 START_PROFILE(smb2_ioctl
);
1668 return_value
= smbd_smb2_request_process_ioctl(req
);
1669 END_PROFILE(smb2_ioctl
);
1673 case SMB2_OP_CANCEL
:
1675 * This call needs to be run as root
1677 * That is what we also do in the SMB1 case.
1679 change_to_root_user();
1682 START_PROFILE(smb2_cancel
);
1683 return_value
= smbd_smb2_request_process_cancel(req
);
1684 END_PROFILE(smb2_cancel
);
1688 case SMB2_OP_KEEPALIVE
:
1689 /* This call needs to be run as root */
1690 change_to_root_user();
1693 START_PROFILE(smb2_keepalive
);
1694 return_value
= smbd_smb2_request_process_keepalive(req
);
1695 END_PROFILE(smb2_keepalive
);
1700 if (!NT_STATUS_IS_OK(session_status
)) {
1701 return_value
= smbd_smb2_request_error(req
, session_status
);
1705 * This call needs to be run as user.
1707 * smbd_smb2_request_check_tcon()
1708 * calls change_to_user() on success.
1710 status
= smbd_smb2_request_check_tcon(req
);
1711 if (!NT_STATUS_IS_OK(status
)) {
1712 return_value
= smbd_smb2_request_error(req
, status
);
1717 START_PROFILE(smb2_find
);
1718 return_value
= smbd_smb2_request_process_find(req
);
1719 END_PROFILE(smb2_find
);
1723 case SMB2_OP_NOTIFY
:
1724 if (!NT_STATUS_IS_OK(session_status
)) {
1725 return_value
= smbd_smb2_request_error(req
, session_status
);
1729 * This call needs to be run as user.
1731 * smbd_smb2_request_check_tcon()
1732 * calls change_to_user() on success.
1734 status
= smbd_smb2_request_check_tcon(req
);
1735 if (!NT_STATUS_IS_OK(status
)) {
1736 return_value
= smbd_smb2_request_error(req
, status
);
1741 START_PROFILE(smb2_notify
);
1742 return_value
= smbd_smb2_request_process_notify(req
);
1743 END_PROFILE(smb2_notify
);
1747 case SMB2_OP_GETINFO
:
1748 if (!NT_STATUS_IS_OK(session_status
)) {
1749 return_value
= smbd_smb2_request_error(req
, session_status
);
1753 * This call needs to be run as user.
1755 * smbd_smb2_request_check_tcon()
1756 * calls change_to_user() on success.
1758 status
= smbd_smb2_request_check_tcon(req
);
1759 if (!NT_STATUS_IS_OK(status
)) {
1760 return_value
= smbd_smb2_request_error(req
, status
);
1765 START_PROFILE(smb2_getinfo
);
1766 return_value
= smbd_smb2_request_process_getinfo(req
);
1767 END_PROFILE(smb2_getinfo
);
1771 case SMB2_OP_SETINFO
:
1772 if (!NT_STATUS_IS_OK(session_status
)) {
1773 return_value
= smbd_smb2_request_error(req
, session_status
);
1777 * This call needs to be run as user.
1779 * smbd_smb2_request_check_tcon()
1780 * calls change_to_user() on success.
1782 status
= smbd_smb2_request_check_tcon(req
);
1783 if (!NT_STATUS_IS_OK(status
)) {
1784 return_value
= smbd_smb2_request_error(req
, status
);
1789 START_PROFILE(smb2_setinfo
);
1790 return_value
= smbd_smb2_request_process_setinfo(req
);
1791 END_PROFILE(smb2_setinfo
);
1796 if (!NT_STATUS_IS_OK(session_status
)) {
1797 return_value
= smbd_smb2_request_error(req
, session_status
);
1801 * This call needs to be run as user.
1803 * smbd_smb2_request_check_tcon()
1804 * calls change_to_user() on success.
1806 status
= smbd_smb2_request_check_tcon(req
);
1807 if (!NT_STATUS_IS_OK(status
)) {
1808 return_value
= smbd_smb2_request_error(req
, status
);
1813 START_PROFILE(smb2_break
);
1814 return_value
= smbd_smb2_request_process_break(req
);
1815 END_PROFILE(smb2_break
);
1820 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1823 return return_value
;
1826 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
1828 struct tevent_req
*subreq
;
1829 int i
= req
->current_idx
;
1833 req
->current_idx
+= 3;
1835 if (req
->current_idx
< req
->out
.vector_count
) {
1837 * We must process the remaining compound
1838 * SMB2 requests before any new incoming SMB2
1839 * requests. This is because incoming SMB2
1840 * requests may include a cancel for a
1841 * compound request we haven't processed
1844 struct tevent_immediate
*im
= tevent_create_immediate(req
);
1846 return NT_STATUS_NO_MEMORY
;
1848 tevent_schedule_immediate(im
,
1849 req
->sconn
->smb2
.event_ctx
,
1850 smbd_smb2_request_dispatch_immediate
,
1852 return NT_STATUS_OK
;
1855 if (req
->compound_related
) {
1856 req
->sconn
->smb2
.compound_related_in_progress
= false;
1859 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
1861 /* Set credit for these operations (zero credits if this
1862 is a final reply for an async operation). */
1863 smb2_calculate_credits(req
, req
);
1865 if (req
->do_signing
) {
1867 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
1868 &req
->out
.vector
[i
], 3);
1869 if (!NT_STATUS_IS_OK(status
)) {
1874 if (DEBUGLEVEL
>= 10) {
1875 dbgtext("smbd_smb2_request_reply: sending...\n");
1876 print_req_vectors(req
);
1879 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1880 if (req
->out
.vector_count
== 4 &&
1881 req
->out
.vector
[3].iov_base
== NULL
&&
1882 req
->out
.vector
[3].iov_len
!= 0) {
1883 /* Dynamic part is NULL. Chop it off,
1884 We're going to send it via sendfile. */
1885 req
->out
.vector_count
-= 1;
1888 subreq
= tstream_writev_queue_send(req
,
1889 req
->sconn
->smb2
.event_ctx
,
1890 req
->sconn
->smb2
.stream
,
1891 req
->sconn
->smb2
.send_queue
,
1893 req
->out
.vector_count
);
1894 if (subreq
== NULL
) {
1895 return NT_STATUS_NO_MEMORY
;
1897 tevent_req_set_callback(subreq
, smbd_smb2_request_writev_done
, req
);
1899 * We're done with this request -
1900 * move it off the "being processed" queue.
1902 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1904 return NT_STATUS_OK
;
1907 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
);
1909 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
1910 struct tevent_immediate
*im
,
1913 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
1914 struct smbd_smb2_request
);
1915 struct smbd_server_connection
*sconn
= req
->sconn
;
1920 if (DEBUGLEVEL
>= 10) {
1921 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1922 req
->current_idx
, req
->in
.vector_count
));
1923 print_req_vectors(req
);
1926 status
= smbd_smb2_request_dispatch(req
);
1927 if (!NT_STATUS_IS_OK(status
)) {
1928 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1932 status
= smbd_smb2_request_next_incoming(sconn
);
1933 if (!NT_STATUS_IS_OK(status
)) {
1934 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1939 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
)
1941 struct smbd_smb2_request
*req
= tevent_req_callback_data(subreq
,
1942 struct smbd_smb2_request
);
1943 struct smbd_server_connection
*sconn
= req
->sconn
;
1948 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1949 TALLOC_FREE(subreq
);
1952 status
= map_nt_error_from_unix(sys_errno
);
1953 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1954 nt_errstr(status
)));
1955 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1959 status
= smbd_smb2_request_next_incoming(sconn
);
1960 if (!NT_STATUS_IS_OK(status
)) {
1961 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1966 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
1968 DATA_BLOB body
, DATA_BLOB
*dyn
,
1969 const char *location
)
1972 int i
= req
->current_idx
;
1973 uint32_t next_command_ofs
;
1975 DEBUG(10,("smbd_smb2_request_done_ex: "
1976 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1977 i
, nt_errstr(status
), (unsigned int)body
.length
,
1979 (unsigned int)(dyn
? dyn
->length
: 0),
1982 if (body
.length
< 2) {
1983 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
1986 if ((body
.length
% 2) != 0) {
1987 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
1990 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
1992 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
1993 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
1995 req
->out
.vector
[i
+1].iov_base
= (void *)body
.data
;
1996 req
->out
.vector
[i
+1].iov_len
= body
.length
;
1999 req
->out
.vector
[i
+2].iov_base
= (void *)dyn
->data
;
2000 req
->out
.vector
[i
+2].iov_len
= dyn
->length
;
2002 req
->out
.vector
[i
+2].iov_base
= NULL
;
2003 req
->out
.vector
[i
+2].iov_len
= 0;
2006 /* see if we need to recalculate the offset to the next response */
2007 if (next_command_ofs
> 0) {
2008 next_command_ofs
= SMB2_HDR_BODY
;
2009 next_command_ofs
+= req
->out
.vector
[i
+1].iov_len
;
2010 next_command_ofs
+= req
->out
.vector
[i
+2].iov_len
;
2013 if ((next_command_ofs
% 8) != 0) {
2014 size_t pad_size
= 8 - (next_command_ofs
% 8);
2015 if (req
->out
.vector
[i
+2].iov_len
== 0) {
2017 * if the dyn buffer is empty
2018 * we can use it to add padding
2022 pad
= talloc_zero_array(req
->out
.vector
,
2025 return smbd_smb2_request_error(req
,
2026 NT_STATUS_NO_MEMORY
);
2029 req
->out
.vector
[i
+2].iov_base
= (void *)pad
;
2030 req
->out
.vector
[i
+2].iov_len
= pad_size
;
2033 * For now we copy the dynamic buffer
2034 * and add the padding to the new buffer
2041 old_size
= req
->out
.vector
[i
+2].iov_len
;
2042 old_dyn
= (uint8_t *)req
->out
.vector
[i
+2].iov_base
;
2044 new_size
= old_size
+ pad_size
;
2045 new_dyn
= talloc_zero_array(req
->out
.vector
,
2047 if (new_dyn
== NULL
) {
2048 return smbd_smb2_request_error(req
,
2049 NT_STATUS_NO_MEMORY
);
2052 memcpy(new_dyn
, old_dyn
, old_size
);
2053 memset(new_dyn
+ old_size
, 0, pad_size
);
2055 req
->out
.vector
[i
+2].iov_base
= (void *)new_dyn
;
2056 req
->out
.vector
[i
+2].iov_len
= new_size
;
2058 next_command_ofs
+= pad_size
;
2061 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
2063 return smbd_smb2_request_reply(req
);
2066 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
2069 const char *location
)
2072 int i
= req
->current_idx
;
2073 uint8_t *outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
2075 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2076 i
, nt_errstr(status
), info
? " +info" : "",
2079 body
.data
= outhdr
+ SMB2_HDR_BODY
;
2081 SSVAL(body
.data
, 0, 9);
2084 SIVAL(body
.data
, 0x04, info
->length
);
2086 /* Allocated size of req->out.vector[i].iov_base
2087 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2088 * 1 byte without having to do an alloc.
2090 info
= talloc_zero_array(req
->out
.vector
,
2094 return NT_STATUS_NO_MEMORY
;
2096 info
->data
= ((uint8_t *)outhdr
) +
2097 OUTVEC_ALLOC_SIZE
- 1;
2099 SCVAL(info
->data
, 0, 0);
2103 * if a request fails, all other remaining
2104 * compounded requests should fail too
2106 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
2108 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
2112 struct smbd_smb2_send_oplock_break_state
{
2113 struct smbd_server_connection
*sconn
;
2114 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x18];
2115 struct iovec vector
;
2118 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
);
2120 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
2121 uint64_t file_id_persistent
,
2122 uint64_t file_id_volatile
,
2123 uint8_t oplock_level
)
2125 struct smbd_smb2_send_oplock_break_state
*state
;
2126 struct tevent_req
*subreq
;
2130 state
= talloc(sconn
, struct smbd_smb2_send_oplock_break_state
);
2131 if (state
== NULL
) {
2132 return NT_STATUS_NO_MEMORY
;
2134 state
->sconn
= sconn
;
2136 state
->vector
.iov_base
= (void *)state
->buf
;
2137 state
->vector
.iov_len
= sizeof(state
->buf
);
2139 _smb2_setlen(state
->buf
, sizeof(state
->buf
) - 4);
2140 hdr
= state
->buf
+ 4;
2141 body
= hdr
+ SMB2_HDR_BODY
;
2143 SIVAL(hdr
, 0, SMB2_MAGIC
);
2144 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
2145 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
2146 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
2147 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
2148 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
2149 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
2150 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
2151 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
2152 SIVAL(hdr
, SMB2_HDR_PID
, 0);
2153 SIVAL(hdr
, SMB2_HDR_TID
, 0);
2154 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
2155 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
2157 SSVAL(body
, 0x00, 0x18);
2159 SCVAL(body
, 0x02, oplock_level
);
2160 SCVAL(body
, 0x03, 0); /* reserved */
2161 SIVAL(body
, 0x04, 0); /* reserved */
2162 SBVAL(body
, 0x08, file_id_persistent
);
2163 SBVAL(body
, 0x10, file_id_volatile
);
2165 subreq
= tstream_writev_queue_send(state
,
2166 sconn
->smb2
.event_ctx
,
2168 sconn
->smb2
.send_queue
,
2170 if (subreq
== NULL
) {
2171 return NT_STATUS_NO_MEMORY
;
2173 tevent_req_set_callback(subreq
,
2174 smbd_smb2_oplock_break_writev_done
,
2177 return NT_STATUS_OK
;
2180 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
)
2182 struct smbd_smb2_send_oplock_break_state
*state
=
2183 tevent_req_callback_data(subreq
,
2184 struct smbd_smb2_send_oplock_break_state
);
2185 struct smbd_server_connection
*sconn
= state
->sconn
;
2189 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
2190 TALLOC_FREE(subreq
);
2192 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
2193 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2200 struct smbd_smb2_request_read_state
{
2202 bool asked_for_header
;
2203 struct smbd_smb2_request
*smb2_req
;
2206 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2208 TALLOC_CTX
*mem_ctx
,
2209 struct iovec
**_vector
,
2211 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
);
2213 static struct tevent_req
*smbd_smb2_request_read_send(TALLOC_CTX
*mem_ctx
,
2214 struct tevent_context
*ev
,
2215 struct smbd_server_connection
*sconn
)
2217 struct tevent_req
*req
;
2218 struct smbd_smb2_request_read_state
*state
;
2219 struct tevent_req
*subreq
;
2221 req
= tevent_req_create(mem_ctx
, &state
,
2222 struct smbd_smb2_request_read_state
);
2227 state
->asked_for_header
= false;
2229 state
->smb2_req
= smbd_smb2_request_allocate(state
);
2230 if (tevent_req_nomem(state
->smb2_req
, req
)) {
2231 return tevent_req_post(req
, ev
);
2233 state
->smb2_req
->sconn
= sconn
;
2235 subreq
= tstream_readv_pdu_queue_send(state
, ev
, sconn
->smb2
.stream
,
2236 sconn
->smb2
.recv_queue
,
2237 smbd_smb2_request_next_vector
,
2239 if (tevent_req_nomem(subreq
, req
)) {
2240 return tevent_req_post(req
, ev
);
2242 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
2247 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2249 TALLOC_CTX
*mem_ctx
,
2250 struct iovec
**_vector
,
2253 struct smbd_smb2_request_read_state
*state
=
2254 talloc_get_type_abort(private_data
,
2255 struct smbd_smb2_request_read_state
);
2256 struct smbd_smb2_request
*req
= state
->smb2_req
;
2257 struct iovec
*vector
;
2258 int idx
= req
->in
.vector_count
;
2260 uint8_t *buf
= NULL
;
2262 if (req
->in
.vector_count
== 0) {
2264 * first we need to get the NBT header
2266 req
->in
.vector
= talloc_array(req
, struct iovec
,
2267 req
->in
.vector_count
+ 1);
2268 if (req
->in
.vector
== NULL
) {
2271 req
->in
.vector_count
+= 1;
2273 req
->in
.vector
[idx
].iov_base
= (void *)req
->in
.nbt_hdr
;
2274 req
->in
.vector
[idx
].iov_len
= 4;
2276 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2277 if (vector
== NULL
) {
2281 vector
[0] = req
->in
.vector
[idx
];
2288 if (req
->in
.vector_count
== 1) {
2290 * Now we analyze the NBT header
2292 state
->missing
= smb2_len(req
->in
.vector
[0].iov_base
);
2294 if (state
->missing
== 0) {
2295 /* if there're no remaining bytes, we're done */
2301 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2303 req
->in
.vector_count
+ 1);
2304 if (req
->in
.vector
== NULL
) {
2307 req
->in
.vector_count
+= 1;
2309 if (CVAL(req
->in
.vector
[0].iov_base
, 0) != 0) {
2311 * it's a special NBT message,
2312 * so get all remaining bytes
2314 len
= state
->missing
;
2315 } else if (state
->missing
< (SMB2_HDR_BODY
+ 2)) {
2317 * it's an invalid message, just read what we can get
2318 * and let the caller handle the error
2320 len
= state
->missing
;
2323 * We assume it's a SMB2 request,
2324 * and we first get the header and the
2325 * first 2 bytes (the struct size) of the body
2327 len
= SMB2_HDR_BODY
+ 2;
2329 state
->asked_for_header
= true;
2332 state
->missing
-= len
;
2334 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2339 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2340 req
->in
.vector
[idx
].iov_len
= len
;
2342 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2343 if (vector
== NULL
) {
2347 vector
[0] = req
->in
.vector
[idx
];
2354 if (state
->missing
== 0) {
2355 /* if there're no remaining bytes, we're done */
2361 if (state
->asked_for_header
) {
2364 size_t next_command_ofs
;
2369 bool invalid
= false;
2371 state
->asked_for_header
= false;
2374 * We got the SMB2 header and the first 2 bytes
2375 * of the body. We fix the size to just the header
2376 * and manually copy the 2 first bytes to the body section
2378 req
->in
.vector
[idx
-1].iov_len
= SMB2_HDR_BODY
;
2379 hdr
= (const uint8_t *)req
->in
.vector
[idx
-1].iov_base
;
2381 /* allocate vectors for body and dynamic areas */
2382 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2384 req
->in
.vector_count
+ 2);
2385 if (req
->in
.vector
== NULL
) {
2388 req
->in
.vector_count
+= 2;
2390 full_size
= state
->missing
+ SMB2_HDR_BODY
+ 2;
2391 next_command_ofs
= IVAL(hdr
, SMB2_HDR_NEXT_COMMAND
);
2392 body_size
= SVAL(hdr
, SMB2_HDR_BODY
);
2394 if (next_command_ofs
!= 0) {
2395 if (next_command_ofs
< (SMB2_HDR_BODY
+ 2)) {
2397 * this is invalid, just return a zero
2398 * body and let the caller deal with the error
2401 } else if (next_command_ofs
> full_size
) {
2403 * this is invalid, just return a zero
2404 * body and let the caller deal with the error
2408 full_size
= next_command_ofs
;
2413 if (body_size
< 2) {
2415 * this is invalid, just return a zero
2416 * body and let the caller deal with the error
2421 if ((body_size
% 2) != 0) {
2425 if (body_size
> (full_size
- SMB2_HDR_BODY
)) {
2427 * this is invalid, just return a zero
2428 * body and let the caller deal with the error
2435 /* the caller should check this */
2439 dyn_size
= full_size
- (SMB2_HDR_BODY
+ body_size
);
2441 state
->missing
-= (body_size
- 2) + dyn_size
;
2443 body
= talloc_array(req
->in
.vector
, uint8_t, body_size
);
2448 dyn
= talloc_array(req
->in
.vector
, uint8_t, dyn_size
);
2453 req
->in
.vector
[idx
].iov_base
= (void *)body
;
2454 req
->in
.vector
[idx
].iov_len
= body_size
;
2455 req
->in
.vector
[idx
+1].iov_base
= (void *)dyn
;
2456 req
->in
.vector
[idx
+1].iov_len
= dyn_size
;
2458 vector
= talloc_array(mem_ctx
, struct iovec
, 2);
2459 if (vector
== NULL
) {
2464 * the first 2 bytes of the body were already fetched
2465 * together with the header
2467 memcpy(body
, hdr
+ SMB2_HDR_BODY
, 2);
2468 vector
[0].iov_base
= body
+ 2;
2469 vector
[0].iov_len
= body_size
- 2;
2471 vector
[1] = req
->in
.vector
[idx
+1];
2479 * when we endup here, we're looking for a new SMB2 request
2480 * next. And we ask for its header and the first 2 bytes of
2481 * the body (like we did for the first SMB2 request).
2484 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2486 req
->in
.vector_count
+ 1);
2487 if (req
->in
.vector
== NULL
) {
2490 req
->in
.vector_count
+= 1;
2493 * We assume it's a SMB2 request,
2494 * and we first get the header and the
2495 * first 2 bytes (the struct size) of the body
2497 len
= SMB2_HDR_BODY
+ 2;
2499 if (len
> state
->missing
) {
2500 /* let the caller handle the error */
2501 len
= state
->missing
;
2504 state
->missing
-= len
;
2505 state
->asked_for_header
= true;
2507 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2512 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2513 req
->in
.vector
[idx
].iov_len
= len
;
2515 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2516 if (vector
== NULL
) {
2520 vector
[0] = req
->in
.vector
[idx
];
2527 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
)
2529 struct tevent_req
*req
=
2530 tevent_req_callback_data(subreq
,
2536 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
2538 status
= map_nt_error_from_unix(sys_errno
);
2539 tevent_req_nterror(req
, status
);
2543 tevent_req_done(req
);
2546 static NTSTATUS
smbd_smb2_request_read_recv(struct tevent_req
*req
,
2547 TALLOC_CTX
*mem_ctx
,
2548 struct smbd_smb2_request
**_smb2_req
)
2550 struct smbd_smb2_request_read_state
*state
=
2551 tevent_req_data(req
,
2552 struct smbd_smb2_request_read_state
);
2555 if (tevent_req_is_nterror(req
, &status
)) {
2556 tevent_req_received(req
);
2560 talloc_steal(mem_ctx
, state
->smb2_req
->mem_pool
);
2561 *_smb2_req
= state
->smb2_req
;
2562 tevent_req_received(req
);
2563 return NT_STATUS_OK
;
2566 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
);
2568 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
)
2570 size_t max_send_queue_len
;
2571 size_t cur_send_queue_len
;
2572 struct tevent_req
*subreq
;
2574 if (sconn
->smb2
.compound_related_in_progress
) {
2576 * Can't read another until the related
2579 return NT_STATUS_OK
;
2582 if (tevent_queue_length(sconn
->smb2
.recv_queue
) > 0) {
2584 * if there is already a smbd_smb2_request_read
2585 * pending, we are done.
2587 return NT_STATUS_OK
;
2590 max_send_queue_len
= MAX(1, sconn
->smb2
.max_credits
/16);
2591 cur_send_queue_len
= tevent_queue_length(sconn
->smb2
.send_queue
);
2593 if (cur_send_queue_len
> max_send_queue_len
) {
2595 * if we have a lot of requests to send,
2596 * we wait until they are on the wire until we
2597 * ask for the next request.
2599 return NT_STATUS_OK
;
2602 /* ask for the next request */
2603 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->smb2
.event_ctx
, sconn
);
2604 if (subreq
== NULL
) {
2605 return NT_STATUS_NO_MEMORY
;
2607 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);
2609 return NT_STATUS_OK
;
2612 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
2613 const uint8_t *inbuf
, size_t size
)
2616 struct smbd_smb2_request
*req
= NULL
;
2618 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2619 (unsigned int)size
));
2621 status
= smbd_initialize_smb2(sconn
);
2622 if (!NT_STATUS_IS_OK(status
)) {
2623 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2627 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
2628 if (!NT_STATUS_IS_OK(status
)) {
2629 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2633 status
= smbd_smb2_request_validate(req
);
2634 if (!NT_STATUS_IS_OK(status
)) {
2635 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2639 status
= smbd_smb2_request_setup_out(req
);
2640 if (!NT_STATUS_IS_OK(status
)) {
2641 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2645 status
= smbd_smb2_request_dispatch(req
);
2646 if (!NT_STATUS_IS_OK(status
)) {
2647 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2651 status
= smbd_smb2_request_next_incoming(sconn
);
2652 if (!NT_STATUS_IS_OK(status
)) {
2653 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2657 sconn
->num_requests
++;
2660 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
)
2662 struct smbd_server_connection
*sconn
= tevent_req_callback_data(subreq
,
2663 struct smbd_server_connection
);
2665 struct smbd_smb2_request
*req
= NULL
;
2667 status
= smbd_smb2_request_read_recv(subreq
, sconn
, &req
);
2668 TALLOC_FREE(subreq
);
2669 if (!NT_STATUS_IS_OK(status
)) {
2670 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2671 nt_errstr(status
)));
2672 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2676 if (req
->in
.nbt_hdr
[0] != 0x00) {
2677 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2678 req
->in
.nbt_hdr
[0]));
2683 req
->current_idx
= 1;
2685 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2686 req
->current_idx
, req
->in
.vector_count
));
2688 status
= smbd_smb2_request_validate(req
);
2689 if (!NT_STATUS_IS_OK(status
)) {
2690 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2694 status
= smbd_smb2_request_setup_out(req
);
2695 if (!NT_STATUS_IS_OK(status
)) {
2696 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2700 status
= smbd_smb2_request_dispatch(req
);
2701 if (!NT_STATUS_IS_OK(status
)) {
2702 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2707 status
= smbd_smb2_request_next_incoming(sconn
);
2708 if (!NT_STATUS_IS_OK(status
)) {
2709 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2713 sconn
->num_requests
++;
2715 /* The timeout_processing function isn't run nearly
2716 often enough to implement 'max log size' without
2717 overrunning the size of the file by many megabytes.
2718 This is especially true if we are running at debug
2719 level 10. Checking every 50 SMB2s is a nice
2720 tradeoff of performance vs log file size overrun. */
2722 if ((sconn
->num_requests
% 50) == 0 &&
2723 need_to_check_log_size()) {
2724 change_to_root_user();