2 Unix SMB/CIFS implementation.
5 Copyright (C) Stefan Metzmacher 2009
6 Copyright (C) Jeremy Allison 2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../libcli/smb/smb_common.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "../lib/util/tevent_ntstatus.h"
28 #include "smbprofile.h"
29 #include "../lib/util/bitmap.h"
30 #include "../librpc/gen_ndr/krb5pac.h"
33 #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9)
35 static const char *smb2_names
[] = {
57 const char *smb2_opcode_name(uint16_t opcode
)
60 return "Bad SMB2 opcode";
62 return smb2_names
[opcode
];
65 static void print_req_vectors(struct smbd_smb2_request
*req
)
69 for (i
= 0; i
< req
->in
.vector_count
; i
++) {
70 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
72 (unsigned int)req
->in
.vector
[i
].iov_len
);
74 for (i
= 0; i
< req
->out
.vector_count
; i
++) {
75 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
77 (unsigned int)req
->out
.vector
[i
].iov_len
);
81 bool smbd_is_smb2_header(const uint8_t *inbuf
, size_t size
)
83 if (size
< (4 + SMB2_HDR_BODY
)) {
87 if (IVAL(inbuf
, 4) != SMB2_MAGIC
) {
94 static NTSTATUS
smbd_initialize_smb2(struct smbd_server_connection
*sconn
)
99 TALLOC_FREE(sconn
->smb1
.fde
);
101 sconn
->smb2
.event_ctx
= server_event_context();
103 sconn
->smb2
.recv_queue
= tevent_queue_create(sconn
, "smb2 recv queue");
104 if (sconn
->smb2
.recv_queue
== NULL
) {
105 return NT_STATUS_NO_MEMORY
;
108 sconn
->smb2
.send_queue
= tevent_queue_create(sconn
, "smb2 send queue");
109 if (sconn
->smb2
.send_queue
== NULL
) {
110 return NT_STATUS_NO_MEMORY
;
113 sconn
->smb2
.sessions
.idtree
= idr_init(sconn
);
114 if (sconn
->smb2
.sessions
.idtree
== NULL
) {
115 return NT_STATUS_NO_MEMORY
;
117 sconn
->smb2
.sessions
.limit
= 0x0000FFFE;
118 sconn
->smb2
.sessions
.list
= NULL
;
119 sconn
->smb2
.seqnum_low
= 0;
120 sconn
->smb2
.credits_granted
= 0;
121 sconn
->smb2
.max_credits
= lp_smb2_max_credits();
122 sconn
->smb2
.credits_bitmap
= bitmap_talloc(sconn
,
123 DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
*sconn
->smb2
.max_credits
);
124 if (sconn
->smb2
.credits_bitmap
== NULL
) {
125 return NT_STATUS_NO_MEMORY
;
128 ret
= tstream_bsd_existing_socket(sconn
, sconn
->sock
,
129 &sconn
->smb2
.stream
);
131 status
= map_nt_error_from_unix(errno
);
135 /* Ensure child is set to non-blocking mode */
136 set_blocking(sconn
->sock
, false);
140 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
141 #define _smb2_setlen(_buf,len) do { \
142 uint8_t *buf = (uint8_t *)_buf; \
144 buf[1] = ((len)&0xFF0000)>>16; \
145 buf[2] = ((len)&0xFF00)>>8; \
146 buf[3] = (len)&0xFF; \
149 static void smb2_setup_nbt_length(struct iovec
*vector
, int count
)
154 for (i
=1; i
< count
; i
++) {
155 len
+= vector
[i
].iov_len
;
158 _smb2_setlen(vector
[0].iov_base
, len
);
161 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request
**req
)
164 (*req
)->parent
= NULL
;
165 (*req
)->mem_pool
= NULL
;
171 static int smbd_smb2_request_destructor(struct smbd_smb2_request
*req
)
175 talloc_free(req
->mem_pool
);
181 static struct smbd_smb2_request
*smbd_smb2_request_allocate(TALLOC_CTX
*mem_ctx
)
183 TALLOC_CTX
*mem_pool
;
184 struct smbd_smb2_request
**parent
;
185 struct smbd_smb2_request
*req
;
188 /* Enable this to find subtle valgrind errors. */
189 mem_pool
= talloc_init("smbd_smb2_request_allocate");
191 mem_pool
= talloc_pool(mem_ctx
, 8192);
193 if (mem_pool
== NULL
) {
197 parent
= talloc(mem_pool
, struct smbd_smb2_request
*);
198 if (parent
== NULL
) {
199 talloc_free(mem_pool
);
203 req
= talloc_zero(parent
, struct smbd_smb2_request
);
205 talloc_free(mem_pool
);
209 req
->mem_pool
= mem_pool
;
210 req
->parent
= parent
;
212 req
->last_session_id
= UINT64_MAX
;
213 req
->last_tid
= UINT32_MAX
;
215 talloc_set_destructor(parent
, smbd_smb2_request_parent_destructor
);
216 talloc_set_destructor(req
, smbd_smb2_request_destructor
);
221 static NTSTATUS
smbd_smb2_request_create(struct smbd_server_connection
*sconn
,
222 const uint8_t *inbuf
, size_t size
,
223 struct smbd_smb2_request
**_req
)
225 struct smbd_smb2_request
*req
;
226 uint32_t protocol_version
;
227 const uint8_t *inhdr
= NULL
;
230 uint32_t next_command_ofs
;
232 if (size
< (4 + SMB2_HDR_BODY
+ 2)) {
233 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size
));
234 return NT_STATUS_INVALID_PARAMETER
;
239 protocol_version
= IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
);
240 if (protocol_version
!= SMB2_MAGIC
) {
241 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
243 return NT_STATUS_INVALID_PARAMETER
;
246 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
247 if (cmd
!= SMB2_OP_NEGPROT
) {
248 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
250 return NT_STATUS_INVALID_PARAMETER
;
253 next_command_ofs
= IVAL(inhdr
, SMB2_HDR_NEXT_COMMAND
);
254 if (next_command_ofs
!= 0) {
255 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
257 return NT_STATUS_INVALID_PARAMETER
;
260 req
= smbd_smb2_request_allocate(sconn
);
262 return NT_STATUS_NO_MEMORY
;
266 talloc_steal(req
, inbuf
);
268 req
->in
.vector
= talloc_array(req
, struct iovec
, 4);
269 if (req
->in
.vector
== NULL
) {
271 return NT_STATUS_NO_MEMORY
;
273 req
->in
.vector_count
= 4;
275 memcpy(req
->in
.nbt_hdr
, inbuf
, 4);
278 req
->in
.vector
[0].iov_base
= discard_const_p(void, req
->in
.nbt_hdr
);
279 req
->in
.vector
[0].iov_len
= 4;
280 ofs
+= req
->in
.vector
[0].iov_len
;
282 req
->in
.vector
[1].iov_base
= discard_const_p(void, (inbuf
+ ofs
));
283 req
->in
.vector
[1].iov_len
= SMB2_HDR_BODY
;
284 ofs
+= req
->in
.vector
[1].iov_len
;
286 req
->in
.vector
[2].iov_base
= discard_const_p(void, (inbuf
+ ofs
));
287 req
->in
.vector
[2].iov_len
= SVAL(inbuf
, ofs
) & 0xFFFE;
288 ofs
+= req
->in
.vector
[2].iov_len
;
291 return NT_STATUS_INVALID_PARAMETER
;
294 req
->in
.vector
[3].iov_base
= discard_const_p(void, (inbuf
+ ofs
));
295 req
->in
.vector
[3].iov_len
= size
- ofs
;
296 ofs
+= req
->in
.vector
[3].iov_len
;
298 req
->current_idx
= 1;
304 static bool smb2_validate_message_id(struct smbd_server_connection
*sconn
,
305 const uint8_t *inhdr
)
307 uint64_t message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
308 struct bitmap
*credits_bm
= sconn
->smb2
.credits_bitmap
;
309 uint16_t opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
310 unsigned int bitmap_offset
;
312 if (opcode
== SMB2_OP_CANCEL
) {
313 /* SMB2_CANCEL requests by definition resend messageids. */
317 if (message_id
< sconn
->smb2
.seqnum_low
||
318 message_id
> (sconn
->smb2
.seqnum_low
+
319 (sconn
->smb2
.max_credits
* DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
))) {
320 DEBUG(0,("smb2_validate_message_id: bad message_id "
321 "%llu (low = %llu, max = %lu)\n",
322 (unsigned long long)message_id
,
323 (unsigned long long)sconn
->smb2
.seqnum_low
,
324 (unsigned long)sconn
->smb2
.max_credits
));
328 if (sconn
->smb2
.credits_granted
== 0) {
329 DEBUG(0,("smb2_validate_message_id: client used more "
330 "credits than granted message_id (%llu)\n",
331 (unsigned long long)message_id
));
335 /* client just used a credit. */
336 sconn
->smb2
.credits_granted
-= 1;
338 /* Mark the message_id as seen in the bitmap. */
339 bitmap_offset
= (unsigned int)(message_id
%
340 (uint64_t)(sconn
->smb2
.max_credits
* DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
));
341 if (bitmap_query(credits_bm
, bitmap_offset
)) {
342 DEBUG(0,("smb2_validate_message_id: duplicate message_id "
343 "%llu (bm offset %u)\n",
344 (unsigned long long)message_id
,
348 bitmap_set(credits_bm
, bitmap_offset
);
350 if (message_id
== sconn
->smb2
.seqnum_low
+ 1) {
351 /* Move the window forward by all the message_id's
353 while (bitmap_query(credits_bm
, bitmap_offset
)) {
354 DEBUG(10,("smb2_validate_message_id: clearing "
355 "id %llu (position %u) from bitmap\n",
356 (unsigned long long)(sconn
->smb2
.seqnum_low
+ 1),
358 bitmap_clear(credits_bm
, bitmap_offset
);
359 sconn
->smb2
.seqnum_low
+= 1;
360 bitmap_offset
= (bitmap_offset
+ 1) %
361 (sconn
->smb2
.max_credits
* DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
);
368 static NTSTATUS
smbd_smb2_request_validate(struct smbd_smb2_request
*req
)
373 count
= req
->in
.vector_count
;
376 /* It's not a SMB2 request */
377 return NT_STATUS_INVALID_PARAMETER
;
380 for (idx
=1; idx
< count
; idx
+= 3) {
381 const uint8_t *inhdr
= NULL
;
384 if (req
->in
.vector
[idx
].iov_len
!= SMB2_HDR_BODY
) {
385 return NT_STATUS_INVALID_PARAMETER
;
388 if (req
->in
.vector
[idx
+1].iov_len
< 2) {
389 return NT_STATUS_INVALID_PARAMETER
;
392 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
394 /* Check the SMB2 header */
395 if (IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
) != SMB2_MAGIC
) {
396 return NT_STATUS_INVALID_PARAMETER
;
399 if (!smb2_validate_message_id(req
->sconn
, inhdr
)) {
400 return NT_STATUS_INVALID_PARAMETER
;
403 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
406 * the 1st request should never have the
407 * SMB2_HDR_FLAG_CHAINED flag set
409 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
410 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
413 } else if (idx
== 4) {
415 * the 2nd request triggers related vs. unrelated
416 * compounded requests
418 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
419 req
->compound_related
= true;
421 } else if (idx
> 4) {
424 * It seems the this tests are wrong
425 * see the SMB2-COMPOUND test
429 * all other requests should match the 2nd one
431 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
432 if (!req
->compound_related
) {
434 NT_STATUS_INVALID_PARAMETER
;
438 if (req
->compound_related
) {
440 NT_STATUS_INVALID_PARAMETER
;
451 static void smb2_set_operation_credit(struct smbd_server_connection
*sconn
,
452 const struct iovec
*in_vector
,
453 struct iovec
*out_vector
)
455 const uint8_t *inhdr
= (const uint8_t *)in_vector
->iov_base
;
456 uint8_t *outhdr
= (uint8_t *)out_vector
->iov_base
;
457 uint16_t credits_requested
;
459 uint16_t credits_granted
= 0;
461 credits_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
462 out_flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
464 SMB_ASSERT(sconn
->smb2
.max_credits
>= sconn
->smb2
.credits_granted
);
466 if (out_flags
& SMB2_HDR_FLAG_ASYNC
) {
468 * In case we already send an async interim
469 * response, we should not grant
470 * credits on the final response.
472 credits_requested
= 0;
475 if (credits_requested
) {
476 uint16_t modified_credits_requested
;
480 * Split up max_credits into 1/16ths, and then scale
481 * the requested credits by how many 16ths have been
482 * currently granted. Less than 1/16th == grant all
483 * requested (100%), scale down as more have been
484 * granted. Never ask for less than 1 as the client
485 * asked for at least 1. JRA.
488 multiplier
= 16 - (((sconn
->smb2
.credits_granted
* 16) / sconn
->smb2
.max_credits
) % 16);
490 modified_credits_requested
= (multiplier
* credits_requested
) / 16;
491 if (modified_credits_requested
== 0) {
492 modified_credits_requested
= 1;
495 /* Remember what we gave out. */
496 credits_granted
= MIN(modified_credits_requested
,
497 (sconn
->smb2
.max_credits
- sconn
->smb2
.credits_granted
));
500 if (credits_granted
== 0 && sconn
->smb2
.credits_granted
== 0) {
501 /* First negprot packet, or ensure the client credits can
502 never drop to zero. */
506 SSVAL(outhdr
, SMB2_HDR_CREDIT
, credits_granted
);
507 sconn
->smb2
.credits_granted
+= credits_granted
;
509 DEBUG(10,("smb2_set_operation_credit: requested %u, "
510 "granted %u, total granted %u\n",
511 (unsigned int)credits_requested
,
512 (unsigned int)credits_granted
,
513 (unsigned int)sconn
->smb2
.credits_granted
));
516 static void smb2_calculate_credits(const struct smbd_smb2_request
*inreq
,
517 struct smbd_smb2_request
*outreq
)
520 uint16_t total_credits
= 0;
522 count
= outreq
->out
.vector_count
;
524 for (idx
=1; idx
< count
; idx
+= 3) {
525 uint8_t *outhdr
= (uint8_t *)outreq
->out
.vector
[idx
].iov_base
;
526 smb2_set_operation_credit(outreq
->sconn
,
527 &inreq
->in
.vector
[idx
],
528 &outreq
->out
.vector
[idx
]);
529 /* To match Windows, count up what we
531 total_credits
+= SVAL(outhdr
, SMB2_HDR_CREDIT
);
532 /* Set to zero in all but the last reply. */
533 if (idx
+ 3 < count
) {
534 SSVAL(outhdr
, SMB2_HDR_CREDIT
, 0);
536 SSVAL(outhdr
, SMB2_HDR_CREDIT
, total_credits
);
541 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
)
543 struct iovec
*vector
;
547 count
= req
->in
.vector_count
;
548 vector
= talloc_zero_array(req
, struct iovec
, count
);
549 if (vector
== NULL
) {
550 return NT_STATUS_NO_MEMORY
;
553 vector
[0].iov_base
= req
->out
.nbt_hdr
;
554 vector
[0].iov_len
= 4;
555 SIVAL(req
->out
.nbt_hdr
, 0, 0);
557 for (idx
=1; idx
< count
; idx
+= 3) {
558 const uint8_t *inhdr
= NULL
;
560 uint8_t *outhdr
= NULL
;
561 uint8_t *outbody
= NULL
;
562 uint32_t next_command_ofs
= 0;
563 struct iovec
*current
= &vector
[idx
];
565 if ((idx
+ 3) < count
) {
566 /* we have a next command -
567 * setup for the error case. */
568 next_command_ofs
= SMB2_HDR_BODY
+ 9;
571 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
572 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
574 outhdr
= talloc_zero_array(vector
, uint8_t,
576 if (outhdr
== NULL
) {
577 return NT_STATUS_NO_MEMORY
;
580 outbody
= outhdr
+ SMB2_HDR_BODY
;
582 current
[0].iov_base
= (void *)outhdr
;
583 current
[0].iov_len
= SMB2_HDR_BODY
;
585 current
[1].iov_base
= (void *)outbody
;
586 current
[1].iov_len
= 8;
588 current
[2].iov_base
= NULL
;
589 current
[2].iov_len
= 0;
591 /* setup the SMB2 header */
592 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
593 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
594 SSVAL(outhdr
, SMB2_HDR_CREDIT_CHARGE
,
595 SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
));
596 SIVAL(outhdr
, SMB2_HDR_STATUS
,
597 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
598 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
599 SVAL(inhdr
, SMB2_HDR_OPCODE
));
600 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
601 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
602 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
603 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
604 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
605 SIVAL(outhdr
, SMB2_HDR_PID
,
606 IVAL(inhdr
, SMB2_HDR_PID
));
607 SIVAL(outhdr
, SMB2_HDR_TID
,
608 IVAL(inhdr
, SMB2_HDR_TID
));
609 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
610 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
611 memcpy(outhdr
+ SMB2_HDR_SIGNATURE
,
612 inhdr
+ SMB2_HDR_SIGNATURE
, 16);
614 /* setup error body header */
615 SSVAL(outbody
, 0x00, 0x08 + 1);
616 SSVAL(outbody
, 0x02, 0);
617 SIVAL(outbody
, 0x04, 0);
620 req
->out
.vector
= vector
;
621 req
->out
.vector_count
= count
;
623 /* setup the length of the NBT packet */
624 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
626 DLIST_ADD_END(req
->sconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
631 void smbd_server_connection_terminate_ex(struct smbd_server_connection
*sconn
,
633 const char *location
)
635 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
637 exit_server_cleanly(reason
);
640 static bool dup_smb2_vec3(TALLOC_CTX
*ctx
,
641 struct iovec
*outvec
,
642 const struct iovec
*srcvec
)
644 /* vec[0] is always boilerplate and must
645 * be allocated with size OUTVEC_ALLOC_SIZE. */
647 outvec
[0].iov_base
= talloc_memdup(ctx
,
650 if (!outvec
[0].iov_base
) {
653 outvec
[0].iov_len
= SMB2_HDR_BODY
;
656 * If this is a "standard" vec[1] of length 8,
657 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
658 * then duplicate this. Else use talloc_memdup().
661 if (srcvec
[1].iov_len
== 8 &&
662 srcvec
[1].iov_base
==
663 ((uint8_t *)srcvec
[0].iov_base
) +
665 outvec
[1].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
667 outvec
[1].iov_len
= 8;
669 outvec
[1].iov_base
= talloc_memdup(ctx
,
672 if (!outvec
[1].iov_base
) {
675 outvec
[1].iov_len
= srcvec
[1].iov_len
;
679 * If this is a "standard" vec[2] of length 1,
680 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
681 * then duplicate this. Else use talloc_memdup().
684 if (srcvec
[2].iov_base
&&
686 if (srcvec
[2].iov_base
==
687 ((uint8_t *)srcvec
[0].iov_base
) +
688 (OUTVEC_ALLOC_SIZE
- 1) &&
689 srcvec
[2].iov_len
== 1) {
690 /* Common SMB2 error packet case. */
691 outvec
[2].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
692 (OUTVEC_ALLOC_SIZE
- 1);
694 outvec
[2].iov_base
= talloc_memdup(ctx
,
697 if (!outvec
[2].iov_base
) {
701 outvec
[2].iov_len
= srcvec
[2].iov_len
;
703 outvec
[2].iov_base
= NULL
;
704 outvec
[2].iov_len
= 0;
709 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
711 struct smbd_smb2_request
*newreq
= NULL
;
712 struct iovec
*outvec
= NULL
;
713 int count
= req
->out
.vector_count
;
716 newreq
= smbd_smb2_request_allocate(req
->sconn
);
721 newreq
->sconn
= req
->sconn
;
722 newreq
->session
= req
->session
;
723 newreq
->do_signing
= req
->do_signing
;
724 newreq
->current_idx
= req
->current_idx
;
726 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
731 newreq
->out
.vector
= outvec
;
732 newreq
->out
.vector_count
= count
;
734 /* Setup the outvec's identically to req. */
735 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
736 outvec
[0].iov_len
= 4;
737 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
739 /* Setup the vectors identically to the ones in req. */
740 for (i
= 1; i
< count
; i
+= 3) {
741 if (!dup_smb2_vec3(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
752 smb2_setup_nbt_length(newreq
->out
.vector
,
753 newreq
->out
.vector_count
);
758 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
);
760 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
763 uint8_t *outhdr
= NULL
;
764 struct smbd_smb2_request
*nreq
= NULL
;
766 /* Create a new smb2 request we'll use
767 for the interim return. */
768 nreq
= dup_smb2_req(req
);
770 return NT_STATUS_NO_MEMORY
;
773 /* Lose the last 3 out vectors. They're the
774 ones we'll be using for the async reply. */
775 nreq
->out
.vector_count
-= 3;
777 smb2_setup_nbt_length(nreq
->out
.vector
,
778 nreq
->out
.vector_count
);
780 /* Step back to the previous reply. */
781 i
= nreq
->current_idx
- 3;
782 outhdr
= (uint8_t *)nreq
->out
.vector
[i
].iov_base
;
783 /* And end the chain. */
784 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
786 /* Calculate outgoing credits */
787 smb2_calculate_credits(req
, nreq
);
789 /* Re-sign if needed. */
790 if (nreq
->do_signing
) {
792 status
= smb2_signing_sign_pdu(nreq
->session
->session_key
,
793 &nreq
->out
.vector
[i
], 3);
794 if (!NT_STATUS_IS_OK(status
)) {
798 if (DEBUGLEVEL
>= 10) {
799 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
800 (unsigned int)nreq
->current_idx
);
801 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
802 (unsigned int)nreq
->out
.vector_count
);
803 print_req_vectors(nreq
);
805 nreq
->subreq
= tstream_writev_queue_send(nreq
,
806 nreq
->sconn
->smb2
.event_ctx
,
807 nreq
->sconn
->smb2
.stream
,
808 nreq
->sconn
->smb2
.send_queue
,
810 nreq
->out
.vector_count
);
812 if (nreq
->subreq
== NULL
) {
813 return NT_STATUS_NO_MEMORY
;
816 tevent_req_set_callback(nreq
->subreq
,
817 smbd_smb2_request_writev_done
,
823 struct smbd_smb2_request_pending_state
{
824 struct smbd_server_connection
*sconn
;
825 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x08 + 1];
826 struct iovec vector
[3];
829 static void smbd_smb2_request_pending_writev_done(struct tevent_req
*subreq
)
831 struct smbd_smb2_request_pending_state
*state
=
832 tevent_req_callback_data(subreq
,
833 struct smbd_smb2_request_pending_state
);
834 struct smbd_server_connection
*sconn
= state
->sconn
;
838 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
841 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
842 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
849 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
850 struct tevent_timer
*te
,
851 struct timeval current_time
,
854 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
855 struct tevent_req
*subreq
,
859 int i
= req
->current_idx
;
860 struct timeval defer_endtime
;
861 uint8_t *outhdr
= NULL
;
864 if (!tevent_req_is_in_progress(subreq
)) {
868 req
->subreq
= subreq
;
872 /* We're already async. */
876 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
877 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
878 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
879 /* We're already async. */
883 if (req
->in
.vector_count
> i
+ 3) {
885 * We're trying to go async in a compound
886 * request chain. This is not allowed.
887 * Cancel the outstanding request.
889 tevent_req_cancel(req
->subreq
);
890 return smbd_smb2_request_error(req
,
891 NT_STATUS_INSUFFICIENT_RESOURCES
);
894 if (DEBUGLEVEL
>= 10) {
895 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
896 (unsigned int)req
->current_idx
);
897 print_req_vectors(req
);
900 if (req
->out
.vector_count
> 4) {
901 struct iovec
*outvec
= NULL
;
903 /* This is a compound reply. We
904 * must do an interim response
905 * followed by the async response
908 status
= smb2_send_async_interim_response(req
);
909 if (!NT_STATUS_IS_OK(status
)) {
914 * We're splitting off the last SMB2
915 * request in a compound set, and the
916 * smb2_send_async_interim_response()
917 * call above just sent all the replies
918 * for the previous SMB2 requests in
919 * this compound set. So we're no longer
920 * in the "compound_related_in_progress"
921 * state, and this is no longer a compound
924 req
->compound_related
= false;
925 req
->sconn
->smb2
.compound_related_in_progress
= false;
927 /* Re-arrange the in.vectors. */
928 req
->in
.vector
[1] = req
->in
.vector
[i
];
929 req
->in
.vector
[2] = req
->in
.vector
[i
+1];
930 req
->in
.vector
[3] = req
->in
.vector
[i
+2];
931 req
->in
.vector_count
= 4;
933 /* Reset the new in size. */
934 smb2_setup_nbt_length(req
->in
.vector
, 4);
936 /* Now recreate the out.vectors. */
937 outvec
= talloc_zero_array(req
, struct iovec
, 4);
939 return NT_STATUS_NO_MEMORY
;
942 /* 0 is always boilerplate and must
943 * be of size 4 for the length field. */
945 outvec
[0].iov_base
= req
->out
.nbt_hdr
;
946 outvec
[0].iov_len
= 4;
947 SIVAL(req
->out
.nbt_hdr
, 0, 0);
949 if (!dup_smb2_vec3(outvec
, &outvec
[1], &req
->out
.vector
[i
])) {
950 return NT_STATUS_NO_MEMORY
;
953 TALLOC_FREE(req
->out
.vector
);
955 req
->out
.vector
= outvec
;
957 req
->current_idx
= 1;
958 req
->out
.vector_count
= 4;
960 outhdr
= (uint8_t *)req
->out
.vector
[1].iov_base
;
961 flags
= (IVAL(outhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
962 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
);
965 defer_endtime
= timeval_current_ofs_usec(defer_time
);
966 req
->async_te
= tevent_add_timer(req
->sconn
->smb2
.event_ctx
,
968 smbd_smb2_request_pending_timer
,
970 if (req
->async_te
== NULL
) {
971 return NT_STATUS_NO_MEMORY
;
977 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
978 struct tevent_timer
*te
,
979 struct timeval current_time
,
982 struct smbd_smb2_request
*req
=
983 talloc_get_type_abort(private_data
,
984 struct smbd_smb2_request
);
985 struct smbd_smb2_request_pending_state
*state
= NULL
;
986 int i
= req
->current_idx
;
987 uint8_t *outhdr
= NULL
;
988 const uint8_t *inhdr
= NULL
;
990 uint8_t *body
= NULL
;
992 uint64_t message_id
= 0;
993 uint64_t async_id
= 0;
994 struct tevent_req
*subreq
= NULL
;
996 TALLOC_FREE(req
->async_te
);
998 /* Ensure our final reply matches the interim one. */
999 inhdr
= (const uint8_t *)req
->in
.vector
[1].iov_base
;
1000 outhdr
= (uint8_t *)req
->out
.vector
[1].iov_base
;
1001 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1002 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1004 async_id
= message_id
; /* keep it simple for now... */
1006 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1007 SBVAL(outhdr
, SMB2_HDR_ASYNC_ID
, async_id
);
1009 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1011 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1012 (unsigned long long)async_id
));
1015 * What we send is identical to a smbd_smb2_request_error
1016 * packet with an error status of STATUS_PENDING. Make use
1017 * of this fact sometime when refactoring. JRA.
1020 state
= talloc_zero(req
->sconn
, struct smbd_smb2_request_pending_state
);
1021 if (state
== NULL
) {
1022 smbd_server_connection_terminate(req
->sconn
,
1023 nt_errstr(NT_STATUS_NO_MEMORY
));
1026 state
->sconn
= req
->sconn
;
1028 state
->vector
[0].iov_base
= (void *)state
->buf
;
1029 state
->vector
[0].iov_len
= 4;
1031 state
->vector
[1].iov_base
= state
->buf
+ 4;
1032 state
->vector
[1].iov_len
= SMB2_HDR_BODY
;
1034 state
->vector
[2].iov_base
= state
->buf
+ 4 + SMB2_HDR_BODY
;
1035 state
->vector
[2].iov_len
= 9;
1037 smb2_setup_nbt_length(state
->vector
, 3);
1039 hdr
= (uint8_t *)state
->vector
[1].iov_base
;
1040 body
= (uint8_t *)state
->vector
[2].iov_base
;
1042 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
1043 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1044 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1045 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
1046 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(outhdr
, SMB2_HDR_OPCODE
));
1048 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
);
1049 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1050 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
1051 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
1052 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
1053 BVAL(outhdr
, SMB2_HDR_SESSION_ID
));
1054 memcpy(hdr
+SMB2_HDR_SIGNATURE
,
1055 outhdr
+SMB2_HDR_SIGNATURE
, 16);
1057 SSVAL(body
, 0x00, 0x08 + 1);
1059 SCVAL(body
, 0x02, 0);
1060 SCVAL(body
, 0x03, 0);
1061 SIVAL(body
, 0x04, 0);
1062 /* Match W2K8R2... */
1063 SCVAL(body
, 0x08, 0x21);
1065 /* Ensure we correctly go through crediting. Grant
1066 the credits now, and zero credits on the final
1068 smb2_set_operation_credit(req
->sconn
,
1072 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1074 if (req
->do_signing
) {
1077 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
1078 &state
->vector
[1], 2);
1079 if (!NT_STATUS_IS_OK(status
)) {
1080 smbd_server_connection_terminate(req
->sconn
,
1086 subreq
= tstream_writev_queue_send(state
,
1087 state
->sconn
->smb2
.event_ctx
,
1088 state
->sconn
->smb2
.stream
,
1089 state
->sconn
->smb2
.send_queue
,
1092 if (subreq
== NULL
) {
1093 smbd_server_connection_terminate(state
->sconn
,
1094 nt_errstr(NT_STATUS_NO_MEMORY
));
1097 tevent_req_set_callback(subreq
,
1098 smbd_smb2_request_pending_writev_done
,
1102 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
1104 struct smbd_server_connection
*sconn
= req
->sconn
;
1105 struct smbd_smb2_request
*cur
;
1106 const uint8_t *inhdr
;
1107 int i
= req
->current_idx
;
1109 uint64_t search_message_id
;
1110 uint64_t search_async_id
;
1113 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1115 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1116 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1117 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
1120 * we don't need the request anymore
1121 * cancel requests never have a response
1123 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1126 for (cur
= sconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
1127 const uint8_t *outhdr
;
1128 uint64_t message_id
;
1131 i
= cur
->current_idx
;
1133 outhdr
= (const uint8_t *)cur
->out
.vector
[i
].iov_base
;
1135 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1136 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
1138 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1139 if (search_async_id
== async_id
) {
1140 found_id
= async_id
;
1144 if (search_message_id
== message_id
) {
1145 found_id
= message_id
;
1151 if (cur
&& cur
->subreq
) {
1152 inhdr
= (const uint8_t *)cur
->in
.vector
[i
].iov_base
;
1153 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1154 "cancel opcode[%s] mid %llu\n",
1155 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1156 (unsigned long long)found_id
));
1157 tevent_req_cancel(cur
->subreq
);
1160 return NT_STATUS_OK
;
1163 /*************************************************************
1164 Ensure an incoming tid is a valid one for us to access.
1165 Change to the associated uid credentials and chdir to the
1166 valid tid directory.
1167 *************************************************************/
1169 static NTSTATUS
smbd_smb2_request_check_tcon(struct smbd_smb2_request
*req
)
1171 const uint8_t *inhdr
;
1172 int i
= req
->current_idx
;
1176 struct smbd_smb2_tcon
*tcon
;
1180 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1182 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1183 in_tid
= IVAL(inhdr
, SMB2_HDR_TID
);
1185 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1186 in_tid
= req
->last_tid
;
1189 /* lookup an existing session */
1190 p
= idr_find(req
->session
->tcons
.idtree
, in_tid
);
1192 return NT_STATUS_NETWORK_NAME_DELETED
;
1194 tcon
= talloc_get_type_abort(p
, struct smbd_smb2_tcon
);
1196 if (!change_to_user(tcon
->compat_conn
,req
->session
->vuid
)) {
1197 return NT_STATUS_ACCESS_DENIED
;
1200 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1201 if (!set_current_service(tcon
->compat_conn
, 0, true)) {
1202 return NT_STATUS_ACCESS_DENIED
;
1206 req
->last_tid
= in_tid
;
1208 return NT_STATUS_OK
;
1211 /*************************************************************
1212 Ensure an incoming session_id is a valid one for us to access.
1213 *************************************************************/
1215 static NTSTATUS
smbd_smb2_request_check_session(struct smbd_smb2_request
*req
)
1217 const uint8_t *inhdr
;
1218 int i
= req
->current_idx
;
1220 uint64_t in_session_id
;
1222 struct smbd_smb2_session
*session
;
1224 req
->session
= NULL
;
1227 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1229 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1230 in_session_id
= BVAL(inhdr
, SMB2_HDR_SESSION_ID
);
1232 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1233 in_session_id
= req
->last_session_id
;
1236 /* lookup an existing session */
1237 p
= idr_find(req
->sconn
->smb2
.sessions
.idtree
, in_session_id
);
1239 return NT_STATUS_USER_SESSION_DELETED
;
1241 session
= talloc_get_type_abort(p
, struct smbd_smb2_session
);
1243 if (!NT_STATUS_IS_OK(session
->status
)) {
1244 return NT_STATUS_ACCESS_DENIED
;
1247 set_current_user_info(session
->session_info
->unix_info
->sanitized_username
,
1248 session
->session_info
->unix_info
->unix_name
,
1249 session
->session_info
->info
->domain_name
);
1251 req
->session
= session
;
1252 req
->last_session_id
= in_session_id
;
1254 return NT_STATUS_OK
;
1257 NTSTATUS
smbd_smb2_request_verify_sizes(struct smbd_smb2_request
*req
,
1258 size_t expected_body_size
)
1260 const uint8_t *inhdr
;
1262 const uint8_t *inbody
;
1263 int i
= req
->current_idx
;
1265 size_t min_dyn_size
= expected_body_size
& 0x00000001;
1268 * The following should be checked already.
1270 if ((i
+2) > req
->in
.vector_count
) {
1271 return NT_STATUS_INTERNAL_ERROR
;
1273 if (req
->in
.vector
[i
+0].iov_len
!= SMB2_HDR_BODY
) {
1274 return NT_STATUS_INTERNAL_ERROR
;
1276 if (req
->in
.vector
[i
+1].iov_len
< 2) {
1277 return NT_STATUS_INTERNAL_ERROR
;
1280 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1281 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1285 case SMB2_OP_GETINFO
:
1291 * Now check the expected body size,
1292 * where the last byte might be in the
1293 * dynnamic section..
1295 if (req
->in
.vector
[i
+1].iov_len
!= (expected_body_size
& 0xFFFFFFFE)) {
1296 return NT_STATUS_INVALID_PARAMETER
;
1298 if (req
->in
.vector
[i
+2].iov_len
< min_dyn_size
) {
1299 return NT_STATUS_INVALID_PARAMETER
;
1302 inbody
= (const uint8_t *)req
->in
.vector
[i
+1].iov_base
;
1304 body_size
= SVAL(inbody
, 0x00);
1305 if (body_size
!= expected_body_size
) {
1306 return NT_STATUS_INVALID_PARAMETER
;
1309 return NT_STATUS_OK
;
1312 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
1314 const uint8_t *inhdr
;
1315 int i
= req
->current_idx
;
1320 NTSTATUS session_status
;
1321 uint32_t allowed_flags
;
1322 NTSTATUS return_value
;
1324 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1326 /* TODO: verify more things */
1328 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1329 opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1330 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1331 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1332 smb2_opcode_name(opcode
),
1333 (unsigned long long)mid
));
1335 if (get_Protocol() >= PROTOCOL_SMB2_02
) {
1337 * once the protocol is negotiated
1338 * SMB2_OP_NEGPROT is not allowed anymore
1340 if (opcode
== SMB2_OP_NEGPROT
) {
1341 /* drop the connection */
1342 return NT_STATUS_INVALID_PARAMETER
;
1346 * if the protocol is not negotiated yet
1347 * only SMB2_OP_NEGPROT is allowed.
1349 if (opcode
!= SMB2_OP_NEGPROT
) {
1350 /* drop the connection */
1351 return NT_STATUS_INVALID_PARAMETER
;
1355 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
1356 SMB2_HDR_FLAG_SIGNED
|
1358 if (opcode
== SMB2_OP_CANCEL
) {
1359 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
1361 if ((flags
& ~allowed_flags
) != 0) {
1362 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1366 * Check if the client provided a valid session id,
1367 * if so smbd_smb2_request_check_session() calls
1368 * set_current_user_info().
1370 * As some command don't require a valid session id
1371 * we defer the check of the session_status
1373 session_status
= smbd_smb2_request_check_session(req
);
1375 req
->do_signing
= false;
1376 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
1377 if (!NT_STATUS_IS_OK(session_status
)) {
1378 return smbd_smb2_request_error(req
, session_status
);
1381 req
->do_signing
= true;
1382 status
= smb2_signing_check_pdu(req
->session
->session_key
,
1383 &req
->in
.vector
[i
], 3);
1384 if (!NT_STATUS_IS_OK(status
)) {
1385 return smbd_smb2_request_error(req
, status
);
1387 } else if (opcode
== SMB2_OP_CANCEL
) {
1388 /* Cancel requests are allowed to skip the signing */
1389 } else if (req
->session
&& req
->session
->do_signing
) {
1390 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
1393 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
1395 * This check is mostly for giving the correct error code
1396 * for compounded requests.
1398 * TODO: we may need to move this after the session
1401 if (!NT_STATUS_IS_OK(req
->next_status
)) {
1402 return smbd_smb2_request_error(req
, req
->next_status
);
1405 req
->compat_chain_fsp
= NULL
;
1408 if (req
->compound_related
) {
1409 req
->sconn
->smb2
.compound_related_in_progress
= true;
1413 case SMB2_OP_NEGPROT
:
1414 /* This call needs to be run as root */
1415 change_to_root_user();
1418 START_PROFILE(smb2_negprot
);
1419 return_value
= smbd_smb2_request_process_negprot(req
);
1420 END_PROFILE(smb2_negprot
);
1424 case SMB2_OP_SESSSETUP
:
1425 /* This call needs to be run as root */
1426 change_to_root_user();
1429 START_PROFILE(smb2_sesssetup
);
1430 return_value
= smbd_smb2_request_process_sesssetup(req
);
1431 END_PROFILE(smb2_sesssetup
);
1435 case SMB2_OP_LOGOFF
:
1436 if (!NT_STATUS_IS_OK(session_status
)) {
1437 return_value
= smbd_smb2_request_error(req
, session_status
);
1441 /* This call needs to be run as root */
1442 change_to_root_user();
1445 START_PROFILE(smb2_logoff
);
1446 return_value
= smbd_smb2_request_process_logoff(req
);
1447 END_PROFILE(smb2_logoff
);
1452 if (!NT_STATUS_IS_OK(session_status
)) {
1453 return_value
= smbd_smb2_request_error(req
, session_status
);
1458 * This call needs to be run as root.
1460 * smbd_smb2_request_process_tcon()
1461 * calls make_connection_snum(), which will call
1462 * change_to_user(), when needed.
1464 change_to_root_user();
1467 START_PROFILE(smb2_tcon
);
1468 return_value
= smbd_smb2_request_process_tcon(req
);
1469 END_PROFILE(smb2_tcon
);
1474 if (!NT_STATUS_IS_OK(session_status
)) {
1475 return_value
= smbd_smb2_request_error(req
, session_status
);
1479 * This call needs to be run as user.
1481 * smbd_smb2_request_check_tcon()
1482 * calls change_to_user() on success.
1484 status
= smbd_smb2_request_check_tcon(req
);
1485 if (!NT_STATUS_IS_OK(status
)) {
1486 return_value
= smbd_smb2_request_error(req
, status
);
1489 /* This call needs to be run as root */
1490 change_to_root_user();
1494 START_PROFILE(smb2_tdis
);
1495 return_value
= smbd_smb2_request_process_tdis(req
);
1496 END_PROFILE(smb2_tdis
);
1500 case SMB2_OP_CREATE
:
1501 if (!NT_STATUS_IS_OK(session_status
)) {
1502 return_value
= smbd_smb2_request_error(req
, session_status
);
1506 * This call needs to be run as user.
1508 * smbd_smb2_request_check_tcon()
1509 * calls change_to_user() on success.
1511 status
= smbd_smb2_request_check_tcon(req
);
1512 if (!NT_STATUS_IS_OK(status
)) {
1513 return_value
= smbd_smb2_request_error(req
, status
);
1518 START_PROFILE(smb2_create
);
1519 return_value
= smbd_smb2_request_process_create(req
);
1520 END_PROFILE(smb2_create
);
1525 if (!NT_STATUS_IS_OK(session_status
)) {
1526 return_value
= smbd_smb2_request_error(req
, session_status
);
1530 * This call needs to be run as user.
1532 * smbd_smb2_request_check_tcon()
1533 * calls change_to_user() on success.
1535 status
= smbd_smb2_request_check_tcon(req
);
1536 if (!NT_STATUS_IS_OK(status
)) {
1537 return_value
= smbd_smb2_request_error(req
, status
);
1542 START_PROFILE(smb2_close
);
1543 return_value
= smbd_smb2_request_process_close(req
);
1544 END_PROFILE(smb2_close
);
1549 if (!NT_STATUS_IS_OK(session_status
)) {
1550 return_value
= smbd_smb2_request_error(req
, session_status
);
1554 * This call needs to be run as user.
1556 * smbd_smb2_request_check_tcon()
1557 * calls change_to_user() on success.
1559 status
= smbd_smb2_request_check_tcon(req
);
1560 if (!NT_STATUS_IS_OK(status
)) {
1561 return_value
= smbd_smb2_request_error(req
, status
);
1566 START_PROFILE(smb2_flush
);
1567 return_value
= smbd_smb2_request_process_flush(req
);
1568 END_PROFILE(smb2_flush
);
1573 if (!NT_STATUS_IS_OK(session_status
)) {
1574 return_value
= smbd_smb2_request_error(req
, session_status
);
1578 * This call needs to be run as user.
1580 * smbd_smb2_request_check_tcon()
1581 * calls change_to_user() on success.
1583 status
= smbd_smb2_request_check_tcon(req
);
1584 if (!NT_STATUS_IS_OK(status
)) {
1585 return_value
= smbd_smb2_request_error(req
, status
);
1590 START_PROFILE(smb2_read
);
1591 return_value
= smbd_smb2_request_process_read(req
);
1592 END_PROFILE(smb2_read
);
1597 if (!NT_STATUS_IS_OK(session_status
)) {
1598 return_value
= smbd_smb2_request_error(req
, session_status
);
1602 * This call needs to be run as user.
1604 * smbd_smb2_request_check_tcon()
1605 * calls change_to_user() on success.
1607 status
= smbd_smb2_request_check_tcon(req
);
1608 if (!NT_STATUS_IS_OK(status
)) {
1609 return_value
= smbd_smb2_request_error(req
, status
);
1614 START_PROFILE(smb2_write
);
1615 return_value
= smbd_smb2_request_process_write(req
);
1616 END_PROFILE(smb2_write
);
1621 if (!NT_STATUS_IS_OK(session_status
)) {
1622 /* Too ugly to live ? JRA. */
1623 if (NT_STATUS_EQUAL(session_status
,NT_STATUS_USER_SESSION_DELETED
)) {
1624 session_status
= NT_STATUS_FILE_CLOSED
;
1626 return_value
= smbd_smb2_request_error(req
, session_status
);
1630 * This call needs to be run as user.
1632 * smbd_smb2_request_check_tcon()
1633 * calls change_to_user() on success.
1635 status
= smbd_smb2_request_check_tcon(req
);
1636 if (!NT_STATUS_IS_OK(status
)) {
1637 /* Too ugly to live ? JRA. */
1638 if (NT_STATUS_EQUAL(status
,NT_STATUS_NETWORK_NAME_DELETED
)) {
1639 status
= NT_STATUS_FILE_CLOSED
;
1641 return_value
= smbd_smb2_request_error(req
, status
);
1646 START_PROFILE(smb2_lock
);
1647 return_value
= smbd_smb2_request_process_lock(req
);
1648 END_PROFILE(smb2_lock
);
1653 if (!NT_STATUS_IS_OK(session_status
)) {
1654 return_value
= smbd_smb2_request_error(req
, session_status
);
1658 * This call needs to be run as user.
1660 * smbd_smb2_request_check_tcon()
1661 * calls change_to_user() on success.
1663 status
= smbd_smb2_request_check_tcon(req
);
1664 if (!NT_STATUS_IS_OK(status
)) {
1665 return_value
= smbd_smb2_request_error(req
, status
);
1670 START_PROFILE(smb2_ioctl
);
1671 return_value
= smbd_smb2_request_process_ioctl(req
);
1672 END_PROFILE(smb2_ioctl
);
1676 case SMB2_OP_CANCEL
:
1678 * This call needs to be run as root
1680 * That is what we also do in the SMB1 case.
1682 change_to_root_user();
1685 START_PROFILE(smb2_cancel
);
1686 return_value
= smbd_smb2_request_process_cancel(req
);
1687 END_PROFILE(smb2_cancel
);
1691 case SMB2_OP_KEEPALIVE
:
1692 /* This call needs to be run as root */
1693 change_to_root_user();
1696 START_PROFILE(smb2_keepalive
);
1697 return_value
= smbd_smb2_request_process_keepalive(req
);
1698 END_PROFILE(smb2_keepalive
);
1703 if (!NT_STATUS_IS_OK(session_status
)) {
1704 return_value
= smbd_smb2_request_error(req
, session_status
);
1708 * This call needs to be run as user.
1710 * smbd_smb2_request_check_tcon()
1711 * calls change_to_user() on success.
1713 status
= smbd_smb2_request_check_tcon(req
);
1714 if (!NT_STATUS_IS_OK(status
)) {
1715 return_value
= smbd_smb2_request_error(req
, status
);
1720 START_PROFILE(smb2_find
);
1721 return_value
= smbd_smb2_request_process_find(req
);
1722 END_PROFILE(smb2_find
);
1726 case SMB2_OP_NOTIFY
:
1727 if (!NT_STATUS_IS_OK(session_status
)) {
1728 return_value
= smbd_smb2_request_error(req
, session_status
);
1732 * This call needs to be run as user.
1734 * smbd_smb2_request_check_tcon()
1735 * calls change_to_user() on success.
1737 status
= smbd_smb2_request_check_tcon(req
);
1738 if (!NT_STATUS_IS_OK(status
)) {
1739 return_value
= smbd_smb2_request_error(req
, status
);
1744 START_PROFILE(smb2_notify
);
1745 return_value
= smbd_smb2_request_process_notify(req
);
1746 END_PROFILE(smb2_notify
);
1750 case SMB2_OP_GETINFO
:
1751 if (!NT_STATUS_IS_OK(session_status
)) {
1752 return_value
= smbd_smb2_request_error(req
, session_status
);
1756 * This call needs to be run as user.
1758 * smbd_smb2_request_check_tcon()
1759 * calls change_to_user() on success.
1761 status
= smbd_smb2_request_check_tcon(req
);
1762 if (!NT_STATUS_IS_OK(status
)) {
1763 return_value
= smbd_smb2_request_error(req
, status
);
1768 START_PROFILE(smb2_getinfo
);
1769 return_value
= smbd_smb2_request_process_getinfo(req
);
1770 END_PROFILE(smb2_getinfo
);
1774 case SMB2_OP_SETINFO
:
1775 if (!NT_STATUS_IS_OK(session_status
)) {
1776 return_value
= smbd_smb2_request_error(req
, session_status
);
1780 * This call needs to be run as user.
1782 * smbd_smb2_request_check_tcon()
1783 * calls change_to_user() on success.
1785 status
= smbd_smb2_request_check_tcon(req
);
1786 if (!NT_STATUS_IS_OK(status
)) {
1787 return_value
= smbd_smb2_request_error(req
, status
);
1792 START_PROFILE(smb2_setinfo
);
1793 return_value
= smbd_smb2_request_process_setinfo(req
);
1794 END_PROFILE(smb2_setinfo
);
1799 if (!NT_STATUS_IS_OK(session_status
)) {
1800 return_value
= smbd_smb2_request_error(req
, session_status
);
1804 * This call needs to be run as user.
1806 * smbd_smb2_request_check_tcon()
1807 * calls change_to_user() on success.
1809 status
= smbd_smb2_request_check_tcon(req
);
1810 if (!NT_STATUS_IS_OK(status
)) {
1811 return_value
= smbd_smb2_request_error(req
, status
);
1816 START_PROFILE(smb2_break
);
1817 return_value
= smbd_smb2_request_process_break(req
);
1818 END_PROFILE(smb2_break
);
1823 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1826 return return_value
;
1829 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
1831 struct tevent_req
*subreq
;
1832 int i
= req
->current_idx
;
1835 TALLOC_FREE(req
->async_te
);
1837 req
->current_idx
+= 3;
1839 if (req
->current_idx
< req
->out
.vector_count
) {
1841 * We must process the remaining compound
1842 * SMB2 requests before any new incoming SMB2
1843 * requests. This is because incoming SMB2
1844 * requests may include a cancel for a
1845 * compound request we haven't processed
1848 struct tevent_immediate
*im
= tevent_create_immediate(req
);
1850 return NT_STATUS_NO_MEMORY
;
1852 tevent_schedule_immediate(im
,
1853 req
->sconn
->smb2
.event_ctx
,
1854 smbd_smb2_request_dispatch_immediate
,
1856 return NT_STATUS_OK
;
1859 if (req
->compound_related
) {
1860 req
->sconn
->smb2
.compound_related_in_progress
= false;
1863 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
1865 /* Set credit for these operations (zero credits if this
1866 is a final reply for an async operation). */
1867 smb2_calculate_credits(req
, req
);
1869 if (req
->do_signing
) {
1871 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
1872 &req
->out
.vector
[i
], 3);
1873 if (!NT_STATUS_IS_OK(status
)) {
1878 if (DEBUGLEVEL
>= 10) {
1879 dbgtext("smbd_smb2_request_reply: sending...\n");
1880 print_req_vectors(req
);
1883 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1884 if (req
->out
.vector_count
== 4 &&
1885 req
->out
.vector
[3].iov_base
== NULL
&&
1886 req
->out
.vector
[3].iov_len
!= 0) {
1887 /* Dynamic part is NULL. Chop it off,
1888 We're going to send it via sendfile. */
1889 req
->out
.vector_count
-= 1;
1892 subreq
= tstream_writev_queue_send(req
,
1893 req
->sconn
->smb2
.event_ctx
,
1894 req
->sconn
->smb2
.stream
,
1895 req
->sconn
->smb2
.send_queue
,
1897 req
->out
.vector_count
);
1898 if (subreq
== NULL
) {
1899 return NT_STATUS_NO_MEMORY
;
1901 tevent_req_set_callback(subreq
, smbd_smb2_request_writev_done
, req
);
1903 * We're done with this request -
1904 * move it off the "being processed" queue.
1906 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1908 return NT_STATUS_OK
;
1911 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
);
1913 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
1914 struct tevent_immediate
*im
,
1917 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
1918 struct smbd_smb2_request
);
1919 struct smbd_server_connection
*sconn
= req
->sconn
;
1924 if (DEBUGLEVEL
>= 10) {
1925 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1926 req
->current_idx
, req
->in
.vector_count
));
1927 print_req_vectors(req
);
1930 status
= smbd_smb2_request_dispatch(req
);
1931 if (!NT_STATUS_IS_OK(status
)) {
1932 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1936 status
= smbd_smb2_request_next_incoming(sconn
);
1937 if (!NT_STATUS_IS_OK(status
)) {
1938 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1943 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
)
1945 struct smbd_smb2_request
*req
= tevent_req_callback_data(subreq
,
1946 struct smbd_smb2_request
);
1947 struct smbd_server_connection
*sconn
= req
->sconn
;
1952 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1953 TALLOC_FREE(subreq
);
1956 status
= map_nt_error_from_unix(sys_errno
);
1957 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1958 nt_errstr(status
)));
1959 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1963 status
= smbd_smb2_request_next_incoming(sconn
);
1964 if (!NT_STATUS_IS_OK(status
)) {
1965 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1970 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
1972 DATA_BLOB body
, DATA_BLOB
*dyn
,
1973 const char *location
)
1976 int i
= req
->current_idx
;
1977 uint32_t next_command_ofs
;
1979 DEBUG(10,("smbd_smb2_request_done_ex: "
1980 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1981 i
, nt_errstr(status
), (unsigned int)body
.length
,
1983 (unsigned int)(dyn
? dyn
->length
: 0),
1986 if (body
.length
< 2) {
1987 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
1990 if ((body
.length
% 2) != 0) {
1991 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
1994 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
1996 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
1997 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
1999 req
->out
.vector
[i
+1].iov_base
= (void *)body
.data
;
2000 req
->out
.vector
[i
+1].iov_len
= body
.length
;
2003 req
->out
.vector
[i
+2].iov_base
= (void *)dyn
->data
;
2004 req
->out
.vector
[i
+2].iov_len
= dyn
->length
;
2006 req
->out
.vector
[i
+2].iov_base
= NULL
;
2007 req
->out
.vector
[i
+2].iov_len
= 0;
2010 /* see if we need to recalculate the offset to the next response */
2011 if (next_command_ofs
> 0) {
2012 next_command_ofs
= SMB2_HDR_BODY
;
2013 next_command_ofs
+= req
->out
.vector
[i
+1].iov_len
;
2014 next_command_ofs
+= req
->out
.vector
[i
+2].iov_len
;
2017 if ((next_command_ofs
% 8) != 0) {
2018 size_t pad_size
= 8 - (next_command_ofs
% 8);
2019 if (req
->out
.vector
[i
+2].iov_len
== 0) {
2021 * if the dyn buffer is empty
2022 * we can use it to add padding
2026 pad
= talloc_zero_array(req
->out
.vector
,
2029 return smbd_smb2_request_error(req
,
2030 NT_STATUS_NO_MEMORY
);
2033 req
->out
.vector
[i
+2].iov_base
= (void *)pad
;
2034 req
->out
.vector
[i
+2].iov_len
= pad_size
;
2037 * For now we copy the dynamic buffer
2038 * and add the padding to the new buffer
2045 old_size
= req
->out
.vector
[i
+2].iov_len
;
2046 old_dyn
= (uint8_t *)req
->out
.vector
[i
+2].iov_base
;
2048 new_size
= old_size
+ pad_size
;
2049 new_dyn
= talloc_zero_array(req
->out
.vector
,
2051 if (new_dyn
== NULL
) {
2052 return smbd_smb2_request_error(req
,
2053 NT_STATUS_NO_MEMORY
);
2056 memcpy(new_dyn
, old_dyn
, old_size
);
2057 memset(new_dyn
+ old_size
, 0, pad_size
);
2059 req
->out
.vector
[i
+2].iov_base
= (void *)new_dyn
;
2060 req
->out
.vector
[i
+2].iov_len
= new_size
;
2062 next_command_ofs
+= pad_size
;
2065 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
2067 return smbd_smb2_request_reply(req
);
2070 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
2073 const char *location
)
2076 int i
= req
->current_idx
;
2077 uint8_t *outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
2079 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2080 i
, nt_errstr(status
), info
? " +info" : "",
2083 body
.data
= outhdr
+ SMB2_HDR_BODY
;
2085 SSVAL(body
.data
, 0, 9);
2088 SIVAL(body
.data
, 0x04, info
->length
);
2090 /* Allocated size of req->out.vector[i].iov_base
2091 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2092 * 1 byte without having to do an alloc.
2094 info
= talloc_zero_array(req
->out
.vector
,
2098 return NT_STATUS_NO_MEMORY
;
2100 info
->data
= ((uint8_t *)outhdr
) +
2101 OUTVEC_ALLOC_SIZE
- 1;
2103 SCVAL(info
->data
, 0, 0);
2107 * if a request fails, all other remaining
2108 * compounded requests should fail too
2110 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
2112 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
2116 struct smbd_smb2_send_oplock_break_state
{
2117 struct smbd_server_connection
*sconn
;
2118 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x18];
2119 struct iovec vector
;
2122 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
);
2124 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
2125 uint64_t file_id_persistent
,
2126 uint64_t file_id_volatile
,
2127 uint8_t oplock_level
)
2129 struct smbd_smb2_send_oplock_break_state
*state
;
2130 struct tevent_req
*subreq
;
2134 state
= talloc(sconn
, struct smbd_smb2_send_oplock_break_state
);
2135 if (state
== NULL
) {
2136 return NT_STATUS_NO_MEMORY
;
2138 state
->sconn
= sconn
;
2140 state
->vector
.iov_base
= (void *)state
->buf
;
2141 state
->vector
.iov_len
= sizeof(state
->buf
);
2143 _smb2_setlen(state
->buf
, sizeof(state
->buf
) - 4);
2144 hdr
= state
->buf
+ 4;
2145 body
= hdr
+ SMB2_HDR_BODY
;
2147 SIVAL(hdr
, 0, SMB2_MAGIC
);
2148 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
2149 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
2150 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
2151 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
2152 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
2153 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
2154 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
2155 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
2156 SIVAL(hdr
, SMB2_HDR_PID
, 0);
2157 SIVAL(hdr
, SMB2_HDR_TID
, 0);
2158 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
2159 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
2161 SSVAL(body
, 0x00, 0x18);
2163 SCVAL(body
, 0x02, oplock_level
);
2164 SCVAL(body
, 0x03, 0); /* reserved */
2165 SIVAL(body
, 0x04, 0); /* reserved */
2166 SBVAL(body
, 0x08, file_id_persistent
);
2167 SBVAL(body
, 0x10, file_id_volatile
);
2169 subreq
= tstream_writev_queue_send(state
,
2170 sconn
->smb2
.event_ctx
,
2172 sconn
->smb2
.send_queue
,
2174 if (subreq
== NULL
) {
2175 return NT_STATUS_NO_MEMORY
;
2177 tevent_req_set_callback(subreq
,
2178 smbd_smb2_oplock_break_writev_done
,
2181 return NT_STATUS_OK
;
2184 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
)
2186 struct smbd_smb2_send_oplock_break_state
*state
=
2187 tevent_req_callback_data(subreq
,
2188 struct smbd_smb2_send_oplock_break_state
);
2189 struct smbd_server_connection
*sconn
= state
->sconn
;
2193 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
2194 TALLOC_FREE(subreq
);
2196 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
2197 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2204 struct smbd_smb2_request_read_state
{
2206 bool asked_for_header
;
2207 struct smbd_smb2_request
*smb2_req
;
2210 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2212 TALLOC_CTX
*mem_ctx
,
2213 struct iovec
**_vector
,
2215 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
);
2217 static struct tevent_req
*smbd_smb2_request_read_send(TALLOC_CTX
*mem_ctx
,
2218 struct tevent_context
*ev
,
2219 struct smbd_server_connection
*sconn
)
2221 struct tevent_req
*req
;
2222 struct smbd_smb2_request_read_state
*state
;
2223 struct tevent_req
*subreq
;
2225 req
= tevent_req_create(mem_ctx
, &state
,
2226 struct smbd_smb2_request_read_state
);
2231 state
->asked_for_header
= false;
2233 state
->smb2_req
= smbd_smb2_request_allocate(state
);
2234 if (tevent_req_nomem(state
->smb2_req
, req
)) {
2235 return tevent_req_post(req
, ev
);
2237 state
->smb2_req
->sconn
= sconn
;
2239 subreq
= tstream_readv_pdu_queue_send(state
, ev
, sconn
->smb2
.stream
,
2240 sconn
->smb2
.recv_queue
,
2241 smbd_smb2_request_next_vector
,
2243 if (tevent_req_nomem(subreq
, req
)) {
2244 return tevent_req_post(req
, ev
);
2246 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
2251 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2253 TALLOC_CTX
*mem_ctx
,
2254 struct iovec
**_vector
,
2257 struct smbd_smb2_request_read_state
*state
=
2258 talloc_get_type_abort(private_data
,
2259 struct smbd_smb2_request_read_state
);
2260 struct smbd_smb2_request
*req
= state
->smb2_req
;
2261 struct iovec
*vector
;
2262 int idx
= req
->in
.vector_count
;
2264 uint8_t *buf
= NULL
;
2266 if (req
->in
.vector_count
== 0) {
2268 * first we need to get the NBT header
2270 req
->in
.vector
= talloc_array(req
, struct iovec
,
2271 req
->in
.vector_count
+ 1);
2272 if (req
->in
.vector
== NULL
) {
2275 req
->in
.vector_count
+= 1;
2277 req
->in
.vector
[idx
].iov_base
= (void *)req
->in
.nbt_hdr
;
2278 req
->in
.vector
[idx
].iov_len
= 4;
2280 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2281 if (vector
== NULL
) {
2285 vector
[0] = req
->in
.vector
[idx
];
2292 if (req
->in
.vector_count
== 1) {
2294 * Now we analyze the NBT header
2296 state
->missing
= smb2_len(req
->in
.vector
[0].iov_base
);
2298 if (state
->missing
== 0) {
2299 /* if there're no remaining bytes, we're done */
2305 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2307 req
->in
.vector_count
+ 1);
2308 if (req
->in
.vector
== NULL
) {
2311 req
->in
.vector_count
+= 1;
2313 if (CVAL(req
->in
.vector
[0].iov_base
, 0) != 0) {
2315 * it's a special NBT message,
2316 * so get all remaining bytes
2318 len
= state
->missing
;
2319 } else if (state
->missing
< (SMB2_HDR_BODY
+ 2)) {
2321 * it's an invalid message, just read what we can get
2322 * and let the caller handle the error
2324 len
= state
->missing
;
2327 * We assume it's a SMB2 request,
2328 * and we first get the header and the
2329 * first 2 bytes (the struct size) of the body
2331 len
= SMB2_HDR_BODY
+ 2;
2333 state
->asked_for_header
= true;
2336 state
->missing
-= len
;
2338 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2343 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2344 req
->in
.vector
[idx
].iov_len
= len
;
2346 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2347 if (vector
== NULL
) {
2351 vector
[0] = req
->in
.vector
[idx
];
2358 if (state
->missing
== 0) {
2359 /* if there're no remaining bytes, we're done */
2365 if (state
->asked_for_header
) {
2368 size_t next_command_ofs
;
2373 bool invalid
= false;
2375 state
->asked_for_header
= false;
2378 * We got the SMB2 header and the first 2 bytes
2379 * of the body. We fix the size to just the header
2380 * and manually copy the 2 first bytes to the body section
2382 req
->in
.vector
[idx
-1].iov_len
= SMB2_HDR_BODY
;
2383 hdr
= (const uint8_t *)req
->in
.vector
[idx
-1].iov_base
;
2385 /* allocate vectors for body and dynamic areas */
2386 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2388 req
->in
.vector_count
+ 2);
2389 if (req
->in
.vector
== NULL
) {
2392 req
->in
.vector_count
+= 2;
2394 full_size
= state
->missing
+ SMB2_HDR_BODY
+ 2;
2395 next_command_ofs
= IVAL(hdr
, SMB2_HDR_NEXT_COMMAND
);
2396 body_size
= SVAL(hdr
, SMB2_HDR_BODY
);
2398 if (next_command_ofs
!= 0) {
2399 if (next_command_ofs
< (SMB2_HDR_BODY
+ 2)) {
2401 * this is invalid, just return a zero
2402 * body and let the caller deal with the error
2405 } else if (next_command_ofs
> full_size
) {
2407 * this is invalid, just return a zero
2408 * body and let the caller deal with the error
2412 full_size
= next_command_ofs
;
2417 if (body_size
< 2) {
2419 * this is invalid, just return a zero
2420 * body and let the caller deal with the error
2426 * Mask out the lowest bit, the "dynamic" part
2431 if (body_size
> (full_size
- SMB2_HDR_BODY
)) {
2433 * this is invalid, just return a zero
2434 * body and let the caller deal with the error
2441 /* the caller should check this */
2445 dyn_size
= full_size
- (SMB2_HDR_BODY
+ body_size
);
2447 state
->missing
-= (body_size
- 2) + dyn_size
;
2449 body
= talloc_array(req
->in
.vector
, uint8_t, body_size
);
2454 dyn
= talloc_array(req
->in
.vector
, uint8_t, dyn_size
);
2459 req
->in
.vector
[idx
].iov_base
= (void *)body
;
2460 req
->in
.vector
[idx
].iov_len
= body_size
;
2461 req
->in
.vector
[idx
+1].iov_base
= (void *)dyn
;
2462 req
->in
.vector
[idx
+1].iov_len
= dyn_size
;
2464 vector
= talloc_array(mem_ctx
, struct iovec
, 2);
2465 if (vector
== NULL
) {
2470 * the first 2 bytes of the body were already fetched
2471 * together with the header
2473 memcpy(body
, hdr
+ SMB2_HDR_BODY
, 2);
2474 vector
[0].iov_base
= body
+ 2;
2475 vector
[0].iov_len
= body_size
- 2;
2477 vector
[1] = req
->in
.vector
[idx
+1];
2485 * when we endup here, we're looking for a new SMB2 request
2486 * next. And we ask for its header and the first 2 bytes of
2487 * the body (like we did for the first SMB2 request).
2490 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2492 req
->in
.vector_count
+ 1);
2493 if (req
->in
.vector
== NULL
) {
2496 req
->in
.vector_count
+= 1;
2499 * We assume it's a SMB2 request,
2500 * and we first get the header and the
2501 * first 2 bytes (the struct size) of the body
2503 len
= SMB2_HDR_BODY
+ 2;
2505 if (len
> state
->missing
) {
2506 /* let the caller handle the error */
2507 len
= state
->missing
;
2510 state
->missing
-= len
;
2511 state
->asked_for_header
= true;
2513 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2518 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2519 req
->in
.vector
[idx
].iov_len
= len
;
2521 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2522 if (vector
== NULL
) {
2526 vector
[0] = req
->in
.vector
[idx
];
2533 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
)
2535 struct tevent_req
*req
=
2536 tevent_req_callback_data(subreq
,
2542 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
2544 status
= map_nt_error_from_unix(sys_errno
);
2545 tevent_req_nterror(req
, status
);
2549 tevent_req_done(req
);
2552 static NTSTATUS
smbd_smb2_request_read_recv(struct tevent_req
*req
,
2553 TALLOC_CTX
*mem_ctx
,
2554 struct smbd_smb2_request
**_smb2_req
)
2556 struct smbd_smb2_request_read_state
*state
=
2557 tevent_req_data(req
,
2558 struct smbd_smb2_request_read_state
);
2561 if (tevent_req_is_nterror(req
, &status
)) {
2562 tevent_req_received(req
);
2566 talloc_steal(mem_ctx
, state
->smb2_req
->mem_pool
);
2567 *_smb2_req
= state
->smb2_req
;
2568 tevent_req_received(req
);
2569 return NT_STATUS_OK
;
2572 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
);
2574 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
)
2576 size_t max_send_queue_len
;
2577 size_t cur_send_queue_len
;
2578 struct tevent_req
*subreq
;
2580 if (sconn
->smb2
.compound_related_in_progress
) {
2582 * Can't read another until the related
2585 return NT_STATUS_OK
;
2588 if (tevent_queue_length(sconn
->smb2
.recv_queue
) > 0) {
2590 * if there is already a smbd_smb2_request_read
2591 * pending, we are done.
2593 return NT_STATUS_OK
;
2596 max_send_queue_len
= MAX(1, sconn
->smb2
.max_credits
/16);
2597 cur_send_queue_len
= tevent_queue_length(sconn
->smb2
.send_queue
);
2599 if (cur_send_queue_len
> max_send_queue_len
) {
2601 * if we have a lot of requests to send,
2602 * we wait until they are on the wire until we
2603 * ask for the next request.
2605 return NT_STATUS_OK
;
2608 /* ask for the next request */
2609 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->smb2
.event_ctx
, sconn
);
2610 if (subreq
== NULL
) {
2611 return NT_STATUS_NO_MEMORY
;
2613 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);
2615 return NT_STATUS_OK
;
2618 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
2619 const uint8_t *inbuf
, size_t size
)
2622 struct smbd_smb2_request
*req
= NULL
;
2624 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2625 (unsigned int)size
));
2627 status
= smbd_initialize_smb2(sconn
);
2628 if (!NT_STATUS_IS_OK(status
)) {
2629 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2633 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
2634 if (!NT_STATUS_IS_OK(status
)) {
2635 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2639 status
= smbd_smb2_request_setup_out(req
);
2640 if (!NT_STATUS_IS_OK(status
)) {
2641 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2645 status
= smbd_smb2_request_dispatch(req
);
2646 if (!NT_STATUS_IS_OK(status
)) {
2647 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2651 status
= smbd_smb2_request_next_incoming(sconn
);
2652 if (!NT_STATUS_IS_OK(status
)) {
2653 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2657 sconn
->num_requests
++;
2660 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
)
2662 struct smbd_server_connection
*sconn
= tevent_req_callback_data(subreq
,
2663 struct smbd_server_connection
);
2665 struct smbd_smb2_request
*req
= NULL
;
2667 status
= smbd_smb2_request_read_recv(subreq
, sconn
, &req
);
2668 TALLOC_FREE(subreq
);
2669 if (!NT_STATUS_IS_OK(status
)) {
2670 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2671 nt_errstr(status
)));
2672 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2676 if (req
->in
.nbt_hdr
[0] != 0x00) {
2677 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2678 req
->in
.nbt_hdr
[0]));
2683 req
->current_idx
= 1;
2685 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2686 req
->current_idx
, req
->in
.vector_count
));
2688 status
= smbd_smb2_request_validate(req
);
2689 if (!NT_STATUS_IS_OK(status
)) {
2690 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2694 status
= smbd_smb2_request_setup_out(req
);
2695 if (!NT_STATUS_IS_OK(status
)) {
2696 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2700 status
= smbd_smb2_request_dispatch(req
);
2701 if (!NT_STATUS_IS_OK(status
)) {
2702 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2707 status
= smbd_smb2_request_next_incoming(sconn
);
2708 if (!NT_STATUS_IS_OK(status
)) {
2709 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2713 sconn
->num_requests
++;
2715 /* The timeout_processing function isn't run nearly
2716 often enough to implement 'max log size' without
2717 overrunning the size of the file by many megabytes.
2718 This is especially true if we are running at debug
2719 level 10. Checking every 50 SMB2s is a nice
2720 tradeoff of performance vs log file size overrun. */
2722 if ((sconn
->num_requests
% 50) == 0 &&
2723 need_to_check_log_size()) {
2724 change_to_root_user();