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
.credits_granted
= 1;
118 sconn
->smb2
.max_credits
= lp_smb2_max_credits();
119 sconn
->smb2
.credits_bitmap
= bitmap_talloc(sconn
,
120 sconn
->smb2
.max_credits
);
121 if (sconn
->smb2
.credits_bitmap
== NULL
) {
122 return NT_STATUS_NO_MEMORY
;
125 ret
= tstream_bsd_existing_socket(sconn
, sconn
->sock
,
126 &sconn
->smb2
.stream
);
128 status
= map_nt_error_from_unix(errno
);
132 /* Ensure child is set to non-blocking mode */
133 set_blocking(sconn
->sock
, false);
137 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
138 #define _smb2_setlen(_buf,len) do { \
139 uint8_t *buf = (uint8_t *)_buf; \
141 buf[1] = ((len)&0xFF0000)>>16; \
142 buf[2] = ((len)&0xFF00)>>8; \
143 buf[3] = (len)&0xFF; \
146 static void smb2_setup_nbt_length(struct iovec
*vector
, int count
)
151 for (i
=1; i
< count
; i
++) {
152 len
+= vector
[i
].iov_len
;
155 _smb2_setlen(vector
[0].iov_base
, len
);
158 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request
**req
)
161 (*req
)->parent
= NULL
;
162 (*req
)->mem_pool
= NULL
;
168 static int smbd_smb2_request_destructor(struct smbd_smb2_request
*req
)
172 talloc_free(req
->mem_pool
);
178 static struct smbd_smb2_request
*smbd_smb2_request_allocate(TALLOC_CTX
*mem_ctx
)
180 TALLOC_CTX
*mem_pool
;
181 struct smbd_smb2_request
**parent
;
182 struct smbd_smb2_request
*req
;
185 /* Enable this to find subtle valgrind errors. */
186 mem_pool
= talloc_init("smbd_smb2_request_allocate");
188 mem_pool
= talloc_pool(mem_ctx
, 8192);
190 if (mem_pool
== NULL
) {
194 parent
= talloc(mem_pool
, struct smbd_smb2_request
*);
195 if (parent
== NULL
) {
196 talloc_free(mem_pool
);
200 req
= talloc_zero(parent
, struct smbd_smb2_request
);
202 talloc_free(mem_pool
);
206 req
->mem_pool
= mem_pool
;
207 req
->parent
= parent
;
209 req
->last_session_id
= UINT64_MAX
;
210 req
->last_tid
= UINT32_MAX
;
212 talloc_set_destructor(parent
, smbd_smb2_request_parent_destructor
);
213 talloc_set_destructor(req
, smbd_smb2_request_destructor
);
218 static NTSTATUS
smbd_smb2_request_create(struct smbd_server_connection
*sconn
,
219 const uint8_t *inbuf
, size_t size
,
220 struct smbd_smb2_request
**_req
)
222 struct smbd_smb2_request
*req
;
223 uint32_t protocol_version
;
224 const uint8_t *inhdr
= NULL
;
227 uint32_t next_command_ofs
;
229 if (size
< (4 + SMB2_HDR_BODY
+ 2)) {
230 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size
));
231 return NT_STATUS_INVALID_PARAMETER
;
236 protocol_version
= IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
);
237 if (protocol_version
!= SMB2_MAGIC
) {
238 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
240 return NT_STATUS_INVALID_PARAMETER
;
243 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
244 if (cmd
!= SMB2_OP_NEGPROT
) {
245 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
247 return NT_STATUS_INVALID_PARAMETER
;
250 next_command_ofs
= IVAL(inhdr
, SMB2_HDR_NEXT_COMMAND
);
251 if (next_command_ofs
!= 0) {
252 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
254 return NT_STATUS_INVALID_PARAMETER
;
257 req
= smbd_smb2_request_allocate(sconn
);
259 return NT_STATUS_NO_MEMORY
;
263 talloc_steal(req
, inbuf
);
265 req
->in
.vector
= talloc_array(req
, struct iovec
, 4);
266 if (req
->in
.vector
== NULL
) {
268 return NT_STATUS_NO_MEMORY
;
270 req
->in
.vector_count
= 4;
272 memcpy(req
->in
.nbt_hdr
, inbuf
, 4);
275 req
->in
.vector
[0].iov_base
= (void *)req
->in
.nbt_hdr
;
276 req
->in
.vector
[0].iov_len
= 4;
277 ofs
+= req
->in
.vector
[0].iov_len
;
279 req
->in
.vector
[1].iov_base
= (void *)(inbuf
+ ofs
);
280 req
->in
.vector
[1].iov_len
= SMB2_HDR_BODY
;
281 ofs
+= req
->in
.vector
[1].iov_len
;
283 req
->in
.vector
[2].iov_base
= (void *)(inbuf
+ ofs
);
284 req
->in
.vector
[2].iov_len
= SVAL(inbuf
, ofs
) & 0xFFFE;
285 ofs
+= req
->in
.vector
[2].iov_len
;
288 return NT_STATUS_INVALID_PARAMETER
;
291 req
->in
.vector
[3].iov_base
= (void *)(inbuf
+ ofs
);
292 req
->in
.vector
[3].iov_len
= size
- ofs
;
293 ofs
+= req
->in
.vector
[3].iov_len
;
295 req
->current_idx
= 1;
301 static bool smb2_validate_sequence_number(struct smbd_server_connection
*sconn
,
302 uint64_t message_id
, uint64_t seq_id
)
304 struct bitmap
*credits_bm
= sconn
->smb2
.credits_bitmap
;
307 if (seq_id
< sconn
->smb2
.seqnum_low
) {
308 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
309 "%llu (sequence id %llu) (low = %llu, max = %lu)\n",
310 (unsigned long long)message_id
,
311 (unsigned long long)seq_id
,
312 (unsigned long long)sconn
->smb2
.seqnum_low
,
313 (unsigned long)sconn
->smb2
.max_credits
));
317 if (seq_id
> (sconn
->smb2
.seqnum_low
+ sconn
->smb2
.max_credits
)) {
318 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
319 "%llu (sequence id %llu) (low = %llu, max = %lu)\n",
320 (unsigned long long)message_id
,
321 (unsigned long long)seq_id
,
322 (unsigned long long)sconn
->smb2
.seqnum_low
,
323 (unsigned long)sconn
->smb2
.max_credits
));
327 offset
= seq_id
% sconn
->smb2
.max_credits
;
329 if (bitmap_query(credits_bm
, offset
)) {
330 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
331 "%llu (sequence id %llu) (low = %llu, max = %lu) "
333 (unsigned long long)message_id
,
334 (unsigned long long)seq_id
,
335 (unsigned long long)sconn
->smb2
.seqnum_low
,
336 (unsigned long)sconn
->smb2
.max_credits
,
341 /* Mark the message_ids as seen in the bitmap. */
342 bitmap_set(credits_bm
, offset
);
344 if (seq_id
!= sconn
->smb2
.seqnum_low
) {
349 * Move the window forward by all the message_id's
352 while (bitmap_query(credits_bm
, offset
)) {
353 DEBUG(10,("smb2_validate_sequence_number: clearing "
354 "id %llu (position %u) from bitmap\n",
355 (unsigned long long)(sconn
->smb2
.seqnum_low
),
357 bitmap_clear(credits_bm
, offset
);
359 sconn
->smb2
.seqnum_low
+= 1;
360 offset
= sconn
->smb2
.seqnum_low
% sconn
->smb2
.max_credits
;
366 static bool smb2_validate_message_id(struct smbd_server_connection
*sconn
,
367 const uint8_t *inhdr
)
369 uint64_t message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
370 uint16_t opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
373 if (opcode
== SMB2_OP_CANCEL
) {
374 /* SMB2_CANCEL requests by definition resend messageids. */
378 if (sconn
->smb2
.credits_granted
== 0) {
379 DEBUG(0,("smb2_validate_message_id: client used more "
380 "credits than granted message_id (%llu)\n",
381 (unsigned long long)message_id
));
385 DEBUG(11, ("smb2_validate_message_id: mid %llu, credits_granted %llu, "
386 "max_credits %llu, seqnum_low: %llu\n",
387 (unsigned long long) message_id
,
388 (unsigned long long) sconn
->smb2
.credits_granted
,
389 (unsigned long long) sconn
->smb2
.max_credits
,
390 (unsigned long long) sconn
->smb2
.seqnum_low
));
392 ok
= smb2_validate_sequence_number(sconn
, message_id
, message_id
);
397 /* substract used credits */
398 sconn
->smb2
.credits_granted
-= 1;
403 static NTSTATUS
smbd_smb2_request_validate(struct smbd_smb2_request
*req
)
408 count
= req
->in
.vector_count
;
411 /* It's not a SMB2 request */
412 return NT_STATUS_INVALID_PARAMETER
;
415 for (idx
=1; idx
< count
; idx
+= 3) {
416 const uint8_t *inhdr
= NULL
;
419 if (req
->in
.vector
[idx
].iov_len
!= SMB2_HDR_BODY
) {
420 return NT_STATUS_INVALID_PARAMETER
;
423 if (req
->in
.vector
[idx
+1].iov_len
< 2) {
424 return NT_STATUS_INVALID_PARAMETER
;
427 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
429 /* Check the SMB2 header */
430 if (IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
) != SMB2_MAGIC
) {
431 return NT_STATUS_INVALID_PARAMETER
;
434 if (!smb2_validate_message_id(req
->sconn
, inhdr
)) {
435 return NT_STATUS_INVALID_PARAMETER
;
438 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
441 * the 1st request should never have the
442 * SMB2_HDR_FLAG_CHAINED flag set
444 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
445 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
448 } else if (idx
== 4) {
450 * the 2nd request triggers related vs. unrelated
451 * compounded requests
453 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
454 req
->compound_related
= true;
456 } else if (idx
> 4) {
459 * It seems the this tests are wrong
460 * see the SMB2-COMPOUND test
464 * all other requests should match the 2nd one
466 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
467 if (!req
->compound_related
) {
469 NT_STATUS_INVALID_PARAMETER
;
473 if (req
->compound_related
) {
475 NT_STATUS_INVALID_PARAMETER
;
486 static void smb2_set_operation_credit(struct smbd_server_connection
*sconn
,
487 const struct iovec
*in_vector
,
488 struct iovec
*out_vector
)
490 const uint8_t *inhdr
= (const uint8_t *)in_vector
->iov_base
;
491 uint8_t *outhdr
= (uint8_t *)out_vector
->iov_base
;
492 uint16_t credits_requested
;
494 uint16_t credits_granted
= 0;
496 credits_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
497 out_flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
499 SMB_ASSERT(sconn
->smb2
.max_credits
>= sconn
->smb2
.credits_granted
);
501 if (out_flags
& SMB2_HDR_FLAG_ASYNC
) {
503 * In case we already send an async interim
504 * response, we should not grant
505 * credits on the final response.
507 credits_requested
= 0;
510 if (credits_requested
) {
511 uint16_t modified_credits_requested
;
515 * Split up max_credits into 1/16ths, and then scale
516 * the requested credits by how many 16ths have been
517 * currently granted. Less than 1/16th == grant all
518 * requested (100%), scale down as more have been
519 * granted. Never ask for less than 1 as the client
520 * asked for at least 1. JRA.
523 multiplier
= 16 - (((sconn
->smb2
.credits_granted
* 16) / sconn
->smb2
.max_credits
) % 16);
525 modified_credits_requested
= (multiplier
* credits_requested
) / 16;
526 if (modified_credits_requested
== 0) {
527 modified_credits_requested
= 1;
530 /* Remember what we gave out. */
531 credits_granted
= MIN(modified_credits_requested
,
532 (sconn
->smb2
.max_credits
- sconn
->smb2
.credits_granted
));
535 if (credits_granted
== 0 && sconn
->smb2
.credits_granted
== 0) {
536 /* First negprot packet, or ensure the client credits can
537 never drop to zero. */
541 SSVAL(outhdr
, SMB2_HDR_CREDIT
, credits_granted
);
542 sconn
->smb2
.credits_granted
+= credits_granted
;
544 DEBUG(10,("smb2_set_operation_credit: requested %u, "
545 "granted %u, total granted %u\n",
546 (unsigned int)credits_requested
,
547 (unsigned int)credits_granted
,
548 (unsigned int)sconn
->smb2
.credits_granted
));
551 static void smb2_calculate_credits(const struct smbd_smb2_request
*inreq
,
552 struct smbd_smb2_request
*outreq
)
555 uint16_t total_credits
= 0;
557 count
= outreq
->out
.vector_count
;
559 for (idx
=1; idx
< count
; idx
+= 3) {
560 uint8_t *outhdr
= (uint8_t *)outreq
->out
.vector
[idx
].iov_base
;
561 smb2_set_operation_credit(outreq
->sconn
,
562 &inreq
->in
.vector
[idx
],
563 &outreq
->out
.vector
[idx
]);
564 /* To match Windows, count up what we
566 total_credits
+= SVAL(outhdr
, SMB2_HDR_CREDIT
);
567 /* Set to zero in all but the last reply. */
568 if (idx
+ 3 < count
) {
569 SSVAL(outhdr
, SMB2_HDR_CREDIT
, 0);
571 SSVAL(outhdr
, SMB2_HDR_CREDIT
, total_credits
);
576 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
)
578 struct iovec
*vector
;
582 count
= req
->in
.vector_count
;
583 vector
= talloc_zero_array(req
, struct iovec
, count
);
584 if (vector
== NULL
) {
585 return NT_STATUS_NO_MEMORY
;
588 vector
[0].iov_base
= req
->out
.nbt_hdr
;
589 vector
[0].iov_len
= 4;
590 SIVAL(req
->out
.nbt_hdr
, 0, 0);
592 for (idx
=1; idx
< count
; idx
+= 3) {
593 const uint8_t *inhdr
= NULL
;
595 uint8_t *outhdr
= NULL
;
596 uint8_t *outbody
= NULL
;
597 uint32_t next_command_ofs
= 0;
598 struct iovec
*current
= &vector
[idx
];
600 if ((idx
+ 3) < count
) {
601 /* we have a next command -
602 * setup for the error case. */
603 next_command_ofs
= SMB2_HDR_BODY
+ 9;
606 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
607 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
609 outhdr
= talloc_zero_array(vector
, uint8_t,
611 if (outhdr
== NULL
) {
612 return NT_STATUS_NO_MEMORY
;
615 outbody
= outhdr
+ SMB2_HDR_BODY
;
617 current
[0].iov_base
= (void *)outhdr
;
618 current
[0].iov_len
= SMB2_HDR_BODY
;
620 current
[1].iov_base
= (void *)outbody
;
621 current
[1].iov_len
= 8;
623 current
[2].iov_base
= NULL
;
624 current
[2].iov_len
= 0;
626 /* setup the SMB2 header */
627 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
628 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
629 SSVAL(outhdr
, SMB2_HDR_CREDIT_CHARGE
,
630 SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
));
631 SIVAL(outhdr
, SMB2_HDR_STATUS
,
632 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
633 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
634 SVAL(inhdr
, SMB2_HDR_OPCODE
));
635 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
636 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
637 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
638 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
639 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
640 SIVAL(outhdr
, SMB2_HDR_PID
,
641 IVAL(inhdr
, SMB2_HDR_PID
));
642 SIVAL(outhdr
, SMB2_HDR_TID
,
643 IVAL(inhdr
, SMB2_HDR_TID
));
644 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
645 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
646 memcpy(outhdr
+ SMB2_HDR_SIGNATURE
,
647 inhdr
+ SMB2_HDR_SIGNATURE
, 16);
649 /* setup error body header */
650 SSVAL(outbody
, 0x00, 0x08 + 1);
651 SSVAL(outbody
, 0x02, 0);
652 SIVAL(outbody
, 0x04, 0);
655 req
->out
.vector
= vector
;
656 req
->out
.vector_count
= count
;
658 /* setup the length of the NBT packet */
659 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
661 DLIST_ADD_END(req
->sconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
666 void smbd_server_connection_terminate_ex(struct smbd_server_connection
*sconn
,
668 const char *location
)
670 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
672 exit_server_cleanly(reason
);
675 static bool dup_smb2_vec3(TALLOC_CTX
*ctx
,
676 struct iovec
*outvec
,
677 const struct iovec
*srcvec
)
679 /* vec[0] is always boilerplate and must
680 * be allocated with size OUTVEC_ALLOC_SIZE. */
682 outvec
[0].iov_base
= talloc_memdup(ctx
,
685 if (!outvec
[0].iov_base
) {
688 outvec
[0].iov_len
= SMB2_HDR_BODY
;
691 * If this is a "standard" vec[1] of length 8,
692 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
693 * then duplicate this. Else use talloc_memdup().
696 if (srcvec
[1].iov_len
== 8 &&
697 srcvec
[1].iov_base
==
698 ((uint8_t *)srcvec
[0].iov_base
) +
700 outvec
[1].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
702 outvec
[1].iov_len
= 8;
704 outvec
[1].iov_base
= talloc_memdup(ctx
,
707 if (!outvec
[1].iov_base
) {
710 outvec
[1].iov_len
= srcvec
[1].iov_len
;
714 * If this is a "standard" vec[2] of length 1,
715 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
716 * then duplicate this. Else use talloc_memdup().
719 if (srcvec
[2].iov_base
&&
721 if (srcvec
[2].iov_base
==
722 ((uint8_t *)srcvec
[0].iov_base
) +
723 (OUTVEC_ALLOC_SIZE
- 1) &&
724 srcvec
[2].iov_len
== 1) {
725 /* Common SMB2 error packet case. */
726 outvec
[2].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
727 (OUTVEC_ALLOC_SIZE
- 1);
729 outvec
[2].iov_base
= talloc_memdup(ctx
,
732 if (!outvec
[2].iov_base
) {
736 outvec
[2].iov_len
= srcvec
[2].iov_len
;
738 outvec
[2].iov_base
= NULL
;
739 outvec
[2].iov_len
= 0;
744 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
746 struct smbd_smb2_request
*newreq
= NULL
;
747 struct iovec
*outvec
= NULL
;
748 int count
= req
->out
.vector_count
;
751 newreq
= smbd_smb2_request_allocate(req
->sconn
);
756 newreq
->sconn
= req
->sconn
;
757 newreq
->session
= req
->session
;
758 newreq
->do_signing
= req
->do_signing
;
759 newreq
->current_idx
= req
->current_idx
;
760 newreq
->async
= false;
761 newreq
->cancelled
= false;
762 /* Note we are leaving:
766 uninitialized as NULL here as
767 they're not used in the interim
768 response code. JRA. */
770 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
775 newreq
->out
.vector
= outvec
;
776 newreq
->out
.vector_count
= count
;
778 /* Setup the outvec's identically to req. */
779 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
780 outvec
[0].iov_len
= 4;
781 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
783 /* Setup the vectors identically to the ones in req. */
784 for (i
= 1; i
< count
; i
+= 3) {
785 if (!dup_smb2_vec3(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
796 smb2_setup_nbt_length(newreq
->out
.vector
,
797 newreq
->out
.vector_count
);
802 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
);
804 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
807 uint8_t *outhdr
= NULL
;
808 struct smbd_smb2_request
*nreq
= NULL
;
810 /* Create a new smb2 request we'll use
811 for the interim return. */
812 nreq
= dup_smb2_req(req
);
814 return NT_STATUS_NO_MEMORY
;
817 /* Lose the last 3 out vectors. They're the
818 ones we'll be using for the async reply. */
819 nreq
->out
.vector_count
-= 3;
821 smb2_setup_nbt_length(nreq
->out
.vector
,
822 nreq
->out
.vector_count
);
824 /* Step back to the previous reply. */
825 i
= nreq
->current_idx
- 3;
826 outhdr
= (uint8_t *)nreq
->out
.vector
[i
].iov_base
;
827 /* And end the chain. */
828 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
830 /* Calculate outgoing credits */
831 smb2_calculate_credits(req
, nreq
);
833 /* Re-sign if needed. */
834 if (nreq
->do_signing
) {
836 status
= smb2_signing_sign_pdu(nreq
->session
->session_key
,
837 &nreq
->out
.vector
[i
], 3);
838 if (!NT_STATUS_IS_OK(status
)) {
842 if (DEBUGLEVEL
>= 10) {
843 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
844 (unsigned int)nreq
->current_idx
);
845 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
846 (unsigned int)nreq
->out
.vector_count
);
847 print_req_vectors(nreq
);
849 nreq
->subreq
= tstream_writev_queue_send(nreq
,
850 nreq
->sconn
->smb2
.event_ctx
,
851 nreq
->sconn
->smb2
.stream
,
852 nreq
->sconn
->smb2
.send_queue
,
854 nreq
->out
.vector_count
);
856 if (nreq
->subreq
== NULL
) {
857 return NT_STATUS_NO_MEMORY
;
860 tevent_req_set_callback(nreq
->subreq
,
861 smbd_smb2_request_writev_done
,
867 struct smbd_smb2_request_pending_state
{
868 struct smbd_server_connection
*sconn
;
869 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x08 + 1];
870 struct iovec vector
[3];
873 static void smbd_smb2_request_pending_writev_done(struct tevent_req
*subreq
)
875 struct smbd_smb2_request_pending_state
*state
=
876 tevent_req_callback_data(subreq
,
877 struct smbd_smb2_request_pending_state
);
878 struct smbd_server_connection
*sconn
= state
->sconn
;
882 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
885 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
886 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
893 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
894 struct tevent_req
*subreq
)
897 struct smbd_smb2_request_pending_state
*state
= NULL
;
898 int i
= req
->current_idx
;
899 uint8_t *reqhdr
= NULL
;
901 uint8_t *body
= NULL
;
903 uint64_t message_id
= 0;
904 uint64_t async_id
= 0;
905 struct iovec
*outvec
= NULL
;
907 if (!tevent_req_is_in_progress(subreq
)) {
911 req
->subreq
= subreq
;
915 /* We're already async. */
919 if (req
->in
.vector_count
> i
+ 3) {
921 * We're trying to go async in a compound
922 * request chain. This is not allowed.
923 * Cancel the outstanding request.
925 tevent_req_cancel(req
->subreq
);
926 return smbd_smb2_request_error(req
,
927 NT_STATUS_INSUFFICIENT_RESOURCES
);
930 if (DEBUGLEVEL
>= 10) {
931 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
932 (unsigned int)req
->current_idx
);
933 print_req_vectors(req
);
936 if (req
->out
.vector_count
> 4) {
937 /* This is a compound reply. We
938 * must do an interim response
939 * followed by the async response
942 status
= smb2_send_async_interim_response(req
);
943 if (!NT_STATUS_IS_OK(status
)) {
948 * We're splitting off the last SMB2
949 * request in a compound set, and the
950 * smb2_send_async_interim_response()
951 * call above just sent all the replies
952 * for the previous SMB2 requests in
953 * this compound set. So we're no longer
954 * in the "compound_related_in_progress"
955 * state, and this is no longer a compound
958 req
->compound_related
= false;
959 req
->sconn
->smb2
.compound_related_in_progress
= false;
962 /* Don't return an intermediate packet on a pipe read/write. */
963 if (req
->tcon
&& req
->tcon
->compat_conn
&& IS_IPC(req
->tcon
->compat_conn
)) {
967 reqhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
968 flags
= (IVAL(reqhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
969 message_id
= BVAL(reqhdr
, SMB2_HDR_MESSAGE_ID
);
970 async_id
= message_id
; /* keep it simple for now... */
973 * What we send is identical to a smbd_smb2_request_error
974 * packet with an error status of STATUS_PENDING. Make use
975 * of this fact sometime when refactoring. JRA.
978 state
= talloc_zero(req
->sconn
, struct smbd_smb2_request_pending_state
);
980 return NT_STATUS_NO_MEMORY
;
982 state
->sconn
= req
->sconn
;
984 state
->vector
[0].iov_base
= (void *)state
->buf
;
985 state
->vector
[0].iov_len
= 4;
987 state
->vector
[1].iov_base
= state
->buf
+ 4;
988 state
->vector
[1].iov_len
= SMB2_HDR_BODY
;
990 state
->vector
[2].iov_base
= state
->buf
+ 4 + SMB2_HDR_BODY
;
991 state
->vector
[2].iov_len
= 9;
993 smb2_setup_nbt_length(state
->vector
, 3);
995 hdr
= (uint8_t *)state
->vector
[1].iov_base
;
996 body
= (uint8_t *)state
->vector
[2].iov_base
;
998 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
999 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1000 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1001 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
1002 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(reqhdr
, SMB2_HDR_OPCODE
));
1004 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
);
1005 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1006 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
1007 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
1008 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
1009 BVAL(reqhdr
, SMB2_HDR_SESSION_ID
));
1010 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
1012 SSVAL(body
, 0x00, 0x08 + 1);
1014 SCVAL(body
, 0x02, 0);
1015 SCVAL(body
, 0x03, 0);
1016 SIVAL(body
, 0x04, 0);
1017 /* Match W2K8R2... */
1018 SCVAL(body
, 0x08, 0x21);
1020 /* Ensure we correctly go through crediting. Grant
1021 the credits now, and zero credits on the final
1023 smb2_set_operation_credit(req
->sconn
,
1027 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1029 if (req
->do_signing
) {
1030 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
1031 &state
->vector
[1], 2);
1032 if (!NT_STATUS_IS_OK(status
)) {
1037 subreq
= tstream_writev_queue_send(state
,
1038 req
->sconn
->smb2
.event_ctx
,
1039 req
->sconn
->smb2
.stream
,
1040 req
->sconn
->smb2
.send_queue
,
1044 if (subreq
== NULL
) {
1045 return NT_STATUS_NO_MEMORY
;
1048 tevent_req_set_callback(subreq
,
1049 smbd_smb2_request_pending_writev_done
,
1052 /* Note we're going async with this request. */
1058 * Now manipulate req so that the outstanding async request
1059 * is the only one left in the struct smbd_smb2_request.
1062 if (req
->current_idx
== 1) {
1063 /* There was only one. */
1067 /* Re-arrange the in.vectors. */
1068 req
->in
.vector
[1] = req
->in
.vector
[i
];
1069 req
->in
.vector
[2] = req
->in
.vector
[i
+1];
1070 req
->in
.vector
[3] = req
->in
.vector
[i
+2];
1071 req
->in
.vector_count
= 4;
1072 /* Reset the new in size. */
1073 smb2_setup_nbt_length(req
->in
.vector
, 4);
1075 /* Now recreate the out.vectors. */
1076 outvec
= talloc_zero_array(req
, struct iovec
, 4);
1078 return NT_STATUS_NO_MEMORY
;
1081 /* 0 is always boilerplate and must
1082 * be of size 4 for the length field. */
1084 outvec
[0].iov_base
= req
->out
.nbt_hdr
;
1085 outvec
[0].iov_len
= 4;
1086 SIVAL(req
->out
.nbt_hdr
, 0, 0);
1088 if (!dup_smb2_vec3(outvec
, &outvec
[1], &req
->out
.vector
[i
])) {
1089 return NT_STATUS_NO_MEMORY
;
1092 TALLOC_FREE(req
->out
.vector
);
1094 req
->out
.vector
= outvec
;
1096 req
->current_idx
= 1;
1097 req
->out
.vector_count
= 4;
1101 smb2_setup_nbt_length(req
->out
.vector
,
1102 req
->out
.vector_count
);
1105 /* Ensure our final reply matches the interim one. */
1106 reqhdr
= (uint8_t *)req
->out
.vector
[1].iov_base
;
1107 SIVAL(reqhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1108 SBVAL(reqhdr
, SMB2_HDR_PID
, async_id
);
1111 const uint8_t *inhdr
=
1112 (const uint8_t *)req
->in
.vector
[1].iov_base
;
1113 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1115 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1116 (unsigned long long)async_id
));
1120 return NT_STATUS_OK
;
1123 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
1125 struct smbd_server_connection
*sconn
= req
->sconn
;
1126 struct smbd_smb2_request
*cur
;
1127 const uint8_t *inhdr
;
1128 int i
= req
->current_idx
;
1130 uint64_t search_message_id
;
1131 uint64_t search_async_id
;
1134 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1136 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1137 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1138 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
1141 * we don't need the request anymore
1142 * cancel requests never have a response
1144 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1147 for (cur
= sconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
1148 const uint8_t *outhdr
;
1149 uint64_t message_id
;
1152 i
= cur
->current_idx
;
1154 outhdr
= (const uint8_t *)cur
->out
.vector
[i
].iov_base
;
1156 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1157 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
1159 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1160 if (search_async_id
== async_id
) {
1161 found_id
= async_id
;
1165 if (search_message_id
== message_id
) {
1166 found_id
= message_id
;
1172 if (cur
&& cur
->subreq
) {
1173 inhdr
= (const uint8_t *)cur
->in
.vector
[i
].iov_base
;
1174 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1175 "cancel opcode[%s] mid %llu\n",
1176 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1177 (unsigned long long)found_id
));
1178 tevent_req_cancel(cur
->subreq
);
1181 return NT_STATUS_OK
;
1184 NTSTATUS
smbd_smb2_request_verify_sizes(struct smbd_smb2_request
*req
,
1185 size_t expected_body_size
)
1187 const uint8_t *inhdr
;
1189 const uint8_t *inbody
;
1190 int i
= req
->current_idx
;
1192 size_t min_dyn_size
= expected_body_size
& 0x00000001;
1195 * The following should be checked already.
1197 if ((i
+2) > req
->in
.vector_count
) {
1198 return NT_STATUS_INTERNAL_ERROR
;
1200 if (req
->in
.vector
[i
+0].iov_len
!= SMB2_HDR_BODY
) {
1201 return NT_STATUS_INTERNAL_ERROR
;
1203 if (req
->in
.vector
[i
+1].iov_len
< 2) {
1204 return NT_STATUS_INTERNAL_ERROR
;
1207 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1208 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1212 case SMB2_OP_GETINFO
:
1218 * Now check the expected body size,
1219 * where the last byte might be in the
1220 * dynnamic section..
1222 if (req
->in
.vector
[i
+1].iov_len
!= (expected_body_size
& 0xFFFFFFFE)) {
1223 return NT_STATUS_INVALID_PARAMETER
;
1225 if (req
->in
.vector
[i
+2].iov_len
< min_dyn_size
) {
1226 return NT_STATUS_INVALID_PARAMETER
;
1229 inbody
= (const uint8_t *)req
->in
.vector
[i
+1].iov_base
;
1231 body_size
= SVAL(inbody
, 0x00);
1232 if (body_size
!= expected_body_size
) {
1233 return NT_STATUS_INVALID_PARAMETER
;
1236 return NT_STATUS_OK
;
1239 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
1241 const uint8_t *inhdr
;
1242 int i
= req
->current_idx
;
1247 NTSTATUS session_status
;
1248 uint32_t allowed_flags
;
1249 NTSTATUS return_value
;
1251 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1253 /* TODO: verify more things */
1255 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1256 opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1257 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1258 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1259 smb2_opcode_name(opcode
),
1260 (unsigned long long)mid
));
1262 if (get_Protocol() >= PROTOCOL_SMB2
) {
1264 * once the protocol is negotiated
1265 * SMB2_OP_NEGPROT is not allowed anymore
1267 if (opcode
== SMB2_OP_NEGPROT
) {
1268 /* drop the connection */
1269 return NT_STATUS_INVALID_PARAMETER
;
1273 * if the protocol is not negotiated yet
1274 * only SMB2_OP_NEGPROT is allowed.
1276 if (opcode
!= SMB2_OP_NEGPROT
) {
1277 /* drop the connection */
1278 return NT_STATUS_INVALID_PARAMETER
;
1282 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
1283 SMB2_HDR_FLAG_SIGNED
|
1285 if (opcode
== SMB2_OP_CANCEL
) {
1286 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
1288 if ((flags
& ~allowed_flags
) != 0) {
1289 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1293 * Check if the client provided a valid session id,
1294 * if so smbd_smb2_request_check_session() calls
1295 * set_current_user_info().
1297 * As some command don't require a valid session id
1298 * we defer the check of the session_status
1300 session_status
= smbd_smb2_request_check_session(req
);
1302 req
->do_signing
= false;
1303 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
1304 if (!NT_STATUS_IS_OK(session_status
)) {
1305 return smbd_smb2_request_error(req
, session_status
);
1308 req
->do_signing
= true;
1309 status
= smb2_signing_check_pdu(req
->session
->session_key
,
1310 &req
->in
.vector
[i
], 3);
1311 if (!NT_STATUS_IS_OK(status
)) {
1312 return smbd_smb2_request_error(req
, status
);
1314 } else if (opcode
== SMB2_OP_CANCEL
) {
1315 /* Cancel requests are allowed to skip the signing */
1316 } else if (req
->session
&& req
->session
->do_signing
) {
1317 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
1320 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
1322 * This check is mostly for giving the correct error code
1323 * for compounded requests.
1325 * TODO: we may need to move this after the session
1328 if (!NT_STATUS_IS_OK(req
->next_status
)) {
1329 return smbd_smb2_request_error(req
, req
->next_status
);
1332 req
->compat_chain_fsp
= NULL
;
1335 if (req
->compound_related
) {
1336 req
->sconn
->smb2
.compound_related_in_progress
= true;
1340 case SMB2_OP_NEGPROT
:
1341 /* This call needs to be run as root */
1342 change_to_root_user();
1345 START_PROFILE(smb2_negprot
);
1346 return_value
= smbd_smb2_request_process_negprot(req
);
1347 END_PROFILE(smb2_negprot
);
1351 case SMB2_OP_SESSSETUP
:
1352 /* This call needs to be run as root */
1353 change_to_root_user();
1356 START_PROFILE(smb2_sesssetup
);
1357 return_value
= smbd_smb2_request_process_sesssetup(req
);
1358 END_PROFILE(smb2_sesssetup
);
1362 case SMB2_OP_LOGOFF
:
1363 if (!NT_STATUS_IS_OK(session_status
)) {
1364 return_value
= smbd_smb2_request_error(req
, session_status
);
1368 /* This call needs to be run as root */
1369 change_to_root_user();
1372 START_PROFILE(smb2_logoff
);
1373 return_value
= smbd_smb2_request_process_logoff(req
);
1374 END_PROFILE(smb2_logoff
);
1379 if (!NT_STATUS_IS_OK(session_status
)) {
1380 return_value
= smbd_smb2_request_error(req
, session_status
);
1385 * This call needs to be run as root.
1387 * smbd_smb2_request_process_tcon()
1388 * calls make_connection_snum(), which will call
1389 * change_to_user(), when needed.
1391 change_to_root_user();
1394 START_PROFILE(smb2_tcon
);
1395 return_value
= smbd_smb2_request_process_tcon(req
);
1396 END_PROFILE(smb2_tcon
);
1401 if (!NT_STATUS_IS_OK(session_status
)) {
1402 return_value
= smbd_smb2_request_error(req
, session_status
);
1406 * This call needs to be run as user.
1408 * smbd_smb2_request_check_tcon()
1409 * calls change_to_user() on success.
1411 status
= smbd_smb2_request_check_tcon(req
);
1412 if (!NT_STATUS_IS_OK(status
)) {
1413 return_value
= smbd_smb2_request_error(req
, status
);
1416 /* This call needs to be run as root */
1417 change_to_root_user();
1421 START_PROFILE(smb2_tdis
);
1422 return_value
= smbd_smb2_request_process_tdis(req
);
1423 END_PROFILE(smb2_tdis
);
1427 case SMB2_OP_CREATE
:
1428 if (!NT_STATUS_IS_OK(session_status
)) {
1429 return_value
= smbd_smb2_request_error(req
, session_status
);
1433 * This call needs to be run as user.
1435 * smbd_smb2_request_check_tcon()
1436 * calls change_to_user() on success.
1438 status
= smbd_smb2_request_check_tcon(req
);
1439 if (!NT_STATUS_IS_OK(status
)) {
1440 return_value
= smbd_smb2_request_error(req
, status
);
1445 START_PROFILE(smb2_create
);
1446 return_value
= smbd_smb2_request_process_create(req
);
1447 END_PROFILE(smb2_create
);
1452 if (!NT_STATUS_IS_OK(session_status
)) {
1453 return_value
= smbd_smb2_request_error(req
, session_status
);
1457 * This call needs to be run as user.
1459 * smbd_smb2_request_check_tcon()
1460 * calls change_to_user() on success.
1462 status
= smbd_smb2_request_check_tcon(req
);
1463 if (!NT_STATUS_IS_OK(status
)) {
1464 return_value
= smbd_smb2_request_error(req
, status
);
1469 START_PROFILE(smb2_close
);
1470 return_value
= smbd_smb2_request_process_close(req
);
1471 END_PROFILE(smb2_close
);
1476 if (!NT_STATUS_IS_OK(session_status
)) {
1477 return_value
= smbd_smb2_request_error(req
, session_status
);
1481 * This call needs to be run as user.
1483 * smbd_smb2_request_check_tcon()
1484 * calls change_to_user() on success.
1486 status
= smbd_smb2_request_check_tcon(req
);
1487 if (!NT_STATUS_IS_OK(status
)) {
1488 return_value
= smbd_smb2_request_error(req
, status
);
1493 START_PROFILE(smb2_flush
);
1494 return_value
= smbd_smb2_request_process_flush(req
);
1495 END_PROFILE(smb2_flush
);
1500 if (!NT_STATUS_IS_OK(session_status
)) {
1501 return_value
= smbd_smb2_request_error(req
, session_status
);
1505 * This call needs to be run as user.
1507 * smbd_smb2_request_check_tcon()
1508 * calls change_to_user() on success.
1510 status
= smbd_smb2_request_check_tcon(req
);
1511 if (!NT_STATUS_IS_OK(status
)) {
1512 return_value
= smbd_smb2_request_error(req
, status
);
1517 START_PROFILE(smb2_read
);
1518 return_value
= smbd_smb2_request_process_read(req
);
1519 END_PROFILE(smb2_read
);
1524 if (!NT_STATUS_IS_OK(session_status
)) {
1525 return_value
= smbd_smb2_request_error(req
, session_status
);
1529 * This call needs to be run as user.
1531 * smbd_smb2_request_check_tcon()
1532 * calls change_to_user() on success.
1534 status
= smbd_smb2_request_check_tcon(req
);
1535 if (!NT_STATUS_IS_OK(status
)) {
1536 return_value
= smbd_smb2_request_error(req
, status
);
1541 START_PROFILE(smb2_write
);
1542 return_value
= smbd_smb2_request_process_write(req
);
1543 END_PROFILE(smb2_write
);
1548 if (!NT_STATUS_IS_OK(session_status
)) {
1549 /* Too ugly to live ? JRA. */
1550 if (NT_STATUS_EQUAL(session_status
,NT_STATUS_USER_SESSION_DELETED
)) {
1551 session_status
= NT_STATUS_FILE_CLOSED
;
1553 return_value
= smbd_smb2_request_error(req
, session_status
);
1557 * This call needs to be run as user.
1559 * smbd_smb2_request_check_tcon()
1560 * calls change_to_user() on success.
1562 status
= smbd_smb2_request_check_tcon(req
);
1563 if (!NT_STATUS_IS_OK(status
)) {
1564 /* Too ugly to live ? JRA. */
1565 if (NT_STATUS_EQUAL(status
,NT_STATUS_NETWORK_NAME_DELETED
)) {
1566 status
= NT_STATUS_FILE_CLOSED
;
1568 return_value
= smbd_smb2_request_error(req
, status
);
1573 START_PROFILE(smb2_lock
);
1574 return_value
= smbd_smb2_request_process_lock(req
);
1575 END_PROFILE(smb2_lock
);
1580 if (!NT_STATUS_IS_OK(session_status
)) {
1581 return_value
= smbd_smb2_request_error(req
, session_status
);
1585 * This call needs to be run as user.
1587 * smbd_smb2_request_check_tcon()
1588 * calls change_to_user() on success.
1590 status
= smbd_smb2_request_check_tcon(req
);
1591 if (!NT_STATUS_IS_OK(status
)) {
1592 return_value
= smbd_smb2_request_error(req
, status
);
1597 START_PROFILE(smb2_ioctl
);
1598 return_value
= smbd_smb2_request_process_ioctl(req
);
1599 END_PROFILE(smb2_ioctl
);
1603 case SMB2_OP_CANCEL
:
1605 * This call needs to be run as root
1607 * That is what we also do in the SMB1 case.
1609 change_to_root_user();
1612 START_PROFILE(smb2_cancel
);
1613 return_value
= smbd_smb2_request_process_cancel(req
);
1614 END_PROFILE(smb2_cancel
);
1618 case SMB2_OP_KEEPALIVE
:
1619 /* This call needs to be run as root */
1620 change_to_root_user();
1623 START_PROFILE(smb2_keepalive
);
1624 return_value
= smbd_smb2_request_process_keepalive(req
);
1625 END_PROFILE(smb2_keepalive
);
1630 if (!NT_STATUS_IS_OK(session_status
)) {
1631 return_value
= smbd_smb2_request_error(req
, session_status
);
1635 * This call needs to be run as user.
1637 * smbd_smb2_request_check_tcon()
1638 * calls change_to_user() on success.
1640 status
= smbd_smb2_request_check_tcon(req
);
1641 if (!NT_STATUS_IS_OK(status
)) {
1642 return_value
= smbd_smb2_request_error(req
, status
);
1647 START_PROFILE(smb2_find
);
1648 return_value
= smbd_smb2_request_process_find(req
);
1649 END_PROFILE(smb2_find
);
1653 case SMB2_OP_NOTIFY
:
1654 if (!NT_STATUS_IS_OK(session_status
)) {
1655 return_value
= smbd_smb2_request_error(req
, session_status
);
1659 * This call needs to be run as user.
1661 * smbd_smb2_request_check_tcon()
1662 * calls change_to_user() on success.
1664 status
= smbd_smb2_request_check_tcon(req
);
1665 if (!NT_STATUS_IS_OK(status
)) {
1666 return_value
= smbd_smb2_request_error(req
, status
);
1671 START_PROFILE(smb2_notify
);
1672 return_value
= smbd_smb2_request_process_notify(req
);
1673 END_PROFILE(smb2_notify
);
1677 case SMB2_OP_GETINFO
:
1678 if (!NT_STATUS_IS_OK(session_status
)) {
1679 return_value
= smbd_smb2_request_error(req
, session_status
);
1683 * This call needs to be run as user.
1685 * smbd_smb2_request_check_tcon()
1686 * calls change_to_user() on success.
1688 status
= smbd_smb2_request_check_tcon(req
);
1689 if (!NT_STATUS_IS_OK(status
)) {
1690 return_value
= smbd_smb2_request_error(req
, status
);
1695 START_PROFILE(smb2_getinfo
);
1696 return_value
= smbd_smb2_request_process_getinfo(req
);
1697 END_PROFILE(smb2_getinfo
);
1701 case SMB2_OP_SETINFO
:
1702 if (!NT_STATUS_IS_OK(session_status
)) {
1703 return_value
= smbd_smb2_request_error(req
, session_status
);
1707 * This call needs to be run as user.
1709 * smbd_smb2_request_check_tcon()
1710 * calls change_to_user() on success.
1712 status
= smbd_smb2_request_check_tcon(req
);
1713 if (!NT_STATUS_IS_OK(status
)) {
1714 return_value
= smbd_smb2_request_error(req
, status
);
1719 START_PROFILE(smb2_setinfo
);
1720 return_value
= smbd_smb2_request_process_setinfo(req
);
1721 END_PROFILE(smb2_setinfo
);
1726 if (!NT_STATUS_IS_OK(session_status
)) {
1727 return_value
= smbd_smb2_request_error(req
, session_status
);
1731 * This call needs to be run as user.
1733 * smbd_smb2_request_check_tcon()
1734 * calls change_to_user() on success.
1736 status
= smbd_smb2_request_check_tcon(req
);
1737 if (!NT_STATUS_IS_OK(status
)) {
1738 return_value
= smbd_smb2_request_error(req
, status
);
1743 START_PROFILE(smb2_break
);
1744 return_value
= smbd_smb2_request_process_break(req
);
1745 END_PROFILE(smb2_break
);
1750 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1753 return return_value
;
1756 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
1758 struct tevent_req
*subreq
;
1759 int i
= req
->current_idx
;
1763 req
->current_idx
+= 3;
1765 if (req
->current_idx
< req
->out
.vector_count
) {
1767 * We must process the remaining compound
1768 * SMB2 requests before any new incoming SMB2
1769 * requests. This is because incoming SMB2
1770 * requests may include a cancel for a
1771 * compound request we haven't processed
1774 struct tevent_immediate
*im
= tevent_create_immediate(req
);
1776 return NT_STATUS_NO_MEMORY
;
1778 tevent_schedule_immediate(im
,
1779 req
->sconn
->smb2
.event_ctx
,
1780 smbd_smb2_request_dispatch_immediate
,
1782 return NT_STATUS_OK
;
1785 if (req
->compound_related
) {
1786 req
->sconn
->smb2
.compound_related_in_progress
= false;
1789 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
1791 /* Set credit for these operations (zero credits if this
1792 is a final reply for an async operation). */
1793 smb2_calculate_credits(req
, req
);
1795 if (req
->do_signing
) {
1797 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
1798 &req
->out
.vector
[i
], 3);
1799 if (!NT_STATUS_IS_OK(status
)) {
1804 if (DEBUGLEVEL
>= 10) {
1805 dbgtext("smbd_smb2_request_reply: sending...\n");
1806 print_req_vectors(req
);
1809 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1810 if (req
->out
.vector_count
== 4 &&
1811 req
->out
.vector
[3].iov_base
== NULL
&&
1812 req
->out
.vector
[3].iov_len
!= 0) {
1813 /* Dynamic part is NULL. Chop it off,
1814 We're going to send it via sendfile. */
1815 req
->out
.vector_count
-= 1;
1818 subreq
= tstream_writev_queue_send(req
,
1819 req
->sconn
->smb2
.event_ctx
,
1820 req
->sconn
->smb2
.stream
,
1821 req
->sconn
->smb2
.send_queue
,
1823 req
->out
.vector_count
);
1824 if (subreq
== NULL
) {
1825 return NT_STATUS_NO_MEMORY
;
1827 tevent_req_set_callback(subreq
, smbd_smb2_request_writev_done
, req
);
1829 * We're done with this request -
1830 * move it off the "being processed" queue.
1832 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1834 return NT_STATUS_OK
;
1837 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
);
1839 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
1840 struct tevent_immediate
*im
,
1843 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
1844 struct smbd_smb2_request
);
1845 struct smbd_server_connection
*sconn
= req
->sconn
;
1850 if (DEBUGLEVEL
>= 10) {
1851 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1852 req
->current_idx
, req
->in
.vector_count
));
1853 print_req_vectors(req
);
1856 status
= smbd_smb2_request_dispatch(req
);
1857 if (!NT_STATUS_IS_OK(status
)) {
1858 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1862 status
= smbd_smb2_request_next_incoming(sconn
);
1863 if (!NT_STATUS_IS_OK(status
)) {
1864 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1869 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
)
1871 struct smbd_smb2_request
*req
= tevent_req_callback_data(subreq
,
1872 struct smbd_smb2_request
);
1873 struct smbd_server_connection
*sconn
= req
->sconn
;
1878 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1879 TALLOC_FREE(subreq
);
1882 status
= map_nt_error_from_unix(sys_errno
);
1883 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1884 nt_errstr(status
)));
1885 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1889 status
= smbd_smb2_request_next_incoming(sconn
);
1890 if (!NT_STATUS_IS_OK(status
)) {
1891 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1896 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
1898 DATA_BLOB body
, DATA_BLOB
*dyn
,
1899 const char *location
)
1902 int i
= req
->current_idx
;
1903 uint32_t next_command_ofs
;
1905 DEBUG(10,("smbd_smb2_request_done_ex: "
1906 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1907 i
, nt_errstr(status
), (unsigned int)body
.length
,
1909 (unsigned int)(dyn
? dyn
->length
: 0),
1912 if (body
.length
< 2) {
1913 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
1916 if ((body
.length
% 2) != 0) {
1917 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
1920 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
1922 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
1923 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
1925 req
->out
.vector
[i
+1].iov_base
= (void *)body
.data
;
1926 req
->out
.vector
[i
+1].iov_len
= body
.length
;
1929 req
->out
.vector
[i
+2].iov_base
= (void *)dyn
->data
;
1930 req
->out
.vector
[i
+2].iov_len
= dyn
->length
;
1932 req
->out
.vector
[i
+2].iov_base
= NULL
;
1933 req
->out
.vector
[i
+2].iov_len
= 0;
1936 /* see if we need to recalculate the offset to the next response */
1937 if (next_command_ofs
> 0) {
1938 next_command_ofs
= SMB2_HDR_BODY
;
1939 next_command_ofs
+= req
->out
.vector
[i
+1].iov_len
;
1940 next_command_ofs
+= req
->out
.vector
[i
+2].iov_len
;
1943 if ((next_command_ofs
% 8) != 0) {
1944 size_t pad_size
= 8 - (next_command_ofs
% 8);
1945 if (req
->out
.vector
[i
+2].iov_len
== 0) {
1947 * if the dyn buffer is empty
1948 * we can use it to add padding
1952 pad
= talloc_zero_array(req
->out
.vector
,
1955 return smbd_smb2_request_error(req
,
1956 NT_STATUS_NO_MEMORY
);
1959 req
->out
.vector
[i
+2].iov_base
= (void *)pad
;
1960 req
->out
.vector
[i
+2].iov_len
= pad_size
;
1963 * For now we copy the dynamic buffer
1964 * and add the padding to the new buffer
1971 old_size
= req
->out
.vector
[i
+2].iov_len
;
1972 old_dyn
= (uint8_t *)req
->out
.vector
[i
+2].iov_base
;
1974 new_size
= old_size
+ pad_size
;
1975 new_dyn
= talloc_zero_array(req
->out
.vector
,
1977 if (new_dyn
== NULL
) {
1978 return smbd_smb2_request_error(req
,
1979 NT_STATUS_NO_MEMORY
);
1982 memcpy(new_dyn
, old_dyn
, old_size
);
1983 memset(new_dyn
+ old_size
, 0, pad_size
);
1985 req
->out
.vector
[i
+2].iov_base
= (void *)new_dyn
;
1986 req
->out
.vector
[i
+2].iov_len
= new_size
;
1988 next_command_ofs
+= pad_size
;
1991 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
1993 return smbd_smb2_request_reply(req
);
1996 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
1999 const char *location
)
2002 int i
= req
->current_idx
;
2003 uint8_t *outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
2005 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2006 i
, nt_errstr(status
), info
? " +info" : "",
2009 body
.data
= outhdr
+ SMB2_HDR_BODY
;
2011 SSVAL(body
.data
, 0, 9);
2014 SIVAL(body
.data
, 0x04, info
->length
);
2016 /* Allocated size of req->out.vector[i].iov_base
2017 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2018 * 1 byte without having to do an alloc.
2020 info
= talloc_zero_array(req
->out
.vector
,
2024 return NT_STATUS_NO_MEMORY
;
2026 info
->data
= ((uint8_t *)outhdr
) +
2027 OUTVEC_ALLOC_SIZE
- 1;
2029 SCVAL(info
->data
, 0, 0);
2033 * if a request fails, all other remaining
2034 * compounded requests should fail too
2036 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
2038 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
2042 struct smbd_smb2_send_oplock_break_state
{
2043 struct smbd_server_connection
*sconn
;
2044 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x18];
2045 struct iovec vector
;
2048 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
);
2050 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
2051 uint64_t file_id_persistent
,
2052 uint64_t file_id_volatile
,
2053 uint8_t oplock_level
)
2055 struct smbd_smb2_send_oplock_break_state
*state
;
2056 struct tevent_req
*subreq
;
2060 state
= talloc(sconn
, struct smbd_smb2_send_oplock_break_state
);
2061 if (state
== NULL
) {
2062 return NT_STATUS_NO_MEMORY
;
2064 state
->sconn
= sconn
;
2066 state
->vector
.iov_base
= (void *)state
->buf
;
2067 state
->vector
.iov_len
= sizeof(state
->buf
);
2069 _smb2_setlen(state
->buf
, sizeof(state
->buf
) - 4);
2070 hdr
= state
->buf
+ 4;
2071 body
= hdr
+ SMB2_HDR_BODY
;
2073 SIVAL(hdr
, 0, SMB2_MAGIC
);
2074 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
2075 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
2076 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
2077 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
2078 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
2079 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
2080 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
2081 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
2082 SIVAL(hdr
, SMB2_HDR_PID
, 0);
2083 SIVAL(hdr
, SMB2_HDR_TID
, 0);
2084 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
2085 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
2087 SSVAL(body
, 0x00, 0x18);
2089 SCVAL(body
, 0x02, oplock_level
);
2090 SCVAL(body
, 0x03, 0); /* reserved */
2091 SIVAL(body
, 0x04, 0); /* reserved */
2092 SBVAL(body
, 0x08, file_id_persistent
);
2093 SBVAL(body
, 0x10, file_id_volatile
);
2095 subreq
= tstream_writev_queue_send(state
,
2096 sconn
->smb2
.event_ctx
,
2098 sconn
->smb2
.send_queue
,
2100 if (subreq
== NULL
) {
2101 return NT_STATUS_NO_MEMORY
;
2103 tevent_req_set_callback(subreq
,
2104 smbd_smb2_oplock_break_writev_done
,
2107 return NT_STATUS_OK
;
2110 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
)
2112 struct smbd_smb2_send_oplock_break_state
*state
=
2113 tevent_req_callback_data(subreq
,
2114 struct smbd_smb2_send_oplock_break_state
);
2115 struct smbd_server_connection
*sconn
= state
->sconn
;
2119 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
2120 TALLOC_FREE(subreq
);
2122 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
2123 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2130 struct smbd_smb2_request_read_state
{
2132 bool asked_for_header
;
2133 struct smbd_smb2_request
*smb2_req
;
2136 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2138 TALLOC_CTX
*mem_ctx
,
2139 struct iovec
**_vector
,
2141 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
);
2143 static struct tevent_req
*smbd_smb2_request_read_send(TALLOC_CTX
*mem_ctx
,
2144 struct tevent_context
*ev
,
2145 struct smbd_server_connection
*sconn
)
2147 struct tevent_req
*req
;
2148 struct smbd_smb2_request_read_state
*state
;
2149 struct tevent_req
*subreq
;
2151 req
= tevent_req_create(mem_ctx
, &state
,
2152 struct smbd_smb2_request_read_state
);
2157 state
->asked_for_header
= false;
2159 state
->smb2_req
= smbd_smb2_request_allocate(state
);
2160 if (tevent_req_nomem(state
->smb2_req
, req
)) {
2161 return tevent_req_post(req
, ev
);
2163 state
->smb2_req
->sconn
= sconn
;
2165 subreq
= tstream_readv_pdu_queue_send(state
, ev
, sconn
->smb2
.stream
,
2166 sconn
->smb2
.recv_queue
,
2167 smbd_smb2_request_next_vector
,
2169 if (tevent_req_nomem(subreq
, req
)) {
2170 return tevent_req_post(req
, ev
);
2172 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
2177 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2179 TALLOC_CTX
*mem_ctx
,
2180 struct iovec
**_vector
,
2183 struct smbd_smb2_request_read_state
*state
=
2184 talloc_get_type_abort(private_data
,
2185 struct smbd_smb2_request_read_state
);
2186 struct smbd_smb2_request
*req
= state
->smb2_req
;
2187 struct iovec
*vector
;
2188 int idx
= req
->in
.vector_count
;
2190 uint8_t *buf
= NULL
;
2192 if (req
->in
.vector_count
== 0) {
2194 * first we need to get the NBT header
2196 req
->in
.vector
= talloc_array(req
, struct iovec
,
2197 req
->in
.vector_count
+ 1);
2198 if (req
->in
.vector
== NULL
) {
2201 req
->in
.vector_count
+= 1;
2203 req
->in
.vector
[idx
].iov_base
= (void *)req
->in
.nbt_hdr
;
2204 req
->in
.vector
[idx
].iov_len
= 4;
2206 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2207 if (vector
== NULL
) {
2211 vector
[0] = req
->in
.vector
[idx
];
2218 if (req
->in
.vector_count
== 1) {
2220 * Now we analyze the NBT header
2222 state
->missing
= smb2_len(req
->in
.vector
[0].iov_base
);
2224 if (state
->missing
== 0) {
2225 /* if there're no remaining bytes, we're done */
2231 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2233 req
->in
.vector_count
+ 1);
2234 if (req
->in
.vector
== NULL
) {
2237 req
->in
.vector_count
+= 1;
2239 if (CVAL(req
->in
.vector
[0].iov_base
, 0) != 0) {
2241 * it's a special NBT message,
2242 * so get all remaining bytes
2244 len
= state
->missing
;
2245 } else if (state
->missing
< (SMB2_HDR_BODY
+ 2)) {
2247 * it's an invalid message, just read what we can get
2248 * and let the caller handle the error
2250 len
= state
->missing
;
2253 * We assume it's a SMB2 request,
2254 * and we first get the header and the
2255 * first 2 bytes (the struct size) of the body
2257 len
= SMB2_HDR_BODY
+ 2;
2259 state
->asked_for_header
= true;
2262 state
->missing
-= len
;
2264 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2269 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2270 req
->in
.vector
[idx
].iov_len
= len
;
2272 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2273 if (vector
== NULL
) {
2277 vector
[0] = req
->in
.vector
[idx
];
2284 if (state
->missing
== 0) {
2285 /* if there're no remaining bytes, we're done */
2291 if (state
->asked_for_header
) {
2294 size_t next_command_ofs
;
2299 bool invalid
= false;
2301 state
->asked_for_header
= false;
2304 * We got the SMB2 header and the first 2 bytes
2305 * of the body. We fix the size to just the header
2306 * and manually copy the 2 first bytes to the body section
2308 req
->in
.vector
[idx
-1].iov_len
= SMB2_HDR_BODY
;
2309 hdr
= (const uint8_t *)req
->in
.vector
[idx
-1].iov_base
;
2311 /* allocate vectors for body and dynamic areas */
2312 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2314 req
->in
.vector_count
+ 2);
2315 if (req
->in
.vector
== NULL
) {
2318 req
->in
.vector_count
+= 2;
2320 full_size
= state
->missing
+ SMB2_HDR_BODY
+ 2;
2321 next_command_ofs
= IVAL(hdr
, SMB2_HDR_NEXT_COMMAND
);
2322 body_size
= SVAL(hdr
, SMB2_HDR_BODY
);
2324 if (next_command_ofs
!= 0) {
2325 if (next_command_ofs
< (SMB2_HDR_BODY
+ 2)) {
2327 * this is invalid, just return a zero
2328 * body and let the caller deal with the error
2331 } else if (next_command_ofs
> full_size
) {
2333 * this is invalid, just return a zero
2334 * body and let the caller deal with the error
2338 full_size
= next_command_ofs
;
2343 if (body_size
< 2) {
2345 * this is invalid, just return a zero
2346 * body and let the caller deal with the error
2351 if ((body_size
% 2) != 0) {
2355 if (body_size
> (full_size
- SMB2_HDR_BODY
)) {
2357 * this is invalid, just return a zero
2358 * body and let the caller deal with the error
2365 /* the caller should check this */
2369 dyn_size
= full_size
- (SMB2_HDR_BODY
+ body_size
);
2371 state
->missing
-= (body_size
- 2) + dyn_size
;
2373 body
= talloc_array(req
->in
.vector
, uint8_t, body_size
);
2378 dyn
= talloc_array(req
->in
.vector
, uint8_t, dyn_size
);
2383 req
->in
.vector
[idx
].iov_base
= (void *)body
;
2384 req
->in
.vector
[idx
].iov_len
= body_size
;
2385 req
->in
.vector
[idx
+1].iov_base
= (void *)dyn
;
2386 req
->in
.vector
[idx
+1].iov_len
= dyn_size
;
2388 vector
= talloc_array(mem_ctx
, struct iovec
, 2);
2389 if (vector
== NULL
) {
2394 * the first 2 bytes of the body were already fetched
2395 * together with the header
2397 memcpy(body
, hdr
+ SMB2_HDR_BODY
, 2);
2398 vector
[0].iov_base
= body
+ 2;
2399 vector
[0].iov_len
= body_size
- 2;
2401 vector
[1] = req
->in
.vector
[idx
+1];
2409 * when we endup here, we're looking for a new SMB2 request
2410 * next. And we ask for its header and the first 2 bytes of
2411 * the body (like we did for the first SMB2 request).
2414 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2416 req
->in
.vector_count
+ 1);
2417 if (req
->in
.vector
== NULL
) {
2420 req
->in
.vector_count
+= 1;
2423 * We assume it's a SMB2 request,
2424 * and we first get the header and the
2425 * first 2 bytes (the struct size) of the body
2427 len
= SMB2_HDR_BODY
+ 2;
2429 if (len
> state
->missing
) {
2430 /* let the caller handle the error */
2431 len
= state
->missing
;
2434 state
->missing
-= len
;
2435 state
->asked_for_header
= true;
2437 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2442 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2443 req
->in
.vector
[idx
].iov_len
= len
;
2445 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2446 if (vector
== NULL
) {
2450 vector
[0] = req
->in
.vector
[idx
];
2457 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
)
2459 struct tevent_req
*req
=
2460 tevent_req_callback_data(subreq
,
2466 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
2468 status
= map_nt_error_from_unix(sys_errno
);
2469 tevent_req_nterror(req
, status
);
2473 tevent_req_done(req
);
2476 static NTSTATUS
smbd_smb2_request_read_recv(struct tevent_req
*req
,
2477 TALLOC_CTX
*mem_ctx
,
2478 struct smbd_smb2_request
**_smb2_req
)
2480 struct smbd_smb2_request_read_state
*state
=
2481 tevent_req_data(req
,
2482 struct smbd_smb2_request_read_state
);
2485 if (tevent_req_is_nterror(req
, &status
)) {
2486 tevent_req_received(req
);
2490 talloc_steal(mem_ctx
, state
->smb2_req
->mem_pool
);
2491 *_smb2_req
= state
->smb2_req
;
2492 tevent_req_received(req
);
2493 return NT_STATUS_OK
;
2496 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
);
2498 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
)
2500 size_t max_send_queue_len
;
2501 size_t cur_send_queue_len
;
2502 struct tevent_req
*subreq
;
2504 if (sconn
->smb2
.compound_related_in_progress
) {
2506 * Can't read another until the related
2509 return NT_STATUS_OK
;
2512 if (tevent_queue_length(sconn
->smb2
.recv_queue
) > 0) {
2514 * if there is already a smbd_smb2_request_read
2515 * pending, we are done.
2517 return NT_STATUS_OK
;
2520 max_send_queue_len
= MAX(1, sconn
->smb2
.max_credits
/16);
2521 cur_send_queue_len
= tevent_queue_length(sconn
->smb2
.send_queue
);
2523 if (cur_send_queue_len
> max_send_queue_len
) {
2525 * if we have a lot of requests to send,
2526 * we wait until they are on the wire until we
2527 * ask for the next request.
2529 return NT_STATUS_OK
;
2532 /* ask for the next request */
2533 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->smb2
.event_ctx
, sconn
);
2534 if (subreq
== NULL
) {
2535 return NT_STATUS_NO_MEMORY
;
2537 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);
2539 return NT_STATUS_OK
;
2542 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
2543 const uint8_t *inbuf
, size_t size
)
2546 struct smbd_smb2_request
*req
= NULL
;
2548 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2549 (unsigned int)size
));
2551 status
= smbd_initialize_smb2(sconn
);
2552 if (!NT_STATUS_IS_OK(status
)) {
2553 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2557 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
2558 if (!NT_STATUS_IS_OK(status
)) {
2559 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2563 status
= smbd_smb2_request_validate(req
);
2564 if (!NT_STATUS_IS_OK(status
)) {
2565 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2569 status
= smbd_smb2_request_setup_out(req
);
2570 if (!NT_STATUS_IS_OK(status
)) {
2571 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2575 status
= smbd_smb2_request_dispatch(req
);
2576 if (!NT_STATUS_IS_OK(status
)) {
2577 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2581 status
= smbd_smb2_request_next_incoming(sconn
);
2582 if (!NT_STATUS_IS_OK(status
)) {
2583 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2587 sconn
->num_requests
++;
2590 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
)
2592 struct smbd_server_connection
*sconn
= tevent_req_callback_data(subreq
,
2593 struct smbd_server_connection
);
2595 struct smbd_smb2_request
*req
= NULL
;
2597 status
= smbd_smb2_request_read_recv(subreq
, sconn
, &req
);
2598 TALLOC_FREE(subreq
);
2599 if (!NT_STATUS_IS_OK(status
)) {
2600 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2601 nt_errstr(status
)));
2602 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2606 if (req
->in
.nbt_hdr
[0] != 0x00) {
2607 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2608 req
->in
.nbt_hdr
[0]));
2613 req
->current_idx
= 1;
2615 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2616 req
->current_idx
, req
->in
.vector_count
));
2618 status
= smbd_smb2_request_validate(req
);
2619 if (!NT_STATUS_IS_OK(status
)) {
2620 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2624 status
= smbd_smb2_request_setup_out(req
);
2625 if (!NT_STATUS_IS_OK(status
)) {
2626 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2630 status
= smbd_smb2_request_dispatch(req
);
2631 if (!NT_STATUS_IS_OK(status
)) {
2632 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2637 status
= smbd_smb2_request_next_incoming(sconn
);
2638 if (!NT_STATUS_IS_OK(status
)) {
2639 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2643 sconn
->num_requests
++;
2645 /* The timeout_processing function isn't run nearly
2646 often enough to implement 'max log size' without
2647 overrunning the size of the file by many megabytes.
2648 This is especially true if we are running at debug
2649 level 10. Checking every 50 SMB2s is a nice
2650 tradeoff of performance vs log file size overrun. */
2652 if ((sconn
->num_requests
% 50) == 0 &&
2653 need_to_check_log_size()) {
2654 change_to_root_user();