2 Unix SMB/CIFS implementation.
5 Copyright (C) Stefan Metzmacher 2009
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "smbd/globals.h"
23 #include "../libcli/smb/smb_common.h"
24 #include "../lib/tsocket/tsocket.h"
26 bool smbd_is_smb2_header(const uint8_t *inbuf
, size_t size
)
28 if (size
< (4 + SMB2_HDR_BODY
)) {
32 if (IVAL(inbuf
, 4) != SMB2_MAGIC
) {
39 static NTSTATUS
smbd_initialize_smb2(struct smbd_server_connection
*sconn
)
44 TALLOC_FREE(sconn
->smb1
.fde
);
46 sconn
->smb2
.event_ctx
= smbd_event_context();
48 sconn
->smb2
.recv_queue
= tevent_queue_create(sconn
, "smb2 recv queue");
49 if (sconn
->smb2
.recv_queue
== NULL
) {
50 return NT_STATUS_NO_MEMORY
;
53 sconn
->smb2
.send_queue
= tevent_queue_create(sconn
, "smb2 send queue");
54 if (sconn
->smb2
.send_queue
== NULL
) {
55 return NT_STATUS_NO_MEMORY
;
58 sconn
->smb2
.sessions
.idtree
= idr_init(sconn
);
59 if (sconn
->smb2
.sessions
.idtree
== NULL
) {
60 return NT_STATUS_NO_MEMORY
;
62 sconn
->smb2
.sessions
.limit
= 0x0000FFFE;
63 sconn
->smb2
.sessions
.list
= NULL
;
65 ret
= tstream_bsd_existing_socket(sconn
, smbd_server_fd(),
68 status
= map_nt_error_from_unix(errno
);
72 /* Ensure child is set to non-blocking mode */
73 set_blocking(smbd_server_fd(),false);
77 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
78 #define _smb2_setlen(_buf,len) do { \
79 uint8_t *buf = (uint8_t *)_buf; \
81 buf[1] = ((len)&0xFF0000)>>16; \
82 buf[2] = ((len)&0xFF00)>>8; \
83 buf[3] = (len)&0xFF; \
86 static void smb2_setup_nbt_length(struct iovec
*vector
, int count
)
91 for (i
=1; i
< count
; i
++) {
92 len
+= vector
[i
].iov_len
;
95 _smb2_setlen(vector
[0].iov_base
, len
);
98 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request
**req
)
101 (*req
)->parent
= NULL
;
102 (*req
)->mem_pool
= NULL
;
108 static int smbd_smb2_request_destructor(struct smbd_smb2_request
*req
)
110 if (req
->out
.vector
) {
111 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
116 talloc_free(req
->mem_pool
);
122 static struct smbd_smb2_request
*smbd_smb2_request_allocate(TALLOC_CTX
*mem_ctx
)
124 TALLOC_CTX
*mem_pool
;
125 struct smbd_smb2_request
**parent
;
126 struct smbd_smb2_request
*req
;
128 mem_pool
= talloc_pool(mem_ctx
, 8192);
129 if (mem_pool
== NULL
) {
133 parent
= talloc(mem_pool
, struct smbd_smb2_request
*);
134 if (parent
== NULL
) {
135 talloc_free(mem_pool
);
139 req
= talloc_zero(parent
, struct smbd_smb2_request
);
141 talloc_free(mem_pool
);
145 req
->mem_pool
= mem_pool
;
146 req
->parent
= parent
;
148 talloc_set_destructor(parent
, smbd_smb2_request_parent_destructor
);
149 talloc_set_destructor(req
, smbd_smb2_request_destructor
);
154 static NTSTATUS
smbd_smb2_request_create(struct smbd_server_connection
*sconn
,
155 const uint8_t *inbuf
, size_t size
,
156 struct smbd_smb2_request
**_req
)
158 struct smbd_smb2_request
*req
;
159 uint32_t protocol_version
;
160 const uint8_t *inhdr
= NULL
;
163 uint32_t next_command_ofs
;
165 if (size
< (4 + SMB2_HDR_BODY
+ 2)) {
166 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size
));
167 return NT_STATUS_INVALID_PARAMETER
;
172 protocol_version
= IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
);
173 if (protocol_version
!= SMB2_MAGIC
) {
174 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
176 return NT_STATUS_INVALID_PARAMETER
;
179 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
180 if (cmd
!= SMB2_OP_NEGPROT
) {
181 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
183 return NT_STATUS_INVALID_PARAMETER
;
186 next_command_ofs
= IVAL(inhdr
, SMB2_HDR_NEXT_COMMAND
);
187 if (next_command_ofs
!= 0) {
188 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
190 return NT_STATUS_INVALID_PARAMETER
;
193 req
= smbd_smb2_request_allocate(sconn
);
195 return NT_STATUS_NO_MEMORY
;
199 talloc_steal(req
, inbuf
);
201 req
->in
.vector
= talloc_array(req
, struct iovec
, 4);
202 if (req
->in
.vector
== NULL
) {
204 return NT_STATUS_NO_MEMORY
;
206 req
->in
.vector_count
= 4;
208 memcpy(req
->in
.nbt_hdr
, inbuf
, 4);
211 req
->in
.vector
[0].iov_base
= (void *)req
->in
.nbt_hdr
;
212 req
->in
.vector
[0].iov_len
= 4;
213 ofs
+= req
->in
.vector
[0].iov_len
;
215 req
->in
.vector
[1].iov_base
= (void *)(inbuf
+ ofs
);
216 req
->in
.vector
[1].iov_len
= SMB2_HDR_BODY
;
217 ofs
+= req
->in
.vector
[1].iov_len
;
219 req
->in
.vector
[2].iov_base
= (void *)(inbuf
+ ofs
);
220 req
->in
.vector
[2].iov_len
= SVAL(inbuf
, ofs
) & 0xFFFE;
221 ofs
+= req
->in
.vector
[2].iov_len
;
224 return NT_STATUS_INVALID_PARAMETER
;
227 req
->in
.vector
[3].iov_base
= (void *)(inbuf
+ ofs
);
228 req
->in
.vector
[3].iov_len
= size
- ofs
;
229 ofs
+= req
->in
.vector
[3].iov_len
;
231 req
->current_idx
= 1;
237 static NTSTATUS
smbd_smb2_request_validate(struct smbd_smb2_request
*req
,
238 uint16_t *p_creds_requested
)
242 bool compound_related
= false;
244 count
= req
->in
.vector_count
;
247 /* It's not a SMB2 request */
248 return NT_STATUS_INVALID_PARAMETER
;
251 for (idx
=1; idx
< count
; idx
+= 3) {
252 const uint8_t *inhdr
= NULL
;
255 if (req
->in
.vector
[idx
].iov_len
!= SMB2_HDR_BODY
) {
256 return NT_STATUS_INVALID_PARAMETER
;
259 if (req
->in
.vector
[idx
+1].iov_len
< 2) {
260 return NT_STATUS_INVALID_PARAMETER
;
263 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
265 /* setup the SMB2 header */
266 if (IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
) != SMB2_MAGIC
) {
267 return NT_STATUS_INVALID_PARAMETER
;
270 *p_creds_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
272 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
275 * the 1st request should never have the
276 * SMB2_HDR_FLAG_CHAINED flag set
278 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
279 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
282 } else if (idx
== 4) {
284 * the 2nd request triggers related vs. unrelated
285 * compounded requests
287 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
288 compound_related
= true;
290 } else if (idx
> 4) {
293 * It seems the this tests are wrong
294 * see the SMB2-COMPOUND test
298 * all other requests should match the 2nd one
300 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
301 if (!compound_related
) {
303 NT_STATUS_INVALID_PARAMETER
;
307 if (compound_related
) {
309 NT_STATUS_INVALID_PARAMETER
;
320 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
, uint16_t creds
)
322 struct iovec
*vector
;
326 count
= req
->in
.vector_count
;
327 vector
= talloc_array(req
, struct iovec
, count
);
328 if (vector
== NULL
) {
329 return NT_STATUS_NO_MEMORY
;
332 vector
[0].iov_base
= req
->out
.nbt_hdr
;
333 vector
[0].iov_len
= 4;
334 SIVAL(req
->out
.nbt_hdr
, 0, 0);
336 for (idx
=1; idx
< count
; idx
+= 3) {
337 const uint8_t *inhdr
= NULL
;
339 uint8_t *outhdr
= NULL
;
340 uint8_t *outbody
= NULL
;
341 uint32_t next_command_ofs
= 0;
342 struct iovec
*current
= &vector
[idx
];
344 if ((idx
+ 3) < count
) {
345 /* we have a next command */
346 next_command_ofs
= SMB2_HDR_BODY
+ 8;
349 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
350 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
352 outhdr
= talloc_array(vector
, uint8_t,
354 if (outhdr
== NULL
) {
355 return NT_STATUS_NO_MEMORY
;
358 outbody
= outhdr
+ SMB2_HDR_BODY
;
360 current
[0].iov_base
= (void *)outhdr
;
361 current
[0].iov_len
= SMB2_HDR_BODY
;
363 current
[1].iov_base
= (void *)outbody
;
364 current
[1].iov_len
= 8;
366 current
[2].iov_base
= NULL
;
367 current
[2].iov_len
= 0;
369 /* setup the SMB2 header */
370 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
371 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
372 SSVAL(outhdr
, SMB2_HDR_EPOCH
, 0);
373 SIVAL(outhdr
, SMB2_HDR_STATUS
,
374 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
375 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
376 SVAL(inhdr
, SMB2_HDR_OPCODE
));
377 SSVAL(outhdr
, SMB2_HDR_CREDIT
, creds
);
378 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
379 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
380 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
381 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
382 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
383 SIVAL(outhdr
, SMB2_HDR_PID
,
384 IVAL(inhdr
, SMB2_HDR_PID
));
385 SIVAL(outhdr
, SMB2_HDR_TID
,
386 IVAL(inhdr
, SMB2_HDR_TID
));
387 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
388 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
389 memset(outhdr
+ SMB2_HDR_SIGNATURE
, 0, 16);
391 /* setup error body header */
392 SSVAL(outbody
, 0x00, 0x08 + 1);
393 SSVAL(outbody
, 0x02, 0);
394 SIVAL(outbody
, 0x04, 0);
397 req
->out
.vector
= vector
;
398 req
->out
.vector_count
= count
;
400 /* setup the length of the NBT packet */
401 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
403 DLIST_ADD_END(req
->sconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
408 void smbd_server_connection_terminate_ex(struct smbd_server_connection
*sconn
,
410 const char *location
)
412 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
414 exit_server_cleanly(reason
);
417 struct smbd_smb2_request_pending_state
{
418 struct smbd_server_connection
*sconn
;
419 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x08];
423 static void smbd_smb2_request_pending_writev_done(struct tevent_req
*subreq
);
425 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
426 struct tevent_req
*subreq
)
428 struct smbd_smb2_request_pending_state
*state
;
430 int i
= req
->current_idx
;
437 if (!tevent_req_is_in_progress(subreq
)) {
441 req
->subreq
= subreq
;
444 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
446 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
447 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
449 async_id
= message_id
; /* keep it simple for now... */
450 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
451 SBVAL(outhdr
, SMB2_HDR_PID
, async_id
);
453 /* TODO: add a paramter to delay this */
454 state
= talloc(req
->sconn
, struct smbd_smb2_request_pending_state
);
456 return NT_STATUS_NO_MEMORY
;
458 state
->sconn
= req
->sconn
;
460 state
->vector
.iov_base
= (void *)state
->buf
;
461 state
->vector
.iov_len
= sizeof(state
->buf
);
463 _smb2_setlen(state
->buf
, sizeof(state
->buf
) - 4);
464 hdr
= state
->buf
+ 4;
465 body
= hdr
+ SMB2_HDR_BODY
;
467 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
468 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
469 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
470 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
471 SSVAL(hdr
, SMB2_HDR_OPCODE
,
472 SVAL(outhdr
, SMB2_HDR_OPCODE
));
473 SSVAL(hdr
, SMB2_HDR_CREDIT
, 1);
474 SIVAL(hdr
, SMB2_HDR_FLAGS
,
475 IVAL(outhdr
, SMB2_HDR_FLAGS
));
476 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
477 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
,
478 BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
));
479 SBVAL(hdr
, SMB2_HDR_PID
,
480 BVAL(outhdr
, SMB2_HDR_PID
));
481 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
482 BVAL(outhdr
, SMB2_HDR_SESSION_ID
));
483 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
485 SSVAL(body
, 0x00, 0x08 + 1);
487 SCVAL(body
, 0x02, 0);
488 SCVAL(body
, 0x03, 0);
489 SIVAL(body
, 0x04, 0);
491 subreq
= tstream_writev_queue_send(state
,
492 req
->sconn
->smb2
.event_ctx
,
493 req
->sconn
->smb2
.stream
,
494 req
->sconn
->smb2
.send_queue
,
496 if (subreq
== NULL
) {
497 return NT_STATUS_NO_MEMORY
;
499 tevent_req_set_callback(subreq
,
500 smbd_smb2_request_pending_writev_done
,
506 static void smbd_smb2_request_pending_writev_done(struct tevent_req
*subreq
)
508 struct smbd_smb2_request_pending_state
*state
=
509 tevent_req_callback_data(subreq
,
510 struct smbd_smb2_request_pending_state
);
511 struct smbd_server_connection
*sconn
= state
->sconn
;
515 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
518 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
519 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
526 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
528 struct smbd_server_connection
*sconn
= req
->sconn
;
529 struct smbd_smb2_request
*cur
;
530 const uint8_t *inhdr
;
531 int i
= req
->current_idx
;
533 uint64_t search_message_id
;
534 uint64_t search_async_id
;
536 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
538 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
539 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
540 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
543 * we don't need the request anymore
544 * cancel requests never have a response
548 for (cur
= sconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
549 const uint8_t *outhdr
;
553 i
= cur
->current_idx
;
555 outhdr
= (const uint8_t *)cur
->out
.vector
[i
].iov_base
;
557 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
558 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
560 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
561 if (search_async_id
== async_id
) {
565 if (search_message_id
== message_id
) {
571 if (cur
&& cur
->subreq
) {
572 tevent_req_cancel(cur
->subreq
);
578 static NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
580 const uint8_t *inhdr
;
581 int i
= req
->current_idx
;
585 NTSTATUS session_status
;
586 uint32_t allowed_flags
;
588 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
590 /* TODO: verify more things */
592 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
593 opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
594 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%u]\n", opcode
));
596 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
597 SMB2_HDR_FLAG_SIGNED
|
599 if (opcode
== SMB2_OP_CANCEL
) {
600 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
602 if ((flags
& ~allowed_flags
) != 0) {
603 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
606 session_status
= smbd_smb2_request_check_session(req
);
608 req
->do_signing
= false;
609 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
610 if (!NT_STATUS_IS_OK(session_status
)) {
611 return smbd_smb2_request_error(req
, session_status
);
614 req
->do_signing
= true;
615 status
= smb2_signing_check_pdu(req
->session
->session_key
,
616 &req
->in
.vector
[i
], 3);
617 if (!NT_STATUS_IS_OK(status
)) {
618 return smbd_smb2_request_error(req
, status
);
620 } else if (req
->session
&& req
->session
->do_signing
) {
621 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
624 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
626 * This check is mostly for giving the correct error code
627 * for compounded requests.
629 * TODO: we may need to move this after the session
632 if (!NT_STATUS_IS_OK(req
->next_status
)) {
633 return smbd_smb2_request_error(req
, req
->next_status
);
636 req
->compat_chain_fsp
= NULL
;
640 case SMB2_OP_NEGPROT
:
641 return smbd_smb2_request_process_negprot(req
);
643 case SMB2_OP_SESSSETUP
:
644 return smbd_smb2_request_process_sesssetup(req
);
647 if (!NT_STATUS_IS_OK(session_status
)) {
648 return smbd_smb2_request_error(req
, session_status
);
650 return smbd_smb2_request_process_logoff(req
);
653 if (!NT_STATUS_IS_OK(session_status
)) {
654 return smbd_smb2_request_error(req
, session_status
);
656 status
= smbd_smb2_request_check_session(req
);
657 if (!NT_STATUS_IS_OK(status
)) {
658 return smbd_smb2_request_error(req
, status
);
660 return smbd_smb2_request_process_tcon(req
);
663 if (!NT_STATUS_IS_OK(session_status
)) {
664 return smbd_smb2_request_error(req
, session_status
);
666 status
= smbd_smb2_request_check_tcon(req
);
667 if (!NT_STATUS_IS_OK(status
)) {
668 return smbd_smb2_request_error(req
, status
);
670 return smbd_smb2_request_process_tdis(req
);
673 if (!NT_STATUS_IS_OK(session_status
)) {
674 return smbd_smb2_request_error(req
, session_status
);
676 status
= smbd_smb2_request_check_tcon(req
);
677 if (!NT_STATUS_IS_OK(status
)) {
678 return smbd_smb2_request_error(req
, status
);
680 return smbd_smb2_request_process_create(req
);
683 if (!NT_STATUS_IS_OK(session_status
)) {
684 return smbd_smb2_request_error(req
, session_status
);
686 status
= smbd_smb2_request_check_tcon(req
);
687 if (!NT_STATUS_IS_OK(status
)) {
688 return smbd_smb2_request_error(req
, status
);
690 return smbd_smb2_request_process_close(req
);
693 if (!NT_STATUS_IS_OK(session_status
)) {
694 return smbd_smb2_request_error(req
, session_status
);
696 status
= smbd_smb2_request_check_tcon(req
);
697 if (!NT_STATUS_IS_OK(status
)) {
698 return smbd_smb2_request_error(req
, status
);
700 return smbd_smb2_request_process_flush(req
);
703 if (!NT_STATUS_IS_OK(session_status
)) {
704 return smbd_smb2_request_error(req
, session_status
);
706 status
= smbd_smb2_request_check_tcon(req
);
707 if (!NT_STATUS_IS_OK(status
)) {
708 return smbd_smb2_request_error(req
, status
);
710 return smbd_smb2_request_process_read(req
);
713 if (!NT_STATUS_IS_OK(session_status
)) {
714 return smbd_smb2_request_error(req
, session_status
);
716 status
= smbd_smb2_request_check_tcon(req
);
717 if (!NT_STATUS_IS_OK(status
)) {
718 return smbd_smb2_request_error(req
, status
);
720 return smbd_smb2_request_process_write(req
);
723 if (!NT_STATUS_IS_OK(session_status
)) {
724 return smbd_smb2_request_error(req
, session_status
);
726 status
= smbd_smb2_request_check_tcon(req
);
727 if (!NT_STATUS_IS_OK(status
)) {
728 return smbd_smb2_request_error(req
, status
);
730 return smbd_smb2_request_process_lock(req
);
733 if (!NT_STATUS_IS_OK(session_status
)) {
734 return smbd_smb2_request_error(req
, session_status
);
736 status
= smbd_smb2_request_check_tcon(req
);
737 if (!NT_STATUS_IS_OK(status
)) {
738 return smbd_smb2_request_error(req
, status
);
740 return smbd_smb2_request_process_ioctl(req
);
743 return smbd_smb2_request_process_cancel(req
);
745 case SMB2_OP_KEEPALIVE
:
746 return smbd_smb2_request_process_keepalive(req
);
749 if (!NT_STATUS_IS_OK(session_status
)) {
750 return smbd_smb2_request_error(req
, session_status
);
752 status
= smbd_smb2_request_check_tcon(req
);
753 if (!NT_STATUS_IS_OK(status
)) {
754 return smbd_smb2_request_error(req
, status
);
756 return smbd_smb2_request_process_find(req
);
759 if (!NT_STATUS_IS_OK(session_status
)) {
760 return smbd_smb2_request_error(req
, session_status
);
762 status
= smbd_smb2_request_check_tcon(req
);
763 if (!NT_STATUS_IS_OK(status
)) {
764 return smbd_smb2_request_error(req
, status
);
766 return smbd_smb2_request_process_notify(req
);
768 case SMB2_OP_GETINFO
:
769 if (!NT_STATUS_IS_OK(session_status
)) {
770 return smbd_smb2_request_error(req
, session_status
);
772 status
= smbd_smb2_request_check_tcon(req
);
773 if (!NT_STATUS_IS_OK(status
)) {
774 return smbd_smb2_request_error(req
, status
);
776 return smbd_smb2_request_process_getinfo(req
);
778 case SMB2_OP_SETINFO
:
779 if (!NT_STATUS_IS_OK(session_status
)) {
780 return smbd_smb2_request_error(req
, session_status
);
782 status
= smbd_smb2_request_check_tcon(req
);
783 if (!NT_STATUS_IS_OK(status
)) {
784 return smbd_smb2_request_error(req
, status
);
786 return smbd_smb2_request_process_setinfo(req
);
789 if (!NT_STATUS_IS_OK(session_status
)) {
790 return smbd_smb2_request_error(req
, session_status
);
792 status
= smbd_smb2_request_check_tcon(req
);
793 if (!NT_STATUS_IS_OK(status
)) {
794 return smbd_smb2_request_error(req
, status
);
796 return smbd_smb2_request_process_break(req
);
799 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
802 static void smbd_smb2_request_dispatch_compound(struct tevent_req
*subreq
);
803 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
);
805 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
807 struct tevent_req
*subreq
;
811 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
813 if (req
->do_signing
) {
814 int i
= req
->current_idx
;
816 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
817 &req
->out
.vector
[i
], 3);
818 if (!NT_STATUS_IS_OK(status
)) {
823 req
->current_idx
+= 3;
825 if (req
->current_idx
< req
->out
.vector_count
) {
826 struct timeval zero
= timeval_zero();
827 subreq
= tevent_wakeup_send(req
,
828 req
->sconn
->smb2
.event_ctx
,
830 if (subreq
== NULL
) {
831 return NT_STATUS_NO_MEMORY
;
833 tevent_req_set_callback(subreq
,
834 smbd_smb2_request_dispatch_compound
,
840 subreq
= tstream_writev_queue_send(req
,
841 req
->sconn
->smb2
.event_ctx
,
842 req
->sconn
->smb2
.stream
,
843 req
->sconn
->smb2
.send_queue
,
845 req
->out
.vector_count
);
846 if (subreq
== NULL
) {
847 return NT_STATUS_NO_MEMORY
;
849 tevent_req_set_callback(subreq
, smbd_smb2_request_writev_done
, req
);
854 static void smbd_smb2_request_dispatch_compound(struct tevent_req
*subreq
)
856 struct smbd_smb2_request
*req
= tevent_req_callback_data(subreq
,
857 struct smbd_smb2_request
);
858 struct smbd_server_connection
*sconn
= req
->sconn
;
861 tevent_wakeup_recv(subreq
);
864 DEBUG(10,("smbd_smb2_request_dispatch_compound: idx[%d] of %d vectors\n",
865 req
->current_idx
, req
->in
.vector_count
));
867 status
= smbd_smb2_request_dispatch(req
);
868 if (!NT_STATUS_IS_OK(status
)) {
869 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
874 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
)
876 struct smbd_smb2_request
*req
= tevent_req_callback_data(subreq
,
877 struct smbd_smb2_request
);
878 struct smbd_server_connection
*sconn
= req
->sconn
;
882 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
886 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
887 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
892 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
895 const char *location
)
899 int i
= req
->current_idx
;
901 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
902 i
, nt_errstr(status
), info
? " +info" : "",
905 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
907 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
909 outbody
= outhdr
+ SMB2_HDR_BODY
;
911 req
->out
.vector
[i
+1].iov_base
= (void *)outbody
;
912 req
->out
.vector
[i
+1].iov_len
= 8;
915 SIVAL(outbody
, 0x04, info
->length
);
916 req
->out
.vector
[i
+2].iov_base
= (void *)info
->data
;
917 req
->out
.vector
[i
+2].iov_len
= info
->length
;
919 req
->out
.vector
[i
+2].iov_base
= NULL
;
920 req
->out
.vector
[i
+2].iov_len
= 0;
924 * if a request fails, all other remaining
925 * compounded requests should fail too
927 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
929 return smbd_smb2_request_reply(req
);
932 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
934 DATA_BLOB body
, DATA_BLOB
*dyn
,
935 const char *location
)
939 int i
= req
->current_idx
;
940 uint32_t next_command_ofs
;
942 DEBUG(10,("smbd_smb2_request_done_ex: "
943 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
944 i
, nt_errstr(status
), (unsigned int)body
.length
,
946 (unsigned int)(dyn
? dyn
->length
: 0),
949 if (body
.length
< 2) {
950 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
953 if ((body
.length
% 2) != 0) {
954 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
957 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
958 /* the fallback dynamic buffer */
959 outdyn
= outhdr
+ SMB2_HDR_BODY
+ 8;
961 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
962 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
964 req
->out
.vector
[i
+1].iov_base
= (void *)body
.data
;
965 req
->out
.vector
[i
+1].iov_len
= body
.length
;
968 req
->out
.vector
[i
+2].iov_base
= (void *)dyn
->data
;
969 req
->out
.vector
[i
+2].iov_len
= dyn
->length
;
971 req
->out
.vector
[i
+2].iov_base
= NULL
;
972 req
->out
.vector
[i
+2].iov_len
= 0;
975 /* see if we need to recalculate the offset to the next response */
976 if (next_command_ofs
> 0) {
977 next_command_ofs
= SMB2_HDR_BODY
;
978 next_command_ofs
+= req
->out
.vector
[i
+1].iov_len
;
979 next_command_ofs
+= req
->out
.vector
[i
+2].iov_len
;
982 if ((next_command_ofs
% 8) != 0) {
983 size_t pad_size
= 8 - (next_command_ofs
% 8);
984 if (req
->out
.vector
[i
+2].iov_len
== 0) {
986 * if the dyn buffer is empty
987 * we can use it to add padding
991 pad
= talloc_zero_array(req
->out
.vector
,
994 return smbd_smb2_request_error(req
,
995 NT_STATUS_NO_MEMORY
);
998 req
->out
.vector
[i
+2].iov_base
= (void *)pad
;
999 req
->out
.vector
[i
+2].iov_len
= pad_size
;
1002 * For now we copy the dynamic buffer
1003 * and add the padding to the new buffer
1010 old_size
= req
->out
.vector
[i
+2].iov_len
;
1011 old_dyn
= (uint8_t *)req
->out
.vector
[i
+2].iov_base
;
1013 new_size
= old_size
+ pad_size
;
1014 new_dyn
= talloc_array(req
->out
.vector
,
1016 if (new_dyn
== NULL
) {
1017 return smbd_smb2_request_error(req
,
1018 NT_STATUS_NO_MEMORY
);
1021 memcpy(new_dyn
, old_dyn
, old_size
);
1022 memset(new_dyn
+ old_size
, 0, pad_size
);
1024 req
->out
.vector
[i
+2].iov_base
= (void *)new_dyn
;
1025 req
->out
.vector
[i
+2].iov_len
= new_size
;
1027 TALLOC_FREE(old_dyn
);
1029 next_command_ofs
+= pad_size
;
1032 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
1034 return smbd_smb2_request_reply(req
);
1037 struct smbd_smb2_send_oplock_break_state
{
1038 struct smbd_server_connection
*sconn
;
1039 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x18];
1040 struct iovec vector
;
1043 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
);
1045 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
1046 uint64_t file_id_persistent
,
1047 uint64_t file_id_volatile
,
1048 uint8_t oplock_level
)
1050 struct smbd_smb2_send_oplock_break_state
*state
;
1051 struct tevent_req
*subreq
;
1055 state
= talloc(sconn
, struct smbd_smb2_send_oplock_break_state
);
1056 if (state
== NULL
) {
1057 return NT_STATUS_NO_MEMORY
;
1059 state
->sconn
= sconn
;
1061 state
->vector
.iov_base
= (void *)state
->buf
;
1062 state
->vector
.iov_len
= sizeof(state
->buf
);
1064 _smb2_setlen(state
->buf
, sizeof(state
->buf
) - 4);
1065 hdr
= state
->buf
+ 4;
1066 body
= hdr
+ SMB2_HDR_BODY
;
1068 SIVAL(hdr
, 0, SMB2_MAGIC
);
1069 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1070 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1071 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
1072 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
1073 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
1074 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
1075 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1076 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
1077 SIVAL(hdr
, SMB2_HDR_PID
, 0);
1078 SIVAL(hdr
, SMB2_HDR_TID
, 0);
1079 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
1080 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
1082 SSVAL(body
, 0x00, 0x18);
1084 SCVAL(body
, 0x02, oplock_level
);
1085 SCVAL(body
, 0x03, 0); /* reserved */
1086 SIVAL(body
, 0x04, 0); /* reserved */
1087 SBVAL(body
, 0x08, file_id_persistent
);
1088 SBVAL(body
, 0x10, file_id_volatile
);
1090 subreq
= tstream_writev_queue_send(state
,
1091 sconn
->smb2
.event_ctx
,
1093 sconn
->smb2
.send_queue
,
1095 if (subreq
== NULL
) {
1096 return NT_STATUS_NO_MEMORY
;
1098 tevent_req_set_callback(subreq
,
1099 smbd_smb2_oplock_break_writev_done
,
1102 return NT_STATUS_OK
;
1105 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
)
1107 struct smbd_smb2_send_oplock_break_state
*state
=
1108 tevent_req_callback_data(subreq
,
1109 struct smbd_smb2_send_oplock_break_state
);
1110 struct smbd_server_connection
*sconn
= state
->sconn
;
1114 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1115 TALLOC_FREE(subreq
);
1117 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
1118 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1125 struct smbd_smb2_request_read_state
{
1127 bool asked_for_header
;
1128 struct smbd_smb2_request
*smb2_req
;
1131 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
1133 TALLOC_CTX
*mem_ctx
,
1134 struct iovec
**_vector
,
1136 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
);
1138 static struct tevent_req
*smbd_smb2_request_read_send(TALLOC_CTX
*mem_ctx
,
1139 struct tevent_context
*ev
,
1140 struct smbd_server_connection
*sconn
)
1142 struct tevent_req
*req
;
1143 struct smbd_smb2_request_read_state
*state
;
1144 struct tevent_req
*subreq
;
1146 req
= tevent_req_create(mem_ctx
, &state
,
1147 struct smbd_smb2_request_read_state
);
1152 state
->asked_for_header
= false;
1154 state
->smb2_req
= smbd_smb2_request_allocate(state
);
1155 if (tevent_req_nomem(state
->smb2_req
, req
)) {
1156 return tevent_req_post(req
, ev
);
1158 state
->smb2_req
->sconn
= sconn
;
1160 subreq
= tstream_readv_pdu_queue_send(state
, ev
, sconn
->smb2
.stream
,
1161 sconn
->smb2
.recv_queue
,
1162 smbd_smb2_request_next_vector
,
1164 if (tevent_req_nomem(subreq
, req
)) {
1165 return tevent_req_post(req
, ev
);
1167 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
1172 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
1174 TALLOC_CTX
*mem_ctx
,
1175 struct iovec
**_vector
,
1178 struct smbd_smb2_request_read_state
*state
=
1179 talloc_get_type_abort(private_data
,
1180 struct smbd_smb2_request_read_state
);
1181 struct smbd_smb2_request
*req
= state
->smb2_req
;
1182 struct iovec
*vector
;
1183 int idx
= req
->in
.vector_count
;
1185 uint8_t *buf
= NULL
;
1187 if (req
->in
.vector_count
== 0) {
1189 * first we need to get the NBT header
1191 req
->in
.vector
= talloc_array(req
, struct iovec
,
1192 req
->in
.vector_count
+ 1);
1193 if (req
->in
.vector
== NULL
) {
1196 req
->in
.vector_count
+= 1;
1198 req
->in
.vector
[idx
].iov_base
= (void *)req
->in
.nbt_hdr
;
1199 req
->in
.vector
[idx
].iov_len
= 4;
1201 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
1202 if (vector
== NULL
) {
1206 vector
[0] = req
->in
.vector
[idx
];
1213 if (req
->in
.vector_count
== 1) {
1215 * Now we analyze the NBT header
1217 state
->missing
= smb2_len(req
->in
.vector
[0].iov_base
);
1219 if (state
->missing
== 0) {
1220 /* if there're no remaining bytes, we're done */
1226 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
1228 req
->in
.vector_count
+ 1);
1229 if (req
->in
.vector
== NULL
) {
1232 req
->in
.vector_count
+= 1;
1234 if (CVAL(req
->in
.vector
[0].iov_base
, 0) != 0) {
1236 * it's a special NBT message,
1237 * so get all remaining bytes
1239 len
= state
->missing
;
1240 } else if (state
->missing
< (SMB2_HDR_BODY
+ 2)) {
1242 * it's an invalid message, just read what we can get
1243 * and let the caller handle the error
1245 len
= state
->missing
;
1248 * We assume it's a SMB2 request,
1249 * and we first get the header and the
1250 * first 2 bytes (the struct size) of the body
1252 len
= SMB2_HDR_BODY
+ 2;
1254 state
->asked_for_header
= true;
1257 state
->missing
-= len
;
1259 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
1264 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
1265 req
->in
.vector
[idx
].iov_len
= len
;
1267 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
1268 if (vector
== NULL
) {
1272 vector
[0] = req
->in
.vector
[idx
];
1279 if (state
->missing
== 0) {
1280 /* if there're no remaining bytes, we're done */
1286 if (state
->asked_for_header
) {
1289 size_t next_command_ofs
;
1294 bool invalid
= false;
1296 state
->asked_for_header
= false;
1299 * We got the SMB2 header and the first 2 bytes
1300 * of the body. We fix the size to just the header
1301 * and manually copy the 2 first bytes to the body section
1303 req
->in
.vector
[idx
-1].iov_len
= SMB2_HDR_BODY
;
1304 hdr
= (const uint8_t *)req
->in
.vector
[idx
-1].iov_base
;
1306 /* allocate vectors for body and dynamic areas */
1307 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
1309 req
->in
.vector_count
+ 2);
1310 if (req
->in
.vector
== NULL
) {
1313 req
->in
.vector_count
+= 2;
1315 full_size
= state
->missing
+ SMB2_HDR_BODY
+ 2;
1316 next_command_ofs
= IVAL(hdr
, SMB2_HDR_NEXT_COMMAND
);
1317 body_size
= SVAL(hdr
, SMB2_HDR_BODY
);
1319 if (next_command_ofs
!= 0) {
1320 if (next_command_ofs
< (SMB2_HDR_BODY
+ 2)) {
1322 * this is invalid, just return a zero
1323 * body and let the caller deal with the error
1326 } else if (next_command_ofs
> full_size
) {
1328 * this is invalid, just return a zero
1329 * body and let the caller deal with the error
1333 full_size
= next_command_ofs
;
1338 if (body_size
< 2) {
1340 * this is invalid, just return a zero
1341 * body and let the caller deal with the error
1346 if ((body_size
% 2) != 0) {
1350 if (body_size
> (full_size
- SMB2_HDR_BODY
)) {
1352 * this is invalid, just return a zero
1353 * body and let the caller deal with the error
1360 /* the caller should check this */
1364 dyn_size
= full_size
- (SMB2_HDR_BODY
+ body_size
);
1366 state
->missing
-= (body_size
- 2) + dyn_size
;
1368 body
= talloc_array(req
->in
.vector
, uint8_t, body_size
);
1373 dyn
= talloc_array(req
->in
.vector
, uint8_t, dyn_size
);
1378 req
->in
.vector
[idx
].iov_base
= (void *)body
;
1379 req
->in
.vector
[idx
].iov_len
= body_size
;
1380 req
->in
.vector
[idx
+1].iov_base
= (void *)dyn
;
1381 req
->in
.vector
[idx
+1].iov_len
= dyn_size
;
1383 vector
= talloc_array(mem_ctx
, struct iovec
, 2);
1384 if (vector
== NULL
) {
1389 * the first 2 bytes of the body were already fetched
1390 * together with the header
1392 memcpy(body
, hdr
+ SMB2_HDR_BODY
, 2);
1393 vector
[0].iov_base
= body
+ 2;
1394 vector
[0].iov_len
= body_size
- 2;
1396 vector
[1] = req
->in
.vector
[idx
+1];
1404 * when we endup here, we're looking for a new SMB2 request
1405 * next. And we ask for its header and the first 2 bytes of
1406 * the body (like we did for the first SMB2 request).
1409 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
1411 req
->in
.vector_count
+ 1);
1412 if (req
->in
.vector
== NULL
) {
1415 req
->in
.vector_count
+= 1;
1418 * We assume it's a SMB2 request,
1419 * and we first get the header and the
1420 * first 2 bytes (the struct size) of the body
1422 len
= SMB2_HDR_BODY
+ 2;
1424 if (len
> state
->missing
) {
1425 /* let the caller handle the error */
1426 len
= state
->missing
;
1429 state
->missing
-= len
;
1430 state
->asked_for_header
= true;
1432 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
1437 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
1438 req
->in
.vector
[idx
].iov_len
= len
;
1440 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
1441 if (vector
== NULL
) {
1445 vector
[0] = req
->in
.vector
[idx
];
1452 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
)
1454 struct tevent_req
*req
=
1455 tevent_req_callback_data(subreq
,
1461 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
1463 status
= map_nt_error_from_unix(sys_errno
);
1464 tevent_req_nterror(req
, status
);
1468 tevent_req_done(req
);
1471 static NTSTATUS
smbd_smb2_request_read_recv(struct tevent_req
*req
,
1472 TALLOC_CTX
*mem_ctx
,
1473 struct smbd_smb2_request
**_smb2_req
)
1475 struct smbd_smb2_request_read_state
*state
=
1476 tevent_req_data(req
,
1477 struct smbd_smb2_request_read_state
);
1480 if (tevent_req_is_nterror(req
, &status
)) {
1481 tevent_req_received(req
);
1485 talloc_steal(mem_ctx
, state
->smb2_req
->mem_pool
);
1486 *_smb2_req
= state
->smb2_req
;
1487 tevent_req_received(req
);
1488 return NT_STATUS_OK
;
1491 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
);
1493 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
1494 const uint8_t *inbuf
, size_t size
)
1497 struct smbd_smb2_request
*req
;
1498 struct tevent_req
*subreq
;
1500 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
1501 (unsigned int)size
));
1503 status
= smbd_initialize_smb2(sconn
);
1504 if (!NT_STATUS_IS_OK(status
)) {
1505 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1509 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
1510 if (!NT_STATUS_IS_OK(status
)) {
1511 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1515 status
= smbd_smb2_request_setup_out(req
, (uint16_t)lp_maxmux());
1516 if (!NT_STATUS_IS_OK(status
)) {
1517 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1521 status
= smbd_smb2_request_dispatch(req
);
1522 if (!NT_STATUS_IS_OK(status
)) {
1523 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1527 /* ask for the next request */
1528 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->smb2
.event_ctx
, sconn
);
1529 if (subreq
== NULL
) {
1530 smbd_server_connection_terminate(sconn
, "no memory for reading");
1533 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);
1536 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
)
1538 uint16_t creds_requested
= 0;
1539 struct smbd_server_connection
*sconn
= tevent_req_callback_data(subreq
,
1540 struct smbd_server_connection
);
1542 struct smbd_smb2_request
*req
= NULL
;
1544 status
= smbd_smb2_request_read_recv(subreq
, sconn
, &req
);
1545 TALLOC_FREE(subreq
);
1546 if (!NT_STATUS_IS_OK(status
)) {
1547 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1551 if (req
->in
.nbt_hdr
[0] != 0x00) {
1552 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
1553 req
->in
.nbt_hdr
[0]));
1558 req
->current_idx
= 1;
1560 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
1561 req
->current_idx
, req
->in
.vector_count
));
1563 status
= smbd_smb2_request_validate(req
, &creds_requested
);
1564 if (!NT_STATUS_IS_OK(status
)) {
1565 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1569 status
= smbd_smb2_request_setup_out(req
, creds_requested
);
1570 if (!NT_STATUS_IS_OK(status
)) {
1571 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1575 status
= smbd_smb2_request_dispatch(req
);
1576 if (!NT_STATUS_IS_OK(status
)) {
1577 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1582 /* ask for the next request (this constructs the main loop) */
1583 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->smb2
.event_ctx
, sconn
);
1584 if (subreq
== NULL
) {
1585 smbd_server_connection_terminate(sconn
, "no memory for reading");
1588 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);