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 #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9)
28 static const char *smb2_names
[] = {
50 const char *smb2_opcode_name(uint16_t opcode
)
53 return "Bad SMB2 opcode";
55 return smb2_names
[opcode
];
58 static void print_req_vectors(struct smbd_smb2_request
*req
)
62 for (i
= 0; i
< req
->in
.vector_count
; i
++) {
63 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
65 (unsigned int)req
->in
.vector
[i
].iov_len
);
67 for (i
= 0; i
< req
->out
.vector_count
; i
++) {
68 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
70 (unsigned int)req
->out
.vector
[i
].iov_len
);
74 bool smbd_is_smb2_header(const uint8_t *inbuf
, size_t size
)
76 if (size
< (4 + SMB2_HDR_BODY
)) {
80 if (IVAL(inbuf
, 4) != SMB2_MAGIC
) {
87 static NTSTATUS
smbd_initialize_smb2(struct smbd_server_connection
*sconn
)
92 TALLOC_FREE(sconn
->smb1
.fde
);
94 sconn
->smb2
.event_ctx
= smbd_event_context();
96 sconn
->smb2
.recv_queue
= tevent_queue_create(sconn
, "smb2 recv queue");
97 if (sconn
->smb2
.recv_queue
== NULL
) {
98 return NT_STATUS_NO_MEMORY
;
101 sconn
->smb2
.send_queue
= tevent_queue_create(sconn
, "smb2 send queue");
102 if (sconn
->smb2
.send_queue
== NULL
) {
103 return NT_STATUS_NO_MEMORY
;
106 sconn
->smb2
.sessions
.idtree
= idr_init(sconn
);
107 if (sconn
->smb2
.sessions
.idtree
== NULL
) {
108 return NT_STATUS_NO_MEMORY
;
110 sconn
->smb2
.sessions
.limit
= 0x0000FFFE;
111 sconn
->smb2
.sessions
.list
= NULL
;
113 ret
= tstream_bsd_existing_socket(sconn
, smbd_server_fd(),
114 &sconn
->smb2
.stream
);
116 status
= map_nt_error_from_unix(errno
);
120 /* Ensure child is set to non-blocking mode */
121 set_blocking(smbd_server_fd(),false);
125 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
126 #define _smb2_setlen(_buf,len) do { \
127 uint8_t *buf = (uint8_t *)_buf; \
129 buf[1] = ((len)&0xFF0000)>>16; \
130 buf[2] = ((len)&0xFF00)>>8; \
131 buf[3] = (len)&0xFF; \
134 static void smb2_setup_nbt_length(struct iovec
*vector
, int count
)
139 for (i
=1; i
< count
; i
++) {
140 len
+= vector
[i
].iov_len
;
143 _smb2_setlen(vector
[0].iov_base
, len
);
146 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request
**req
)
149 (*req
)->parent
= NULL
;
150 (*req
)->mem_pool
= NULL
;
156 static int smbd_smb2_request_destructor(struct smbd_smb2_request
*req
)
158 if (req
->out
.vector
) {
159 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
164 talloc_free(req
->mem_pool
);
170 static struct smbd_smb2_request
*smbd_smb2_request_allocate(TALLOC_CTX
*mem_ctx
)
172 TALLOC_CTX
*mem_pool
;
173 struct smbd_smb2_request
**parent
;
174 struct smbd_smb2_request
*req
;
177 /* Enable this to find subtle valgrind errors. */
178 mem_pool
= talloc_init("smbd_smb2_request_allocate");
180 mem_pool
= talloc_pool(mem_ctx
, 8192);
182 if (mem_pool
== NULL
) {
186 parent
= talloc(mem_pool
, struct smbd_smb2_request
*);
187 if (parent
== NULL
) {
188 talloc_free(mem_pool
);
192 req
= talloc_zero(parent
, struct smbd_smb2_request
);
194 talloc_free(mem_pool
);
198 req
->mem_pool
= mem_pool
;
199 req
->parent
= parent
;
201 talloc_set_destructor(parent
, smbd_smb2_request_parent_destructor
);
202 talloc_set_destructor(req
, smbd_smb2_request_destructor
);
207 static NTSTATUS
smbd_smb2_request_create(struct smbd_server_connection
*sconn
,
208 const uint8_t *inbuf
, size_t size
,
209 struct smbd_smb2_request
**_req
)
211 struct smbd_smb2_request
*req
;
212 uint32_t protocol_version
;
213 const uint8_t *inhdr
= NULL
;
216 uint32_t next_command_ofs
;
218 if (size
< (4 + SMB2_HDR_BODY
+ 2)) {
219 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size
));
220 return NT_STATUS_INVALID_PARAMETER
;
225 protocol_version
= IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
);
226 if (protocol_version
!= SMB2_MAGIC
) {
227 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
229 return NT_STATUS_INVALID_PARAMETER
;
232 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
233 if (cmd
!= SMB2_OP_NEGPROT
) {
234 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
236 return NT_STATUS_INVALID_PARAMETER
;
239 next_command_ofs
= IVAL(inhdr
, SMB2_HDR_NEXT_COMMAND
);
240 if (next_command_ofs
!= 0) {
241 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
243 return NT_STATUS_INVALID_PARAMETER
;
246 req
= smbd_smb2_request_allocate(sconn
);
248 return NT_STATUS_NO_MEMORY
;
252 talloc_steal(req
, inbuf
);
254 req
->in
.vector
= talloc_array(req
, struct iovec
, 4);
255 if (req
->in
.vector
== NULL
) {
257 return NT_STATUS_NO_MEMORY
;
259 req
->in
.vector_count
= 4;
261 memcpy(req
->in
.nbt_hdr
, inbuf
, 4);
264 req
->in
.vector
[0].iov_base
= (void *)req
->in
.nbt_hdr
;
265 req
->in
.vector
[0].iov_len
= 4;
266 ofs
+= req
->in
.vector
[0].iov_len
;
268 req
->in
.vector
[1].iov_base
= (void *)(inbuf
+ ofs
);
269 req
->in
.vector
[1].iov_len
= SMB2_HDR_BODY
;
270 ofs
+= req
->in
.vector
[1].iov_len
;
272 req
->in
.vector
[2].iov_base
= (void *)(inbuf
+ ofs
);
273 req
->in
.vector
[2].iov_len
= SVAL(inbuf
, ofs
) & 0xFFFE;
274 ofs
+= req
->in
.vector
[2].iov_len
;
277 return NT_STATUS_INVALID_PARAMETER
;
280 req
->in
.vector
[3].iov_base
= (void *)(inbuf
+ ofs
);
281 req
->in
.vector
[3].iov_len
= size
- ofs
;
282 ofs
+= req
->in
.vector
[3].iov_len
;
284 req
->current_idx
= 1;
290 static NTSTATUS
smbd_smb2_request_validate(struct smbd_smb2_request
*req
,
291 uint16_t *p_creds_requested
)
295 bool compound_related
= false;
297 *p_creds_requested
= 0;
298 count
= req
->in
.vector_count
;
301 /* It's not a SMB2 request */
302 return NT_STATUS_INVALID_PARAMETER
;
305 for (idx
=1; idx
< count
; idx
+= 3) {
306 uint16_t creds_requested
= 0;
307 const uint8_t *inhdr
= NULL
;
310 if (req
->in
.vector
[idx
].iov_len
!= SMB2_HDR_BODY
) {
311 return NT_STATUS_INVALID_PARAMETER
;
314 if (req
->in
.vector
[idx
+1].iov_len
< 2) {
315 return NT_STATUS_INVALID_PARAMETER
;
318 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
320 /* setup the SMB2 header */
321 if (IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
) != SMB2_MAGIC
) {
322 return NT_STATUS_INVALID_PARAMETER
;
325 creds_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
326 if (*p_creds_requested
+ creds_requested
< creds_requested
) {
327 *p_creds_requested
= 65535;
329 *p_creds_requested
+= creds_requested
;
332 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
335 * the 1st request should never have the
336 * SMB2_HDR_FLAG_CHAINED flag set
338 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
339 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
342 } else if (idx
== 4) {
344 * the 2nd request triggers related vs. unrelated
345 * compounded requests
347 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
348 compound_related
= true;
350 } else if (idx
> 4) {
353 * It seems the this tests are wrong
354 * see the SMB2-COMPOUND test
358 * all other requests should match the 2nd one
360 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
361 if (!compound_related
) {
363 NT_STATUS_INVALID_PARAMETER
;
367 if (compound_related
) {
369 NT_STATUS_INVALID_PARAMETER
;
380 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
, uint16_t creds
)
382 struct iovec
*vector
;
386 count
= req
->in
.vector_count
;
387 vector
= talloc_zero_array(req
, struct iovec
, count
);
388 if (vector
== NULL
) {
389 return NT_STATUS_NO_MEMORY
;
392 vector
[0].iov_base
= req
->out
.nbt_hdr
;
393 vector
[0].iov_len
= 4;
394 SIVAL(req
->out
.nbt_hdr
, 0, 0);
396 for (idx
=1; idx
< count
; idx
+= 3) {
397 const uint8_t *inhdr
= NULL
;
399 uint8_t *outhdr
= NULL
;
400 uint8_t *outbody
= NULL
;
401 uint32_t next_command_ofs
= 0;
402 struct iovec
*current
= &vector
[idx
];
404 if ((idx
+ 3) < count
) {
405 /* we have a next command -
406 * setup for the error case. */
407 next_command_ofs
= SMB2_HDR_BODY
+ 9;
410 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
411 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
413 outhdr
= talloc_zero_array(vector
, uint8_t,
415 if (outhdr
== NULL
) {
416 return NT_STATUS_NO_MEMORY
;
419 outbody
= outhdr
+ SMB2_HDR_BODY
;
421 current
[0].iov_base
= (void *)outhdr
;
422 current
[0].iov_len
= SMB2_HDR_BODY
;
424 current
[1].iov_base
= (void *)outbody
;
425 current
[1].iov_len
= 8;
427 current
[2].iov_base
= NULL
;
428 current
[2].iov_len
= 0;
430 /* setup the SMB2 header */
431 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
432 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
433 SSVAL(outhdr
, SMB2_HDR_EPOCH
, 0);
434 SIVAL(outhdr
, SMB2_HDR_STATUS
,
435 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
436 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
437 SVAL(inhdr
, SMB2_HDR_OPCODE
));
438 SSVAL(outhdr
, SMB2_HDR_CREDIT
, creds
);
439 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
440 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
441 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
442 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
443 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
444 SIVAL(outhdr
, SMB2_HDR_PID
,
445 IVAL(inhdr
, SMB2_HDR_PID
));
446 SIVAL(outhdr
, SMB2_HDR_TID
,
447 IVAL(inhdr
, SMB2_HDR_TID
));
448 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
449 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
450 memset(outhdr
+ SMB2_HDR_SIGNATURE
, 0, 16);
452 /* setup error body header */
453 SSVAL(outbody
, 0x00, 0x08 + 1);
454 SSVAL(outbody
, 0x02, 0);
455 SIVAL(outbody
, 0x04, 0);
458 req
->out
.vector
= vector
;
459 req
->out
.vector_count
= count
;
461 /* setup the length of the NBT packet */
462 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
464 DLIST_ADD_END(req
->sconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
469 void smbd_server_connection_terminate_ex(struct smbd_server_connection
*sconn
,
471 const char *location
)
473 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
475 exit_server_cleanly(reason
);
478 static bool dup_smb2_vec(struct iovec
*dstvec
,
479 const struct iovec
*srcvec
,
483 if (srcvec
[offset
].iov_len
&&
484 srcvec
[offset
].iov_base
) {
485 dstvec
[offset
].iov_base
= talloc_memdup(dstvec
,
486 srcvec
[offset
].iov_base
,
487 srcvec
[offset
].iov_len
);
488 if (!dstvec
[offset
].iov_base
) {
491 dstvec
[offset
].iov_len
= srcvec
[offset
].iov_len
;
493 dstvec
[offset
].iov_base
= NULL
;
494 dstvec
[offset
].iov_len
= 0;
499 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
501 struct smbd_smb2_request
*newreq
= NULL
;
502 struct iovec
*outvec
= NULL
;
503 int count
= req
->out
.vector_count
;
506 newreq
= smbd_smb2_request_allocate(req
->sconn
);
511 newreq
->sconn
= req
->sconn
;
512 newreq
->do_signing
= req
->do_signing
;
513 newreq
->current_idx
= req
->current_idx
;
514 newreq
->async
= false;
515 newreq
->cancelled
= false;
517 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
522 newreq
->out
.vector
= outvec
;
523 newreq
->out
.vector_count
= count
;
525 /* Setup the outvec's identically to req. */
526 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
527 outvec
[0].iov_len
= 4;
528 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
530 for (i
= 1; i
< count
; i
+= 3) {
531 /* i + 0 and i + 1 are always
533 outvec
[i
].iov_base
= talloc_memdup(outvec
,
534 req
->out
.vector
[i
].iov_base
,
536 if (!outvec
[i
].iov_base
) {
539 outvec
[i
].iov_len
= SMB2_HDR_BODY
;
541 outvec
[i
+1].iov_base
= ((uint8_t *)outvec
[i
].iov_base
) +
543 outvec
[i
+1].iov_len
= 8;
545 if (req
->out
.vector
[i
+2].iov_base
==
546 ((uint8_t *)req
->out
.vector
[i
].iov_base
) +
547 (OUTVEC_ALLOC_SIZE
- 1) &&
548 req
->out
.vector
[i
+2].iov_len
== 1) {
549 /* Common SMB2 error packet case. */
550 outvec
[i
+2].iov_base
= ((uint8_t *)outvec
[i
].iov_base
) +
551 (OUTVEC_ALLOC_SIZE
- 1);
552 outvec
[i
+2].iov_len
= 1;
553 } else if (!dup_smb2_vec(outvec
,
566 smb2_setup_nbt_length(newreq
->out
.vector
,
567 newreq
->out
.vector_count
);
572 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
);
574 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
577 uint8_t *outhdr
= NULL
;
578 struct smbd_smb2_request
*nreq
= NULL
;
580 /* Create a new smb2 request we'll use
581 for the interim return. */
582 nreq
= dup_smb2_req(req
);
584 return NT_STATUS_NO_MEMORY
;
587 /* Lose the last 3 out vectors. They're the
588 ones we'll be using for the async reply. */
589 nreq
->out
.vector_count
-= 3;
591 smb2_setup_nbt_length(nreq
->out
.vector
,
592 nreq
->out
.vector_count
);
594 /* Step back to the previous reply. */
595 i
= nreq
->current_idx
- 3;
596 outhdr
= (uint8_t *)nreq
->out
.vector
[i
].iov_base
;
597 /* And end the chain. */
598 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
600 /* Re-sign if needed. */
601 if (nreq
->do_signing
) {
603 status
= smb2_signing_sign_pdu(nreq
->session
->session_key
,
604 &nreq
->out
.vector
[i
], 3);
605 if (!NT_STATUS_IS_OK(status
)) {
609 if (DEBUGLEVEL
>= 10) {
610 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
611 (unsigned int)nreq
->current_idx
);
612 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
613 (unsigned int)nreq
->out
.vector_count
);
614 print_req_vectors(nreq
);
616 nreq
->subreq
= tstream_writev_queue_send(nreq
,
617 nreq
->sconn
->smb2
.event_ctx
,
618 nreq
->sconn
->smb2
.stream
,
619 nreq
->sconn
->smb2
.send_queue
,
621 nreq
->out
.vector_count
);
623 if (nreq
->subreq
== NULL
) {
624 return NT_STATUS_NO_MEMORY
;
627 tevent_req_set_callback(nreq
->subreq
,
628 smbd_smb2_request_writev_done
,
634 struct smbd_smb2_request_pending_state
{
635 struct smbd_server_connection
*sconn
;
636 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x08 + 1];
637 struct iovec vector
[3];
640 static void smbd_smb2_request_pending_writev_done(struct tevent_req
*subreq
)
642 struct smbd_smb2_request_pending_state
*state
=
643 tevent_req_callback_data(subreq
,
644 struct smbd_smb2_request_pending_state
);
645 struct smbd_server_connection
*sconn
= state
->sconn
;
649 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
652 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
653 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
660 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
661 struct tevent_req
*subreq
)
664 struct smbd_smb2_request_pending_state
*state
= NULL
;
665 int i
= req
->current_idx
;
666 uint8_t *reqhdr
= NULL
;
668 uint8_t *body
= NULL
;
670 uint64_t message_id
= 0;
671 uint64_t async_id
= 0;
672 struct iovec
*outvec
= NULL
;
674 if (!tevent_req_is_in_progress(subreq
)) {
679 /* We're already async. */
683 if (req
->in
.vector_count
> i
+ 3) {
685 * We're trying to go async in a compound
686 * request chain. This is not allowed.
687 * Cancel the outstanding request.
689 tevent_req_cancel(subreq
);
690 return smbd_smb2_request_error(req
,
691 NT_STATUS_INSUFFICIENT_RESOURCES
);
694 req
->subreq
= subreq
;
697 if (DEBUGLEVEL
>= 10) {
698 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
699 (unsigned int)req
->current_idx
);
700 print_req_vectors(req
);
703 if (req
->out
.vector_count
> 4) {
704 /* This is a compound reply. We
705 * must do an interim response
706 * followed by the async response
709 status
= smb2_send_async_interim_response(req
);
710 if (!NT_STATUS_IS_OK(status
)) {
715 reqhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
716 flags
= (IVAL(reqhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
717 message_id
= BVAL(reqhdr
, SMB2_HDR_MESSAGE_ID
);
718 async_id
= message_id
; /* keep it simple for now... */
721 * What we send is identical to a smbd_smb2_request_error
722 * packet with an error status of STATUS_PENDING. Make use
723 * of this fact sometime when refactoring. JRA.
726 state
= talloc_zero(req
->sconn
, struct smbd_smb2_request_pending_state
);
728 return NT_STATUS_NO_MEMORY
;
730 state
->sconn
= req
->sconn
;
732 state
->vector
[0].iov_base
= (void *)state
->buf
;
733 state
->vector
[0].iov_len
= 4;
735 state
->vector
[1].iov_base
= state
->buf
+ 4;
736 state
->vector
[1].iov_len
= SMB2_HDR_BODY
;
738 state
->vector
[2].iov_base
= state
->buf
+ 4 + SMB2_HDR_BODY
;
739 state
->vector
[2].iov_len
= 9;
741 smb2_setup_nbt_length(state
->vector
, 3);
743 hdr
= (uint8_t *)state
->vector
[1].iov_base
;
744 body
= (uint8_t *)state
->vector
[2].iov_base
;
746 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
747 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
748 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
749 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
750 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(reqhdr
, SMB2_HDR_OPCODE
));
751 SSVAL(hdr
, SMB2_HDR_CREDIT
, 5);
752 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
753 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
754 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
755 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
756 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
757 BVAL(reqhdr
, SMB2_HDR_SESSION_ID
));
758 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
760 SSVAL(body
, 0x00, 0x08 + 1);
762 SCVAL(body
, 0x02, 0);
763 SCVAL(body
, 0x03, 0);
764 SIVAL(body
, 0x04, 0);
765 /* Match W2K8R2... */
766 SCVAL(body
, 0x08, 0x21);
768 if (req
->do_signing
) {
769 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
771 if (!NT_STATUS_IS_OK(status
)) {
776 subreq
= tstream_writev_queue_send(state
,
777 req
->sconn
->smb2
.event_ctx
,
778 req
->sconn
->smb2
.stream
,
779 req
->sconn
->smb2
.send_queue
,
783 if (subreq
== NULL
) {
784 return NT_STATUS_NO_MEMORY
;
787 tevent_req_set_callback(subreq
,
788 smbd_smb2_request_pending_writev_done
,
791 /* Note we're going async with this request. */
795 * Now manipulate req so that the outstanding async request
796 * is the only one left in the struct smbd_smb2_request.
799 if (req
->current_idx
== 1) {
800 /* There was only one. */
804 /* Re-arrange the in.vectors. */
805 req
->in
.vector
[1] = req
->in
.vector
[i
];
806 req
->in
.vector
[2] = req
->in
.vector
[i
+1];
807 req
->in
.vector
[3] = req
->in
.vector
[i
+2];
808 req
->in
.vector_count
= 4;
809 /* Reset the new in size. */
810 smb2_setup_nbt_length(req
->in
.vector
, 4);
812 /* Now recreate the out.vectors. */
813 outvec
= talloc_zero_array(req
, struct iovec
, 4);
815 return NT_STATUS_NO_MEMORY
;
817 outvec
[0].iov_base
= req
->out
.nbt_hdr
;
818 outvec
[0].iov_len
= 4;
819 SIVAL(req
->out
.nbt_hdr
, 0, 0);
821 outvec
[1].iov_base
= talloc_memdup(outvec
,
822 req
->out
.vector
[i
].iov_base
,
824 if (!outvec
[1].iov_base
) {
825 return NT_STATUS_NO_MEMORY
;
827 outvec
[1].iov_len
= SMB2_HDR_BODY
;
829 outvec
[2].iov_base
= ((uint8_t *)outvec
[1].iov_base
) +
831 outvec
[2].iov_len
= 8;
833 if (req
->out
.vector
[i
+2].iov_base
&&
834 req
->out
.vector
[i
+2].iov_len
) {
835 if (req
->out
.vector
[i
+2].iov_base
==
836 ((uint8_t *)req
->out
.vector
[i
].iov_base
) +
837 (OUTVEC_ALLOC_SIZE
- 1) &&
838 req
->out
.vector
[i
].iov_len
== 1) {
839 /* Common SMB2 error packet case. */
840 outvec
[3].iov_base
= ((uint8_t *)outvec
[1].iov_base
) +
841 (OUTVEC_ALLOC_SIZE
- 1);
843 outvec
[3].iov_base
= talloc_memdup(outvec
,
844 req
->out
.vector
[i
+2].iov_base
,
845 req
->out
.vector
[i
+2].iov_len
);
846 if (!outvec
[3].iov_base
) {
847 return NT_STATUS_NO_MEMORY
;
850 outvec
[3].iov_len
= req
->out
.vector
[i
+2].iov_len
;
852 outvec
[3].iov_base
= NULL
;
853 outvec
[3].iov_len
= 0;
856 TALLOC_FREE(req
->out
.vector
);
858 req
->out
.vector
= outvec
;
860 req
->current_idx
= 1;
861 req
->out
.vector_count
= 4;
865 smb2_setup_nbt_length(req
->out
.vector
,
866 req
->out
.vector_count
);
868 /* Ensure our final reply matches the interim one. */
869 reqhdr
= (uint8_t *)req
->out
.vector
[1].iov_base
;
870 SIVAL(reqhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
871 SBVAL(reqhdr
, SMB2_HDR_PID
, async_id
);
874 const uint8_t *inhdr
=
875 (const uint8_t *)req
->in
.vector
[1].iov_base
;
876 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
878 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
879 (unsigned long long)async_id
));
884 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
886 struct smbd_server_connection
*sconn
= req
->sconn
;
887 struct smbd_smb2_request
*cur
;
888 const uint8_t *inhdr
;
889 int i
= req
->current_idx
;
891 uint64_t search_message_id
;
892 uint64_t search_async_id
;
895 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
897 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
898 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
899 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
902 * we don't need the request anymore
903 * cancel requests never have a response
907 for (cur
= sconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
908 const uint8_t *outhdr
;
912 i
= cur
->current_idx
;
914 outhdr
= (const uint8_t *)cur
->out
.vector
[i
].iov_base
;
916 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
917 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
919 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
920 if (search_async_id
== async_id
) {
925 if (search_message_id
== message_id
) {
926 found_id
= message_id
;
932 if (cur
&& cur
->subreq
) {
933 inhdr
= (const uint8_t *)cur
->in
.vector
[i
].iov_base
;
934 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
935 "cancel opcode[%s] mid %llu\n",
936 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
937 (unsigned long long)found_id
));
938 tevent_req_cancel(cur
->subreq
);
944 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
946 const uint8_t *inhdr
;
947 int i
= req
->current_idx
;
952 NTSTATUS session_status
;
953 uint32_t allowed_flags
;
955 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
957 /* TODO: verify more things */
959 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
960 opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
961 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
962 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
963 smb2_opcode_name(opcode
),
964 (unsigned long long)mid
));
966 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
967 SMB2_HDR_FLAG_SIGNED
|
969 if (opcode
== SMB2_OP_CANCEL
) {
970 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
972 if ((flags
& ~allowed_flags
) != 0) {
973 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
976 session_status
= smbd_smb2_request_check_session(req
);
978 req
->do_signing
= false;
979 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
980 if (!NT_STATUS_IS_OK(session_status
)) {
981 return smbd_smb2_request_error(req
, session_status
);
984 req
->do_signing
= true;
985 status
= smb2_signing_check_pdu(req
->session
->session_key
,
986 &req
->in
.vector
[i
], 3);
987 if (!NT_STATUS_IS_OK(status
)) {
988 return smbd_smb2_request_error(req
, status
);
990 } else if (req
->session
&& req
->session
->do_signing
) {
991 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
994 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
996 * This check is mostly for giving the correct error code
997 * for compounded requests.
999 * TODO: we may need to move this after the session
1002 if (!NT_STATUS_IS_OK(req
->next_status
)) {
1003 return smbd_smb2_request_error(req
, req
->next_status
);
1006 req
->compat_chain_fsp
= NULL
;
1010 case SMB2_OP_NEGPROT
:
1011 return smbd_smb2_request_process_negprot(req
);
1013 case SMB2_OP_SESSSETUP
:
1014 return smbd_smb2_request_process_sesssetup(req
);
1016 case SMB2_OP_LOGOFF
:
1017 if (!NT_STATUS_IS_OK(session_status
)) {
1018 return smbd_smb2_request_error(req
, session_status
);
1020 return smbd_smb2_request_process_logoff(req
);
1023 if (!NT_STATUS_IS_OK(session_status
)) {
1024 return smbd_smb2_request_error(req
, session_status
);
1026 status
= smbd_smb2_request_check_session(req
);
1027 if (!NT_STATUS_IS_OK(status
)) {
1028 return smbd_smb2_request_error(req
, status
);
1030 return smbd_smb2_request_process_tcon(req
);
1033 if (!NT_STATUS_IS_OK(session_status
)) {
1034 return smbd_smb2_request_error(req
, session_status
);
1036 status
= smbd_smb2_request_check_tcon(req
);
1037 if (!NT_STATUS_IS_OK(status
)) {
1038 return smbd_smb2_request_error(req
, status
);
1040 return smbd_smb2_request_process_tdis(req
);
1042 case SMB2_OP_CREATE
:
1043 if (!NT_STATUS_IS_OK(session_status
)) {
1044 return smbd_smb2_request_error(req
, session_status
);
1046 status
= smbd_smb2_request_check_tcon(req
);
1047 if (!NT_STATUS_IS_OK(status
)) {
1048 return smbd_smb2_request_error(req
, status
);
1050 return smbd_smb2_request_process_create(req
);
1053 if (!NT_STATUS_IS_OK(session_status
)) {
1054 return smbd_smb2_request_error(req
, session_status
);
1056 status
= smbd_smb2_request_check_tcon(req
);
1057 if (!NT_STATUS_IS_OK(status
)) {
1058 return smbd_smb2_request_error(req
, status
);
1060 return smbd_smb2_request_process_close(req
);
1063 if (!NT_STATUS_IS_OK(session_status
)) {
1064 return smbd_smb2_request_error(req
, session_status
);
1066 status
= smbd_smb2_request_check_tcon(req
);
1067 if (!NT_STATUS_IS_OK(status
)) {
1068 return smbd_smb2_request_error(req
, status
);
1070 return smbd_smb2_request_process_flush(req
);
1073 if (!NT_STATUS_IS_OK(session_status
)) {
1074 return smbd_smb2_request_error(req
, session_status
);
1076 status
= smbd_smb2_request_check_tcon(req
);
1077 if (!NT_STATUS_IS_OK(status
)) {
1078 return smbd_smb2_request_error(req
, status
);
1080 return smbd_smb2_request_process_read(req
);
1083 if (!NT_STATUS_IS_OK(session_status
)) {
1084 return smbd_smb2_request_error(req
, session_status
);
1086 status
= smbd_smb2_request_check_tcon(req
);
1087 if (!NT_STATUS_IS_OK(status
)) {
1088 return smbd_smb2_request_error(req
, status
);
1090 return smbd_smb2_request_process_write(req
);
1093 if (!NT_STATUS_IS_OK(session_status
)) {
1094 return smbd_smb2_request_error(req
, session_status
);
1096 status
= smbd_smb2_request_check_tcon(req
);
1097 if (!NT_STATUS_IS_OK(status
)) {
1098 return smbd_smb2_request_error(req
, status
);
1100 return smbd_smb2_request_process_lock(req
);
1103 if (!NT_STATUS_IS_OK(session_status
)) {
1104 return smbd_smb2_request_error(req
, session_status
);
1106 status
= smbd_smb2_request_check_tcon(req
);
1107 if (!NT_STATUS_IS_OK(status
)) {
1108 return smbd_smb2_request_error(req
, status
);
1110 return smbd_smb2_request_process_ioctl(req
);
1112 case SMB2_OP_CANCEL
:
1113 return smbd_smb2_request_process_cancel(req
);
1115 case SMB2_OP_KEEPALIVE
:
1116 return smbd_smb2_request_process_keepalive(req
);
1119 if (!NT_STATUS_IS_OK(session_status
)) {
1120 return smbd_smb2_request_error(req
, session_status
);
1122 status
= smbd_smb2_request_check_tcon(req
);
1123 if (!NT_STATUS_IS_OK(status
)) {
1124 return smbd_smb2_request_error(req
, status
);
1126 return smbd_smb2_request_process_find(req
);
1128 case SMB2_OP_NOTIFY
:
1129 if (!NT_STATUS_IS_OK(session_status
)) {
1130 return smbd_smb2_request_error(req
, session_status
);
1132 status
= smbd_smb2_request_check_tcon(req
);
1133 if (!NT_STATUS_IS_OK(status
)) {
1134 return smbd_smb2_request_error(req
, status
);
1136 return smbd_smb2_request_process_notify(req
);
1138 case SMB2_OP_GETINFO
:
1139 if (!NT_STATUS_IS_OK(session_status
)) {
1140 return smbd_smb2_request_error(req
, session_status
);
1142 status
= smbd_smb2_request_check_tcon(req
);
1143 if (!NT_STATUS_IS_OK(status
)) {
1144 return smbd_smb2_request_error(req
, status
);
1146 return smbd_smb2_request_process_getinfo(req
);
1148 case SMB2_OP_SETINFO
:
1149 if (!NT_STATUS_IS_OK(session_status
)) {
1150 return smbd_smb2_request_error(req
, session_status
);
1152 status
= smbd_smb2_request_check_tcon(req
);
1153 if (!NT_STATUS_IS_OK(status
)) {
1154 return smbd_smb2_request_error(req
, status
);
1156 return smbd_smb2_request_process_setinfo(req
);
1159 if (!NT_STATUS_IS_OK(session_status
)) {
1160 return smbd_smb2_request_error(req
, session_status
);
1162 status
= smbd_smb2_request_check_tcon(req
);
1163 if (!NT_STATUS_IS_OK(status
)) {
1164 return smbd_smb2_request_error(req
, status
);
1166 return smbd_smb2_request_process_break(req
);
1169 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1172 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
1174 struct tevent_req
*subreq
;
1178 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
1180 if (req
->do_signing
) {
1181 int i
= req
->current_idx
;
1183 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
1184 &req
->out
.vector
[i
], 3);
1185 if (!NT_STATUS_IS_OK(status
)) {
1190 req
->current_idx
+= 3;
1192 if (req
->current_idx
< req
->out
.vector_count
) {
1194 * We must process the remaining compound
1195 * SMB2 requests before any new incoming SMB2
1196 * requests. This is because incoming SMB2
1197 * requests may include a cancel for a
1198 * compound request we haven't processed
1201 struct tevent_immediate
*im
= tevent_create_immediate(req
);
1203 return NT_STATUS_NO_MEMORY
;
1205 tevent_schedule_immediate(im
,
1206 req
->sconn
->smb2
.event_ctx
,
1207 smbd_smb2_request_dispatch_immediate
,
1209 return NT_STATUS_OK
;
1212 if (DEBUGLEVEL
>= 10) {
1213 dbgtext("smbd_smb2_request_reply: sending...\n");
1214 print_req_vectors(req
);
1217 subreq
= tstream_writev_queue_send(req
,
1218 req
->sconn
->smb2
.event_ctx
,
1219 req
->sconn
->smb2
.stream
,
1220 req
->sconn
->smb2
.send_queue
,
1222 req
->out
.vector_count
);
1223 if (subreq
== NULL
) {
1224 return NT_STATUS_NO_MEMORY
;
1226 tevent_req_set_callback(subreq
, smbd_smb2_request_writev_done
, req
);
1228 return NT_STATUS_OK
;
1231 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
1232 struct tevent_immediate
*im
,
1235 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
1236 struct smbd_smb2_request
);
1237 struct smbd_server_connection
*sconn
= req
->sconn
;
1242 if (DEBUGLEVEL
>= 10) {
1243 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1244 req
->current_idx
, req
->in
.vector_count
));
1245 print_req_vectors(req
);
1248 status
= smbd_smb2_request_dispatch(req
);
1249 if (!NT_STATUS_IS_OK(status
)) {
1250 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1255 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
)
1257 struct smbd_smb2_request
*req
= tevent_req_callback_data(subreq
,
1258 struct smbd_smb2_request
);
1259 struct smbd_server_connection
*sconn
= req
->sconn
;
1263 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1264 TALLOC_FREE(subreq
);
1267 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
1268 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1269 nt_errstr(status
)));
1270 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1275 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
1277 DATA_BLOB body
, DATA_BLOB
*dyn
,
1278 const char *location
)
1281 int i
= req
->current_idx
;
1282 uint32_t next_command_ofs
;
1284 DEBUG(10,("smbd_smb2_request_done_ex: "
1285 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1286 i
, nt_errstr(status
), (unsigned int)body
.length
,
1288 (unsigned int)(dyn
? dyn
->length
: 0),
1291 if (body
.length
< 2) {
1292 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
1295 if ((body
.length
% 2) != 0) {
1296 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
1299 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
1301 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
1302 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
1304 req
->out
.vector
[i
+1].iov_base
= (void *)body
.data
;
1305 req
->out
.vector
[i
+1].iov_len
= body
.length
;
1308 req
->out
.vector
[i
+2].iov_base
= (void *)dyn
->data
;
1309 req
->out
.vector
[i
+2].iov_len
= dyn
->length
;
1311 req
->out
.vector
[i
+2].iov_base
= NULL
;
1312 req
->out
.vector
[i
+2].iov_len
= 0;
1315 /* see if we need to recalculate the offset to the next response */
1316 if (next_command_ofs
> 0) {
1317 next_command_ofs
= SMB2_HDR_BODY
;
1318 next_command_ofs
+= req
->out
.vector
[i
+1].iov_len
;
1319 next_command_ofs
+= req
->out
.vector
[i
+2].iov_len
;
1322 if ((next_command_ofs
% 8) != 0) {
1323 size_t pad_size
= 8 - (next_command_ofs
% 8);
1324 if (req
->out
.vector
[i
+2].iov_len
== 0) {
1326 * if the dyn buffer is empty
1327 * we can use it to add padding
1331 pad
= talloc_zero_array(req
->out
.vector
,
1334 return smbd_smb2_request_error(req
,
1335 NT_STATUS_NO_MEMORY
);
1338 req
->out
.vector
[i
+2].iov_base
= (void *)pad
;
1339 req
->out
.vector
[i
+2].iov_len
= pad_size
;
1342 * For now we copy the dynamic buffer
1343 * and add the padding to the new buffer
1350 old_size
= req
->out
.vector
[i
+2].iov_len
;
1351 old_dyn
= (uint8_t *)req
->out
.vector
[i
+2].iov_base
;
1353 new_size
= old_size
+ pad_size
;
1354 new_dyn
= talloc_zero_array(req
->out
.vector
,
1356 if (new_dyn
== NULL
) {
1357 return smbd_smb2_request_error(req
,
1358 NT_STATUS_NO_MEMORY
);
1361 memcpy(new_dyn
, old_dyn
, old_size
);
1362 memset(new_dyn
+ old_size
, 0, pad_size
);
1364 req
->out
.vector
[i
+2].iov_base
= (void *)new_dyn
;
1365 req
->out
.vector
[i
+2].iov_len
= new_size
;
1367 next_command_ofs
+= pad_size
;
1370 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
1372 return smbd_smb2_request_reply(req
);
1375 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
1378 const char *location
)
1381 int i
= req
->current_idx
;
1382 uint8_t *outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
1384 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1385 i
, nt_errstr(status
), info
? " +info" : "",
1388 body
.data
= outhdr
+ SMB2_HDR_BODY
;
1390 SSVAL(body
.data
, 0, 9);
1393 SIVAL(body
.data
, 0x04, info
->length
);
1395 /* Allocated size of req->out.vector[i].iov_base
1396 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
1397 * 1 byte without having to do an alloc.
1399 info
= talloc_zero_array(req
->out
.vector
,
1403 return NT_STATUS_NO_MEMORY
;
1405 info
->data
= ((uint8_t *)outhdr
) +
1406 OUTVEC_ALLOC_SIZE
- 1;
1408 SCVAL(info
->data
, 0, 0);
1412 * if a request fails, all other remaining
1413 * compounded requests should fail too
1415 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
1417 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
1421 struct smbd_smb2_send_oplock_break_state
{
1422 struct smbd_server_connection
*sconn
;
1423 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x18];
1424 struct iovec vector
;
1427 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
);
1429 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
1430 uint64_t file_id_persistent
,
1431 uint64_t file_id_volatile
,
1432 uint8_t oplock_level
)
1434 struct smbd_smb2_send_oplock_break_state
*state
;
1435 struct tevent_req
*subreq
;
1439 state
= talloc(sconn
, struct smbd_smb2_send_oplock_break_state
);
1440 if (state
== NULL
) {
1441 return NT_STATUS_NO_MEMORY
;
1443 state
->sconn
= sconn
;
1445 state
->vector
.iov_base
= (void *)state
->buf
;
1446 state
->vector
.iov_len
= sizeof(state
->buf
);
1448 _smb2_setlen(state
->buf
, sizeof(state
->buf
) - 4);
1449 hdr
= state
->buf
+ 4;
1450 body
= hdr
+ SMB2_HDR_BODY
;
1452 SIVAL(hdr
, 0, SMB2_MAGIC
);
1453 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1454 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1455 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
1456 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
1457 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
1458 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
1459 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1460 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
1461 SIVAL(hdr
, SMB2_HDR_PID
, 0);
1462 SIVAL(hdr
, SMB2_HDR_TID
, 0);
1463 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
1464 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
1466 SSVAL(body
, 0x00, 0x18);
1468 SCVAL(body
, 0x02, oplock_level
);
1469 SCVAL(body
, 0x03, 0); /* reserved */
1470 SIVAL(body
, 0x04, 0); /* reserved */
1471 SBVAL(body
, 0x08, file_id_persistent
);
1472 SBVAL(body
, 0x10, file_id_volatile
);
1474 subreq
= tstream_writev_queue_send(state
,
1475 sconn
->smb2
.event_ctx
,
1477 sconn
->smb2
.send_queue
,
1479 if (subreq
== NULL
) {
1480 return NT_STATUS_NO_MEMORY
;
1482 tevent_req_set_callback(subreq
,
1483 smbd_smb2_oplock_break_writev_done
,
1486 return NT_STATUS_OK
;
1489 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
)
1491 struct smbd_smb2_send_oplock_break_state
*state
=
1492 tevent_req_callback_data(subreq
,
1493 struct smbd_smb2_send_oplock_break_state
);
1494 struct smbd_server_connection
*sconn
= state
->sconn
;
1498 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1499 TALLOC_FREE(subreq
);
1501 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
1502 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1509 struct smbd_smb2_request_read_state
{
1511 bool asked_for_header
;
1512 struct smbd_smb2_request
*smb2_req
;
1515 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
1517 TALLOC_CTX
*mem_ctx
,
1518 struct iovec
**_vector
,
1520 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
);
1522 static struct tevent_req
*smbd_smb2_request_read_send(TALLOC_CTX
*mem_ctx
,
1523 struct tevent_context
*ev
,
1524 struct smbd_server_connection
*sconn
)
1526 struct tevent_req
*req
;
1527 struct smbd_smb2_request_read_state
*state
;
1528 struct tevent_req
*subreq
;
1530 req
= tevent_req_create(mem_ctx
, &state
,
1531 struct smbd_smb2_request_read_state
);
1536 state
->asked_for_header
= false;
1538 state
->smb2_req
= smbd_smb2_request_allocate(state
);
1539 if (tevent_req_nomem(state
->smb2_req
, req
)) {
1540 return tevent_req_post(req
, ev
);
1542 state
->smb2_req
->sconn
= sconn
;
1544 subreq
= tstream_readv_pdu_queue_send(state
, ev
, sconn
->smb2
.stream
,
1545 sconn
->smb2
.recv_queue
,
1546 smbd_smb2_request_next_vector
,
1548 if (tevent_req_nomem(subreq
, req
)) {
1549 return tevent_req_post(req
, ev
);
1551 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
1556 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
1558 TALLOC_CTX
*mem_ctx
,
1559 struct iovec
**_vector
,
1562 struct smbd_smb2_request_read_state
*state
=
1563 talloc_get_type_abort(private_data
,
1564 struct smbd_smb2_request_read_state
);
1565 struct smbd_smb2_request
*req
= state
->smb2_req
;
1566 struct iovec
*vector
;
1567 int idx
= req
->in
.vector_count
;
1569 uint8_t *buf
= NULL
;
1571 if (req
->in
.vector_count
== 0) {
1573 * first we need to get the NBT header
1575 req
->in
.vector
= talloc_array(req
, struct iovec
,
1576 req
->in
.vector_count
+ 1);
1577 if (req
->in
.vector
== NULL
) {
1580 req
->in
.vector_count
+= 1;
1582 req
->in
.vector
[idx
].iov_base
= (void *)req
->in
.nbt_hdr
;
1583 req
->in
.vector
[idx
].iov_len
= 4;
1585 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
1586 if (vector
== NULL
) {
1590 vector
[0] = req
->in
.vector
[idx
];
1597 if (req
->in
.vector_count
== 1) {
1599 * Now we analyze the NBT header
1601 state
->missing
= smb2_len(req
->in
.vector
[0].iov_base
);
1603 if (state
->missing
== 0) {
1604 /* if there're no remaining bytes, we're done */
1610 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
1612 req
->in
.vector_count
+ 1);
1613 if (req
->in
.vector
== NULL
) {
1616 req
->in
.vector_count
+= 1;
1618 if (CVAL(req
->in
.vector
[0].iov_base
, 0) != 0) {
1620 * it's a special NBT message,
1621 * so get all remaining bytes
1623 len
= state
->missing
;
1624 } else if (state
->missing
< (SMB2_HDR_BODY
+ 2)) {
1626 * it's an invalid message, just read what we can get
1627 * and let the caller handle the error
1629 len
= state
->missing
;
1632 * We assume it's a SMB2 request,
1633 * and we first get the header and the
1634 * first 2 bytes (the struct size) of the body
1636 len
= SMB2_HDR_BODY
+ 2;
1638 state
->asked_for_header
= true;
1641 state
->missing
-= len
;
1643 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
1648 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
1649 req
->in
.vector
[idx
].iov_len
= len
;
1651 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
1652 if (vector
== NULL
) {
1656 vector
[0] = req
->in
.vector
[idx
];
1663 if (state
->missing
== 0) {
1664 /* if there're no remaining bytes, we're done */
1670 if (state
->asked_for_header
) {
1673 size_t next_command_ofs
;
1678 bool invalid
= false;
1680 state
->asked_for_header
= false;
1683 * We got the SMB2 header and the first 2 bytes
1684 * of the body. We fix the size to just the header
1685 * and manually copy the 2 first bytes to the body section
1687 req
->in
.vector
[idx
-1].iov_len
= SMB2_HDR_BODY
;
1688 hdr
= (const uint8_t *)req
->in
.vector
[idx
-1].iov_base
;
1690 /* allocate vectors for body and dynamic areas */
1691 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
1693 req
->in
.vector_count
+ 2);
1694 if (req
->in
.vector
== NULL
) {
1697 req
->in
.vector_count
+= 2;
1699 full_size
= state
->missing
+ SMB2_HDR_BODY
+ 2;
1700 next_command_ofs
= IVAL(hdr
, SMB2_HDR_NEXT_COMMAND
);
1701 body_size
= SVAL(hdr
, SMB2_HDR_BODY
);
1703 if (next_command_ofs
!= 0) {
1704 if (next_command_ofs
< (SMB2_HDR_BODY
+ 2)) {
1706 * this is invalid, just return a zero
1707 * body and let the caller deal with the error
1710 } else if (next_command_ofs
> full_size
) {
1712 * this is invalid, just return a zero
1713 * body and let the caller deal with the error
1717 full_size
= next_command_ofs
;
1722 if (body_size
< 2) {
1724 * this is invalid, just return a zero
1725 * body and let the caller deal with the error
1730 if ((body_size
% 2) != 0) {
1734 if (body_size
> (full_size
- SMB2_HDR_BODY
)) {
1736 * this is invalid, just return a zero
1737 * body and let the caller deal with the error
1744 /* the caller should check this */
1748 dyn_size
= full_size
- (SMB2_HDR_BODY
+ body_size
);
1750 state
->missing
-= (body_size
- 2) + dyn_size
;
1752 body
= talloc_array(req
->in
.vector
, uint8_t, body_size
);
1757 dyn
= talloc_array(req
->in
.vector
, uint8_t, dyn_size
);
1762 req
->in
.vector
[idx
].iov_base
= (void *)body
;
1763 req
->in
.vector
[idx
].iov_len
= body_size
;
1764 req
->in
.vector
[idx
+1].iov_base
= (void *)dyn
;
1765 req
->in
.vector
[idx
+1].iov_len
= dyn_size
;
1767 vector
= talloc_array(mem_ctx
, struct iovec
, 2);
1768 if (vector
== NULL
) {
1773 * the first 2 bytes of the body were already fetched
1774 * together with the header
1776 memcpy(body
, hdr
+ SMB2_HDR_BODY
, 2);
1777 vector
[0].iov_base
= body
+ 2;
1778 vector
[0].iov_len
= body_size
- 2;
1780 vector
[1] = req
->in
.vector
[idx
+1];
1788 * when we endup here, we're looking for a new SMB2 request
1789 * next. And we ask for its header and the first 2 bytes of
1790 * the body (like we did for the first SMB2 request).
1793 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
1795 req
->in
.vector_count
+ 1);
1796 if (req
->in
.vector
== NULL
) {
1799 req
->in
.vector_count
+= 1;
1802 * We assume it's a SMB2 request,
1803 * and we first get the header and the
1804 * first 2 bytes (the struct size) of the body
1806 len
= SMB2_HDR_BODY
+ 2;
1808 if (len
> state
->missing
) {
1809 /* let the caller handle the error */
1810 len
= state
->missing
;
1813 state
->missing
-= len
;
1814 state
->asked_for_header
= true;
1816 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
1821 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
1822 req
->in
.vector
[idx
].iov_len
= len
;
1824 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
1825 if (vector
== NULL
) {
1829 vector
[0] = req
->in
.vector
[idx
];
1836 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
)
1838 struct tevent_req
*req
=
1839 tevent_req_callback_data(subreq
,
1845 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
1847 status
= map_nt_error_from_unix(sys_errno
);
1848 tevent_req_nterror(req
, status
);
1852 tevent_req_done(req
);
1855 static NTSTATUS
smbd_smb2_request_read_recv(struct tevent_req
*req
,
1856 TALLOC_CTX
*mem_ctx
,
1857 struct smbd_smb2_request
**_smb2_req
)
1859 struct smbd_smb2_request_read_state
*state
=
1860 tevent_req_data(req
,
1861 struct smbd_smb2_request_read_state
);
1864 if (tevent_req_is_nterror(req
, &status
)) {
1865 tevent_req_received(req
);
1869 talloc_steal(mem_ctx
, state
->smb2_req
->mem_pool
);
1870 *_smb2_req
= state
->smb2_req
;
1871 tevent_req_received(req
);
1872 return NT_STATUS_OK
;
1875 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
);
1877 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
1878 const uint8_t *inbuf
, size_t size
)
1881 struct smbd_smb2_request
*req
;
1882 struct tevent_req
*subreq
;
1884 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
1885 (unsigned int)size
));
1887 status
= smbd_initialize_smb2(sconn
);
1888 if (!NT_STATUS_IS_OK(status
)) {
1889 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1893 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
1894 if (!NT_STATUS_IS_OK(status
)) {
1895 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1899 status
= smbd_smb2_request_setup_out(req
, (uint16_t)lp_maxmux());
1900 if (!NT_STATUS_IS_OK(status
)) {
1901 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1905 status
= smbd_smb2_request_dispatch(req
);
1906 if (!NT_STATUS_IS_OK(status
)) {
1907 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1911 /* ask for the next request */
1912 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->smb2
.event_ctx
, sconn
);
1913 if (subreq
== NULL
) {
1914 smbd_server_connection_terminate(sconn
, "no memory for reading");
1917 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);
1920 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
)
1922 uint16_t creds_requested
= 0;
1923 struct smbd_server_connection
*sconn
= tevent_req_callback_data(subreq
,
1924 struct smbd_server_connection
);
1926 struct smbd_smb2_request
*req
= NULL
;
1928 status
= smbd_smb2_request_read_recv(subreq
, sconn
, &req
);
1929 TALLOC_FREE(subreq
);
1930 if (!NT_STATUS_IS_OK(status
)) {
1931 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
1932 nt_errstr(status
)));
1933 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1937 if (req
->in
.nbt_hdr
[0] != 0x00) {
1938 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
1939 req
->in
.nbt_hdr
[0]));
1944 req
->current_idx
= 1;
1946 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
1947 req
->current_idx
, req
->in
.vector_count
));
1949 status
= smbd_smb2_request_validate(req
, &creds_requested
);
1950 if (!NT_STATUS_IS_OK(status
)) {
1951 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1955 status
= smbd_smb2_request_setup_out(req
, 5);
1956 if (!NT_STATUS_IS_OK(status
)) {
1957 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1961 status
= smbd_smb2_request_dispatch(req
);
1962 if (!NT_STATUS_IS_OK(status
)) {
1963 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1968 /* ask for the next request (this constructs the main loop) */
1969 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->smb2
.event_ctx
, sconn
);
1970 if (subreq
== NULL
) {
1971 smbd_server_connection_terminate(sconn
, "no memory for reading");
1974 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);