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/globals.h"
24 #include "../libcli/smb/smb_common.h"
25 #include "../lib/tsocket/tsocket.h"
27 #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9)
29 static const char *smb2_names
[] = {
51 const char *smb2_opcode_name(uint16_t opcode
)
54 return "Bad SMB2 opcode";
56 return smb2_names
[opcode
];
59 static void print_req_vectors(struct smbd_smb2_request
*req
)
63 for (i
= 0; i
< req
->in
.vector_count
; i
++) {
64 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
66 (unsigned int)req
->in
.vector
[i
].iov_len
);
68 for (i
= 0; i
< req
->out
.vector_count
; i
++) {
69 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
71 (unsigned int)req
->out
.vector
[i
].iov_len
);
75 bool smbd_is_smb2_header(const uint8_t *inbuf
, size_t size
)
77 if (size
< (4 + SMB2_HDR_BODY
)) {
81 if (IVAL(inbuf
, 4) != SMB2_MAGIC
) {
88 static NTSTATUS
smbd_initialize_smb2(struct smbd_server_connection
*sconn
)
93 TALLOC_FREE(sconn
->smb1
.fde
);
95 sconn
->smb2
.event_ctx
= smbd_event_context();
97 sconn
->smb2
.recv_queue
= tevent_queue_create(sconn
, "smb2 recv queue");
98 if (sconn
->smb2
.recv_queue
== NULL
) {
99 return NT_STATUS_NO_MEMORY
;
102 sconn
->smb2
.send_queue
= tevent_queue_create(sconn
, "smb2 send queue");
103 if (sconn
->smb2
.send_queue
== NULL
) {
104 return NT_STATUS_NO_MEMORY
;
107 sconn
->smb2
.sessions
.idtree
= idr_init(sconn
);
108 if (sconn
->smb2
.sessions
.idtree
== NULL
) {
109 return NT_STATUS_NO_MEMORY
;
111 sconn
->smb2
.sessions
.limit
= 0x0000FFFE;
112 sconn
->smb2
.sessions
.list
= NULL
;
114 ret
= tstream_bsd_existing_socket(sconn
, sconn
->sock
,
115 &sconn
->smb2
.stream
);
117 status
= map_nt_error_from_unix(errno
);
121 /* Ensure child is set to non-blocking mode */
122 set_blocking(sconn
->sock
, false);
126 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
127 #define _smb2_setlen(_buf,len) do { \
128 uint8_t *buf = (uint8_t *)_buf; \
130 buf[1] = ((len)&0xFF0000)>>16; \
131 buf[2] = ((len)&0xFF00)>>8; \
132 buf[3] = (len)&0xFF; \
135 static void smb2_setup_nbt_length(struct iovec
*vector
, int count
)
140 for (i
=1; i
< count
; i
++) {
141 len
+= vector
[i
].iov_len
;
144 _smb2_setlen(vector
[0].iov_base
, len
);
147 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request
**req
)
150 (*req
)->parent
= NULL
;
151 (*req
)->mem_pool
= NULL
;
157 static int smbd_smb2_request_destructor(struct smbd_smb2_request
*req
)
161 talloc_free(req
->mem_pool
);
167 static struct smbd_smb2_request
*smbd_smb2_request_allocate(TALLOC_CTX
*mem_ctx
)
169 TALLOC_CTX
*mem_pool
;
170 struct smbd_smb2_request
**parent
;
171 struct smbd_smb2_request
*req
;
174 /* Enable this to find subtle valgrind errors. */
175 mem_pool
= talloc_init("smbd_smb2_request_allocate");
177 mem_pool
= talloc_pool(mem_ctx
, 8192);
179 if (mem_pool
== NULL
) {
183 parent
= talloc(mem_pool
, struct smbd_smb2_request
*);
184 if (parent
== NULL
) {
185 talloc_free(mem_pool
);
189 req
= talloc_zero(parent
, struct smbd_smb2_request
);
191 talloc_free(mem_pool
);
195 req
->mem_pool
= mem_pool
;
196 req
->parent
= parent
;
198 talloc_set_destructor(parent
, smbd_smb2_request_parent_destructor
);
199 talloc_set_destructor(req
, smbd_smb2_request_destructor
);
204 static NTSTATUS
smbd_smb2_request_create(struct smbd_server_connection
*sconn
,
205 const uint8_t *inbuf
, size_t size
,
206 struct smbd_smb2_request
**_req
)
208 struct smbd_smb2_request
*req
;
209 uint32_t protocol_version
;
210 const uint8_t *inhdr
= NULL
;
213 uint32_t next_command_ofs
;
215 if (size
< (4 + SMB2_HDR_BODY
+ 2)) {
216 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size
));
217 return NT_STATUS_INVALID_PARAMETER
;
222 protocol_version
= IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
);
223 if (protocol_version
!= SMB2_MAGIC
) {
224 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
226 return NT_STATUS_INVALID_PARAMETER
;
229 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
230 if (cmd
!= SMB2_OP_NEGPROT
) {
231 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
233 return NT_STATUS_INVALID_PARAMETER
;
236 next_command_ofs
= IVAL(inhdr
, SMB2_HDR_NEXT_COMMAND
);
237 if (next_command_ofs
!= 0) {
238 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
240 return NT_STATUS_INVALID_PARAMETER
;
243 req
= smbd_smb2_request_allocate(sconn
);
245 return NT_STATUS_NO_MEMORY
;
249 talloc_steal(req
, inbuf
);
251 req
->in
.vector
= talloc_array(req
, struct iovec
, 4);
252 if (req
->in
.vector
== NULL
) {
254 return NT_STATUS_NO_MEMORY
;
256 req
->in
.vector_count
= 4;
258 memcpy(req
->in
.nbt_hdr
, inbuf
, 4);
261 req
->in
.vector
[0].iov_base
= (void *)req
->in
.nbt_hdr
;
262 req
->in
.vector
[0].iov_len
= 4;
263 ofs
+= req
->in
.vector
[0].iov_len
;
265 req
->in
.vector
[1].iov_base
= (void *)(inbuf
+ ofs
);
266 req
->in
.vector
[1].iov_len
= SMB2_HDR_BODY
;
267 ofs
+= req
->in
.vector
[1].iov_len
;
269 req
->in
.vector
[2].iov_base
= (void *)(inbuf
+ ofs
);
270 req
->in
.vector
[2].iov_len
= SVAL(inbuf
, ofs
) & 0xFFFE;
271 ofs
+= req
->in
.vector
[2].iov_len
;
274 return NT_STATUS_INVALID_PARAMETER
;
277 req
->in
.vector
[3].iov_base
= (void *)(inbuf
+ ofs
);
278 req
->in
.vector
[3].iov_len
= size
- ofs
;
279 ofs
+= req
->in
.vector
[3].iov_len
;
281 req
->current_idx
= 1;
287 static NTSTATUS
smbd_smb2_request_validate(struct smbd_smb2_request
*req
,
288 uint16_t *p_creds_requested
)
292 bool compound_related
= false;
294 *p_creds_requested
= 0;
295 count
= req
->in
.vector_count
;
298 /* It's not a SMB2 request */
299 return NT_STATUS_INVALID_PARAMETER
;
302 for (idx
=1; idx
< count
; idx
+= 3) {
303 uint16_t creds_requested
= 0;
304 const uint8_t *inhdr
= NULL
;
307 if (req
->in
.vector
[idx
].iov_len
!= SMB2_HDR_BODY
) {
308 return NT_STATUS_INVALID_PARAMETER
;
311 if (req
->in
.vector
[idx
+1].iov_len
< 2) {
312 return NT_STATUS_INVALID_PARAMETER
;
315 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
317 /* setup the SMB2 header */
318 if (IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
) != SMB2_MAGIC
) {
319 return NT_STATUS_INVALID_PARAMETER
;
322 creds_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
323 if (*p_creds_requested
+ creds_requested
< creds_requested
) {
324 *p_creds_requested
= 65535;
326 *p_creds_requested
+= creds_requested
;
329 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
332 * the 1st request should never have the
333 * SMB2_HDR_FLAG_CHAINED flag set
335 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
336 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
339 } else if (idx
== 4) {
341 * the 2nd request triggers related vs. unrelated
342 * compounded requests
344 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
345 compound_related
= true;
347 } else if (idx
> 4) {
350 * It seems the this tests are wrong
351 * see the SMB2-COMPOUND test
355 * all other requests should match the 2nd one
357 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
358 if (!compound_related
) {
360 NT_STATUS_INVALID_PARAMETER
;
364 if (compound_related
) {
366 NT_STATUS_INVALID_PARAMETER
;
377 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
, uint16_t creds
)
379 struct iovec
*vector
;
383 count
= req
->in
.vector_count
;
384 vector
= talloc_zero_array(req
, struct iovec
, count
);
385 if (vector
== NULL
) {
386 return NT_STATUS_NO_MEMORY
;
389 vector
[0].iov_base
= req
->out
.nbt_hdr
;
390 vector
[0].iov_len
= 4;
391 SIVAL(req
->out
.nbt_hdr
, 0, 0);
393 for (idx
=1; idx
< count
; idx
+= 3) {
394 const uint8_t *inhdr
= NULL
;
396 uint8_t *outhdr
= NULL
;
397 uint8_t *outbody
= NULL
;
398 uint32_t next_command_ofs
= 0;
399 struct iovec
*current
= &vector
[idx
];
401 if ((idx
+ 3) < count
) {
402 /* we have a next command -
403 * setup for the error case. */
404 next_command_ofs
= SMB2_HDR_BODY
+ 9;
407 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
408 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
410 outhdr
= talloc_zero_array(vector
, uint8_t,
412 if (outhdr
== NULL
) {
413 return NT_STATUS_NO_MEMORY
;
416 outbody
= outhdr
+ SMB2_HDR_BODY
;
418 current
[0].iov_base
= (void *)outhdr
;
419 current
[0].iov_len
= SMB2_HDR_BODY
;
421 current
[1].iov_base
= (void *)outbody
;
422 current
[1].iov_len
= 8;
424 current
[2].iov_base
= NULL
;
425 current
[2].iov_len
= 0;
427 /* setup the SMB2 header */
428 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
429 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
430 SSVAL(outhdr
, SMB2_HDR_EPOCH
, 0);
431 SIVAL(outhdr
, SMB2_HDR_STATUS
,
432 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
433 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
434 SVAL(inhdr
, SMB2_HDR_OPCODE
));
435 SSVAL(outhdr
, SMB2_HDR_CREDIT
, creds
);
437 /* Remember what we gave out. */
438 req
->sconn
->smb2
.credits_granted
+= creds
;
440 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
441 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
442 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
443 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
444 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
445 SIVAL(outhdr
, SMB2_HDR_PID
,
446 IVAL(inhdr
, SMB2_HDR_PID
));
447 SIVAL(outhdr
, SMB2_HDR_TID
,
448 IVAL(inhdr
, SMB2_HDR_TID
));
449 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
450 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
451 memset(outhdr
+ SMB2_HDR_SIGNATURE
, 0, 16);
453 /* setup error body header */
454 SSVAL(outbody
, 0x00, 0x08 + 1);
455 SSVAL(outbody
, 0x02, 0);
456 SIVAL(outbody
, 0x04, 0);
459 req
->out
.vector
= vector
;
460 req
->out
.vector_count
= count
;
462 /* setup the length of the NBT packet */
463 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
465 DLIST_ADD_END(req
->sconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
470 void smbd_server_connection_terminate_ex(struct smbd_server_connection
*sconn
,
472 const char *location
)
474 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
476 exit_server_cleanly(reason
);
479 static bool dup_smb2_vec3(TALLOC_CTX
*ctx
,
480 struct iovec
*outvec
,
481 const struct iovec
*srcvec
)
483 /* vec[0] is always boilerplate and must
484 * be allocated with size OUTVEC_ALLOC_SIZE. */
486 outvec
[0].iov_base
= talloc_memdup(ctx
,
489 if (!outvec
[0].iov_base
) {
492 outvec
[0].iov_len
= SMB2_HDR_BODY
;
495 * If this is a "standard" vec[1] of length 8,
496 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
497 * then duplicate this. Else use talloc_memdup().
500 if (srcvec
[1].iov_len
== 8 &&
501 srcvec
[1].iov_base
==
502 ((uint8_t *)srcvec
[0].iov_base
) +
504 outvec
[1].iov_base
= ((uint8_t *)outvec
[1].iov_base
) +
506 outvec
[1].iov_len
= 8;
508 outvec
[1].iov_base
= talloc_memdup(ctx
,
511 if (!outvec
[1].iov_base
) {
514 outvec
[1].iov_len
= srcvec
[1].iov_len
;
518 * If this is a "standard" vec[2] of length 1,
519 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
520 * then duplicate this. Else use talloc_memdup().
523 if (srcvec
[2].iov_base
&&
525 if (srcvec
[2].iov_base
==
526 ((uint8_t *)srcvec
[0].iov_base
) +
527 (OUTVEC_ALLOC_SIZE
- 1) &&
528 srcvec
[2].iov_len
== 1) {
529 /* Common SMB2 error packet case. */
530 outvec
[2].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
531 (OUTVEC_ALLOC_SIZE
- 1);
533 outvec
[2].iov_base
= talloc_memdup(ctx
,
536 if (!outvec
[2].iov_base
) {
540 outvec
[2].iov_len
= srcvec
[2].iov_len
;
542 outvec
[2].iov_base
= NULL
;
543 outvec
[2].iov_len
= 0;
548 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
550 struct smbd_smb2_request
*newreq
= NULL
;
551 struct iovec
*outvec
= NULL
;
552 int count
= req
->out
.vector_count
;
555 newreq
= smbd_smb2_request_allocate(req
->sconn
);
560 newreq
->sconn
= req
->sconn
;
561 newreq
->do_signing
= req
->do_signing
;
562 newreq
->current_idx
= req
->current_idx
;
563 newreq
->async
= false;
564 newreq
->cancelled
= false;
566 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
571 newreq
->out
.vector
= outvec
;
572 newreq
->out
.vector_count
= count
;
574 /* Setup the outvec's identically to req. */
575 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
576 outvec
[0].iov_len
= 4;
577 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
579 /* Setup the vectors identically to the ones in req. */
580 for (i
= 1; i
< count
; i
+= 3) {
581 if (!dup_smb2_vec3(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
592 smb2_setup_nbt_length(newreq
->out
.vector
,
593 newreq
->out
.vector_count
);
598 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
);
600 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
603 uint8_t *outhdr
= NULL
;
604 struct smbd_smb2_request
*nreq
= NULL
;
606 /* Create a new smb2 request we'll use
607 for the interim return. */
608 nreq
= dup_smb2_req(req
);
610 return NT_STATUS_NO_MEMORY
;
613 /* Lose the last 3 out vectors. They're the
614 ones we'll be using for the async reply. */
615 nreq
->out
.vector_count
-= 3;
617 smb2_setup_nbt_length(nreq
->out
.vector
,
618 nreq
->out
.vector_count
);
620 /* Step back to the previous reply. */
621 i
= nreq
->current_idx
- 3;
622 outhdr
= (uint8_t *)nreq
->out
.vector
[i
].iov_base
;
623 /* And end the chain. */
624 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
626 /* Re-sign if needed. */
627 if (nreq
->do_signing
) {
629 status
= smb2_signing_sign_pdu(nreq
->session
->session_key
,
630 &nreq
->out
.vector
[i
], 3);
631 if (!NT_STATUS_IS_OK(status
)) {
635 if (DEBUGLEVEL
>= 10) {
636 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
637 (unsigned int)nreq
->current_idx
);
638 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
639 (unsigned int)nreq
->out
.vector_count
);
640 print_req_vectors(nreq
);
642 nreq
->subreq
= tstream_writev_queue_send(nreq
,
643 nreq
->sconn
->smb2
.event_ctx
,
644 nreq
->sconn
->smb2
.stream
,
645 nreq
->sconn
->smb2
.send_queue
,
647 nreq
->out
.vector_count
);
649 if (nreq
->subreq
== NULL
) {
650 return NT_STATUS_NO_MEMORY
;
653 tevent_req_set_callback(nreq
->subreq
,
654 smbd_smb2_request_writev_done
,
660 struct smbd_smb2_request_pending_state
{
661 struct smbd_server_connection
*sconn
;
662 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x08 + 1];
663 struct iovec vector
[3];
666 static void smbd_smb2_request_pending_writev_done(struct tevent_req
*subreq
)
668 struct smbd_smb2_request_pending_state
*state
=
669 tevent_req_callback_data(subreq
,
670 struct smbd_smb2_request_pending_state
);
671 struct smbd_server_connection
*sconn
= state
->sconn
;
675 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
678 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
679 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
686 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
687 struct tevent_req
*subreq
)
690 struct smbd_smb2_request_pending_state
*state
= NULL
;
691 int i
= req
->current_idx
;
692 uint8_t *reqhdr
= NULL
;
694 uint8_t *body
= NULL
;
696 uint64_t message_id
= 0;
697 uint64_t async_id
= 0;
698 struct iovec
*outvec
= NULL
;
700 if (!tevent_req_is_in_progress(subreq
)) {
704 req
->subreq
= subreq
;
708 /* We're already async. */
712 if (req
->in
.vector_count
> i
+ 3) {
714 * We're trying to go async in a compound
715 * request chain. This is not allowed.
716 * Cancel the outstanding request.
718 tevent_req_cancel(req
->subreq
);
719 return smbd_smb2_request_error(req
,
720 NT_STATUS_INSUFFICIENT_RESOURCES
);
723 if (DEBUGLEVEL
>= 10) {
724 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
725 (unsigned int)req
->current_idx
);
726 print_req_vectors(req
);
729 if (req
->out
.vector_count
> 4) {
730 /* This is a compound reply. We
731 * must do an interim response
732 * followed by the async response
735 status
= smb2_send_async_interim_response(req
);
736 if (!NT_STATUS_IS_OK(status
)) {
741 /* Don't return an intermediate packet on a pipe read/write. */
742 if (req
->tcon
&& req
->tcon
->compat_conn
&& IS_IPC(req
->tcon
->compat_conn
)) {
746 reqhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
747 flags
= (IVAL(reqhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
748 message_id
= BVAL(reqhdr
, SMB2_HDR_MESSAGE_ID
);
749 async_id
= message_id
; /* keep it simple for now... */
752 * What we send is identical to a smbd_smb2_request_error
753 * packet with an error status of STATUS_PENDING. Make use
754 * of this fact sometime when refactoring. JRA.
757 state
= talloc_zero(req
->sconn
, struct smbd_smb2_request_pending_state
);
759 return NT_STATUS_NO_MEMORY
;
761 state
->sconn
= req
->sconn
;
763 state
->vector
[0].iov_base
= (void *)state
->buf
;
764 state
->vector
[0].iov_len
= 4;
766 state
->vector
[1].iov_base
= state
->buf
+ 4;
767 state
->vector
[1].iov_len
= SMB2_HDR_BODY
;
769 state
->vector
[2].iov_base
= state
->buf
+ 4 + SMB2_HDR_BODY
;
770 state
->vector
[2].iov_len
= 9;
772 smb2_setup_nbt_length(state
->vector
, 3);
774 hdr
= (uint8_t *)state
->vector
[1].iov_base
;
775 body
= (uint8_t *)state
->vector
[2].iov_base
;
777 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
778 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
779 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
780 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
781 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(reqhdr
, SMB2_HDR_OPCODE
));
782 SSVAL(hdr
, SMB2_HDR_CREDIT
, 5);
784 req
->sconn
->smb2
.credits_granted
+= 5;
786 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
787 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
788 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
789 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
790 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
791 BVAL(reqhdr
, SMB2_HDR_SESSION_ID
));
792 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
794 SSVAL(body
, 0x00, 0x08 + 1);
796 SCVAL(body
, 0x02, 0);
797 SCVAL(body
, 0x03, 0);
798 SIVAL(body
, 0x04, 0);
799 /* Match W2K8R2... */
800 SCVAL(body
, 0x08, 0x21);
802 if (req
->do_signing
) {
803 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
805 if (!NT_STATUS_IS_OK(status
)) {
810 subreq
= tstream_writev_queue_send(state
,
811 req
->sconn
->smb2
.event_ctx
,
812 req
->sconn
->smb2
.stream
,
813 req
->sconn
->smb2
.send_queue
,
817 if (subreq
== NULL
) {
818 return NT_STATUS_NO_MEMORY
;
821 tevent_req_set_callback(subreq
,
822 smbd_smb2_request_pending_writev_done
,
825 /* Note we're going async with this request. */
829 * Now manipulate req so that the outstanding async request
830 * is the only one left in the struct smbd_smb2_request.
833 if (req
->current_idx
== 1) {
834 /* There was only one. */
838 /* Re-arrange the in.vectors. */
839 req
->in
.vector
[1] = req
->in
.vector
[i
];
840 req
->in
.vector
[2] = req
->in
.vector
[i
+1];
841 req
->in
.vector
[3] = req
->in
.vector
[i
+2];
842 req
->in
.vector_count
= 4;
843 /* Reset the new in size. */
844 smb2_setup_nbt_length(req
->in
.vector
, 4);
846 /* Now recreate the out.vectors. */
847 outvec
= talloc_zero_array(req
, struct iovec
, 4);
849 return NT_STATUS_NO_MEMORY
;
852 /* 0 is always boilerplate and must
853 * be of size 4 for the length field. */
855 outvec
[0].iov_base
= req
->out
.nbt_hdr
;
856 outvec
[0].iov_len
= 4;
857 SIVAL(req
->out
.nbt_hdr
, 0, 0);
859 if (!dup_smb2_vec3(outvec
, &outvec
[1], &req
->out
.vector
[i
])) {
860 return NT_STATUS_NO_MEMORY
;
863 TALLOC_FREE(req
->out
.vector
);
865 req
->out
.vector
= outvec
;
867 req
->current_idx
= 1;
868 req
->out
.vector_count
= 4;
872 smb2_setup_nbt_length(req
->out
.vector
,
873 req
->out
.vector_count
);
875 /* Ensure our final reply matches the interim one. */
876 reqhdr
= (uint8_t *)req
->out
.vector
[1].iov_base
;
877 SIVAL(reqhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
878 SBVAL(reqhdr
, SMB2_HDR_PID
, async_id
);
879 /* Only return credits on the interim response. */
880 SSVAL(reqhdr
, SMB2_HDR_CREDIT
, 0);
883 const uint8_t *inhdr
=
884 (const uint8_t *)req
->in
.vector
[1].iov_base
;
885 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
887 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
888 (unsigned long long)async_id
));
893 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
895 struct smbd_server_connection
*sconn
= req
->sconn
;
896 struct smbd_smb2_request
*cur
;
897 const uint8_t *inhdr
;
898 int i
= req
->current_idx
;
900 uint64_t search_message_id
;
901 uint64_t search_async_id
;
904 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
906 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
907 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
908 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
911 * we don't need the request anymore
912 * cancel requests never have a response
914 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
917 for (cur
= sconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
918 const uint8_t *outhdr
;
922 i
= cur
->current_idx
;
924 outhdr
= (const uint8_t *)cur
->out
.vector
[i
].iov_base
;
926 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
927 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
929 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
930 if (search_async_id
== async_id
) {
935 if (search_message_id
== message_id
) {
936 found_id
= message_id
;
942 if (cur
&& cur
->subreq
) {
943 inhdr
= (const uint8_t *)cur
->in
.vector
[i
].iov_base
;
944 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
945 "cancel opcode[%s] mid %llu\n",
946 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
947 (unsigned long long)found_id
));
948 tevent_req_cancel(cur
->subreq
);
954 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
956 const uint8_t *inhdr
;
957 int i
= req
->current_idx
;
962 NTSTATUS session_status
;
963 uint32_t allowed_flags
;
964 NTSTATUS return_value
;
966 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
968 /* TODO: verify more things */
970 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
971 opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
972 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
973 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
974 smb2_opcode_name(opcode
),
975 (unsigned long long)mid
));
977 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
978 SMB2_HDR_FLAG_SIGNED
|
980 if (opcode
== SMB2_OP_CANCEL
) {
981 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
983 if ((flags
& ~allowed_flags
) != 0) {
984 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
987 session_status
= smbd_smb2_request_check_session(req
);
989 req
->do_signing
= false;
990 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
991 if (!NT_STATUS_IS_OK(session_status
)) {
992 return smbd_smb2_request_error(req
, session_status
);
995 req
->do_signing
= true;
996 status
= smb2_signing_check_pdu(req
->session
->session_key
,
997 &req
->in
.vector
[i
], 3);
998 if (!NT_STATUS_IS_OK(status
)) {
999 return smbd_smb2_request_error(req
, status
);
1001 } else if (req
->session
&& req
->session
->do_signing
) {
1002 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
1005 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
1007 * This check is mostly for giving the correct error code
1008 * for compounded requests.
1010 * TODO: we may need to move this after the session
1013 if (!NT_STATUS_IS_OK(req
->next_status
)) {
1014 return smbd_smb2_request_error(req
, req
->next_status
);
1017 req
->compat_chain_fsp
= NULL
;
1021 case SMB2_OP_NEGPROT
:
1023 START_PROFILE(smb2_negprot
);
1024 return_value
= smbd_smb2_request_process_negprot(req
);
1025 END_PROFILE(smb2_negprot
);
1029 case SMB2_OP_SESSSETUP
:
1031 START_PROFILE(smb2_sesssetup
);
1032 return_value
= smbd_smb2_request_process_sesssetup(req
);
1033 END_PROFILE(smb2_sesssetup
);
1037 case SMB2_OP_LOGOFF
:
1038 if (!NT_STATUS_IS_OK(session_status
)) {
1039 return_value
= smbd_smb2_request_error(req
, session_status
);
1044 START_PROFILE(smb2_logoff
);
1045 return_value
= smbd_smb2_request_process_logoff(req
);
1046 END_PROFILE(smb2_logoff
);
1051 if (!NT_STATUS_IS_OK(session_status
)) {
1052 return_value
= smbd_smb2_request_error(req
, session_status
);
1055 status
= smbd_smb2_request_check_session(req
);
1056 if (!NT_STATUS_IS_OK(status
)) {
1057 return_value
= smbd_smb2_request_error(req
, status
);
1062 START_PROFILE(smb2_tcon
);
1063 return_value
= smbd_smb2_request_process_tcon(req
);
1064 END_PROFILE(smb2_tcon
);
1069 if (!NT_STATUS_IS_OK(session_status
)) {
1070 return_value
= smbd_smb2_request_error(req
, session_status
);
1073 status
= smbd_smb2_request_check_tcon(req
);
1074 if (!NT_STATUS_IS_OK(status
)) {
1075 return_value
= smbd_smb2_request_error(req
, status
);
1080 START_PROFILE(smb2_tdis
);
1081 return_value
= smbd_smb2_request_process_tdis(req
);
1082 END_PROFILE(smb2_tdis
);
1086 case SMB2_OP_CREATE
:
1087 if (!NT_STATUS_IS_OK(session_status
)) {
1088 return_value
= smbd_smb2_request_error(req
, session_status
);
1091 status
= smbd_smb2_request_check_tcon(req
);
1092 if (!NT_STATUS_IS_OK(status
)) {
1093 return_value
= smbd_smb2_request_error(req
, status
);
1098 START_PROFILE(smb2_create
);
1099 return_value
= smbd_smb2_request_process_create(req
);
1100 END_PROFILE(smb2_create
);
1105 if (!NT_STATUS_IS_OK(session_status
)) {
1106 return_value
= smbd_smb2_request_error(req
, session_status
);
1109 status
= smbd_smb2_request_check_tcon(req
);
1110 if (!NT_STATUS_IS_OK(status
)) {
1111 return_value
= smbd_smb2_request_error(req
, status
);
1116 START_PROFILE(smb2_close
);
1117 return_value
= smbd_smb2_request_process_close(req
);
1118 END_PROFILE(smb2_close
);
1123 if (!NT_STATUS_IS_OK(session_status
)) {
1124 return_value
= smbd_smb2_request_error(req
, session_status
);
1127 status
= smbd_smb2_request_check_tcon(req
);
1128 if (!NT_STATUS_IS_OK(status
)) {
1129 return_value
= smbd_smb2_request_error(req
, status
);
1134 START_PROFILE(smb2_flush
);
1135 return_value
= smbd_smb2_request_process_flush(req
);
1136 END_PROFILE(smb2_flush
);
1141 if (!NT_STATUS_IS_OK(session_status
)) {
1142 return_value
= smbd_smb2_request_error(req
, session_status
);
1145 status
= smbd_smb2_request_check_tcon(req
);
1146 if (!NT_STATUS_IS_OK(status
)) {
1147 return_value
= smbd_smb2_request_error(req
, status
);
1152 START_PROFILE(smb2_read
);
1153 return_value
= smbd_smb2_request_process_read(req
);
1154 END_PROFILE(smb2_read
);
1159 if (!NT_STATUS_IS_OK(session_status
)) {
1160 return_value
= smbd_smb2_request_error(req
, session_status
);
1163 status
= smbd_smb2_request_check_tcon(req
);
1164 if (!NT_STATUS_IS_OK(status
)) {
1165 return_value
= smbd_smb2_request_error(req
, status
);
1170 START_PROFILE(smb2_write
);
1171 return_value
= smbd_smb2_request_process_write(req
);
1172 END_PROFILE(smb2_write
);
1177 if (!NT_STATUS_IS_OK(session_status
)) {
1178 /* Too ugly to live ? JRA. */
1179 if (NT_STATUS_EQUAL(session_status
,NT_STATUS_USER_SESSION_DELETED
)) {
1180 session_status
= NT_STATUS_FILE_CLOSED
;
1182 return_value
= smbd_smb2_request_error(req
, session_status
);
1185 status
= smbd_smb2_request_check_tcon(req
);
1186 if (!NT_STATUS_IS_OK(status
)) {
1187 /* Too ugly to live ? JRA. */
1188 if (NT_STATUS_EQUAL(status
,NT_STATUS_NETWORK_NAME_DELETED
)) {
1189 status
= NT_STATUS_FILE_CLOSED
;
1191 return_value
= smbd_smb2_request_error(req
, status
);
1196 START_PROFILE(smb2_lock
);
1197 return_value
= smbd_smb2_request_process_lock(req
);
1198 END_PROFILE(smb2_lock
);
1203 if (!NT_STATUS_IS_OK(session_status
)) {
1204 return_value
= smbd_smb2_request_error(req
, session_status
);
1207 status
= smbd_smb2_request_check_tcon(req
);
1208 if (!NT_STATUS_IS_OK(status
)) {
1209 return_value
= smbd_smb2_request_error(req
, status
);
1214 START_PROFILE(smb2_ioctl
);
1215 return_value
= smbd_smb2_request_process_ioctl(req
);
1216 END_PROFILE(smb2_ioctl
);
1220 case SMB2_OP_CANCEL
:
1222 START_PROFILE(smb2_cancel
);
1223 return_value
= smbd_smb2_request_process_cancel(req
);
1224 END_PROFILE(smb2_cancel
);
1228 case SMB2_OP_KEEPALIVE
:
1229 {START_PROFILE(smb2_keepalive
);
1230 return_value
= smbd_smb2_request_process_keepalive(req
);
1231 END_PROFILE(smb2_keepalive
);}
1235 if (!NT_STATUS_IS_OK(session_status
)) {
1236 return_value
= smbd_smb2_request_error(req
, session_status
);
1239 status
= smbd_smb2_request_check_tcon(req
);
1240 if (!NT_STATUS_IS_OK(status
)) {
1241 return_value
= smbd_smb2_request_error(req
, status
);
1246 START_PROFILE(smb2_find
);
1247 return_value
= smbd_smb2_request_process_find(req
);
1248 END_PROFILE(smb2_find
);
1252 case SMB2_OP_NOTIFY
:
1253 if (!NT_STATUS_IS_OK(session_status
)) {
1254 return_value
= smbd_smb2_request_error(req
, session_status
);
1257 status
= smbd_smb2_request_check_tcon(req
);
1258 if (!NT_STATUS_IS_OK(status
)) {
1259 return_value
= smbd_smb2_request_error(req
, status
);
1264 START_PROFILE(smb2_notify
);
1265 return_value
= smbd_smb2_request_process_notify(req
);
1266 END_PROFILE(smb2_notify
);
1270 case SMB2_OP_GETINFO
:
1271 if (!NT_STATUS_IS_OK(session_status
)) {
1272 return_value
= smbd_smb2_request_error(req
, session_status
);
1275 status
= smbd_smb2_request_check_tcon(req
);
1276 if (!NT_STATUS_IS_OK(status
)) {
1277 return_value
= smbd_smb2_request_error(req
, status
);
1282 START_PROFILE(smb2_getinfo
);
1283 return_value
= smbd_smb2_request_process_getinfo(req
);
1284 END_PROFILE(smb2_getinfo
);
1288 case SMB2_OP_SETINFO
:
1289 if (!NT_STATUS_IS_OK(session_status
)) {
1290 return_value
= smbd_smb2_request_error(req
, session_status
);
1293 status
= smbd_smb2_request_check_tcon(req
);
1294 if (!NT_STATUS_IS_OK(status
)) {
1295 return_value
= smbd_smb2_request_error(req
, status
);
1300 START_PROFILE(smb2_setinfo
);
1301 return_value
= smbd_smb2_request_process_setinfo(req
);
1302 END_PROFILE(smb2_setinfo
);
1307 if (!NT_STATUS_IS_OK(session_status
)) {
1308 return_value
= smbd_smb2_request_error(req
, session_status
);
1311 status
= smbd_smb2_request_check_tcon(req
);
1312 if (!NT_STATUS_IS_OK(status
)) {
1313 return_value
= smbd_smb2_request_error(req
, status
);
1318 START_PROFILE(smb2_break
);
1319 return_value
= smbd_smb2_request_process_break(req
);
1320 END_PROFILE(smb2_break
);
1325 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1328 return return_value
;
1331 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
1333 struct tevent_req
*subreq
;
1337 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
1339 if (req
->do_signing
) {
1340 int i
= req
->current_idx
;
1342 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
1343 &req
->out
.vector
[i
], 3);
1344 if (!NT_STATUS_IS_OK(status
)) {
1349 req
->current_idx
+= 3;
1351 if (req
->current_idx
< req
->out
.vector_count
) {
1353 * We must process the remaining compound
1354 * SMB2 requests before any new incoming SMB2
1355 * requests. This is because incoming SMB2
1356 * requests may include a cancel for a
1357 * compound request we haven't processed
1360 struct tevent_immediate
*im
= tevent_create_immediate(req
);
1362 return NT_STATUS_NO_MEMORY
;
1364 tevent_schedule_immediate(im
,
1365 req
->sconn
->smb2
.event_ctx
,
1366 smbd_smb2_request_dispatch_immediate
,
1368 return NT_STATUS_OK
;
1371 if (DEBUGLEVEL
>= 10) {
1372 dbgtext("smbd_smb2_request_reply: sending...\n");
1373 print_req_vectors(req
);
1376 subreq
= tstream_writev_queue_send(req
,
1377 req
->sconn
->smb2
.event_ctx
,
1378 req
->sconn
->smb2
.stream
,
1379 req
->sconn
->smb2
.send_queue
,
1381 req
->out
.vector_count
);
1382 if (subreq
== NULL
) {
1383 return NT_STATUS_NO_MEMORY
;
1385 tevent_req_set_callback(subreq
, smbd_smb2_request_writev_done
, req
);
1387 * We're done with this request -
1388 * move it off the "being processed" queue.
1390 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1392 return NT_STATUS_OK
;
1395 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
1396 struct tevent_immediate
*im
,
1399 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
1400 struct smbd_smb2_request
);
1401 struct smbd_server_connection
*sconn
= req
->sconn
;
1406 if (DEBUGLEVEL
>= 10) {
1407 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1408 req
->current_idx
, req
->in
.vector_count
));
1409 print_req_vectors(req
);
1412 status
= smbd_smb2_request_dispatch(req
);
1413 if (!NT_STATUS_IS_OK(status
)) {
1414 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1419 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
)
1421 struct smbd_smb2_request
*req
= tevent_req_callback_data(subreq
,
1422 struct smbd_smb2_request
);
1423 struct smbd_server_connection
*sconn
= req
->sconn
;
1427 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1428 TALLOC_FREE(subreq
);
1431 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
1432 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1433 nt_errstr(status
)));
1434 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1439 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
1441 DATA_BLOB body
, DATA_BLOB
*dyn
,
1442 const char *location
)
1445 int i
= req
->current_idx
;
1446 uint32_t next_command_ofs
;
1448 DEBUG(10,("smbd_smb2_request_done_ex: "
1449 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1450 i
, nt_errstr(status
), (unsigned int)body
.length
,
1452 (unsigned int)(dyn
? dyn
->length
: 0),
1455 if (body
.length
< 2) {
1456 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
1459 if ((body
.length
% 2) != 0) {
1460 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
1463 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
1465 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
1466 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
1468 req
->out
.vector
[i
+1].iov_base
= (void *)body
.data
;
1469 req
->out
.vector
[i
+1].iov_len
= body
.length
;
1472 req
->out
.vector
[i
+2].iov_base
= (void *)dyn
->data
;
1473 req
->out
.vector
[i
+2].iov_len
= dyn
->length
;
1475 req
->out
.vector
[i
+2].iov_base
= NULL
;
1476 req
->out
.vector
[i
+2].iov_len
= 0;
1479 /* see if we need to recalculate the offset to the next response */
1480 if (next_command_ofs
> 0) {
1481 next_command_ofs
= SMB2_HDR_BODY
;
1482 next_command_ofs
+= req
->out
.vector
[i
+1].iov_len
;
1483 next_command_ofs
+= req
->out
.vector
[i
+2].iov_len
;
1486 if ((next_command_ofs
% 8) != 0) {
1487 size_t pad_size
= 8 - (next_command_ofs
% 8);
1488 if (req
->out
.vector
[i
+2].iov_len
== 0) {
1490 * if the dyn buffer is empty
1491 * we can use it to add padding
1495 pad
= talloc_zero_array(req
->out
.vector
,
1498 return smbd_smb2_request_error(req
,
1499 NT_STATUS_NO_MEMORY
);
1502 req
->out
.vector
[i
+2].iov_base
= (void *)pad
;
1503 req
->out
.vector
[i
+2].iov_len
= pad_size
;
1506 * For now we copy the dynamic buffer
1507 * and add the padding to the new buffer
1514 old_size
= req
->out
.vector
[i
+2].iov_len
;
1515 old_dyn
= (uint8_t *)req
->out
.vector
[i
+2].iov_base
;
1517 new_size
= old_size
+ pad_size
;
1518 new_dyn
= talloc_zero_array(req
->out
.vector
,
1520 if (new_dyn
== NULL
) {
1521 return smbd_smb2_request_error(req
,
1522 NT_STATUS_NO_MEMORY
);
1525 memcpy(new_dyn
, old_dyn
, old_size
);
1526 memset(new_dyn
+ old_size
, 0, pad_size
);
1528 req
->out
.vector
[i
+2].iov_base
= (void *)new_dyn
;
1529 req
->out
.vector
[i
+2].iov_len
= new_size
;
1531 next_command_ofs
+= pad_size
;
1534 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
1536 return smbd_smb2_request_reply(req
);
1539 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
1542 const char *location
)
1545 int i
= req
->current_idx
;
1546 uint8_t *outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
1548 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1549 i
, nt_errstr(status
), info
? " +info" : "",
1552 body
.data
= outhdr
+ SMB2_HDR_BODY
;
1554 SSVAL(body
.data
, 0, 9);
1557 SIVAL(body
.data
, 0x04, info
->length
);
1559 /* Allocated size of req->out.vector[i].iov_base
1560 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
1561 * 1 byte without having to do an alloc.
1563 info
= talloc_zero_array(req
->out
.vector
,
1567 return NT_STATUS_NO_MEMORY
;
1569 info
->data
= ((uint8_t *)outhdr
) +
1570 OUTVEC_ALLOC_SIZE
- 1;
1572 SCVAL(info
->data
, 0, 0);
1576 * if a request fails, all other remaining
1577 * compounded requests should fail too
1579 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
1581 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
1585 struct smbd_smb2_send_oplock_break_state
{
1586 struct smbd_server_connection
*sconn
;
1587 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x18];
1588 struct iovec vector
;
1591 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
);
1593 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
1594 uint64_t file_id_persistent
,
1595 uint64_t file_id_volatile
,
1596 uint8_t oplock_level
)
1598 struct smbd_smb2_send_oplock_break_state
*state
;
1599 struct tevent_req
*subreq
;
1603 state
= talloc(sconn
, struct smbd_smb2_send_oplock_break_state
);
1604 if (state
== NULL
) {
1605 return NT_STATUS_NO_MEMORY
;
1607 state
->sconn
= sconn
;
1609 state
->vector
.iov_base
= (void *)state
->buf
;
1610 state
->vector
.iov_len
= sizeof(state
->buf
);
1612 _smb2_setlen(state
->buf
, sizeof(state
->buf
) - 4);
1613 hdr
= state
->buf
+ 4;
1614 body
= hdr
+ SMB2_HDR_BODY
;
1616 SIVAL(hdr
, 0, SMB2_MAGIC
);
1617 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1618 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1619 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
1620 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
1621 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
1622 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
1623 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1624 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
1625 SIVAL(hdr
, SMB2_HDR_PID
, 0);
1626 SIVAL(hdr
, SMB2_HDR_TID
, 0);
1627 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
1628 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
1630 SSVAL(body
, 0x00, 0x18);
1632 SCVAL(body
, 0x02, oplock_level
);
1633 SCVAL(body
, 0x03, 0); /* reserved */
1634 SIVAL(body
, 0x04, 0); /* reserved */
1635 SBVAL(body
, 0x08, file_id_persistent
);
1636 SBVAL(body
, 0x10, file_id_volatile
);
1638 subreq
= tstream_writev_queue_send(state
,
1639 sconn
->smb2
.event_ctx
,
1641 sconn
->smb2
.send_queue
,
1643 if (subreq
== NULL
) {
1644 return NT_STATUS_NO_MEMORY
;
1646 tevent_req_set_callback(subreq
,
1647 smbd_smb2_oplock_break_writev_done
,
1650 return NT_STATUS_OK
;
1653 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
)
1655 struct smbd_smb2_send_oplock_break_state
*state
=
1656 tevent_req_callback_data(subreq
,
1657 struct smbd_smb2_send_oplock_break_state
);
1658 struct smbd_server_connection
*sconn
= state
->sconn
;
1662 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1663 TALLOC_FREE(subreq
);
1665 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
1666 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1673 struct smbd_smb2_request_read_state
{
1675 bool asked_for_header
;
1676 struct smbd_smb2_request
*smb2_req
;
1679 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
1681 TALLOC_CTX
*mem_ctx
,
1682 struct iovec
**_vector
,
1684 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
);
1686 static struct tevent_req
*smbd_smb2_request_read_send(TALLOC_CTX
*mem_ctx
,
1687 struct tevent_context
*ev
,
1688 struct smbd_server_connection
*sconn
)
1690 struct tevent_req
*req
;
1691 struct smbd_smb2_request_read_state
*state
;
1692 struct tevent_req
*subreq
;
1694 req
= tevent_req_create(mem_ctx
, &state
,
1695 struct smbd_smb2_request_read_state
);
1700 state
->asked_for_header
= false;
1702 state
->smb2_req
= smbd_smb2_request_allocate(state
);
1703 if (tevent_req_nomem(state
->smb2_req
, req
)) {
1704 return tevent_req_post(req
, ev
);
1706 state
->smb2_req
->sconn
= sconn
;
1708 subreq
= tstream_readv_pdu_queue_send(state
, ev
, sconn
->smb2
.stream
,
1709 sconn
->smb2
.recv_queue
,
1710 smbd_smb2_request_next_vector
,
1712 if (tevent_req_nomem(subreq
, req
)) {
1713 return tevent_req_post(req
, ev
);
1715 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
1720 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
1722 TALLOC_CTX
*mem_ctx
,
1723 struct iovec
**_vector
,
1726 struct smbd_smb2_request_read_state
*state
=
1727 talloc_get_type_abort(private_data
,
1728 struct smbd_smb2_request_read_state
);
1729 struct smbd_smb2_request
*req
= state
->smb2_req
;
1730 struct iovec
*vector
;
1731 int idx
= req
->in
.vector_count
;
1733 uint8_t *buf
= NULL
;
1735 if (req
->in
.vector_count
== 0) {
1737 * first we need to get the NBT header
1739 req
->in
.vector
= talloc_array(req
, struct iovec
,
1740 req
->in
.vector_count
+ 1);
1741 if (req
->in
.vector
== NULL
) {
1744 req
->in
.vector_count
+= 1;
1746 req
->in
.vector
[idx
].iov_base
= (void *)req
->in
.nbt_hdr
;
1747 req
->in
.vector
[idx
].iov_len
= 4;
1749 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
1750 if (vector
== NULL
) {
1754 vector
[0] = req
->in
.vector
[idx
];
1761 if (req
->in
.vector_count
== 1) {
1763 * Now we analyze the NBT header
1765 state
->missing
= smb2_len(req
->in
.vector
[0].iov_base
);
1767 if (state
->missing
== 0) {
1768 /* if there're no remaining bytes, we're done */
1774 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
1776 req
->in
.vector_count
+ 1);
1777 if (req
->in
.vector
== NULL
) {
1780 req
->in
.vector_count
+= 1;
1782 if (CVAL(req
->in
.vector
[0].iov_base
, 0) != 0) {
1784 * it's a special NBT message,
1785 * so get all remaining bytes
1787 len
= state
->missing
;
1788 } else if (state
->missing
< (SMB2_HDR_BODY
+ 2)) {
1790 * it's an invalid message, just read what we can get
1791 * and let the caller handle the error
1793 len
= state
->missing
;
1796 * We assume it's a SMB2 request,
1797 * and we first get the header and the
1798 * first 2 bytes (the struct size) of the body
1800 len
= SMB2_HDR_BODY
+ 2;
1802 state
->asked_for_header
= true;
1805 state
->missing
-= len
;
1807 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
1812 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
1813 req
->in
.vector
[idx
].iov_len
= len
;
1815 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
1816 if (vector
== NULL
) {
1820 vector
[0] = req
->in
.vector
[idx
];
1827 if (state
->missing
== 0) {
1828 /* if there're no remaining bytes, we're done */
1834 if (state
->asked_for_header
) {
1837 size_t next_command_ofs
;
1842 bool invalid
= false;
1844 state
->asked_for_header
= false;
1847 * We got the SMB2 header and the first 2 bytes
1848 * of the body. We fix the size to just the header
1849 * and manually copy the 2 first bytes to the body section
1851 req
->in
.vector
[idx
-1].iov_len
= SMB2_HDR_BODY
;
1852 hdr
= (const uint8_t *)req
->in
.vector
[idx
-1].iov_base
;
1854 /* allocate vectors for body and dynamic areas */
1855 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
1857 req
->in
.vector_count
+ 2);
1858 if (req
->in
.vector
== NULL
) {
1861 req
->in
.vector_count
+= 2;
1863 full_size
= state
->missing
+ SMB2_HDR_BODY
+ 2;
1864 next_command_ofs
= IVAL(hdr
, SMB2_HDR_NEXT_COMMAND
);
1865 body_size
= SVAL(hdr
, SMB2_HDR_BODY
);
1867 if (next_command_ofs
!= 0) {
1868 if (next_command_ofs
< (SMB2_HDR_BODY
+ 2)) {
1870 * this is invalid, just return a zero
1871 * body and let the caller deal with the error
1874 } else if (next_command_ofs
> full_size
) {
1876 * this is invalid, just return a zero
1877 * body and let the caller deal with the error
1881 full_size
= next_command_ofs
;
1886 if (body_size
< 2) {
1888 * this is invalid, just return a zero
1889 * body and let the caller deal with the error
1894 if ((body_size
% 2) != 0) {
1898 if (body_size
> (full_size
- SMB2_HDR_BODY
)) {
1900 * this is invalid, just return a zero
1901 * body and let the caller deal with the error
1908 /* the caller should check this */
1912 dyn_size
= full_size
- (SMB2_HDR_BODY
+ body_size
);
1914 state
->missing
-= (body_size
- 2) + dyn_size
;
1916 body
= talloc_array(req
->in
.vector
, uint8_t, body_size
);
1921 dyn
= talloc_array(req
->in
.vector
, uint8_t, dyn_size
);
1926 req
->in
.vector
[idx
].iov_base
= (void *)body
;
1927 req
->in
.vector
[idx
].iov_len
= body_size
;
1928 req
->in
.vector
[idx
+1].iov_base
= (void *)dyn
;
1929 req
->in
.vector
[idx
+1].iov_len
= dyn_size
;
1931 vector
= talloc_array(mem_ctx
, struct iovec
, 2);
1932 if (vector
== NULL
) {
1937 * the first 2 bytes of the body were already fetched
1938 * together with the header
1940 memcpy(body
, hdr
+ SMB2_HDR_BODY
, 2);
1941 vector
[0].iov_base
= body
+ 2;
1942 vector
[0].iov_len
= body_size
- 2;
1944 vector
[1] = req
->in
.vector
[idx
+1];
1952 * when we endup here, we're looking for a new SMB2 request
1953 * next. And we ask for its header and the first 2 bytes of
1954 * the body (like we did for the first SMB2 request).
1957 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
1959 req
->in
.vector_count
+ 1);
1960 if (req
->in
.vector
== NULL
) {
1963 req
->in
.vector_count
+= 1;
1966 * We assume it's a SMB2 request,
1967 * and we first get the header and the
1968 * first 2 bytes (the struct size) of the body
1970 len
= SMB2_HDR_BODY
+ 2;
1972 if (len
> state
->missing
) {
1973 /* let the caller handle the error */
1974 len
= state
->missing
;
1977 state
->missing
-= len
;
1978 state
->asked_for_header
= true;
1980 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
1985 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
1986 req
->in
.vector
[idx
].iov_len
= len
;
1988 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
1989 if (vector
== NULL
) {
1993 vector
[0] = req
->in
.vector
[idx
];
2000 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
)
2002 struct tevent_req
*req
=
2003 tevent_req_callback_data(subreq
,
2009 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
2011 status
= map_nt_error_from_unix(sys_errno
);
2012 tevent_req_nterror(req
, status
);
2016 tevent_req_done(req
);
2019 static NTSTATUS
smbd_smb2_request_read_recv(struct tevent_req
*req
,
2020 TALLOC_CTX
*mem_ctx
,
2021 struct smbd_smb2_request
**_smb2_req
)
2023 struct smbd_smb2_request_read_state
*state
=
2024 tevent_req_data(req
,
2025 struct smbd_smb2_request_read_state
);
2028 if (tevent_req_is_nterror(req
, &status
)) {
2029 tevent_req_received(req
);
2033 talloc_steal(mem_ctx
, state
->smb2_req
->mem_pool
);
2034 *_smb2_req
= state
->smb2_req
;
2035 tevent_req_received(req
);
2036 return NT_STATUS_OK
;
2039 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
);
2041 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
2042 const uint8_t *inbuf
, size_t size
)
2045 struct smbd_smb2_request
*req
= NULL
;
2046 struct tevent_req
*subreq
;
2048 if (lp_security() == SEC_SHARE
) {
2049 DEBUG(2,("WARNING!!: \"security = share\" is deprecated for "
2050 "SMB2 servers. Mapping to \"security = user\" and "
2051 "\"map to guest = Bad User\"\n" ));
2052 lp_do_parameter(-1, "security", "user");
2053 lp_do_parameter(-1, "map to guest", "Bad User");
2056 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2057 (unsigned int)size
));
2059 status
= smbd_initialize_smb2(sconn
);
2060 if (!NT_STATUS_IS_OK(status
)) {
2061 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2065 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
2066 if (!NT_STATUS_IS_OK(status
)) {
2067 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2071 status
= smbd_smb2_request_setup_out(req
, 1);
2072 if (!NT_STATUS_IS_OK(status
)) {
2073 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2077 status
= smbd_smb2_request_dispatch(req
);
2078 if (!NT_STATUS_IS_OK(status
)) {
2079 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2083 /* ask for the next request */
2084 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->smb2
.event_ctx
, sconn
);
2085 if (subreq
== NULL
) {
2086 smbd_server_connection_terminate(sconn
, "no memory for reading");
2089 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);
2092 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
)
2094 uint16_t creds_requested
= 0;
2095 struct smbd_server_connection
*sconn
= tevent_req_callback_data(subreq
,
2096 struct smbd_server_connection
);
2098 struct smbd_smb2_request
*req
= NULL
;
2100 status
= smbd_smb2_request_read_recv(subreq
, sconn
, &req
);
2101 TALLOC_FREE(subreq
);
2102 if (!NT_STATUS_IS_OK(status
)) {
2103 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2104 nt_errstr(status
)));
2105 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2109 if (req
->in
.nbt_hdr
[0] != 0x00) {
2110 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2111 req
->in
.nbt_hdr
[0]));
2116 req
->current_idx
= 1;
2118 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2119 req
->current_idx
, req
->in
.vector_count
));
2121 status
= smbd_smb2_request_validate(req
, &creds_requested
);
2122 if (!NT_STATUS_IS_OK(status
)) {
2123 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2127 status
= smbd_smb2_request_setup_out(req
, 5);
2128 if (!NT_STATUS_IS_OK(status
)) {
2129 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2133 status
= smbd_smb2_request_dispatch(req
);
2134 if (!NT_STATUS_IS_OK(status
)) {
2135 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2140 /* ask for the next request (this constructs the main loop) */
2141 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->smb2
.event_ctx
, sconn
);
2142 if (subreq
== NULL
) {
2143 smbd_server_connection_terminate(sconn
, "no memory for reading");
2146 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);