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 DEBUG(11, ("smb2_validate_message_id: mid %llu, credits_granted %llu, "
379 "max_credits %llu, seqnum_low: %llu\n",
380 (unsigned long long) message_id
,
381 (unsigned long long) sconn
->smb2
.credits_granted
,
382 (unsigned long long) sconn
->smb2
.max_credits
,
383 (unsigned long long) sconn
->smb2
.seqnum_low
));
385 if (sconn
->smb2
.credits_granted
< 1) {
386 DEBUG(0, ("smb2_validate_message_id: client used more "
387 "credits than granted, mid %llu, credits_granted %llu, "
388 "max_credits %llu, seqnum_low: %llu\n",
389 (unsigned long long) message_id
,
390 (unsigned long long) sconn
->smb2
.credits_granted
,
391 (unsigned long long) sconn
->smb2
.max_credits
,
392 (unsigned long long) sconn
->smb2
.seqnum_low
));
396 ok
= smb2_validate_sequence_number(sconn
, message_id
, message_id
);
401 /* substract used credits */
402 sconn
->smb2
.credits_granted
-= 1;
407 static NTSTATUS
smbd_smb2_request_validate(struct smbd_smb2_request
*req
)
412 count
= req
->in
.vector_count
;
415 /* It's not a SMB2 request */
416 return NT_STATUS_INVALID_PARAMETER
;
419 for (idx
=1; idx
< count
; idx
+= 3) {
420 const uint8_t *inhdr
= NULL
;
423 if (req
->in
.vector
[idx
].iov_len
!= SMB2_HDR_BODY
) {
424 return NT_STATUS_INVALID_PARAMETER
;
427 if (req
->in
.vector
[idx
+1].iov_len
< 2) {
428 return NT_STATUS_INVALID_PARAMETER
;
431 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
433 /* Check the SMB2 header */
434 if (IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
) != SMB2_MAGIC
) {
435 return NT_STATUS_INVALID_PARAMETER
;
438 if (!smb2_validate_message_id(req
->sconn
, inhdr
)) {
439 return NT_STATUS_INVALID_PARAMETER
;
442 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
445 * the 1st request should never have the
446 * SMB2_HDR_FLAG_CHAINED flag set
448 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
449 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
452 } else if (idx
== 4) {
454 * the 2nd request triggers related vs. unrelated
455 * compounded requests
457 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
458 req
->compound_related
= true;
460 } else if (idx
> 4) {
463 * It seems the this tests are wrong
464 * see the SMB2-COMPOUND test
468 * all other requests should match the 2nd one
470 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
471 if (!req
->compound_related
) {
473 NT_STATUS_INVALID_PARAMETER
;
477 if (req
->compound_related
) {
479 NT_STATUS_INVALID_PARAMETER
;
490 static void smb2_set_operation_credit(struct smbd_server_connection
*sconn
,
491 const struct iovec
*in_vector
,
492 struct iovec
*out_vector
)
494 const uint8_t *inhdr
= (const uint8_t *)in_vector
->iov_base
;
495 uint8_t *outhdr
= (uint8_t *)out_vector
->iov_base
;
496 uint16_t credits_requested
;
498 uint16_t credits_granted
= 0;
500 credits_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
501 out_flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
503 SMB_ASSERT(sconn
->smb2
.max_credits
>= sconn
->smb2
.credits_granted
);
505 if (out_flags
& SMB2_HDR_FLAG_ASYNC
) {
507 * In case we already send an async interim
508 * response, we should not grant
509 * credits on the final response.
511 credits_requested
= 0;
514 if (credits_requested
) {
515 uint16_t modified_credits_requested
;
519 * Split up max_credits into 1/16ths, and then scale
520 * the requested credits by how many 16ths have been
521 * currently granted. Less than 1/16th == grant all
522 * requested (100%), scale down as more have been
523 * granted. Never ask for less than 1 as the client
524 * asked for at least 1. JRA.
527 multiplier
= 16 - (((sconn
->smb2
.credits_granted
* 16) / sconn
->smb2
.max_credits
) % 16);
529 modified_credits_requested
= (multiplier
* credits_requested
) / 16;
530 if (modified_credits_requested
== 0) {
531 modified_credits_requested
= 1;
534 /* Remember what we gave out. */
535 credits_granted
= MIN(modified_credits_requested
,
536 (sconn
->smb2
.max_credits
- sconn
->smb2
.credits_granted
));
539 if (credits_granted
== 0 && sconn
->smb2
.credits_granted
== 0) {
540 /* First negprot packet, or ensure the client credits can
541 never drop to zero. */
545 SSVAL(outhdr
, SMB2_HDR_CREDIT
, credits_granted
);
546 sconn
->smb2
.credits_granted
+= credits_granted
;
548 DEBUG(10,("smb2_set_operation_credit: requested %u, "
549 "granted %u, total granted %u\n",
550 (unsigned int)credits_requested
,
551 (unsigned int)credits_granted
,
552 (unsigned int)sconn
->smb2
.credits_granted
));
555 static void smb2_calculate_credits(const struct smbd_smb2_request
*inreq
,
556 struct smbd_smb2_request
*outreq
)
559 uint16_t total_credits
= 0;
561 count
= outreq
->out
.vector_count
;
563 for (idx
=1; idx
< count
; idx
+= 3) {
564 uint8_t *outhdr
= (uint8_t *)outreq
->out
.vector
[idx
].iov_base
;
565 smb2_set_operation_credit(outreq
->sconn
,
566 &inreq
->in
.vector
[idx
],
567 &outreq
->out
.vector
[idx
]);
568 /* To match Windows, count up what we
570 total_credits
+= SVAL(outhdr
, SMB2_HDR_CREDIT
);
571 /* Set to zero in all but the last reply. */
572 if (idx
+ 3 < count
) {
573 SSVAL(outhdr
, SMB2_HDR_CREDIT
, 0);
575 SSVAL(outhdr
, SMB2_HDR_CREDIT
, total_credits
);
580 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
)
582 struct iovec
*vector
;
586 count
= req
->in
.vector_count
;
587 vector
= talloc_zero_array(req
, struct iovec
, count
);
588 if (vector
== NULL
) {
589 return NT_STATUS_NO_MEMORY
;
592 vector
[0].iov_base
= req
->out
.nbt_hdr
;
593 vector
[0].iov_len
= 4;
594 SIVAL(req
->out
.nbt_hdr
, 0, 0);
596 for (idx
=1; idx
< count
; idx
+= 3) {
597 const uint8_t *inhdr
= NULL
;
599 uint8_t *outhdr
= NULL
;
600 uint8_t *outbody
= NULL
;
601 uint32_t next_command_ofs
= 0;
602 struct iovec
*current
= &vector
[idx
];
604 if ((idx
+ 3) < count
) {
605 /* we have a next command -
606 * setup for the error case. */
607 next_command_ofs
= SMB2_HDR_BODY
+ 9;
610 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
611 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
613 outhdr
= talloc_zero_array(vector
, uint8_t,
615 if (outhdr
== NULL
) {
616 return NT_STATUS_NO_MEMORY
;
619 outbody
= outhdr
+ SMB2_HDR_BODY
;
621 current
[0].iov_base
= (void *)outhdr
;
622 current
[0].iov_len
= SMB2_HDR_BODY
;
624 current
[1].iov_base
= (void *)outbody
;
625 current
[1].iov_len
= 8;
627 current
[2].iov_base
= NULL
;
628 current
[2].iov_len
= 0;
630 /* setup the SMB2 header */
631 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
632 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
633 SSVAL(outhdr
, SMB2_HDR_CREDIT_CHARGE
,
634 SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
));
635 SIVAL(outhdr
, SMB2_HDR_STATUS
,
636 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
637 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
638 SVAL(inhdr
, SMB2_HDR_OPCODE
));
639 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
640 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
641 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
642 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
643 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
644 SIVAL(outhdr
, SMB2_HDR_PID
,
645 IVAL(inhdr
, SMB2_HDR_PID
));
646 SIVAL(outhdr
, SMB2_HDR_TID
,
647 IVAL(inhdr
, SMB2_HDR_TID
));
648 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
649 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
650 memcpy(outhdr
+ SMB2_HDR_SIGNATURE
,
651 inhdr
+ SMB2_HDR_SIGNATURE
, 16);
653 /* setup error body header */
654 SSVAL(outbody
, 0x00, 0x08 + 1);
655 SSVAL(outbody
, 0x02, 0);
656 SIVAL(outbody
, 0x04, 0);
659 req
->out
.vector
= vector
;
660 req
->out
.vector_count
= count
;
662 /* setup the length of the NBT packet */
663 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
665 DLIST_ADD_END(req
->sconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
670 void smbd_server_connection_terminate_ex(struct smbd_server_connection
*sconn
,
672 const char *location
)
674 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
676 exit_server_cleanly(reason
);
679 static bool dup_smb2_vec3(TALLOC_CTX
*ctx
,
680 struct iovec
*outvec
,
681 const struct iovec
*srcvec
)
683 /* vec[0] is always boilerplate and must
684 * be allocated with size OUTVEC_ALLOC_SIZE. */
686 outvec
[0].iov_base
= talloc_memdup(ctx
,
689 if (!outvec
[0].iov_base
) {
692 outvec
[0].iov_len
= SMB2_HDR_BODY
;
695 * If this is a "standard" vec[1] of length 8,
696 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
697 * then duplicate this. Else use talloc_memdup().
700 if (srcvec
[1].iov_len
== 8 &&
701 srcvec
[1].iov_base
==
702 ((uint8_t *)srcvec
[0].iov_base
) +
704 outvec
[1].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
706 outvec
[1].iov_len
= 8;
708 outvec
[1].iov_base
= talloc_memdup(ctx
,
711 if (!outvec
[1].iov_base
) {
714 outvec
[1].iov_len
= srcvec
[1].iov_len
;
718 * If this is a "standard" vec[2] of length 1,
719 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
720 * then duplicate this. Else use talloc_memdup().
723 if (srcvec
[2].iov_base
&&
725 if (srcvec
[2].iov_base
==
726 ((uint8_t *)srcvec
[0].iov_base
) +
727 (OUTVEC_ALLOC_SIZE
- 1) &&
728 srcvec
[2].iov_len
== 1) {
729 /* Common SMB2 error packet case. */
730 outvec
[2].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
731 (OUTVEC_ALLOC_SIZE
- 1);
733 outvec
[2].iov_base
= talloc_memdup(ctx
,
736 if (!outvec
[2].iov_base
) {
740 outvec
[2].iov_len
= srcvec
[2].iov_len
;
742 outvec
[2].iov_base
= NULL
;
743 outvec
[2].iov_len
= 0;
748 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
750 struct smbd_smb2_request
*newreq
= NULL
;
751 struct iovec
*outvec
= NULL
;
752 int count
= req
->out
.vector_count
;
755 newreq
= smbd_smb2_request_allocate(req
->sconn
);
760 newreq
->sconn
= req
->sconn
;
761 newreq
->session
= req
->session
;
762 newreq
->do_signing
= req
->do_signing
;
763 newreq
->current_idx
= req
->current_idx
;
764 newreq
->async
= false;
765 newreq
->cancelled
= false;
766 /* Note we are leaving:
770 uninitialized as NULL here as
771 they're not used in the interim
772 response code. JRA. */
774 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
779 newreq
->out
.vector
= outvec
;
780 newreq
->out
.vector_count
= count
;
782 /* Setup the outvec's identically to req. */
783 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
784 outvec
[0].iov_len
= 4;
785 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
787 /* Setup the vectors identically to the ones in req. */
788 for (i
= 1; i
< count
; i
+= 3) {
789 if (!dup_smb2_vec3(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
800 smb2_setup_nbt_length(newreq
->out
.vector
,
801 newreq
->out
.vector_count
);
806 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
);
808 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
811 uint8_t *outhdr
= NULL
;
812 struct smbd_smb2_request
*nreq
= NULL
;
814 /* Create a new smb2 request we'll use
815 for the interim return. */
816 nreq
= dup_smb2_req(req
);
818 return NT_STATUS_NO_MEMORY
;
821 /* Lose the last 3 out vectors. They're the
822 ones we'll be using for the async reply. */
823 nreq
->out
.vector_count
-= 3;
825 smb2_setup_nbt_length(nreq
->out
.vector
,
826 nreq
->out
.vector_count
);
828 /* Step back to the previous reply. */
829 i
= nreq
->current_idx
- 3;
830 outhdr
= (uint8_t *)nreq
->out
.vector
[i
].iov_base
;
831 /* And end the chain. */
832 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
834 /* Calculate outgoing credits */
835 smb2_calculate_credits(req
, nreq
);
837 /* Re-sign if needed. */
838 if (nreq
->do_signing
) {
840 status
= smb2_signing_sign_pdu(nreq
->session
->session_key
,
841 &nreq
->out
.vector
[i
], 3);
842 if (!NT_STATUS_IS_OK(status
)) {
846 if (DEBUGLEVEL
>= 10) {
847 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
848 (unsigned int)nreq
->current_idx
);
849 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
850 (unsigned int)nreq
->out
.vector_count
);
851 print_req_vectors(nreq
);
853 nreq
->subreq
= tstream_writev_queue_send(nreq
,
854 nreq
->sconn
->smb2
.event_ctx
,
855 nreq
->sconn
->smb2
.stream
,
856 nreq
->sconn
->smb2
.send_queue
,
858 nreq
->out
.vector_count
);
860 if (nreq
->subreq
== NULL
) {
861 return NT_STATUS_NO_MEMORY
;
864 tevent_req_set_callback(nreq
->subreq
,
865 smbd_smb2_request_writev_done
,
871 struct smbd_smb2_request_pending_state
{
872 struct smbd_server_connection
*sconn
;
873 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x08 + 1];
874 struct iovec vector
[3];
877 static void smbd_smb2_request_pending_writev_done(struct tevent_req
*subreq
)
879 struct smbd_smb2_request_pending_state
*state
=
880 tevent_req_callback_data(subreq
,
881 struct smbd_smb2_request_pending_state
);
882 struct smbd_server_connection
*sconn
= state
->sconn
;
886 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
889 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
890 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
897 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
898 struct tevent_req
*subreq
)
901 struct smbd_smb2_request_pending_state
*state
= NULL
;
902 int i
= req
->current_idx
;
903 uint8_t *reqhdr
= NULL
;
905 uint8_t *body
= NULL
;
907 uint64_t message_id
= 0;
908 uint64_t async_id
= 0;
909 struct iovec
*outvec
= NULL
;
911 if (!tevent_req_is_in_progress(subreq
)) {
915 req
->subreq
= subreq
;
919 /* We're already async. */
923 if (req
->in
.vector_count
> i
+ 3) {
925 * We're trying to go async in a compound
926 * request chain. This is not allowed.
927 * Cancel the outstanding request.
929 tevent_req_cancel(req
->subreq
);
930 return smbd_smb2_request_error(req
,
931 NT_STATUS_INSUFFICIENT_RESOURCES
);
934 if (DEBUGLEVEL
>= 10) {
935 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
936 (unsigned int)req
->current_idx
);
937 print_req_vectors(req
);
940 if (req
->out
.vector_count
> 4) {
941 /* This is a compound reply. We
942 * must do an interim response
943 * followed by the async response
946 status
= smb2_send_async_interim_response(req
);
947 if (!NT_STATUS_IS_OK(status
)) {
952 * We're splitting off the last SMB2
953 * request in a compound set, and the
954 * smb2_send_async_interim_response()
955 * call above just sent all the replies
956 * for the previous SMB2 requests in
957 * this compound set. So we're no longer
958 * in the "compound_related_in_progress"
959 * state, and this is no longer a compound
962 req
->compound_related
= false;
963 req
->sconn
->smb2
.compound_related_in_progress
= false;
966 /* Don't return an intermediate packet on a pipe read/write. */
967 if (req
->tcon
&& req
->tcon
->compat_conn
&& IS_IPC(req
->tcon
->compat_conn
)) {
971 reqhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
972 flags
= (IVAL(reqhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
973 message_id
= BVAL(reqhdr
, SMB2_HDR_MESSAGE_ID
);
974 async_id
= message_id
; /* keep it simple for now... */
977 * What we send is identical to a smbd_smb2_request_error
978 * packet with an error status of STATUS_PENDING. Make use
979 * of this fact sometime when refactoring. JRA.
982 state
= talloc_zero(req
->sconn
, struct smbd_smb2_request_pending_state
);
984 return NT_STATUS_NO_MEMORY
;
986 state
->sconn
= req
->sconn
;
988 state
->vector
[0].iov_base
= (void *)state
->buf
;
989 state
->vector
[0].iov_len
= 4;
991 state
->vector
[1].iov_base
= state
->buf
+ 4;
992 state
->vector
[1].iov_len
= SMB2_HDR_BODY
;
994 state
->vector
[2].iov_base
= state
->buf
+ 4 + SMB2_HDR_BODY
;
995 state
->vector
[2].iov_len
= 9;
997 smb2_setup_nbt_length(state
->vector
, 3);
999 hdr
= (uint8_t *)state
->vector
[1].iov_base
;
1000 body
= (uint8_t *)state
->vector
[2].iov_base
;
1002 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
1003 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1004 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1005 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
1006 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(reqhdr
, SMB2_HDR_OPCODE
));
1008 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
);
1009 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1010 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
1011 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
1012 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
1013 BVAL(reqhdr
, SMB2_HDR_SESSION_ID
));
1014 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
1016 SSVAL(body
, 0x00, 0x08 + 1);
1018 SCVAL(body
, 0x02, 0);
1019 SCVAL(body
, 0x03, 0);
1020 SIVAL(body
, 0x04, 0);
1021 /* Match W2K8R2... */
1022 SCVAL(body
, 0x08, 0x21);
1024 /* Ensure we correctly go through crediting. Grant
1025 the credits now, and zero credits on the final
1027 smb2_set_operation_credit(req
->sconn
,
1031 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1033 if (req
->do_signing
) {
1034 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
1035 &state
->vector
[1], 2);
1036 if (!NT_STATUS_IS_OK(status
)) {
1041 subreq
= tstream_writev_queue_send(state
,
1042 req
->sconn
->smb2
.event_ctx
,
1043 req
->sconn
->smb2
.stream
,
1044 req
->sconn
->smb2
.send_queue
,
1048 if (subreq
== NULL
) {
1049 return NT_STATUS_NO_MEMORY
;
1052 tevent_req_set_callback(subreq
,
1053 smbd_smb2_request_pending_writev_done
,
1056 /* Note we're going async with this request. */
1062 * Now manipulate req so that the outstanding async request
1063 * is the only one left in the struct smbd_smb2_request.
1066 if (req
->current_idx
== 1) {
1067 /* There was only one. */
1071 /* Re-arrange the in.vectors. */
1072 req
->in
.vector
[1] = req
->in
.vector
[i
];
1073 req
->in
.vector
[2] = req
->in
.vector
[i
+1];
1074 req
->in
.vector
[3] = req
->in
.vector
[i
+2];
1075 req
->in
.vector_count
= 4;
1076 /* Reset the new in size. */
1077 smb2_setup_nbt_length(req
->in
.vector
, 4);
1079 /* Now recreate the out.vectors. */
1080 outvec
= talloc_zero_array(req
, struct iovec
, 4);
1082 return NT_STATUS_NO_MEMORY
;
1085 /* 0 is always boilerplate and must
1086 * be of size 4 for the length field. */
1088 outvec
[0].iov_base
= req
->out
.nbt_hdr
;
1089 outvec
[0].iov_len
= 4;
1090 SIVAL(req
->out
.nbt_hdr
, 0, 0);
1092 if (!dup_smb2_vec3(outvec
, &outvec
[1], &req
->out
.vector
[i
])) {
1093 return NT_STATUS_NO_MEMORY
;
1096 TALLOC_FREE(req
->out
.vector
);
1098 req
->out
.vector
= outvec
;
1100 req
->current_idx
= 1;
1101 req
->out
.vector_count
= 4;
1105 smb2_setup_nbt_length(req
->out
.vector
,
1106 req
->out
.vector_count
);
1109 /* Ensure our final reply matches the interim one. */
1110 reqhdr
= (uint8_t *)req
->out
.vector
[1].iov_base
;
1111 SIVAL(reqhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1112 SBVAL(reqhdr
, SMB2_HDR_PID
, async_id
);
1115 const uint8_t *inhdr
=
1116 (const uint8_t *)req
->in
.vector
[1].iov_base
;
1117 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1119 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1120 (unsigned long long)async_id
));
1124 return NT_STATUS_OK
;
1127 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
1129 struct smbd_server_connection
*sconn
= req
->sconn
;
1130 struct smbd_smb2_request
*cur
;
1131 const uint8_t *inhdr
;
1132 int i
= req
->current_idx
;
1134 uint64_t search_message_id
;
1135 uint64_t search_async_id
;
1138 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1140 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1141 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1142 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
1145 * we don't need the request anymore
1146 * cancel requests never have a response
1148 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1151 for (cur
= sconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
1152 const uint8_t *outhdr
;
1153 uint64_t message_id
;
1156 i
= cur
->current_idx
;
1158 outhdr
= (const uint8_t *)cur
->out
.vector
[i
].iov_base
;
1160 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1161 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
1163 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1164 if (search_async_id
== async_id
) {
1165 found_id
= async_id
;
1169 if (search_message_id
== message_id
) {
1170 found_id
= message_id
;
1176 if (cur
&& cur
->subreq
) {
1177 inhdr
= (const uint8_t *)cur
->in
.vector
[i
].iov_base
;
1178 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1179 "cancel opcode[%s] mid %llu\n",
1180 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1181 (unsigned long long)found_id
));
1182 tevent_req_cancel(cur
->subreq
);
1185 return NT_STATUS_OK
;
1188 NTSTATUS
smbd_smb2_request_verify_sizes(struct smbd_smb2_request
*req
,
1189 size_t expected_body_size
)
1191 const uint8_t *inhdr
;
1193 const uint8_t *inbody
;
1194 int i
= req
->current_idx
;
1196 size_t min_dyn_size
= expected_body_size
& 0x00000001;
1199 * The following should be checked already.
1201 if ((i
+2) > req
->in
.vector_count
) {
1202 return NT_STATUS_INTERNAL_ERROR
;
1204 if (req
->in
.vector
[i
+0].iov_len
!= SMB2_HDR_BODY
) {
1205 return NT_STATUS_INTERNAL_ERROR
;
1207 if (req
->in
.vector
[i
+1].iov_len
< 2) {
1208 return NT_STATUS_INTERNAL_ERROR
;
1211 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1212 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1216 case SMB2_OP_GETINFO
:
1222 * Now check the expected body size,
1223 * where the last byte might be in the
1224 * dynnamic section..
1226 if (req
->in
.vector
[i
+1].iov_len
!= (expected_body_size
& 0xFFFFFFFE)) {
1227 return NT_STATUS_INVALID_PARAMETER
;
1229 if (req
->in
.vector
[i
+2].iov_len
< min_dyn_size
) {
1230 return NT_STATUS_INVALID_PARAMETER
;
1233 inbody
= (const uint8_t *)req
->in
.vector
[i
+1].iov_base
;
1235 body_size
= SVAL(inbody
, 0x00);
1236 if (body_size
!= expected_body_size
) {
1237 return NT_STATUS_INVALID_PARAMETER
;
1240 return NT_STATUS_OK
;
1243 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
1245 const uint8_t *inhdr
;
1246 int i
= req
->current_idx
;
1251 NTSTATUS session_status
;
1252 uint32_t allowed_flags
;
1253 NTSTATUS return_value
;
1255 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1257 /* TODO: verify more things */
1259 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1260 opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1261 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1262 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1263 smb2_opcode_name(opcode
),
1264 (unsigned long long)mid
));
1266 if (get_Protocol() >= PROTOCOL_SMB2
) {
1268 * once the protocol is negotiated
1269 * SMB2_OP_NEGPROT is not allowed anymore
1271 if (opcode
== SMB2_OP_NEGPROT
) {
1272 /* drop the connection */
1273 return NT_STATUS_INVALID_PARAMETER
;
1277 * if the protocol is not negotiated yet
1278 * only SMB2_OP_NEGPROT is allowed.
1280 if (opcode
!= SMB2_OP_NEGPROT
) {
1281 /* drop the connection */
1282 return NT_STATUS_INVALID_PARAMETER
;
1286 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
1287 SMB2_HDR_FLAG_SIGNED
|
1289 if (opcode
== SMB2_OP_CANCEL
) {
1290 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
1292 if ((flags
& ~allowed_flags
) != 0) {
1293 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1297 * Check if the client provided a valid session id,
1298 * if so smbd_smb2_request_check_session() calls
1299 * set_current_user_info().
1301 * As some command don't require a valid session id
1302 * we defer the check of the session_status
1304 session_status
= smbd_smb2_request_check_session(req
);
1306 req
->do_signing
= false;
1307 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
1308 if (!NT_STATUS_IS_OK(session_status
)) {
1309 return smbd_smb2_request_error(req
, session_status
);
1312 req
->do_signing
= true;
1313 status
= smb2_signing_check_pdu(req
->session
->session_key
,
1314 &req
->in
.vector
[i
], 3);
1315 if (!NT_STATUS_IS_OK(status
)) {
1316 return smbd_smb2_request_error(req
, status
);
1318 } else if (opcode
== SMB2_OP_CANCEL
) {
1319 /* Cancel requests are allowed to skip the signing */
1320 } else if (req
->session
&& req
->session
->do_signing
) {
1321 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
1324 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
1326 * This check is mostly for giving the correct error code
1327 * for compounded requests.
1329 * TODO: we may need to move this after the session
1332 if (!NT_STATUS_IS_OK(req
->next_status
)) {
1333 return smbd_smb2_request_error(req
, req
->next_status
);
1336 req
->compat_chain_fsp
= NULL
;
1339 if (req
->compound_related
) {
1340 req
->sconn
->smb2
.compound_related_in_progress
= true;
1344 case SMB2_OP_NEGPROT
:
1345 /* This call needs to be run as root */
1346 change_to_root_user();
1349 START_PROFILE(smb2_negprot
);
1350 return_value
= smbd_smb2_request_process_negprot(req
);
1351 END_PROFILE(smb2_negprot
);
1355 case SMB2_OP_SESSSETUP
:
1356 /* This call needs to be run as root */
1357 change_to_root_user();
1360 START_PROFILE(smb2_sesssetup
);
1361 return_value
= smbd_smb2_request_process_sesssetup(req
);
1362 END_PROFILE(smb2_sesssetup
);
1366 case SMB2_OP_LOGOFF
:
1367 if (!NT_STATUS_IS_OK(session_status
)) {
1368 return_value
= smbd_smb2_request_error(req
, session_status
);
1372 /* This call needs to be run as root */
1373 change_to_root_user();
1376 START_PROFILE(smb2_logoff
);
1377 return_value
= smbd_smb2_request_process_logoff(req
);
1378 END_PROFILE(smb2_logoff
);
1383 if (!NT_STATUS_IS_OK(session_status
)) {
1384 return_value
= smbd_smb2_request_error(req
, session_status
);
1389 * This call needs to be run as root.
1391 * smbd_smb2_request_process_tcon()
1392 * calls make_connection_snum(), which will call
1393 * change_to_user(), when needed.
1395 change_to_root_user();
1398 START_PROFILE(smb2_tcon
);
1399 return_value
= smbd_smb2_request_process_tcon(req
);
1400 END_PROFILE(smb2_tcon
);
1405 if (!NT_STATUS_IS_OK(session_status
)) {
1406 return_value
= smbd_smb2_request_error(req
, session_status
);
1410 * This call needs to be run as user.
1412 * smbd_smb2_request_check_tcon()
1413 * calls change_to_user() on success.
1415 status
= smbd_smb2_request_check_tcon(req
);
1416 if (!NT_STATUS_IS_OK(status
)) {
1417 return_value
= smbd_smb2_request_error(req
, status
);
1420 /* This call needs to be run as root */
1421 change_to_root_user();
1425 START_PROFILE(smb2_tdis
);
1426 return_value
= smbd_smb2_request_process_tdis(req
);
1427 END_PROFILE(smb2_tdis
);
1431 case SMB2_OP_CREATE
:
1432 if (!NT_STATUS_IS_OK(session_status
)) {
1433 return_value
= smbd_smb2_request_error(req
, session_status
);
1437 * This call needs to be run as user.
1439 * smbd_smb2_request_check_tcon()
1440 * calls change_to_user() on success.
1442 status
= smbd_smb2_request_check_tcon(req
);
1443 if (!NT_STATUS_IS_OK(status
)) {
1444 return_value
= smbd_smb2_request_error(req
, status
);
1449 START_PROFILE(smb2_create
);
1450 return_value
= smbd_smb2_request_process_create(req
);
1451 END_PROFILE(smb2_create
);
1456 if (!NT_STATUS_IS_OK(session_status
)) {
1457 return_value
= smbd_smb2_request_error(req
, session_status
);
1461 * This call needs to be run as user.
1463 * smbd_smb2_request_check_tcon()
1464 * calls change_to_user() on success.
1466 status
= smbd_smb2_request_check_tcon(req
);
1467 if (!NT_STATUS_IS_OK(status
)) {
1468 return_value
= smbd_smb2_request_error(req
, status
);
1473 START_PROFILE(smb2_close
);
1474 return_value
= smbd_smb2_request_process_close(req
);
1475 END_PROFILE(smb2_close
);
1480 if (!NT_STATUS_IS_OK(session_status
)) {
1481 return_value
= smbd_smb2_request_error(req
, session_status
);
1485 * This call needs to be run as user.
1487 * smbd_smb2_request_check_tcon()
1488 * calls change_to_user() on success.
1490 status
= smbd_smb2_request_check_tcon(req
);
1491 if (!NT_STATUS_IS_OK(status
)) {
1492 return_value
= smbd_smb2_request_error(req
, status
);
1497 START_PROFILE(smb2_flush
);
1498 return_value
= smbd_smb2_request_process_flush(req
);
1499 END_PROFILE(smb2_flush
);
1504 if (!NT_STATUS_IS_OK(session_status
)) {
1505 return_value
= smbd_smb2_request_error(req
, session_status
);
1509 * This call needs to be run as user.
1511 * smbd_smb2_request_check_tcon()
1512 * calls change_to_user() on success.
1514 status
= smbd_smb2_request_check_tcon(req
);
1515 if (!NT_STATUS_IS_OK(status
)) {
1516 return_value
= smbd_smb2_request_error(req
, status
);
1521 START_PROFILE(smb2_read
);
1522 return_value
= smbd_smb2_request_process_read(req
);
1523 END_PROFILE(smb2_read
);
1528 if (!NT_STATUS_IS_OK(session_status
)) {
1529 return_value
= smbd_smb2_request_error(req
, session_status
);
1533 * This call needs to be run as user.
1535 * smbd_smb2_request_check_tcon()
1536 * calls change_to_user() on success.
1538 status
= smbd_smb2_request_check_tcon(req
);
1539 if (!NT_STATUS_IS_OK(status
)) {
1540 return_value
= smbd_smb2_request_error(req
, status
);
1545 START_PROFILE(smb2_write
);
1546 return_value
= smbd_smb2_request_process_write(req
);
1547 END_PROFILE(smb2_write
);
1552 if (!NT_STATUS_IS_OK(session_status
)) {
1553 /* Too ugly to live ? JRA. */
1554 if (NT_STATUS_EQUAL(session_status
,NT_STATUS_USER_SESSION_DELETED
)) {
1555 session_status
= NT_STATUS_FILE_CLOSED
;
1557 return_value
= smbd_smb2_request_error(req
, session_status
);
1561 * This call needs to be run as user.
1563 * smbd_smb2_request_check_tcon()
1564 * calls change_to_user() on success.
1566 status
= smbd_smb2_request_check_tcon(req
);
1567 if (!NT_STATUS_IS_OK(status
)) {
1568 /* Too ugly to live ? JRA. */
1569 if (NT_STATUS_EQUAL(status
,NT_STATUS_NETWORK_NAME_DELETED
)) {
1570 status
= NT_STATUS_FILE_CLOSED
;
1572 return_value
= smbd_smb2_request_error(req
, status
);
1577 START_PROFILE(smb2_lock
);
1578 return_value
= smbd_smb2_request_process_lock(req
);
1579 END_PROFILE(smb2_lock
);
1584 if (!NT_STATUS_IS_OK(session_status
)) {
1585 return_value
= smbd_smb2_request_error(req
, session_status
);
1589 * This call needs to be run as user.
1591 * smbd_smb2_request_check_tcon()
1592 * calls change_to_user() on success.
1594 status
= smbd_smb2_request_check_tcon(req
);
1595 if (!NT_STATUS_IS_OK(status
)) {
1596 return_value
= smbd_smb2_request_error(req
, status
);
1601 START_PROFILE(smb2_ioctl
);
1602 return_value
= smbd_smb2_request_process_ioctl(req
);
1603 END_PROFILE(smb2_ioctl
);
1607 case SMB2_OP_CANCEL
:
1609 * This call needs to be run as root
1611 * That is what we also do in the SMB1 case.
1613 change_to_root_user();
1616 START_PROFILE(smb2_cancel
);
1617 return_value
= smbd_smb2_request_process_cancel(req
);
1618 END_PROFILE(smb2_cancel
);
1622 case SMB2_OP_KEEPALIVE
:
1623 /* This call needs to be run as root */
1624 change_to_root_user();
1627 START_PROFILE(smb2_keepalive
);
1628 return_value
= smbd_smb2_request_process_keepalive(req
);
1629 END_PROFILE(smb2_keepalive
);
1634 if (!NT_STATUS_IS_OK(session_status
)) {
1635 return_value
= smbd_smb2_request_error(req
, session_status
);
1639 * This call needs to be run as user.
1641 * smbd_smb2_request_check_tcon()
1642 * calls change_to_user() on success.
1644 status
= smbd_smb2_request_check_tcon(req
);
1645 if (!NT_STATUS_IS_OK(status
)) {
1646 return_value
= smbd_smb2_request_error(req
, status
);
1651 START_PROFILE(smb2_find
);
1652 return_value
= smbd_smb2_request_process_find(req
);
1653 END_PROFILE(smb2_find
);
1657 case SMB2_OP_NOTIFY
:
1658 if (!NT_STATUS_IS_OK(session_status
)) {
1659 return_value
= smbd_smb2_request_error(req
, session_status
);
1663 * This call needs to be run as user.
1665 * smbd_smb2_request_check_tcon()
1666 * calls change_to_user() on success.
1668 status
= smbd_smb2_request_check_tcon(req
);
1669 if (!NT_STATUS_IS_OK(status
)) {
1670 return_value
= smbd_smb2_request_error(req
, status
);
1675 START_PROFILE(smb2_notify
);
1676 return_value
= smbd_smb2_request_process_notify(req
);
1677 END_PROFILE(smb2_notify
);
1681 case SMB2_OP_GETINFO
:
1682 if (!NT_STATUS_IS_OK(session_status
)) {
1683 return_value
= smbd_smb2_request_error(req
, session_status
);
1687 * This call needs to be run as user.
1689 * smbd_smb2_request_check_tcon()
1690 * calls change_to_user() on success.
1692 status
= smbd_smb2_request_check_tcon(req
);
1693 if (!NT_STATUS_IS_OK(status
)) {
1694 return_value
= smbd_smb2_request_error(req
, status
);
1699 START_PROFILE(smb2_getinfo
);
1700 return_value
= smbd_smb2_request_process_getinfo(req
);
1701 END_PROFILE(smb2_getinfo
);
1705 case SMB2_OP_SETINFO
:
1706 if (!NT_STATUS_IS_OK(session_status
)) {
1707 return_value
= smbd_smb2_request_error(req
, session_status
);
1711 * This call needs to be run as user.
1713 * smbd_smb2_request_check_tcon()
1714 * calls change_to_user() on success.
1716 status
= smbd_smb2_request_check_tcon(req
);
1717 if (!NT_STATUS_IS_OK(status
)) {
1718 return_value
= smbd_smb2_request_error(req
, status
);
1723 START_PROFILE(smb2_setinfo
);
1724 return_value
= smbd_smb2_request_process_setinfo(req
);
1725 END_PROFILE(smb2_setinfo
);
1730 if (!NT_STATUS_IS_OK(session_status
)) {
1731 return_value
= smbd_smb2_request_error(req
, session_status
);
1735 * This call needs to be run as user.
1737 * smbd_smb2_request_check_tcon()
1738 * calls change_to_user() on success.
1740 status
= smbd_smb2_request_check_tcon(req
);
1741 if (!NT_STATUS_IS_OK(status
)) {
1742 return_value
= smbd_smb2_request_error(req
, status
);
1747 START_PROFILE(smb2_break
);
1748 return_value
= smbd_smb2_request_process_break(req
);
1749 END_PROFILE(smb2_break
);
1754 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1757 return return_value
;
1760 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
1762 struct tevent_req
*subreq
;
1763 int i
= req
->current_idx
;
1767 req
->current_idx
+= 3;
1769 if (req
->current_idx
< req
->out
.vector_count
) {
1771 * We must process the remaining compound
1772 * SMB2 requests before any new incoming SMB2
1773 * requests. This is because incoming SMB2
1774 * requests may include a cancel for a
1775 * compound request we haven't processed
1778 struct tevent_immediate
*im
= tevent_create_immediate(req
);
1780 return NT_STATUS_NO_MEMORY
;
1782 tevent_schedule_immediate(im
,
1783 req
->sconn
->smb2
.event_ctx
,
1784 smbd_smb2_request_dispatch_immediate
,
1786 return NT_STATUS_OK
;
1789 if (req
->compound_related
) {
1790 req
->sconn
->smb2
.compound_related_in_progress
= false;
1793 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
1795 /* Set credit for these operations (zero credits if this
1796 is a final reply for an async operation). */
1797 smb2_calculate_credits(req
, req
);
1799 if (req
->do_signing
) {
1801 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
1802 &req
->out
.vector
[i
], 3);
1803 if (!NT_STATUS_IS_OK(status
)) {
1808 if (DEBUGLEVEL
>= 10) {
1809 dbgtext("smbd_smb2_request_reply: sending...\n");
1810 print_req_vectors(req
);
1813 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1814 if (req
->out
.vector_count
== 4 &&
1815 req
->out
.vector
[3].iov_base
== NULL
&&
1816 req
->out
.vector
[3].iov_len
!= 0) {
1817 /* Dynamic part is NULL. Chop it off,
1818 We're going to send it via sendfile. */
1819 req
->out
.vector_count
-= 1;
1822 subreq
= tstream_writev_queue_send(req
,
1823 req
->sconn
->smb2
.event_ctx
,
1824 req
->sconn
->smb2
.stream
,
1825 req
->sconn
->smb2
.send_queue
,
1827 req
->out
.vector_count
);
1828 if (subreq
== NULL
) {
1829 return NT_STATUS_NO_MEMORY
;
1831 tevent_req_set_callback(subreq
, smbd_smb2_request_writev_done
, req
);
1833 * We're done with this request -
1834 * move it off the "being processed" queue.
1836 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1838 return NT_STATUS_OK
;
1841 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
);
1843 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
1844 struct tevent_immediate
*im
,
1847 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
1848 struct smbd_smb2_request
);
1849 struct smbd_server_connection
*sconn
= req
->sconn
;
1854 if (DEBUGLEVEL
>= 10) {
1855 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1856 req
->current_idx
, req
->in
.vector_count
));
1857 print_req_vectors(req
);
1860 status
= smbd_smb2_request_dispatch(req
);
1861 if (!NT_STATUS_IS_OK(status
)) {
1862 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1866 status
= smbd_smb2_request_next_incoming(sconn
);
1867 if (!NT_STATUS_IS_OK(status
)) {
1868 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1873 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
)
1875 struct smbd_smb2_request
*req
= tevent_req_callback_data(subreq
,
1876 struct smbd_smb2_request
);
1877 struct smbd_server_connection
*sconn
= req
->sconn
;
1882 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1883 TALLOC_FREE(subreq
);
1886 status
= map_nt_error_from_unix(sys_errno
);
1887 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1888 nt_errstr(status
)));
1889 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1893 status
= smbd_smb2_request_next_incoming(sconn
);
1894 if (!NT_STATUS_IS_OK(status
)) {
1895 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1900 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
1902 DATA_BLOB body
, DATA_BLOB
*dyn
,
1903 const char *location
)
1906 int i
= req
->current_idx
;
1907 uint32_t next_command_ofs
;
1909 DEBUG(10,("smbd_smb2_request_done_ex: "
1910 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1911 i
, nt_errstr(status
), (unsigned int)body
.length
,
1913 (unsigned int)(dyn
? dyn
->length
: 0),
1916 if (body
.length
< 2) {
1917 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
1920 if ((body
.length
% 2) != 0) {
1921 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
1924 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
1926 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
1927 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
1929 req
->out
.vector
[i
+1].iov_base
= (void *)body
.data
;
1930 req
->out
.vector
[i
+1].iov_len
= body
.length
;
1933 req
->out
.vector
[i
+2].iov_base
= (void *)dyn
->data
;
1934 req
->out
.vector
[i
+2].iov_len
= dyn
->length
;
1936 req
->out
.vector
[i
+2].iov_base
= NULL
;
1937 req
->out
.vector
[i
+2].iov_len
= 0;
1940 /* see if we need to recalculate the offset to the next response */
1941 if (next_command_ofs
> 0) {
1942 next_command_ofs
= SMB2_HDR_BODY
;
1943 next_command_ofs
+= req
->out
.vector
[i
+1].iov_len
;
1944 next_command_ofs
+= req
->out
.vector
[i
+2].iov_len
;
1947 if ((next_command_ofs
% 8) != 0) {
1948 size_t pad_size
= 8 - (next_command_ofs
% 8);
1949 if (req
->out
.vector
[i
+2].iov_len
== 0) {
1951 * if the dyn buffer is empty
1952 * we can use it to add padding
1956 pad
= talloc_zero_array(req
->out
.vector
,
1959 return smbd_smb2_request_error(req
,
1960 NT_STATUS_NO_MEMORY
);
1963 req
->out
.vector
[i
+2].iov_base
= (void *)pad
;
1964 req
->out
.vector
[i
+2].iov_len
= pad_size
;
1967 * For now we copy the dynamic buffer
1968 * and add the padding to the new buffer
1975 old_size
= req
->out
.vector
[i
+2].iov_len
;
1976 old_dyn
= (uint8_t *)req
->out
.vector
[i
+2].iov_base
;
1978 new_size
= old_size
+ pad_size
;
1979 new_dyn
= talloc_zero_array(req
->out
.vector
,
1981 if (new_dyn
== NULL
) {
1982 return smbd_smb2_request_error(req
,
1983 NT_STATUS_NO_MEMORY
);
1986 memcpy(new_dyn
, old_dyn
, old_size
);
1987 memset(new_dyn
+ old_size
, 0, pad_size
);
1989 req
->out
.vector
[i
+2].iov_base
= (void *)new_dyn
;
1990 req
->out
.vector
[i
+2].iov_len
= new_size
;
1992 next_command_ofs
+= pad_size
;
1995 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
1997 return smbd_smb2_request_reply(req
);
2000 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
2003 const char *location
)
2006 int i
= req
->current_idx
;
2007 uint8_t *outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
2009 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2010 i
, nt_errstr(status
), info
? " +info" : "",
2013 body
.data
= outhdr
+ SMB2_HDR_BODY
;
2015 SSVAL(body
.data
, 0, 9);
2018 SIVAL(body
.data
, 0x04, info
->length
);
2020 /* Allocated size of req->out.vector[i].iov_base
2021 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2022 * 1 byte without having to do an alloc.
2024 info
= talloc_zero_array(req
->out
.vector
,
2028 return NT_STATUS_NO_MEMORY
;
2030 info
->data
= ((uint8_t *)outhdr
) +
2031 OUTVEC_ALLOC_SIZE
- 1;
2033 SCVAL(info
->data
, 0, 0);
2037 * if a request fails, all other remaining
2038 * compounded requests should fail too
2040 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
2042 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
2046 struct smbd_smb2_send_oplock_break_state
{
2047 struct smbd_server_connection
*sconn
;
2048 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x18];
2049 struct iovec vector
;
2052 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
);
2054 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
2055 uint64_t file_id_persistent
,
2056 uint64_t file_id_volatile
,
2057 uint8_t oplock_level
)
2059 struct smbd_smb2_send_oplock_break_state
*state
;
2060 struct tevent_req
*subreq
;
2064 state
= talloc(sconn
, struct smbd_smb2_send_oplock_break_state
);
2065 if (state
== NULL
) {
2066 return NT_STATUS_NO_MEMORY
;
2068 state
->sconn
= sconn
;
2070 state
->vector
.iov_base
= (void *)state
->buf
;
2071 state
->vector
.iov_len
= sizeof(state
->buf
);
2073 _smb2_setlen(state
->buf
, sizeof(state
->buf
) - 4);
2074 hdr
= state
->buf
+ 4;
2075 body
= hdr
+ SMB2_HDR_BODY
;
2077 SIVAL(hdr
, 0, SMB2_MAGIC
);
2078 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
2079 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
2080 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
2081 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
2082 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
2083 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
2084 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
2085 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
2086 SIVAL(hdr
, SMB2_HDR_PID
, 0);
2087 SIVAL(hdr
, SMB2_HDR_TID
, 0);
2088 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
2089 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
2091 SSVAL(body
, 0x00, 0x18);
2093 SCVAL(body
, 0x02, oplock_level
);
2094 SCVAL(body
, 0x03, 0); /* reserved */
2095 SIVAL(body
, 0x04, 0); /* reserved */
2096 SBVAL(body
, 0x08, file_id_persistent
);
2097 SBVAL(body
, 0x10, file_id_volatile
);
2099 subreq
= tstream_writev_queue_send(state
,
2100 sconn
->smb2
.event_ctx
,
2102 sconn
->smb2
.send_queue
,
2104 if (subreq
== NULL
) {
2105 return NT_STATUS_NO_MEMORY
;
2107 tevent_req_set_callback(subreq
,
2108 smbd_smb2_oplock_break_writev_done
,
2111 return NT_STATUS_OK
;
2114 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
)
2116 struct smbd_smb2_send_oplock_break_state
*state
=
2117 tevent_req_callback_data(subreq
,
2118 struct smbd_smb2_send_oplock_break_state
);
2119 struct smbd_server_connection
*sconn
= state
->sconn
;
2123 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
2124 TALLOC_FREE(subreq
);
2126 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
2127 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2134 struct smbd_smb2_request_read_state
{
2136 bool asked_for_header
;
2137 struct smbd_smb2_request
*smb2_req
;
2140 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2142 TALLOC_CTX
*mem_ctx
,
2143 struct iovec
**_vector
,
2145 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
);
2147 static struct tevent_req
*smbd_smb2_request_read_send(TALLOC_CTX
*mem_ctx
,
2148 struct tevent_context
*ev
,
2149 struct smbd_server_connection
*sconn
)
2151 struct tevent_req
*req
;
2152 struct smbd_smb2_request_read_state
*state
;
2153 struct tevent_req
*subreq
;
2155 req
= tevent_req_create(mem_ctx
, &state
,
2156 struct smbd_smb2_request_read_state
);
2161 state
->asked_for_header
= false;
2163 state
->smb2_req
= smbd_smb2_request_allocate(state
);
2164 if (tevent_req_nomem(state
->smb2_req
, req
)) {
2165 return tevent_req_post(req
, ev
);
2167 state
->smb2_req
->sconn
= sconn
;
2169 subreq
= tstream_readv_pdu_queue_send(state
, ev
, sconn
->smb2
.stream
,
2170 sconn
->smb2
.recv_queue
,
2171 smbd_smb2_request_next_vector
,
2173 if (tevent_req_nomem(subreq
, req
)) {
2174 return tevent_req_post(req
, ev
);
2176 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
2181 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2183 TALLOC_CTX
*mem_ctx
,
2184 struct iovec
**_vector
,
2187 struct smbd_smb2_request_read_state
*state
=
2188 talloc_get_type_abort(private_data
,
2189 struct smbd_smb2_request_read_state
);
2190 struct smbd_smb2_request
*req
= state
->smb2_req
;
2191 struct iovec
*vector
;
2192 int idx
= req
->in
.vector_count
;
2194 uint8_t *buf
= NULL
;
2196 if (req
->in
.vector_count
== 0) {
2198 * first we need to get the NBT header
2200 req
->in
.vector
= talloc_array(req
, struct iovec
,
2201 req
->in
.vector_count
+ 1);
2202 if (req
->in
.vector
== NULL
) {
2205 req
->in
.vector_count
+= 1;
2207 req
->in
.vector
[idx
].iov_base
= (void *)req
->in
.nbt_hdr
;
2208 req
->in
.vector
[idx
].iov_len
= 4;
2210 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2211 if (vector
== NULL
) {
2215 vector
[0] = req
->in
.vector
[idx
];
2222 if (req
->in
.vector_count
== 1) {
2224 * Now we analyze the NBT header
2226 state
->missing
= smb2_len(req
->in
.vector
[0].iov_base
);
2228 if (state
->missing
== 0) {
2229 /* if there're no remaining bytes, we're done */
2235 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2237 req
->in
.vector_count
+ 1);
2238 if (req
->in
.vector
== NULL
) {
2241 req
->in
.vector_count
+= 1;
2243 if (CVAL(req
->in
.vector
[0].iov_base
, 0) != 0) {
2245 * it's a special NBT message,
2246 * so get all remaining bytes
2248 len
= state
->missing
;
2249 } else if (state
->missing
< (SMB2_HDR_BODY
+ 2)) {
2251 * it's an invalid message, just read what we can get
2252 * and let the caller handle the error
2254 len
= state
->missing
;
2257 * We assume it's a SMB2 request,
2258 * and we first get the header and the
2259 * first 2 bytes (the struct size) of the body
2261 len
= SMB2_HDR_BODY
+ 2;
2263 state
->asked_for_header
= true;
2266 state
->missing
-= len
;
2268 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2273 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2274 req
->in
.vector
[idx
].iov_len
= len
;
2276 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2277 if (vector
== NULL
) {
2281 vector
[0] = req
->in
.vector
[idx
];
2288 if (state
->missing
== 0) {
2289 /* if there're no remaining bytes, we're done */
2295 if (state
->asked_for_header
) {
2298 size_t next_command_ofs
;
2303 bool invalid
= false;
2305 state
->asked_for_header
= false;
2308 * We got the SMB2 header and the first 2 bytes
2309 * of the body. We fix the size to just the header
2310 * and manually copy the 2 first bytes to the body section
2312 req
->in
.vector
[idx
-1].iov_len
= SMB2_HDR_BODY
;
2313 hdr
= (const uint8_t *)req
->in
.vector
[idx
-1].iov_base
;
2315 /* allocate vectors for body and dynamic areas */
2316 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2318 req
->in
.vector_count
+ 2);
2319 if (req
->in
.vector
== NULL
) {
2322 req
->in
.vector_count
+= 2;
2324 full_size
= state
->missing
+ SMB2_HDR_BODY
+ 2;
2325 next_command_ofs
= IVAL(hdr
, SMB2_HDR_NEXT_COMMAND
);
2326 body_size
= SVAL(hdr
, SMB2_HDR_BODY
);
2328 if (next_command_ofs
!= 0) {
2329 if (next_command_ofs
< (SMB2_HDR_BODY
+ 2)) {
2331 * this is invalid, just return a zero
2332 * body and let the caller deal with the error
2335 } else if (next_command_ofs
> full_size
) {
2337 * this is invalid, just return a zero
2338 * body and let the caller deal with the error
2342 full_size
= next_command_ofs
;
2347 if (body_size
< 2) {
2349 * this is invalid, just return a zero
2350 * body and let the caller deal with the error
2355 if ((body_size
% 2) != 0) {
2359 if (body_size
> (full_size
- SMB2_HDR_BODY
)) {
2361 * this is invalid, just return a zero
2362 * body and let the caller deal with the error
2369 /* the caller should check this */
2373 dyn_size
= full_size
- (SMB2_HDR_BODY
+ body_size
);
2375 state
->missing
-= (body_size
- 2) + dyn_size
;
2377 body
= talloc_array(req
->in
.vector
, uint8_t, body_size
);
2382 dyn
= talloc_array(req
->in
.vector
, uint8_t, dyn_size
);
2387 req
->in
.vector
[idx
].iov_base
= (void *)body
;
2388 req
->in
.vector
[idx
].iov_len
= body_size
;
2389 req
->in
.vector
[idx
+1].iov_base
= (void *)dyn
;
2390 req
->in
.vector
[idx
+1].iov_len
= dyn_size
;
2392 vector
= talloc_array(mem_ctx
, struct iovec
, 2);
2393 if (vector
== NULL
) {
2398 * the first 2 bytes of the body were already fetched
2399 * together with the header
2401 memcpy(body
, hdr
+ SMB2_HDR_BODY
, 2);
2402 vector
[0].iov_base
= body
+ 2;
2403 vector
[0].iov_len
= body_size
- 2;
2405 vector
[1] = req
->in
.vector
[idx
+1];
2413 * when we endup here, we're looking for a new SMB2 request
2414 * next. And we ask for its header and the first 2 bytes of
2415 * the body (like we did for the first SMB2 request).
2418 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2420 req
->in
.vector_count
+ 1);
2421 if (req
->in
.vector
== NULL
) {
2424 req
->in
.vector_count
+= 1;
2427 * We assume it's a SMB2 request,
2428 * and we first get the header and the
2429 * first 2 bytes (the struct size) of the body
2431 len
= SMB2_HDR_BODY
+ 2;
2433 if (len
> state
->missing
) {
2434 /* let the caller handle the error */
2435 len
= state
->missing
;
2438 state
->missing
-= len
;
2439 state
->asked_for_header
= true;
2441 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2446 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2447 req
->in
.vector
[idx
].iov_len
= len
;
2449 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2450 if (vector
== NULL
) {
2454 vector
[0] = req
->in
.vector
[idx
];
2461 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
)
2463 struct tevent_req
*req
=
2464 tevent_req_callback_data(subreq
,
2470 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
2472 status
= map_nt_error_from_unix(sys_errno
);
2473 tevent_req_nterror(req
, status
);
2477 tevent_req_done(req
);
2480 static NTSTATUS
smbd_smb2_request_read_recv(struct tevent_req
*req
,
2481 TALLOC_CTX
*mem_ctx
,
2482 struct smbd_smb2_request
**_smb2_req
)
2484 struct smbd_smb2_request_read_state
*state
=
2485 tevent_req_data(req
,
2486 struct smbd_smb2_request_read_state
);
2489 if (tevent_req_is_nterror(req
, &status
)) {
2490 tevent_req_received(req
);
2494 talloc_steal(mem_ctx
, state
->smb2_req
->mem_pool
);
2495 *_smb2_req
= state
->smb2_req
;
2496 tevent_req_received(req
);
2497 return NT_STATUS_OK
;
2500 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
);
2502 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
)
2504 size_t max_send_queue_len
;
2505 size_t cur_send_queue_len
;
2506 struct tevent_req
*subreq
;
2508 if (sconn
->smb2
.compound_related_in_progress
) {
2510 * Can't read another until the related
2513 return NT_STATUS_OK
;
2516 if (tevent_queue_length(sconn
->smb2
.recv_queue
) > 0) {
2518 * if there is already a smbd_smb2_request_read
2519 * pending, we are done.
2521 return NT_STATUS_OK
;
2524 max_send_queue_len
= MAX(1, sconn
->smb2
.max_credits
/16);
2525 cur_send_queue_len
= tevent_queue_length(sconn
->smb2
.send_queue
);
2527 if (cur_send_queue_len
> max_send_queue_len
) {
2529 * if we have a lot of requests to send,
2530 * we wait until they are on the wire until we
2531 * ask for the next request.
2533 return NT_STATUS_OK
;
2536 /* ask for the next request */
2537 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->smb2
.event_ctx
, sconn
);
2538 if (subreq
== NULL
) {
2539 return NT_STATUS_NO_MEMORY
;
2541 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);
2543 return NT_STATUS_OK
;
2546 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
2547 const uint8_t *inbuf
, size_t size
)
2550 struct smbd_smb2_request
*req
= NULL
;
2552 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2553 (unsigned int)size
));
2555 status
= smbd_initialize_smb2(sconn
);
2556 if (!NT_STATUS_IS_OK(status
)) {
2557 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2561 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
2562 if (!NT_STATUS_IS_OK(status
)) {
2563 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2567 status
= smbd_smb2_request_validate(req
);
2568 if (!NT_STATUS_IS_OK(status
)) {
2569 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2573 status
= smbd_smb2_request_setup_out(req
);
2574 if (!NT_STATUS_IS_OK(status
)) {
2575 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2579 status
= smbd_smb2_request_dispatch(req
);
2580 if (!NT_STATUS_IS_OK(status
)) {
2581 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2585 status
= smbd_smb2_request_next_incoming(sconn
);
2586 if (!NT_STATUS_IS_OK(status
)) {
2587 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2591 sconn
->num_requests
++;
2594 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
)
2596 struct smbd_server_connection
*sconn
= tevent_req_callback_data(subreq
,
2597 struct smbd_server_connection
);
2599 struct smbd_smb2_request
*req
= NULL
;
2601 status
= smbd_smb2_request_read_recv(subreq
, sconn
, &req
);
2602 TALLOC_FREE(subreq
);
2603 if (!NT_STATUS_IS_OK(status
)) {
2604 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2605 nt_errstr(status
)));
2606 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2610 if (req
->in
.nbt_hdr
[0] != 0x00) {
2611 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2612 req
->in
.nbt_hdr
[0]));
2617 req
->current_idx
= 1;
2619 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2620 req
->current_idx
, req
->in
.vector_count
));
2622 status
= smbd_smb2_request_validate(req
);
2623 if (!NT_STATUS_IS_OK(status
)) {
2624 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2628 status
= smbd_smb2_request_setup_out(req
);
2629 if (!NT_STATUS_IS_OK(status
)) {
2630 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2634 status
= smbd_smb2_request_dispatch(req
);
2635 if (!NT_STATUS_IS_OK(status
)) {
2636 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2641 status
= smbd_smb2_request_next_incoming(sconn
);
2642 if (!NT_STATUS_IS_OK(status
)) {
2643 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2647 sconn
->num_requests
++;
2649 /* The timeout_processing function isn't run nearly
2650 often enough to implement 'max log size' without
2651 overrunning the size of the file by many megabytes.
2652 This is especially true if we are running at debug
2653 level 10. Checking every 50 SMB2s is a nice
2654 tradeoff of performance vs log file size overrun. */
2656 if ((sconn
->num_requests
% 50) == 0 &&
2657 need_to_check_log_size()) {
2658 change_to_root_user();