2 Unix SMB/CIFS implementation.
5 Copyright (C) Stefan Metzmacher 2009
6 Copyright (C) Jeremy Allison 2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../libcli/smb/smb_common.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "../lib/util/tevent_ntstatus.h"
28 #include "smbprofile.h"
30 #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9)
32 static const char *smb2_names
[] = {
54 const char *smb2_opcode_name(uint16_t opcode
)
57 return "Bad SMB2 opcode";
59 return smb2_names
[opcode
];
62 static void print_req_vectors(struct smbd_smb2_request
*req
)
66 for (i
= 0; i
< req
->in
.vector_count
; i
++) {
67 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
69 (unsigned int)req
->in
.vector
[i
].iov_len
);
71 for (i
= 0; i
< req
->out
.vector_count
; i
++) {
72 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
74 (unsigned int)req
->out
.vector
[i
].iov_len
);
78 bool smbd_is_smb2_header(const uint8_t *inbuf
, size_t size
)
80 if (size
< (4 + SMB2_HDR_BODY
)) {
84 if (IVAL(inbuf
, 4) != SMB2_MAGIC
) {
91 static NTSTATUS
smbd_initialize_smb2(struct smbd_server_connection
*sconn
)
96 TALLOC_FREE(sconn
->smb1
.fde
);
98 sconn
->smb2
.event_ctx
= smbd_event_context();
100 sconn
->smb2
.recv_queue
= tevent_queue_create(sconn
, "smb2 recv queue");
101 if (sconn
->smb2
.recv_queue
== NULL
) {
102 return NT_STATUS_NO_MEMORY
;
105 sconn
->smb2
.send_queue
= tevent_queue_create(sconn
, "smb2 send queue");
106 if (sconn
->smb2
.send_queue
== NULL
) {
107 return NT_STATUS_NO_MEMORY
;
110 sconn
->smb2
.sessions
.idtree
= idr_init(sconn
);
111 if (sconn
->smb2
.sessions
.idtree
== NULL
) {
112 return NT_STATUS_NO_MEMORY
;
114 sconn
->smb2
.sessions
.limit
= 0x0000FFFE;
115 sconn
->smb2
.sessions
.list
= NULL
;
116 sconn
->smb2
.seqnum_low
= 0;
117 sconn
->smb2
.credits_granted
= 0;
118 sconn
->smb2
.max_credits
= lp_smb2_max_credits();
119 sconn
->smb2
.credits_bitmap
= bitmap_talloc(sconn
,
120 DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
*sconn
->smb2
.max_credits
);
121 if (sconn
->smb2
.credits_bitmap
== NULL
) {
122 return NT_STATUS_NO_MEMORY
;
125 ret
= tstream_bsd_existing_socket(sconn
, sconn
->sock
,
126 &sconn
->smb2
.stream
);
128 status
= map_nt_error_from_unix(errno
);
132 /* Ensure child is set to non-blocking mode */
133 set_blocking(sconn
->sock
, false);
137 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
138 #define _smb2_setlen(_buf,len) do { \
139 uint8_t *buf = (uint8_t *)_buf; \
141 buf[1] = ((len)&0xFF0000)>>16; \
142 buf[2] = ((len)&0xFF00)>>8; \
143 buf[3] = (len)&0xFF; \
146 static void smb2_setup_nbt_length(struct iovec
*vector
, int count
)
151 for (i
=1; i
< count
; i
++) {
152 len
+= vector
[i
].iov_len
;
155 _smb2_setlen(vector
[0].iov_base
, len
);
158 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request
**req
)
161 (*req
)->parent
= NULL
;
162 (*req
)->mem_pool
= NULL
;
168 static int smbd_smb2_request_destructor(struct smbd_smb2_request
*req
)
172 talloc_free(req
->mem_pool
);
178 static struct smbd_smb2_request
*smbd_smb2_request_allocate(TALLOC_CTX
*mem_ctx
)
180 TALLOC_CTX
*mem_pool
;
181 struct smbd_smb2_request
**parent
;
182 struct smbd_smb2_request
*req
;
185 /* Enable this to find subtle valgrind errors. */
186 mem_pool
= talloc_init("smbd_smb2_request_allocate");
188 mem_pool
= talloc_pool(mem_ctx
, 8192);
190 if (mem_pool
== NULL
) {
194 parent
= talloc(mem_pool
, struct smbd_smb2_request
*);
195 if (parent
== NULL
) {
196 talloc_free(mem_pool
);
200 req
= talloc_zero(parent
, struct smbd_smb2_request
);
202 talloc_free(mem_pool
);
206 req
->mem_pool
= mem_pool
;
207 req
->parent
= parent
;
209 talloc_set_destructor(parent
, smbd_smb2_request_parent_destructor
);
210 talloc_set_destructor(req
, smbd_smb2_request_destructor
);
215 static NTSTATUS
smbd_smb2_request_create(struct smbd_server_connection
*sconn
,
216 const uint8_t *inbuf
, size_t size
,
217 struct smbd_smb2_request
**_req
)
219 struct smbd_smb2_request
*req
;
220 uint32_t protocol_version
;
221 const uint8_t *inhdr
= NULL
;
224 uint32_t next_command_ofs
;
226 if (size
< (4 + SMB2_HDR_BODY
+ 2)) {
227 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size
));
228 return NT_STATUS_INVALID_PARAMETER
;
233 protocol_version
= IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
);
234 if (protocol_version
!= SMB2_MAGIC
) {
235 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
237 return NT_STATUS_INVALID_PARAMETER
;
240 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
241 if (cmd
!= SMB2_OP_NEGPROT
) {
242 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
244 return NT_STATUS_INVALID_PARAMETER
;
247 next_command_ofs
= IVAL(inhdr
, SMB2_HDR_NEXT_COMMAND
);
248 if (next_command_ofs
!= 0) {
249 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
251 return NT_STATUS_INVALID_PARAMETER
;
254 req
= smbd_smb2_request_allocate(sconn
);
256 return NT_STATUS_NO_MEMORY
;
260 talloc_steal(req
, inbuf
);
262 req
->in
.vector
= talloc_array(req
, struct iovec
, 4);
263 if (req
->in
.vector
== NULL
) {
265 return NT_STATUS_NO_MEMORY
;
267 req
->in
.vector_count
= 4;
269 memcpy(req
->in
.nbt_hdr
, inbuf
, 4);
272 req
->in
.vector
[0].iov_base
= (void *)req
->in
.nbt_hdr
;
273 req
->in
.vector
[0].iov_len
= 4;
274 ofs
+= req
->in
.vector
[0].iov_len
;
276 req
->in
.vector
[1].iov_base
= (void *)(inbuf
+ ofs
);
277 req
->in
.vector
[1].iov_len
= SMB2_HDR_BODY
;
278 ofs
+= req
->in
.vector
[1].iov_len
;
280 req
->in
.vector
[2].iov_base
= (void *)(inbuf
+ ofs
);
281 req
->in
.vector
[2].iov_len
= SVAL(inbuf
, ofs
) & 0xFFFE;
282 ofs
+= req
->in
.vector
[2].iov_len
;
285 return NT_STATUS_INVALID_PARAMETER
;
288 req
->in
.vector
[3].iov_base
= (void *)(inbuf
+ ofs
);
289 req
->in
.vector
[3].iov_len
= size
- ofs
;
290 ofs
+= req
->in
.vector
[3].iov_len
;
292 req
->current_idx
= 1;
298 static bool smb2_validate_message_id(struct smbd_server_connection
*sconn
,
299 const uint8_t *inhdr
)
301 uint64_t message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
302 struct bitmap
*credits_bm
= sconn
->smb2
.credits_bitmap
;
303 uint16_t opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
304 unsigned int bitmap_offset
;
306 if (opcode
== SMB2_OP_CANCEL
) {
307 /* SMB2_CANCEL requests by definition resend messageids. */
311 if (message_id
< sconn
->smb2
.seqnum_low
||
312 message_id
> (sconn
->smb2
.seqnum_low
+
313 (sconn
->smb2
.max_credits
* DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
))) {
314 DEBUG(0,("smb2_validate_message_id: bad message_id "
315 "%llu (low = %llu, max = %lu)\n",
316 (unsigned long long)message_id
,
317 (unsigned long long)sconn
->smb2
.seqnum_low
,
318 (unsigned long)sconn
->smb2
.max_credits
));
322 /* client just used a credit. */
323 SMB_ASSERT(sconn
->smb2
.credits_granted
> 0);
324 sconn
->smb2
.credits_granted
-= 1;
326 /* Mark the message_id as seen in the bitmap. */
327 bitmap_offset
= (unsigned int)(message_id
%
328 (uint64_t)(sconn
->smb2
.max_credits
* DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
));
329 if (bitmap_query(credits_bm
, bitmap_offset
)) {
330 DEBUG(0,("smb2_validate_message_id: duplicate message_id "
331 "%llu (bm offset %u)\n",
332 (unsigned long long)message_id
,
336 bitmap_set(credits_bm
, bitmap_offset
);
338 if (message_id
== sconn
->smb2
.seqnum_low
+ 1) {
339 /* Move the window forward by all the message_id's
341 while (bitmap_query(credits_bm
, bitmap_offset
)) {
342 DEBUG(10,("smb2_validate_message_id: clearing "
343 "id %llu (position %u) from bitmap\n",
344 (unsigned long long)(sconn
->smb2
.seqnum_low
+ 1),
346 bitmap_clear(credits_bm
, bitmap_offset
);
347 sconn
->smb2
.seqnum_low
+= 1;
348 bitmap_offset
= (bitmap_offset
+ 1) %
349 (sconn
->smb2
.max_credits
* DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
);
356 static NTSTATUS
smbd_smb2_request_validate(struct smbd_smb2_request
*req
)
360 bool compound_related
= false;
362 count
= req
->in
.vector_count
;
365 /* It's not a SMB2 request */
366 return NT_STATUS_INVALID_PARAMETER
;
369 for (idx
=1; idx
< count
; idx
+= 3) {
370 const uint8_t *inhdr
= NULL
;
373 if (req
->in
.vector
[idx
].iov_len
!= SMB2_HDR_BODY
) {
374 return NT_STATUS_INVALID_PARAMETER
;
377 if (req
->in
.vector
[idx
+1].iov_len
< 2) {
378 return NT_STATUS_INVALID_PARAMETER
;
381 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
383 /* Check the SMB2 header */
384 if (IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
) != SMB2_MAGIC
) {
385 return NT_STATUS_INVALID_PARAMETER
;
388 if (!smb2_validate_message_id(req
->sconn
, inhdr
)) {
389 return NT_STATUS_INVALID_PARAMETER
;
392 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
395 * the 1st request should never have the
396 * SMB2_HDR_FLAG_CHAINED flag set
398 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
399 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
402 } else if (idx
== 4) {
404 * the 2nd request triggers related vs. unrelated
405 * compounded requests
407 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
408 compound_related
= true;
410 } else if (idx
> 4) {
413 * It seems the this tests are wrong
414 * see the SMB2-COMPOUND test
418 * all other requests should match the 2nd one
420 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
421 if (!compound_related
) {
423 NT_STATUS_INVALID_PARAMETER
;
427 if (compound_related
) {
429 NT_STATUS_INVALID_PARAMETER
;
440 static void smb2_set_operation_credit(struct smbd_server_connection
*sconn
,
441 const struct iovec
*in_vector
,
442 struct iovec
*out_vector
)
444 uint8_t *outhdr
= (uint8_t *)out_vector
->iov_base
;
445 uint16_t credits_requested
= 0;
446 uint16_t credits_granted
= 0;
448 if (in_vector
!= NULL
) {
449 const uint8_t *inhdr
= (const uint8_t *)in_vector
->iov_base
;
450 credits_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
453 SMB_ASSERT(sconn
->smb2
.max_credits
>= sconn
->smb2
.credits_granted
);
455 /* Remember what we gave out. */
456 credits_granted
= MIN(credits_requested
, (sconn
->smb2
.max_credits
-
457 sconn
->smb2
.credits_granted
));
459 if (credits_granted
== 0 && sconn
->smb2
.credits_granted
== 0) {
460 /* First negprot packet, or ensure the client credits can
461 never drop to zero. */
465 SSVAL(outhdr
, SMB2_HDR_CREDIT
, credits_granted
);
466 sconn
->smb2
.credits_granted
+= credits_granted
;
468 DEBUG(10,("smb2_set_operation_credit: requested %u, "
469 "granted %u, total granted %u\n",
470 (unsigned int)credits_requested
,
471 (unsigned int)credits_granted
,
472 (unsigned int)sconn
->smb2
.credits_granted
));
475 static void smb2_calculate_credits(const struct smbd_smb2_request
*inreq
,
476 struct smbd_smb2_request
*outreq
)
480 count
= outreq
->out
.vector_count
;
482 for (idx
=1; idx
< count
; idx
+= 3) {
483 smb2_set_operation_credit(outreq
->sconn
,
484 &inreq
->in
.vector
[idx
],
485 &outreq
->out
.vector
[idx
]);
489 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
)
491 struct iovec
*vector
;
495 count
= req
->in
.vector_count
;
496 vector
= talloc_zero_array(req
, struct iovec
, count
);
497 if (vector
== NULL
) {
498 return NT_STATUS_NO_MEMORY
;
501 vector
[0].iov_base
= req
->out
.nbt_hdr
;
502 vector
[0].iov_len
= 4;
503 SIVAL(req
->out
.nbt_hdr
, 0, 0);
505 for (idx
=1; idx
< count
; idx
+= 3) {
506 const uint8_t *inhdr
= NULL
;
508 uint8_t *outhdr
= NULL
;
509 uint8_t *outbody
= NULL
;
510 uint32_t next_command_ofs
= 0;
511 struct iovec
*current
= &vector
[idx
];
513 if ((idx
+ 3) < count
) {
514 /* we have a next command -
515 * setup for the error case. */
516 next_command_ofs
= SMB2_HDR_BODY
+ 9;
519 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
520 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
522 outhdr
= talloc_zero_array(vector
, uint8_t,
524 if (outhdr
== NULL
) {
525 return NT_STATUS_NO_MEMORY
;
528 outbody
= outhdr
+ SMB2_HDR_BODY
;
530 current
[0].iov_base
= (void *)outhdr
;
531 current
[0].iov_len
= SMB2_HDR_BODY
;
533 current
[1].iov_base
= (void *)outbody
;
534 current
[1].iov_len
= 8;
536 current
[2].iov_base
= NULL
;
537 current
[2].iov_len
= 0;
539 /* setup the SMB2 header */
540 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
541 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
542 SSVAL(outhdr
, SMB2_HDR_EPOCH
, 0);
543 SIVAL(outhdr
, SMB2_HDR_STATUS
,
544 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
545 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
546 SVAL(inhdr
, SMB2_HDR_OPCODE
));
547 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
548 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
549 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
550 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
551 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
552 SIVAL(outhdr
, SMB2_HDR_PID
,
553 IVAL(inhdr
, SMB2_HDR_PID
));
554 SIVAL(outhdr
, SMB2_HDR_TID
,
555 IVAL(inhdr
, SMB2_HDR_TID
));
556 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
557 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
558 memset(outhdr
+ SMB2_HDR_SIGNATURE
, 0, 16);
560 /* setup error body header */
561 SSVAL(outbody
, 0x00, 0x08 + 1);
562 SSVAL(outbody
, 0x02, 0);
563 SIVAL(outbody
, 0x04, 0);
566 req
->out
.vector
= vector
;
567 req
->out
.vector_count
= count
;
569 /* setup the length of the NBT packet */
570 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
572 DLIST_ADD_END(req
->sconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
577 void smbd_server_connection_terminate_ex(struct smbd_server_connection
*sconn
,
579 const char *location
)
581 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
583 exit_server_cleanly(reason
);
586 static bool dup_smb2_vec3(TALLOC_CTX
*ctx
,
587 struct iovec
*outvec
,
588 const struct iovec
*srcvec
)
590 /* vec[0] is always boilerplate and must
591 * be allocated with size OUTVEC_ALLOC_SIZE. */
593 outvec
[0].iov_base
= talloc_memdup(ctx
,
596 if (!outvec
[0].iov_base
) {
599 outvec
[0].iov_len
= SMB2_HDR_BODY
;
602 * If this is a "standard" vec[1] of length 8,
603 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
604 * then duplicate this. Else use talloc_memdup().
607 if (srcvec
[1].iov_len
== 8 &&
608 srcvec
[1].iov_base
==
609 ((uint8_t *)srcvec
[0].iov_base
) +
611 outvec
[1].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
613 outvec
[1].iov_len
= 8;
615 outvec
[1].iov_base
= talloc_memdup(ctx
,
618 if (!outvec
[1].iov_base
) {
621 outvec
[1].iov_len
= srcvec
[1].iov_len
;
625 * If this is a "standard" vec[2] of length 1,
626 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
627 * then duplicate this. Else use talloc_memdup().
630 if (srcvec
[2].iov_base
&&
632 if (srcvec
[2].iov_base
==
633 ((uint8_t *)srcvec
[0].iov_base
) +
634 (OUTVEC_ALLOC_SIZE
- 1) &&
635 srcvec
[2].iov_len
== 1) {
636 /* Common SMB2 error packet case. */
637 outvec
[2].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
638 (OUTVEC_ALLOC_SIZE
- 1);
640 outvec
[2].iov_base
= talloc_memdup(ctx
,
643 if (!outvec
[2].iov_base
) {
647 outvec
[2].iov_len
= srcvec
[2].iov_len
;
649 outvec
[2].iov_base
= NULL
;
650 outvec
[2].iov_len
= 0;
655 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
657 struct smbd_smb2_request
*newreq
= NULL
;
658 struct iovec
*outvec
= NULL
;
659 int count
= req
->out
.vector_count
;
662 newreq
= smbd_smb2_request_allocate(req
->sconn
);
667 newreq
->sconn
= req
->sconn
;
668 newreq
->session
= req
->session
;
669 newreq
->do_signing
= req
->do_signing
;
670 newreq
->current_idx
= req
->current_idx
;
671 newreq
->async
= false;
672 newreq
->cancelled
= false;
673 /* Note we are leaving:
677 uninitialized as NULL here as
678 they're not used in the interim
679 response code. JRA. */
681 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
686 newreq
->out
.vector
= outvec
;
687 newreq
->out
.vector_count
= count
;
689 /* Setup the outvec's identically to req. */
690 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
691 outvec
[0].iov_len
= 4;
692 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
694 /* Setup the vectors identically to the ones in req. */
695 for (i
= 1; i
< count
; i
+= 3) {
696 if (!dup_smb2_vec3(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
707 smb2_setup_nbt_length(newreq
->out
.vector
,
708 newreq
->out
.vector_count
);
713 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
);
715 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
718 uint8_t *outhdr
= NULL
;
719 struct smbd_smb2_request
*nreq
= NULL
;
721 /* Create a new smb2 request we'll use
722 for the interim return. */
723 nreq
= dup_smb2_req(req
);
725 return NT_STATUS_NO_MEMORY
;
728 /* Lose the last 3 out vectors. They're the
729 ones we'll be using for the async reply. */
730 nreq
->out
.vector_count
-= 3;
732 smb2_setup_nbt_length(nreq
->out
.vector
,
733 nreq
->out
.vector_count
);
735 /* Step back to the previous reply. */
736 i
= nreq
->current_idx
- 3;
737 outhdr
= (uint8_t *)nreq
->out
.vector
[i
].iov_base
;
738 /* And end the chain. */
739 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
741 /* Calculate outgoing credits */
742 smb2_calculate_credits(req
, nreq
);
744 /* Re-sign if needed. */
745 if (nreq
->do_signing
) {
747 status
= smb2_signing_sign_pdu(nreq
->session
->session_key
,
748 &nreq
->out
.vector
[i
], 3);
749 if (!NT_STATUS_IS_OK(status
)) {
753 if (DEBUGLEVEL
>= 10) {
754 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
755 (unsigned int)nreq
->current_idx
);
756 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
757 (unsigned int)nreq
->out
.vector_count
);
758 print_req_vectors(nreq
);
760 nreq
->subreq
= tstream_writev_queue_send(nreq
,
761 nreq
->sconn
->smb2
.event_ctx
,
762 nreq
->sconn
->smb2
.stream
,
763 nreq
->sconn
->smb2
.send_queue
,
765 nreq
->out
.vector_count
);
767 if (nreq
->subreq
== NULL
) {
768 return NT_STATUS_NO_MEMORY
;
771 tevent_req_set_callback(nreq
->subreq
,
772 smbd_smb2_request_writev_done
,
778 struct smbd_smb2_request_pending_state
{
779 struct smbd_server_connection
*sconn
;
780 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x08 + 1];
781 struct iovec vector
[3];
784 static void smbd_smb2_request_pending_writev_done(struct tevent_req
*subreq
)
786 struct smbd_smb2_request_pending_state
*state
=
787 tevent_req_callback_data(subreq
,
788 struct smbd_smb2_request_pending_state
);
789 struct smbd_server_connection
*sconn
= state
->sconn
;
793 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
796 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
797 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
804 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
805 struct tevent_req
*subreq
)
808 struct smbd_smb2_request_pending_state
*state
= NULL
;
809 int i
= req
->current_idx
;
810 uint8_t *reqhdr
= NULL
;
812 uint8_t *body
= NULL
;
814 uint64_t message_id
= 0;
815 uint64_t async_id
= 0;
816 struct iovec
*outvec
= NULL
;
818 if (!tevent_req_is_in_progress(subreq
)) {
822 req
->subreq
= subreq
;
826 /* We're already async. */
830 if (req
->in
.vector_count
> i
+ 3) {
832 * We're trying to go async in a compound
833 * request chain. This is not allowed.
834 * Cancel the outstanding request.
836 tevent_req_cancel(req
->subreq
);
837 return smbd_smb2_request_error(req
,
838 NT_STATUS_INSUFFICIENT_RESOURCES
);
841 if (DEBUGLEVEL
>= 10) {
842 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
843 (unsigned int)req
->current_idx
);
844 print_req_vectors(req
);
847 if (req
->out
.vector_count
> 4) {
848 /* This is a compound reply. We
849 * must do an interim response
850 * followed by the async response
853 status
= smb2_send_async_interim_response(req
);
854 if (!NT_STATUS_IS_OK(status
)) {
859 /* Don't return an intermediate packet on a pipe read/write. */
860 if (req
->tcon
&& req
->tcon
->compat_conn
&& IS_IPC(req
->tcon
->compat_conn
)) {
864 reqhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
865 flags
= (IVAL(reqhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
866 message_id
= BVAL(reqhdr
, SMB2_HDR_MESSAGE_ID
);
867 async_id
= message_id
; /* keep it simple for now... */
870 * What we send is identical to a smbd_smb2_request_error
871 * packet with an error status of STATUS_PENDING. Make use
872 * of this fact sometime when refactoring. JRA.
875 state
= talloc_zero(req
->sconn
, struct smbd_smb2_request_pending_state
);
877 return NT_STATUS_NO_MEMORY
;
879 state
->sconn
= req
->sconn
;
881 state
->vector
[0].iov_base
= (void *)state
->buf
;
882 state
->vector
[0].iov_len
= 4;
884 state
->vector
[1].iov_base
= state
->buf
+ 4;
885 state
->vector
[1].iov_len
= SMB2_HDR_BODY
;
887 state
->vector
[2].iov_base
= state
->buf
+ 4 + SMB2_HDR_BODY
;
888 state
->vector
[2].iov_len
= 9;
890 smb2_setup_nbt_length(state
->vector
, 3);
892 hdr
= (uint8_t *)state
->vector
[1].iov_base
;
893 body
= (uint8_t *)state
->vector
[2].iov_base
;
895 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
896 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
897 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
898 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
899 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(reqhdr
, SMB2_HDR_OPCODE
));
901 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
902 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
903 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
904 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
905 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
906 BVAL(reqhdr
, SMB2_HDR_SESSION_ID
));
907 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
909 SSVAL(body
, 0x00, 0x08 + 1);
911 SCVAL(body
, 0x02, 0);
912 SCVAL(body
, 0x03, 0);
913 SIVAL(body
, 0x04, 0);
914 /* Match W2K8R2... */
915 SCVAL(body
, 0x08, 0x21);
917 /* Ensure we correctly go through crediting. Grant
918 the credits now, and zero credits on the final
920 smb2_set_operation_credit(req
->sconn
,
924 if (req
->do_signing
) {
925 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
926 &state
->vector
[1], 2);
927 if (!NT_STATUS_IS_OK(status
)) {
932 subreq
= tstream_writev_queue_send(state
,
933 req
->sconn
->smb2
.event_ctx
,
934 req
->sconn
->smb2
.stream
,
935 req
->sconn
->smb2
.send_queue
,
939 if (subreq
== NULL
) {
940 return NT_STATUS_NO_MEMORY
;
943 tevent_req_set_callback(subreq
,
944 smbd_smb2_request_pending_writev_done
,
947 /* Note we're going async with this request. */
951 * Now manipulate req so that the outstanding async request
952 * is the only one left in the struct smbd_smb2_request.
955 if (req
->current_idx
== 1) {
956 /* There was only one. */
960 /* Re-arrange the in.vectors. */
961 req
->in
.vector
[1] = req
->in
.vector
[i
];
962 req
->in
.vector
[2] = req
->in
.vector
[i
+1];
963 req
->in
.vector
[3] = req
->in
.vector
[i
+2];
964 req
->in
.vector_count
= 4;
965 /* Reset the new in size. */
966 smb2_setup_nbt_length(req
->in
.vector
, 4);
968 /* Now recreate the out.vectors. */
969 outvec
= talloc_zero_array(req
, struct iovec
, 4);
971 return NT_STATUS_NO_MEMORY
;
974 /* 0 is always boilerplate and must
975 * be of size 4 for the length field. */
977 outvec
[0].iov_base
= req
->out
.nbt_hdr
;
978 outvec
[0].iov_len
= 4;
979 SIVAL(req
->out
.nbt_hdr
, 0, 0);
981 if (!dup_smb2_vec3(outvec
, &outvec
[1], &req
->out
.vector
[i
])) {
982 return NT_STATUS_NO_MEMORY
;
985 TALLOC_FREE(req
->out
.vector
);
987 req
->out
.vector
= outvec
;
989 req
->current_idx
= 1;
990 req
->out
.vector_count
= 4;
994 smb2_setup_nbt_length(req
->out
.vector
,
995 req
->out
.vector_count
);
997 /* Ensure our final reply matches the interim one. */
998 reqhdr
= (uint8_t *)req
->out
.vector
[1].iov_base
;
999 SIVAL(reqhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1000 SBVAL(reqhdr
, SMB2_HDR_PID
, async_id
);
1003 const uint8_t *inhdr
=
1004 (const uint8_t *)req
->in
.vector
[1].iov_base
;
1005 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1007 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1008 (unsigned long long)async_id
));
1010 return NT_STATUS_OK
;
1013 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
1015 struct smbd_server_connection
*sconn
= req
->sconn
;
1016 struct smbd_smb2_request
*cur
;
1017 const uint8_t *inhdr
;
1018 int i
= req
->current_idx
;
1020 uint64_t search_message_id
;
1021 uint64_t search_async_id
;
1024 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1026 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1027 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1028 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
1031 * we don't need the request anymore
1032 * cancel requests never have a response
1034 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1037 for (cur
= sconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
1038 const uint8_t *outhdr
;
1039 uint64_t message_id
;
1042 i
= cur
->current_idx
;
1044 outhdr
= (const uint8_t *)cur
->out
.vector
[i
].iov_base
;
1046 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1047 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
1049 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1050 if (search_async_id
== async_id
) {
1051 found_id
= async_id
;
1055 if (search_message_id
== message_id
) {
1056 found_id
= message_id
;
1062 if (cur
&& cur
->subreq
) {
1063 inhdr
= (const uint8_t *)cur
->in
.vector
[i
].iov_base
;
1064 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1065 "cancel opcode[%s] mid %llu\n",
1066 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1067 (unsigned long long)found_id
));
1068 tevent_req_cancel(cur
->subreq
);
1071 return NT_STATUS_OK
;
1074 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
1076 const uint8_t *inhdr
;
1077 int i
= req
->current_idx
;
1082 NTSTATUS session_status
;
1083 uint32_t allowed_flags
;
1084 NTSTATUS return_value
;
1086 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1088 /* TODO: verify more things */
1090 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1091 opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1092 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1093 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1094 smb2_opcode_name(opcode
),
1095 (unsigned long long)mid
));
1097 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
1098 SMB2_HDR_FLAG_SIGNED
|
1100 if (opcode
== SMB2_OP_CANCEL
) {
1101 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
1103 if ((flags
& ~allowed_flags
) != 0) {
1104 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1107 session_status
= smbd_smb2_request_check_session(req
);
1109 req
->do_signing
= false;
1110 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
1111 if (!NT_STATUS_IS_OK(session_status
)) {
1112 return smbd_smb2_request_error(req
, session_status
);
1115 req
->do_signing
= true;
1116 status
= smb2_signing_check_pdu(req
->session
->session_key
,
1117 &req
->in
.vector
[i
], 3);
1118 if (!NT_STATUS_IS_OK(status
)) {
1119 return smbd_smb2_request_error(req
, status
);
1121 } else if (req
->session
&& req
->session
->do_signing
) {
1122 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
1125 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
1127 * This check is mostly for giving the correct error code
1128 * for compounded requests.
1130 * TODO: we may need to move this after the session
1133 if (!NT_STATUS_IS_OK(req
->next_status
)) {
1134 return smbd_smb2_request_error(req
, req
->next_status
);
1137 req
->compat_chain_fsp
= NULL
;
1141 case SMB2_OP_NEGPROT
:
1143 START_PROFILE(smb2_negprot
);
1144 return_value
= smbd_smb2_request_process_negprot(req
);
1145 END_PROFILE(smb2_negprot
);
1149 case SMB2_OP_SESSSETUP
:
1151 START_PROFILE(smb2_sesssetup
);
1152 return_value
= smbd_smb2_request_process_sesssetup(req
);
1153 END_PROFILE(smb2_sesssetup
);
1157 case SMB2_OP_LOGOFF
:
1158 if (!NT_STATUS_IS_OK(session_status
)) {
1159 return_value
= smbd_smb2_request_error(req
, session_status
);
1164 START_PROFILE(smb2_logoff
);
1165 return_value
= smbd_smb2_request_process_logoff(req
);
1166 END_PROFILE(smb2_logoff
);
1171 if (!NT_STATUS_IS_OK(session_status
)) {
1172 return_value
= smbd_smb2_request_error(req
, session_status
);
1177 START_PROFILE(smb2_tcon
);
1178 return_value
= smbd_smb2_request_process_tcon(req
);
1179 END_PROFILE(smb2_tcon
);
1184 if (!NT_STATUS_IS_OK(session_status
)) {
1185 return_value
= smbd_smb2_request_error(req
, session_status
);
1188 status
= smbd_smb2_request_check_tcon(req
);
1189 if (!NT_STATUS_IS_OK(status
)) {
1190 return_value
= smbd_smb2_request_error(req
, status
);
1195 START_PROFILE(smb2_tdis
);
1196 return_value
= smbd_smb2_request_process_tdis(req
);
1197 END_PROFILE(smb2_tdis
);
1201 case SMB2_OP_CREATE
:
1202 if (!NT_STATUS_IS_OK(session_status
)) {
1203 return_value
= smbd_smb2_request_error(req
, session_status
);
1206 status
= smbd_smb2_request_check_tcon(req
);
1207 if (!NT_STATUS_IS_OK(status
)) {
1208 return_value
= smbd_smb2_request_error(req
, status
);
1213 START_PROFILE(smb2_create
);
1214 return_value
= smbd_smb2_request_process_create(req
);
1215 END_PROFILE(smb2_create
);
1220 if (!NT_STATUS_IS_OK(session_status
)) {
1221 return_value
= smbd_smb2_request_error(req
, session_status
);
1224 status
= smbd_smb2_request_check_tcon(req
);
1225 if (!NT_STATUS_IS_OK(status
)) {
1226 return_value
= smbd_smb2_request_error(req
, status
);
1231 START_PROFILE(smb2_close
);
1232 return_value
= smbd_smb2_request_process_close(req
);
1233 END_PROFILE(smb2_close
);
1238 if (!NT_STATUS_IS_OK(session_status
)) {
1239 return_value
= smbd_smb2_request_error(req
, session_status
);
1242 status
= smbd_smb2_request_check_tcon(req
);
1243 if (!NT_STATUS_IS_OK(status
)) {
1244 return_value
= smbd_smb2_request_error(req
, status
);
1249 START_PROFILE(smb2_flush
);
1250 return_value
= smbd_smb2_request_process_flush(req
);
1251 END_PROFILE(smb2_flush
);
1256 if (!NT_STATUS_IS_OK(session_status
)) {
1257 return_value
= smbd_smb2_request_error(req
, session_status
);
1260 status
= smbd_smb2_request_check_tcon(req
);
1261 if (!NT_STATUS_IS_OK(status
)) {
1262 return_value
= smbd_smb2_request_error(req
, status
);
1267 START_PROFILE(smb2_read
);
1268 return_value
= smbd_smb2_request_process_read(req
);
1269 END_PROFILE(smb2_read
);
1274 if (!NT_STATUS_IS_OK(session_status
)) {
1275 return_value
= smbd_smb2_request_error(req
, session_status
);
1278 status
= smbd_smb2_request_check_tcon(req
);
1279 if (!NT_STATUS_IS_OK(status
)) {
1280 return_value
= smbd_smb2_request_error(req
, status
);
1285 START_PROFILE(smb2_write
);
1286 return_value
= smbd_smb2_request_process_write(req
);
1287 END_PROFILE(smb2_write
);
1292 if (!NT_STATUS_IS_OK(session_status
)) {
1293 /* Too ugly to live ? JRA. */
1294 if (NT_STATUS_EQUAL(session_status
,NT_STATUS_USER_SESSION_DELETED
)) {
1295 session_status
= NT_STATUS_FILE_CLOSED
;
1297 return_value
= smbd_smb2_request_error(req
, session_status
);
1300 status
= smbd_smb2_request_check_tcon(req
);
1301 if (!NT_STATUS_IS_OK(status
)) {
1302 /* Too ugly to live ? JRA. */
1303 if (NT_STATUS_EQUAL(status
,NT_STATUS_NETWORK_NAME_DELETED
)) {
1304 status
= NT_STATUS_FILE_CLOSED
;
1306 return_value
= smbd_smb2_request_error(req
, status
);
1311 START_PROFILE(smb2_lock
);
1312 return_value
= smbd_smb2_request_process_lock(req
);
1313 END_PROFILE(smb2_lock
);
1318 if (!NT_STATUS_IS_OK(session_status
)) {
1319 return_value
= smbd_smb2_request_error(req
, session_status
);
1322 status
= smbd_smb2_request_check_tcon(req
);
1323 if (!NT_STATUS_IS_OK(status
)) {
1324 return_value
= smbd_smb2_request_error(req
, status
);
1329 START_PROFILE(smb2_ioctl
);
1330 return_value
= smbd_smb2_request_process_ioctl(req
);
1331 END_PROFILE(smb2_ioctl
);
1335 case SMB2_OP_CANCEL
:
1337 START_PROFILE(smb2_cancel
);
1338 return_value
= smbd_smb2_request_process_cancel(req
);
1339 END_PROFILE(smb2_cancel
);
1343 case SMB2_OP_KEEPALIVE
:
1344 {START_PROFILE(smb2_keepalive
);
1345 return_value
= smbd_smb2_request_process_keepalive(req
);
1346 END_PROFILE(smb2_keepalive
);}
1350 if (!NT_STATUS_IS_OK(session_status
)) {
1351 return_value
= smbd_smb2_request_error(req
, session_status
);
1354 status
= smbd_smb2_request_check_tcon(req
);
1355 if (!NT_STATUS_IS_OK(status
)) {
1356 return_value
= smbd_smb2_request_error(req
, status
);
1361 START_PROFILE(smb2_find
);
1362 return_value
= smbd_smb2_request_process_find(req
);
1363 END_PROFILE(smb2_find
);
1367 case SMB2_OP_NOTIFY
:
1368 if (!NT_STATUS_IS_OK(session_status
)) {
1369 return_value
= smbd_smb2_request_error(req
, session_status
);
1372 status
= smbd_smb2_request_check_tcon(req
);
1373 if (!NT_STATUS_IS_OK(status
)) {
1374 return_value
= smbd_smb2_request_error(req
, status
);
1379 START_PROFILE(smb2_notify
);
1380 return_value
= smbd_smb2_request_process_notify(req
);
1381 END_PROFILE(smb2_notify
);
1385 case SMB2_OP_GETINFO
:
1386 if (!NT_STATUS_IS_OK(session_status
)) {
1387 return_value
= smbd_smb2_request_error(req
, session_status
);
1390 status
= smbd_smb2_request_check_tcon(req
);
1391 if (!NT_STATUS_IS_OK(status
)) {
1392 return_value
= smbd_smb2_request_error(req
, status
);
1397 START_PROFILE(smb2_getinfo
);
1398 return_value
= smbd_smb2_request_process_getinfo(req
);
1399 END_PROFILE(smb2_getinfo
);
1403 case SMB2_OP_SETINFO
:
1404 if (!NT_STATUS_IS_OK(session_status
)) {
1405 return_value
= smbd_smb2_request_error(req
, session_status
);
1408 status
= smbd_smb2_request_check_tcon(req
);
1409 if (!NT_STATUS_IS_OK(status
)) {
1410 return_value
= smbd_smb2_request_error(req
, status
);
1415 START_PROFILE(smb2_setinfo
);
1416 return_value
= smbd_smb2_request_process_setinfo(req
);
1417 END_PROFILE(smb2_setinfo
);
1422 if (!NT_STATUS_IS_OK(session_status
)) {
1423 return_value
= smbd_smb2_request_error(req
, session_status
);
1426 status
= smbd_smb2_request_check_tcon(req
);
1427 if (!NT_STATUS_IS_OK(status
)) {
1428 return_value
= smbd_smb2_request_error(req
, status
);
1433 START_PROFILE(smb2_break
);
1434 return_value
= smbd_smb2_request_process_break(req
);
1435 END_PROFILE(smb2_break
);
1440 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1443 return return_value
;
1446 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
1448 struct tevent_req
*subreq
;
1449 int i
= req
->current_idx
;
1453 req
->current_idx
+= 3;
1455 if (req
->current_idx
< req
->out
.vector_count
) {
1457 * We must process the remaining compound
1458 * SMB2 requests before any new incoming SMB2
1459 * requests. This is because incoming SMB2
1460 * requests may include a cancel for a
1461 * compound request we haven't processed
1464 struct tevent_immediate
*im
= tevent_create_immediate(req
);
1466 return NT_STATUS_NO_MEMORY
;
1468 tevent_schedule_immediate(im
,
1469 req
->sconn
->smb2
.event_ctx
,
1470 smbd_smb2_request_dispatch_immediate
,
1472 return NT_STATUS_OK
;
1475 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
1477 /* Set credit for this operation (zero credits if this
1478 is a final reply for an async operation). */
1479 smb2_set_operation_credit(req
->sconn
,
1480 req
->async
? NULL
: &req
->in
.vector
[i
],
1481 &req
->out
.vector
[i
]);
1483 if (req
->do_signing
) {
1485 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
1486 &req
->out
.vector
[i
], 3);
1487 if (!NT_STATUS_IS_OK(status
)) {
1492 if (DEBUGLEVEL
>= 10) {
1493 dbgtext("smbd_smb2_request_reply: sending...\n");
1494 print_req_vectors(req
);
1497 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1498 if (req
->out
.vector_count
== 4 &&
1499 req
->out
.vector
[3].iov_base
== NULL
&&
1500 req
->out
.vector
[3].iov_len
!= 0) {
1501 /* Dynamic part is NULL. Chop it off,
1502 We're going to send it via sendfile. */
1503 req
->out
.vector_count
-= 1;
1506 subreq
= tstream_writev_queue_send(req
,
1507 req
->sconn
->smb2
.event_ctx
,
1508 req
->sconn
->smb2
.stream
,
1509 req
->sconn
->smb2
.send_queue
,
1511 req
->out
.vector_count
);
1512 if (subreq
== NULL
) {
1513 return NT_STATUS_NO_MEMORY
;
1515 tevent_req_set_callback(subreq
, smbd_smb2_request_writev_done
, req
);
1517 * We're done with this request -
1518 * move it off the "being processed" queue.
1520 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1522 return NT_STATUS_OK
;
1525 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
1526 struct tevent_immediate
*im
,
1529 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
1530 struct smbd_smb2_request
);
1531 struct smbd_server_connection
*sconn
= req
->sconn
;
1536 if (DEBUGLEVEL
>= 10) {
1537 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1538 req
->current_idx
, req
->in
.vector_count
));
1539 print_req_vectors(req
);
1542 status
= smbd_smb2_request_dispatch(req
);
1543 if (!NT_STATUS_IS_OK(status
)) {
1544 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1549 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
)
1551 struct smbd_smb2_request
*req
= tevent_req_callback_data(subreq
,
1552 struct smbd_smb2_request
);
1553 struct smbd_server_connection
*sconn
= req
->sconn
;
1557 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1558 TALLOC_FREE(subreq
);
1561 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
1562 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1563 nt_errstr(status
)));
1564 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1569 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
1571 DATA_BLOB body
, DATA_BLOB
*dyn
,
1572 const char *location
)
1575 int i
= req
->current_idx
;
1576 uint32_t next_command_ofs
;
1578 DEBUG(10,("smbd_smb2_request_done_ex: "
1579 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1580 i
, nt_errstr(status
), (unsigned int)body
.length
,
1582 (unsigned int)(dyn
? dyn
->length
: 0),
1585 if (body
.length
< 2) {
1586 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
1589 if ((body
.length
% 2) != 0) {
1590 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
1593 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
1595 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
1596 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
1598 req
->out
.vector
[i
+1].iov_base
= (void *)body
.data
;
1599 req
->out
.vector
[i
+1].iov_len
= body
.length
;
1602 req
->out
.vector
[i
+2].iov_base
= (void *)dyn
->data
;
1603 req
->out
.vector
[i
+2].iov_len
= dyn
->length
;
1605 req
->out
.vector
[i
+2].iov_base
= NULL
;
1606 req
->out
.vector
[i
+2].iov_len
= 0;
1609 /* see if we need to recalculate the offset to the next response */
1610 if (next_command_ofs
> 0) {
1611 next_command_ofs
= SMB2_HDR_BODY
;
1612 next_command_ofs
+= req
->out
.vector
[i
+1].iov_len
;
1613 next_command_ofs
+= req
->out
.vector
[i
+2].iov_len
;
1616 if ((next_command_ofs
% 8) != 0) {
1617 size_t pad_size
= 8 - (next_command_ofs
% 8);
1618 if (req
->out
.vector
[i
+2].iov_len
== 0) {
1620 * if the dyn buffer is empty
1621 * we can use it to add padding
1625 pad
= talloc_zero_array(req
->out
.vector
,
1628 return smbd_smb2_request_error(req
,
1629 NT_STATUS_NO_MEMORY
);
1632 req
->out
.vector
[i
+2].iov_base
= (void *)pad
;
1633 req
->out
.vector
[i
+2].iov_len
= pad_size
;
1636 * For now we copy the dynamic buffer
1637 * and add the padding to the new buffer
1644 old_size
= req
->out
.vector
[i
+2].iov_len
;
1645 old_dyn
= (uint8_t *)req
->out
.vector
[i
+2].iov_base
;
1647 new_size
= old_size
+ pad_size
;
1648 new_dyn
= talloc_zero_array(req
->out
.vector
,
1650 if (new_dyn
== NULL
) {
1651 return smbd_smb2_request_error(req
,
1652 NT_STATUS_NO_MEMORY
);
1655 memcpy(new_dyn
, old_dyn
, old_size
);
1656 memset(new_dyn
+ old_size
, 0, pad_size
);
1658 req
->out
.vector
[i
+2].iov_base
= (void *)new_dyn
;
1659 req
->out
.vector
[i
+2].iov_len
= new_size
;
1661 next_command_ofs
+= pad_size
;
1664 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
1666 return smbd_smb2_request_reply(req
);
1669 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
1672 const char *location
)
1675 int i
= req
->current_idx
;
1676 uint8_t *outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
1678 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1679 i
, nt_errstr(status
), info
? " +info" : "",
1682 body
.data
= outhdr
+ SMB2_HDR_BODY
;
1684 SSVAL(body
.data
, 0, 9);
1687 SIVAL(body
.data
, 0x04, info
->length
);
1689 /* Allocated size of req->out.vector[i].iov_base
1690 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
1691 * 1 byte without having to do an alloc.
1693 info
= talloc_zero_array(req
->out
.vector
,
1697 return NT_STATUS_NO_MEMORY
;
1699 info
->data
= ((uint8_t *)outhdr
) +
1700 OUTVEC_ALLOC_SIZE
- 1;
1702 SCVAL(info
->data
, 0, 0);
1706 * if a request fails, all other remaining
1707 * compounded requests should fail too
1709 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
1711 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
1715 struct smbd_smb2_send_oplock_break_state
{
1716 struct smbd_server_connection
*sconn
;
1717 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x18];
1718 struct iovec vector
;
1721 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
);
1723 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
1724 uint64_t file_id_persistent
,
1725 uint64_t file_id_volatile
,
1726 uint8_t oplock_level
)
1728 struct smbd_smb2_send_oplock_break_state
*state
;
1729 struct tevent_req
*subreq
;
1733 state
= talloc(sconn
, struct smbd_smb2_send_oplock_break_state
);
1734 if (state
== NULL
) {
1735 return NT_STATUS_NO_MEMORY
;
1737 state
->sconn
= sconn
;
1739 state
->vector
.iov_base
= (void *)state
->buf
;
1740 state
->vector
.iov_len
= sizeof(state
->buf
);
1742 _smb2_setlen(state
->buf
, sizeof(state
->buf
) - 4);
1743 hdr
= state
->buf
+ 4;
1744 body
= hdr
+ SMB2_HDR_BODY
;
1746 SIVAL(hdr
, 0, SMB2_MAGIC
);
1747 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1748 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1749 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
1750 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
1751 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
1752 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
1753 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1754 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
1755 SIVAL(hdr
, SMB2_HDR_PID
, 0);
1756 SIVAL(hdr
, SMB2_HDR_TID
, 0);
1757 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
1758 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
1760 SSVAL(body
, 0x00, 0x18);
1762 SCVAL(body
, 0x02, oplock_level
);
1763 SCVAL(body
, 0x03, 0); /* reserved */
1764 SIVAL(body
, 0x04, 0); /* reserved */
1765 SBVAL(body
, 0x08, file_id_persistent
);
1766 SBVAL(body
, 0x10, file_id_volatile
);
1768 subreq
= tstream_writev_queue_send(state
,
1769 sconn
->smb2
.event_ctx
,
1771 sconn
->smb2
.send_queue
,
1773 if (subreq
== NULL
) {
1774 return NT_STATUS_NO_MEMORY
;
1776 tevent_req_set_callback(subreq
,
1777 smbd_smb2_oplock_break_writev_done
,
1780 return NT_STATUS_OK
;
1783 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
)
1785 struct smbd_smb2_send_oplock_break_state
*state
=
1786 tevent_req_callback_data(subreq
,
1787 struct smbd_smb2_send_oplock_break_state
);
1788 struct smbd_server_connection
*sconn
= state
->sconn
;
1792 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1793 TALLOC_FREE(subreq
);
1795 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
1796 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1803 struct smbd_smb2_request_read_state
{
1805 bool asked_for_header
;
1806 struct smbd_smb2_request
*smb2_req
;
1809 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
1811 TALLOC_CTX
*mem_ctx
,
1812 struct iovec
**_vector
,
1814 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
);
1816 static struct tevent_req
*smbd_smb2_request_read_send(TALLOC_CTX
*mem_ctx
,
1817 struct tevent_context
*ev
,
1818 struct smbd_server_connection
*sconn
)
1820 struct tevent_req
*req
;
1821 struct smbd_smb2_request_read_state
*state
;
1822 struct tevent_req
*subreq
;
1824 req
= tevent_req_create(mem_ctx
, &state
,
1825 struct smbd_smb2_request_read_state
);
1830 state
->asked_for_header
= false;
1832 state
->smb2_req
= smbd_smb2_request_allocate(state
);
1833 if (tevent_req_nomem(state
->smb2_req
, req
)) {
1834 return tevent_req_post(req
, ev
);
1836 state
->smb2_req
->sconn
= sconn
;
1838 subreq
= tstream_readv_pdu_queue_send(state
, ev
, sconn
->smb2
.stream
,
1839 sconn
->smb2
.recv_queue
,
1840 smbd_smb2_request_next_vector
,
1842 if (tevent_req_nomem(subreq
, req
)) {
1843 return tevent_req_post(req
, ev
);
1845 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
1850 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
1852 TALLOC_CTX
*mem_ctx
,
1853 struct iovec
**_vector
,
1856 struct smbd_smb2_request_read_state
*state
=
1857 talloc_get_type_abort(private_data
,
1858 struct smbd_smb2_request_read_state
);
1859 struct smbd_smb2_request
*req
= state
->smb2_req
;
1860 struct iovec
*vector
;
1861 int idx
= req
->in
.vector_count
;
1863 uint8_t *buf
= NULL
;
1865 if (req
->in
.vector_count
== 0) {
1867 * first we need to get the NBT header
1869 req
->in
.vector
= talloc_array(req
, struct iovec
,
1870 req
->in
.vector_count
+ 1);
1871 if (req
->in
.vector
== NULL
) {
1874 req
->in
.vector_count
+= 1;
1876 req
->in
.vector
[idx
].iov_base
= (void *)req
->in
.nbt_hdr
;
1877 req
->in
.vector
[idx
].iov_len
= 4;
1879 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
1880 if (vector
== NULL
) {
1884 vector
[0] = req
->in
.vector
[idx
];
1891 if (req
->in
.vector_count
== 1) {
1893 * Now we analyze the NBT header
1895 state
->missing
= smb2_len(req
->in
.vector
[0].iov_base
);
1897 if (state
->missing
== 0) {
1898 /* if there're no remaining bytes, we're done */
1904 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
1906 req
->in
.vector_count
+ 1);
1907 if (req
->in
.vector
== NULL
) {
1910 req
->in
.vector_count
+= 1;
1912 if (CVAL(req
->in
.vector
[0].iov_base
, 0) != 0) {
1914 * it's a special NBT message,
1915 * so get all remaining bytes
1917 len
= state
->missing
;
1918 } else if (state
->missing
< (SMB2_HDR_BODY
+ 2)) {
1920 * it's an invalid message, just read what we can get
1921 * and let the caller handle the error
1923 len
= state
->missing
;
1926 * We assume it's a SMB2 request,
1927 * and we first get the header and the
1928 * first 2 bytes (the struct size) of the body
1930 len
= SMB2_HDR_BODY
+ 2;
1932 state
->asked_for_header
= true;
1935 state
->missing
-= len
;
1937 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
1942 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
1943 req
->in
.vector
[idx
].iov_len
= len
;
1945 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
1946 if (vector
== NULL
) {
1950 vector
[0] = req
->in
.vector
[idx
];
1957 if (state
->missing
== 0) {
1958 /* if there're no remaining bytes, we're done */
1964 if (state
->asked_for_header
) {
1967 size_t next_command_ofs
;
1972 bool invalid
= false;
1974 state
->asked_for_header
= false;
1977 * We got the SMB2 header and the first 2 bytes
1978 * of the body. We fix the size to just the header
1979 * and manually copy the 2 first bytes to the body section
1981 req
->in
.vector
[idx
-1].iov_len
= SMB2_HDR_BODY
;
1982 hdr
= (const uint8_t *)req
->in
.vector
[idx
-1].iov_base
;
1984 /* allocate vectors for body and dynamic areas */
1985 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
1987 req
->in
.vector_count
+ 2);
1988 if (req
->in
.vector
== NULL
) {
1991 req
->in
.vector_count
+= 2;
1993 full_size
= state
->missing
+ SMB2_HDR_BODY
+ 2;
1994 next_command_ofs
= IVAL(hdr
, SMB2_HDR_NEXT_COMMAND
);
1995 body_size
= SVAL(hdr
, SMB2_HDR_BODY
);
1997 if (next_command_ofs
!= 0) {
1998 if (next_command_ofs
< (SMB2_HDR_BODY
+ 2)) {
2000 * this is invalid, just return a zero
2001 * body and let the caller deal with the error
2004 } else if (next_command_ofs
> full_size
) {
2006 * this is invalid, just return a zero
2007 * body and let the caller deal with the error
2011 full_size
= next_command_ofs
;
2016 if (body_size
< 2) {
2018 * this is invalid, just return a zero
2019 * body and let the caller deal with the error
2024 if ((body_size
% 2) != 0) {
2028 if (body_size
> (full_size
- SMB2_HDR_BODY
)) {
2030 * this is invalid, just return a zero
2031 * body and let the caller deal with the error
2038 /* the caller should check this */
2042 dyn_size
= full_size
- (SMB2_HDR_BODY
+ body_size
);
2044 state
->missing
-= (body_size
- 2) + dyn_size
;
2046 body
= talloc_array(req
->in
.vector
, uint8_t, body_size
);
2051 dyn
= talloc_array(req
->in
.vector
, uint8_t, dyn_size
);
2056 req
->in
.vector
[idx
].iov_base
= (void *)body
;
2057 req
->in
.vector
[idx
].iov_len
= body_size
;
2058 req
->in
.vector
[idx
+1].iov_base
= (void *)dyn
;
2059 req
->in
.vector
[idx
+1].iov_len
= dyn_size
;
2061 vector
= talloc_array(mem_ctx
, struct iovec
, 2);
2062 if (vector
== NULL
) {
2067 * the first 2 bytes of the body were already fetched
2068 * together with the header
2070 memcpy(body
, hdr
+ SMB2_HDR_BODY
, 2);
2071 vector
[0].iov_base
= body
+ 2;
2072 vector
[0].iov_len
= body_size
- 2;
2074 vector
[1] = req
->in
.vector
[idx
+1];
2082 * when we endup here, we're looking for a new SMB2 request
2083 * next. And we ask for its header and the first 2 bytes of
2084 * the body (like we did for the first SMB2 request).
2087 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2089 req
->in
.vector_count
+ 1);
2090 if (req
->in
.vector
== NULL
) {
2093 req
->in
.vector_count
+= 1;
2096 * We assume it's a SMB2 request,
2097 * and we first get the header and the
2098 * first 2 bytes (the struct size) of the body
2100 len
= SMB2_HDR_BODY
+ 2;
2102 if (len
> state
->missing
) {
2103 /* let the caller handle the error */
2104 len
= state
->missing
;
2107 state
->missing
-= len
;
2108 state
->asked_for_header
= true;
2110 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2115 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2116 req
->in
.vector
[idx
].iov_len
= len
;
2118 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2119 if (vector
== NULL
) {
2123 vector
[0] = req
->in
.vector
[idx
];
2130 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
)
2132 struct tevent_req
*req
=
2133 tevent_req_callback_data(subreq
,
2139 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
2141 status
= map_nt_error_from_unix(sys_errno
);
2142 tevent_req_nterror(req
, status
);
2146 tevent_req_done(req
);
2149 static NTSTATUS
smbd_smb2_request_read_recv(struct tevent_req
*req
,
2150 TALLOC_CTX
*mem_ctx
,
2151 struct smbd_smb2_request
**_smb2_req
)
2153 struct smbd_smb2_request_read_state
*state
=
2154 tevent_req_data(req
,
2155 struct smbd_smb2_request_read_state
);
2158 if (tevent_req_is_nterror(req
, &status
)) {
2159 tevent_req_received(req
);
2163 talloc_steal(mem_ctx
, state
->smb2_req
->mem_pool
);
2164 *_smb2_req
= state
->smb2_req
;
2165 tevent_req_received(req
);
2166 return NT_STATUS_OK
;
2169 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
);
2171 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
2172 const uint8_t *inbuf
, size_t size
)
2175 struct smbd_smb2_request
*req
= NULL
;
2176 struct tevent_req
*subreq
;
2178 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2179 (unsigned int)size
));
2181 status
= smbd_initialize_smb2(sconn
);
2182 if (!NT_STATUS_IS_OK(status
)) {
2183 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2187 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
2188 if (!NT_STATUS_IS_OK(status
)) {
2189 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2193 status
= smbd_smb2_request_setup_out(req
);
2194 if (!NT_STATUS_IS_OK(status
)) {
2195 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2199 status
= smbd_smb2_request_dispatch(req
);
2200 if (!NT_STATUS_IS_OK(status
)) {
2201 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2205 /* ask for the next request */
2206 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->smb2
.event_ctx
, sconn
);
2207 if (subreq
== NULL
) {
2208 smbd_server_connection_terminate(sconn
, "no memory for reading");
2211 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);
2213 sconn
->num_requests
++;
2216 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
)
2218 struct smbd_server_connection
*sconn
= tevent_req_callback_data(subreq
,
2219 struct smbd_server_connection
);
2221 struct smbd_smb2_request
*req
= NULL
;
2223 status
= smbd_smb2_request_read_recv(subreq
, sconn
, &req
);
2224 TALLOC_FREE(subreq
);
2225 if (!NT_STATUS_IS_OK(status
)) {
2226 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2227 nt_errstr(status
)));
2228 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2232 if (req
->in
.nbt_hdr
[0] != 0x00) {
2233 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2234 req
->in
.nbt_hdr
[0]));
2239 req
->current_idx
= 1;
2241 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2242 req
->current_idx
, req
->in
.vector_count
));
2244 status
= smbd_smb2_request_validate(req
);
2245 if (!NT_STATUS_IS_OK(status
)) {
2246 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2250 status
= smbd_smb2_request_setup_out(req
);
2251 if (!NT_STATUS_IS_OK(status
)) {
2252 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2256 status
= smbd_smb2_request_dispatch(req
);
2257 if (!NT_STATUS_IS_OK(status
)) {
2258 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2263 /* ask for the next request (this constructs the main loop) */
2264 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->smb2
.event_ctx
, sconn
);
2265 if (subreq
== NULL
) {
2266 smbd_server_connection_terminate(sconn
, "no memory for reading");
2269 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);
2271 sconn
->num_requests
++;
2273 /* The timeout_processing function isn't run nearly
2274 often enough to implement 'max log size' without
2275 overrunning the size of the file by many megabytes.
2276 This is especially true if we are running at debug
2277 level 10. Checking every 50 SMB2s is a nice
2278 tradeoff of performance vs log file size overrun. */
2280 if ((sconn
->num_requests
% 50) == 0 &&
2281 need_to_check_log_size()) {
2282 change_to_root_user();