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 "smbprofile.h"
29 #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9)
31 static const char *smb2_names
[] = {
53 const char *smb2_opcode_name(uint16_t opcode
)
56 return "Bad SMB2 opcode";
58 return smb2_names
[opcode
];
61 static void print_req_vectors(struct smbd_smb2_request
*req
)
65 for (i
= 0; i
< req
->in
.vector_count
; i
++) {
66 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
68 (unsigned int)req
->in
.vector
[i
].iov_len
);
70 for (i
= 0; i
< req
->out
.vector_count
; i
++) {
71 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
73 (unsigned int)req
->out
.vector
[i
].iov_len
);
77 bool smbd_is_smb2_header(const uint8_t *inbuf
, size_t size
)
79 if (size
< (4 + SMB2_HDR_BODY
)) {
83 if (IVAL(inbuf
, 4) != SMB2_MAGIC
) {
90 static NTSTATUS
smbd_initialize_smb2(struct smbd_server_connection
*sconn
)
95 TALLOC_FREE(sconn
->smb1
.fde
);
97 sconn
->smb2
.event_ctx
= smbd_event_context();
99 sconn
->smb2
.recv_queue
= tevent_queue_create(sconn
, "smb2 recv queue");
100 if (sconn
->smb2
.recv_queue
== NULL
) {
101 return NT_STATUS_NO_MEMORY
;
104 sconn
->smb2
.send_queue
= tevent_queue_create(sconn
, "smb2 send queue");
105 if (sconn
->smb2
.send_queue
== NULL
) {
106 return NT_STATUS_NO_MEMORY
;
109 sconn
->smb2
.sessions
.idtree
= idr_init(sconn
);
110 if (sconn
->smb2
.sessions
.idtree
== NULL
) {
111 return NT_STATUS_NO_MEMORY
;
113 sconn
->smb2
.sessions
.limit
= 0x0000FFFE;
114 sconn
->smb2
.sessions
.list
= NULL
;
115 sconn
->smb2
.seqnum_low
= 0;
116 sconn
->smb2
.credits_granted
= 0;
117 sconn
->smb2
.max_credits
= lp_smb2_max_credits();
118 sconn
->smb2
.credits_bitmap
= bitmap_talloc(sconn
,
119 DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
*sconn
->smb2
.max_credits
);
120 if (sconn
->smb2
.credits_bitmap
== NULL
) {
121 return NT_STATUS_NO_MEMORY
;
124 ret
= tstream_bsd_existing_socket(sconn
, sconn
->sock
,
125 &sconn
->smb2
.stream
);
127 status
= map_nt_error_from_unix(errno
);
131 /* Ensure child is set to non-blocking mode */
132 set_blocking(sconn
->sock
, false);
136 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
137 #define _smb2_setlen(_buf,len) do { \
138 uint8_t *buf = (uint8_t *)_buf; \
140 buf[1] = ((len)&0xFF0000)>>16; \
141 buf[2] = ((len)&0xFF00)>>8; \
142 buf[3] = (len)&0xFF; \
145 static void smb2_setup_nbt_length(struct iovec
*vector
, int count
)
150 for (i
=1; i
< count
; i
++) {
151 len
+= vector
[i
].iov_len
;
154 _smb2_setlen(vector
[0].iov_base
, len
);
157 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request
**req
)
160 (*req
)->parent
= NULL
;
161 (*req
)->mem_pool
= NULL
;
167 static int smbd_smb2_request_destructor(struct smbd_smb2_request
*req
)
171 talloc_free(req
->mem_pool
);
177 static struct smbd_smb2_request
*smbd_smb2_request_allocate(TALLOC_CTX
*mem_ctx
)
179 TALLOC_CTX
*mem_pool
;
180 struct smbd_smb2_request
**parent
;
181 struct smbd_smb2_request
*req
;
184 /* Enable this to find subtle valgrind errors. */
185 mem_pool
= talloc_init("smbd_smb2_request_allocate");
187 mem_pool
= talloc_pool(mem_ctx
, 8192);
189 if (mem_pool
== NULL
) {
193 parent
= talloc(mem_pool
, struct smbd_smb2_request
*);
194 if (parent
== NULL
) {
195 talloc_free(mem_pool
);
199 req
= talloc_zero(parent
, struct smbd_smb2_request
);
201 talloc_free(mem_pool
);
205 req
->mem_pool
= mem_pool
;
206 req
->parent
= parent
;
208 talloc_set_destructor(parent
, smbd_smb2_request_parent_destructor
);
209 talloc_set_destructor(req
, smbd_smb2_request_destructor
);
214 static NTSTATUS
smbd_smb2_request_create(struct smbd_server_connection
*sconn
,
215 const uint8_t *inbuf
, size_t size
,
216 struct smbd_smb2_request
**_req
)
218 struct smbd_smb2_request
*req
;
219 uint32_t protocol_version
;
220 const uint8_t *inhdr
= NULL
;
223 uint32_t next_command_ofs
;
225 if (size
< (4 + SMB2_HDR_BODY
+ 2)) {
226 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size
));
227 return NT_STATUS_INVALID_PARAMETER
;
232 protocol_version
= IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
);
233 if (protocol_version
!= SMB2_MAGIC
) {
234 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
236 return NT_STATUS_INVALID_PARAMETER
;
239 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
240 if (cmd
!= SMB2_OP_NEGPROT
) {
241 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
243 return NT_STATUS_INVALID_PARAMETER
;
246 next_command_ofs
= IVAL(inhdr
, SMB2_HDR_NEXT_COMMAND
);
247 if (next_command_ofs
!= 0) {
248 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
250 return NT_STATUS_INVALID_PARAMETER
;
253 req
= smbd_smb2_request_allocate(sconn
);
255 return NT_STATUS_NO_MEMORY
;
259 talloc_steal(req
, inbuf
);
261 req
->in
.vector
= talloc_array(req
, struct iovec
, 4);
262 if (req
->in
.vector
== NULL
) {
264 return NT_STATUS_NO_MEMORY
;
266 req
->in
.vector_count
= 4;
268 memcpy(req
->in
.nbt_hdr
, inbuf
, 4);
271 req
->in
.vector
[0].iov_base
= (void *)req
->in
.nbt_hdr
;
272 req
->in
.vector
[0].iov_len
= 4;
273 ofs
+= req
->in
.vector
[0].iov_len
;
275 req
->in
.vector
[1].iov_base
= (void *)(inbuf
+ ofs
);
276 req
->in
.vector
[1].iov_len
= SMB2_HDR_BODY
;
277 ofs
+= req
->in
.vector
[1].iov_len
;
279 req
->in
.vector
[2].iov_base
= (void *)(inbuf
+ ofs
);
280 req
->in
.vector
[2].iov_len
= SVAL(inbuf
, ofs
) & 0xFFFE;
281 ofs
+= req
->in
.vector
[2].iov_len
;
284 return NT_STATUS_INVALID_PARAMETER
;
287 req
->in
.vector
[3].iov_base
= (void *)(inbuf
+ ofs
);
288 req
->in
.vector
[3].iov_len
= size
- ofs
;
289 ofs
+= req
->in
.vector
[3].iov_len
;
291 req
->current_idx
= 1;
297 static bool smb2_validate_message_id(struct smbd_server_connection
*sconn
,
298 const uint8_t *inhdr
)
300 uint64_t message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
301 struct bitmap
*credits_bm
= sconn
->smb2
.credits_bitmap
;
302 uint16_t opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
303 unsigned int bitmap_offset
;
305 if (opcode
== SMB2_OP_CANCEL
) {
306 /* SMB2_CANCEL requests by definition resend messageids. */
310 if (message_id
< sconn
->smb2
.seqnum_low
||
311 message_id
> (sconn
->smb2
.seqnum_low
+
312 (sconn
->smb2
.max_credits
* DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
))) {
313 DEBUG(0,("smb2_validate_message_id: bad message_id "
314 "%llu (low = %llu, max = %lu)\n",
315 (unsigned long long)message_id
,
316 (unsigned long long)sconn
->smb2
.seqnum_low
,
317 (unsigned long)sconn
->smb2
.max_credits
));
321 /* client just used a credit. */
322 SMB_ASSERT(sconn
->smb2
.credits_granted
> 0);
323 sconn
->smb2
.credits_granted
-= 1;
325 /* Mark the message_id as seen in the bitmap. */
326 bitmap_offset
= (unsigned int)(message_id
%
327 (uint64_t)(sconn
->smb2
.max_credits
* DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
));
328 if (bitmap_query(credits_bm
, bitmap_offset
)) {
329 DEBUG(0,("smb2_validate_message_id: duplicate message_id "
330 "%llu (bm offset %u)\n",
331 (unsigned long long)message_id
,
335 bitmap_set(credits_bm
, bitmap_offset
);
337 if (message_id
== sconn
->smb2
.seqnum_low
+ 1) {
338 /* Move the window forward by all the message_id's
340 while (bitmap_query(credits_bm
, bitmap_offset
)) {
341 DEBUG(10,("smb2_validate_message_id: clearing "
342 "id %llu (position %u) from bitmap\n",
343 (unsigned long long)(sconn
->smb2
.seqnum_low
+ 1),
345 bitmap_clear(credits_bm
, bitmap_offset
);
346 sconn
->smb2
.seqnum_low
+= 1;
347 bitmap_offset
= (bitmap_offset
+ 1) %
348 (sconn
->smb2
.max_credits
* DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
);
355 static NTSTATUS
smbd_smb2_request_validate(struct smbd_smb2_request
*req
)
359 bool compound_related
= false;
361 count
= req
->in
.vector_count
;
364 /* It's not a SMB2 request */
365 return NT_STATUS_INVALID_PARAMETER
;
368 for (idx
=1; idx
< count
; idx
+= 3) {
369 const uint8_t *inhdr
= NULL
;
372 if (req
->in
.vector
[idx
].iov_len
!= SMB2_HDR_BODY
) {
373 return NT_STATUS_INVALID_PARAMETER
;
376 if (req
->in
.vector
[idx
+1].iov_len
< 2) {
377 return NT_STATUS_INVALID_PARAMETER
;
380 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
382 /* Check the SMB2 header */
383 if (IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
) != SMB2_MAGIC
) {
384 return NT_STATUS_INVALID_PARAMETER
;
387 if (!smb2_validate_message_id(req
->sconn
, inhdr
)) {
388 return NT_STATUS_INVALID_PARAMETER
;
391 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
394 * the 1st request should never have the
395 * SMB2_HDR_FLAG_CHAINED flag set
397 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
398 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
401 } else if (idx
== 4) {
403 * the 2nd request triggers related vs. unrelated
404 * compounded requests
406 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
407 compound_related
= true;
409 } else if (idx
> 4) {
412 * It seems the this tests are wrong
413 * see the SMB2-COMPOUND test
417 * all other requests should match the 2nd one
419 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
420 if (!compound_related
) {
422 NT_STATUS_INVALID_PARAMETER
;
426 if (compound_related
) {
428 NT_STATUS_INVALID_PARAMETER
;
439 static void smb2_set_operation_credit(struct smbd_server_connection
*sconn
,
440 const struct iovec
*in_vector
,
441 struct iovec
*out_vector
)
443 uint8_t *outhdr
= (uint8_t *)out_vector
->iov_base
;
444 uint16_t credits_requested
= 0;
445 uint16_t credits_granted
= 0;
447 if (in_vector
!= NULL
) {
448 const uint8_t *inhdr
= (const uint8_t *)in_vector
->iov_base
;
449 credits_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
452 SMB_ASSERT(sconn
->smb2
.max_credits
>= sconn
->smb2
.credits_granted
);
454 /* Remember what we gave out. */
455 credits_granted
= MIN(credits_requested
, (sconn
->smb2
.max_credits
-
456 sconn
->smb2
.credits_granted
));
458 if (credits_granted
== 0 && sconn
->smb2
.credits_granted
== 0) {
459 /* First negprot packet, or ensure the client credits can
460 never drop to zero. */
464 SSVAL(outhdr
, SMB2_HDR_CREDIT
, credits_granted
);
465 sconn
->smb2
.credits_granted
+= credits_granted
;
467 DEBUG(10,("smb2_set_operation_credit: requested %u, "
468 "granted %u, total granted %u\n",
469 (unsigned int)credits_requested
,
470 (unsigned int)credits_granted
,
471 (unsigned int)sconn
->smb2
.credits_granted
));
474 static void smb2_calculate_credits(const struct smbd_smb2_request
*inreq
,
475 struct smbd_smb2_request
*outreq
)
479 count
= outreq
->out
.vector_count
;
481 for (idx
=1; idx
< count
; idx
+= 3) {
482 smb2_set_operation_credit(outreq
->sconn
,
483 &inreq
->in
.vector
[idx
],
484 &outreq
->out
.vector
[idx
]);
488 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
)
490 struct iovec
*vector
;
494 count
= req
->in
.vector_count
;
495 vector
= talloc_zero_array(req
, struct iovec
, count
);
496 if (vector
== NULL
) {
497 return NT_STATUS_NO_MEMORY
;
500 vector
[0].iov_base
= req
->out
.nbt_hdr
;
501 vector
[0].iov_len
= 4;
502 SIVAL(req
->out
.nbt_hdr
, 0, 0);
504 for (idx
=1; idx
< count
; idx
+= 3) {
505 const uint8_t *inhdr
= NULL
;
507 uint8_t *outhdr
= NULL
;
508 uint8_t *outbody
= NULL
;
509 uint32_t next_command_ofs
= 0;
510 struct iovec
*current
= &vector
[idx
];
512 if ((idx
+ 3) < count
) {
513 /* we have a next command -
514 * setup for the error case. */
515 next_command_ofs
= SMB2_HDR_BODY
+ 9;
518 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
519 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
521 outhdr
= talloc_zero_array(vector
, uint8_t,
523 if (outhdr
== NULL
) {
524 return NT_STATUS_NO_MEMORY
;
527 outbody
= outhdr
+ SMB2_HDR_BODY
;
529 current
[0].iov_base
= (void *)outhdr
;
530 current
[0].iov_len
= SMB2_HDR_BODY
;
532 current
[1].iov_base
= (void *)outbody
;
533 current
[1].iov_len
= 8;
535 current
[2].iov_base
= NULL
;
536 current
[2].iov_len
= 0;
538 /* setup the SMB2 header */
539 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
540 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
541 SSVAL(outhdr
, SMB2_HDR_EPOCH
, 0);
542 SIVAL(outhdr
, SMB2_HDR_STATUS
,
543 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
544 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
545 SVAL(inhdr
, SMB2_HDR_OPCODE
));
546 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
547 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
548 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
549 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
550 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
551 SIVAL(outhdr
, SMB2_HDR_PID
,
552 IVAL(inhdr
, SMB2_HDR_PID
));
553 SIVAL(outhdr
, SMB2_HDR_TID
,
554 IVAL(inhdr
, SMB2_HDR_TID
));
555 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
556 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
557 memset(outhdr
+ SMB2_HDR_SIGNATURE
, 0, 16);
559 /* setup error body header */
560 SSVAL(outbody
, 0x00, 0x08 + 1);
561 SSVAL(outbody
, 0x02, 0);
562 SIVAL(outbody
, 0x04, 0);
565 req
->out
.vector
= vector
;
566 req
->out
.vector_count
= count
;
568 /* setup the length of the NBT packet */
569 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
571 DLIST_ADD_END(req
->sconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
576 void smbd_server_connection_terminate_ex(struct smbd_server_connection
*sconn
,
578 const char *location
)
580 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
582 exit_server_cleanly(reason
);
585 static bool dup_smb2_vec3(TALLOC_CTX
*ctx
,
586 struct iovec
*outvec
,
587 const struct iovec
*srcvec
)
589 /* vec[0] is always boilerplate and must
590 * be allocated with size OUTVEC_ALLOC_SIZE. */
592 outvec
[0].iov_base
= talloc_memdup(ctx
,
595 if (!outvec
[0].iov_base
) {
598 outvec
[0].iov_len
= SMB2_HDR_BODY
;
601 * If this is a "standard" vec[1] of length 8,
602 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
603 * then duplicate this. Else use talloc_memdup().
606 if (srcvec
[1].iov_len
== 8 &&
607 srcvec
[1].iov_base
==
608 ((uint8_t *)srcvec
[0].iov_base
) +
610 outvec
[1].iov_base
= ((uint8_t *)outvec
[1].iov_base
) +
612 outvec
[1].iov_len
= 8;
614 outvec
[1].iov_base
= talloc_memdup(ctx
,
617 if (!outvec
[1].iov_base
) {
620 outvec
[1].iov_len
= srcvec
[1].iov_len
;
624 * If this is a "standard" vec[2] of length 1,
625 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
626 * then duplicate this. Else use talloc_memdup().
629 if (srcvec
[2].iov_base
&&
631 if (srcvec
[2].iov_base
==
632 ((uint8_t *)srcvec
[0].iov_base
) +
633 (OUTVEC_ALLOC_SIZE
- 1) &&
634 srcvec
[2].iov_len
== 1) {
635 /* Common SMB2 error packet case. */
636 outvec
[2].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
637 (OUTVEC_ALLOC_SIZE
- 1);
639 outvec
[2].iov_base
= talloc_memdup(ctx
,
642 if (!outvec
[2].iov_base
) {
646 outvec
[2].iov_len
= srcvec
[2].iov_len
;
648 outvec
[2].iov_base
= NULL
;
649 outvec
[2].iov_len
= 0;
654 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
656 struct smbd_smb2_request
*newreq
= NULL
;
657 struct iovec
*outvec
= NULL
;
658 int count
= req
->out
.vector_count
;
661 newreq
= smbd_smb2_request_allocate(req
->sconn
);
666 newreq
->sconn
= req
->sconn
;
667 newreq
->do_signing
= req
->do_signing
;
668 newreq
->current_idx
= req
->current_idx
;
669 newreq
->async
= false;
670 newreq
->cancelled
= false;
672 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
677 newreq
->out
.vector
= outvec
;
678 newreq
->out
.vector_count
= count
;
680 /* Setup the outvec's identically to req. */
681 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
682 outvec
[0].iov_len
= 4;
683 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
685 /* Setup the vectors identically to the ones in req. */
686 for (i
= 1; i
< count
; i
+= 3) {
687 if (!dup_smb2_vec3(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
698 smb2_setup_nbt_length(newreq
->out
.vector
,
699 newreq
->out
.vector_count
);
704 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
);
706 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
709 uint8_t *outhdr
= NULL
;
710 struct smbd_smb2_request
*nreq
= NULL
;
712 /* Create a new smb2 request we'll use
713 for the interim return. */
714 nreq
= dup_smb2_req(req
);
716 return NT_STATUS_NO_MEMORY
;
719 /* Lose the last 3 out vectors. They're the
720 ones we'll be using for the async reply. */
721 nreq
->out
.vector_count
-= 3;
723 smb2_setup_nbt_length(nreq
->out
.vector
,
724 nreq
->out
.vector_count
);
726 /* Step back to the previous reply. */
727 i
= nreq
->current_idx
- 3;
728 outhdr
= (uint8_t *)nreq
->out
.vector
[i
].iov_base
;
729 /* And end the chain. */
730 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
732 /* Calculate outgoing credits */
733 smb2_calculate_credits(req
, nreq
);
735 /* Re-sign if needed. */
736 if (nreq
->do_signing
) {
738 status
= smb2_signing_sign_pdu(nreq
->session
->session_key
,
739 &nreq
->out
.vector
[i
], 3);
740 if (!NT_STATUS_IS_OK(status
)) {
744 if (DEBUGLEVEL
>= 10) {
745 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
746 (unsigned int)nreq
->current_idx
);
747 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
748 (unsigned int)nreq
->out
.vector_count
);
749 print_req_vectors(nreq
);
751 nreq
->subreq
= tstream_writev_queue_send(nreq
,
752 nreq
->sconn
->smb2
.event_ctx
,
753 nreq
->sconn
->smb2
.stream
,
754 nreq
->sconn
->smb2
.send_queue
,
756 nreq
->out
.vector_count
);
758 if (nreq
->subreq
== NULL
) {
759 return NT_STATUS_NO_MEMORY
;
762 tevent_req_set_callback(nreq
->subreq
,
763 smbd_smb2_request_writev_done
,
769 struct smbd_smb2_request_pending_state
{
770 struct smbd_server_connection
*sconn
;
771 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x08 + 1];
772 struct iovec vector
[3];
775 static void smbd_smb2_request_pending_writev_done(struct tevent_req
*subreq
)
777 struct smbd_smb2_request_pending_state
*state
=
778 tevent_req_callback_data(subreq
,
779 struct smbd_smb2_request_pending_state
);
780 struct smbd_server_connection
*sconn
= state
->sconn
;
784 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
787 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
788 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
795 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
796 struct tevent_req
*subreq
)
799 struct smbd_smb2_request_pending_state
*state
= NULL
;
800 int i
= req
->current_idx
;
801 uint8_t *reqhdr
= NULL
;
803 uint8_t *body
= NULL
;
805 uint64_t message_id
= 0;
806 uint64_t async_id
= 0;
807 struct iovec
*outvec
= NULL
;
809 if (!tevent_req_is_in_progress(subreq
)) {
813 req
->subreq
= subreq
;
817 /* We're already async. */
821 if (req
->in
.vector_count
> i
+ 3) {
823 * We're trying to go async in a compound
824 * request chain. This is not allowed.
825 * Cancel the outstanding request.
827 tevent_req_cancel(req
->subreq
);
828 return smbd_smb2_request_error(req
,
829 NT_STATUS_INSUFFICIENT_RESOURCES
);
832 if (DEBUGLEVEL
>= 10) {
833 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
834 (unsigned int)req
->current_idx
);
835 print_req_vectors(req
);
838 if (req
->out
.vector_count
> 4) {
839 /* This is a compound reply. We
840 * must do an interim response
841 * followed by the async response
844 status
= smb2_send_async_interim_response(req
);
845 if (!NT_STATUS_IS_OK(status
)) {
850 /* Don't return an intermediate packet on a pipe read/write. */
851 if (req
->tcon
&& req
->tcon
->compat_conn
&& IS_IPC(req
->tcon
->compat_conn
)) {
855 reqhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
856 flags
= (IVAL(reqhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
857 message_id
= BVAL(reqhdr
, SMB2_HDR_MESSAGE_ID
);
858 async_id
= message_id
; /* keep it simple for now... */
861 * What we send is identical to a smbd_smb2_request_error
862 * packet with an error status of STATUS_PENDING. Make use
863 * of this fact sometime when refactoring. JRA.
866 state
= talloc_zero(req
->sconn
, struct smbd_smb2_request_pending_state
);
868 return NT_STATUS_NO_MEMORY
;
870 state
->sconn
= req
->sconn
;
872 state
->vector
[0].iov_base
= (void *)state
->buf
;
873 state
->vector
[0].iov_len
= 4;
875 state
->vector
[1].iov_base
= state
->buf
+ 4;
876 state
->vector
[1].iov_len
= SMB2_HDR_BODY
;
878 state
->vector
[2].iov_base
= state
->buf
+ 4 + SMB2_HDR_BODY
;
879 state
->vector
[2].iov_len
= 9;
881 smb2_setup_nbt_length(state
->vector
, 3);
883 hdr
= (uint8_t *)state
->vector
[1].iov_base
;
884 body
= (uint8_t *)state
->vector
[2].iov_base
;
886 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
887 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
888 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
889 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
890 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(reqhdr
, SMB2_HDR_OPCODE
));
892 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
893 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
894 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
895 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
896 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
897 BVAL(reqhdr
, SMB2_HDR_SESSION_ID
));
898 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
900 SSVAL(body
, 0x00, 0x08 + 1);
902 SCVAL(body
, 0x02, 0);
903 SCVAL(body
, 0x03, 0);
904 SIVAL(body
, 0x04, 0);
905 /* Match W2K8R2... */
906 SCVAL(body
, 0x08, 0x21);
908 /* Ensure we correctly go through crediting. Grant
909 the credits now, and zero credits on the final
911 smb2_set_operation_credit(req
->sconn
,
915 if (req
->do_signing
) {
916 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
918 if (!NT_STATUS_IS_OK(status
)) {
923 subreq
= tstream_writev_queue_send(state
,
924 req
->sconn
->smb2
.event_ctx
,
925 req
->sconn
->smb2
.stream
,
926 req
->sconn
->smb2
.send_queue
,
930 if (subreq
== NULL
) {
931 return NT_STATUS_NO_MEMORY
;
934 tevent_req_set_callback(subreq
,
935 smbd_smb2_request_pending_writev_done
,
938 /* Note we're going async with this request. */
942 * Now manipulate req so that the outstanding async request
943 * is the only one left in the struct smbd_smb2_request.
946 if (req
->current_idx
== 1) {
947 /* There was only one. */
951 /* Re-arrange the in.vectors. */
952 req
->in
.vector
[1] = req
->in
.vector
[i
];
953 req
->in
.vector
[2] = req
->in
.vector
[i
+1];
954 req
->in
.vector
[3] = req
->in
.vector
[i
+2];
955 req
->in
.vector_count
= 4;
956 /* Reset the new in size. */
957 smb2_setup_nbt_length(req
->in
.vector
, 4);
959 /* Now recreate the out.vectors. */
960 outvec
= talloc_zero_array(req
, struct iovec
, 4);
962 return NT_STATUS_NO_MEMORY
;
965 /* 0 is always boilerplate and must
966 * be of size 4 for the length field. */
968 outvec
[0].iov_base
= req
->out
.nbt_hdr
;
969 outvec
[0].iov_len
= 4;
970 SIVAL(req
->out
.nbt_hdr
, 0, 0);
972 if (!dup_smb2_vec3(outvec
, &outvec
[1], &req
->out
.vector
[i
])) {
973 return NT_STATUS_NO_MEMORY
;
976 TALLOC_FREE(req
->out
.vector
);
978 req
->out
.vector
= outvec
;
980 req
->current_idx
= 1;
981 req
->out
.vector_count
= 4;
985 smb2_setup_nbt_length(req
->out
.vector
,
986 req
->out
.vector_count
);
988 /* Ensure our final reply matches the interim one. */
989 reqhdr
= (uint8_t *)req
->out
.vector
[1].iov_base
;
990 SIVAL(reqhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
991 SBVAL(reqhdr
, SMB2_HDR_PID
, async_id
);
994 const uint8_t *inhdr
=
995 (const uint8_t *)req
->in
.vector
[1].iov_base
;
996 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
998 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
999 (unsigned long long)async_id
));
1001 return NT_STATUS_OK
;
1004 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
1006 struct smbd_server_connection
*sconn
= req
->sconn
;
1007 struct smbd_smb2_request
*cur
;
1008 const uint8_t *inhdr
;
1009 int i
= req
->current_idx
;
1011 uint64_t search_message_id
;
1012 uint64_t search_async_id
;
1015 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1017 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1018 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1019 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
1022 * we don't need the request anymore
1023 * cancel requests never have a response
1025 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1028 for (cur
= sconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
1029 const uint8_t *outhdr
;
1030 uint64_t message_id
;
1033 i
= cur
->current_idx
;
1035 outhdr
= (const uint8_t *)cur
->out
.vector
[i
].iov_base
;
1037 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1038 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
1040 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1041 if (search_async_id
== async_id
) {
1042 found_id
= async_id
;
1046 if (search_message_id
== message_id
) {
1047 found_id
= message_id
;
1053 if (cur
&& cur
->subreq
) {
1054 inhdr
= (const uint8_t *)cur
->in
.vector
[i
].iov_base
;
1055 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1056 "cancel opcode[%s] mid %llu\n",
1057 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1058 (unsigned long long)found_id
));
1059 tevent_req_cancel(cur
->subreq
);
1062 return NT_STATUS_OK
;
1065 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
1067 const uint8_t *inhdr
;
1068 int i
= req
->current_idx
;
1073 NTSTATUS session_status
;
1074 uint32_t allowed_flags
;
1075 NTSTATUS return_value
;
1077 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1079 /* TODO: verify more things */
1081 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1082 opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1083 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1084 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1085 smb2_opcode_name(opcode
),
1086 (unsigned long long)mid
));
1088 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
1089 SMB2_HDR_FLAG_SIGNED
|
1091 if (opcode
== SMB2_OP_CANCEL
) {
1092 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
1094 if ((flags
& ~allowed_flags
) != 0) {
1095 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1098 session_status
= smbd_smb2_request_check_session(req
);
1100 req
->do_signing
= false;
1101 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
1102 if (!NT_STATUS_IS_OK(session_status
)) {
1103 return smbd_smb2_request_error(req
, session_status
);
1106 req
->do_signing
= true;
1107 status
= smb2_signing_check_pdu(req
->session
->session_key
,
1108 &req
->in
.vector
[i
], 3);
1109 if (!NT_STATUS_IS_OK(status
)) {
1110 return smbd_smb2_request_error(req
, status
);
1112 } else if (req
->session
&& req
->session
->do_signing
) {
1113 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
1116 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
1118 * This check is mostly for giving the correct error code
1119 * for compounded requests.
1121 * TODO: we may need to move this after the session
1124 if (!NT_STATUS_IS_OK(req
->next_status
)) {
1125 return smbd_smb2_request_error(req
, req
->next_status
);
1128 req
->compat_chain_fsp
= NULL
;
1132 case SMB2_OP_NEGPROT
:
1134 START_PROFILE(smb2_negprot
);
1135 return_value
= smbd_smb2_request_process_negprot(req
);
1136 END_PROFILE(smb2_negprot
);
1140 case SMB2_OP_SESSSETUP
:
1142 START_PROFILE(smb2_sesssetup
);
1143 return_value
= smbd_smb2_request_process_sesssetup(req
);
1144 END_PROFILE(smb2_sesssetup
);
1148 case SMB2_OP_LOGOFF
:
1149 if (!NT_STATUS_IS_OK(session_status
)) {
1150 return_value
= smbd_smb2_request_error(req
, session_status
);
1155 START_PROFILE(smb2_logoff
);
1156 return_value
= smbd_smb2_request_process_logoff(req
);
1157 END_PROFILE(smb2_logoff
);
1162 if (!NT_STATUS_IS_OK(session_status
)) {
1163 return_value
= smbd_smb2_request_error(req
, session_status
);
1166 status
= smbd_smb2_request_check_session(req
);
1167 if (!NT_STATUS_IS_OK(status
)) {
1168 return_value
= smbd_smb2_request_error(req
, status
);
1173 START_PROFILE(smb2_tcon
);
1174 return_value
= smbd_smb2_request_process_tcon(req
);
1175 END_PROFILE(smb2_tcon
);
1180 if (!NT_STATUS_IS_OK(session_status
)) {
1181 return_value
= smbd_smb2_request_error(req
, session_status
);
1184 status
= smbd_smb2_request_check_tcon(req
);
1185 if (!NT_STATUS_IS_OK(status
)) {
1186 return_value
= smbd_smb2_request_error(req
, status
);
1191 START_PROFILE(smb2_tdis
);
1192 return_value
= smbd_smb2_request_process_tdis(req
);
1193 END_PROFILE(smb2_tdis
);
1197 case SMB2_OP_CREATE
:
1198 if (!NT_STATUS_IS_OK(session_status
)) {
1199 return_value
= smbd_smb2_request_error(req
, session_status
);
1202 status
= smbd_smb2_request_check_tcon(req
);
1203 if (!NT_STATUS_IS_OK(status
)) {
1204 return_value
= smbd_smb2_request_error(req
, status
);
1209 START_PROFILE(smb2_create
);
1210 return_value
= smbd_smb2_request_process_create(req
);
1211 END_PROFILE(smb2_create
);
1216 if (!NT_STATUS_IS_OK(session_status
)) {
1217 return_value
= smbd_smb2_request_error(req
, session_status
);
1220 status
= smbd_smb2_request_check_tcon(req
);
1221 if (!NT_STATUS_IS_OK(status
)) {
1222 return_value
= smbd_smb2_request_error(req
, status
);
1227 START_PROFILE(smb2_close
);
1228 return_value
= smbd_smb2_request_process_close(req
);
1229 END_PROFILE(smb2_close
);
1234 if (!NT_STATUS_IS_OK(session_status
)) {
1235 return_value
= smbd_smb2_request_error(req
, session_status
);
1238 status
= smbd_smb2_request_check_tcon(req
);
1239 if (!NT_STATUS_IS_OK(status
)) {
1240 return_value
= smbd_smb2_request_error(req
, status
);
1245 START_PROFILE(smb2_flush
);
1246 return_value
= smbd_smb2_request_process_flush(req
);
1247 END_PROFILE(smb2_flush
);
1252 if (!NT_STATUS_IS_OK(session_status
)) {
1253 return_value
= smbd_smb2_request_error(req
, session_status
);
1256 status
= smbd_smb2_request_check_tcon(req
);
1257 if (!NT_STATUS_IS_OK(status
)) {
1258 return_value
= smbd_smb2_request_error(req
, status
);
1263 START_PROFILE(smb2_read
);
1264 return_value
= smbd_smb2_request_process_read(req
);
1265 END_PROFILE(smb2_read
);
1270 if (!NT_STATUS_IS_OK(session_status
)) {
1271 return_value
= smbd_smb2_request_error(req
, session_status
);
1274 status
= smbd_smb2_request_check_tcon(req
);
1275 if (!NT_STATUS_IS_OK(status
)) {
1276 return_value
= smbd_smb2_request_error(req
, status
);
1281 START_PROFILE(smb2_write
);
1282 return_value
= smbd_smb2_request_process_write(req
);
1283 END_PROFILE(smb2_write
);
1288 if (!NT_STATUS_IS_OK(session_status
)) {
1289 /* Too ugly to live ? JRA. */
1290 if (NT_STATUS_EQUAL(session_status
,NT_STATUS_USER_SESSION_DELETED
)) {
1291 session_status
= NT_STATUS_FILE_CLOSED
;
1293 return_value
= smbd_smb2_request_error(req
, session_status
);
1296 status
= smbd_smb2_request_check_tcon(req
);
1297 if (!NT_STATUS_IS_OK(status
)) {
1298 /* Too ugly to live ? JRA. */
1299 if (NT_STATUS_EQUAL(status
,NT_STATUS_NETWORK_NAME_DELETED
)) {
1300 status
= NT_STATUS_FILE_CLOSED
;
1302 return_value
= smbd_smb2_request_error(req
, status
);
1307 START_PROFILE(smb2_lock
);
1308 return_value
= smbd_smb2_request_process_lock(req
);
1309 END_PROFILE(smb2_lock
);
1314 if (!NT_STATUS_IS_OK(session_status
)) {
1315 return_value
= smbd_smb2_request_error(req
, session_status
);
1318 status
= smbd_smb2_request_check_tcon(req
);
1319 if (!NT_STATUS_IS_OK(status
)) {
1320 return_value
= smbd_smb2_request_error(req
, status
);
1325 START_PROFILE(smb2_ioctl
);
1326 return_value
= smbd_smb2_request_process_ioctl(req
);
1327 END_PROFILE(smb2_ioctl
);
1331 case SMB2_OP_CANCEL
:
1333 START_PROFILE(smb2_cancel
);
1334 return_value
= smbd_smb2_request_process_cancel(req
);
1335 END_PROFILE(smb2_cancel
);
1339 case SMB2_OP_KEEPALIVE
:
1340 {START_PROFILE(smb2_keepalive
);
1341 return_value
= smbd_smb2_request_process_keepalive(req
);
1342 END_PROFILE(smb2_keepalive
);}
1346 if (!NT_STATUS_IS_OK(session_status
)) {
1347 return_value
= smbd_smb2_request_error(req
, session_status
);
1350 status
= smbd_smb2_request_check_tcon(req
);
1351 if (!NT_STATUS_IS_OK(status
)) {
1352 return_value
= smbd_smb2_request_error(req
, status
);
1357 START_PROFILE(smb2_find
);
1358 return_value
= smbd_smb2_request_process_find(req
);
1359 END_PROFILE(smb2_find
);
1363 case SMB2_OP_NOTIFY
:
1364 if (!NT_STATUS_IS_OK(session_status
)) {
1365 return_value
= smbd_smb2_request_error(req
, session_status
);
1368 status
= smbd_smb2_request_check_tcon(req
);
1369 if (!NT_STATUS_IS_OK(status
)) {
1370 return_value
= smbd_smb2_request_error(req
, status
);
1375 START_PROFILE(smb2_notify
);
1376 return_value
= smbd_smb2_request_process_notify(req
);
1377 END_PROFILE(smb2_notify
);
1381 case SMB2_OP_GETINFO
:
1382 if (!NT_STATUS_IS_OK(session_status
)) {
1383 return_value
= smbd_smb2_request_error(req
, session_status
);
1386 status
= smbd_smb2_request_check_tcon(req
);
1387 if (!NT_STATUS_IS_OK(status
)) {
1388 return_value
= smbd_smb2_request_error(req
, status
);
1393 START_PROFILE(smb2_getinfo
);
1394 return_value
= smbd_smb2_request_process_getinfo(req
);
1395 END_PROFILE(smb2_getinfo
);
1399 case SMB2_OP_SETINFO
:
1400 if (!NT_STATUS_IS_OK(session_status
)) {
1401 return_value
= smbd_smb2_request_error(req
, session_status
);
1404 status
= smbd_smb2_request_check_tcon(req
);
1405 if (!NT_STATUS_IS_OK(status
)) {
1406 return_value
= smbd_smb2_request_error(req
, status
);
1411 START_PROFILE(smb2_setinfo
);
1412 return_value
= smbd_smb2_request_process_setinfo(req
);
1413 END_PROFILE(smb2_setinfo
);
1418 if (!NT_STATUS_IS_OK(session_status
)) {
1419 return_value
= smbd_smb2_request_error(req
, session_status
);
1422 status
= smbd_smb2_request_check_tcon(req
);
1423 if (!NT_STATUS_IS_OK(status
)) {
1424 return_value
= smbd_smb2_request_error(req
, status
);
1429 START_PROFILE(smb2_break
);
1430 return_value
= smbd_smb2_request_process_break(req
);
1431 END_PROFILE(smb2_break
);
1436 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1439 return return_value
;
1442 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
1444 struct tevent_req
*subreq
;
1445 int i
= req
->current_idx
;
1449 req
->current_idx
+= 3;
1451 if (req
->current_idx
< req
->out
.vector_count
) {
1453 * We must process the remaining compound
1454 * SMB2 requests before any new incoming SMB2
1455 * requests. This is because incoming SMB2
1456 * requests may include a cancel for a
1457 * compound request we haven't processed
1460 struct tevent_immediate
*im
= tevent_create_immediate(req
);
1462 return NT_STATUS_NO_MEMORY
;
1464 tevent_schedule_immediate(im
,
1465 req
->sconn
->smb2
.event_ctx
,
1466 smbd_smb2_request_dispatch_immediate
,
1468 return NT_STATUS_OK
;
1471 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
1473 /* Set credit for this operation (zero credits if this
1474 is a final reply for an async operation). */
1475 smb2_set_operation_credit(req
->sconn
,
1476 req
->async
? NULL
: &req
->in
.vector
[i
],
1477 &req
->out
.vector
[i
]);
1479 if (req
->do_signing
) {
1481 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
1482 &req
->out
.vector
[i
], 3);
1483 if (!NT_STATUS_IS_OK(status
)) {
1488 if (DEBUGLEVEL
>= 10) {
1489 dbgtext("smbd_smb2_request_reply: sending...\n");
1490 print_req_vectors(req
);
1493 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1494 if (req
->out
.vector_count
== 4 &&
1495 req
->out
.vector
[3].iov_base
== NULL
&&
1496 req
->out
.vector
[3].iov_len
!= 0) {
1497 /* Dynamic part is NULL. Chop it off,
1498 We're going to send it via sendfile. */
1499 req
->out
.vector_count
-= 1;
1502 subreq
= tstream_writev_queue_send(req
,
1503 req
->sconn
->smb2
.event_ctx
,
1504 req
->sconn
->smb2
.stream
,
1505 req
->sconn
->smb2
.send_queue
,
1507 req
->out
.vector_count
);
1508 if (subreq
== NULL
) {
1509 return NT_STATUS_NO_MEMORY
;
1511 tevent_req_set_callback(subreq
, smbd_smb2_request_writev_done
, req
);
1513 * We're done with this request -
1514 * move it off the "being processed" queue.
1516 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1518 return NT_STATUS_OK
;
1521 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
1522 struct tevent_immediate
*im
,
1525 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
1526 struct smbd_smb2_request
);
1527 struct smbd_server_connection
*sconn
= req
->sconn
;
1532 if (DEBUGLEVEL
>= 10) {
1533 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1534 req
->current_idx
, req
->in
.vector_count
));
1535 print_req_vectors(req
);
1538 status
= smbd_smb2_request_dispatch(req
);
1539 if (!NT_STATUS_IS_OK(status
)) {
1540 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1545 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
)
1547 struct smbd_smb2_request
*req
= tevent_req_callback_data(subreq
,
1548 struct smbd_smb2_request
);
1549 struct smbd_server_connection
*sconn
= req
->sconn
;
1553 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1554 TALLOC_FREE(subreq
);
1557 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
1558 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1559 nt_errstr(status
)));
1560 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1565 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
1567 DATA_BLOB body
, DATA_BLOB
*dyn
,
1568 const char *location
)
1571 int i
= req
->current_idx
;
1572 uint32_t next_command_ofs
;
1574 DEBUG(10,("smbd_smb2_request_done_ex: "
1575 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1576 i
, nt_errstr(status
), (unsigned int)body
.length
,
1578 (unsigned int)(dyn
? dyn
->length
: 0),
1581 if (body
.length
< 2) {
1582 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
1585 if ((body
.length
% 2) != 0) {
1586 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
1589 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
1591 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
1592 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
1594 req
->out
.vector
[i
+1].iov_base
= (void *)body
.data
;
1595 req
->out
.vector
[i
+1].iov_len
= body
.length
;
1598 req
->out
.vector
[i
+2].iov_base
= (void *)dyn
->data
;
1599 req
->out
.vector
[i
+2].iov_len
= dyn
->length
;
1601 req
->out
.vector
[i
+2].iov_base
= NULL
;
1602 req
->out
.vector
[i
+2].iov_len
= 0;
1605 /* see if we need to recalculate the offset to the next response */
1606 if (next_command_ofs
> 0) {
1607 next_command_ofs
= SMB2_HDR_BODY
;
1608 next_command_ofs
+= req
->out
.vector
[i
+1].iov_len
;
1609 next_command_ofs
+= req
->out
.vector
[i
+2].iov_len
;
1612 if ((next_command_ofs
% 8) != 0) {
1613 size_t pad_size
= 8 - (next_command_ofs
% 8);
1614 if (req
->out
.vector
[i
+2].iov_len
== 0) {
1616 * if the dyn buffer is empty
1617 * we can use it to add padding
1621 pad
= talloc_zero_array(req
->out
.vector
,
1624 return smbd_smb2_request_error(req
,
1625 NT_STATUS_NO_MEMORY
);
1628 req
->out
.vector
[i
+2].iov_base
= (void *)pad
;
1629 req
->out
.vector
[i
+2].iov_len
= pad_size
;
1632 * For now we copy the dynamic buffer
1633 * and add the padding to the new buffer
1640 old_size
= req
->out
.vector
[i
+2].iov_len
;
1641 old_dyn
= (uint8_t *)req
->out
.vector
[i
+2].iov_base
;
1643 new_size
= old_size
+ pad_size
;
1644 new_dyn
= talloc_zero_array(req
->out
.vector
,
1646 if (new_dyn
== NULL
) {
1647 return smbd_smb2_request_error(req
,
1648 NT_STATUS_NO_MEMORY
);
1651 memcpy(new_dyn
, old_dyn
, old_size
);
1652 memset(new_dyn
+ old_size
, 0, pad_size
);
1654 req
->out
.vector
[i
+2].iov_base
= (void *)new_dyn
;
1655 req
->out
.vector
[i
+2].iov_len
= new_size
;
1657 next_command_ofs
+= pad_size
;
1660 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
1662 return smbd_smb2_request_reply(req
);
1665 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
1668 const char *location
)
1671 int i
= req
->current_idx
;
1672 uint8_t *outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
1674 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1675 i
, nt_errstr(status
), info
? " +info" : "",
1678 body
.data
= outhdr
+ SMB2_HDR_BODY
;
1680 SSVAL(body
.data
, 0, 9);
1683 SIVAL(body
.data
, 0x04, info
->length
);
1685 /* Allocated size of req->out.vector[i].iov_base
1686 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
1687 * 1 byte without having to do an alloc.
1689 info
= talloc_zero_array(req
->out
.vector
,
1693 return NT_STATUS_NO_MEMORY
;
1695 info
->data
= ((uint8_t *)outhdr
) +
1696 OUTVEC_ALLOC_SIZE
- 1;
1698 SCVAL(info
->data
, 0, 0);
1702 * if a request fails, all other remaining
1703 * compounded requests should fail too
1705 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
1707 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
1711 struct smbd_smb2_send_oplock_break_state
{
1712 struct smbd_server_connection
*sconn
;
1713 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x18];
1714 struct iovec vector
;
1717 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
);
1719 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
1720 uint64_t file_id_persistent
,
1721 uint64_t file_id_volatile
,
1722 uint8_t oplock_level
)
1724 struct smbd_smb2_send_oplock_break_state
*state
;
1725 struct tevent_req
*subreq
;
1729 state
= talloc(sconn
, struct smbd_smb2_send_oplock_break_state
);
1730 if (state
== NULL
) {
1731 return NT_STATUS_NO_MEMORY
;
1733 state
->sconn
= sconn
;
1735 state
->vector
.iov_base
= (void *)state
->buf
;
1736 state
->vector
.iov_len
= sizeof(state
->buf
);
1738 _smb2_setlen(state
->buf
, sizeof(state
->buf
) - 4);
1739 hdr
= state
->buf
+ 4;
1740 body
= hdr
+ SMB2_HDR_BODY
;
1742 SIVAL(hdr
, 0, SMB2_MAGIC
);
1743 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1744 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1745 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
1746 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
1747 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
1748 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
1749 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1750 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
1751 SIVAL(hdr
, SMB2_HDR_PID
, 0);
1752 SIVAL(hdr
, SMB2_HDR_TID
, 0);
1753 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
1754 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
1756 SSVAL(body
, 0x00, 0x18);
1758 SCVAL(body
, 0x02, oplock_level
);
1759 SCVAL(body
, 0x03, 0); /* reserved */
1760 SIVAL(body
, 0x04, 0); /* reserved */
1761 SBVAL(body
, 0x08, file_id_persistent
);
1762 SBVAL(body
, 0x10, file_id_volatile
);
1764 subreq
= tstream_writev_queue_send(state
,
1765 sconn
->smb2
.event_ctx
,
1767 sconn
->smb2
.send_queue
,
1769 if (subreq
== NULL
) {
1770 return NT_STATUS_NO_MEMORY
;
1772 tevent_req_set_callback(subreq
,
1773 smbd_smb2_oplock_break_writev_done
,
1776 return NT_STATUS_OK
;
1779 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
)
1781 struct smbd_smb2_send_oplock_break_state
*state
=
1782 tevent_req_callback_data(subreq
,
1783 struct smbd_smb2_send_oplock_break_state
);
1784 struct smbd_server_connection
*sconn
= state
->sconn
;
1788 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1789 TALLOC_FREE(subreq
);
1791 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
1792 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1799 struct smbd_smb2_request_read_state
{
1801 bool asked_for_header
;
1802 struct smbd_smb2_request
*smb2_req
;
1805 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
1807 TALLOC_CTX
*mem_ctx
,
1808 struct iovec
**_vector
,
1810 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
);
1812 static struct tevent_req
*smbd_smb2_request_read_send(TALLOC_CTX
*mem_ctx
,
1813 struct tevent_context
*ev
,
1814 struct smbd_server_connection
*sconn
)
1816 struct tevent_req
*req
;
1817 struct smbd_smb2_request_read_state
*state
;
1818 struct tevent_req
*subreq
;
1820 req
= tevent_req_create(mem_ctx
, &state
,
1821 struct smbd_smb2_request_read_state
);
1826 state
->asked_for_header
= false;
1828 state
->smb2_req
= smbd_smb2_request_allocate(state
);
1829 if (tevent_req_nomem(state
->smb2_req
, req
)) {
1830 return tevent_req_post(req
, ev
);
1832 state
->smb2_req
->sconn
= sconn
;
1834 subreq
= tstream_readv_pdu_queue_send(state
, ev
, sconn
->smb2
.stream
,
1835 sconn
->smb2
.recv_queue
,
1836 smbd_smb2_request_next_vector
,
1838 if (tevent_req_nomem(subreq
, req
)) {
1839 return tevent_req_post(req
, ev
);
1841 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
1846 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
1848 TALLOC_CTX
*mem_ctx
,
1849 struct iovec
**_vector
,
1852 struct smbd_smb2_request_read_state
*state
=
1853 talloc_get_type_abort(private_data
,
1854 struct smbd_smb2_request_read_state
);
1855 struct smbd_smb2_request
*req
= state
->smb2_req
;
1856 struct iovec
*vector
;
1857 int idx
= req
->in
.vector_count
;
1859 uint8_t *buf
= NULL
;
1861 if (req
->in
.vector_count
== 0) {
1863 * first we need to get the NBT header
1865 req
->in
.vector
= talloc_array(req
, struct iovec
,
1866 req
->in
.vector_count
+ 1);
1867 if (req
->in
.vector
== NULL
) {
1870 req
->in
.vector_count
+= 1;
1872 req
->in
.vector
[idx
].iov_base
= (void *)req
->in
.nbt_hdr
;
1873 req
->in
.vector
[idx
].iov_len
= 4;
1875 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
1876 if (vector
== NULL
) {
1880 vector
[0] = req
->in
.vector
[idx
];
1887 if (req
->in
.vector_count
== 1) {
1889 * Now we analyze the NBT header
1891 state
->missing
= smb2_len(req
->in
.vector
[0].iov_base
);
1893 if (state
->missing
== 0) {
1894 /* if there're no remaining bytes, we're done */
1900 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
1902 req
->in
.vector_count
+ 1);
1903 if (req
->in
.vector
== NULL
) {
1906 req
->in
.vector_count
+= 1;
1908 if (CVAL(req
->in
.vector
[0].iov_base
, 0) != 0) {
1910 * it's a special NBT message,
1911 * so get all remaining bytes
1913 len
= state
->missing
;
1914 } else if (state
->missing
< (SMB2_HDR_BODY
+ 2)) {
1916 * it's an invalid message, just read what we can get
1917 * and let the caller handle the error
1919 len
= state
->missing
;
1922 * We assume it's a SMB2 request,
1923 * and we first get the header and the
1924 * first 2 bytes (the struct size) of the body
1926 len
= SMB2_HDR_BODY
+ 2;
1928 state
->asked_for_header
= true;
1931 state
->missing
-= len
;
1933 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
1938 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
1939 req
->in
.vector
[idx
].iov_len
= len
;
1941 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
1942 if (vector
== NULL
) {
1946 vector
[0] = req
->in
.vector
[idx
];
1953 if (state
->missing
== 0) {
1954 /* if there're no remaining bytes, we're done */
1960 if (state
->asked_for_header
) {
1963 size_t next_command_ofs
;
1968 bool invalid
= false;
1970 state
->asked_for_header
= false;
1973 * We got the SMB2 header and the first 2 bytes
1974 * of the body. We fix the size to just the header
1975 * and manually copy the 2 first bytes to the body section
1977 req
->in
.vector
[idx
-1].iov_len
= SMB2_HDR_BODY
;
1978 hdr
= (const uint8_t *)req
->in
.vector
[idx
-1].iov_base
;
1980 /* allocate vectors for body and dynamic areas */
1981 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
1983 req
->in
.vector_count
+ 2);
1984 if (req
->in
.vector
== NULL
) {
1987 req
->in
.vector_count
+= 2;
1989 full_size
= state
->missing
+ SMB2_HDR_BODY
+ 2;
1990 next_command_ofs
= IVAL(hdr
, SMB2_HDR_NEXT_COMMAND
);
1991 body_size
= SVAL(hdr
, SMB2_HDR_BODY
);
1993 if (next_command_ofs
!= 0) {
1994 if (next_command_ofs
< (SMB2_HDR_BODY
+ 2)) {
1996 * this is invalid, just return a zero
1997 * body and let the caller deal with the error
2000 } else if (next_command_ofs
> full_size
) {
2002 * this is invalid, just return a zero
2003 * body and let the caller deal with the error
2007 full_size
= next_command_ofs
;
2012 if (body_size
< 2) {
2014 * this is invalid, just return a zero
2015 * body and let the caller deal with the error
2020 if ((body_size
% 2) != 0) {
2024 if (body_size
> (full_size
- SMB2_HDR_BODY
)) {
2026 * this is invalid, just return a zero
2027 * body and let the caller deal with the error
2034 /* the caller should check this */
2038 dyn_size
= full_size
- (SMB2_HDR_BODY
+ body_size
);
2040 state
->missing
-= (body_size
- 2) + dyn_size
;
2042 body
= talloc_array(req
->in
.vector
, uint8_t, body_size
);
2047 dyn
= talloc_array(req
->in
.vector
, uint8_t, dyn_size
);
2052 req
->in
.vector
[idx
].iov_base
= (void *)body
;
2053 req
->in
.vector
[idx
].iov_len
= body_size
;
2054 req
->in
.vector
[idx
+1].iov_base
= (void *)dyn
;
2055 req
->in
.vector
[idx
+1].iov_len
= dyn_size
;
2057 vector
= talloc_array(mem_ctx
, struct iovec
, 2);
2058 if (vector
== NULL
) {
2063 * the first 2 bytes of the body were already fetched
2064 * together with the header
2066 memcpy(body
, hdr
+ SMB2_HDR_BODY
, 2);
2067 vector
[0].iov_base
= body
+ 2;
2068 vector
[0].iov_len
= body_size
- 2;
2070 vector
[1] = req
->in
.vector
[idx
+1];
2078 * when we endup here, we're looking for a new SMB2 request
2079 * next. And we ask for its header and the first 2 bytes of
2080 * the body (like we did for the first SMB2 request).
2083 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2085 req
->in
.vector_count
+ 1);
2086 if (req
->in
.vector
== NULL
) {
2089 req
->in
.vector_count
+= 1;
2092 * We assume it's a SMB2 request,
2093 * and we first get the header and the
2094 * first 2 bytes (the struct size) of the body
2096 len
= SMB2_HDR_BODY
+ 2;
2098 if (len
> state
->missing
) {
2099 /* let the caller handle the error */
2100 len
= state
->missing
;
2103 state
->missing
-= len
;
2104 state
->asked_for_header
= true;
2106 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2111 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2112 req
->in
.vector
[idx
].iov_len
= len
;
2114 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2115 if (vector
== NULL
) {
2119 vector
[0] = req
->in
.vector
[idx
];
2126 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
)
2128 struct tevent_req
*req
=
2129 tevent_req_callback_data(subreq
,
2135 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
2137 status
= map_nt_error_from_unix(sys_errno
);
2138 tevent_req_nterror(req
, status
);
2142 tevent_req_done(req
);
2145 static NTSTATUS
smbd_smb2_request_read_recv(struct tevent_req
*req
,
2146 TALLOC_CTX
*mem_ctx
,
2147 struct smbd_smb2_request
**_smb2_req
)
2149 struct smbd_smb2_request_read_state
*state
=
2150 tevent_req_data(req
,
2151 struct smbd_smb2_request_read_state
);
2154 if (tevent_req_is_nterror(req
, &status
)) {
2155 tevent_req_received(req
);
2159 talloc_steal(mem_ctx
, state
->smb2_req
->mem_pool
);
2160 *_smb2_req
= state
->smb2_req
;
2161 tevent_req_received(req
);
2162 return NT_STATUS_OK
;
2165 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
);
2167 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
2168 const uint8_t *inbuf
, size_t size
)
2171 struct smbd_smb2_request
*req
= NULL
;
2172 struct tevent_req
*subreq
;
2174 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2175 (unsigned int)size
));
2177 status
= smbd_initialize_smb2(sconn
);
2178 if (!NT_STATUS_IS_OK(status
)) {
2179 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2183 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
2184 if (!NT_STATUS_IS_OK(status
)) {
2185 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2189 status
= smbd_smb2_request_setup_out(req
);
2190 if (!NT_STATUS_IS_OK(status
)) {
2191 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2195 status
= smbd_smb2_request_dispatch(req
);
2196 if (!NT_STATUS_IS_OK(status
)) {
2197 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2201 /* ask for the next request */
2202 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->smb2
.event_ctx
, sconn
);
2203 if (subreq
== NULL
) {
2204 smbd_server_connection_terminate(sconn
, "no memory for reading");
2207 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);
2210 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
)
2212 struct smbd_server_connection
*sconn
= tevent_req_callback_data(subreq
,
2213 struct smbd_server_connection
);
2215 struct smbd_smb2_request
*req
= NULL
;
2217 status
= smbd_smb2_request_read_recv(subreq
, sconn
, &req
);
2218 TALLOC_FREE(subreq
);
2219 if (!NT_STATUS_IS_OK(status
)) {
2220 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2221 nt_errstr(status
)));
2222 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2226 if (req
->in
.nbt_hdr
[0] != 0x00) {
2227 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2228 req
->in
.nbt_hdr
[0]));
2233 req
->current_idx
= 1;
2235 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2236 req
->current_idx
, req
->in
.vector_count
));
2238 status
= smbd_smb2_request_validate(req
);
2239 if (!NT_STATUS_IS_OK(status
)) {
2240 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2244 status
= smbd_smb2_request_setup_out(req
);
2245 if (!NT_STATUS_IS_OK(status
)) {
2246 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2250 status
= smbd_smb2_request_dispatch(req
);
2251 if (!NT_STATUS_IS_OK(status
)) {
2252 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2257 /* ask for the next request (this constructs the main loop) */
2258 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->smb2
.event_ctx
, sconn
);
2259 if (subreq
== NULL
) {
2260 smbd_server_connection_terminate(sconn
, "no memory for reading");
2263 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);