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
;
430 if (req
->in
.vector
[idx
].iov_len
!= SMB2_HDR_BODY
) {
431 return NT_STATUS_INVALID_PARAMETER
;
434 if (req
->in
.vector
[idx
+1].iov_len
< 2) {
435 return NT_STATUS_INVALID_PARAMETER
;
438 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
440 /* Check the SMB2 header */
441 if (IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
) != SMB2_MAGIC
) {
442 return NT_STATUS_INVALID_PARAMETER
;
445 if (!smb2_validate_message_id(req
->sconn
, inhdr
)) {
446 return NT_STATUS_INVALID_PARAMETER
;
453 static void smb2_set_operation_credit(struct smbd_server_connection
*sconn
,
454 const struct iovec
*in_vector
,
455 struct iovec
*out_vector
)
457 const uint8_t *inhdr
= (const uint8_t *)in_vector
->iov_base
;
458 uint8_t *outhdr
= (uint8_t *)out_vector
->iov_base
;
459 uint16_t credits_requested
;
463 uint16_t credits_granted
= 0;
464 uint64_t credits_possible
;
465 uint16_t current_max_credits
;
468 * first we grant only 1/16th of the max range.
470 * Windows also starts with the 1/16th and then grants
471 * more later. I was only able to trigger higher
472 * values, when using a verify high credit charge.
474 * TODO: scale up depending one load, free memory
476 * Maybe also on the relationship between number
477 * of requests and the used sequence number.
478 * Which means we would grant more credits
479 * for client which use multi credit requests.
481 current_max_credits
= sconn
->smb2
.max_credits
/ 16;
482 current_max_credits
= MAX(current_max_credits
, 1);
484 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
485 credits_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
486 out_flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
487 out_status
= NT_STATUS(IVAL(outhdr
, SMB2_HDR_STATUS
));
489 SMB_ASSERT(sconn
->smb2
.max_credits
>= sconn
->smb2
.credits_granted
);
491 if (out_flags
& SMB2_HDR_FLAG_ASYNC
) {
493 * In case we already send an async interim
494 * response, we should not grant
495 * credits on the final response.
498 } else if (credits_requested
> 0) {
499 uint16_t additional_max
= 0;
500 uint16_t additional_credits
= credits_requested
- 1;
503 case SMB2_OP_NEGPROT
:
505 case SMB2_OP_SESSSETUP
:
507 * Windows 2012 RC1 starts to grant
509 * with a successful session setup
511 if (NT_STATUS_IS_OK(out_status
)) {
517 * We match windows and only grant additional credits
524 additional_credits
= MIN(additional_credits
, additional_max
);
526 credits_granted
= 1 + additional_credits
;
527 } else if (sconn
->smb2
.credits_granted
== 0) {
529 * Make sure the client has always at least one credit
535 * sequence numbers should not wrap
537 * 1. calculate the possible credits until
538 * the sequence numbers start to wrap on 64-bit.
540 * 2. UINT64_MAX is used for Break Notifications.
542 * 2. truncate the possible credits to the maximum
543 * credits we want to grant to the client in total.
545 * 3. remove the range we'll already granted to the client
546 * this makes sure the client consumes the lowest sequence
547 * number, before we can grant additional credits.
549 credits_possible
= UINT64_MAX
- sconn
->smb2
.seqnum_low
;
550 if (credits_possible
> 0) {
551 /* remove UINT64_MAX */
552 credits_possible
-= 1;
554 credits_possible
= MIN(credits_possible
, current_max_credits
);
555 credits_possible
-= sconn
->smb2
.seqnum_range
;
557 credits_granted
= MIN(credits_granted
, credits_possible
);
559 SSVAL(outhdr
, SMB2_HDR_CREDIT
, credits_granted
);
560 sconn
->smb2
.credits_granted
+= credits_granted
;
561 sconn
->smb2
.seqnum_range
+= credits_granted
;
563 DEBUG(10,("smb2_set_operation_credit: requested %u, "
564 "granted %u, current possible/max %u/%u, "
565 "total granted/max/low/range %u/%u/%llu/%u\n",
566 (unsigned int)credits_requested
,
567 (unsigned int)credits_granted
,
568 (unsigned int)credits_possible
,
569 (unsigned int)current_max_credits
,
570 (unsigned int)sconn
->smb2
.credits_granted
,
571 (unsigned int)sconn
->smb2
.max_credits
,
572 (unsigned long long)sconn
->smb2
.seqnum_low
,
573 (unsigned int)sconn
->smb2
.seqnum_range
));
576 static void smb2_calculate_credits(const struct smbd_smb2_request
*inreq
,
577 struct smbd_smb2_request
*outreq
)
580 uint16_t total_credits
= 0;
582 count
= outreq
->out
.vector_count
;
584 for (idx
=1; idx
< count
; idx
+= 3) {
585 uint8_t *outhdr
= (uint8_t *)outreq
->out
.vector
[idx
].iov_base
;
586 smb2_set_operation_credit(outreq
->sconn
,
587 &inreq
->in
.vector
[idx
],
588 &outreq
->out
.vector
[idx
]);
589 /* To match Windows, count up what we
591 total_credits
+= SVAL(outhdr
, SMB2_HDR_CREDIT
);
592 /* Set to zero in all but the last reply. */
593 if (idx
+ 3 < count
) {
594 SSVAL(outhdr
, SMB2_HDR_CREDIT
, 0);
596 SSVAL(outhdr
, SMB2_HDR_CREDIT
, total_credits
);
601 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
)
603 struct iovec
*vector
;
607 count
= req
->in
.vector_count
;
608 vector
= talloc_zero_array(req
, struct iovec
, count
);
609 if (vector
== NULL
) {
610 return NT_STATUS_NO_MEMORY
;
613 vector
[0].iov_base
= req
->out
.nbt_hdr
;
614 vector
[0].iov_len
= 4;
615 SIVAL(req
->out
.nbt_hdr
, 0, 0);
617 for (idx
=1; idx
< count
; idx
+= 3) {
618 const uint8_t *inhdr
= NULL
;
620 uint8_t *outhdr
= NULL
;
621 uint8_t *outbody
= NULL
;
622 uint32_t next_command_ofs
= 0;
623 struct iovec
*current
= &vector
[idx
];
625 if ((idx
+ 3) < count
) {
626 /* we have a next command -
627 * setup for the error case. */
628 next_command_ofs
= SMB2_HDR_BODY
+ 9;
631 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
632 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
634 outhdr
= talloc_zero_array(vector
, uint8_t,
636 if (outhdr
== NULL
) {
637 return NT_STATUS_NO_MEMORY
;
640 outbody
= outhdr
+ SMB2_HDR_BODY
;
642 current
[0].iov_base
= (void *)outhdr
;
643 current
[0].iov_len
= SMB2_HDR_BODY
;
645 current
[1].iov_base
= (void *)outbody
;
646 current
[1].iov_len
= 8;
648 current
[2].iov_base
= NULL
;
649 current
[2].iov_len
= 0;
651 /* setup the SMB2 header */
652 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
653 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
654 SSVAL(outhdr
, SMB2_HDR_CREDIT_CHARGE
,
655 SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
));
656 SIVAL(outhdr
, SMB2_HDR_STATUS
,
657 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
658 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
659 SVAL(inhdr
, SMB2_HDR_OPCODE
));
660 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
661 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
662 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
663 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
664 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
665 SIVAL(outhdr
, SMB2_HDR_PID
,
666 IVAL(inhdr
, SMB2_HDR_PID
));
667 SIVAL(outhdr
, SMB2_HDR_TID
,
668 IVAL(inhdr
, SMB2_HDR_TID
));
669 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
670 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
671 memcpy(outhdr
+ SMB2_HDR_SIGNATURE
,
672 inhdr
+ SMB2_HDR_SIGNATURE
, 16);
674 /* setup error body header */
675 SSVAL(outbody
, 0x00, 0x08 + 1);
676 SSVAL(outbody
, 0x02, 0);
677 SIVAL(outbody
, 0x04, 0);
680 req
->out
.vector
= vector
;
681 req
->out
.vector_count
= count
;
683 /* setup the length of the NBT packet */
684 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
686 DLIST_ADD_END(req
->sconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
691 void smbd_server_connection_terminate_ex(struct smbd_server_connection
*sconn
,
693 const char *location
)
695 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
697 exit_server_cleanly(reason
);
700 static bool dup_smb2_vec3(TALLOC_CTX
*ctx
,
701 struct iovec
*outvec
,
702 const struct iovec
*srcvec
)
704 /* vec[0] is always boilerplate and must
705 * be allocated with size OUTVEC_ALLOC_SIZE. */
707 outvec
[0].iov_base
= talloc_memdup(ctx
,
710 if (!outvec
[0].iov_base
) {
713 outvec
[0].iov_len
= SMB2_HDR_BODY
;
716 * If this is a "standard" vec[1] of length 8,
717 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
718 * then duplicate this. Else use talloc_memdup().
721 if (srcvec
[1].iov_len
== 8 &&
722 srcvec
[1].iov_base
==
723 ((uint8_t *)srcvec
[0].iov_base
) +
725 outvec
[1].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
727 outvec
[1].iov_len
= 8;
729 outvec
[1].iov_base
= talloc_memdup(ctx
,
732 if (!outvec
[1].iov_base
) {
735 outvec
[1].iov_len
= srcvec
[1].iov_len
;
739 * If this is a "standard" vec[2] of length 1,
740 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
741 * then duplicate this. Else use talloc_memdup().
744 if (srcvec
[2].iov_base
&&
746 if (srcvec
[2].iov_base
==
747 ((uint8_t *)srcvec
[0].iov_base
) +
748 (OUTVEC_ALLOC_SIZE
- 1) &&
749 srcvec
[2].iov_len
== 1) {
750 /* Common SMB2 error packet case. */
751 outvec
[2].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
752 (OUTVEC_ALLOC_SIZE
- 1);
754 outvec
[2].iov_base
= talloc_memdup(ctx
,
757 if (!outvec
[2].iov_base
) {
761 outvec
[2].iov_len
= srcvec
[2].iov_len
;
763 outvec
[2].iov_base
= NULL
;
764 outvec
[2].iov_len
= 0;
769 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
771 struct smbd_smb2_request
*newreq
= NULL
;
772 struct iovec
*outvec
= NULL
;
773 int count
= req
->out
.vector_count
;
776 newreq
= smbd_smb2_request_allocate(req
->sconn
);
781 newreq
->sconn
= req
->sconn
;
782 newreq
->session
= req
->session
;
783 newreq
->do_signing
= req
->do_signing
;
784 newreq
->current_idx
= req
->current_idx
;
785 newreq
->async
= false;
786 newreq
->cancelled
= false;
787 /* Note we are leaving:
791 uninitialized as NULL here as
792 they're not used in the interim
793 response code. JRA. */
795 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
800 newreq
->out
.vector
= outvec
;
801 newreq
->out
.vector_count
= count
;
803 /* Setup the outvec's identically to req. */
804 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
805 outvec
[0].iov_len
= 4;
806 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
808 /* Setup the vectors identically to the ones in req. */
809 for (i
= 1; i
< count
; i
+= 3) {
810 if (!dup_smb2_vec3(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
821 smb2_setup_nbt_length(newreq
->out
.vector
,
822 newreq
->out
.vector_count
);
827 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
);
829 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
832 uint8_t *outhdr
= NULL
;
833 struct smbd_smb2_request
*nreq
= NULL
;
835 /* Create a new smb2 request we'll use
836 for the interim return. */
837 nreq
= dup_smb2_req(req
);
839 return NT_STATUS_NO_MEMORY
;
842 /* Lose the last 3 out vectors. They're the
843 ones we'll be using for the async reply. */
844 nreq
->out
.vector_count
-= 3;
846 smb2_setup_nbt_length(nreq
->out
.vector
,
847 nreq
->out
.vector_count
);
849 /* Step back to the previous reply. */
850 i
= nreq
->current_idx
- 3;
851 outhdr
= (uint8_t *)nreq
->out
.vector
[i
].iov_base
;
852 /* And end the chain. */
853 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
855 /* Calculate outgoing credits */
856 smb2_calculate_credits(req
, nreq
);
858 /* Re-sign if needed. */
859 if (nreq
->do_signing
) {
861 status
= smb2_signing_sign_pdu(nreq
->session
->session_key
,
862 &nreq
->out
.vector
[i
], 3);
863 if (!NT_STATUS_IS_OK(status
)) {
867 if (DEBUGLEVEL
>= 10) {
868 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
869 (unsigned int)nreq
->current_idx
);
870 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
871 (unsigned int)nreq
->out
.vector_count
);
872 print_req_vectors(nreq
);
874 nreq
->subreq
= tstream_writev_queue_send(nreq
,
875 nreq
->sconn
->smb2
.event_ctx
,
876 nreq
->sconn
->smb2
.stream
,
877 nreq
->sconn
->smb2
.send_queue
,
879 nreq
->out
.vector_count
);
881 if (nreq
->subreq
== NULL
) {
882 return NT_STATUS_NO_MEMORY
;
885 tevent_req_set_callback(nreq
->subreq
,
886 smbd_smb2_request_writev_done
,
892 struct smbd_smb2_request_pending_state
{
893 struct smbd_server_connection
*sconn
;
894 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x08 + 1];
895 struct iovec vector
[3];
898 static void smbd_smb2_request_pending_writev_done(struct tevent_req
*subreq
)
900 struct smbd_smb2_request_pending_state
*state
=
901 tevent_req_callback_data(subreq
,
902 struct smbd_smb2_request_pending_state
);
903 struct smbd_server_connection
*sconn
= state
->sconn
;
907 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
910 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
911 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
918 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
919 struct tevent_req
*subreq
)
922 struct smbd_smb2_request_pending_state
*state
= NULL
;
923 int i
= req
->current_idx
;
924 uint8_t *reqhdr
= NULL
;
926 uint8_t *body
= NULL
;
928 uint64_t message_id
= 0;
929 uint64_t async_id
= 0;
931 if (!tevent_req_is_in_progress(subreq
)) {
935 req
->subreq
= subreq
;
939 /* We're already async. */
943 if (req
->in
.vector_count
> i
+ 3) {
945 * We're trying to go async in a compound
947 * This is only allowed for opens that
948 * cause an oplock break, otherwise it
949 * is not allowed. See [MS-SMB2].pdf
950 * note <194> on Section 3.3.5.2.7.
952 const uint8_t *inhdr
=
953 (const uint8_t *)req
->in
.vector
[i
].iov_base
;
955 if (SVAL(inhdr
, SMB2_HDR_OPCODE
) != SMB2_OP_CREATE
) {
957 * Cancel the outstanding request.
959 bool ok
= tevent_req_cancel(req
->subreq
);
963 TALLOC_FREE(req
->subreq
);
964 return smbd_smb2_request_error(req
,
965 NT_STATUS_INTERNAL_ERROR
);
969 if (DEBUGLEVEL
>= 10) {
970 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
971 (unsigned int)req
->current_idx
);
972 print_req_vectors(req
);
977 * We're going async in a compound
978 * chain after the first request has
979 * already been processed. Send an
980 * interim response containing the
981 * set of replies already generated.
983 status
= smb2_send_async_interim_response(req
);
984 if (!NT_STATUS_IS_OK(status
)) {
988 req
->current_idx
= 1;
991 * Re-arrange the in.vectors to remove what
994 memmove(&req
->in
.vector
[1],
996 sizeof(req
->in
.vector
[0])*(req
->in
.vector_count
- i
));
997 req
->in
.vector_count
= 1 + (req
->in
.vector_count
- i
);
999 smb2_setup_nbt_length(req
->in
.vector
, req
->in
.vector_count
);
1001 /* Re-arrange the out.vectors to match. */
1002 memmove(&req
->out
.vector
[1],
1003 &req
->out
.vector
[i
],
1004 sizeof(req
->out
.vector
[0])*(req
->out
.vector_count
- i
));
1005 req
->out
.vector_count
= 1 + (req
->out
.vector_count
- i
);
1007 if (req
->in
.vector_count
== 4) {
1008 uint8_t *outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
1010 * We only have one remaining request as
1011 * we've processed everything else.
1012 * This is no longer a compound request.
1014 req
->compound_related
= false;
1015 flags
= (IVAL(outhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
1016 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
);
1020 /* Don't return an intermediate packet on a pipe read/write. */
1021 if (req
->tcon
&& req
->tcon
->compat_conn
&& IS_IPC(req
->tcon
->compat_conn
)) {
1025 reqhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
1026 flags
= (IVAL(reqhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
1027 message_id
= BVAL(reqhdr
, SMB2_HDR_MESSAGE_ID
);
1028 async_id
= message_id
; /* keep it simple for now... */
1031 * What we send is identical to a smbd_smb2_request_error
1032 * packet with an error status of STATUS_PENDING. Make use
1033 * of this fact sometime when refactoring. JRA.
1036 state
= talloc_zero(req
->sconn
, struct smbd_smb2_request_pending_state
);
1037 if (state
== NULL
) {
1038 return NT_STATUS_NO_MEMORY
;
1040 state
->sconn
= req
->sconn
;
1042 state
->vector
[0].iov_base
= (void *)state
->buf
;
1043 state
->vector
[0].iov_len
= 4;
1045 state
->vector
[1].iov_base
= state
->buf
+ 4;
1046 state
->vector
[1].iov_len
= SMB2_HDR_BODY
;
1048 state
->vector
[2].iov_base
= state
->buf
+ 4 + SMB2_HDR_BODY
;
1049 state
->vector
[2].iov_len
= 9;
1051 smb2_setup_nbt_length(state
->vector
, 3);
1053 hdr
= (uint8_t *)state
->vector
[1].iov_base
;
1054 body
= (uint8_t *)state
->vector
[2].iov_base
;
1056 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
1057 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1058 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1059 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
1060 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(reqhdr
, SMB2_HDR_OPCODE
));
1062 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
);
1063 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1064 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
1065 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
1066 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
1067 BVAL(reqhdr
, SMB2_HDR_SESSION_ID
));
1068 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
1070 SSVAL(body
, 0x00, 0x08 + 1);
1072 SCVAL(body
, 0x02, 0);
1073 SCVAL(body
, 0x03, 0);
1074 SIVAL(body
, 0x04, 0);
1075 /* Match W2K8R2... */
1076 SCVAL(body
, 0x08, 0x21);
1078 /* Ensure we correctly go through crediting. Grant
1079 the credits now, and zero credits on the final
1081 smb2_set_operation_credit(req
->sconn
,
1085 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1087 if (req
->do_signing
) {
1088 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
1089 &state
->vector
[1], 2);
1090 if (!NT_STATUS_IS_OK(status
)) {
1095 subreq
= tstream_writev_queue_send(state
,
1096 req
->sconn
->smb2
.event_ctx
,
1097 req
->sconn
->smb2
.stream
,
1098 req
->sconn
->smb2
.send_queue
,
1102 if (subreq
== NULL
) {
1103 return NT_STATUS_NO_MEMORY
;
1106 tevent_req_set_callback(subreq
,
1107 smbd_smb2_request_pending_writev_done
,
1110 /* Note we're going async with this request. */
1115 smb2_setup_nbt_length(req
->out
.vector
,
1116 req
->out
.vector_count
);
1119 /* Ensure our final reply matches the interim one. */
1120 reqhdr
= (uint8_t *)req
->out
.vector
[1].iov_base
;
1121 SIVAL(reqhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1122 SBVAL(reqhdr
, SMB2_HDR_PID
, async_id
);
1125 const uint8_t *inhdr
=
1126 (const uint8_t *)req
->in
.vector
[1].iov_base
;
1127 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1129 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1130 (unsigned long long)async_id
));
1134 return NT_STATUS_OK
;
1137 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
1139 struct smbd_server_connection
*sconn
= req
->sconn
;
1140 struct smbd_smb2_request
*cur
;
1141 const uint8_t *inhdr
;
1142 int i
= req
->current_idx
;
1144 uint64_t search_message_id
;
1145 uint64_t search_async_id
;
1148 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1150 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1151 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1152 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
1155 * we don't need the request anymore
1156 * cancel requests never have a response
1158 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1161 for (cur
= sconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
1162 const uint8_t *outhdr
;
1163 uint64_t message_id
;
1166 if (cur
->compound_related
) {
1168 * Never cancel anything in a compound request.
1169 * Way too hard to deal with the result.
1174 i
= cur
->current_idx
;
1176 outhdr
= (const uint8_t *)cur
->out
.vector
[i
].iov_base
;
1178 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1179 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
1181 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1182 if (search_async_id
== async_id
) {
1183 found_id
= async_id
;
1187 if (search_message_id
== message_id
) {
1188 found_id
= message_id
;
1194 if (cur
&& cur
->subreq
) {
1195 inhdr
= (const uint8_t *)cur
->in
.vector
[i
].iov_base
;
1196 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1197 "cancel opcode[%s] mid %llu\n",
1198 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1199 (unsigned long long)found_id
));
1200 tevent_req_cancel(cur
->subreq
);
1203 return NT_STATUS_OK
;
1206 NTSTATUS
smbd_smb2_request_verify_sizes(struct smbd_smb2_request
*req
,
1207 size_t expected_body_size
)
1209 const uint8_t *inhdr
;
1211 const uint8_t *inbody
;
1212 int i
= req
->current_idx
;
1214 size_t min_dyn_size
= expected_body_size
& 0x00000001;
1217 * The following should be checked already.
1219 if ((i
+2) > req
->in
.vector_count
) {
1220 return NT_STATUS_INTERNAL_ERROR
;
1222 if (req
->in
.vector
[i
+0].iov_len
!= SMB2_HDR_BODY
) {
1223 return NT_STATUS_INTERNAL_ERROR
;
1225 if (req
->in
.vector
[i
+1].iov_len
< 2) {
1226 return NT_STATUS_INTERNAL_ERROR
;
1229 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1230 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1234 case SMB2_OP_GETINFO
:
1240 * Now check the expected body size,
1241 * where the last byte might be in the
1242 * dynnamic section..
1244 if (req
->in
.vector
[i
+1].iov_len
!= (expected_body_size
& 0xFFFFFFFE)) {
1245 return NT_STATUS_INVALID_PARAMETER
;
1247 if (req
->in
.vector
[i
+2].iov_len
< min_dyn_size
) {
1248 return NT_STATUS_INVALID_PARAMETER
;
1251 inbody
= (const uint8_t *)req
->in
.vector
[i
+1].iov_base
;
1253 body_size
= SVAL(inbody
, 0x00);
1254 if (body_size
!= expected_body_size
) {
1255 return NT_STATUS_INVALID_PARAMETER
;
1258 return NT_STATUS_OK
;
1261 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
1263 const uint8_t *inhdr
;
1264 int i
= req
->current_idx
;
1269 NTSTATUS session_status
;
1270 uint32_t allowed_flags
;
1271 NTSTATUS return_value
;
1273 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1275 /* TODO: verify more things */
1277 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1278 opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1279 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1280 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1281 smb2_opcode_name(opcode
),
1282 (unsigned long long)mid
));
1284 if (get_Protocol() >= PROTOCOL_SMB2
) {
1286 * once the protocol is negotiated
1287 * SMB2_OP_NEGPROT is not allowed anymore
1289 if (opcode
== SMB2_OP_NEGPROT
) {
1290 /* drop the connection */
1291 return NT_STATUS_INVALID_PARAMETER
;
1295 * if the protocol is not negotiated yet
1296 * only SMB2_OP_NEGPROT is allowed.
1298 if (opcode
!= SMB2_OP_NEGPROT
) {
1299 /* drop the connection */
1300 return NT_STATUS_INVALID_PARAMETER
;
1304 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
1305 SMB2_HDR_FLAG_SIGNED
|
1307 if (opcode
== SMB2_OP_CANCEL
) {
1308 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
1310 if ((flags
& ~allowed_flags
) != 0) {
1311 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1315 * Check if the client provided a valid session id,
1316 * if so smbd_smb2_request_check_session() calls
1317 * set_current_user_info().
1319 * As some command don't require a valid session id
1320 * we defer the check of the session_status
1322 session_status
= smbd_smb2_request_check_session(req
);
1324 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
1326 * This check is mostly for giving the correct error code
1327 * for compounded requests.
1329 if (!NT_STATUS_IS_OK(session_status
)) {
1330 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1333 req
->compat_chain_fsp
= NULL
;
1336 req
->do_signing
= false;
1337 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
1338 if (!NT_STATUS_IS_OK(session_status
)) {
1339 return smbd_smb2_request_error(req
, session_status
);
1342 req
->do_signing
= true;
1343 status
= smb2_signing_check_pdu(req
->session
->session_key
,
1344 &req
->in
.vector
[i
], 3);
1345 if (!NT_STATUS_IS_OK(status
)) {
1346 return smbd_smb2_request_error(req
, status
);
1348 } else if (opcode
== SMB2_OP_CANCEL
) {
1349 /* Cancel requests are allowed to skip the signing */
1350 } else if (req
->session
&& req
->session
->do_signing
) {
1351 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
1354 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
1355 req
->compound_related
= true;
1359 case SMB2_OP_NEGPROT
:
1360 /* This call needs to be run as root */
1361 change_to_root_user();
1364 START_PROFILE(smb2_negprot
);
1365 return_value
= smbd_smb2_request_process_negprot(req
);
1366 END_PROFILE(smb2_negprot
);
1370 case SMB2_OP_SESSSETUP
:
1371 /* This call needs to be run as root */
1372 change_to_root_user();
1375 START_PROFILE(smb2_sesssetup
);
1376 return_value
= smbd_smb2_request_process_sesssetup(req
);
1377 END_PROFILE(smb2_sesssetup
);
1381 case SMB2_OP_LOGOFF
:
1382 if (!NT_STATUS_IS_OK(session_status
)) {
1383 return_value
= smbd_smb2_request_error(req
, session_status
);
1387 /* This call needs to be run as root */
1388 change_to_root_user();
1391 START_PROFILE(smb2_logoff
);
1392 return_value
= smbd_smb2_request_process_logoff(req
);
1393 END_PROFILE(smb2_logoff
);
1398 if (!NT_STATUS_IS_OK(session_status
)) {
1399 return_value
= smbd_smb2_request_error(req
, session_status
);
1404 * This call needs to be run as root.
1406 * smbd_smb2_request_process_tcon()
1407 * calls make_connection_snum(), which will call
1408 * change_to_user(), when needed.
1410 change_to_root_user();
1413 START_PROFILE(smb2_tcon
);
1414 return_value
= smbd_smb2_request_process_tcon(req
);
1415 END_PROFILE(smb2_tcon
);
1420 if (!NT_STATUS_IS_OK(session_status
)) {
1421 return_value
= smbd_smb2_request_error(req
, session_status
);
1425 * This call needs to be run as user.
1427 * smbd_smb2_request_check_tcon()
1428 * calls change_to_user() on success.
1430 status
= smbd_smb2_request_check_tcon(req
);
1431 if (!NT_STATUS_IS_OK(status
)) {
1432 return_value
= smbd_smb2_request_error(req
, status
);
1435 /* This call needs to be run as root */
1436 change_to_root_user();
1440 START_PROFILE(smb2_tdis
);
1441 return_value
= smbd_smb2_request_process_tdis(req
);
1442 END_PROFILE(smb2_tdis
);
1446 case SMB2_OP_CREATE
:
1447 if (!NT_STATUS_IS_OK(session_status
)) {
1448 return_value
= smbd_smb2_request_error(req
, session_status
);
1452 * This call needs to be run as user.
1454 * smbd_smb2_request_check_tcon()
1455 * calls change_to_user() on success.
1457 status
= smbd_smb2_request_check_tcon(req
);
1458 if (!NT_STATUS_IS_OK(status
)) {
1459 return_value
= smbd_smb2_request_error(req
, status
);
1464 START_PROFILE(smb2_create
);
1465 return_value
= smbd_smb2_request_process_create(req
);
1466 END_PROFILE(smb2_create
);
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
);
1488 START_PROFILE(smb2_close
);
1489 return_value
= smbd_smb2_request_process_close(req
);
1490 END_PROFILE(smb2_close
);
1495 if (!NT_STATUS_IS_OK(session_status
)) {
1496 return_value
= smbd_smb2_request_error(req
, session_status
);
1500 * This call needs to be run as user.
1502 * smbd_smb2_request_check_tcon()
1503 * calls change_to_user() on success.
1505 status
= smbd_smb2_request_check_tcon(req
);
1506 if (!NT_STATUS_IS_OK(status
)) {
1507 return_value
= smbd_smb2_request_error(req
, status
);
1512 START_PROFILE(smb2_flush
);
1513 return_value
= smbd_smb2_request_process_flush(req
);
1514 END_PROFILE(smb2_flush
);
1519 if (!NT_STATUS_IS_OK(session_status
)) {
1520 return_value
= smbd_smb2_request_error(req
, session_status
);
1524 * This call needs to be run as user.
1526 * smbd_smb2_request_check_tcon()
1527 * calls change_to_user() on success.
1529 status
= smbd_smb2_request_check_tcon(req
);
1530 if (!NT_STATUS_IS_OK(status
)) {
1531 return_value
= smbd_smb2_request_error(req
, status
);
1536 START_PROFILE(smb2_read
);
1537 return_value
= smbd_smb2_request_process_read(req
);
1538 END_PROFILE(smb2_read
);
1543 if (!NT_STATUS_IS_OK(session_status
)) {
1544 return_value
= smbd_smb2_request_error(req
, session_status
);
1548 * This call needs to be run as user.
1550 * smbd_smb2_request_check_tcon()
1551 * calls change_to_user() on success.
1553 status
= smbd_smb2_request_check_tcon(req
);
1554 if (!NT_STATUS_IS_OK(status
)) {
1555 return_value
= smbd_smb2_request_error(req
, status
);
1560 START_PROFILE(smb2_write
);
1561 return_value
= smbd_smb2_request_process_write(req
);
1562 END_PROFILE(smb2_write
);
1567 if (!NT_STATUS_IS_OK(session_status
)) {
1568 /* Too ugly to live ? JRA. */
1569 if (NT_STATUS_EQUAL(session_status
,NT_STATUS_USER_SESSION_DELETED
)) {
1570 session_status
= NT_STATUS_FILE_CLOSED
;
1572 return_value
= smbd_smb2_request_error(req
, session_status
);
1576 * This call needs to be run as user.
1578 * smbd_smb2_request_check_tcon()
1579 * calls change_to_user() on success.
1581 status
= smbd_smb2_request_check_tcon(req
);
1582 if (!NT_STATUS_IS_OK(status
)) {
1583 /* Too ugly to live ? JRA. */
1584 if (NT_STATUS_EQUAL(status
,NT_STATUS_NETWORK_NAME_DELETED
)) {
1585 status
= NT_STATUS_FILE_CLOSED
;
1587 return_value
= smbd_smb2_request_error(req
, status
);
1592 START_PROFILE(smb2_lock
);
1593 return_value
= smbd_smb2_request_process_lock(req
);
1594 END_PROFILE(smb2_lock
);
1599 if (!NT_STATUS_IS_OK(session_status
)) {
1600 return_value
= smbd_smb2_request_error(req
, session_status
);
1604 * This call needs to be run as user.
1606 * smbd_smb2_request_check_tcon()
1607 * calls change_to_user() on success.
1609 status
= smbd_smb2_request_check_tcon(req
);
1610 if (!NT_STATUS_IS_OK(status
)) {
1611 return_value
= smbd_smb2_request_error(req
, status
);
1616 START_PROFILE(smb2_ioctl
);
1617 return_value
= smbd_smb2_request_process_ioctl(req
);
1618 END_PROFILE(smb2_ioctl
);
1622 case SMB2_OP_CANCEL
:
1624 * This call needs to be run as root
1626 * That is what we also do in the SMB1 case.
1628 change_to_root_user();
1631 START_PROFILE(smb2_cancel
);
1632 return_value
= smbd_smb2_request_process_cancel(req
);
1633 END_PROFILE(smb2_cancel
);
1637 case SMB2_OP_KEEPALIVE
:
1638 /* This call needs to be run as root */
1639 change_to_root_user();
1642 START_PROFILE(smb2_keepalive
);
1643 return_value
= smbd_smb2_request_process_keepalive(req
);
1644 END_PROFILE(smb2_keepalive
);
1649 if (!NT_STATUS_IS_OK(session_status
)) {
1650 return_value
= smbd_smb2_request_error(req
, session_status
);
1654 * This call needs to be run as user.
1656 * smbd_smb2_request_check_tcon()
1657 * calls change_to_user() on success.
1659 status
= smbd_smb2_request_check_tcon(req
);
1660 if (!NT_STATUS_IS_OK(status
)) {
1661 return_value
= smbd_smb2_request_error(req
, status
);
1666 START_PROFILE(smb2_find
);
1667 return_value
= smbd_smb2_request_process_find(req
);
1668 END_PROFILE(smb2_find
);
1672 case SMB2_OP_NOTIFY
:
1673 if (!NT_STATUS_IS_OK(session_status
)) {
1674 return_value
= smbd_smb2_request_error(req
, session_status
);
1678 * This call needs to be run as user.
1680 * smbd_smb2_request_check_tcon()
1681 * calls change_to_user() on success.
1683 status
= smbd_smb2_request_check_tcon(req
);
1684 if (!NT_STATUS_IS_OK(status
)) {
1685 return_value
= smbd_smb2_request_error(req
, status
);
1690 START_PROFILE(smb2_notify
);
1691 return_value
= smbd_smb2_request_process_notify(req
);
1692 END_PROFILE(smb2_notify
);
1696 case SMB2_OP_GETINFO
:
1697 if (!NT_STATUS_IS_OK(session_status
)) {
1698 return_value
= smbd_smb2_request_error(req
, session_status
);
1702 * This call needs to be run as user.
1704 * smbd_smb2_request_check_tcon()
1705 * calls change_to_user() on success.
1707 status
= smbd_smb2_request_check_tcon(req
);
1708 if (!NT_STATUS_IS_OK(status
)) {
1709 return_value
= smbd_smb2_request_error(req
, status
);
1714 START_PROFILE(smb2_getinfo
);
1715 return_value
= smbd_smb2_request_process_getinfo(req
);
1716 END_PROFILE(smb2_getinfo
);
1720 case SMB2_OP_SETINFO
:
1721 if (!NT_STATUS_IS_OK(session_status
)) {
1722 return_value
= smbd_smb2_request_error(req
, session_status
);
1726 * This call needs to be run as user.
1728 * smbd_smb2_request_check_tcon()
1729 * calls change_to_user() on success.
1731 status
= smbd_smb2_request_check_tcon(req
);
1732 if (!NT_STATUS_IS_OK(status
)) {
1733 return_value
= smbd_smb2_request_error(req
, status
);
1738 START_PROFILE(smb2_setinfo
);
1739 return_value
= smbd_smb2_request_process_setinfo(req
);
1740 END_PROFILE(smb2_setinfo
);
1745 if (!NT_STATUS_IS_OK(session_status
)) {
1746 return_value
= smbd_smb2_request_error(req
, session_status
);
1750 * This call needs to be run as user.
1752 * smbd_smb2_request_check_tcon()
1753 * calls change_to_user() on success.
1755 status
= smbd_smb2_request_check_tcon(req
);
1756 if (!NT_STATUS_IS_OK(status
)) {
1757 return_value
= smbd_smb2_request_error(req
, status
);
1762 START_PROFILE(smb2_break
);
1763 return_value
= smbd_smb2_request_process_break(req
);
1764 END_PROFILE(smb2_break
);
1769 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1772 return return_value
;
1775 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
1777 struct tevent_req
*subreq
;
1778 int i
= req
->current_idx
;
1782 req
->current_idx
+= 3;
1784 if (req
->current_idx
< req
->out
.vector_count
) {
1786 * We must process the remaining compound
1787 * SMB2 requests before any new incoming SMB2
1788 * requests. This is because incoming SMB2
1789 * requests may include a cancel for a
1790 * compound request we haven't processed
1793 struct tevent_immediate
*im
= tevent_create_immediate(req
);
1795 return NT_STATUS_NO_MEMORY
;
1798 if (req
->do_signing
) {
1800 * We sign each reply as we go along.
1801 * We can do this as smb2_calculate_credits()
1802 * grants zero credits on every part of a
1803 * compound reply except the last one,
1804 * which is signed just before calling
1805 * tstream_writev_queue_send().
1808 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
1809 &req
->out
.vector
[i
], 3);
1810 if (!NT_STATUS_IS_OK(status
)) {
1816 tevent_schedule_immediate(im
,
1817 req
->sconn
->smb2
.event_ctx
,
1818 smbd_smb2_request_dispatch_immediate
,
1820 return NT_STATUS_OK
;
1823 if (req
->compound_related
) {
1824 req
->compound_related
= false;
1827 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
1829 /* Set credit for these operations (zero credits if this
1830 is a final reply for an async operation). */
1831 smb2_calculate_credits(req
, req
);
1833 if (req
->do_signing
) {
1835 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
1836 &req
->out
.vector
[i
], 3);
1837 if (!NT_STATUS_IS_OK(status
)) {
1842 if (DEBUGLEVEL
>= 10) {
1843 dbgtext("smbd_smb2_request_reply: sending...\n");
1844 print_req_vectors(req
);
1847 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1848 if (req
->out
.vector_count
== 4 &&
1849 req
->out
.vector
[3].iov_base
== NULL
&&
1850 req
->out
.vector
[3].iov_len
!= 0) {
1851 /* Dynamic part is NULL. Chop it off,
1852 We're going to send it via sendfile. */
1853 req
->out
.vector_count
-= 1;
1856 subreq
= tstream_writev_queue_send(req
,
1857 req
->sconn
->smb2
.event_ctx
,
1858 req
->sconn
->smb2
.stream
,
1859 req
->sconn
->smb2
.send_queue
,
1861 req
->out
.vector_count
);
1862 if (subreq
== NULL
) {
1863 return NT_STATUS_NO_MEMORY
;
1865 tevent_req_set_callback(subreq
, smbd_smb2_request_writev_done
, req
);
1867 * We're done with this request -
1868 * move it off the "being processed" queue.
1870 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1872 return NT_STATUS_OK
;
1875 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
);
1877 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
1878 struct tevent_immediate
*im
,
1881 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
1882 struct smbd_smb2_request
);
1883 struct smbd_server_connection
*sconn
= req
->sconn
;
1888 if (DEBUGLEVEL
>= 10) {
1889 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1890 req
->current_idx
, req
->in
.vector_count
));
1891 print_req_vectors(req
);
1894 status
= smbd_smb2_request_dispatch(req
);
1895 if (!NT_STATUS_IS_OK(status
)) {
1896 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1900 status
= smbd_smb2_request_next_incoming(sconn
);
1901 if (!NT_STATUS_IS_OK(status
)) {
1902 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1907 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
)
1909 struct smbd_smb2_request
*req
= tevent_req_callback_data(subreq
,
1910 struct smbd_smb2_request
);
1911 struct smbd_server_connection
*sconn
= req
->sconn
;
1916 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1917 TALLOC_FREE(subreq
);
1920 status
= map_nt_error_from_unix(sys_errno
);
1921 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1922 nt_errstr(status
)));
1923 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1927 status
= smbd_smb2_request_next_incoming(sconn
);
1928 if (!NT_STATUS_IS_OK(status
)) {
1929 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1934 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
1936 DATA_BLOB body
, DATA_BLOB
*dyn
,
1937 const char *location
)
1940 int i
= req
->current_idx
;
1941 uint32_t next_command_ofs
;
1943 DEBUG(10,("smbd_smb2_request_done_ex: "
1944 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1945 i
, nt_errstr(status
), (unsigned int)body
.length
,
1947 (unsigned int)(dyn
? dyn
->length
: 0),
1950 if (body
.length
< 2) {
1951 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
1954 if ((body
.length
% 2) != 0) {
1955 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
1958 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
1960 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
1961 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
1963 req
->out
.vector
[i
+1].iov_base
= (void *)body
.data
;
1964 req
->out
.vector
[i
+1].iov_len
= body
.length
;
1967 req
->out
.vector
[i
+2].iov_base
= (void *)dyn
->data
;
1968 req
->out
.vector
[i
+2].iov_len
= dyn
->length
;
1970 req
->out
.vector
[i
+2].iov_base
= NULL
;
1971 req
->out
.vector
[i
+2].iov_len
= 0;
1974 /* see if we need to recalculate the offset to the next response */
1975 if (next_command_ofs
> 0) {
1976 next_command_ofs
= SMB2_HDR_BODY
;
1977 next_command_ofs
+= req
->out
.vector
[i
+1].iov_len
;
1978 next_command_ofs
+= req
->out
.vector
[i
+2].iov_len
;
1981 if ((next_command_ofs
% 8) != 0) {
1982 size_t pad_size
= 8 - (next_command_ofs
% 8);
1983 if (req
->out
.vector
[i
+2].iov_len
== 0) {
1985 * if the dyn buffer is empty
1986 * we can use it to add padding
1990 pad
= talloc_zero_array(req
->out
.vector
,
1993 return smbd_smb2_request_error(req
,
1994 NT_STATUS_NO_MEMORY
);
1997 req
->out
.vector
[i
+2].iov_base
= (void *)pad
;
1998 req
->out
.vector
[i
+2].iov_len
= pad_size
;
2001 * For now we copy the dynamic buffer
2002 * and add the padding to the new buffer
2009 old_size
= req
->out
.vector
[i
+2].iov_len
;
2010 old_dyn
= (uint8_t *)req
->out
.vector
[i
+2].iov_base
;
2012 new_size
= old_size
+ pad_size
;
2013 new_dyn
= talloc_zero_array(req
->out
.vector
,
2015 if (new_dyn
== NULL
) {
2016 return smbd_smb2_request_error(req
,
2017 NT_STATUS_NO_MEMORY
);
2020 memcpy(new_dyn
, old_dyn
, old_size
);
2021 memset(new_dyn
+ old_size
, 0, pad_size
);
2023 req
->out
.vector
[i
+2].iov_base
= (void *)new_dyn
;
2024 req
->out
.vector
[i
+2].iov_len
= new_size
;
2026 next_command_ofs
+= pad_size
;
2029 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
2031 return smbd_smb2_request_reply(req
);
2034 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
2037 const char *location
)
2040 int i
= req
->current_idx
;
2041 uint8_t *outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
2043 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2044 i
, nt_errstr(status
), info
? " +info" : "",
2047 body
.data
= outhdr
+ SMB2_HDR_BODY
;
2049 SSVAL(body
.data
, 0, 9);
2052 SIVAL(body
.data
, 0x04, info
->length
);
2054 /* Allocated size of req->out.vector[i].iov_base
2055 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2056 * 1 byte without having to do an alloc.
2058 info
= talloc_zero_array(req
->out
.vector
,
2062 return NT_STATUS_NO_MEMORY
;
2064 info
->data
= ((uint8_t *)outhdr
) +
2065 OUTVEC_ALLOC_SIZE
- 1;
2067 SCVAL(info
->data
, 0, 0);
2071 * Note: Even if there is an error, continue to process the request.
2075 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
2079 struct smbd_smb2_send_oplock_break_state
{
2080 struct smbd_server_connection
*sconn
;
2081 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x18];
2082 struct iovec vector
;
2085 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
);
2087 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
2088 uint64_t file_id_persistent
,
2089 uint64_t file_id_volatile
,
2090 uint8_t oplock_level
)
2092 struct smbd_smb2_send_oplock_break_state
*state
;
2093 struct tevent_req
*subreq
;
2097 state
= talloc(sconn
, struct smbd_smb2_send_oplock_break_state
);
2098 if (state
== NULL
) {
2099 return NT_STATUS_NO_MEMORY
;
2101 state
->sconn
= sconn
;
2103 state
->vector
.iov_base
= (void *)state
->buf
;
2104 state
->vector
.iov_len
= sizeof(state
->buf
);
2106 _smb2_setlen(state
->buf
, sizeof(state
->buf
) - 4);
2107 hdr
= state
->buf
+ 4;
2108 body
= hdr
+ SMB2_HDR_BODY
;
2110 SIVAL(hdr
, 0, SMB2_MAGIC
);
2111 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
2112 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
2113 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
2114 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
2115 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
2116 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
2117 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
2118 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
2119 SIVAL(hdr
, SMB2_HDR_PID
, 0);
2120 SIVAL(hdr
, SMB2_HDR_TID
, 0);
2121 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
2122 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
2124 SSVAL(body
, 0x00, 0x18);
2126 SCVAL(body
, 0x02, oplock_level
);
2127 SCVAL(body
, 0x03, 0); /* reserved */
2128 SIVAL(body
, 0x04, 0); /* reserved */
2129 SBVAL(body
, 0x08, file_id_persistent
);
2130 SBVAL(body
, 0x10, file_id_volatile
);
2132 subreq
= tstream_writev_queue_send(state
,
2133 sconn
->smb2
.event_ctx
,
2135 sconn
->smb2
.send_queue
,
2137 if (subreq
== NULL
) {
2138 return NT_STATUS_NO_MEMORY
;
2140 tevent_req_set_callback(subreq
,
2141 smbd_smb2_oplock_break_writev_done
,
2144 return NT_STATUS_OK
;
2147 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
)
2149 struct smbd_smb2_send_oplock_break_state
*state
=
2150 tevent_req_callback_data(subreq
,
2151 struct smbd_smb2_send_oplock_break_state
);
2152 struct smbd_server_connection
*sconn
= state
->sconn
;
2156 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
2157 TALLOC_FREE(subreq
);
2159 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
2160 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2167 struct smbd_smb2_request_read_state
{
2169 bool asked_for_header
;
2170 struct smbd_smb2_request
*smb2_req
;
2173 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2175 TALLOC_CTX
*mem_ctx
,
2176 struct iovec
**_vector
,
2178 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
);
2180 static struct tevent_req
*smbd_smb2_request_read_send(TALLOC_CTX
*mem_ctx
,
2181 struct tevent_context
*ev
,
2182 struct smbd_server_connection
*sconn
)
2184 struct tevent_req
*req
;
2185 struct smbd_smb2_request_read_state
*state
;
2186 struct tevent_req
*subreq
;
2188 req
= tevent_req_create(mem_ctx
, &state
,
2189 struct smbd_smb2_request_read_state
);
2194 state
->asked_for_header
= false;
2196 state
->smb2_req
= smbd_smb2_request_allocate(state
);
2197 if (tevent_req_nomem(state
->smb2_req
, req
)) {
2198 return tevent_req_post(req
, ev
);
2200 state
->smb2_req
->sconn
= sconn
;
2202 subreq
= tstream_readv_pdu_queue_send(state
, ev
, sconn
->smb2
.stream
,
2203 sconn
->smb2
.recv_queue
,
2204 smbd_smb2_request_next_vector
,
2206 if (tevent_req_nomem(subreq
, req
)) {
2207 return tevent_req_post(req
, ev
);
2209 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
2214 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2216 TALLOC_CTX
*mem_ctx
,
2217 struct iovec
**_vector
,
2220 struct smbd_smb2_request_read_state
*state
=
2221 talloc_get_type_abort(private_data
,
2222 struct smbd_smb2_request_read_state
);
2223 struct smbd_smb2_request
*req
= state
->smb2_req
;
2224 struct iovec
*vector
;
2225 int idx
= req
->in
.vector_count
;
2227 uint8_t *buf
= NULL
;
2229 if (req
->in
.vector_count
== 0) {
2231 * first we need to get the NBT header
2233 req
->in
.vector
= talloc_array(req
, struct iovec
,
2234 req
->in
.vector_count
+ 1);
2235 if (req
->in
.vector
== NULL
) {
2238 req
->in
.vector_count
+= 1;
2240 req
->in
.vector
[idx
].iov_base
= (void *)req
->in
.nbt_hdr
;
2241 req
->in
.vector
[idx
].iov_len
= 4;
2243 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2244 if (vector
== NULL
) {
2248 vector
[0] = req
->in
.vector
[idx
];
2255 if (req
->in
.vector_count
== 1) {
2257 * Now we analyze the NBT header
2259 state
->missing
= smb2_len(req
->in
.vector
[0].iov_base
);
2261 if (state
->missing
== 0) {
2262 /* if there're no remaining bytes, we're done */
2268 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2270 req
->in
.vector_count
+ 1);
2271 if (req
->in
.vector
== NULL
) {
2274 req
->in
.vector_count
+= 1;
2276 if (CVAL(req
->in
.vector
[0].iov_base
, 0) != 0) {
2278 * it's a special NBT message,
2279 * so get all remaining bytes
2281 len
= state
->missing
;
2282 } else if (state
->missing
< (SMB2_HDR_BODY
+ 2)) {
2284 * it's an invalid message, just read what we can get
2285 * and let the caller handle the error
2287 len
= state
->missing
;
2290 * We assume it's a SMB2 request,
2291 * and we first get the header and the
2292 * first 2 bytes (the struct size) of the body
2294 len
= SMB2_HDR_BODY
+ 2;
2296 state
->asked_for_header
= true;
2299 state
->missing
-= len
;
2301 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2306 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2307 req
->in
.vector
[idx
].iov_len
= len
;
2309 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2310 if (vector
== NULL
) {
2314 vector
[0] = req
->in
.vector
[idx
];
2321 if (state
->missing
== 0) {
2322 /* if there're no remaining bytes, we're done */
2328 if (state
->asked_for_header
) {
2331 size_t next_command_ofs
;
2336 bool invalid
= false;
2338 state
->asked_for_header
= false;
2341 * We got the SMB2 header and the first 2 bytes
2342 * of the body. We fix the size to just the header
2343 * and manually copy the 2 first bytes to the body section
2345 req
->in
.vector
[idx
-1].iov_len
= SMB2_HDR_BODY
;
2346 hdr
= (const uint8_t *)req
->in
.vector
[idx
-1].iov_base
;
2348 /* allocate vectors for body and dynamic areas */
2349 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2351 req
->in
.vector_count
+ 2);
2352 if (req
->in
.vector
== NULL
) {
2355 req
->in
.vector_count
+= 2;
2357 full_size
= state
->missing
+ SMB2_HDR_BODY
+ 2;
2358 next_command_ofs
= IVAL(hdr
, SMB2_HDR_NEXT_COMMAND
);
2359 body_size
= SVAL(hdr
, SMB2_HDR_BODY
);
2361 if (next_command_ofs
!= 0) {
2362 if (next_command_ofs
< (SMB2_HDR_BODY
+ 2)) {
2364 * this is invalid, just return a zero
2365 * body and let the caller deal with the error
2368 } else if (next_command_ofs
> full_size
) {
2370 * this is invalid, just return a zero
2371 * body and let the caller deal with the error
2375 full_size
= next_command_ofs
;
2380 if (body_size
< 2) {
2382 * this is invalid, just return a zero
2383 * body and let the caller deal with the error
2388 if ((body_size
% 2) != 0) {
2392 if (body_size
> (full_size
- SMB2_HDR_BODY
)) {
2394 * this is invalid, just return a zero
2395 * body and let the caller deal with the error
2402 /* the caller should check this */
2406 dyn_size
= full_size
- (SMB2_HDR_BODY
+ body_size
);
2408 state
->missing
-= (body_size
- 2) + dyn_size
;
2410 body
= talloc_array(req
->in
.vector
, uint8_t, body_size
);
2415 dyn
= talloc_array(req
->in
.vector
, uint8_t, dyn_size
);
2420 req
->in
.vector
[idx
].iov_base
= (void *)body
;
2421 req
->in
.vector
[idx
].iov_len
= body_size
;
2422 req
->in
.vector
[idx
+1].iov_base
= (void *)dyn
;
2423 req
->in
.vector
[idx
+1].iov_len
= dyn_size
;
2425 vector
= talloc_array(mem_ctx
, struct iovec
, 2);
2426 if (vector
== NULL
) {
2431 * the first 2 bytes of the body were already fetched
2432 * together with the header
2434 memcpy(body
, hdr
+ SMB2_HDR_BODY
, 2);
2435 vector
[0].iov_base
= body
+ 2;
2436 vector
[0].iov_len
= body_size
- 2;
2438 vector
[1] = req
->in
.vector
[idx
+1];
2446 * when we endup here, we're looking for a new SMB2 request
2447 * next. And we ask for its header and the first 2 bytes of
2448 * the body (like we did for the first SMB2 request).
2451 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2453 req
->in
.vector_count
+ 1);
2454 if (req
->in
.vector
== NULL
) {
2457 req
->in
.vector_count
+= 1;
2460 * We assume it's a SMB2 request,
2461 * and we first get the header and the
2462 * first 2 bytes (the struct size) of the body
2464 len
= SMB2_HDR_BODY
+ 2;
2466 if (len
> state
->missing
) {
2467 /* let the caller handle the error */
2468 len
= state
->missing
;
2471 state
->missing
-= len
;
2472 state
->asked_for_header
= true;
2474 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2479 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2480 req
->in
.vector
[idx
].iov_len
= len
;
2482 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2483 if (vector
== NULL
) {
2487 vector
[0] = req
->in
.vector
[idx
];
2494 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
)
2496 struct tevent_req
*req
=
2497 tevent_req_callback_data(subreq
,
2503 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
2505 status
= map_nt_error_from_unix(sys_errno
);
2506 tevent_req_nterror(req
, status
);
2510 tevent_req_done(req
);
2513 static NTSTATUS
smbd_smb2_request_read_recv(struct tevent_req
*req
,
2514 TALLOC_CTX
*mem_ctx
,
2515 struct smbd_smb2_request
**_smb2_req
)
2517 struct smbd_smb2_request_read_state
*state
=
2518 tevent_req_data(req
,
2519 struct smbd_smb2_request_read_state
);
2522 if (tevent_req_is_nterror(req
, &status
)) {
2523 tevent_req_received(req
);
2527 talloc_steal(mem_ctx
, state
->smb2_req
->mem_pool
);
2528 *_smb2_req
= state
->smb2_req
;
2529 tevent_req_received(req
);
2530 return NT_STATUS_OK
;
2533 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
);
2535 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
)
2537 size_t max_send_queue_len
;
2538 size_t cur_send_queue_len
;
2539 struct tevent_req
*subreq
;
2541 if (tevent_queue_length(sconn
->smb2
.recv_queue
) > 0) {
2543 * if there is already a smbd_smb2_request_read
2544 * pending, we are done.
2546 return NT_STATUS_OK
;
2549 max_send_queue_len
= MAX(1, sconn
->smb2
.max_credits
/16);
2550 cur_send_queue_len
= tevent_queue_length(sconn
->smb2
.send_queue
);
2552 if (cur_send_queue_len
> max_send_queue_len
) {
2554 * if we have a lot of requests to send,
2555 * we wait until they are on the wire until we
2556 * ask for the next request.
2558 return NT_STATUS_OK
;
2561 /* ask for the next request */
2562 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->smb2
.event_ctx
, sconn
);
2563 if (subreq
== NULL
) {
2564 return NT_STATUS_NO_MEMORY
;
2566 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);
2568 return NT_STATUS_OK
;
2571 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
2572 const uint8_t *inbuf
, size_t size
)
2575 struct smbd_smb2_request
*req
= NULL
;
2577 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2578 (unsigned int)size
));
2580 status
= smbd_initialize_smb2(sconn
);
2581 if (!NT_STATUS_IS_OK(status
)) {
2582 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2586 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
2587 if (!NT_STATUS_IS_OK(status
)) {
2588 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2592 status
= smbd_smb2_request_validate(req
);
2593 if (!NT_STATUS_IS_OK(status
)) {
2594 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2598 status
= smbd_smb2_request_setup_out(req
);
2599 if (!NT_STATUS_IS_OK(status
)) {
2600 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2604 status
= smbd_smb2_request_dispatch(req
);
2605 if (!NT_STATUS_IS_OK(status
)) {
2606 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2610 status
= smbd_smb2_request_next_incoming(sconn
);
2611 if (!NT_STATUS_IS_OK(status
)) {
2612 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2616 sconn
->num_requests
++;
2619 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
)
2621 struct smbd_server_connection
*sconn
= tevent_req_callback_data(subreq
,
2622 struct smbd_server_connection
);
2624 struct smbd_smb2_request
*req
= NULL
;
2626 status
= smbd_smb2_request_read_recv(subreq
, sconn
, &req
);
2627 TALLOC_FREE(subreq
);
2628 if (!NT_STATUS_IS_OK(status
)) {
2629 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2630 nt_errstr(status
)));
2631 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2635 if (req
->in
.nbt_hdr
[0] != 0x00) {
2636 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2637 req
->in
.nbt_hdr
[0]));
2642 req
->current_idx
= 1;
2644 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2645 req
->current_idx
, req
->in
.vector_count
));
2647 status
= smbd_smb2_request_validate(req
);
2648 if (!NT_STATUS_IS_OK(status
)) {
2649 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2653 status
= smbd_smb2_request_setup_out(req
);
2654 if (!NT_STATUS_IS_OK(status
)) {
2655 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2659 status
= smbd_smb2_request_dispatch(req
);
2660 if (!NT_STATUS_IS_OK(status
)) {
2661 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2666 status
= smbd_smb2_request_next_incoming(sconn
);
2667 if (!NT_STATUS_IS_OK(status
)) {
2668 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2672 sconn
->num_requests
++;
2674 /* The timeout_processing function isn't run nearly
2675 often enough to implement 'max log size' without
2676 overrunning the size of the file by many megabytes.
2677 This is especially true if we are running at debug
2678 level 10. Checking every 50 SMB2s is a nice
2679 tradeoff of performance vs log file size overrun. */
2681 if ((sconn
->num_requests
% 50) == 0 &&
2682 need_to_check_log_size()) {
2683 change_to_root_user();