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
.seqnum_low
= 0;
112 sconn
->smb2
.credits_granted
= 1;
113 sconn
->smb2
.max_credits
= lp_smb2_max_credits();
114 sconn
->smb2
.credits_bitmap
= bitmap_talloc(sconn
,
115 sconn
->smb2
.max_credits
);
116 if (sconn
->smb2
.credits_bitmap
== NULL
) {
117 return NT_STATUS_NO_MEMORY
;
120 ret
= tstream_bsd_existing_socket(sconn
, sconn
->sock
,
121 &sconn
->smb2
.stream
);
123 status
= map_nt_error_from_unix(errno
);
127 /* Ensure child is set to non-blocking mode */
128 set_blocking(sconn
->sock
, false);
132 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
133 #define _smb2_setlen(_buf,len) do { \
134 uint8_t *buf = (uint8_t *)_buf; \
136 buf[1] = ((len)&0xFF0000)>>16; \
137 buf[2] = ((len)&0xFF00)>>8; \
138 buf[3] = (len)&0xFF; \
141 static void smb2_setup_nbt_length(struct iovec
*vector
, int count
)
146 for (i
=1; i
< count
; i
++) {
147 len
+= vector
[i
].iov_len
;
150 _smb2_setlen(vector
[0].iov_base
, len
);
153 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request
**req
)
156 (*req
)->parent
= NULL
;
157 (*req
)->mem_pool
= NULL
;
163 static int smbd_smb2_request_destructor(struct smbd_smb2_request
*req
)
167 talloc_free(req
->mem_pool
);
173 static struct smbd_smb2_request
*smbd_smb2_request_allocate(TALLOC_CTX
*mem_ctx
)
175 TALLOC_CTX
*mem_pool
;
176 struct smbd_smb2_request
**parent
;
177 struct smbd_smb2_request
*req
;
180 /* Enable this to find subtle valgrind errors. */
181 mem_pool
= talloc_init("smbd_smb2_request_allocate");
183 mem_pool
= talloc_pool(mem_ctx
, 8192);
185 if (mem_pool
== NULL
) {
189 parent
= talloc(mem_pool
, struct smbd_smb2_request
*);
190 if (parent
== NULL
) {
191 talloc_free(mem_pool
);
195 req
= talloc_zero(parent
, struct smbd_smb2_request
);
197 talloc_free(mem_pool
);
201 req
->mem_pool
= mem_pool
;
202 req
->parent
= parent
;
204 req
->last_session_id
= UINT64_MAX
;
205 req
->last_tid
= UINT32_MAX
;
207 talloc_set_destructor(parent
, smbd_smb2_request_parent_destructor
);
208 talloc_set_destructor(req
, smbd_smb2_request_destructor
);
213 static NTSTATUS
smbd_smb2_request_create(struct smbd_server_connection
*sconn
,
214 const uint8_t *inbuf
, size_t size
,
215 struct smbd_smb2_request
**_req
)
217 struct smbd_smb2_request
*req
;
218 uint32_t protocol_version
;
219 const uint8_t *inhdr
= NULL
;
222 uint32_t next_command_ofs
;
224 if (size
< (4 + SMB2_HDR_BODY
+ 2)) {
225 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size
));
226 return NT_STATUS_INVALID_PARAMETER
;
231 protocol_version
= IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
);
232 if (protocol_version
!= SMB2_MAGIC
) {
233 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
235 return NT_STATUS_INVALID_PARAMETER
;
238 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
239 if (cmd
!= SMB2_OP_NEGPROT
) {
240 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
242 return NT_STATUS_INVALID_PARAMETER
;
245 next_command_ofs
= IVAL(inhdr
, SMB2_HDR_NEXT_COMMAND
);
246 if (next_command_ofs
!= 0) {
247 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
249 return NT_STATUS_INVALID_PARAMETER
;
252 req
= smbd_smb2_request_allocate(sconn
);
254 return NT_STATUS_NO_MEMORY
;
258 talloc_steal(req
, inbuf
);
260 req
->in
.vector
= talloc_array(req
, struct iovec
, 4);
261 if (req
->in
.vector
== NULL
) {
263 return NT_STATUS_NO_MEMORY
;
265 req
->in
.vector_count
= 4;
267 memcpy(req
->in
.nbt_hdr
, inbuf
, 4);
270 req
->in
.vector
[0].iov_base
= discard_const_p(void, req
->in
.nbt_hdr
);
271 req
->in
.vector
[0].iov_len
= 4;
272 ofs
+= req
->in
.vector
[0].iov_len
;
274 req
->in
.vector
[1].iov_base
= discard_const_p(void, (inbuf
+ ofs
));
275 req
->in
.vector
[1].iov_len
= SMB2_HDR_BODY
;
276 ofs
+= req
->in
.vector
[1].iov_len
;
278 req
->in
.vector
[2].iov_base
= discard_const_p(void, (inbuf
+ ofs
));
279 req
->in
.vector
[2].iov_len
= SVAL(inbuf
, ofs
) & 0xFFFE;
280 ofs
+= req
->in
.vector
[2].iov_len
;
283 return NT_STATUS_INVALID_PARAMETER
;
286 req
->in
.vector
[3].iov_base
= discard_const_p(void, (inbuf
+ ofs
));
287 req
->in
.vector
[3].iov_len
= size
- ofs
;
288 ofs
+= req
->in
.vector
[3].iov_len
;
290 req
->current_idx
= 1;
296 static bool smb2_validate_sequence_number(struct smbd_server_connection
*sconn
,
297 uint64_t message_id
, uint64_t seq_id
)
299 struct bitmap
*credits_bm
= sconn
->smb2
.credits_bitmap
;
302 if (seq_id
< sconn
->smb2
.seqnum_low
) {
303 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
304 "%llu (sequence id %llu) (low = %llu, max = %lu)\n",
305 (unsigned long long)message_id
,
306 (unsigned long long)seq_id
,
307 (unsigned long long)sconn
->smb2
.seqnum_low
,
308 (unsigned long)sconn
->smb2
.max_credits
));
312 if (seq_id
> (sconn
->smb2
.seqnum_low
+ sconn
->smb2
.max_credits
)) {
313 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
314 "%llu (sequence id %llu) (low = %llu, max = %lu)\n",
315 (unsigned long long)message_id
,
316 (unsigned long long)seq_id
,
317 (unsigned long long)sconn
->smb2
.seqnum_low
,
318 (unsigned long)sconn
->smb2
.max_credits
));
322 offset
= seq_id
% sconn
->smb2
.max_credits
;
324 if (bitmap_query(credits_bm
, offset
)) {
325 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
326 "%llu (sequence id %llu) (low = %llu, max = %lu) "
328 (unsigned long long)message_id
,
329 (unsigned long long)seq_id
,
330 (unsigned long long)sconn
->smb2
.seqnum_low
,
331 (unsigned long)sconn
->smb2
.max_credits
,
336 /* Mark the message_ids as seen in the bitmap. */
337 bitmap_set(credits_bm
, offset
);
339 if (seq_id
!= sconn
->smb2
.seqnum_low
) {
344 * Move the window forward by all the message_id's
347 while (bitmap_query(credits_bm
, offset
)) {
348 DEBUG(10,("smb2_validate_sequence_number: clearing "
349 "id %llu (position %u) from bitmap\n",
350 (unsigned long long)(sconn
->smb2
.seqnum_low
),
352 bitmap_clear(credits_bm
, offset
);
354 sconn
->smb2
.seqnum_low
+= 1;
355 offset
= sconn
->smb2
.seqnum_low
% sconn
->smb2
.max_credits
;
361 static bool smb2_validate_message_id(struct smbd_server_connection
*sconn
,
362 const uint8_t *inhdr
)
364 uint64_t message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
365 uint16_t opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
366 uint16_t credit_charge
= 1;
369 if (opcode
== SMB2_OP_CANCEL
) {
370 /* SMB2_CANCEL requests by definition resend messageids. */
374 if (sconn
->smb2
.credits_granted
== 0) {
375 DEBUG(0,("smb2_validate_message_id: client used more "
376 "credits than granted, message_id (%llu)\n",
377 (unsigned long long)message_id
));
381 if (sconn
->smb2
.supports_multicredit
) {
382 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
383 credit_charge
= MAX(credit_charge
, 1);
386 DEBUG(11, ("smb2_validate_message_id: mid %llu, credits_granted %llu, "
387 "charge %llu, max_credits %llu, seqnum_low: %llu\n",
388 (unsigned long long) message_id
,
389 (unsigned long long) sconn
->smb2
.credits_granted
,
390 (unsigned long long) credit_charge
,
391 (unsigned long long) sconn
->smb2
.max_credits
,
392 (unsigned long long) sconn
->smb2
.seqnum_low
));
395 * now check the message ids
397 * for multi-credit requests we need to check all current mid plus
398 * the implicit mids caused by the credit charge
399 * e.g. current mid = 15, charge 5 => mark 15-19 as used
402 for (i
= 0; i
<= (credit_charge
-1); i
++) {
403 uint64_t id
= message_id
+ i
;
406 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
407 (unsigned long long)message_id
,
409 (unsigned long long)id
));
411 ok
= smb2_validate_sequence_number(sconn
, message_id
, id
);
417 /* substract used credits */
418 sconn
->smb2
.credits_granted
-= credit_charge
;
423 static NTSTATUS
smbd_smb2_request_validate(struct smbd_smb2_request
*req
)
428 count
= req
->in
.vector_count
;
431 /* It's not a SMB2 request */
432 return NT_STATUS_INVALID_PARAMETER
;
435 for (idx
=1; idx
< count
; idx
+= 3) {
436 const uint8_t *inhdr
= NULL
;
439 if (req
->in
.vector
[idx
].iov_len
!= SMB2_HDR_BODY
) {
440 return NT_STATUS_INVALID_PARAMETER
;
443 if (req
->in
.vector
[idx
+1].iov_len
< 2) {
444 return NT_STATUS_INVALID_PARAMETER
;
447 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
449 /* Check the SMB2 header */
450 if (IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
) != SMB2_MAGIC
) {
451 return NT_STATUS_INVALID_PARAMETER
;
454 if (!smb2_validate_message_id(req
->sconn
, inhdr
)) {
455 return NT_STATUS_INVALID_PARAMETER
;
458 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
461 * the 1st request should never have the
462 * SMB2_HDR_FLAG_CHAINED flag set
464 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
465 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
468 } else if (idx
== 4) {
470 * the 2nd request triggers related vs. unrelated
471 * compounded requests
473 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
474 req
->compound_related
= true;
476 } else if (idx
> 4) {
479 * It seems the this tests are wrong
480 * see the SMB2-COMPOUND test
484 * all other requests should match the 2nd one
486 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
487 if (!req
->compound_related
) {
489 NT_STATUS_INVALID_PARAMETER
;
493 if (req
->compound_related
) {
495 NT_STATUS_INVALID_PARAMETER
;
506 static void smb2_set_operation_credit(struct smbd_server_connection
*sconn
,
507 const struct iovec
*in_vector
,
508 struct iovec
*out_vector
)
510 const uint8_t *inhdr
= (const uint8_t *)in_vector
->iov_base
;
511 uint8_t *outhdr
= (uint8_t *)out_vector
->iov_base
;
512 uint16_t credits_requested
;
514 uint16_t credits_granted
= 0;
516 credits_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
517 out_flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
519 SMB_ASSERT(sconn
->smb2
.max_credits
>= sconn
->smb2
.credits_granted
);
521 if (out_flags
& SMB2_HDR_FLAG_ASYNC
) {
523 * In case we already send an async interim
524 * response, we should not grant
525 * credits on the final response.
527 credits_requested
= 0;
530 if (credits_requested
) {
531 uint16_t modified_credits_requested
;
535 * Split up max_credits into 1/16ths, and then scale
536 * the requested credits by how many 16ths have been
537 * currently granted. Less than 1/16th == grant all
538 * requested (100%), scale down as more have been
539 * granted. Never ask for less than 1 as the client
540 * asked for at least 1. JRA.
543 multiplier
= 16 - (((sconn
->smb2
.credits_granted
* 16) / sconn
->smb2
.max_credits
) % 16);
545 modified_credits_requested
= (multiplier
* credits_requested
) / 16;
546 if (modified_credits_requested
== 0) {
547 modified_credits_requested
= 1;
550 /* Remember what we gave out. */
551 credits_granted
= MIN(modified_credits_requested
,
552 (sconn
->smb2
.max_credits
- sconn
->smb2
.credits_granted
));
555 if (credits_granted
== 0 && sconn
->smb2
.credits_granted
== 0) {
556 /* First negprot packet, or ensure the client credits can
557 never drop to zero. */
561 SSVAL(outhdr
, SMB2_HDR_CREDIT
, credits_granted
);
562 sconn
->smb2
.credits_granted
+= credits_granted
;
564 DEBUG(10,("smb2_set_operation_credit: requested %u, "
565 "granted %u, total granted %u\n",
566 (unsigned int)credits_requested
,
567 (unsigned int)credits_granted
,
568 (unsigned int)sconn
->smb2
.credits_granted
));
571 static void smb2_calculate_credits(const struct smbd_smb2_request
*inreq
,
572 struct smbd_smb2_request
*outreq
)
575 uint16_t total_credits
= 0;
577 count
= outreq
->out
.vector_count
;
579 for (idx
=1; idx
< count
; idx
+= 3) {
580 uint8_t *outhdr
= (uint8_t *)outreq
->out
.vector
[idx
].iov_base
;
581 smb2_set_operation_credit(outreq
->sconn
,
582 &inreq
->in
.vector
[idx
],
583 &outreq
->out
.vector
[idx
]);
584 /* To match Windows, count up what we
586 total_credits
+= SVAL(outhdr
, SMB2_HDR_CREDIT
);
587 /* Set to zero in all but the last reply. */
588 if (idx
+ 3 < count
) {
589 SSVAL(outhdr
, SMB2_HDR_CREDIT
, 0);
591 SSVAL(outhdr
, SMB2_HDR_CREDIT
, total_credits
);
596 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
)
598 struct iovec
*vector
;
602 req
->request_time
= timeval_current();
604 count
= req
->in
.vector_count
;
605 vector
= talloc_zero_array(req
, struct iovec
, count
);
606 if (vector
== NULL
) {
607 return NT_STATUS_NO_MEMORY
;
610 vector
[0].iov_base
= req
->out
.nbt_hdr
;
611 vector
[0].iov_len
= 4;
612 SIVAL(req
->out
.nbt_hdr
, 0, 0);
614 for (idx
=1; idx
< count
; idx
+= 3) {
615 const uint8_t *inhdr
= NULL
;
616 uint8_t *outhdr
= NULL
;
617 uint8_t *outbody
= NULL
;
618 uint32_t next_command_ofs
= 0;
619 struct iovec
*current
= &vector
[idx
];
621 if ((idx
+ 3) < count
) {
622 /* we have a next command -
623 * setup for the error case. */
624 next_command_ofs
= SMB2_HDR_BODY
+ 9;
627 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
629 outhdr
= talloc_zero_array(vector
, uint8_t,
631 if (outhdr
== NULL
) {
632 return NT_STATUS_NO_MEMORY
;
635 outbody
= outhdr
+ SMB2_HDR_BODY
;
637 current
[0].iov_base
= (void *)outhdr
;
638 current
[0].iov_len
= SMB2_HDR_BODY
;
640 current
[1].iov_base
= (void *)outbody
;
641 current
[1].iov_len
= 8;
643 current
[2].iov_base
= NULL
;
644 current
[2].iov_len
= 0;
646 /* setup the SMB2 header */
647 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
648 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
649 SSVAL(outhdr
, SMB2_HDR_CREDIT_CHARGE
,
650 SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
));
651 SIVAL(outhdr
, SMB2_HDR_STATUS
,
652 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
653 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
654 SVAL(inhdr
, SMB2_HDR_OPCODE
));
655 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
656 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
657 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
658 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
659 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
660 SIVAL(outhdr
, SMB2_HDR_PID
,
661 IVAL(inhdr
, SMB2_HDR_PID
));
662 SIVAL(outhdr
, SMB2_HDR_TID
,
663 IVAL(inhdr
, SMB2_HDR_TID
));
664 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
665 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
666 memcpy(outhdr
+ SMB2_HDR_SIGNATURE
,
667 inhdr
+ SMB2_HDR_SIGNATURE
, 16);
669 /* setup error body header */
670 SSVAL(outbody
, 0x00, 0x08 + 1);
671 SSVAL(outbody
, 0x02, 0);
672 SIVAL(outbody
, 0x04, 0);
675 req
->out
.vector
= vector
;
676 req
->out
.vector_count
= count
;
678 /* setup the length of the NBT packet */
679 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
681 DLIST_ADD_END(req
->sconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
686 void smbd_server_connection_terminate_ex(struct smbd_server_connection
*sconn
,
688 const char *location
)
690 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
692 exit_server_cleanly(reason
);
695 static bool dup_smb2_vec3(TALLOC_CTX
*ctx
,
696 struct iovec
*outvec
,
697 const struct iovec
*srcvec
)
699 /* vec[0] is always boilerplate and must
700 * be allocated with size OUTVEC_ALLOC_SIZE. */
702 outvec
[0].iov_base
= talloc_memdup(ctx
,
705 if (!outvec
[0].iov_base
) {
708 outvec
[0].iov_len
= SMB2_HDR_BODY
;
711 * If this is a "standard" vec[1] of length 8,
712 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
713 * then duplicate this. Else use talloc_memdup().
716 if (srcvec
[1].iov_len
== 8 &&
717 srcvec
[1].iov_base
==
718 ((uint8_t *)srcvec
[0].iov_base
) +
720 outvec
[1].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
722 outvec
[1].iov_len
= 8;
724 outvec
[1].iov_base
= talloc_memdup(ctx
,
727 if (!outvec
[1].iov_base
) {
730 outvec
[1].iov_len
= srcvec
[1].iov_len
;
734 * If this is a "standard" vec[2] of length 1,
735 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
736 * then duplicate this. Else use talloc_memdup().
739 if (srcvec
[2].iov_base
&&
741 if (srcvec
[2].iov_base
==
742 ((uint8_t *)srcvec
[0].iov_base
) +
743 (OUTVEC_ALLOC_SIZE
- 1) &&
744 srcvec
[2].iov_len
== 1) {
745 /* Common SMB2 error packet case. */
746 outvec
[2].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
747 (OUTVEC_ALLOC_SIZE
- 1);
749 outvec
[2].iov_base
= talloc_memdup(ctx
,
752 if (!outvec
[2].iov_base
) {
756 outvec
[2].iov_len
= srcvec
[2].iov_len
;
758 outvec
[2].iov_base
= NULL
;
759 outvec
[2].iov_len
= 0;
764 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
766 struct smbd_smb2_request
*newreq
= NULL
;
767 struct iovec
*outvec
= NULL
;
768 int count
= req
->out
.vector_count
;
771 newreq
= smbd_smb2_request_allocate(req
->sconn
);
776 newreq
->sconn
= req
->sconn
;
777 newreq
->session
= req
->session
;
778 newreq
->do_signing
= req
->do_signing
;
779 newreq
->current_idx
= req
->current_idx
;
781 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
786 newreq
->out
.vector
= outvec
;
787 newreq
->out
.vector_count
= count
;
789 /* Setup the outvec's identically to req. */
790 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
791 outvec
[0].iov_len
= 4;
792 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
794 /* Setup the vectors identically to the ones in req. */
795 for (i
= 1; i
< count
; i
+= 3) {
796 if (!dup_smb2_vec3(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
807 smb2_setup_nbt_length(newreq
->out
.vector
,
808 newreq
->out
.vector_count
);
813 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
);
815 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
818 uint8_t *outhdr
= NULL
;
819 struct smbd_smb2_request
*nreq
= NULL
;
821 /* Create a new smb2 request we'll use
822 for the interim return. */
823 nreq
= dup_smb2_req(req
);
825 return NT_STATUS_NO_MEMORY
;
828 /* Lose the last 3 out vectors. They're the
829 ones we'll be using for the async reply. */
830 nreq
->out
.vector_count
-= 3;
832 smb2_setup_nbt_length(nreq
->out
.vector
,
833 nreq
->out
.vector_count
);
835 /* Step back to the previous reply. */
836 i
= nreq
->current_idx
- 3;
837 outhdr
= (uint8_t *)nreq
->out
.vector
[i
].iov_base
;
838 /* And end the chain. */
839 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
841 /* Calculate outgoing credits */
842 smb2_calculate_credits(req
, nreq
);
844 /* Re-sign if needed. */
845 if (nreq
->do_signing
) {
847 struct smbXsrv_session
*x
= nreq
->session
;
848 struct smbXsrv_connection
*conn
= x
->connection
;
849 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
851 status
= smb2_signing_sign_pdu(signing_key
,
853 &nreq
->out
.vector
[i
], 3);
854 if (!NT_STATUS_IS_OK(status
)) {
858 if (DEBUGLEVEL
>= 10) {
859 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
860 (unsigned int)nreq
->current_idx
);
861 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
862 (unsigned int)nreq
->out
.vector_count
);
863 print_req_vectors(nreq
);
865 nreq
->subreq
= tstream_writev_queue_send(nreq
,
867 nreq
->sconn
->smb2
.stream
,
868 nreq
->sconn
->smb2
.send_queue
,
870 nreq
->out
.vector_count
);
872 if (nreq
->subreq
== NULL
) {
873 return NT_STATUS_NO_MEMORY
;
876 tevent_req_set_callback(nreq
->subreq
,
877 smbd_smb2_request_writev_done
,
883 struct smbd_smb2_request_pending_state
{
884 struct smbd_server_connection
*sconn
;
885 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x08 + 1];
886 struct iovec vector
[3];
889 static void smbd_smb2_request_pending_writev_done(struct tevent_req
*subreq
)
891 struct smbd_smb2_request_pending_state
*state
=
892 tevent_req_callback_data(subreq
,
893 struct smbd_smb2_request_pending_state
);
894 struct smbd_server_connection
*sconn
= state
->sconn
;
898 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
901 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
902 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
909 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
910 struct tevent_timer
*te
,
911 struct timeval current_time
,
914 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
915 struct tevent_req
*subreq
,
919 int i
= req
->current_idx
;
920 struct timeval defer_endtime
;
921 uint8_t *outhdr
= NULL
;
924 if (!tevent_req_is_in_progress(subreq
)) {
928 req
->subreq
= subreq
;
932 /* We're already async. */
936 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
937 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
938 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
939 /* We're already async. */
943 if (req
->in
.vector_count
> i
+ 3) {
945 * We're trying to go async in a compound
946 * request chain. This is not allowed.
947 * Cancel the outstanding request.
949 tevent_req_cancel(req
->subreq
);
950 return smbd_smb2_request_error(req
,
951 NT_STATUS_INSUFFICIENT_RESOURCES
);
954 if (DEBUGLEVEL
>= 10) {
955 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
956 (unsigned int)req
->current_idx
);
957 print_req_vectors(req
);
960 if (req
->out
.vector_count
> 4) {
961 struct iovec
*outvec
= NULL
;
963 /* This is a compound reply. We
964 * must do an interim response
965 * followed by the async response
968 status
= smb2_send_async_interim_response(req
);
969 if (!NT_STATUS_IS_OK(status
)) {
974 * We're splitting off the last SMB2
975 * request in a compound set, and the
976 * smb2_send_async_interim_response()
977 * call above just sent all the replies
978 * for the previous SMB2 requests in
979 * this compound set. So we're no longer
980 * in the "compound_related_in_progress"
981 * state, and this is no longer a compound
984 req
->compound_related
= false;
985 req
->sconn
->smb2
.compound_related_in_progress
= false;
987 /* Re-arrange the in.vectors. */
988 req
->in
.vector
[1] = req
->in
.vector
[i
];
989 req
->in
.vector
[2] = req
->in
.vector
[i
+1];
990 req
->in
.vector
[3] = req
->in
.vector
[i
+2];
991 req
->in
.vector_count
= 4;
993 /* Reset the new in size. */
994 smb2_setup_nbt_length(req
->in
.vector
, 4);
996 /* Now recreate the out.vectors. */
997 outvec
= talloc_zero_array(req
, struct iovec
, 4);
999 return NT_STATUS_NO_MEMORY
;
1002 /* 0 is always boilerplate and must
1003 * be of size 4 for the length field. */
1005 outvec
[0].iov_base
= req
->out
.nbt_hdr
;
1006 outvec
[0].iov_len
= 4;
1007 SIVAL(req
->out
.nbt_hdr
, 0, 0);
1009 if (!dup_smb2_vec3(outvec
, &outvec
[1], &req
->out
.vector
[i
])) {
1010 return NT_STATUS_NO_MEMORY
;
1013 TALLOC_FREE(req
->out
.vector
);
1015 req
->out
.vector
= outvec
;
1017 req
->current_idx
= 1;
1018 req
->out
.vector_count
= 4;
1020 outhdr
= (uint8_t *)req
->out
.vector
[1].iov_base
;
1021 flags
= (IVAL(outhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
1022 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
);
1025 defer_endtime
= timeval_current_ofs_usec(defer_time
);
1026 req
->async_te
= tevent_add_timer(req
->sconn
->ev_ctx
,
1028 smbd_smb2_request_pending_timer
,
1030 if (req
->async_te
== NULL
) {
1031 return NT_STATUS_NO_MEMORY
;
1034 return NT_STATUS_OK
;
1037 static void smbd_smb2_request_pending_timer(struct tevent_context
*ev
,
1038 struct tevent_timer
*te
,
1039 struct timeval current_time
,
1042 struct smbd_smb2_request
*req
=
1043 talloc_get_type_abort(private_data
,
1044 struct smbd_smb2_request
);
1045 struct smbd_smb2_request_pending_state
*state
= NULL
;
1046 int i
= req
->current_idx
;
1047 uint8_t *outhdr
= NULL
;
1048 const uint8_t *inhdr
= NULL
;
1049 uint8_t *hdr
= NULL
;
1050 uint8_t *body
= NULL
;
1052 uint64_t message_id
= 0;
1053 uint64_t async_id
= 0;
1054 struct tevent_req
*subreq
= NULL
;
1056 TALLOC_FREE(req
->async_te
);
1058 /* Ensure our final reply matches the interim one. */
1059 inhdr
= (const uint8_t *)req
->in
.vector
[1].iov_base
;
1060 outhdr
= (uint8_t *)req
->out
.vector
[1].iov_base
;
1061 flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
1062 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1064 async_id
= message_id
; /* keep it simple for now... */
1066 SIVAL(outhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1067 SBVAL(outhdr
, SMB2_HDR_ASYNC_ID
, async_id
);
1069 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1071 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1072 (unsigned long long)async_id
));
1075 * What we send is identical to a smbd_smb2_request_error
1076 * packet with an error status of STATUS_PENDING. Make use
1077 * of this fact sometime when refactoring. JRA.
1080 state
= talloc_zero(req
->sconn
, struct smbd_smb2_request_pending_state
);
1081 if (state
== NULL
) {
1082 smbd_server_connection_terminate(req
->sconn
,
1083 nt_errstr(NT_STATUS_NO_MEMORY
));
1086 state
->sconn
= req
->sconn
;
1088 state
->vector
[0].iov_base
= (void *)state
->buf
;
1089 state
->vector
[0].iov_len
= 4;
1091 state
->vector
[1].iov_base
= state
->buf
+ 4;
1092 state
->vector
[1].iov_len
= SMB2_HDR_BODY
;
1094 state
->vector
[2].iov_base
= state
->buf
+ 4 + SMB2_HDR_BODY
;
1095 state
->vector
[2].iov_len
= 9;
1097 smb2_setup_nbt_length(state
->vector
, 3);
1099 hdr
= (uint8_t *)state
->vector
[1].iov_base
;
1100 body
= (uint8_t *)state
->vector
[2].iov_base
;
1102 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
1103 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1104 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1105 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
1106 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(outhdr
, SMB2_HDR_OPCODE
));
1108 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
);
1109 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1110 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
1111 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
1112 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
1113 BVAL(outhdr
, SMB2_HDR_SESSION_ID
));
1114 memcpy(hdr
+SMB2_HDR_SIGNATURE
,
1115 outhdr
+SMB2_HDR_SIGNATURE
, 16);
1117 SSVAL(body
, 0x00, 0x08 + 1);
1119 SCVAL(body
, 0x02, 0);
1120 SCVAL(body
, 0x03, 0);
1121 SIVAL(body
, 0x04, 0);
1122 /* Match W2K8R2... */
1123 SCVAL(body
, 0x08, 0x21);
1125 /* Ensure we correctly go through crediting. Grant
1126 the credits now, and zero credits on the final
1128 smb2_set_operation_credit(req
->sconn
,
1132 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1134 if (req
->do_signing
) {
1136 struct smbXsrv_session
*x
= req
->session
;
1137 struct smbXsrv_connection
*conn
= x
->connection
;
1138 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
1140 status
= smb2_signing_sign_pdu(signing_key
,
1142 &state
->vector
[1], 2);
1143 if (!NT_STATUS_IS_OK(status
)) {
1144 smbd_server_connection_terminate(req
->sconn
,
1150 subreq
= tstream_writev_queue_send(state
,
1151 state
->sconn
->ev_ctx
,
1152 state
->sconn
->smb2
.stream
,
1153 state
->sconn
->smb2
.send_queue
,
1156 if (subreq
== NULL
) {
1157 smbd_server_connection_terminate(state
->sconn
,
1158 nt_errstr(NT_STATUS_NO_MEMORY
));
1161 tevent_req_set_callback(subreq
,
1162 smbd_smb2_request_pending_writev_done
,
1166 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
1168 struct smbd_server_connection
*sconn
= req
->sconn
;
1169 struct smbd_smb2_request
*cur
;
1170 const uint8_t *inhdr
;
1171 int i
= req
->current_idx
;
1173 uint64_t search_message_id
;
1174 uint64_t search_async_id
;
1177 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1179 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1180 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1181 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
1184 * we don't need the request anymore
1185 * cancel requests never have a response
1187 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1190 for (cur
= sconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
1191 const uint8_t *outhdr
;
1192 uint64_t message_id
;
1195 i
= cur
->current_idx
;
1197 outhdr
= (const uint8_t *)cur
->out
.vector
[i
].iov_base
;
1199 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1200 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
1202 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1203 if (search_async_id
== async_id
) {
1204 found_id
= async_id
;
1208 if (search_message_id
== message_id
) {
1209 found_id
= message_id
;
1215 if (cur
&& cur
->subreq
) {
1216 inhdr
= (const uint8_t *)cur
->in
.vector
[i
].iov_base
;
1217 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1218 "cancel opcode[%s] mid %llu\n",
1219 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1220 (unsigned long long)found_id
));
1221 tevent_req_cancel(cur
->subreq
);
1224 return NT_STATUS_OK
;
1227 /*************************************************************
1228 Ensure an incoming tid is a valid one for us to access.
1229 Change to the associated uid credentials and chdir to the
1230 valid tid directory.
1231 *************************************************************/
1233 static NTSTATUS
smbd_smb2_request_check_tcon(struct smbd_smb2_request
*req
)
1235 const uint8_t *inhdr
;
1236 int i
= req
->current_idx
;
1239 struct smbXsrv_tcon0
*tcon
;
1241 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1245 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1247 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1248 in_tid
= IVAL(inhdr
, SMB2_HDR_TID
);
1250 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1251 in_tid
= req
->last_tid
;
1254 status
= smb2srv_tcon_lookup(req
->session
,
1255 in_tid
, now
, &tcon
);
1256 if (!NT_STATUS_IS_OK(status
)) {
1260 if (!change_to_user(tcon
->compat
, req
->session
->compat
->vuid
)) {
1261 return NT_STATUS_ACCESS_DENIED
;
1264 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1265 if (!set_current_service(tcon
->compat
, 0, true)) {
1266 return NT_STATUS_ACCESS_DENIED
;
1270 req
->last_tid
= in_tid
;
1272 return NT_STATUS_OK
;
1275 /*************************************************************
1276 Ensure an incoming session_id is a valid one for us to access.
1277 *************************************************************/
1279 static NTSTATUS
smbd_smb2_request_check_session(struct smbd_smb2_request
*req
)
1281 const uint8_t *inhdr
;
1282 int i
= req
->current_idx
;
1285 uint64_t in_session_id
;
1286 struct smbXsrv_session
*session
= NULL
;
1287 struct auth_session_info
*session_info
;
1289 NTTIME now
= timeval_to_nttime(&req
->request_time
);
1291 req
->session
= NULL
;
1294 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1296 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1297 in_opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1298 in_session_id
= BVAL(inhdr
, SMB2_HDR_SESSION_ID
);
1300 if (in_flags
& SMB2_HDR_FLAG_CHAINED
) {
1301 in_session_id
= req
->last_session_id
;
1304 /* lookup an existing session */
1305 status
= smb2srv_session_lookup(req
->sconn
->conn
,
1309 req
->session
= session
;
1310 req
->last_session_id
= in_session_id
;
1312 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
1313 switch (in_opcode
) {
1314 case SMB2_OP_SESSSETUP
:
1315 status
= NT_STATUS_OK
;
1321 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1322 switch (in_opcode
) {
1324 case SMB2_OP_CREATE
:
1325 case SMB2_OP_GETINFO
:
1326 case SMB2_OP_SETINFO
:
1327 return NT_STATUS_INVALID_HANDLE
;
1330 * Notice the check for
1331 * (session_info == NULL)
1334 status
= NT_STATUS_OK
;
1338 if (!NT_STATUS_IS_OK(status
)) {
1342 session_info
= session
->global
->auth_session_info
;
1343 if (session_info
== NULL
) {
1344 return NT_STATUS_INVALID_HANDLE
;
1347 set_current_user_info(session_info
->unix_info
->sanitized_username
,
1348 session_info
->unix_info
->unix_name
,
1349 session_info
->info
->domain_name
);
1351 return NT_STATUS_OK
;
1354 NTSTATUS
smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request
*req
,
1355 uint32_t data_length
)
1357 uint16_t needed_charge
;
1358 uint16_t credit_charge
;
1359 const uint8_t *inhdr
;
1360 int i
= req
->current_idx
;
1362 if (!req
->sconn
->smb2
.supports_multicredit
) {
1363 if (data_length
> 65536) {
1364 return NT_STATUS_INVALID_PARAMETER
;
1366 return NT_STATUS_OK
;
1369 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1370 credit_charge
= SVAL(inhdr
, SMB2_HDR_CREDIT_CHARGE
);
1372 /* requests larger than 64 KB need credit charge */
1373 if (credit_charge
== 0 && data_length
> 65536) {
1374 DEBUG(2, ("Request larger than 64KB w/o creditcharge\n"));
1375 return NT_STATUS_INVALID_PARAMETER
;
1378 needed_charge
= (data_length
- 1)/ 65536 + 1;
1380 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1381 (unsigned long long) BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
),
1382 credit_charge
, needed_charge
));
1384 if (needed_charge
> credit_charge
) {
1385 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1386 credit_charge
, needed_charge
));
1387 return NT_STATUS_INVALID_PARAMETER
;
1390 return NT_STATUS_OK
;
1393 NTSTATUS
smbd_smb2_request_verify_sizes(struct smbd_smb2_request
*req
,
1394 size_t expected_body_size
)
1396 const uint8_t *inhdr
;
1398 const uint8_t *inbody
;
1399 int i
= req
->current_idx
;
1401 size_t min_dyn_size
= expected_body_size
& 0x00000001;
1404 * The following should be checked already.
1406 if ((i
+2) > req
->in
.vector_count
) {
1407 return NT_STATUS_INTERNAL_ERROR
;
1409 if (req
->in
.vector
[i
+0].iov_len
!= SMB2_HDR_BODY
) {
1410 return NT_STATUS_INTERNAL_ERROR
;
1412 if (req
->in
.vector
[i
+1].iov_len
< 2) {
1413 return NT_STATUS_INTERNAL_ERROR
;
1416 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1417 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1421 case SMB2_OP_GETINFO
:
1427 * Now check the expected body size,
1428 * where the last byte might be in the
1431 if (req
->in
.vector
[i
+1].iov_len
!= (expected_body_size
& 0xFFFFFFFE)) {
1432 return NT_STATUS_INVALID_PARAMETER
;
1434 if (req
->in
.vector
[i
+2].iov_len
< min_dyn_size
) {
1435 return NT_STATUS_INVALID_PARAMETER
;
1438 inbody
= (const uint8_t *)req
->in
.vector
[i
+1].iov_base
;
1440 body_size
= SVAL(inbody
, 0x00);
1441 if (body_size
!= expected_body_size
) {
1442 return NT_STATUS_INVALID_PARAMETER
;
1445 return NT_STATUS_OK
;
1448 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
1450 const uint8_t *inhdr
;
1451 int i
= req
->current_idx
;
1456 NTSTATUS session_status
;
1457 uint32_t allowed_flags
;
1458 NTSTATUS return_value
;
1459 struct smbXsrv_session
*x
= NULL
;
1460 bool signing_required
= false;
1462 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1464 /* TODO: verify more things */
1466 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1467 opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1468 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1469 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1470 smb2_opcode_name(opcode
),
1471 (unsigned long long)mid
));
1473 if (get_Protocol() >= PROTOCOL_SMB2_02
) {
1475 * once the protocol is negotiated
1476 * SMB2_OP_NEGPROT is not allowed anymore
1478 if (opcode
== SMB2_OP_NEGPROT
) {
1479 /* drop the connection */
1480 return NT_STATUS_INVALID_PARAMETER
;
1484 * if the protocol is not negotiated yet
1485 * only SMB2_OP_NEGPROT is allowed.
1487 if (opcode
!= SMB2_OP_NEGPROT
) {
1488 /* drop the connection */
1489 return NT_STATUS_INVALID_PARAMETER
;
1493 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
1494 SMB2_HDR_FLAG_SIGNED
|
1496 if (opcode
== SMB2_OP_CANCEL
) {
1497 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
1499 if ((flags
& ~allowed_flags
) != 0) {
1500 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1504 * Check if the client provided a valid session id,
1505 * if so smbd_smb2_request_check_session() calls
1506 * set_current_user_info().
1508 * As some command don't require a valid session id
1509 * we defer the check of the session_status
1511 session_status
= smbd_smb2_request_check_session(req
);
1515 signing_required
= x
->global
->signing_required
;
1517 if (opcode
== SMB2_OP_SESSSETUP
&&
1518 x
->global
->channels
[0].signing_key
.length
) {
1519 signing_required
= true;
1523 req
->do_signing
= false;
1524 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
1525 struct smbXsrv_connection
*conn
= x
->connection
;
1526 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
1528 if (!NT_STATUS_IS_OK(session_status
)) {
1529 return smbd_smb2_request_error(req
, session_status
);
1532 req
->do_signing
= true;
1533 status
= smb2_signing_check_pdu(signing_key
,
1535 &req
->in
.vector
[i
], 3);
1536 if (!NT_STATUS_IS_OK(status
)) {
1537 return smbd_smb2_request_error(req
, status
);
1539 } else if (opcode
== SMB2_OP_CANCEL
) {
1540 /* Cancel requests are allowed to skip the signing */
1541 } else if (signing_required
) {
1542 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
1545 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
1547 * This check is mostly for giving the correct error code
1548 * for compounded requests.
1550 * TODO: we may need to move this after the session
1553 if (!NT_STATUS_IS_OK(req
->next_status
)) {
1554 return smbd_smb2_request_error(req
, req
->next_status
);
1557 req
->compat_chain_fsp
= NULL
;
1560 if (req
->compound_related
) {
1561 req
->sconn
->smb2
.compound_related_in_progress
= true;
1565 case SMB2_OP_NEGPROT
:
1566 /* This call needs to be run as root */
1567 change_to_root_user();
1570 START_PROFILE(smb2_negprot
);
1571 return_value
= smbd_smb2_request_process_negprot(req
);
1572 END_PROFILE(smb2_negprot
);
1576 case SMB2_OP_SESSSETUP
:
1577 /* This call needs to be run as root */
1578 change_to_root_user();
1581 START_PROFILE(smb2_sesssetup
);
1582 return_value
= smbd_smb2_request_process_sesssetup(req
);
1583 END_PROFILE(smb2_sesssetup
);
1587 case SMB2_OP_LOGOFF
:
1588 if (!NT_STATUS_IS_OK(session_status
)) {
1589 return_value
= smbd_smb2_request_error(req
, session_status
);
1593 /* This call needs to be run as root */
1594 change_to_root_user();
1597 START_PROFILE(smb2_logoff
);
1598 return_value
= smbd_smb2_request_process_logoff(req
);
1599 END_PROFILE(smb2_logoff
);
1604 if (!NT_STATUS_IS_OK(session_status
)) {
1605 return_value
= smbd_smb2_request_error(req
, session_status
);
1610 * This call needs to be run as root.
1612 * smbd_smb2_request_process_tcon()
1613 * calls make_connection_snum(), which will call
1614 * change_to_user(), when needed.
1616 change_to_root_user();
1619 START_PROFILE(smb2_tcon
);
1620 return_value
= smbd_smb2_request_process_tcon(req
);
1621 END_PROFILE(smb2_tcon
);
1626 if (!NT_STATUS_IS_OK(session_status
)) {
1627 return_value
= smbd_smb2_request_error(req
, session_status
);
1631 * This call needs to be run as user.
1633 * smbd_smb2_request_check_tcon()
1634 * calls change_to_user() on success.
1636 status
= smbd_smb2_request_check_tcon(req
);
1637 if (!NT_STATUS_IS_OK(status
)) {
1638 return_value
= smbd_smb2_request_error(req
, status
);
1641 /* This call needs to be run as root */
1642 change_to_root_user();
1646 START_PROFILE(smb2_tdis
);
1647 return_value
= smbd_smb2_request_process_tdis(req
);
1648 END_PROFILE(smb2_tdis
);
1652 case SMB2_OP_CREATE
:
1653 if (!NT_STATUS_IS_OK(session_status
)) {
1654 return_value
= smbd_smb2_request_error(req
, session_status
);
1658 * This call needs to be run as user.
1660 * smbd_smb2_request_check_tcon()
1661 * calls change_to_user() on success.
1663 status
= smbd_smb2_request_check_tcon(req
);
1664 if (!NT_STATUS_IS_OK(status
)) {
1665 return_value
= smbd_smb2_request_error(req
, status
);
1670 START_PROFILE(smb2_create
);
1671 return_value
= smbd_smb2_request_process_create(req
);
1672 END_PROFILE(smb2_create
);
1677 if (!NT_STATUS_IS_OK(session_status
)) {
1678 return_value
= smbd_smb2_request_error(req
, session_status
);
1682 * This call needs to be run as user.
1684 * smbd_smb2_request_check_tcon()
1685 * calls change_to_user() on success.
1687 status
= smbd_smb2_request_check_tcon(req
);
1688 if (!NT_STATUS_IS_OK(status
)) {
1689 return_value
= smbd_smb2_request_error(req
, status
);
1694 START_PROFILE(smb2_close
);
1695 return_value
= smbd_smb2_request_process_close(req
);
1696 END_PROFILE(smb2_close
);
1701 if (!NT_STATUS_IS_OK(session_status
)) {
1702 return_value
= smbd_smb2_request_error(req
, session_status
);
1706 * This call needs to be run as user.
1708 * smbd_smb2_request_check_tcon()
1709 * calls change_to_user() on success.
1711 status
= smbd_smb2_request_check_tcon(req
);
1712 if (!NT_STATUS_IS_OK(status
)) {
1713 return_value
= smbd_smb2_request_error(req
, status
);
1718 START_PROFILE(smb2_flush
);
1719 return_value
= smbd_smb2_request_process_flush(req
);
1720 END_PROFILE(smb2_flush
);
1725 if (!NT_STATUS_IS_OK(session_status
)) {
1726 return_value
= smbd_smb2_request_error(req
, session_status
);
1730 * This call needs to be run as user.
1732 * smbd_smb2_request_check_tcon()
1733 * calls change_to_user() on success.
1735 status
= smbd_smb2_request_check_tcon(req
);
1736 if (!NT_STATUS_IS_OK(status
)) {
1737 return_value
= smbd_smb2_request_error(req
, status
);
1742 START_PROFILE(smb2_read
);
1743 return_value
= smbd_smb2_request_process_read(req
);
1744 END_PROFILE(smb2_read
);
1749 if (!NT_STATUS_IS_OK(session_status
)) {
1750 return_value
= smbd_smb2_request_error(req
, session_status
);
1754 * This call needs to be run as user.
1756 * smbd_smb2_request_check_tcon()
1757 * calls change_to_user() on success.
1759 status
= smbd_smb2_request_check_tcon(req
);
1760 if (!NT_STATUS_IS_OK(status
)) {
1761 return_value
= smbd_smb2_request_error(req
, status
);
1766 START_PROFILE(smb2_write
);
1767 return_value
= smbd_smb2_request_process_write(req
);
1768 END_PROFILE(smb2_write
);
1773 if (!NT_STATUS_IS_OK(session_status
)) {
1774 /* Too ugly to live ? JRA. */
1775 if (NT_STATUS_EQUAL(session_status
,NT_STATUS_USER_SESSION_DELETED
)) {
1776 session_status
= NT_STATUS_FILE_CLOSED
;
1778 return_value
= smbd_smb2_request_error(req
, session_status
);
1782 * This call needs to be run as user.
1784 * smbd_smb2_request_check_tcon()
1785 * calls change_to_user() on success.
1787 status
= smbd_smb2_request_check_tcon(req
);
1788 if (!NT_STATUS_IS_OK(status
)) {
1789 /* Too ugly to live ? JRA. */
1790 if (NT_STATUS_EQUAL(status
,NT_STATUS_NETWORK_NAME_DELETED
)) {
1791 status
= NT_STATUS_FILE_CLOSED
;
1793 return_value
= smbd_smb2_request_error(req
, status
);
1798 START_PROFILE(smb2_lock
);
1799 return_value
= smbd_smb2_request_process_lock(req
);
1800 END_PROFILE(smb2_lock
);
1805 if (!NT_STATUS_IS_OK(session_status
)) {
1806 return_value
= smbd_smb2_request_error(req
, session_status
);
1810 * This call needs to be run as user.
1812 * smbd_smb2_request_check_tcon()
1813 * calls change_to_user() on success.
1815 status
= smbd_smb2_request_check_tcon(req
);
1816 if (!NT_STATUS_IS_OK(status
)) {
1817 return_value
= smbd_smb2_request_error(req
, status
);
1822 START_PROFILE(smb2_ioctl
);
1823 return_value
= smbd_smb2_request_process_ioctl(req
);
1824 END_PROFILE(smb2_ioctl
);
1828 case SMB2_OP_CANCEL
:
1830 * This call needs to be run as root
1832 * That is what we also do in the SMB1 case.
1834 change_to_root_user();
1837 START_PROFILE(smb2_cancel
);
1838 return_value
= smbd_smb2_request_process_cancel(req
);
1839 END_PROFILE(smb2_cancel
);
1843 case SMB2_OP_KEEPALIVE
:
1844 /* This call needs to be run as root */
1845 change_to_root_user();
1848 START_PROFILE(smb2_keepalive
);
1849 return_value
= smbd_smb2_request_process_keepalive(req
);
1850 END_PROFILE(smb2_keepalive
);
1855 if (!NT_STATUS_IS_OK(session_status
)) {
1856 return_value
= smbd_smb2_request_error(req
, session_status
);
1860 * This call needs to be run as user.
1862 * smbd_smb2_request_check_tcon()
1863 * calls change_to_user() on success.
1865 status
= smbd_smb2_request_check_tcon(req
);
1866 if (!NT_STATUS_IS_OK(status
)) {
1867 return_value
= smbd_smb2_request_error(req
, status
);
1872 START_PROFILE(smb2_find
);
1873 return_value
= smbd_smb2_request_process_find(req
);
1874 END_PROFILE(smb2_find
);
1878 case SMB2_OP_NOTIFY
:
1879 if (!NT_STATUS_IS_OK(session_status
)) {
1880 return_value
= smbd_smb2_request_error(req
, session_status
);
1884 * This call needs to be run as user.
1886 * smbd_smb2_request_check_tcon()
1887 * calls change_to_user() on success.
1889 status
= smbd_smb2_request_check_tcon(req
);
1890 if (!NT_STATUS_IS_OK(status
)) {
1891 return_value
= smbd_smb2_request_error(req
, status
);
1896 START_PROFILE(smb2_notify
);
1897 return_value
= smbd_smb2_request_process_notify(req
);
1898 END_PROFILE(smb2_notify
);
1902 case SMB2_OP_GETINFO
:
1903 if (!NT_STATUS_IS_OK(session_status
)) {
1904 return_value
= smbd_smb2_request_error(req
, session_status
);
1908 * This call needs to be run as user.
1910 * smbd_smb2_request_check_tcon()
1911 * calls change_to_user() on success.
1913 status
= smbd_smb2_request_check_tcon(req
);
1914 if (!NT_STATUS_IS_OK(status
)) {
1915 return_value
= smbd_smb2_request_error(req
, status
);
1920 START_PROFILE(smb2_getinfo
);
1921 return_value
= smbd_smb2_request_process_getinfo(req
);
1922 END_PROFILE(smb2_getinfo
);
1926 case SMB2_OP_SETINFO
:
1927 if (!NT_STATUS_IS_OK(session_status
)) {
1928 return_value
= smbd_smb2_request_error(req
, session_status
);
1932 * This call needs to be run as user.
1934 * smbd_smb2_request_check_tcon()
1935 * calls change_to_user() on success.
1937 status
= smbd_smb2_request_check_tcon(req
);
1938 if (!NT_STATUS_IS_OK(status
)) {
1939 return_value
= smbd_smb2_request_error(req
, status
);
1944 START_PROFILE(smb2_setinfo
);
1945 return_value
= smbd_smb2_request_process_setinfo(req
);
1946 END_PROFILE(smb2_setinfo
);
1951 if (!NT_STATUS_IS_OK(session_status
)) {
1952 return_value
= smbd_smb2_request_error(req
, session_status
);
1956 * This call needs to be run as user.
1958 * smbd_smb2_request_check_tcon()
1959 * calls change_to_user() on success.
1961 status
= smbd_smb2_request_check_tcon(req
);
1962 if (!NT_STATUS_IS_OK(status
)) {
1963 return_value
= smbd_smb2_request_error(req
, status
);
1968 START_PROFILE(smb2_break
);
1969 return_value
= smbd_smb2_request_process_break(req
);
1970 END_PROFILE(smb2_break
);
1975 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1978 return return_value
;
1981 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
1983 struct tevent_req
*subreq
;
1984 int i
= req
->current_idx
;
1987 TALLOC_FREE(req
->async_te
);
1989 req
->current_idx
+= 3;
1991 if (req
->current_idx
< req
->out
.vector_count
) {
1993 * We must process the remaining compound
1994 * SMB2 requests before any new incoming SMB2
1995 * requests. This is because incoming SMB2
1996 * requests may include a cancel for a
1997 * compound request we haven't processed
2000 struct tevent_immediate
*im
= tevent_create_immediate(req
);
2002 return NT_STATUS_NO_MEMORY
;
2004 tevent_schedule_immediate(im
,
2006 smbd_smb2_request_dispatch_immediate
,
2008 return NT_STATUS_OK
;
2011 if (req
->compound_related
) {
2012 req
->sconn
->smb2
.compound_related_in_progress
= false;
2015 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
2017 /* Set credit for these operations (zero credits if this
2018 is a final reply for an async operation). */
2019 smb2_calculate_credits(req
, req
);
2021 if (req
->do_signing
) {
2023 struct smbXsrv_session
*x
= req
->session
;
2024 struct smbXsrv_connection
*conn
= x
->connection
;
2025 DATA_BLOB signing_key
= x
->global
->channels
[0].signing_key
;
2027 status
= smb2_signing_sign_pdu(signing_key
,
2029 &req
->out
.vector
[i
], 3);
2030 if (!NT_STATUS_IS_OK(status
)) {
2035 if (DEBUGLEVEL
>= 10) {
2036 dbgtext("smbd_smb2_request_reply: sending...\n");
2037 print_req_vectors(req
);
2040 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2041 if (req
->out
.vector_count
== 4 &&
2042 req
->out
.vector
[3].iov_base
== NULL
&&
2043 req
->out
.vector
[3].iov_len
!= 0) {
2044 /* Dynamic part is NULL. Chop it off,
2045 We're going to send it via sendfile. */
2046 req
->out
.vector_count
-= 1;
2049 subreq
= tstream_writev_queue_send(req
,
2051 req
->sconn
->smb2
.stream
,
2052 req
->sconn
->smb2
.send_queue
,
2054 req
->out
.vector_count
);
2055 if (subreq
== NULL
) {
2056 return NT_STATUS_NO_MEMORY
;
2058 tevent_req_set_callback(subreq
, smbd_smb2_request_writev_done
, req
);
2060 * We're done with this request -
2061 * move it off the "being processed" queue.
2063 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
2065 return NT_STATUS_OK
;
2068 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
);
2070 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
2071 struct tevent_immediate
*im
,
2074 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
2075 struct smbd_smb2_request
);
2076 struct smbd_server_connection
*sconn
= req
->sconn
;
2081 if (DEBUGLEVEL
>= 10) {
2082 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2083 req
->current_idx
, req
->in
.vector_count
));
2084 print_req_vectors(req
);
2087 status
= smbd_smb2_request_dispatch(req
);
2088 if (!NT_STATUS_IS_OK(status
)) {
2089 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2093 status
= smbd_smb2_request_next_incoming(sconn
);
2094 if (!NT_STATUS_IS_OK(status
)) {
2095 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2100 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
)
2102 struct smbd_smb2_request
*req
= tevent_req_callback_data(subreq
,
2103 struct smbd_smb2_request
);
2104 struct smbd_server_connection
*sconn
= req
->sconn
;
2109 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
2110 TALLOC_FREE(subreq
);
2113 status
= map_nt_error_from_unix(sys_errno
);
2114 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2115 nt_errstr(status
)));
2116 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2120 status
= smbd_smb2_request_next_incoming(sconn
);
2121 if (!NT_STATUS_IS_OK(status
)) {
2122 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2127 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
2129 DATA_BLOB body
, DATA_BLOB
*dyn
,
2130 const char *location
)
2133 int i
= req
->current_idx
;
2134 uint32_t next_command_ofs
;
2136 DEBUG(10,("smbd_smb2_request_done_ex: "
2137 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2138 i
, nt_errstr(status
), (unsigned int)body
.length
,
2140 (unsigned int)(dyn
? dyn
->length
: 0),
2143 if (body
.length
< 2) {
2144 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2147 if ((body
.length
% 2) != 0) {
2148 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
2151 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
2153 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
2154 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
2156 req
->out
.vector
[i
+1].iov_base
= (void *)body
.data
;
2157 req
->out
.vector
[i
+1].iov_len
= body
.length
;
2160 req
->out
.vector
[i
+2].iov_base
= (void *)dyn
->data
;
2161 req
->out
.vector
[i
+2].iov_len
= dyn
->length
;
2163 req
->out
.vector
[i
+2].iov_base
= NULL
;
2164 req
->out
.vector
[i
+2].iov_len
= 0;
2167 /* see if we need to recalculate the offset to the next response */
2168 if (next_command_ofs
> 0) {
2169 next_command_ofs
= SMB2_HDR_BODY
;
2170 next_command_ofs
+= req
->out
.vector
[i
+1].iov_len
;
2171 next_command_ofs
+= req
->out
.vector
[i
+2].iov_len
;
2174 if ((next_command_ofs
% 8) != 0) {
2175 size_t pad_size
= 8 - (next_command_ofs
% 8);
2176 if (req
->out
.vector
[i
+2].iov_len
== 0) {
2178 * if the dyn buffer is empty
2179 * we can use it to add padding
2183 pad
= talloc_zero_array(req
->out
.vector
,
2186 return smbd_smb2_request_error(req
,
2187 NT_STATUS_NO_MEMORY
);
2190 req
->out
.vector
[i
+2].iov_base
= (void *)pad
;
2191 req
->out
.vector
[i
+2].iov_len
= pad_size
;
2194 * For now we copy the dynamic buffer
2195 * and add the padding to the new buffer
2202 old_size
= req
->out
.vector
[i
+2].iov_len
;
2203 old_dyn
= (uint8_t *)req
->out
.vector
[i
+2].iov_base
;
2205 new_size
= old_size
+ pad_size
;
2206 new_dyn
= talloc_zero_array(req
->out
.vector
,
2208 if (new_dyn
== NULL
) {
2209 return smbd_smb2_request_error(req
,
2210 NT_STATUS_NO_MEMORY
);
2213 memcpy(new_dyn
, old_dyn
, old_size
);
2214 memset(new_dyn
+ old_size
, 0, pad_size
);
2216 req
->out
.vector
[i
+2].iov_base
= (void *)new_dyn
;
2217 req
->out
.vector
[i
+2].iov_len
= new_size
;
2219 next_command_ofs
+= pad_size
;
2222 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
2224 return smbd_smb2_request_reply(req
);
2227 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
2230 const char *location
)
2233 int i
= req
->current_idx
;
2234 uint8_t *outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
2236 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2237 i
, nt_errstr(status
), info
? " +info" : "",
2240 body
.data
= outhdr
+ SMB2_HDR_BODY
;
2242 SSVAL(body
.data
, 0, 9);
2245 SIVAL(body
.data
, 0x04, info
->length
);
2247 /* Allocated size of req->out.vector[i].iov_base
2248 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2249 * 1 byte without having to do an alloc.
2251 info
= talloc_zero_array(req
->out
.vector
,
2255 return NT_STATUS_NO_MEMORY
;
2257 info
->data
= ((uint8_t *)outhdr
) +
2258 OUTVEC_ALLOC_SIZE
- 1;
2260 SCVAL(info
->data
, 0, 0);
2264 * if a request fails, all other remaining
2265 * compounded requests should fail too
2267 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
2269 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
2273 struct smbd_smb2_send_oplock_break_state
{
2274 struct smbd_server_connection
*sconn
;
2275 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x18];
2276 struct iovec vector
;
2279 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
);
2281 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
2282 uint64_t file_id_persistent
,
2283 uint64_t file_id_volatile
,
2284 uint8_t oplock_level
)
2286 struct smbd_smb2_send_oplock_break_state
*state
;
2287 struct tevent_req
*subreq
;
2291 state
= talloc(sconn
, struct smbd_smb2_send_oplock_break_state
);
2292 if (state
== NULL
) {
2293 return NT_STATUS_NO_MEMORY
;
2295 state
->sconn
= sconn
;
2297 state
->vector
.iov_base
= (void *)state
->buf
;
2298 state
->vector
.iov_len
= sizeof(state
->buf
);
2300 _smb2_setlen(state
->buf
, sizeof(state
->buf
) - 4);
2301 hdr
= state
->buf
+ 4;
2302 body
= hdr
+ SMB2_HDR_BODY
;
2304 SIVAL(hdr
, 0, SMB2_MAGIC
);
2305 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
2306 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
2307 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
2308 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
2309 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
2310 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
2311 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
2312 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
2313 SIVAL(hdr
, SMB2_HDR_PID
, 0);
2314 SIVAL(hdr
, SMB2_HDR_TID
, 0);
2315 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
2316 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
2318 SSVAL(body
, 0x00, 0x18);
2320 SCVAL(body
, 0x02, oplock_level
);
2321 SCVAL(body
, 0x03, 0); /* reserved */
2322 SIVAL(body
, 0x04, 0); /* reserved */
2323 SBVAL(body
, 0x08, file_id_persistent
);
2324 SBVAL(body
, 0x10, file_id_volatile
);
2326 subreq
= tstream_writev_queue_send(state
,
2329 sconn
->smb2
.send_queue
,
2331 if (subreq
== NULL
) {
2332 return NT_STATUS_NO_MEMORY
;
2334 tevent_req_set_callback(subreq
,
2335 smbd_smb2_oplock_break_writev_done
,
2338 return NT_STATUS_OK
;
2341 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
)
2343 struct smbd_smb2_send_oplock_break_state
*state
=
2344 tevent_req_callback_data(subreq
,
2345 struct smbd_smb2_send_oplock_break_state
);
2346 struct smbd_server_connection
*sconn
= state
->sconn
;
2350 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
2351 TALLOC_FREE(subreq
);
2353 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
2354 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2361 struct smbd_smb2_request_read_state
{
2363 bool asked_for_header
;
2364 struct smbd_smb2_request
*smb2_req
;
2367 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2369 TALLOC_CTX
*mem_ctx
,
2370 struct iovec
**_vector
,
2372 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
);
2374 static struct tevent_req
*smbd_smb2_request_read_send(TALLOC_CTX
*mem_ctx
,
2375 struct tevent_context
*ev
,
2376 struct smbd_server_connection
*sconn
)
2378 struct tevent_req
*req
;
2379 struct smbd_smb2_request_read_state
*state
;
2380 struct tevent_req
*subreq
;
2382 req
= tevent_req_create(mem_ctx
, &state
,
2383 struct smbd_smb2_request_read_state
);
2388 state
->asked_for_header
= false;
2390 state
->smb2_req
= smbd_smb2_request_allocate(state
);
2391 if (tevent_req_nomem(state
->smb2_req
, req
)) {
2392 return tevent_req_post(req
, ev
);
2394 state
->smb2_req
->sconn
= sconn
;
2396 subreq
= tstream_readv_pdu_queue_send(state
, ev
, sconn
->smb2
.stream
,
2397 sconn
->smb2
.recv_queue
,
2398 smbd_smb2_request_next_vector
,
2400 if (tevent_req_nomem(subreq
, req
)) {
2401 return tevent_req_post(req
, ev
);
2403 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
2408 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2410 TALLOC_CTX
*mem_ctx
,
2411 struct iovec
**_vector
,
2414 struct smbd_smb2_request_read_state
*state
=
2415 talloc_get_type_abort(private_data
,
2416 struct smbd_smb2_request_read_state
);
2417 struct smbd_smb2_request
*req
= state
->smb2_req
;
2418 struct iovec
*vector
;
2419 int idx
= req
->in
.vector_count
;
2421 uint8_t *buf
= NULL
;
2423 if (req
->in
.vector_count
== 0) {
2425 * first we need to get the NBT header
2427 req
->in
.vector
= talloc_array(req
, struct iovec
,
2428 req
->in
.vector_count
+ 1);
2429 if (req
->in
.vector
== NULL
) {
2432 req
->in
.vector_count
+= 1;
2434 req
->in
.vector
[idx
].iov_base
= (void *)req
->in
.nbt_hdr
;
2435 req
->in
.vector
[idx
].iov_len
= 4;
2437 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2438 if (vector
== NULL
) {
2442 vector
[0] = req
->in
.vector
[idx
];
2449 if (req
->in
.vector_count
== 1) {
2451 * Now we analyze the NBT header
2453 state
->missing
= smb2_len(req
->in
.vector
[0].iov_base
);
2455 if (state
->missing
== 0) {
2456 /* if there're no remaining bytes, we're done */
2462 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2464 req
->in
.vector_count
+ 1);
2465 if (req
->in
.vector
== NULL
) {
2468 req
->in
.vector_count
+= 1;
2470 if (CVAL(req
->in
.vector
[0].iov_base
, 0) != 0) {
2472 * it's a special NBT message,
2473 * so get all remaining bytes
2475 len
= state
->missing
;
2476 } else if (state
->missing
< (SMB2_HDR_BODY
+ 2)) {
2478 * it's an invalid message, just read what we can get
2479 * and let the caller handle the error
2481 len
= state
->missing
;
2484 * We assume it's a SMB2 request,
2485 * and we first get the header and the
2486 * first 2 bytes (the struct size) of the body
2488 len
= SMB2_HDR_BODY
+ 2;
2490 state
->asked_for_header
= true;
2493 state
->missing
-= len
;
2495 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2500 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2501 req
->in
.vector
[idx
].iov_len
= len
;
2503 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2504 if (vector
== NULL
) {
2508 vector
[0] = req
->in
.vector
[idx
];
2515 if (state
->missing
== 0) {
2516 /* if there're no remaining bytes, we're done */
2522 if (state
->asked_for_header
) {
2525 size_t next_command_ofs
;
2530 bool invalid
= false;
2532 state
->asked_for_header
= false;
2535 * We got the SMB2 header and the first 2 bytes
2536 * of the body. We fix the size to just the header
2537 * and manually copy the 2 first bytes to the body section
2539 req
->in
.vector
[idx
-1].iov_len
= SMB2_HDR_BODY
;
2540 hdr
= (const uint8_t *)req
->in
.vector
[idx
-1].iov_base
;
2542 /* allocate vectors for body and dynamic areas */
2543 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2545 req
->in
.vector_count
+ 2);
2546 if (req
->in
.vector
== NULL
) {
2549 req
->in
.vector_count
+= 2;
2551 full_size
= state
->missing
+ SMB2_HDR_BODY
+ 2;
2552 next_command_ofs
= IVAL(hdr
, SMB2_HDR_NEXT_COMMAND
);
2553 body_size
= SVAL(hdr
, SMB2_HDR_BODY
);
2555 if (next_command_ofs
!= 0) {
2556 if (next_command_ofs
< (SMB2_HDR_BODY
+ 2)) {
2558 * this is invalid, just return a zero
2559 * body and let the caller deal with the error
2562 } else if (next_command_ofs
> full_size
) {
2564 * this is invalid, just return a zero
2565 * body and let the caller deal with the error
2569 full_size
= next_command_ofs
;
2574 if (body_size
< 2) {
2576 * this is invalid, just return a zero
2577 * body and let the caller deal with the error
2583 * Mask out the lowest bit, the "dynamic" part
2588 if (body_size
> (full_size
- SMB2_HDR_BODY
)) {
2590 * this is invalid, just return a zero
2591 * body and let the caller deal with the error
2598 /* the caller should check this */
2602 dyn_size
= full_size
- (SMB2_HDR_BODY
+ body_size
);
2604 state
->missing
-= (body_size
- 2) + dyn_size
;
2606 body
= talloc_array(req
->in
.vector
, uint8_t, body_size
);
2611 dyn
= talloc_array(req
->in
.vector
, uint8_t, dyn_size
);
2616 req
->in
.vector
[idx
].iov_base
= (void *)body
;
2617 req
->in
.vector
[idx
].iov_len
= body_size
;
2618 req
->in
.vector
[idx
+1].iov_base
= (void *)dyn
;
2619 req
->in
.vector
[idx
+1].iov_len
= dyn_size
;
2621 vector
= talloc_array(mem_ctx
, struct iovec
, 2);
2622 if (vector
== NULL
) {
2627 * the first 2 bytes of the body were already fetched
2628 * together with the header
2630 memcpy(body
, hdr
+ SMB2_HDR_BODY
, 2);
2631 vector
[0].iov_base
= body
+ 2;
2632 vector
[0].iov_len
= body_size
- 2;
2634 vector
[1] = req
->in
.vector
[idx
+1];
2642 * when we endup here, we're looking for a new SMB2 request
2643 * next. And we ask for its header and the first 2 bytes of
2644 * the body (like we did for the first SMB2 request).
2647 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2649 req
->in
.vector_count
+ 1);
2650 if (req
->in
.vector
== NULL
) {
2653 req
->in
.vector_count
+= 1;
2656 * We assume it's a SMB2 request,
2657 * and we first get the header and the
2658 * first 2 bytes (the struct size) of the body
2660 len
= SMB2_HDR_BODY
+ 2;
2662 if (len
> state
->missing
) {
2663 /* let the caller handle the error */
2664 len
= state
->missing
;
2667 state
->missing
-= len
;
2668 state
->asked_for_header
= true;
2670 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2675 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2676 req
->in
.vector
[idx
].iov_len
= len
;
2678 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2679 if (vector
== NULL
) {
2683 vector
[0] = req
->in
.vector
[idx
];
2690 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
)
2692 struct tevent_req
*req
=
2693 tevent_req_callback_data(subreq
,
2699 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
2701 status
= map_nt_error_from_unix(sys_errno
);
2702 tevent_req_nterror(req
, status
);
2706 tevent_req_done(req
);
2709 static NTSTATUS
smbd_smb2_request_read_recv(struct tevent_req
*req
,
2710 TALLOC_CTX
*mem_ctx
,
2711 struct smbd_smb2_request
**_smb2_req
)
2713 struct smbd_smb2_request_read_state
*state
=
2714 tevent_req_data(req
,
2715 struct smbd_smb2_request_read_state
);
2718 if (tevent_req_is_nterror(req
, &status
)) {
2719 tevent_req_received(req
);
2723 talloc_steal(mem_ctx
, state
->smb2_req
->mem_pool
);
2724 *_smb2_req
= state
->smb2_req
;
2725 tevent_req_received(req
);
2726 return NT_STATUS_OK
;
2729 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
);
2731 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
)
2733 size_t max_send_queue_len
;
2734 size_t cur_send_queue_len
;
2735 struct tevent_req
*subreq
;
2737 if (sconn
->smb2
.compound_related_in_progress
) {
2739 * Can't read another until the related
2742 return NT_STATUS_OK
;
2745 if (tevent_queue_length(sconn
->smb2
.recv_queue
) > 0) {
2747 * if there is already a smbd_smb2_request_read
2748 * pending, we are done.
2750 return NT_STATUS_OK
;
2753 max_send_queue_len
= MAX(1, sconn
->smb2
.max_credits
/16);
2754 cur_send_queue_len
= tevent_queue_length(sconn
->smb2
.send_queue
);
2756 if (cur_send_queue_len
> max_send_queue_len
) {
2758 * if we have a lot of requests to send,
2759 * we wait until they are on the wire until we
2760 * ask for the next request.
2762 return NT_STATUS_OK
;
2765 /* ask for the next request */
2766 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->ev_ctx
, sconn
);
2767 if (subreq
== NULL
) {
2768 return NT_STATUS_NO_MEMORY
;
2770 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);
2772 return NT_STATUS_OK
;
2775 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
2776 const uint8_t *inbuf
, size_t size
)
2779 struct smbd_smb2_request
*req
= NULL
;
2781 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2782 (unsigned int)size
));
2784 status
= smbd_initialize_smb2(sconn
);
2785 if (!NT_STATUS_IS_OK(status
)) {
2786 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2790 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
2791 if (!NT_STATUS_IS_OK(status
)) {
2792 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2796 status
= smbd_smb2_request_validate(req
);
2797 if (!NT_STATUS_IS_OK(status
)) {
2798 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2802 status
= smbd_smb2_request_setup_out(req
);
2803 if (!NT_STATUS_IS_OK(status
)) {
2804 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2808 status
= smbd_smb2_request_dispatch(req
);
2809 if (!NT_STATUS_IS_OK(status
)) {
2810 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2814 status
= smbd_smb2_request_next_incoming(sconn
);
2815 if (!NT_STATUS_IS_OK(status
)) {
2816 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2820 sconn
->num_requests
++;
2823 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
)
2825 struct smbd_server_connection
*sconn
= tevent_req_callback_data(subreq
,
2826 struct smbd_server_connection
);
2828 struct smbd_smb2_request
*req
= NULL
;
2830 status
= smbd_smb2_request_read_recv(subreq
, sconn
, &req
);
2831 TALLOC_FREE(subreq
);
2832 if (!NT_STATUS_IS_OK(status
)) {
2833 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2834 nt_errstr(status
)));
2835 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2839 if (req
->in
.nbt_hdr
[0] != 0x00) {
2840 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2841 req
->in
.nbt_hdr
[0]));
2846 req
->current_idx
= 1;
2848 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2849 req
->current_idx
, req
->in
.vector_count
));
2851 status
= smbd_smb2_request_validate(req
);
2852 if (!NT_STATUS_IS_OK(status
)) {
2853 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2857 status
= smbd_smb2_request_setup_out(req
);
2858 if (!NT_STATUS_IS_OK(status
)) {
2859 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2863 status
= smbd_smb2_request_dispatch(req
);
2864 if (!NT_STATUS_IS_OK(status
)) {
2865 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2870 status
= smbd_smb2_request_next_incoming(sconn
);
2871 if (!NT_STATUS_IS_OK(status
)) {
2872 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2876 sconn
->num_requests
++;
2878 /* The timeout_processing function isn't run nearly
2879 often enough to implement 'max log size' without
2880 overrunning the size of the file by many megabytes.
2881 This is especially true if we are running at debug
2882 level 10. Checking every 50 SMB2s is a nice
2883 tradeoff of performance vs log file size overrun. */
2885 if ((sconn
->num_requests
% 50) == 0 &&
2886 need_to_check_log_size()) {
2887 change_to_root_user();