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"
29 #include "../lib/util/bitmap.h"
30 #include "../librpc/gen_ndr/krb5pac.h"
33 #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9)
35 static const char *smb2_names
[] = {
57 const char *smb2_opcode_name(uint16_t opcode
)
60 return "Bad SMB2 opcode";
62 return smb2_names
[opcode
];
65 static void print_req_vectors(struct smbd_smb2_request
*req
)
69 for (i
= 0; i
< req
->in
.vector_count
; i
++) {
70 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
72 (unsigned int)req
->in
.vector
[i
].iov_len
);
74 for (i
= 0; i
< req
->out
.vector_count
; i
++) {
75 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
77 (unsigned int)req
->out
.vector
[i
].iov_len
);
81 bool smbd_is_smb2_header(const uint8_t *inbuf
, size_t size
)
83 if (size
< (4 + SMB2_HDR_BODY
)) {
87 if (IVAL(inbuf
, 4) != SMB2_MAGIC
) {
94 static NTSTATUS
smbd_initialize_smb2(struct smbd_server_connection
*sconn
)
99 TALLOC_FREE(sconn
->smb1
.fde
);
101 sconn
->smb2
.recv_queue
= tevent_queue_create(sconn
, "smb2 recv queue");
102 if (sconn
->smb2
.recv_queue
== NULL
) {
103 return NT_STATUS_NO_MEMORY
;
106 sconn
->smb2
.send_queue
= tevent_queue_create(sconn
, "smb2 send queue");
107 if (sconn
->smb2
.send_queue
== NULL
) {
108 return NT_STATUS_NO_MEMORY
;
111 sconn
->smb2
.sessions
.idtree
= idr_init(sconn
);
112 if (sconn
->smb2
.sessions
.idtree
== NULL
) {
113 return NT_STATUS_NO_MEMORY
;
115 sconn
->smb2
.sessions
.limit
= 0x0000FFFE;
116 sconn
->smb2
.sessions
.list
= NULL
;
117 sconn
->smb2
.seqnum_low
= 0;
118 sconn
->smb2
.credits_granted
= 0;
119 sconn
->smb2
.max_credits
= lp_smb2_max_credits();
120 sconn
->smb2
.credits_bitmap
= bitmap_talloc(sconn
,
121 DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
*sconn
->smb2
.max_credits
);
122 if (sconn
->smb2
.credits_bitmap
== NULL
) {
123 return NT_STATUS_NO_MEMORY
;
126 ret
= tstream_bsd_existing_socket(sconn
, sconn
->sock
,
127 &sconn
->smb2
.stream
);
129 status
= map_nt_error_from_unix(errno
);
133 /* Ensure child is set to non-blocking mode */
134 set_blocking(sconn
->sock
, false);
138 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
139 #define _smb2_setlen(_buf,len) do { \
140 uint8_t *buf = (uint8_t *)_buf; \
142 buf[1] = ((len)&0xFF0000)>>16; \
143 buf[2] = ((len)&0xFF00)>>8; \
144 buf[3] = (len)&0xFF; \
147 static void smb2_setup_nbt_length(struct iovec
*vector
, int count
)
152 for (i
=1; i
< count
; i
++) {
153 len
+= vector
[i
].iov_len
;
156 _smb2_setlen(vector
[0].iov_base
, len
);
159 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request
**req
)
162 (*req
)->parent
= NULL
;
163 (*req
)->mem_pool
= NULL
;
169 static int smbd_smb2_request_destructor(struct smbd_smb2_request
*req
)
173 talloc_free(req
->mem_pool
);
179 static struct smbd_smb2_request
*smbd_smb2_request_allocate(TALLOC_CTX
*mem_ctx
)
181 TALLOC_CTX
*mem_pool
;
182 struct smbd_smb2_request
**parent
;
183 struct smbd_smb2_request
*req
;
186 /* Enable this to find subtle valgrind errors. */
187 mem_pool
= talloc_init("smbd_smb2_request_allocate");
189 mem_pool
= talloc_pool(mem_ctx
, 8192);
191 if (mem_pool
== NULL
) {
195 parent
= talloc(mem_pool
, struct smbd_smb2_request
*);
196 if (parent
== NULL
) {
197 talloc_free(mem_pool
);
201 req
= talloc_zero(parent
, struct smbd_smb2_request
);
203 talloc_free(mem_pool
);
207 req
->mem_pool
= mem_pool
;
208 req
->parent
= parent
;
210 req
->last_session_id
= UINT64_MAX
;
211 req
->last_tid
= UINT32_MAX
;
213 talloc_set_destructor(parent
, smbd_smb2_request_parent_destructor
);
214 talloc_set_destructor(req
, smbd_smb2_request_destructor
);
219 static NTSTATUS
smbd_smb2_request_create(struct smbd_server_connection
*sconn
,
220 const uint8_t *inbuf
, size_t size
,
221 struct smbd_smb2_request
**_req
)
223 struct smbd_smb2_request
*req
;
224 uint32_t protocol_version
;
225 const uint8_t *inhdr
= NULL
;
228 uint32_t next_command_ofs
;
230 if (size
< (4 + SMB2_HDR_BODY
+ 2)) {
231 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size
));
232 return NT_STATUS_INVALID_PARAMETER
;
237 protocol_version
= IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
);
238 if (protocol_version
!= SMB2_MAGIC
) {
239 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
241 return NT_STATUS_INVALID_PARAMETER
;
244 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
245 if (cmd
!= SMB2_OP_NEGPROT
) {
246 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
248 return NT_STATUS_INVALID_PARAMETER
;
251 next_command_ofs
= IVAL(inhdr
, SMB2_HDR_NEXT_COMMAND
);
252 if (next_command_ofs
!= 0) {
253 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
255 return NT_STATUS_INVALID_PARAMETER
;
258 req
= smbd_smb2_request_allocate(sconn
);
260 return NT_STATUS_NO_MEMORY
;
264 talloc_steal(req
, inbuf
);
266 req
->in
.vector
= talloc_array(req
, struct iovec
, 4);
267 if (req
->in
.vector
== NULL
) {
269 return NT_STATUS_NO_MEMORY
;
271 req
->in
.vector_count
= 4;
273 memcpy(req
->in
.nbt_hdr
, inbuf
, 4);
276 req
->in
.vector
[0].iov_base
= discard_const_p(void, req
->in
.nbt_hdr
);
277 req
->in
.vector
[0].iov_len
= 4;
278 ofs
+= req
->in
.vector
[0].iov_len
;
280 req
->in
.vector
[1].iov_base
= discard_const_p(void, (inbuf
+ ofs
));
281 req
->in
.vector
[1].iov_len
= SMB2_HDR_BODY
;
282 ofs
+= req
->in
.vector
[1].iov_len
;
284 req
->in
.vector
[2].iov_base
= discard_const_p(void, (inbuf
+ ofs
));
285 req
->in
.vector
[2].iov_len
= SVAL(inbuf
, ofs
) & 0xFFFE;
286 ofs
+= req
->in
.vector
[2].iov_len
;
289 return NT_STATUS_INVALID_PARAMETER
;
292 req
->in
.vector
[3].iov_base
= discard_const_p(void, (inbuf
+ ofs
));
293 req
->in
.vector
[3].iov_len
= size
- ofs
;
294 ofs
+= req
->in
.vector
[3].iov_len
;
296 req
->current_idx
= 1;
302 static bool smb2_validate_message_id(struct smbd_server_connection
*sconn
,
303 const uint8_t *inhdr
)
305 uint64_t message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
306 struct bitmap
*credits_bm
= sconn
->smb2
.credits_bitmap
;
307 uint16_t opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
308 unsigned int bitmap_offset
;
309 uint16_t credit_charge
= 1;
312 if (opcode
== SMB2_OP_CANCEL
) {
313 /* SMB2_CANCEL requests by definition resend messageids. */
317 if (message_id
< sconn
->smb2
.seqnum_low
||
318 message_id
> (sconn
->smb2
.seqnum_low
+
319 (sconn
->smb2
.max_credits
* DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
))) {
320 DEBUG(0,("smb2_validate_message_id: bad message_id "
321 "%llu (low = %llu, max = %lu)\n",
322 (unsigned long long)message_id
,
323 (unsigned long long)sconn
->smb2
.seqnum_low
,
324 (unsigned long)sconn
->smb2
.max_credits
));
328 if (sconn
->smb2
.credits_granted
== 0) {
329 DEBUG(0,("smb2_validate_message_id: client used more "
330 "credits than granted, message_id (%llu)\n",
331 (unsigned long long)message_id
));
335 if (sconn
->smb2
.supports_multicredit
) {
336 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
337 credit_charge
= MAX(credit_charge
, 1);
340 DEBUG(11, ("smb2_validate_message_id: mid %llu, credits_granted %llu, "
341 "charge %llu, max_credits %llu, seqnum_low: %llu\n",
342 (unsigned long long) message_id
,
343 (unsigned long long) sconn
->smb2
.credits_granted
,
344 (unsigned long long) credit_charge
,
345 (unsigned long long) sconn
->smb2
.max_credits
,
346 (unsigned long long) sconn
->smb2
.seqnum_low
));
348 /* substract used credits */
349 sconn
->smb2
.credits_granted
-= credit_charge
;
352 * now check the message ids
354 * for multi-credit requests we need to check all current mid plus
355 * the implicit mids caused by the credit charge
356 * e.g. current mid = 15, charge 5 => mark 15-19 as used
359 for (i
= message_id
; i
<= (message_id
+credit_charge
-1); i
++) {
361 DEBUG(11, ("Iterating mid %llu\n", (unsigned long long) i
));
363 /* Mark the message_ids as seen in the bitmap. */
364 bitmap_offset
= (unsigned int)(i
%
365 (uint64_t)(sconn
->smb2
.max_credits
*
366 DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
));
367 if (bitmap_query(credits_bm
, bitmap_offset
)) {
368 DEBUG(0,("smb2_validate_message_id: duplicate "
369 "message_id %llu (bm offset %u)\n",
370 (unsigned long long)i
, bitmap_offset
));
373 bitmap_set(credits_bm
, bitmap_offset
);
375 if (i
== sconn
->smb2
.seqnum_low
+ 1) {
376 /* Move the window forward by all the message_id's
378 while (bitmap_query(credits_bm
, bitmap_offset
)) {
379 DEBUG(10,("smb2_validate_message_id: clearing "
380 "id %llu (position %u) from bitmap\n",
381 (unsigned long long)(sconn
->smb2
.seqnum_low
+ 1),
383 bitmap_clear(credits_bm
, bitmap_offset
);
384 sconn
->smb2
.seqnum_low
+= 1;
385 bitmap_offset
= (bitmap_offset
+ 1) %
386 (sconn
->smb2
.max_credits
*
387 DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
);
395 static NTSTATUS
smbd_smb2_request_validate(struct smbd_smb2_request
*req
)
400 count
= req
->in
.vector_count
;
403 /* It's not a SMB2 request */
404 return NT_STATUS_INVALID_PARAMETER
;
407 for (idx
=1; idx
< count
; idx
+= 3) {
408 const uint8_t *inhdr
= NULL
;
411 if (req
->in
.vector
[idx
].iov_len
!= SMB2_HDR_BODY
) {
412 return NT_STATUS_INVALID_PARAMETER
;
415 if (req
->in
.vector
[idx
+1].iov_len
< 2) {
416 return NT_STATUS_INVALID_PARAMETER
;
419 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
421 /* Check the SMB2 header */
422 if (IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
) != SMB2_MAGIC
) {
423 return NT_STATUS_INVALID_PARAMETER
;
426 if (!smb2_validate_message_id(req
->sconn
, inhdr
)) {
427 return NT_STATUS_INVALID_PARAMETER
;
430 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
433 * the 1st request should never have the
434 * SMB2_HDR_FLAG_CHAINED flag set
436 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
437 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
440 } else if (idx
== 4) {
442 * the 2nd request triggers related vs. unrelated
443 * compounded requests
445 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
446 req
->compound_related
= true;
448 } else if (idx
> 4) {
451 * It seems the this tests are wrong
452 * see the SMB2-COMPOUND test
456 * all other requests should match the 2nd one
458 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
459 if (!req
->compound_related
) {
461 NT_STATUS_INVALID_PARAMETER
;
465 if (req
->compound_related
) {
467 NT_STATUS_INVALID_PARAMETER
;
478 static void smb2_set_operation_credit(struct smbd_server_connection
*sconn
,
479 const struct iovec
*in_vector
,
480 struct iovec
*out_vector
)
482 const uint8_t *inhdr
= (const uint8_t *)in_vector
->iov_base
;
483 uint8_t *outhdr
= (uint8_t *)out_vector
->iov_base
;
484 uint16_t credits_requested
;
486 uint16_t credits_granted
= 0;
488 credits_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
489 out_flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
491 SMB_ASSERT(sconn
->smb2
.max_credits
>= sconn
->smb2
.credits_granted
);
493 if (out_flags
& SMB2_HDR_FLAG_ASYNC
) {
495 * In case we already send an async interim
496 * response, we should not grant
497 * credits on the final response.
499 credits_requested
= 0;
502 if (credits_requested
) {
503 uint16_t modified_credits_requested
;
507 * Split up max_credits into 1/16ths, and then scale
508 * the requested credits by how many 16ths have been
509 * currently granted. Less than 1/16th == grant all
510 * requested (100%), scale down as more have been
511 * granted. Never ask for less than 1 as the client
512 * asked for at least 1. JRA.
515 multiplier
= 16 - (((sconn
->smb2
.credits_granted
* 16) / sconn
->smb2
.max_credits
) % 16);
517 modified_credits_requested
= (multiplier
* credits_requested
) / 16;
518 if (modified_credits_requested
== 0) {
519 modified_credits_requested
= 1;
522 /* Remember what we gave out. */
523 credits_granted
= MIN(modified_credits_requested
,
524 (sconn
->smb2
.max_credits
- sconn
->smb2
.credits_granted
));
527 if (credits_granted
== 0 && sconn
->smb2
.credits_granted
== 0) {
528 /* First negprot packet, or ensure the client credits can
529 never drop to zero. */
533 SSVAL(outhdr
, SMB2_HDR_CREDIT
, credits_granted
);
534 sconn
->smb2
.credits_granted
+= credits_granted
;
536 DEBUG(10,("smb2_set_operation_credit: requested %u, "
537 "granted %u, total granted %u\n",
538 (unsigned int)credits_requested
,
539 (unsigned int)credits_granted
,
540 (unsigned int)sconn
->smb2
.credits_granted
));
543 static void smb2_calculate_credits(const struct smbd_smb2_request
*inreq
,
544 struct smbd_smb2_request
*outreq
)
547 uint16_t total_credits
= 0;
549 count
= outreq
->out
.vector_count
;
551 for (idx
=1; idx
< count
; idx
+= 3) {
552 uint8_t *outhdr
= (uint8_t *)outreq
->out
.vector
[idx
].iov_base
;
553 smb2_set_operation_credit(outreq
->sconn
,
554 &inreq
->in
.vector
[idx
],
555 &outreq
->out
.vector
[idx
]);
556 /* To match Windows, count up what we
558 total_credits
+= SVAL(outhdr
, SMB2_HDR_CREDIT
);
559 /* Set to zero in all but the last reply. */
560 if (idx
+ 3 < count
) {
561 SSVAL(outhdr
, SMB2_HDR_CREDIT
, 0);
563 SSVAL(outhdr
, SMB2_HDR_CREDIT
, total_credits
);
568 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
)
570 struct iovec
*vector
;
574 req
->request_time
= timeval_current();
576 count
= req
->in
.vector_count
;
577 vector
= talloc_zero_array(req
, struct iovec
, count
);
578 if (vector
== NULL
) {
579 return NT_STATUS_NO_MEMORY
;
582 vector
[0].iov_base
= req
->out
.nbt_hdr
;
583 vector
[0].iov_len
= 4;
584 SIVAL(req
->out
.nbt_hdr
, 0, 0);
586 for (idx
=1; idx
< count
; idx
+= 3) {
587 const uint8_t *inhdr
= NULL
;
588 uint8_t *outhdr
= NULL
;
589 uint8_t *outbody
= NULL
;
590 uint32_t next_command_ofs
= 0;
591 struct iovec
*current
= &vector
[idx
];
593 if ((idx
+ 3) < count
) {
594 /* we have a next command -
595 * setup for the error case. */
596 next_command_ofs
= SMB2_HDR_BODY
+ 9;
599 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
601 outhdr
= talloc_zero_array(vector
, uint8_t,
603 if (outhdr
== NULL
) {
604 return NT_STATUS_NO_MEMORY
;
607 outbody
= outhdr
+ SMB2_HDR_BODY
;
609 current
[0].iov_base
= (void *)outhdr
;
610 current
[0].iov_len
= SMB2_HDR_BODY
;
612 current
[1].iov_base
= (void *)outbody
;
613 current
[1].iov_len
= 8;
615 current
[2].iov_base
= NULL
;
616 current
[2].iov_len
= 0;
618 /* setup the SMB2 header */
619 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
620 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
621 SSVAL(outhdr
, SMB2_HDR_CREDIT_CHARGE
,
622 SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
));
623 SIVAL(outhdr
, SMB2_HDR_STATUS
,
624 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
625 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
626 SVAL(inhdr
, SMB2_HDR_OPCODE
));
627 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
628 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
629 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
630 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
631 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
632 SIVAL(outhdr
, SMB2_HDR_PID
,
633 IVAL(inhdr
, SMB2_HDR_PID
));
634 SIVAL(outhdr
, SMB2_HDR_TID
,
635 IVAL(inhdr
, SMB2_HDR_TID
));
636 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
637 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
638 memcpy(outhdr
+ SMB2_HDR_SIGNATURE
,
639 inhdr
+ SMB2_HDR_SIGNATURE
, 16);
641 /* setup error body header */
642 SSVAL(outbody
, 0x00, 0x08 + 1);
643 SSVAL(outbody
, 0x02, 0);
644 SIVAL(outbody
, 0x04, 0);
647 req
->out
.vector
= vector
;
648 req
->out
.vector_count
= count
;
650 /* setup the length of the NBT packet */
651 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
653 DLIST_ADD_END(req
->sconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
658 void smbd_server_connection_terminate_ex(struct smbd_server_connection
*sconn
,
660 const char *location
)
662 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
664 exit_server_cleanly(reason
);
667 static bool dup_smb2_vec3(TALLOC_CTX
*ctx
,
668 struct iovec
*outvec
,
669 const struct iovec
*srcvec
)
671 /* vec[0] is always boilerplate and must
672 * be allocated with size OUTVEC_ALLOC_SIZE. */
674 outvec
[0].iov_base
= talloc_memdup(ctx
,
677 if (!outvec
[0].iov_base
) {
680 outvec
[0].iov_len
= SMB2_HDR_BODY
;
683 * If this is a "standard" vec[1] of length 8,
684 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
685 * then duplicate this. Else use talloc_memdup().
688 if (srcvec
[1].iov_len
== 8 &&
689 srcvec
[1].iov_base
==
690 ((uint8_t *)srcvec
[0].iov_base
) +
692 outvec
[1].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
694 outvec
[1].iov_len
= 8;
696 outvec
[1].iov_base
= talloc_memdup(ctx
,
699 if (!outvec
[1].iov_base
) {
702 outvec
[1].iov_len
= srcvec
[1].iov_len
;
706 * If this is a "standard" vec[2] of length 1,
707 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
708 * then duplicate this. Else use talloc_memdup().
711 if (srcvec
[2].iov_base
&&
713 if (srcvec
[2].iov_base
==
714 ((uint8_t *)srcvec
[0].iov_base
) +
715 (OUTVEC_ALLOC_SIZE
- 1) &&
716 srcvec
[2].iov_len
== 1) {
717 /* Common SMB2 error packet case. */
718 outvec
[2].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
719 (OUTVEC_ALLOC_SIZE
- 1);
721 outvec
[2].iov_base
= talloc_memdup(ctx
,
724 if (!outvec
[2].iov_base
) {
728 outvec
[2].iov_len
= srcvec
[2].iov_len
;
730 outvec
[2].iov_base
= NULL
;
731 outvec
[2].iov_len
= 0;
736 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
738 struct smbd_smb2_request
*newreq
= NULL
;
739 struct iovec
*outvec
= NULL
;
740 int count
= req
->out
.vector_count
;
743 newreq
= smbd_smb2_request_allocate(req
->sconn
);
748 newreq
->sconn
= req
->sconn
;
749 newreq
->session
= req
->session
;
750 newreq
->do_signing
= req
->do_signing
;
751 newreq
->current_idx
= req
->current_idx
;
753 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
758 newreq
->out
.vector
= outvec
;
759 newreq
->out
.vector_count
= count
;
761 /* Setup the outvec's identically to req. */
762 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
763 outvec
[0].iov_len
= 4;
764 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
766 /* Setup the vectors identically to the ones in req. */
767 for (i
= 1; i
< count
; i
+= 3) {
768 if (!dup_smb2_vec3(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
779 smb2_setup_nbt_length(newreq
->out
.vector
,
780 newreq
->out
.vector_count
);
785 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
);
787 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
790 uint8_t *outhdr
= NULL
;
791 struct smbd_smb2_request
*nreq
= NULL
;
793 /* Create a new smb2 request we'll use
794 for the interim return. */
795 nreq
= dup_smb2_req(req
);
797 return NT_STATUS_NO_MEMORY
;
800 /* Lose the last 3 out vectors. They're the
801 ones we'll be using for the async reply. */
802 nreq
->out
.vector_count
-= 3;
804 smb2_setup_nbt_length(nreq
->out
.vector
,
805 nreq
->out
.vector_count
);
807 /* Step back to the previous reply. */
808 i
= nreq
->current_idx
- 3;
809 outhdr
= (uint8_t *)nreq
->out
.vector
[i
].iov_base
;
810 /* And end the chain. */
811 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
813 /* Calculate outgoing credits */
814 smb2_calculate_credits(req
, nreq
);
816 /* Re-sign if needed. */
817 if (nreq
->do_signing
) {
819 status
= smb2_signing_sign_pdu(nreq
->session
->session_key
,
821 &nreq
->out
.vector
[i
], 3);
822 if (!NT_STATUS_IS_OK(status
)) {
826 if (DEBUGLEVEL
>= 10) {
827 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
828 (unsigned int)nreq
->current_idx
);
829 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
830 (unsigned int)nreq
->out
.vector_count
);
831 print_req_vectors(nreq
);
833 nreq
->subreq
= tstream_writev_queue_send(nreq
,
835 nreq
->sconn
->smb2
.stream
,
836 nreq
->sconn
->smb2
.send_queue
,
838 nreq
->out
.vector_count
);
840 if (nreq
->subreq
== NULL
) {
841 return NT_STATUS_NO_MEMORY
;
844 tevent_req_set_callback(nreq
->subreq
,
845 smbd_smb2_request_writev_done
,
851 struct smbd_smb2_request_pending_state
{
852 struct smbd_server_connection
*sconn
;
853 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x08 + 1];
854 struct iovec vector
[3];
857 static void smbd_smb2_request_pending_writev_done(struct tevent_req
*subreq
)
859 struct smbd_smb2_request_pending_state
*state
=
860 tevent_req_callback_data(subreq
,
861 struct smbd_smb2_request_pending_state
);
862 struct smbd_server_connection
*sconn
= state
->sconn
;
866 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
869 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
870 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
877 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
878 struct tevent_timer
*te
,
879 struct timeval current_time
,
882 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
883 struct tevent_req
*subreq
,
887 int i
= req
->current_idx
;
888 struct timeval defer_endtime
;
889 uint8_t *outhdr
= NULL
;
892 if (!tevent_req_is_in_progress(subreq
)) {
896 req
->subreq
= subreq
;
900 /* We're already async. */
904 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
905 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
906 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
907 /* We're already async. */
911 if (req
->in
.vector_count
> i
+ 3) {
913 * We're trying to go async in a compound
914 * request chain. This is not allowed.
915 * Cancel the outstanding request.
917 tevent_req_cancel(req
->subreq
);
918 return smbd_smb2_request_error(req
,
919 NT_STATUS_INSUFFICIENT_RESOURCES
);
922 if (DEBUGLEVEL
>= 10) {
923 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
924 (unsigned int)req
->current_idx
);
925 print_req_vectors(req
);
928 if (req
->out
.vector_count
> 4) {
929 struct iovec
*outvec
= NULL
;
931 /* This is a compound reply. We
932 * must do an interim response
933 * followed by the async response
936 status
= smb2_send_async_interim_response(req
);
937 if (!NT_STATUS_IS_OK(status
)) {
942 * We're splitting off the last SMB2
943 * request in a compound set, and the
944 * smb2_send_async_interim_response()
945 * call above just sent all the replies
946 * for the previous SMB2 requests in
947 * this compound set. So we're no longer
948 * in the "compound_related_in_progress"
949 * state, and this is no longer a compound
952 req
->compound_related
= false;
953 req
->sconn
->smb2
.compound_related_in_progress
= false;
955 /* Re-arrange the in.vectors. */
956 req
->in
.vector
[1] = req
->in
.vector
[i
];
957 req
->in
.vector
[2] = req
->in
.vector
[i
+1];
958 req
->in
.vector
[3] = req
->in
.vector
[i
+2];
959 req
->in
.vector_count
= 4;
961 /* Reset the new in size. */
962 smb2_setup_nbt_length(req
->in
.vector
, 4);
964 /* Now recreate the out.vectors. */
965 outvec
= talloc_zero_array(req
, struct iovec
, 4);
967 return NT_STATUS_NO_MEMORY
;
970 /* 0 is always boilerplate and must
971 * be of size 4 for the length field. */
973 outvec
[0].iov_base
= req
->out
.nbt_hdr
;
974 outvec
[0].iov_len
= 4;
975 SIVAL(req
->out
.nbt_hdr
, 0, 0);
977 if (!dup_smb2_vec3(outvec
, &outvec
[1], &req
->out
.vector
[i
])) {
978 return NT_STATUS_NO_MEMORY
;
981 TALLOC_FREE(req
->out
.vector
);
983 req
->out
.vector
= outvec
;
985 req
->current_idx
= 1;
986 req
->out
.vector_count
= 4;
988 outhdr
= (uint8_t *)req
->out
.vector
[1].iov_base
;
989 flags
= (IVAL(outhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
990 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
);
993 defer_endtime
= timeval_current_ofs_usec(defer_time
);
994 req
->async_te
= tevent_add_timer(req
->sconn
->ev_ctx
,
996 smbd_smb2_request_pending_timer
,
998 if (req
->async_te
== NULL
) {
999 return NT_STATUS_NO_MEMORY
;
1002 return NT_STATUS_OK
;
1005 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
1006 struct tevent_timer
*te
,
1007 struct timeval current_time
,
1010 struct smbd_smb2_request
*req
=
1011 talloc_get_type_abort(private_data
,
1012 struct smbd_smb2_request
);
1013 struct smbd_smb2_request_pending_state
*state
= NULL
;
1014 int i
= req
->current_idx
;
1015 uint8_t *outhdr
= NULL
;
1016 const uint8_t *inhdr
= NULL
;
1017 uint8_t *hdr
= NULL
;
1018 uint8_t *body
= NULL
;
1020 uint64_t message_id
= 0;
1021 uint64_t async_id
= 0;
1022 struct tevent_req
*subreq
= NULL
;
1024 TALLOC_FREE(req
->async_te
);
1026 /* Ensure our final reply matches the interim one. */
1027 inhdr
= (const uint8_t *)req
->in
.vector
[1].iov_base
;
1028 outhdr
= (uint8_t *)req
->out
.vector
[1].iov_base
;
1029 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1030 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1032 async_id
= message_id
; /* keep it simple for now... */
1034 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1035 SBVAL(outhdr
, SMB2_HDR_ASYNC_ID
, async_id
);
1037 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1039 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1040 (unsigned long long)async_id
));
1043 * What we send is identical to a smbd_smb2_request_error
1044 * packet with an error status of STATUS_PENDING. Make use
1045 * of this fact sometime when refactoring. JRA.
1048 state
= talloc_zero(req
->sconn
, struct smbd_smb2_request_pending_state
);
1049 if (state
== NULL
) {
1050 smbd_server_connection_terminate(req
->sconn
,
1051 nt_errstr(NT_STATUS_NO_MEMORY
));
1054 state
->sconn
= req
->sconn
;
1056 state
->vector
[0].iov_base
= (void *)state
->buf
;
1057 state
->vector
[0].iov_len
= 4;
1059 state
->vector
[1].iov_base
= state
->buf
+ 4;
1060 state
->vector
[1].iov_len
= SMB2_HDR_BODY
;
1062 state
->vector
[2].iov_base
= state
->buf
+ 4 + SMB2_HDR_BODY
;
1063 state
->vector
[2].iov_len
= 9;
1065 smb2_setup_nbt_length(state
->vector
, 3);
1067 hdr
= (uint8_t *)state
->vector
[1].iov_base
;
1068 body
= (uint8_t *)state
->vector
[2].iov_base
;
1070 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
1071 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1072 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1073 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
1074 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(outhdr
, SMB2_HDR_OPCODE
));
1076 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
);
1077 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1078 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
1079 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
1080 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
1081 BVAL(outhdr
, SMB2_HDR_SESSION_ID
));
1082 memcpy(hdr
+SMB2_HDR_SIGNATURE
,
1083 outhdr
+SMB2_HDR_SIGNATURE
, 16);
1085 SSVAL(body
, 0x00, 0x08 + 1);
1087 SCVAL(body
, 0x02, 0);
1088 SCVAL(body
, 0x03, 0);
1089 SIVAL(body
, 0x04, 0);
1090 /* Match W2K8R2... */
1091 SCVAL(body
, 0x08, 0x21);
1093 /* Ensure we correctly go through crediting. Grant
1094 the credits now, and zero credits on the final
1096 smb2_set_operation_credit(req
->sconn
,
1100 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1102 if (req
->do_signing
) {
1105 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
1107 &state
->vector
[1], 2);
1108 if (!NT_STATUS_IS_OK(status
)) {
1109 smbd_server_connection_terminate(req
->sconn
,
1115 subreq
= tstream_writev_queue_send(state
,
1116 state
->sconn
->ev_ctx
,
1117 state
->sconn
->smb2
.stream
,
1118 state
->sconn
->smb2
.send_queue
,
1121 if (subreq
== NULL
) {
1122 smbd_server_connection_terminate(state
->sconn
,
1123 nt_errstr(NT_STATUS_NO_MEMORY
));
1126 tevent_req_set_callback(subreq
,
1127 smbd_smb2_request_pending_writev_done
,
1131 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
1133 struct smbd_server_connection
*sconn
= req
->sconn
;
1134 struct smbd_smb2_request
*cur
;
1135 const uint8_t *inhdr
;
1136 int i
= req
->current_idx
;
1138 uint64_t search_message_id
;
1139 uint64_t search_async_id
;
1142 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1144 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1145 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1146 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
1149 * we don't need the request anymore
1150 * cancel requests never have a response
1152 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1155 for (cur
= sconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
1156 const uint8_t *outhdr
;
1157 uint64_t message_id
;
1160 i
= cur
->current_idx
;
1162 outhdr
= (const uint8_t *)cur
->out
.vector
[i
].iov_base
;
1164 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1165 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
1167 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1168 if (search_async_id
== async_id
) {
1169 found_id
= async_id
;
1173 if (search_message_id
== message_id
) {
1174 found_id
= message_id
;
1180 if (cur
&& cur
->subreq
) {
1181 inhdr
= (const uint8_t *)cur
->in
.vector
[i
].iov_base
;
1182 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1183 "cancel opcode[%s] mid %llu\n",
1184 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1185 (unsigned long long)found_id
));
1186 tevent_req_cancel(cur
->subreq
);
1189 return NT_STATUS_OK
;
1192 /*************************************************************
1193 Ensure an incoming tid is a valid one for us to access.
1194 Change to the associated uid credentials and chdir to the
1195 valid tid directory.
1196 *************************************************************/
1198 static NTSTATUS
smbd_smb2_request_check_tcon(struct smbd_smb2_request
*req
)
1200 const uint8_t *inhdr
;
1201 int i
= req
->current_idx
;
1205 struct smbd_smb2_tcon
*tcon
;
1209 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1211 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1212 in_tid
= IVAL(inhdr
, SMB2_HDR_TID
);
1214 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1215 in_tid
= req
->last_tid
;
1218 /* lookup an existing session */
1219 p
= idr_find(req
->session
->tcons
.idtree
, in_tid
);
1221 return NT_STATUS_NETWORK_NAME_DELETED
;
1223 tcon
= talloc_get_type_abort(p
, struct smbd_smb2_tcon
);
1225 if (!change_to_user(tcon
->compat_conn
,req
->session
->vuid
)) {
1226 return NT_STATUS_ACCESS_DENIED
;
1229 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1230 if (!set_current_service(tcon
->compat_conn
, 0, true)) {
1231 return NT_STATUS_ACCESS_DENIED
;
1235 req
->last_tid
= in_tid
;
1237 return NT_STATUS_OK
;
1240 /*************************************************************
1241 Ensure an incoming session_id is a valid one for us to access.
1242 *************************************************************/
1244 static NTSTATUS
smbd_smb2_request_check_session(struct smbd_smb2_request
*req
)
1246 const uint8_t *inhdr
;
1247 int i
= req
->current_idx
;
1249 uint64_t in_session_id
;
1251 struct smbd_smb2_session
*session
;
1253 req
->session
= NULL
;
1256 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1258 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1259 in_session_id
= BVAL(inhdr
, SMB2_HDR_SESSION_ID
);
1261 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1262 in_session_id
= req
->last_session_id
;
1265 /* lookup an existing session */
1266 p
= idr_find(req
->sconn
->smb2
.sessions
.idtree
, in_session_id
);
1268 return NT_STATUS_USER_SESSION_DELETED
;
1270 session
= talloc_get_type_abort(p
, struct smbd_smb2_session
);
1272 if (!NT_STATUS_IS_OK(session
->status
)) {
1273 return NT_STATUS_ACCESS_DENIED
;
1276 set_current_user_info(session
->session_info
->unix_info
->sanitized_username
,
1277 session
->session_info
->unix_info
->unix_name
,
1278 session
->session_info
->info
->domain_name
);
1280 req
->session
= session
;
1281 req
->last_session_id
= in_session_id
;
1283 return NT_STATUS_OK
;
1286 NTSTATUS
smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request
*req
,
1287 uint32_t data_length
)
1289 uint16_t needed_charge
;
1290 uint16_t credit_charge
;
1291 const uint8_t *inhdr
;
1292 int i
= req
->current_idx
;
1294 if (!req
->sconn
->smb2
.supports_multicredit
) {
1295 if (data_length
> 65536) {
1296 return NT_STATUS_INVALID_PARAMETER
;
1298 return NT_STATUS_OK
;
1301 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1302 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
1304 /* requests larger than 64 KB need credit charge */
1305 if (credit_charge
== 0 && data_length
> 65536) {
1306 DEBUG(2, ("Request larger than 64KB w/o creditcharge\n"));
1307 return NT_STATUS_INVALID_PARAMETER
;
1310 needed_charge
= (data_length
- 1)/ 65536 + 1;
1312 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1313 (unsigned long long) BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
),
1314 credit_charge
, needed_charge
));
1316 if (needed_charge
> credit_charge
) {
1317 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1318 credit_charge
, needed_charge
));
1319 return NT_STATUS_INVALID_PARAMETER
;
1322 return NT_STATUS_OK
;
1325 NTSTATUS
smbd_smb2_request_verify_sizes(struct smbd_smb2_request
*req
,
1326 size_t expected_body_size
)
1328 const uint8_t *inhdr
;
1330 const uint8_t *inbody
;
1331 int i
= req
->current_idx
;
1333 size_t min_dyn_size
= expected_body_size
& 0x00000001;
1336 * The following should be checked already.
1338 if ((i
+2) > req
->in
.vector_count
) {
1339 return NT_STATUS_INTERNAL_ERROR
;
1341 if (req
->in
.vector
[i
+0].iov_len
!= SMB2_HDR_BODY
) {
1342 return NT_STATUS_INTERNAL_ERROR
;
1344 if (req
->in
.vector
[i
+1].iov_len
< 2) {
1345 return NT_STATUS_INTERNAL_ERROR
;
1348 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1349 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1353 case SMB2_OP_GETINFO
:
1359 * Now check the expected body size,
1360 * where the last byte might be in the
1363 if (req
->in
.vector
[i
+1].iov_len
!= (expected_body_size
& 0xFFFFFFFE)) {
1364 return NT_STATUS_INVALID_PARAMETER
;
1366 if (req
->in
.vector
[i
+2].iov_len
< min_dyn_size
) {
1367 return NT_STATUS_INVALID_PARAMETER
;
1370 inbody
= (const uint8_t *)req
->in
.vector
[i
+1].iov_base
;
1372 body_size
= SVAL(inbody
, 0x00);
1373 if (body_size
!= expected_body_size
) {
1374 return NT_STATUS_INVALID_PARAMETER
;
1377 return NT_STATUS_OK
;
1380 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
1382 const uint8_t *inhdr
;
1383 int i
= req
->current_idx
;
1388 NTSTATUS session_status
;
1389 uint32_t allowed_flags
;
1390 NTSTATUS return_value
;
1392 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1394 /* TODO: verify more things */
1396 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1397 opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1398 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1399 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1400 smb2_opcode_name(opcode
),
1401 (unsigned long long)mid
));
1403 if (get_Protocol() >= PROTOCOL_SMB2_02
) {
1405 * once the protocol is negotiated
1406 * SMB2_OP_NEGPROT is not allowed anymore
1408 if (opcode
== SMB2_OP_NEGPROT
) {
1409 /* drop the connection */
1410 return NT_STATUS_INVALID_PARAMETER
;
1414 * if the protocol is not negotiated yet
1415 * only SMB2_OP_NEGPROT is allowed.
1417 if (opcode
!= SMB2_OP_NEGPROT
) {
1418 /* drop the connection */
1419 return NT_STATUS_INVALID_PARAMETER
;
1423 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
1424 SMB2_HDR_FLAG_SIGNED
|
1426 if (opcode
== SMB2_OP_CANCEL
) {
1427 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
1429 if ((flags
& ~allowed_flags
) != 0) {
1430 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1434 * Check if the client provided a valid session id,
1435 * if so smbd_smb2_request_check_session() calls
1436 * set_current_user_info().
1438 * As some command don't require a valid session id
1439 * we defer the check of the session_status
1441 session_status
= smbd_smb2_request_check_session(req
);
1443 req
->do_signing
= false;
1444 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
1445 if (!NT_STATUS_IS_OK(session_status
)) {
1446 return smbd_smb2_request_error(req
, session_status
);
1449 req
->do_signing
= true;
1450 status
= smb2_signing_check_pdu(req
->session
->session_key
,
1452 &req
->in
.vector
[i
], 3);
1453 if (!NT_STATUS_IS_OK(status
)) {
1454 return smbd_smb2_request_error(req
, status
);
1456 } else if (opcode
== SMB2_OP_CANCEL
) {
1457 /* Cancel requests are allowed to skip the signing */
1458 } else if (req
->session
&& req
->session
->do_signing
) {
1459 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
1462 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
1464 * This check is mostly for giving the correct error code
1465 * for compounded requests.
1467 * TODO: we may need to move this after the session
1470 if (!NT_STATUS_IS_OK(req
->next_status
)) {
1471 return smbd_smb2_request_error(req
, req
->next_status
);
1474 req
->compat_chain_fsp
= NULL
;
1477 if (req
->compound_related
) {
1478 req
->sconn
->smb2
.compound_related_in_progress
= true;
1482 case SMB2_OP_NEGPROT
:
1483 /* This call needs to be run as root */
1484 change_to_root_user();
1487 START_PROFILE(smb2_negprot
);
1488 return_value
= smbd_smb2_request_process_negprot(req
);
1489 END_PROFILE(smb2_negprot
);
1493 case SMB2_OP_SESSSETUP
:
1494 /* This call needs to be run as root */
1495 change_to_root_user();
1498 START_PROFILE(smb2_sesssetup
);
1499 return_value
= smbd_smb2_request_process_sesssetup(req
);
1500 END_PROFILE(smb2_sesssetup
);
1504 case SMB2_OP_LOGOFF
:
1505 if (!NT_STATUS_IS_OK(session_status
)) {
1506 return_value
= smbd_smb2_request_error(req
, session_status
);
1510 /* This call needs to be run as root */
1511 change_to_root_user();
1514 START_PROFILE(smb2_logoff
);
1515 return_value
= smbd_smb2_request_process_logoff(req
);
1516 END_PROFILE(smb2_logoff
);
1521 if (!NT_STATUS_IS_OK(session_status
)) {
1522 return_value
= smbd_smb2_request_error(req
, session_status
);
1527 * This call needs to be run as root.
1529 * smbd_smb2_request_process_tcon()
1530 * calls make_connection_snum(), which will call
1531 * change_to_user(), when needed.
1533 change_to_root_user();
1536 START_PROFILE(smb2_tcon
);
1537 return_value
= smbd_smb2_request_process_tcon(req
);
1538 END_PROFILE(smb2_tcon
);
1543 if (!NT_STATUS_IS_OK(session_status
)) {
1544 return_value
= smbd_smb2_request_error(req
, session_status
);
1548 * This call needs to be run as user.
1550 * smbd_smb2_request_check_tcon()
1551 * calls change_to_user() on success.
1553 status
= smbd_smb2_request_check_tcon(req
);
1554 if (!NT_STATUS_IS_OK(status
)) {
1555 return_value
= smbd_smb2_request_error(req
, status
);
1558 /* This call needs to be run as root */
1559 change_to_root_user();
1563 START_PROFILE(smb2_tdis
);
1564 return_value
= smbd_smb2_request_process_tdis(req
);
1565 END_PROFILE(smb2_tdis
);
1569 case SMB2_OP_CREATE
:
1570 if (!NT_STATUS_IS_OK(session_status
)) {
1571 return_value
= smbd_smb2_request_error(req
, session_status
);
1575 * This call needs to be run as user.
1577 * smbd_smb2_request_check_tcon()
1578 * calls change_to_user() on success.
1580 status
= smbd_smb2_request_check_tcon(req
);
1581 if (!NT_STATUS_IS_OK(status
)) {
1582 return_value
= smbd_smb2_request_error(req
, status
);
1587 START_PROFILE(smb2_create
);
1588 return_value
= smbd_smb2_request_process_create(req
);
1589 END_PROFILE(smb2_create
);
1594 if (!NT_STATUS_IS_OK(session_status
)) {
1595 return_value
= smbd_smb2_request_error(req
, session_status
);
1599 * This call needs to be run as user.
1601 * smbd_smb2_request_check_tcon()
1602 * calls change_to_user() on success.
1604 status
= smbd_smb2_request_check_tcon(req
);
1605 if (!NT_STATUS_IS_OK(status
)) {
1606 return_value
= smbd_smb2_request_error(req
, status
);
1611 START_PROFILE(smb2_close
);
1612 return_value
= smbd_smb2_request_process_close(req
);
1613 END_PROFILE(smb2_close
);
1618 if (!NT_STATUS_IS_OK(session_status
)) {
1619 return_value
= smbd_smb2_request_error(req
, session_status
);
1623 * This call needs to be run as user.
1625 * smbd_smb2_request_check_tcon()
1626 * calls change_to_user() on success.
1628 status
= smbd_smb2_request_check_tcon(req
);
1629 if (!NT_STATUS_IS_OK(status
)) {
1630 return_value
= smbd_smb2_request_error(req
, status
);
1635 START_PROFILE(smb2_flush
);
1636 return_value
= smbd_smb2_request_process_flush(req
);
1637 END_PROFILE(smb2_flush
);
1642 if (!NT_STATUS_IS_OK(session_status
)) {
1643 return_value
= smbd_smb2_request_error(req
, session_status
);
1647 * This call needs to be run as user.
1649 * smbd_smb2_request_check_tcon()
1650 * calls change_to_user() on success.
1652 status
= smbd_smb2_request_check_tcon(req
);
1653 if (!NT_STATUS_IS_OK(status
)) {
1654 return_value
= smbd_smb2_request_error(req
, status
);
1659 START_PROFILE(smb2_read
);
1660 return_value
= smbd_smb2_request_process_read(req
);
1661 END_PROFILE(smb2_read
);
1666 if (!NT_STATUS_IS_OK(session_status
)) {
1667 return_value
= smbd_smb2_request_error(req
, session_status
);
1671 * This call needs to be run as user.
1673 * smbd_smb2_request_check_tcon()
1674 * calls change_to_user() on success.
1676 status
= smbd_smb2_request_check_tcon(req
);
1677 if (!NT_STATUS_IS_OK(status
)) {
1678 return_value
= smbd_smb2_request_error(req
, status
);
1683 START_PROFILE(smb2_write
);
1684 return_value
= smbd_smb2_request_process_write(req
);
1685 END_PROFILE(smb2_write
);
1690 if (!NT_STATUS_IS_OK(session_status
)) {
1691 /* Too ugly to live ? JRA. */
1692 if (NT_STATUS_EQUAL(session_status
,NT_STATUS_USER_SESSION_DELETED
)) {
1693 session_status
= NT_STATUS_FILE_CLOSED
;
1695 return_value
= smbd_smb2_request_error(req
, session_status
);
1699 * This call needs to be run as user.
1701 * smbd_smb2_request_check_tcon()
1702 * calls change_to_user() on success.
1704 status
= smbd_smb2_request_check_tcon(req
);
1705 if (!NT_STATUS_IS_OK(status
)) {
1706 /* Too ugly to live ? JRA. */
1707 if (NT_STATUS_EQUAL(status
,NT_STATUS_NETWORK_NAME_DELETED
)) {
1708 status
= NT_STATUS_FILE_CLOSED
;
1710 return_value
= smbd_smb2_request_error(req
, status
);
1715 START_PROFILE(smb2_lock
);
1716 return_value
= smbd_smb2_request_process_lock(req
);
1717 END_PROFILE(smb2_lock
);
1722 if (!NT_STATUS_IS_OK(session_status
)) {
1723 return_value
= smbd_smb2_request_error(req
, session_status
);
1727 * This call needs to be run as user.
1729 * smbd_smb2_request_check_tcon()
1730 * calls change_to_user() on success.
1732 status
= smbd_smb2_request_check_tcon(req
);
1733 if (!NT_STATUS_IS_OK(status
)) {
1734 return_value
= smbd_smb2_request_error(req
, status
);
1739 START_PROFILE(smb2_ioctl
);
1740 return_value
= smbd_smb2_request_process_ioctl(req
);
1741 END_PROFILE(smb2_ioctl
);
1745 case SMB2_OP_CANCEL
:
1747 * This call needs to be run as root
1749 * That is what we also do in the SMB1 case.
1751 change_to_root_user();
1754 START_PROFILE(smb2_cancel
);
1755 return_value
= smbd_smb2_request_process_cancel(req
);
1756 END_PROFILE(smb2_cancel
);
1760 case SMB2_OP_KEEPALIVE
:
1761 /* This call needs to be run as root */
1762 change_to_root_user();
1765 START_PROFILE(smb2_keepalive
);
1766 return_value
= smbd_smb2_request_process_keepalive(req
);
1767 END_PROFILE(smb2_keepalive
);
1772 if (!NT_STATUS_IS_OK(session_status
)) {
1773 return_value
= smbd_smb2_request_error(req
, session_status
);
1777 * This call needs to be run as user.
1779 * smbd_smb2_request_check_tcon()
1780 * calls change_to_user() on success.
1782 status
= smbd_smb2_request_check_tcon(req
);
1783 if (!NT_STATUS_IS_OK(status
)) {
1784 return_value
= smbd_smb2_request_error(req
, status
);
1789 START_PROFILE(smb2_find
);
1790 return_value
= smbd_smb2_request_process_find(req
);
1791 END_PROFILE(smb2_find
);
1795 case SMB2_OP_NOTIFY
:
1796 if (!NT_STATUS_IS_OK(session_status
)) {
1797 return_value
= smbd_smb2_request_error(req
, session_status
);
1801 * This call needs to be run as user.
1803 * smbd_smb2_request_check_tcon()
1804 * calls change_to_user() on success.
1806 status
= smbd_smb2_request_check_tcon(req
);
1807 if (!NT_STATUS_IS_OK(status
)) {
1808 return_value
= smbd_smb2_request_error(req
, status
);
1813 START_PROFILE(smb2_notify
);
1814 return_value
= smbd_smb2_request_process_notify(req
);
1815 END_PROFILE(smb2_notify
);
1819 case SMB2_OP_GETINFO
:
1820 if (!NT_STATUS_IS_OK(session_status
)) {
1821 return_value
= smbd_smb2_request_error(req
, session_status
);
1825 * This call needs to be run as user.
1827 * smbd_smb2_request_check_tcon()
1828 * calls change_to_user() on success.
1830 status
= smbd_smb2_request_check_tcon(req
);
1831 if (!NT_STATUS_IS_OK(status
)) {
1832 return_value
= smbd_smb2_request_error(req
, status
);
1837 START_PROFILE(smb2_getinfo
);
1838 return_value
= smbd_smb2_request_process_getinfo(req
);
1839 END_PROFILE(smb2_getinfo
);
1843 case SMB2_OP_SETINFO
:
1844 if (!NT_STATUS_IS_OK(session_status
)) {
1845 return_value
= smbd_smb2_request_error(req
, session_status
);
1849 * This call needs to be run as user.
1851 * smbd_smb2_request_check_tcon()
1852 * calls change_to_user() on success.
1854 status
= smbd_smb2_request_check_tcon(req
);
1855 if (!NT_STATUS_IS_OK(status
)) {
1856 return_value
= smbd_smb2_request_error(req
, status
);
1861 START_PROFILE(smb2_setinfo
);
1862 return_value
= smbd_smb2_request_process_setinfo(req
);
1863 END_PROFILE(smb2_setinfo
);
1868 if (!NT_STATUS_IS_OK(session_status
)) {
1869 return_value
= smbd_smb2_request_error(req
, session_status
);
1873 * This call needs to be run as user.
1875 * smbd_smb2_request_check_tcon()
1876 * calls change_to_user() on success.
1878 status
= smbd_smb2_request_check_tcon(req
);
1879 if (!NT_STATUS_IS_OK(status
)) {
1880 return_value
= smbd_smb2_request_error(req
, status
);
1885 START_PROFILE(smb2_break
);
1886 return_value
= smbd_smb2_request_process_break(req
);
1887 END_PROFILE(smb2_break
);
1892 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1895 return return_value
;
1898 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
1900 struct tevent_req
*subreq
;
1901 int i
= req
->current_idx
;
1904 TALLOC_FREE(req
->async_te
);
1906 req
->current_idx
+= 3;
1908 if (req
->current_idx
< req
->out
.vector_count
) {
1910 * We must process the remaining compound
1911 * SMB2 requests before any new incoming SMB2
1912 * requests. This is because incoming SMB2
1913 * requests may include a cancel for a
1914 * compound request we haven't processed
1917 struct tevent_immediate
*im
= tevent_create_immediate(req
);
1919 return NT_STATUS_NO_MEMORY
;
1921 tevent_schedule_immediate(im
,
1923 smbd_smb2_request_dispatch_immediate
,
1925 return NT_STATUS_OK
;
1928 if (req
->compound_related
) {
1929 req
->sconn
->smb2
.compound_related_in_progress
= false;
1932 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
1934 /* Set credit for these operations (zero credits if this
1935 is a final reply for an async operation). */
1936 smb2_calculate_credits(req
, req
);
1938 if (req
->do_signing
) {
1940 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
1942 &req
->out
.vector
[i
], 3);
1943 if (!NT_STATUS_IS_OK(status
)) {
1948 if (DEBUGLEVEL
>= 10) {
1949 dbgtext("smbd_smb2_request_reply: sending...\n");
1950 print_req_vectors(req
);
1953 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1954 if (req
->out
.vector_count
== 4 &&
1955 req
->out
.vector
[3].iov_base
== NULL
&&
1956 req
->out
.vector
[3].iov_len
!= 0) {
1957 /* Dynamic part is NULL. Chop it off,
1958 We're going to send it via sendfile. */
1959 req
->out
.vector_count
-= 1;
1962 subreq
= tstream_writev_queue_send(req
,
1964 req
->sconn
->smb2
.stream
,
1965 req
->sconn
->smb2
.send_queue
,
1967 req
->out
.vector_count
);
1968 if (subreq
== NULL
) {
1969 return NT_STATUS_NO_MEMORY
;
1971 tevent_req_set_callback(subreq
, smbd_smb2_request_writev_done
, req
);
1973 * We're done with this request -
1974 * move it off the "being processed" queue.
1976 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1978 return NT_STATUS_OK
;
1981 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
);
1983 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
1984 struct tevent_immediate
*im
,
1987 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
1988 struct smbd_smb2_request
);
1989 struct smbd_server_connection
*sconn
= req
->sconn
;
1994 if (DEBUGLEVEL
>= 10) {
1995 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1996 req
->current_idx
, req
->in
.vector_count
));
1997 print_req_vectors(req
);
2000 status
= smbd_smb2_request_dispatch(req
);
2001 if (!NT_STATUS_IS_OK(status
)) {
2002 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2006 status
= smbd_smb2_request_next_incoming(sconn
);
2007 if (!NT_STATUS_IS_OK(status
)) {
2008 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2013 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
)
2015 struct smbd_smb2_request
*req
= tevent_req_callback_data(subreq
,
2016 struct smbd_smb2_request
);
2017 struct smbd_server_connection
*sconn
= req
->sconn
;
2022 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
2023 TALLOC_FREE(subreq
);
2026 status
= map_nt_error_from_unix(sys_errno
);
2027 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2028 nt_errstr(status
)));
2029 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2033 status
= smbd_smb2_request_next_incoming(sconn
);
2034 if (!NT_STATUS_IS_OK(status
)) {
2035 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2040 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
2042 DATA_BLOB body
, DATA_BLOB
*dyn
,
2043 const char *location
)
2046 int i
= req
->current_idx
;
2047 uint32_t next_command_ofs
;
2049 DEBUG(10,("smbd_smb2_request_done_ex: "
2050 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2051 i
, nt_errstr(status
), (unsigned int)body
.length
,
2053 (unsigned int)(dyn
? dyn
->length
: 0),
2056 if (body
.length
< 2) {
2057 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2060 if ((body
.length
% 2) != 0) {
2061 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2064 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
2066 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
2067 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
2069 req
->out
.vector
[i
+1].iov_base
= (void *)body
.data
;
2070 req
->out
.vector
[i
+1].iov_len
= body
.length
;
2073 req
->out
.vector
[i
+2].iov_base
= (void *)dyn
->data
;
2074 req
->out
.vector
[i
+2].iov_len
= dyn
->length
;
2076 req
->out
.vector
[i
+2].iov_base
= NULL
;
2077 req
->out
.vector
[i
+2].iov_len
= 0;
2080 /* see if we need to recalculate the offset to the next response */
2081 if (next_command_ofs
> 0) {
2082 next_command_ofs
= SMB2_HDR_BODY
;
2083 next_command_ofs
+= req
->out
.vector
[i
+1].iov_len
;
2084 next_command_ofs
+= req
->out
.vector
[i
+2].iov_len
;
2087 if ((next_command_ofs
% 8) != 0) {
2088 size_t pad_size
= 8 - (next_command_ofs
% 8);
2089 if (req
->out
.vector
[i
+2].iov_len
== 0) {
2091 * if the dyn buffer is empty
2092 * we can use it to add padding
2096 pad
= talloc_zero_array(req
->out
.vector
,
2099 return smbd_smb2_request_error(req
,
2100 NT_STATUS_NO_MEMORY
);
2103 req
->out
.vector
[i
+2].iov_base
= (void *)pad
;
2104 req
->out
.vector
[i
+2].iov_len
= pad_size
;
2107 * For now we copy the dynamic buffer
2108 * and add the padding to the new buffer
2115 old_size
= req
->out
.vector
[i
+2].iov_len
;
2116 old_dyn
= (uint8_t *)req
->out
.vector
[i
+2].iov_base
;
2118 new_size
= old_size
+ pad_size
;
2119 new_dyn
= talloc_zero_array(req
->out
.vector
,
2121 if (new_dyn
== NULL
) {
2122 return smbd_smb2_request_error(req
,
2123 NT_STATUS_NO_MEMORY
);
2126 memcpy(new_dyn
, old_dyn
, old_size
);
2127 memset(new_dyn
+ old_size
, 0, pad_size
);
2129 req
->out
.vector
[i
+2].iov_base
= (void *)new_dyn
;
2130 req
->out
.vector
[i
+2].iov_len
= new_size
;
2132 next_command_ofs
+= pad_size
;
2135 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
2137 return smbd_smb2_request_reply(req
);
2140 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
2143 const char *location
)
2146 int i
= req
->current_idx
;
2147 uint8_t *outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
2149 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2150 i
, nt_errstr(status
), info
? " +info" : "",
2153 body
.data
= outhdr
+ SMB2_HDR_BODY
;
2155 SSVAL(body
.data
, 0, 9);
2158 SIVAL(body
.data
, 0x04, info
->length
);
2160 /* Allocated size of req->out.vector[i].iov_base
2161 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2162 * 1 byte without having to do an alloc.
2164 info
= talloc_zero_array(req
->out
.vector
,
2168 return NT_STATUS_NO_MEMORY
;
2170 info
->data
= ((uint8_t *)outhdr
) +
2171 OUTVEC_ALLOC_SIZE
- 1;
2173 SCVAL(info
->data
, 0, 0);
2177 * if a request fails, all other remaining
2178 * compounded requests should fail too
2180 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
2182 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
2186 struct smbd_smb2_send_oplock_break_state
{
2187 struct smbd_server_connection
*sconn
;
2188 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x18];
2189 struct iovec vector
;
2192 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
);
2194 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
2195 uint64_t file_id_persistent
,
2196 uint64_t file_id_volatile
,
2197 uint8_t oplock_level
)
2199 struct smbd_smb2_send_oplock_break_state
*state
;
2200 struct tevent_req
*subreq
;
2204 state
= talloc(sconn
, struct smbd_smb2_send_oplock_break_state
);
2205 if (state
== NULL
) {
2206 return NT_STATUS_NO_MEMORY
;
2208 state
->sconn
= sconn
;
2210 state
->vector
.iov_base
= (void *)state
->buf
;
2211 state
->vector
.iov_len
= sizeof(state
->buf
);
2213 _smb2_setlen(state
->buf
, sizeof(state
->buf
) - 4);
2214 hdr
= state
->buf
+ 4;
2215 body
= hdr
+ SMB2_HDR_BODY
;
2217 SIVAL(hdr
, 0, SMB2_MAGIC
);
2218 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
2219 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
2220 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
2221 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
2222 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
2223 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
2224 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
2225 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
2226 SIVAL(hdr
, SMB2_HDR_PID
, 0);
2227 SIVAL(hdr
, SMB2_HDR_TID
, 0);
2228 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
2229 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
2231 SSVAL(body
, 0x00, 0x18);
2233 SCVAL(body
, 0x02, oplock_level
);
2234 SCVAL(body
, 0x03, 0); /* reserved */
2235 SIVAL(body
, 0x04, 0); /* reserved */
2236 SBVAL(body
, 0x08, file_id_persistent
);
2237 SBVAL(body
, 0x10, file_id_volatile
);
2239 subreq
= tstream_writev_queue_send(state
,
2242 sconn
->smb2
.send_queue
,
2244 if (subreq
== NULL
) {
2245 return NT_STATUS_NO_MEMORY
;
2247 tevent_req_set_callback(subreq
,
2248 smbd_smb2_oplock_break_writev_done
,
2251 return NT_STATUS_OK
;
2254 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
)
2256 struct smbd_smb2_send_oplock_break_state
*state
=
2257 tevent_req_callback_data(subreq
,
2258 struct smbd_smb2_send_oplock_break_state
);
2259 struct smbd_server_connection
*sconn
= state
->sconn
;
2263 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
2264 TALLOC_FREE(subreq
);
2266 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
2267 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2274 struct smbd_smb2_request_read_state
{
2276 bool asked_for_header
;
2277 struct smbd_smb2_request
*smb2_req
;
2280 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2282 TALLOC_CTX
*mem_ctx
,
2283 struct iovec
**_vector
,
2285 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
);
2287 static struct tevent_req
*smbd_smb2_request_read_send(TALLOC_CTX
*mem_ctx
,
2288 struct tevent_context
*ev
,
2289 struct smbd_server_connection
*sconn
)
2291 struct tevent_req
*req
;
2292 struct smbd_smb2_request_read_state
*state
;
2293 struct tevent_req
*subreq
;
2295 req
= tevent_req_create(mem_ctx
, &state
,
2296 struct smbd_smb2_request_read_state
);
2301 state
->asked_for_header
= false;
2303 state
->smb2_req
= smbd_smb2_request_allocate(state
);
2304 if (tevent_req_nomem(state
->smb2_req
, req
)) {
2305 return tevent_req_post(req
, ev
);
2307 state
->smb2_req
->sconn
= sconn
;
2309 subreq
= tstream_readv_pdu_queue_send(state
, ev
, sconn
->smb2
.stream
,
2310 sconn
->smb2
.recv_queue
,
2311 smbd_smb2_request_next_vector
,
2313 if (tevent_req_nomem(subreq
, req
)) {
2314 return tevent_req_post(req
, ev
);
2316 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
2321 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2323 TALLOC_CTX
*mem_ctx
,
2324 struct iovec
**_vector
,
2327 struct smbd_smb2_request_read_state
*state
=
2328 talloc_get_type_abort(private_data
,
2329 struct smbd_smb2_request_read_state
);
2330 struct smbd_smb2_request
*req
= state
->smb2_req
;
2331 struct iovec
*vector
;
2332 int idx
= req
->in
.vector_count
;
2334 uint8_t *buf
= NULL
;
2336 if (req
->in
.vector_count
== 0) {
2338 * first we need to get the NBT header
2340 req
->in
.vector
= talloc_array(req
, struct iovec
,
2341 req
->in
.vector_count
+ 1);
2342 if (req
->in
.vector
== NULL
) {
2345 req
->in
.vector_count
+= 1;
2347 req
->in
.vector
[idx
].iov_base
= (void *)req
->in
.nbt_hdr
;
2348 req
->in
.vector
[idx
].iov_len
= 4;
2350 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2351 if (vector
== NULL
) {
2355 vector
[0] = req
->in
.vector
[idx
];
2362 if (req
->in
.vector_count
== 1) {
2364 * Now we analyze the NBT header
2366 state
->missing
= smb2_len(req
->in
.vector
[0].iov_base
);
2368 if (state
->missing
== 0) {
2369 /* if there're no remaining bytes, we're done */
2375 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2377 req
->in
.vector_count
+ 1);
2378 if (req
->in
.vector
== NULL
) {
2381 req
->in
.vector_count
+= 1;
2383 if (CVAL(req
->in
.vector
[0].iov_base
, 0) != 0) {
2385 * it's a special NBT message,
2386 * so get all remaining bytes
2388 len
= state
->missing
;
2389 } else if (state
->missing
< (SMB2_HDR_BODY
+ 2)) {
2391 * it's an invalid message, just read what we can get
2392 * and let the caller handle the error
2394 len
= state
->missing
;
2397 * We assume it's a SMB2 request,
2398 * and we first get the header and the
2399 * first 2 bytes (the struct size) of the body
2401 len
= SMB2_HDR_BODY
+ 2;
2403 state
->asked_for_header
= true;
2406 state
->missing
-= len
;
2408 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2413 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2414 req
->in
.vector
[idx
].iov_len
= len
;
2416 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2417 if (vector
== NULL
) {
2421 vector
[0] = req
->in
.vector
[idx
];
2428 if (state
->missing
== 0) {
2429 /* if there're no remaining bytes, we're done */
2435 if (state
->asked_for_header
) {
2438 size_t next_command_ofs
;
2443 bool invalid
= false;
2445 state
->asked_for_header
= false;
2448 * We got the SMB2 header and the first 2 bytes
2449 * of the body. We fix the size to just the header
2450 * and manually copy the 2 first bytes to the body section
2452 req
->in
.vector
[idx
-1].iov_len
= SMB2_HDR_BODY
;
2453 hdr
= (const uint8_t *)req
->in
.vector
[idx
-1].iov_base
;
2455 /* allocate vectors for body and dynamic areas */
2456 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2458 req
->in
.vector_count
+ 2);
2459 if (req
->in
.vector
== NULL
) {
2462 req
->in
.vector_count
+= 2;
2464 full_size
= state
->missing
+ SMB2_HDR_BODY
+ 2;
2465 next_command_ofs
= IVAL(hdr
, SMB2_HDR_NEXT_COMMAND
);
2466 body_size
= SVAL(hdr
, SMB2_HDR_BODY
);
2468 if (next_command_ofs
!= 0) {
2469 if (next_command_ofs
< (SMB2_HDR_BODY
+ 2)) {
2471 * this is invalid, just return a zero
2472 * body and let the caller deal with the error
2475 } else if (next_command_ofs
> full_size
) {
2477 * this is invalid, just return a zero
2478 * body and let the caller deal with the error
2482 full_size
= next_command_ofs
;
2487 if (body_size
< 2) {
2489 * this is invalid, just return a zero
2490 * body and let the caller deal with the error
2496 * Mask out the lowest bit, the "dynamic" part
2501 if (body_size
> (full_size
- SMB2_HDR_BODY
)) {
2503 * this is invalid, just return a zero
2504 * body and let the caller deal with the error
2511 /* the caller should check this */
2515 dyn_size
= full_size
- (SMB2_HDR_BODY
+ body_size
);
2517 state
->missing
-= (body_size
- 2) + dyn_size
;
2519 body
= talloc_array(req
->in
.vector
, uint8_t, body_size
);
2524 dyn
= talloc_array(req
->in
.vector
, uint8_t, dyn_size
);
2529 req
->in
.vector
[idx
].iov_base
= (void *)body
;
2530 req
->in
.vector
[idx
].iov_len
= body_size
;
2531 req
->in
.vector
[idx
+1].iov_base
= (void *)dyn
;
2532 req
->in
.vector
[idx
+1].iov_len
= dyn_size
;
2534 vector
= talloc_array(mem_ctx
, struct iovec
, 2);
2535 if (vector
== NULL
) {
2540 * the first 2 bytes of the body were already fetched
2541 * together with the header
2543 memcpy(body
, hdr
+ SMB2_HDR_BODY
, 2);
2544 vector
[0].iov_base
= body
+ 2;
2545 vector
[0].iov_len
= body_size
- 2;
2547 vector
[1] = req
->in
.vector
[idx
+1];
2555 * when we endup here, we're looking for a new SMB2 request
2556 * next. And we ask for its header and the first 2 bytes of
2557 * the body (like we did for the first SMB2 request).
2560 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2562 req
->in
.vector_count
+ 1);
2563 if (req
->in
.vector
== NULL
) {
2566 req
->in
.vector_count
+= 1;
2569 * We assume it's a SMB2 request,
2570 * and we first get the header and the
2571 * first 2 bytes (the struct size) of the body
2573 len
= SMB2_HDR_BODY
+ 2;
2575 if (len
> state
->missing
) {
2576 /* let the caller handle the error */
2577 len
= state
->missing
;
2580 state
->missing
-= len
;
2581 state
->asked_for_header
= true;
2583 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2588 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2589 req
->in
.vector
[idx
].iov_len
= len
;
2591 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2592 if (vector
== NULL
) {
2596 vector
[0] = req
->in
.vector
[idx
];
2603 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
)
2605 struct tevent_req
*req
=
2606 tevent_req_callback_data(subreq
,
2612 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
2614 status
= map_nt_error_from_unix(sys_errno
);
2615 tevent_req_nterror(req
, status
);
2619 tevent_req_done(req
);
2622 static NTSTATUS
smbd_smb2_request_read_recv(struct tevent_req
*req
,
2623 TALLOC_CTX
*mem_ctx
,
2624 struct smbd_smb2_request
**_smb2_req
)
2626 struct smbd_smb2_request_read_state
*state
=
2627 tevent_req_data(req
,
2628 struct smbd_smb2_request_read_state
);
2631 if (tevent_req_is_nterror(req
, &status
)) {
2632 tevent_req_received(req
);
2636 talloc_steal(mem_ctx
, state
->smb2_req
->mem_pool
);
2637 *_smb2_req
= state
->smb2_req
;
2638 tevent_req_received(req
);
2639 return NT_STATUS_OK
;
2642 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
);
2644 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
)
2646 size_t max_send_queue_len
;
2647 size_t cur_send_queue_len
;
2648 struct tevent_req
*subreq
;
2650 if (sconn
->smb2
.compound_related_in_progress
) {
2652 * Can't read another until the related
2655 return NT_STATUS_OK
;
2658 if (tevent_queue_length(sconn
->smb2
.recv_queue
) > 0) {
2660 * if there is already a smbd_smb2_request_read
2661 * pending, we are done.
2663 return NT_STATUS_OK
;
2666 max_send_queue_len
= MAX(1, sconn
->smb2
.max_credits
/16);
2667 cur_send_queue_len
= tevent_queue_length(sconn
->smb2
.send_queue
);
2669 if (cur_send_queue_len
> max_send_queue_len
) {
2671 * if we have a lot of requests to send,
2672 * we wait until they are on the wire until we
2673 * ask for the next request.
2675 return NT_STATUS_OK
;
2678 /* ask for the next request */
2679 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->ev_ctx
, sconn
);
2680 if (subreq
== NULL
) {
2681 return NT_STATUS_NO_MEMORY
;
2683 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);
2685 return NT_STATUS_OK
;
2688 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
2689 const uint8_t *inbuf
, size_t size
)
2692 struct smbd_smb2_request
*req
= NULL
;
2694 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2695 (unsigned int)size
));
2697 status
= smbd_initialize_smb2(sconn
);
2698 if (!NT_STATUS_IS_OK(status
)) {
2699 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2703 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
2704 if (!NT_STATUS_IS_OK(status
)) {
2705 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2709 status
= smbd_smb2_request_setup_out(req
);
2710 if (!NT_STATUS_IS_OK(status
)) {
2711 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2715 status
= smbd_smb2_request_dispatch(req
);
2716 if (!NT_STATUS_IS_OK(status
)) {
2717 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2721 status
= smbd_smb2_request_next_incoming(sconn
);
2722 if (!NT_STATUS_IS_OK(status
)) {
2723 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2727 sconn
->num_requests
++;
2730 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
)
2732 struct smbd_server_connection
*sconn
= tevent_req_callback_data(subreq
,
2733 struct smbd_server_connection
);
2735 struct smbd_smb2_request
*req
= NULL
;
2737 status
= smbd_smb2_request_read_recv(subreq
, sconn
, &req
);
2738 TALLOC_FREE(subreq
);
2739 if (!NT_STATUS_IS_OK(status
)) {
2740 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2741 nt_errstr(status
)));
2742 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2746 if (req
->in
.nbt_hdr
[0] != 0x00) {
2747 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2748 req
->in
.nbt_hdr
[0]));
2753 req
->current_idx
= 1;
2755 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2756 req
->current_idx
, req
->in
.vector_count
));
2758 status
= smbd_smb2_request_validate(req
);
2759 if (!NT_STATUS_IS_OK(status
)) {
2760 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2764 status
= smbd_smb2_request_setup_out(req
);
2765 if (!NT_STATUS_IS_OK(status
)) {
2766 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2770 status
= smbd_smb2_request_dispatch(req
);
2771 if (!NT_STATUS_IS_OK(status
)) {
2772 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2777 status
= smbd_smb2_request_next_incoming(sconn
);
2778 if (!NT_STATUS_IS_OK(status
)) {
2779 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2783 sconn
->num_requests
++;
2785 /* The timeout_processing function isn't run nearly
2786 often enough to implement 'max log size' without
2787 overrunning the size of the file by many megabytes.
2788 This is especially true if we are running at debug
2789 level 10. Checking every 50 SMB2s is a nice
2790 tradeoff of performance vs log file size overrun. */
2792 if ((sconn
->num_requests
% 50) == 0 &&
2793 need_to_check_log_size()) {
2794 change_to_root_user();