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
= 0;
118 sconn
->smb2
.max_credits
= lp_smb2_max_credits();
119 sconn
->smb2
.credits_bitmap
= bitmap_talloc(sconn
,
120 DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
*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 talloc_set_destructor(parent
, smbd_smb2_request_parent_destructor
);
210 talloc_set_destructor(req
, smbd_smb2_request_destructor
);
215 static NTSTATUS
smbd_smb2_request_create(struct smbd_server_connection
*sconn
,
216 const uint8_t *inbuf
, size_t size
,
217 struct smbd_smb2_request
**_req
)
219 struct smbd_smb2_request
*req
;
220 uint32_t protocol_version
;
221 const uint8_t *inhdr
= NULL
;
224 uint32_t next_command_ofs
;
226 if (size
< (4 + SMB2_HDR_BODY
+ 2)) {
227 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size
));
228 return NT_STATUS_INVALID_PARAMETER
;
233 protocol_version
= IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
);
234 if (protocol_version
!= SMB2_MAGIC
) {
235 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
237 return NT_STATUS_INVALID_PARAMETER
;
240 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
241 if (cmd
!= SMB2_OP_NEGPROT
) {
242 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
244 return NT_STATUS_INVALID_PARAMETER
;
247 next_command_ofs
= IVAL(inhdr
, SMB2_HDR_NEXT_COMMAND
);
248 if (next_command_ofs
!= 0) {
249 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
251 return NT_STATUS_INVALID_PARAMETER
;
254 req
= smbd_smb2_request_allocate(sconn
);
256 return NT_STATUS_NO_MEMORY
;
260 talloc_steal(req
, inbuf
);
262 req
->in
.vector
= talloc_array(req
, struct iovec
, 4);
263 if (req
->in
.vector
== NULL
) {
265 return NT_STATUS_NO_MEMORY
;
267 req
->in
.vector_count
= 4;
269 memcpy(req
->in
.nbt_hdr
, inbuf
, 4);
272 req
->in
.vector
[0].iov_base
= (void *)req
->in
.nbt_hdr
;
273 req
->in
.vector
[0].iov_len
= 4;
274 ofs
+= req
->in
.vector
[0].iov_len
;
276 req
->in
.vector
[1].iov_base
= (void *)(inbuf
+ ofs
);
277 req
->in
.vector
[1].iov_len
= SMB2_HDR_BODY
;
278 ofs
+= req
->in
.vector
[1].iov_len
;
280 req
->in
.vector
[2].iov_base
= (void *)(inbuf
+ ofs
);
281 req
->in
.vector
[2].iov_len
= SVAL(inbuf
, ofs
) & 0xFFFE;
282 ofs
+= req
->in
.vector
[2].iov_len
;
285 return NT_STATUS_INVALID_PARAMETER
;
288 req
->in
.vector
[3].iov_base
= (void *)(inbuf
+ ofs
);
289 req
->in
.vector
[3].iov_len
= size
- ofs
;
290 ofs
+= req
->in
.vector
[3].iov_len
;
292 req
->current_idx
= 1;
298 static bool smb2_validate_message_id(struct smbd_server_connection
*sconn
,
299 const uint8_t *inhdr
)
301 uint64_t message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
302 struct bitmap
*credits_bm
= sconn
->smb2
.credits_bitmap
;
303 uint16_t opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
304 unsigned int bitmap_offset
;
306 if (opcode
== SMB2_OP_CANCEL
) {
307 /* SMB2_CANCEL requests by definition resend messageids. */
311 if (message_id
< sconn
->smb2
.seqnum_low
||
312 message_id
> (sconn
->smb2
.seqnum_low
+
313 (sconn
->smb2
.max_credits
* DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
))) {
314 DEBUG(0,("smb2_validate_message_id: bad message_id "
315 "%llu (low = %llu, max = %lu)\n",
316 (unsigned long long)message_id
,
317 (unsigned long long)sconn
->smb2
.seqnum_low
,
318 (unsigned long)sconn
->smb2
.max_credits
));
322 /* client just used a credit. */
323 SMB_ASSERT(sconn
->smb2
.credits_granted
> 0);
324 sconn
->smb2
.credits_granted
-= 1;
326 /* Mark the message_id as seen in the bitmap. */
327 bitmap_offset
= (unsigned int)(message_id
%
328 (uint64_t)(sconn
->smb2
.max_credits
* DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
));
329 if (bitmap_query(credits_bm
, bitmap_offset
)) {
330 DEBUG(0,("smb2_validate_message_id: duplicate message_id "
331 "%llu (bm offset %u)\n",
332 (unsigned long long)message_id
,
336 bitmap_set(credits_bm
, bitmap_offset
);
338 if (message_id
== sconn
->smb2
.seqnum_low
+ 1) {
339 /* Move the window forward by all the message_id's
341 while (bitmap_query(credits_bm
, bitmap_offset
)) {
342 DEBUG(10,("smb2_validate_message_id: clearing "
343 "id %llu (position %u) from bitmap\n",
344 (unsigned long long)(sconn
->smb2
.seqnum_low
+ 1),
346 bitmap_clear(credits_bm
, bitmap_offset
);
347 sconn
->smb2
.seqnum_low
+= 1;
348 bitmap_offset
= (bitmap_offset
+ 1) %
349 (sconn
->smb2
.max_credits
* DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
);
356 static NTSTATUS
smbd_smb2_request_validate(struct smbd_smb2_request
*req
)
360 bool compound_related
= false;
362 count
= req
->in
.vector_count
;
365 /* It's not a SMB2 request */
366 return NT_STATUS_INVALID_PARAMETER
;
369 for (idx
=1; idx
< count
; idx
+= 3) {
370 const uint8_t *inhdr
= NULL
;
373 if (req
->in
.vector
[idx
].iov_len
!= SMB2_HDR_BODY
) {
374 return NT_STATUS_INVALID_PARAMETER
;
377 if (req
->in
.vector
[idx
+1].iov_len
< 2) {
378 return NT_STATUS_INVALID_PARAMETER
;
381 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
383 /* Check the SMB2 header */
384 if (IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
) != SMB2_MAGIC
) {
385 return NT_STATUS_INVALID_PARAMETER
;
388 if (!smb2_validate_message_id(req
->sconn
, inhdr
)) {
389 return NT_STATUS_INVALID_PARAMETER
;
392 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
395 * the 1st request should never have the
396 * SMB2_HDR_FLAG_CHAINED flag set
398 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
399 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
402 } else if (idx
== 4) {
404 * the 2nd request triggers related vs. unrelated
405 * compounded requests
407 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
408 compound_related
= true;
410 } else if (idx
> 4) {
413 * It seems the this tests are wrong
414 * see the SMB2-COMPOUND test
418 * all other requests should match the 2nd one
420 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
421 if (!compound_related
) {
423 NT_STATUS_INVALID_PARAMETER
;
427 if (compound_related
) {
429 NT_STATUS_INVALID_PARAMETER
;
440 static void smb2_set_operation_credit(struct smbd_server_connection
*sconn
,
441 const struct iovec
*in_vector
,
442 struct iovec
*out_vector
)
444 const uint8_t *inhdr
= (const uint8_t *)in_vector
->iov_base
;
445 uint8_t *outhdr
= (uint8_t *)out_vector
->iov_base
;
446 uint16_t credits_requested
;
448 uint16_t credits_granted
= 0;
450 credits_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
451 out_flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
453 SMB_ASSERT(sconn
->smb2
.max_credits
>= sconn
->smb2
.credits_granted
);
455 if (out_flags
& SMB2_HDR_FLAG_ASYNC
) {
457 * In case we already send an async interim
458 * response, we should not grant
459 * credits on the final response.
461 credits_requested
= 0;
464 if (credits_requested
) {
465 uint16_t modified_credits_requested
;
469 * Split up max_credits into 1/16ths, and then scale
470 * the requested credits by how many 16ths have been
471 * currently granted. Less than 1/16th == grant all
472 * requested (100%), scale down as more have been
473 * granted. Never ask for less than 1 as the client
474 * asked for at least 1. JRA.
477 multiplier
= 16 - (((sconn
->smb2
.credits_granted
* 16) / sconn
->smb2
.max_credits
) % 16);
479 modified_credits_requested
= (multiplier
* credits_requested
) / 16;
480 if (modified_credits_requested
== 0) {
481 modified_credits_requested
= 1;
484 /* Remember what we gave out. */
485 credits_granted
= MIN(modified_credits_requested
,
486 (sconn
->smb2
.max_credits
- sconn
->smb2
.credits_granted
));
489 if (credits_granted
== 0 && sconn
->smb2
.credits_granted
== 0) {
490 /* First negprot packet, or ensure the client credits can
491 never drop to zero. */
495 SSVAL(outhdr
, SMB2_HDR_CREDIT
, credits_granted
);
496 sconn
->smb2
.credits_granted
+= credits_granted
;
498 DEBUG(10,("smb2_set_operation_credit: requested %u, "
499 "granted %u, total granted %u\n",
500 (unsigned int)credits_requested
,
501 (unsigned int)credits_granted
,
502 (unsigned int)sconn
->smb2
.credits_granted
));
505 static void smb2_calculate_credits(const struct smbd_smb2_request
*inreq
,
506 struct smbd_smb2_request
*outreq
)
510 count
= outreq
->out
.vector_count
;
512 for (idx
=1; idx
< count
; idx
+= 3) {
513 smb2_set_operation_credit(outreq
->sconn
,
514 &inreq
->in
.vector
[idx
],
515 &outreq
->out
.vector
[idx
]);
519 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
)
521 struct iovec
*vector
;
525 count
= req
->in
.vector_count
;
526 vector
= talloc_zero_array(req
, struct iovec
, count
);
527 if (vector
== NULL
) {
528 return NT_STATUS_NO_MEMORY
;
531 vector
[0].iov_base
= req
->out
.nbt_hdr
;
532 vector
[0].iov_len
= 4;
533 SIVAL(req
->out
.nbt_hdr
, 0, 0);
535 for (idx
=1; idx
< count
; idx
+= 3) {
536 const uint8_t *inhdr
= NULL
;
538 uint8_t *outhdr
= NULL
;
539 uint8_t *outbody
= NULL
;
540 uint32_t next_command_ofs
= 0;
541 struct iovec
*current
= &vector
[idx
];
543 if ((idx
+ 3) < count
) {
544 /* we have a next command -
545 * setup for the error case. */
546 next_command_ofs
= SMB2_HDR_BODY
+ 9;
549 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
550 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
552 outhdr
= talloc_zero_array(vector
, uint8_t,
554 if (outhdr
== NULL
) {
555 return NT_STATUS_NO_MEMORY
;
558 outbody
= outhdr
+ SMB2_HDR_BODY
;
560 current
[0].iov_base
= (void *)outhdr
;
561 current
[0].iov_len
= SMB2_HDR_BODY
;
563 current
[1].iov_base
= (void *)outbody
;
564 current
[1].iov_len
= 8;
566 current
[2].iov_base
= NULL
;
567 current
[2].iov_len
= 0;
569 /* setup the SMB2 header */
570 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
571 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
572 SSVAL(outhdr
, SMB2_HDR_EPOCH
, 0);
573 SIVAL(outhdr
, SMB2_HDR_STATUS
,
574 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
575 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
576 SVAL(inhdr
, SMB2_HDR_OPCODE
));
577 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
578 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
579 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
580 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
581 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
582 SIVAL(outhdr
, SMB2_HDR_PID
,
583 IVAL(inhdr
, SMB2_HDR_PID
));
584 SIVAL(outhdr
, SMB2_HDR_TID
,
585 IVAL(inhdr
, SMB2_HDR_TID
));
586 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
587 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
588 memset(outhdr
+ SMB2_HDR_SIGNATURE
, 0, 16);
590 /* setup error body header */
591 SSVAL(outbody
, 0x00, 0x08 + 1);
592 SSVAL(outbody
, 0x02, 0);
593 SIVAL(outbody
, 0x04, 0);
596 req
->out
.vector
= vector
;
597 req
->out
.vector_count
= count
;
599 /* setup the length of the NBT packet */
600 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
602 DLIST_ADD_END(req
->sconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
607 void smbd_server_connection_terminate_ex(struct smbd_server_connection
*sconn
,
609 const char *location
)
611 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
613 exit_server_cleanly(reason
);
616 static bool dup_smb2_vec3(TALLOC_CTX
*ctx
,
617 struct iovec
*outvec
,
618 const struct iovec
*srcvec
)
620 /* vec[0] is always boilerplate and must
621 * be allocated with size OUTVEC_ALLOC_SIZE. */
623 outvec
[0].iov_base
= talloc_memdup(ctx
,
626 if (!outvec
[0].iov_base
) {
629 outvec
[0].iov_len
= SMB2_HDR_BODY
;
632 * If this is a "standard" vec[1] of length 8,
633 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
634 * then duplicate this. Else use talloc_memdup().
637 if (srcvec
[1].iov_len
== 8 &&
638 srcvec
[1].iov_base
==
639 ((uint8_t *)srcvec
[0].iov_base
) +
641 outvec
[1].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
643 outvec
[1].iov_len
= 8;
645 outvec
[1].iov_base
= talloc_memdup(ctx
,
648 if (!outvec
[1].iov_base
) {
651 outvec
[1].iov_len
= srcvec
[1].iov_len
;
655 * If this is a "standard" vec[2] of length 1,
656 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
657 * then duplicate this. Else use talloc_memdup().
660 if (srcvec
[2].iov_base
&&
662 if (srcvec
[2].iov_base
==
663 ((uint8_t *)srcvec
[0].iov_base
) +
664 (OUTVEC_ALLOC_SIZE
- 1) &&
665 srcvec
[2].iov_len
== 1) {
666 /* Common SMB2 error packet case. */
667 outvec
[2].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
668 (OUTVEC_ALLOC_SIZE
- 1);
670 outvec
[2].iov_base
= talloc_memdup(ctx
,
673 if (!outvec
[2].iov_base
) {
677 outvec
[2].iov_len
= srcvec
[2].iov_len
;
679 outvec
[2].iov_base
= NULL
;
680 outvec
[2].iov_len
= 0;
685 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
687 struct smbd_smb2_request
*newreq
= NULL
;
688 struct iovec
*outvec
= NULL
;
689 int count
= req
->out
.vector_count
;
692 newreq
= smbd_smb2_request_allocate(req
->sconn
);
697 newreq
->sconn
= req
->sconn
;
698 newreq
->session
= req
->session
;
699 newreq
->do_signing
= req
->do_signing
;
700 newreq
->current_idx
= req
->current_idx
;
701 newreq
->async
= false;
702 newreq
->cancelled
= false;
703 /* Note we are leaving:
707 uninitialized as NULL here as
708 they're not used in the interim
709 response code. JRA. */
711 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
716 newreq
->out
.vector
= outvec
;
717 newreq
->out
.vector_count
= count
;
719 /* Setup the outvec's identically to req. */
720 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
721 outvec
[0].iov_len
= 4;
722 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
724 /* Setup the vectors identically to the ones in req. */
725 for (i
= 1; i
< count
; i
+= 3) {
726 if (!dup_smb2_vec3(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
737 smb2_setup_nbt_length(newreq
->out
.vector
,
738 newreq
->out
.vector_count
);
743 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
);
745 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
748 uint8_t *outhdr
= NULL
;
749 struct smbd_smb2_request
*nreq
= NULL
;
751 /* Create a new smb2 request we'll use
752 for the interim return. */
753 nreq
= dup_smb2_req(req
);
755 return NT_STATUS_NO_MEMORY
;
758 /* Lose the last 3 out vectors. They're the
759 ones we'll be using for the async reply. */
760 nreq
->out
.vector_count
-= 3;
762 smb2_setup_nbt_length(nreq
->out
.vector
,
763 nreq
->out
.vector_count
);
765 /* Step back to the previous reply. */
766 i
= nreq
->current_idx
- 3;
767 outhdr
= (uint8_t *)nreq
->out
.vector
[i
].iov_base
;
768 /* And end the chain. */
769 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
771 /* Calculate outgoing credits */
772 smb2_calculate_credits(req
, nreq
);
774 /* Re-sign if needed. */
775 if (nreq
->do_signing
) {
777 status
= smb2_signing_sign_pdu(nreq
->session
->session_key
,
778 &nreq
->out
.vector
[i
], 3);
779 if (!NT_STATUS_IS_OK(status
)) {
783 if (DEBUGLEVEL
>= 10) {
784 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
785 (unsigned int)nreq
->current_idx
);
786 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
787 (unsigned int)nreq
->out
.vector_count
);
788 print_req_vectors(nreq
);
790 nreq
->subreq
= tstream_writev_queue_send(nreq
,
791 nreq
->sconn
->smb2
.event_ctx
,
792 nreq
->sconn
->smb2
.stream
,
793 nreq
->sconn
->smb2
.send_queue
,
795 nreq
->out
.vector_count
);
797 if (nreq
->subreq
== NULL
) {
798 return NT_STATUS_NO_MEMORY
;
801 tevent_req_set_callback(nreq
->subreq
,
802 smbd_smb2_request_writev_done
,
808 struct smbd_smb2_request_pending_state
{
809 struct smbd_server_connection
*sconn
;
810 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x08 + 1];
811 struct iovec vector
[3];
814 static void smbd_smb2_request_pending_writev_done(struct tevent_req
*subreq
)
816 struct smbd_smb2_request_pending_state
*state
=
817 tevent_req_callback_data(subreq
,
818 struct smbd_smb2_request_pending_state
);
819 struct smbd_server_connection
*sconn
= state
->sconn
;
823 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
826 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
827 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
834 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
835 struct tevent_req
*subreq
)
838 struct smbd_smb2_request_pending_state
*state
= NULL
;
839 int i
= req
->current_idx
;
840 uint8_t *reqhdr
= NULL
;
842 uint8_t *body
= NULL
;
844 uint64_t message_id
= 0;
845 uint64_t async_id
= 0;
846 struct iovec
*outvec
= NULL
;
848 if (!tevent_req_is_in_progress(subreq
)) {
852 req
->subreq
= subreq
;
856 /* We're already async. */
860 if (req
->in
.vector_count
> i
+ 3) {
862 * We're trying to go async in a compound
863 * request chain. This is not allowed.
864 * Cancel the outstanding request.
866 tevent_req_cancel(req
->subreq
);
867 return smbd_smb2_request_error(req
,
868 NT_STATUS_INSUFFICIENT_RESOURCES
);
871 if (DEBUGLEVEL
>= 10) {
872 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
873 (unsigned int)req
->current_idx
);
874 print_req_vectors(req
);
877 if (req
->out
.vector_count
> 4) {
878 /* This is a compound reply. We
879 * must do an interim response
880 * followed by the async response
883 status
= smb2_send_async_interim_response(req
);
884 if (!NT_STATUS_IS_OK(status
)) {
889 /* Don't return an intermediate packet on a pipe read/write. */
890 if (req
->tcon
&& req
->tcon
->compat_conn
&& IS_IPC(req
->tcon
->compat_conn
)) {
894 reqhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
895 flags
= (IVAL(reqhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
896 message_id
= BVAL(reqhdr
, SMB2_HDR_MESSAGE_ID
);
897 async_id
= message_id
; /* keep it simple for now... */
900 * What we send is identical to a smbd_smb2_request_error
901 * packet with an error status of STATUS_PENDING. Make use
902 * of this fact sometime when refactoring. JRA.
905 state
= talloc_zero(req
->sconn
, struct smbd_smb2_request_pending_state
);
907 return NT_STATUS_NO_MEMORY
;
909 state
->sconn
= req
->sconn
;
911 state
->vector
[0].iov_base
= (void *)state
->buf
;
912 state
->vector
[0].iov_len
= 4;
914 state
->vector
[1].iov_base
= state
->buf
+ 4;
915 state
->vector
[1].iov_len
= SMB2_HDR_BODY
;
917 state
->vector
[2].iov_base
= state
->buf
+ 4 + SMB2_HDR_BODY
;
918 state
->vector
[2].iov_len
= 9;
920 smb2_setup_nbt_length(state
->vector
, 3);
922 hdr
= (uint8_t *)state
->vector
[1].iov_base
;
923 body
= (uint8_t *)state
->vector
[2].iov_base
;
925 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
926 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
927 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
928 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
929 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(reqhdr
, SMB2_HDR_OPCODE
));
931 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
932 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
933 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
934 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
935 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
936 BVAL(reqhdr
, SMB2_HDR_SESSION_ID
));
937 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
939 SSVAL(body
, 0x00, 0x08 + 1);
941 SCVAL(body
, 0x02, 0);
942 SCVAL(body
, 0x03, 0);
943 SIVAL(body
, 0x04, 0);
944 /* Match W2K8R2... */
945 SCVAL(body
, 0x08, 0x21);
947 /* Ensure we correctly go through crediting. Grant
948 the credits now, and zero credits on the final
950 smb2_set_operation_credit(req
->sconn
,
954 if (req
->do_signing
) {
955 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
956 &state
->vector
[1], 2);
957 if (!NT_STATUS_IS_OK(status
)) {
962 subreq
= tstream_writev_queue_send(state
,
963 req
->sconn
->smb2
.event_ctx
,
964 req
->sconn
->smb2
.stream
,
965 req
->sconn
->smb2
.send_queue
,
969 if (subreq
== NULL
) {
970 return NT_STATUS_NO_MEMORY
;
973 tevent_req_set_callback(subreq
,
974 smbd_smb2_request_pending_writev_done
,
977 /* Note we're going async with this request. */
981 * Now manipulate req so that the outstanding async request
982 * is the only one left in the struct smbd_smb2_request.
985 if (req
->current_idx
== 1) {
986 /* There was only one. */
990 /* Re-arrange the in.vectors. */
991 req
->in
.vector
[1] = req
->in
.vector
[i
];
992 req
->in
.vector
[2] = req
->in
.vector
[i
+1];
993 req
->in
.vector
[3] = req
->in
.vector
[i
+2];
994 req
->in
.vector_count
= 4;
995 /* Reset the new in size. */
996 smb2_setup_nbt_length(req
->in
.vector
, 4);
998 /* Now recreate the out.vectors. */
999 outvec
= talloc_zero_array(req
, struct iovec
, 4);
1001 return NT_STATUS_NO_MEMORY
;
1004 /* 0 is always boilerplate and must
1005 * be of size 4 for the length field. */
1007 outvec
[0].iov_base
= req
->out
.nbt_hdr
;
1008 outvec
[0].iov_len
= 4;
1009 SIVAL(req
->out
.nbt_hdr
, 0, 0);
1011 if (!dup_smb2_vec3(outvec
, &outvec
[1], &req
->out
.vector
[i
])) {
1012 return NT_STATUS_NO_MEMORY
;
1015 TALLOC_FREE(req
->out
.vector
);
1017 req
->out
.vector
= outvec
;
1019 req
->current_idx
= 1;
1020 req
->out
.vector_count
= 4;
1024 smb2_setup_nbt_length(req
->out
.vector
,
1025 req
->out
.vector_count
);
1027 /* Ensure our final reply matches the interim one. */
1028 reqhdr
= (uint8_t *)req
->out
.vector
[1].iov_base
;
1029 SIVAL(reqhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1030 SBVAL(reqhdr
, SMB2_HDR_PID
, async_id
);
1033 const uint8_t *inhdr
=
1034 (const uint8_t *)req
->in
.vector
[1].iov_base
;
1035 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1037 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1038 (unsigned long long)async_id
));
1040 return NT_STATUS_OK
;
1043 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
1045 struct smbd_server_connection
*sconn
= req
->sconn
;
1046 struct smbd_smb2_request
*cur
;
1047 const uint8_t *inhdr
;
1048 int i
= req
->current_idx
;
1050 uint64_t search_message_id
;
1051 uint64_t search_async_id
;
1054 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1056 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1057 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1058 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
1061 * we don't need the request anymore
1062 * cancel requests never have a response
1064 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1067 for (cur
= sconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
1068 const uint8_t *outhdr
;
1069 uint64_t message_id
;
1072 i
= cur
->current_idx
;
1074 outhdr
= (const uint8_t *)cur
->out
.vector
[i
].iov_base
;
1076 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1077 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
1079 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1080 if (search_async_id
== async_id
) {
1081 found_id
= async_id
;
1085 if (search_message_id
== message_id
) {
1086 found_id
= message_id
;
1092 if (cur
&& cur
->subreq
) {
1093 inhdr
= (const uint8_t *)cur
->in
.vector
[i
].iov_base
;
1094 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1095 "cancel opcode[%s] mid %llu\n",
1096 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1097 (unsigned long long)found_id
));
1098 tevent_req_cancel(cur
->subreq
);
1101 return NT_STATUS_OK
;
1104 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
1106 const uint8_t *inhdr
;
1107 int i
= req
->current_idx
;
1112 NTSTATUS session_status
;
1113 uint32_t allowed_flags
;
1114 NTSTATUS return_value
;
1116 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1118 /* TODO: verify more things */
1120 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1121 opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1122 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1123 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1124 smb2_opcode_name(opcode
),
1125 (unsigned long long)mid
));
1127 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
1128 SMB2_HDR_FLAG_SIGNED
|
1130 if (opcode
== SMB2_OP_CANCEL
) {
1131 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
1133 if ((flags
& ~allowed_flags
) != 0) {
1134 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1138 * Check if the client provided a valid session id,
1139 * if so smbd_smb2_request_check_session() calls
1140 * set_current_user_info().
1142 * As some command don't require a valid session id
1143 * we defer the check of the session_status
1145 session_status
= smbd_smb2_request_check_session(req
);
1147 req
->do_signing
= false;
1148 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
1149 if (!NT_STATUS_IS_OK(session_status
)) {
1150 return smbd_smb2_request_error(req
, session_status
);
1153 req
->do_signing
= true;
1154 status
= smb2_signing_check_pdu(req
->session
->session_key
,
1155 &req
->in
.vector
[i
], 3);
1156 if (!NT_STATUS_IS_OK(status
)) {
1157 return smbd_smb2_request_error(req
, status
);
1159 } else if (req
->session
&& req
->session
->do_signing
) {
1160 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
1163 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
1165 * This check is mostly for giving the correct error code
1166 * for compounded requests.
1168 * TODO: we may need to move this after the session
1171 if (!NT_STATUS_IS_OK(req
->next_status
)) {
1172 return smbd_smb2_request_error(req
, req
->next_status
);
1175 req
->compat_chain_fsp
= NULL
;
1179 case SMB2_OP_NEGPROT
:
1180 /* This call needs to be run as root */
1181 change_to_root_user();
1184 START_PROFILE(smb2_negprot
);
1185 return_value
= smbd_smb2_request_process_negprot(req
);
1186 END_PROFILE(smb2_negprot
);
1190 case SMB2_OP_SESSSETUP
:
1191 /* This call needs to be run as root */
1192 change_to_root_user();
1195 START_PROFILE(smb2_sesssetup
);
1196 return_value
= smbd_smb2_request_process_sesssetup(req
);
1197 END_PROFILE(smb2_sesssetup
);
1201 case SMB2_OP_LOGOFF
:
1202 if (!NT_STATUS_IS_OK(session_status
)) {
1203 return_value
= smbd_smb2_request_error(req
, session_status
);
1207 /* This call needs to be run as root */
1208 change_to_root_user();
1211 START_PROFILE(smb2_logoff
);
1212 return_value
= smbd_smb2_request_process_logoff(req
);
1213 END_PROFILE(smb2_logoff
);
1218 if (!NT_STATUS_IS_OK(session_status
)) {
1219 return_value
= smbd_smb2_request_error(req
, session_status
);
1224 * This call needs to be run as root.
1226 * smbd_smb2_request_process_tcon()
1227 * calls make_connection_snum(), which will call
1228 * change_to_user(), when needed.
1230 change_to_root_user();
1233 START_PROFILE(smb2_tcon
);
1234 return_value
= smbd_smb2_request_process_tcon(req
);
1235 END_PROFILE(smb2_tcon
);
1240 if (!NT_STATUS_IS_OK(session_status
)) {
1241 return_value
= smbd_smb2_request_error(req
, session_status
);
1245 * This call needs to be run as user.
1247 * smbd_smb2_request_check_tcon()
1248 * calls change_to_user() on success.
1250 status
= smbd_smb2_request_check_tcon(req
);
1251 if (!NT_STATUS_IS_OK(status
)) {
1252 return_value
= smbd_smb2_request_error(req
, status
);
1255 /* This call needs to be run as root */
1256 change_to_root_user();
1260 START_PROFILE(smb2_tdis
);
1261 return_value
= smbd_smb2_request_process_tdis(req
);
1262 END_PROFILE(smb2_tdis
);
1266 case SMB2_OP_CREATE
:
1267 if (!NT_STATUS_IS_OK(session_status
)) {
1268 return_value
= smbd_smb2_request_error(req
, session_status
);
1272 * This call needs to be run as user.
1274 * smbd_smb2_request_check_tcon()
1275 * calls change_to_user() on success.
1277 status
= smbd_smb2_request_check_tcon(req
);
1278 if (!NT_STATUS_IS_OK(status
)) {
1279 return_value
= smbd_smb2_request_error(req
, status
);
1284 START_PROFILE(smb2_create
);
1285 return_value
= smbd_smb2_request_process_create(req
);
1286 END_PROFILE(smb2_create
);
1291 if (!NT_STATUS_IS_OK(session_status
)) {
1292 return_value
= smbd_smb2_request_error(req
, session_status
);
1296 * This call needs to be run as user.
1298 * smbd_smb2_request_check_tcon()
1299 * calls change_to_user() on success.
1301 status
= smbd_smb2_request_check_tcon(req
);
1302 if (!NT_STATUS_IS_OK(status
)) {
1303 return_value
= smbd_smb2_request_error(req
, status
);
1308 START_PROFILE(smb2_close
);
1309 return_value
= smbd_smb2_request_process_close(req
);
1310 END_PROFILE(smb2_close
);
1315 if (!NT_STATUS_IS_OK(session_status
)) {
1316 return_value
= smbd_smb2_request_error(req
, session_status
);
1320 * This call needs to be run as user.
1322 * smbd_smb2_request_check_tcon()
1323 * calls change_to_user() on success.
1325 status
= smbd_smb2_request_check_tcon(req
);
1326 if (!NT_STATUS_IS_OK(status
)) {
1327 return_value
= smbd_smb2_request_error(req
, status
);
1332 START_PROFILE(smb2_flush
);
1333 return_value
= smbd_smb2_request_process_flush(req
);
1334 END_PROFILE(smb2_flush
);
1339 if (!NT_STATUS_IS_OK(session_status
)) {
1340 return_value
= smbd_smb2_request_error(req
, session_status
);
1344 * This call needs to be run as user.
1346 * smbd_smb2_request_check_tcon()
1347 * calls change_to_user() on success.
1349 status
= smbd_smb2_request_check_tcon(req
);
1350 if (!NT_STATUS_IS_OK(status
)) {
1351 return_value
= smbd_smb2_request_error(req
, status
);
1356 START_PROFILE(smb2_read
);
1357 return_value
= smbd_smb2_request_process_read(req
);
1358 END_PROFILE(smb2_read
);
1363 if (!NT_STATUS_IS_OK(session_status
)) {
1364 return_value
= smbd_smb2_request_error(req
, session_status
);
1368 * This call needs to be run as user.
1370 * smbd_smb2_request_check_tcon()
1371 * calls change_to_user() on success.
1373 status
= smbd_smb2_request_check_tcon(req
);
1374 if (!NT_STATUS_IS_OK(status
)) {
1375 return_value
= smbd_smb2_request_error(req
, status
);
1380 START_PROFILE(smb2_write
);
1381 return_value
= smbd_smb2_request_process_write(req
);
1382 END_PROFILE(smb2_write
);
1387 if (!NT_STATUS_IS_OK(session_status
)) {
1388 /* Too ugly to live ? JRA. */
1389 if (NT_STATUS_EQUAL(session_status
,NT_STATUS_USER_SESSION_DELETED
)) {
1390 session_status
= NT_STATUS_FILE_CLOSED
;
1392 return_value
= smbd_smb2_request_error(req
, session_status
);
1396 * This call needs to be run as user.
1398 * smbd_smb2_request_check_tcon()
1399 * calls change_to_user() on success.
1401 status
= smbd_smb2_request_check_tcon(req
);
1402 if (!NT_STATUS_IS_OK(status
)) {
1403 /* Too ugly to live ? JRA. */
1404 if (NT_STATUS_EQUAL(status
,NT_STATUS_NETWORK_NAME_DELETED
)) {
1405 status
= NT_STATUS_FILE_CLOSED
;
1407 return_value
= smbd_smb2_request_error(req
, status
);
1412 START_PROFILE(smb2_lock
);
1413 return_value
= smbd_smb2_request_process_lock(req
);
1414 END_PROFILE(smb2_lock
);
1419 if (!NT_STATUS_IS_OK(session_status
)) {
1420 return_value
= smbd_smb2_request_error(req
, session_status
);
1424 * This call needs to be run as user.
1426 * smbd_smb2_request_check_tcon()
1427 * calls change_to_user() on success.
1429 status
= smbd_smb2_request_check_tcon(req
);
1430 if (!NT_STATUS_IS_OK(status
)) {
1431 return_value
= smbd_smb2_request_error(req
, status
);
1436 START_PROFILE(smb2_ioctl
);
1437 return_value
= smbd_smb2_request_process_ioctl(req
);
1438 END_PROFILE(smb2_ioctl
);
1442 case SMB2_OP_CANCEL
:
1444 * This call needs to be run as root
1446 * That is what we also do in the SMB1 case.
1448 change_to_root_user();
1451 START_PROFILE(smb2_cancel
);
1452 return_value
= smbd_smb2_request_process_cancel(req
);
1453 END_PROFILE(smb2_cancel
);
1457 case SMB2_OP_KEEPALIVE
:
1458 /* This call needs to be run as root */
1459 change_to_root_user();
1462 START_PROFILE(smb2_keepalive
);
1463 return_value
= smbd_smb2_request_process_keepalive(req
);
1464 END_PROFILE(smb2_keepalive
);
1469 if (!NT_STATUS_IS_OK(session_status
)) {
1470 return_value
= smbd_smb2_request_error(req
, session_status
);
1474 * This call needs to be run as user.
1476 * smbd_smb2_request_check_tcon()
1477 * calls change_to_user() on success.
1479 status
= smbd_smb2_request_check_tcon(req
);
1480 if (!NT_STATUS_IS_OK(status
)) {
1481 return_value
= smbd_smb2_request_error(req
, status
);
1486 START_PROFILE(smb2_find
);
1487 return_value
= smbd_smb2_request_process_find(req
);
1488 END_PROFILE(smb2_find
);
1492 case SMB2_OP_NOTIFY
:
1493 if (!NT_STATUS_IS_OK(session_status
)) {
1494 return_value
= smbd_smb2_request_error(req
, session_status
);
1498 * This call needs to be run as user.
1500 * smbd_smb2_request_check_tcon()
1501 * calls change_to_user() on success.
1503 status
= smbd_smb2_request_check_tcon(req
);
1504 if (!NT_STATUS_IS_OK(status
)) {
1505 return_value
= smbd_smb2_request_error(req
, status
);
1510 START_PROFILE(smb2_notify
);
1511 return_value
= smbd_smb2_request_process_notify(req
);
1512 END_PROFILE(smb2_notify
);
1516 case SMB2_OP_GETINFO
:
1517 if (!NT_STATUS_IS_OK(session_status
)) {
1518 return_value
= smbd_smb2_request_error(req
, session_status
);
1522 * This call needs to be run as user.
1524 * smbd_smb2_request_check_tcon()
1525 * calls change_to_user() on success.
1527 status
= smbd_smb2_request_check_tcon(req
);
1528 if (!NT_STATUS_IS_OK(status
)) {
1529 return_value
= smbd_smb2_request_error(req
, status
);
1534 START_PROFILE(smb2_getinfo
);
1535 return_value
= smbd_smb2_request_process_getinfo(req
);
1536 END_PROFILE(smb2_getinfo
);
1540 case SMB2_OP_SETINFO
:
1541 if (!NT_STATUS_IS_OK(session_status
)) {
1542 return_value
= smbd_smb2_request_error(req
, session_status
);
1546 * This call needs to be run as user.
1548 * smbd_smb2_request_check_tcon()
1549 * calls change_to_user() on success.
1551 status
= smbd_smb2_request_check_tcon(req
);
1552 if (!NT_STATUS_IS_OK(status
)) {
1553 return_value
= smbd_smb2_request_error(req
, status
);
1558 START_PROFILE(smb2_setinfo
);
1559 return_value
= smbd_smb2_request_process_setinfo(req
);
1560 END_PROFILE(smb2_setinfo
);
1565 if (!NT_STATUS_IS_OK(session_status
)) {
1566 return_value
= smbd_smb2_request_error(req
, session_status
);
1570 * This call needs to be run as user.
1572 * smbd_smb2_request_check_tcon()
1573 * calls change_to_user() on success.
1575 status
= smbd_smb2_request_check_tcon(req
);
1576 if (!NT_STATUS_IS_OK(status
)) {
1577 return_value
= smbd_smb2_request_error(req
, status
);
1582 START_PROFILE(smb2_break
);
1583 return_value
= smbd_smb2_request_process_break(req
);
1584 END_PROFILE(smb2_break
);
1589 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1592 return return_value
;
1595 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
1597 struct tevent_req
*subreq
;
1598 int i
= req
->current_idx
;
1602 req
->current_idx
+= 3;
1604 if (req
->current_idx
< req
->out
.vector_count
) {
1606 * We must process the remaining compound
1607 * SMB2 requests before any new incoming SMB2
1608 * requests. This is because incoming SMB2
1609 * requests may include a cancel for a
1610 * compound request we haven't processed
1613 struct tevent_immediate
*im
= tevent_create_immediate(req
);
1615 return NT_STATUS_NO_MEMORY
;
1617 tevent_schedule_immediate(im
,
1618 req
->sconn
->smb2
.event_ctx
,
1619 smbd_smb2_request_dispatch_immediate
,
1621 return NT_STATUS_OK
;
1624 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
1626 /* Set credit for this operation (zero credits if this
1627 is a final reply for an async operation). */
1628 smb2_set_operation_credit(req
->sconn
,
1630 &req
->out
.vector
[i
]);
1632 if (req
->do_signing
) {
1634 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
1635 &req
->out
.vector
[i
], 3);
1636 if (!NT_STATUS_IS_OK(status
)) {
1641 if (DEBUGLEVEL
>= 10) {
1642 dbgtext("smbd_smb2_request_reply: sending...\n");
1643 print_req_vectors(req
);
1646 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1647 if (req
->out
.vector_count
== 4 &&
1648 req
->out
.vector
[3].iov_base
== NULL
&&
1649 req
->out
.vector
[3].iov_len
!= 0) {
1650 /* Dynamic part is NULL. Chop it off,
1651 We're going to send it via sendfile. */
1652 req
->out
.vector_count
-= 1;
1655 subreq
= tstream_writev_queue_send(req
,
1656 req
->sconn
->smb2
.event_ctx
,
1657 req
->sconn
->smb2
.stream
,
1658 req
->sconn
->smb2
.send_queue
,
1660 req
->out
.vector_count
);
1661 if (subreq
== NULL
) {
1662 return NT_STATUS_NO_MEMORY
;
1664 tevent_req_set_callback(subreq
, smbd_smb2_request_writev_done
, req
);
1666 * We're done with this request -
1667 * move it off the "being processed" queue.
1669 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1671 return NT_STATUS_OK
;
1674 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
1675 struct tevent_immediate
*im
,
1678 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
1679 struct smbd_smb2_request
);
1680 struct smbd_server_connection
*sconn
= req
->sconn
;
1685 if (DEBUGLEVEL
>= 10) {
1686 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1687 req
->current_idx
, req
->in
.vector_count
));
1688 print_req_vectors(req
);
1691 status
= smbd_smb2_request_dispatch(req
);
1692 if (!NT_STATUS_IS_OK(status
)) {
1693 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1698 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
)
1700 struct smbd_smb2_request
*req
= tevent_req_callback_data(subreq
,
1701 struct smbd_smb2_request
);
1702 struct smbd_server_connection
*sconn
= req
->sconn
;
1706 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1707 TALLOC_FREE(subreq
);
1710 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
1711 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1712 nt_errstr(status
)));
1713 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1718 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
1720 DATA_BLOB body
, DATA_BLOB
*dyn
,
1721 const char *location
)
1724 int i
= req
->current_idx
;
1725 uint32_t next_command_ofs
;
1727 DEBUG(10,("smbd_smb2_request_done_ex: "
1728 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1729 i
, nt_errstr(status
), (unsigned int)body
.length
,
1731 (unsigned int)(dyn
? dyn
->length
: 0),
1734 if (body
.length
< 2) {
1735 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
1738 if ((body
.length
% 2) != 0) {
1739 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
1742 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
1744 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
1745 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
1747 req
->out
.vector
[i
+1].iov_base
= (void *)body
.data
;
1748 req
->out
.vector
[i
+1].iov_len
= body
.length
;
1751 req
->out
.vector
[i
+2].iov_base
= (void *)dyn
->data
;
1752 req
->out
.vector
[i
+2].iov_len
= dyn
->length
;
1754 req
->out
.vector
[i
+2].iov_base
= NULL
;
1755 req
->out
.vector
[i
+2].iov_len
= 0;
1758 /* see if we need to recalculate the offset to the next response */
1759 if (next_command_ofs
> 0) {
1760 next_command_ofs
= SMB2_HDR_BODY
;
1761 next_command_ofs
+= req
->out
.vector
[i
+1].iov_len
;
1762 next_command_ofs
+= req
->out
.vector
[i
+2].iov_len
;
1765 if ((next_command_ofs
% 8) != 0) {
1766 size_t pad_size
= 8 - (next_command_ofs
% 8);
1767 if (req
->out
.vector
[i
+2].iov_len
== 0) {
1769 * if the dyn buffer is empty
1770 * we can use it to add padding
1774 pad
= talloc_zero_array(req
->out
.vector
,
1777 return smbd_smb2_request_error(req
,
1778 NT_STATUS_NO_MEMORY
);
1781 req
->out
.vector
[i
+2].iov_base
= (void *)pad
;
1782 req
->out
.vector
[i
+2].iov_len
= pad_size
;
1785 * For now we copy the dynamic buffer
1786 * and add the padding to the new buffer
1793 old_size
= req
->out
.vector
[i
+2].iov_len
;
1794 old_dyn
= (uint8_t *)req
->out
.vector
[i
+2].iov_base
;
1796 new_size
= old_size
+ pad_size
;
1797 new_dyn
= talloc_zero_array(req
->out
.vector
,
1799 if (new_dyn
== NULL
) {
1800 return smbd_smb2_request_error(req
,
1801 NT_STATUS_NO_MEMORY
);
1804 memcpy(new_dyn
, old_dyn
, old_size
);
1805 memset(new_dyn
+ old_size
, 0, pad_size
);
1807 req
->out
.vector
[i
+2].iov_base
= (void *)new_dyn
;
1808 req
->out
.vector
[i
+2].iov_len
= new_size
;
1810 next_command_ofs
+= pad_size
;
1813 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
1815 return smbd_smb2_request_reply(req
);
1818 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
1821 const char *location
)
1824 int i
= req
->current_idx
;
1825 uint8_t *outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
1827 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1828 i
, nt_errstr(status
), info
? " +info" : "",
1831 body
.data
= outhdr
+ SMB2_HDR_BODY
;
1833 SSVAL(body
.data
, 0, 9);
1836 SIVAL(body
.data
, 0x04, info
->length
);
1838 /* Allocated size of req->out.vector[i].iov_base
1839 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
1840 * 1 byte without having to do an alloc.
1842 info
= talloc_zero_array(req
->out
.vector
,
1846 return NT_STATUS_NO_MEMORY
;
1848 info
->data
= ((uint8_t *)outhdr
) +
1849 OUTVEC_ALLOC_SIZE
- 1;
1851 SCVAL(info
->data
, 0, 0);
1855 * if a request fails, all other remaining
1856 * compounded requests should fail too
1858 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
1860 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
1864 struct smbd_smb2_send_oplock_break_state
{
1865 struct smbd_server_connection
*sconn
;
1866 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x18];
1867 struct iovec vector
;
1870 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
);
1872 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
1873 uint64_t file_id_persistent
,
1874 uint64_t file_id_volatile
,
1875 uint8_t oplock_level
)
1877 struct smbd_smb2_send_oplock_break_state
*state
;
1878 struct tevent_req
*subreq
;
1882 state
= talloc(sconn
, struct smbd_smb2_send_oplock_break_state
);
1883 if (state
== NULL
) {
1884 return NT_STATUS_NO_MEMORY
;
1886 state
->sconn
= sconn
;
1888 state
->vector
.iov_base
= (void *)state
->buf
;
1889 state
->vector
.iov_len
= sizeof(state
->buf
);
1891 _smb2_setlen(state
->buf
, sizeof(state
->buf
) - 4);
1892 hdr
= state
->buf
+ 4;
1893 body
= hdr
+ SMB2_HDR_BODY
;
1895 SIVAL(hdr
, 0, SMB2_MAGIC
);
1896 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1897 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1898 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
1899 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
1900 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
1901 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
1902 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1903 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
1904 SIVAL(hdr
, SMB2_HDR_PID
, 0);
1905 SIVAL(hdr
, SMB2_HDR_TID
, 0);
1906 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
1907 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
1909 SSVAL(body
, 0x00, 0x18);
1911 SCVAL(body
, 0x02, oplock_level
);
1912 SCVAL(body
, 0x03, 0); /* reserved */
1913 SIVAL(body
, 0x04, 0); /* reserved */
1914 SBVAL(body
, 0x08, file_id_persistent
);
1915 SBVAL(body
, 0x10, file_id_volatile
);
1917 subreq
= tstream_writev_queue_send(state
,
1918 sconn
->smb2
.event_ctx
,
1920 sconn
->smb2
.send_queue
,
1922 if (subreq
== NULL
) {
1923 return NT_STATUS_NO_MEMORY
;
1925 tevent_req_set_callback(subreq
,
1926 smbd_smb2_oplock_break_writev_done
,
1929 return NT_STATUS_OK
;
1932 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
)
1934 struct smbd_smb2_send_oplock_break_state
*state
=
1935 tevent_req_callback_data(subreq
,
1936 struct smbd_smb2_send_oplock_break_state
);
1937 struct smbd_server_connection
*sconn
= state
->sconn
;
1941 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1942 TALLOC_FREE(subreq
);
1944 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
1945 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1952 struct smbd_smb2_request_read_state
{
1954 bool asked_for_header
;
1955 struct smbd_smb2_request
*smb2_req
;
1958 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
1960 TALLOC_CTX
*mem_ctx
,
1961 struct iovec
**_vector
,
1963 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
);
1965 static struct tevent_req
*smbd_smb2_request_read_send(TALLOC_CTX
*mem_ctx
,
1966 struct tevent_context
*ev
,
1967 struct smbd_server_connection
*sconn
)
1969 struct tevent_req
*req
;
1970 struct smbd_smb2_request_read_state
*state
;
1971 struct tevent_req
*subreq
;
1973 req
= tevent_req_create(mem_ctx
, &state
,
1974 struct smbd_smb2_request_read_state
);
1979 state
->asked_for_header
= false;
1981 state
->smb2_req
= smbd_smb2_request_allocate(state
);
1982 if (tevent_req_nomem(state
->smb2_req
, req
)) {
1983 return tevent_req_post(req
, ev
);
1985 state
->smb2_req
->sconn
= sconn
;
1987 subreq
= tstream_readv_pdu_queue_send(state
, ev
, sconn
->smb2
.stream
,
1988 sconn
->smb2
.recv_queue
,
1989 smbd_smb2_request_next_vector
,
1991 if (tevent_req_nomem(subreq
, req
)) {
1992 return tevent_req_post(req
, ev
);
1994 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
1999 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2001 TALLOC_CTX
*mem_ctx
,
2002 struct iovec
**_vector
,
2005 struct smbd_smb2_request_read_state
*state
=
2006 talloc_get_type_abort(private_data
,
2007 struct smbd_smb2_request_read_state
);
2008 struct smbd_smb2_request
*req
= state
->smb2_req
;
2009 struct iovec
*vector
;
2010 int idx
= req
->in
.vector_count
;
2012 uint8_t *buf
= NULL
;
2014 if (req
->in
.vector_count
== 0) {
2016 * first we need to get the NBT header
2018 req
->in
.vector
= talloc_array(req
, struct iovec
,
2019 req
->in
.vector_count
+ 1);
2020 if (req
->in
.vector
== NULL
) {
2023 req
->in
.vector_count
+= 1;
2025 req
->in
.vector
[idx
].iov_base
= (void *)req
->in
.nbt_hdr
;
2026 req
->in
.vector
[idx
].iov_len
= 4;
2028 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2029 if (vector
== NULL
) {
2033 vector
[0] = req
->in
.vector
[idx
];
2040 if (req
->in
.vector_count
== 1) {
2042 * Now we analyze the NBT header
2044 state
->missing
= smb2_len(req
->in
.vector
[0].iov_base
);
2046 if (state
->missing
== 0) {
2047 /* if there're no remaining bytes, we're done */
2053 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2055 req
->in
.vector_count
+ 1);
2056 if (req
->in
.vector
== NULL
) {
2059 req
->in
.vector_count
+= 1;
2061 if (CVAL(req
->in
.vector
[0].iov_base
, 0) != 0) {
2063 * it's a special NBT message,
2064 * so get all remaining bytes
2066 len
= state
->missing
;
2067 } else if (state
->missing
< (SMB2_HDR_BODY
+ 2)) {
2069 * it's an invalid message, just read what we can get
2070 * and let the caller handle the error
2072 len
= state
->missing
;
2075 * We assume it's a SMB2 request,
2076 * and we first get the header and the
2077 * first 2 bytes (the struct size) of the body
2079 len
= SMB2_HDR_BODY
+ 2;
2081 state
->asked_for_header
= true;
2084 state
->missing
-= len
;
2086 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2091 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2092 req
->in
.vector
[idx
].iov_len
= len
;
2094 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2095 if (vector
== NULL
) {
2099 vector
[0] = req
->in
.vector
[idx
];
2106 if (state
->missing
== 0) {
2107 /* if there're no remaining bytes, we're done */
2113 if (state
->asked_for_header
) {
2116 size_t next_command_ofs
;
2121 bool invalid
= false;
2123 state
->asked_for_header
= false;
2126 * We got the SMB2 header and the first 2 bytes
2127 * of the body. We fix the size to just the header
2128 * and manually copy the 2 first bytes to the body section
2130 req
->in
.vector
[idx
-1].iov_len
= SMB2_HDR_BODY
;
2131 hdr
= (const uint8_t *)req
->in
.vector
[idx
-1].iov_base
;
2133 /* allocate vectors for body and dynamic areas */
2134 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2136 req
->in
.vector_count
+ 2);
2137 if (req
->in
.vector
== NULL
) {
2140 req
->in
.vector_count
+= 2;
2142 full_size
= state
->missing
+ SMB2_HDR_BODY
+ 2;
2143 next_command_ofs
= IVAL(hdr
, SMB2_HDR_NEXT_COMMAND
);
2144 body_size
= SVAL(hdr
, SMB2_HDR_BODY
);
2146 if (next_command_ofs
!= 0) {
2147 if (next_command_ofs
< (SMB2_HDR_BODY
+ 2)) {
2149 * this is invalid, just return a zero
2150 * body and let the caller deal with the error
2153 } else if (next_command_ofs
> full_size
) {
2155 * this is invalid, just return a zero
2156 * body and let the caller deal with the error
2160 full_size
= next_command_ofs
;
2165 if (body_size
< 2) {
2167 * this is invalid, just return a zero
2168 * body and let the caller deal with the error
2173 if ((body_size
% 2) != 0) {
2177 if (body_size
> (full_size
- SMB2_HDR_BODY
)) {
2179 * this is invalid, just return a zero
2180 * body and let the caller deal with the error
2187 /* the caller should check this */
2191 dyn_size
= full_size
- (SMB2_HDR_BODY
+ body_size
);
2193 state
->missing
-= (body_size
- 2) + dyn_size
;
2195 body
= talloc_array(req
->in
.vector
, uint8_t, body_size
);
2200 dyn
= talloc_array(req
->in
.vector
, uint8_t, dyn_size
);
2205 req
->in
.vector
[idx
].iov_base
= (void *)body
;
2206 req
->in
.vector
[idx
].iov_len
= body_size
;
2207 req
->in
.vector
[idx
+1].iov_base
= (void *)dyn
;
2208 req
->in
.vector
[idx
+1].iov_len
= dyn_size
;
2210 vector
= talloc_array(mem_ctx
, struct iovec
, 2);
2211 if (vector
== NULL
) {
2216 * the first 2 bytes of the body were already fetched
2217 * together with the header
2219 memcpy(body
, hdr
+ SMB2_HDR_BODY
, 2);
2220 vector
[0].iov_base
= body
+ 2;
2221 vector
[0].iov_len
= body_size
- 2;
2223 vector
[1] = req
->in
.vector
[idx
+1];
2231 * when we endup here, we're looking for a new SMB2 request
2232 * next. And we ask for its header and the first 2 bytes of
2233 * the body (like we did for the first SMB2 request).
2236 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2238 req
->in
.vector_count
+ 1);
2239 if (req
->in
.vector
== NULL
) {
2242 req
->in
.vector_count
+= 1;
2245 * We assume it's a SMB2 request,
2246 * and we first get the header and the
2247 * first 2 bytes (the struct size) of the body
2249 len
= SMB2_HDR_BODY
+ 2;
2251 if (len
> state
->missing
) {
2252 /* let the caller handle the error */
2253 len
= state
->missing
;
2256 state
->missing
-= len
;
2257 state
->asked_for_header
= true;
2259 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2264 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2265 req
->in
.vector
[idx
].iov_len
= len
;
2267 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2268 if (vector
== NULL
) {
2272 vector
[0] = req
->in
.vector
[idx
];
2279 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
)
2281 struct tevent_req
*req
=
2282 tevent_req_callback_data(subreq
,
2288 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
2290 status
= map_nt_error_from_unix(sys_errno
);
2291 tevent_req_nterror(req
, status
);
2295 tevent_req_done(req
);
2298 static NTSTATUS
smbd_smb2_request_read_recv(struct tevent_req
*req
,
2299 TALLOC_CTX
*mem_ctx
,
2300 struct smbd_smb2_request
**_smb2_req
)
2302 struct smbd_smb2_request_read_state
*state
=
2303 tevent_req_data(req
,
2304 struct smbd_smb2_request_read_state
);
2307 if (tevent_req_is_nterror(req
, &status
)) {
2308 tevent_req_received(req
);
2312 talloc_steal(mem_ctx
, state
->smb2_req
->mem_pool
);
2313 *_smb2_req
= state
->smb2_req
;
2314 tevent_req_received(req
);
2315 return NT_STATUS_OK
;
2318 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
);
2320 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
2321 const uint8_t *inbuf
, size_t size
)
2324 struct smbd_smb2_request
*req
= NULL
;
2325 struct tevent_req
*subreq
;
2327 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2328 (unsigned int)size
));
2330 status
= smbd_initialize_smb2(sconn
);
2331 if (!NT_STATUS_IS_OK(status
)) {
2332 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2336 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
2337 if (!NT_STATUS_IS_OK(status
)) {
2338 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2342 status
= smbd_smb2_request_setup_out(req
);
2343 if (!NT_STATUS_IS_OK(status
)) {
2344 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2348 status
= smbd_smb2_request_dispatch(req
);
2349 if (!NT_STATUS_IS_OK(status
)) {
2350 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2354 /* ask for the next request */
2355 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->smb2
.event_ctx
, sconn
);
2356 if (subreq
== NULL
) {
2357 smbd_server_connection_terminate(sconn
, "no memory for reading");
2360 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);
2362 sconn
->num_requests
++;
2365 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
)
2367 struct smbd_server_connection
*sconn
= tevent_req_callback_data(subreq
,
2368 struct smbd_server_connection
);
2370 struct smbd_smb2_request
*req
= NULL
;
2372 status
= smbd_smb2_request_read_recv(subreq
, sconn
, &req
);
2373 TALLOC_FREE(subreq
);
2374 if (!NT_STATUS_IS_OK(status
)) {
2375 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2376 nt_errstr(status
)));
2377 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2381 if (req
->in
.nbt_hdr
[0] != 0x00) {
2382 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2383 req
->in
.nbt_hdr
[0]));
2388 req
->current_idx
= 1;
2390 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2391 req
->current_idx
, req
->in
.vector_count
));
2393 status
= smbd_smb2_request_validate(req
);
2394 if (!NT_STATUS_IS_OK(status
)) {
2395 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2399 status
= smbd_smb2_request_setup_out(req
);
2400 if (!NT_STATUS_IS_OK(status
)) {
2401 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2405 status
= smbd_smb2_request_dispatch(req
);
2406 if (!NT_STATUS_IS_OK(status
)) {
2407 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2412 /* ask for the next request (this constructs the main loop) */
2413 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->smb2
.event_ctx
, sconn
);
2414 if (subreq
== NULL
) {
2415 smbd_server_connection_terminate(sconn
, "no memory for reading");
2418 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);
2420 sconn
->num_requests
++;
2422 /* The timeout_processing function isn't run nearly
2423 often enough to implement 'max log size' without
2424 overrunning the size of the file by many megabytes.
2425 This is especially true if we are running at debug
2426 level 10. Checking every 50 SMB2s is a nice
2427 tradeoff of performance vs log file size overrun. */
2429 if ((sconn
->num_requests
% 50) == 0 &&
2430 need_to_check_log_size()) {
2431 change_to_root_user();