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
.event_ctx
= server_event_context();
103 sconn
->smb2
.recv_queue
= tevent_queue_create(sconn
, "smb2 recv queue");
104 if (sconn
->smb2
.recv_queue
== NULL
) {
105 return NT_STATUS_NO_MEMORY
;
108 sconn
->smb2
.send_queue
= tevent_queue_create(sconn
, "smb2 send queue");
109 if (sconn
->smb2
.send_queue
== NULL
) {
110 return NT_STATUS_NO_MEMORY
;
113 sconn
->smb2
.sessions
.idtree
= idr_init(sconn
);
114 if (sconn
->smb2
.sessions
.idtree
== NULL
) {
115 return NT_STATUS_NO_MEMORY
;
117 sconn
->smb2
.sessions
.limit
= 0x0000FFFE;
118 sconn
->smb2
.sessions
.list
= NULL
;
119 sconn
->smb2
.seqnum_low
= 0;
120 sconn
->smb2
.credits_granted
= 0;
121 sconn
->smb2
.max_credits
= lp_smb2_max_credits();
122 sconn
->smb2
.credits_bitmap
= bitmap_talloc(sconn
,
123 DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
*sconn
->smb2
.max_credits
);
124 if (sconn
->smb2
.credits_bitmap
== NULL
) {
125 return NT_STATUS_NO_MEMORY
;
128 ret
= tstream_bsd_existing_socket(sconn
, sconn
->sock
,
129 &sconn
->smb2
.stream
);
131 status
= map_nt_error_from_unix(errno
);
135 /* Ensure child is set to non-blocking mode */
136 set_blocking(sconn
->sock
, false);
140 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
141 #define _smb2_setlen(_buf,len) do { \
142 uint8_t *buf = (uint8_t *)_buf; \
144 buf[1] = ((len)&0xFF0000)>>16; \
145 buf[2] = ((len)&0xFF00)>>8; \
146 buf[3] = (len)&0xFF; \
149 static void smb2_setup_nbt_length(struct iovec
*vector
, int count
)
154 for (i
=1; i
< count
; i
++) {
155 len
+= vector
[i
].iov_len
;
158 _smb2_setlen(vector
[0].iov_base
, len
);
161 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request
**req
)
164 (*req
)->parent
= NULL
;
165 (*req
)->mem_pool
= NULL
;
171 static int smbd_smb2_request_destructor(struct smbd_smb2_request
*req
)
175 talloc_free(req
->mem_pool
);
181 static struct smbd_smb2_request
*smbd_smb2_request_allocate(TALLOC_CTX
*mem_ctx
)
183 TALLOC_CTX
*mem_pool
;
184 struct smbd_smb2_request
**parent
;
185 struct smbd_smb2_request
*req
;
188 /* Enable this to find subtle valgrind errors. */
189 mem_pool
= talloc_init("smbd_smb2_request_allocate");
191 mem_pool
= talloc_pool(mem_ctx
, 8192);
193 if (mem_pool
== NULL
) {
197 parent
= talloc(mem_pool
, struct smbd_smb2_request
*);
198 if (parent
== NULL
) {
199 talloc_free(mem_pool
);
203 req
= talloc_zero(parent
, struct smbd_smb2_request
);
205 talloc_free(mem_pool
);
209 req
->mem_pool
= mem_pool
;
210 req
->parent
= parent
;
212 talloc_set_destructor(parent
, smbd_smb2_request_parent_destructor
);
213 talloc_set_destructor(req
, smbd_smb2_request_destructor
);
218 static NTSTATUS
smbd_smb2_request_create(struct smbd_server_connection
*sconn
,
219 const uint8_t *inbuf
, size_t size
,
220 struct smbd_smb2_request
**_req
)
222 struct smbd_smb2_request
*req
;
223 uint32_t protocol_version
;
224 const uint8_t *inhdr
= NULL
;
227 uint32_t next_command_ofs
;
229 if (size
< (4 + SMB2_HDR_BODY
+ 2)) {
230 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size
));
231 return NT_STATUS_INVALID_PARAMETER
;
236 protocol_version
= IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
);
237 if (protocol_version
!= SMB2_MAGIC
) {
238 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
240 return NT_STATUS_INVALID_PARAMETER
;
243 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
244 if (cmd
!= SMB2_OP_NEGPROT
) {
245 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
247 return NT_STATUS_INVALID_PARAMETER
;
250 next_command_ofs
= IVAL(inhdr
, SMB2_HDR_NEXT_COMMAND
);
251 if (next_command_ofs
!= 0) {
252 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
254 return NT_STATUS_INVALID_PARAMETER
;
257 req
= smbd_smb2_request_allocate(sconn
);
259 return NT_STATUS_NO_MEMORY
;
263 talloc_steal(req
, inbuf
);
265 req
->in
.vector
= talloc_array(req
, struct iovec
, 4);
266 if (req
->in
.vector
== NULL
) {
268 return NT_STATUS_NO_MEMORY
;
270 req
->in
.vector_count
= 4;
272 memcpy(req
->in
.nbt_hdr
, inbuf
, 4);
275 req
->in
.vector
[0].iov_base
= discard_const_p(void, req
->in
.nbt_hdr
);
276 req
->in
.vector
[0].iov_len
= 4;
277 ofs
+= req
->in
.vector
[0].iov_len
;
279 req
->in
.vector
[1].iov_base
= discard_const_p(void, (inbuf
+ ofs
));
280 req
->in
.vector
[1].iov_len
= SMB2_HDR_BODY
;
281 ofs
+= req
->in
.vector
[1].iov_len
;
283 req
->in
.vector
[2].iov_base
= discard_const_p(void, (inbuf
+ ofs
));
284 req
->in
.vector
[2].iov_len
= SVAL(inbuf
, ofs
) & 0xFFFE;
285 ofs
+= req
->in
.vector
[2].iov_len
;
288 return NT_STATUS_INVALID_PARAMETER
;
291 req
->in
.vector
[3].iov_base
= discard_const_p(void, (inbuf
+ ofs
));
292 req
->in
.vector
[3].iov_len
= size
- ofs
;
293 ofs
+= req
->in
.vector
[3].iov_len
;
295 req
->current_idx
= 1;
301 static bool smb2_validate_message_id(struct smbd_server_connection
*sconn
,
302 const uint8_t *inhdr
)
304 uint64_t message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
305 struct bitmap
*credits_bm
= sconn
->smb2
.credits_bitmap
;
306 uint16_t opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
307 unsigned int bitmap_offset
;
309 if (opcode
== SMB2_OP_CANCEL
) {
310 /* SMB2_CANCEL requests by definition resend messageids. */
314 if (message_id
< sconn
->smb2
.seqnum_low
||
315 message_id
> (sconn
->smb2
.seqnum_low
+
316 (sconn
->smb2
.max_credits
* DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
))) {
317 DEBUG(0,("smb2_validate_message_id: bad message_id "
318 "%llu (low = %llu, max = %lu)\n",
319 (unsigned long long)message_id
,
320 (unsigned long long)sconn
->smb2
.seqnum_low
,
321 (unsigned long)sconn
->smb2
.max_credits
));
325 if (sconn
->smb2
.credits_granted
== 0) {
326 smbd_server_connection_terminate(sconn
, "smb2_validate_message_id: "
327 "terminating connection: client used more credits than granted\n");
331 /* client just used a credit. */
332 sconn
->smb2
.credits_granted
-= 1;
334 /* Mark the message_id as seen in the bitmap. */
335 bitmap_offset
= (unsigned int)(message_id
%
336 (uint64_t)(sconn
->smb2
.max_credits
* DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
));
337 if (bitmap_query(credits_bm
, bitmap_offset
)) {
338 DEBUG(0,("smb2_validate_message_id: duplicate message_id "
339 "%llu (bm offset %u)\n",
340 (unsigned long long)message_id
,
344 bitmap_set(credits_bm
, bitmap_offset
);
346 if (message_id
== sconn
->smb2
.seqnum_low
+ 1) {
347 /* Move the window forward by all the message_id's
349 while (bitmap_query(credits_bm
, bitmap_offset
)) {
350 DEBUG(10,("smb2_validate_message_id: clearing "
351 "id %llu (position %u) from bitmap\n",
352 (unsigned long long)(sconn
->smb2
.seqnum_low
+ 1),
354 bitmap_clear(credits_bm
, bitmap_offset
);
355 sconn
->smb2
.seqnum_low
+= 1;
356 bitmap_offset
= (bitmap_offset
+ 1) %
357 (sconn
->smb2
.max_credits
* DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
);
364 static NTSTATUS
smbd_smb2_request_validate(struct smbd_smb2_request
*req
)
369 count
= req
->in
.vector_count
;
372 /* It's not a SMB2 request */
373 return NT_STATUS_INVALID_PARAMETER
;
376 for (idx
=1; idx
< count
; idx
+= 3) {
377 const uint8_t *inhdr
= NULL
;
380 if (req
->in
.vector
[idx
].iov_len
!= SMB2_HDR_BODY
) {
381 return NT_STATUS_INVALID_PARAMETER
;
384 if (req
->in
.vector
[idx
+1].iov_len
< 2) {
385 return NT_STATUS_INVALID_PARAMETER
;
388 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
390 /* Check the SMB2 header */
391 if (IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
) != SMB2_MAGIC
) {
392 return NT_STATUS_INVALID_PARAMETER
;
395 if (!smb2_validate_message_id(req
->sconn
, inhdr
)) {
396 return NT_STATUS_INVALID_PARAMETER
;
399 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
402 * the 1st request should never have the
403 * SMB2_HDR_FLAG_CHAINED flag set
405 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
406 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
409 } else if (idx
== 4) {
411 * the 2nd request triggers related vs. unrelated
412 * compounded requests
414 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
415 req
->compound_related
= true;
417 } else if (idx
> 4) {
420 * It seems the this tests are wrong
421 * see the SMB2-COMPOUND test
425 * all other requests should match the 2nd one
427 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
428 if (!req
->compound_related
) {
430 NT_STATUS_INVALID_PARAMETER
;
434 if (req
->compound_related
) {
436 NT_STATUS_INVALID_PARAMETER
;
447 static void smb2_set_operation_credit(struct smbd_server_connection
*sconn
,
448 const struct iovec
*in_vector
,
449 struct iovec
*out_vector
)
451 const uint8_t *inhdr
= (const uint8_t *)in_vector
->iov_base
;
452 uint8_t *outhdr
= (uint8_t *)out_vector
->iov_base
;
453 uint16_t credits_requested
;
455 uint16_t credits_granted
= 0;
457 credits_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
458 out_flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
460 SMB_ASSERT(sconn
->smb2
.max_credits
>= sconn
->smb2
.credits_granted
);
462 if (out_flags
& SMB2_HDR_FLAG_ASYNC
) {
464 * In case we already send an async interim
465 * response, we should not grant
466 * credits on the final response.
468 credits_requested
= 0;
471 if (credits_requested
) {
472 uint16_t modified_credits_requested
;
476 * Split up max_credits into 1/16ths, and then scale
477 * the requested credits by how many 16ths have been
478 * currently granted. Less than 1/16th == grant all
479 * requested (100%), scale down as more have been
480 * granted. Never ask for less than 1 as the client
481 * asked for at least 1. JRA.
484 multiplier
= 16 - (((sconn
->smb2
.credits_granted
* 16) / sconn
->smb2
.max_credits
) % 16);
486 modified_credits_requested
= (multiplier
* credits_requested
) / 16;
487 if (modified_credits_requested
== 0) {
488 modified_credits_requested
= 1;
491 /* Remember what we gave out. */
492 credits_granted
= MIN(modified_credits_requested
,
493 (sconn
->smb2
.max_credits
- sconn
->smb2
.credits_granted
));
496 if (credits_granted
== 0 && sconn
->smb2
.credits_granted
== 0) {
497 /* First negprot packet, or ensure the client credits can
498 never drop to zero. */
502 SSVAL(outhdr
, SMB2_HDR_CREDIT
, credits_granted
);
503 sconn
->smb2
.credits_granted
+= credits_granted
;
505 DEBUG(10,("smb2_set_operation_credit: requested %u, "
506 "granted %u, total granted %u\n",
507 (unsigned int)credits_requested
,
508 (unsigned int)credits_granted
,
509 (unsigned int)sconn
->smb2
.credits_granted
));
512 static void smb2_calculate_credits(const struct smbd_smb2_request
*inreq
,
513 struct smbd_smb2_request
*outreq
)
517 count
= outreq
->out
.vector_count
;
519 for (idx
=1; idx
< count
; idx
+= 3) {
520 smb2_set_operation_credit(outreq
->sconn
,
521 &inreq
->in
.vector
[idx
],
522 &outreq
->out
.vector
[idx
]);
526 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
)
528 struct iovec
*vector
;
532 count
= req
->in
.vector_count
;
533 vector
= talloc_zero_array(req
, struct iovec
, count
);
534 if (vector
== NULL
) {
535 return NT_STATUS_NO_MEMORY
;
538 vector
[0].iov_base
= req
->out
.nbt_hdr
;
539 vector
[0].iov_len
= 4;
540 SIVAL(req
->out
.nbt_hdr
, 0, 0);
542 for (idx
=1; idx
< count
; idx
+= 3) {
543 const uint8_t *inhdr
= NULL
;
545 uint8_t *outhdr
= NULL
;
546 uint8_t *outbody
= NULL
;
547 uint32_t next_command_ofs
= 0;
548 struct iovec
*current
= &vector
[idx
];
550 if ((idx
+ 3) < count
) {
551 /* we have a next command -
552 * setup for the error case. */
553 next_command_ofs
= SMB2_HDR_BODY
+ 9;
556 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
557 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
559 outhdr
= talloc_zero_array(vector
, uint8_t,
561 if (outhdr
== NULL
) {
562 return NT_STATUS_NO_MEMORY
;
565 outbody
= outhdr
+ SMB2_HDR_BODY
;
567 current
[0].iov_base
= (void *)outhdr
;
568 current
[0].iov_len
= SMB2_HDR_BODY
;
570 current
[1].iov_base
= (void *)outbody
;
571 current
[1].iov_len
= 8;
573 current
[2].iov_base
= NULL
;
574 current
[2].iov_len
= 0;
576 /* setup the SMB2 header */
577 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
578 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
579 SSVAL(outhdr
, SMB2_HDR_EPOCH
, 0);
580 SIVAL(outhdr
, SMB2_HDR_STATUS
,
581 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
582 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
583 SVAL(inhdr
, SMB2_HDR_OPCODE
));
584 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
585 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
586 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
587 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
588 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
589 SIVAL(outhdr
, SMB2_HDR_PID
,
590 IVAL(inhdr
, SMB2_HDR_PID
));
591 SIVAL(outhdr
, SMB2_HDR_TID
,
592 IVAL(inhdr
, SMB2_HDR_TID
));
593 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
594 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
595 memset(outhdr
+ SMB2_HDR_SIGNATURE
, 0, 16);
597 /* setup error body header */
598 SSVAL(outbody
, 0x00, 0x08 + 1);
599 SSVAL(outbody
, 0x02, 0);
600 SIVAL(outbody
, 0x04, 0);
603 req
->out
.vector
= vector
;
604 req
->out
.vector_count
= count
;
606 /* setup the length of the NBT packet */
607 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
609 DLIST_ADD_END(req
->sconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
614 void smbd_server_connection_terminate_ex(struct smbd_server_connection
*sconn
,
616 const char *location
)
618 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
620 exit_server_cleanly(reason
);
623 static bool dup_smb2_vec3(TALLOC_CTX
*ctx
,
624 struct iovec
*outvec
,
625 const struct iovec
*srcvec
)
627 /* vec[0] is always boilerplate and must
628 * be allocated with size OUTVEC_ALLOC_SIZE. */
630 outvec
[0].iov_base
= talloc_memdup(ctx
,
633 if (!outvec
[0].iov_base
) {
636 outvec
[0].iov_len
= SMB2_HDR_BODY
;
639 * If this is a "standard" vec[1] of length 8,
640 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
641 * then duplicate this. Else use talloc_memdup().
644 if (srcvec
[1].iov_len
== 8 &&
645 srcvec
[1].iov_base
==
646 ((uint8_t *)srcvec
[0].iov_base
) +
648 outvec
[1].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
650 outvec
[1].iov_len
= 8;
652 outvec
[1].iov_base
= talloc_memdup(ctx
,
655 if (!outvec
[1].iov_base
) {
658 outvec
[1].iov_len
= srcvec
[1].iov_len
;
662 * If this is a "standard" vec[2] of length 1,
663 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
664 * then duplicate this. Else use talloc_memdup().
667 if (srcvec
[2].iov_base
&&
669 if (srcvec
[2].iov_base
==
670 ((uint8_t *)srcvec
[0].iov_base
) +
671 (OUTVEC_ALLOC_SIZE
- 1) &&
672 srcvec
[2].iov_len
== 1) {
673 /* Common SMB2 error packet case. */
674 outvec
[2].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
675 (OUTVEC_ALLOC_SIZE
- 1);
677 outvec
[2].iov_base
= talloc_memdup(ctx
,
680 if (!outvec
[2].iov_base
) {
684 outvec
[2].iov_len
= srcvec
[2].iov_len
;
686 outvec
[2].iov_base
= NULL
;
687 outvec
[2].iov_len
= 0;
692 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
694 struct smbd_smb2_request
*newreq
= NULL
;
695 struct iovec
*outvec
= NULL
;
696 int count
= req
->out
.vector_count
;
699 newreq
= smbd_smb2_request_allocate(req
->sconn
);
704 newreq
->sconn
= req
->sconn
;
705 newreq
->session
= req
->session
;
706 newreq
->do_signing
= req
->do_signing
;
707 newreq
->current_idx
= req
->current_idx
;
708 newreq
->async
= false;
709 newreq
->cancelled
= false;
710 /* Note we are leaving:
714 uninitialized as NULL here as
715 they're not used in the interim
716 response code. JRA. */
718 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
723 newreq
->out
.vector
= outvec
;
724 newreq
->out
.vector_count
= count
;
726 /* Setup the outvec's identically to req. */
727 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
728 outvec
[0].iov_len
= 4;
729 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
731 /* Setup the vectors identically to the ones in req. */
732 for (i
= 1; i
< count
; i
+= 3) {
733 if (!dup_smb2_vec3(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
744 smb2_setup_nbt_length(newreq
->out
.vector
,
745 newreq
->out
.vector_count
);
750 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
);
752 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
755 uint8_t *outhdr
= NULL
;
756 struct smbd_smb2_request
*nreq
= NULL
;
758 /* Create a new smb2 request we'll use
759 for the interim return. */
760 nreq
= dup_smb2_req(req
);
762 return NT_STATUS_NO_MEMORY
;
765 /* Lose the last 3 out vectors. They're the
766 ones we'll be using for the async reply. */
767 nreq
->out
.vector_count
-= 3;
769 smb2_setup_nbt_length(nreq
->out
.vector
,
770 nreq
->out
.vector_count
);
772 /* Step back to the previous reply. */
773 i
= nreq
->current_idx
- 3;
774 outhdr
= (uint8_t *)nreq
->out
.vector
[i
].iov_base
;
775 /* And end the chain. */
776 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
778 /* Calculate outgoing credits */
779 smb2_calculate_credits(req
, nreq
);
781 /* Re-sign if needed. */
782 if (nreq
->do_signing
) {
784 status
= smb2_signing_sign_pdu(nreq
->session
->session_key
,
785 &nreq
->out
.vector
[i
], 3);
786 if (!NT_STATUS_IS_OK(status
)) {
790 if (DEBUGLEVEL
>= 10) {
791 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
792 (unsigned int)nreq
->current_idx
);
793 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
794 (unsigned int)nreq
->out
.vector_count
);
795 print_req_vectors(nreq
);
797 nreq
->subreq
= tstream_writev_queue_send(nreq
,
798 nreq
->sconn
->smb2
.event_ctx
,
799 nreq
->sconn
->smb2
.stream
,
800 nreq
->sconn
->smb2
.send_queue
,
802 nreq
->out
.vector_count
);
804 if (nreq
->subreq
== NULL
) {
805 return NT_STATUS_NO_MEMORY
;
808 tevent_req_set_callback(nreq
->subreq
,
809 smbd_smb2_request_writev_done
,
815 struct smbd_smb2_request_pending_state
{
816 struct smbd_server_connection
*sconn
;
817 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x08 + 1];
818 struct iovec vector
[3];
821 static void smbd_smb2_request_pending_writev_done(struct tevent_req
*subreq
)
823 struct smbd_smb2_request_pending_state
*state
=
824 tevent_req_callback_data(subreq
,
825 struct smbd_smb2_request_pending_state
);
826 struct smbd_server_connection
*sconn
= state
->sconn
;
830 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
833 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
834 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
841 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
842 struct tevent_req
*subreq
)
845 struct smbd_smb2_request_pending_state
*state
= NULL
;
846 int i
= req
->current_idx
;
847 uint8_t *reqhdr
= NULL
;
849 uint8_t *body
= NULL
;
851 uint64_t message_id
= 0;
852 uint64_t async_id
= 0;
853 struct iovec
*outvec
= NULL
;
855 if (!tevent_req_is_in_progress(subreq
)) {
859 req
->subreq
= subreq
;
863 /* We're already async. */
867 if (req
->in
.vector_count
> i
+ 3) {
869 * We're trying to go async in a compound
870 * request chain. This is not allowed.
871 * Cancel the outstanding request.
873 tevent_req_cancel(req
->subreq
);
874 return smbd_smb2_request_error(req
,
875 NT_STATUS_INSUFFICIENT_RESOURCES
);
878 if (DEBUGLEVEL
>= 10) {
879 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
880 (unsigned int)req
->current_idx
);
881 print_req_vectors(req
);
884 if (req
->out
.vector_count
> 4) {
885 /* This is a compound reply. We
886 * must do an interim response
887 * followed by the async response
890 status
= smb2_send_async_interim_response(req
);
891 if (!NT_STATUS_IS_OK(status
)) {
896 * We're splitting off the last SMB2
897 * request in a compound set, and the
898 * smb2_send_async_interim_response()
899 * call above just sent all the replies
900 * for the previous SMB2 requests in
901 * this compound set. So we're no longer
902 * in the "compound_related_in_progress"
903 * state, and this is no longer a compound
906 req
->compound_related
= false;
907 req
->sconn
->smb2
.compound_related_in_progress
= false;
910 /* Don't return an intermediate packet on a pipe read/write. */
911 if (req
->tcon
&& req
->tcon
->compat_conn
&& IS_IPC(req
->tcon
->compat_conn
)) {
915 reqhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
916 flags
= (IVAL(reqhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
917 message_id
= BVAL(reqhdr
, SMB2_HDR_MESSAGE_ID
);
918 async_id
= message_id
; /* keep it simple for now... */
921 * What we send is identical to a smbd_smb2_request_error
922 * packet with an error status of STATUS_PENDING. Make use
923 * of this fact sometime when refactoring. JRA.
926 state
= talloc_zero(req
->sconn
, struct smbd_smb2_request_pending_state
);
928 return NT_STATUS_NO_MEMORY
;
930 state
->sconn
= req
->sconn
;
932 state
->vector
[0].iov_base
= (void *)state
->buf
;
933 state
->vector
[0].iov_len
= 4;
935 state
->vector
[1].iov_base
= state
->buf
+ 4;
936 state
->vector
[1].iov_len
= SMB2_HDR_BODY
;
938 state
->vector
[2].iov_base
= state
->buf
+ 4 + SMB2_HDR_BODY
;
939 state
->vector
[2].iov_len
= 9;
941 smb2_setup_nbt_length(state
->vector
, 3);
943 hdr
= (uint8_t *)state
->vector
[1].iov_base
;
944 body
= (uint8_t *)state
->vector
[2].iov_base
;
946 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
947 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
948 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
949 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
950 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(reqhdr
, SMB2_HDR_OPCODE
));
952 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
953 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
954 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
955 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
956 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
957 BVAL(reqhdr
, SMB2_HDR_SESSION_ID
));
958 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
960 SSVAL(body
, 0x00, 0x08 + 1);
962 SCVAL(body
, 0x02, 0);
963 SCVAL(body
, 0x03, 0);
964 SIVAL(body
, 0x04, 0);
965 /* Match W2K8R2... */
966 SCVAL(body
, 0x08, 0x21);
968 /* Ensure we correctly go through crediting. Grant
969 the credits now, and zero credits on the final
971 smb2_set_operation_credit(req
->sconn
,
975 if (req
->do_signing
) {
976 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
977 &state
->vector
[1], 2);
978 if (!NT_STATUS_IS_OK(status
)) {
983 subreq
= tstream_writev_queue_send(state
,
984 req
->sconn
->smb2
.event_ctx
,
985 req
->sconn
->smb2
.stream
,
986 req
->sconn
->smb2
.send_queue
,
990 if (subreq
== NULL
) {
991 return NT_STATUS_NO_MEMORY
;
994 tevent_req_set_callback(subreq
,
995 smbd_smb2_request_pending_writev_done
,
998 /* Note we're going async with this request. */
1004 * Now manipulate req so that the outstanding async request
1005 * is the only one left in the struct smbd_smb2_request.
1008 if (req
->current_idx
== 1) {
1009 /* There was only one. */
1013 /* Re-arrange the in.vectors. */
1014 req
->in
.vector
[1] = req
->in
.vector
[i
];
1015 req
->in
.vector
[2] = req
->in
.vector
[i
+1];
1016 req
->in
.vector
[3] = req
->in
.vector
[i
+2];
1017 req
->in
.vector_count
= 4;
1018 /* Reset the new in size. */
1019 smb2_setup_nbt_length(req
->in
.vector
, 4);
1021 /* Now recreate the out.vectors. */
1022 outvec
= talloc_zero_array(req
, struct iovec
, 4);
1024 return NT_STATUS_NO_MEMORY
;
1027 /* 0 is always boilerplate and must
1028 * be of size 4 for the length field. */
1030 outvec
[0].iov_base
= req
->out
.nbt_hdr
;
1031 outvec
[0].iov_len
= 4;
1032 SIVAL(req
->out
.nbt_hdr
, 0, 0);
1034 if (!dup_smb2_vec3(outvec
, &outvec
[1], &req
->out
.vector
[i
])) {
1035 return NT_STATUS_NO_MEMORY
;
1038 TALLOC_FREE(req
->out
.vector
);
1040 req
->out
.vector
= outvec
;
1042 req
->current_idx
= 1;
1043 req
->out
.vector_count
= 4;
1047 smb2_setup_nbt_length(req
->out
.vector
,
1048 req
->out
.vector_count
);
1051 /* Ensure our final reply matches the interim one. */
1052 reqhdr
= (uint8_t *)req
->out
.vector
[1].iov_base
;
1053 SIVAL(reqhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1054 SBVAL(reqhdr
, SMB2_HDR_PID
, async_id
);
1057 const uint8_t *inhdr
=
1058 (const uint8_t *)req
->in
.vector
[1].iov_base
;
1059 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1061 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1062 (unsigned long long)async_id
));
1066 return NT_STATUS_OK
;
1069 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
1071 struct smbd_server_connection
*sconn
= req
->sconn
;
1072 struct smbd_smb2_request
*cur
;
1073 const uint8_t *inhdr
;
1074 int i
= req
->current_idx
;
1076 uint64_t search_message_id
;
1077 uint64_t search_async_id
;
1080 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1082 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1083 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1084 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
1087 * we don't need the request anymore
1088 * cancel requests never have a response
1090 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1093 for (cur
= sconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
1094 const uint8_t *outhdr
;
1095 uint64_t message_id
;
1098 i
= cur
->current_idx
;
1100 outhdr
= (const uint8_t *)cur
->out
.vector
[i
].iov_base
;
1102 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1103 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
1105 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1106 if (search_async_id
== async_id
) {
1107 found_id
= async_id
;
1111 if (search_message_id
== message_id
) {
1112 found_id
= message_id
;
1118 if (cur
&& cur
->subreq
) {
1119 inhdr
= (const uint8_t *)cur
->in
.vector
[i
].iov_base
;
1120 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1121 "cancel opcode[%s] mid %llu\n",
1122 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1123 (unsigned long long)found_id
));
1124 tevent_req_cancel(cur
->subreq
);
1127 return NT_STATUS_OK
;
1130 /*************************************************************
1131 Ensure an incoming tid is a valid one for us to access.
1132 Change to the associated uid credentials and chdir to the
1133 valid tid directory.
1134 *************************************************************/
1136 static NTSTATUS
smbd_smb2_request_check_tcon(struct smbd_smb2_request
*req
)
1138 const uint8_t *inhdr
;
1139 const uint8_t *outhdr
;
1140 int i
= req
->current_idx
;
1143 struct smbd_smb2_tcon
*tcon
;
1144 bool chained_fixup
= false;
1146 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1148 in_tid
= IVAL(inhdr
, SMB2_HDR_TID
);
1150 if (in_tid
== (0xFFFFFFFF)) {
1153 * async request - fill in tid from
1154 * already setup out.vector[].iov_base.
1156 outhdr
= (const uint8_t *)req
->out
.vector
[i
].iov_base
;
1157 in_tid
= IVAL(outhdr
, SMB2_HDR_TID
);
1160 * Chained request - fill in tid from
1161 * the previous request out.vector[].iov_base.
1163 outhdr
= (const uint8_t *)req
->out
.vector
[i
-3].iov_base
;
1164 in_tid
= IVAL(outhdr
, SMB2_HDR_TID
);
1165 chained_fixup
= true;
1169 /* lookup an existing session */
1170 p
= idr_find(req
->session
->tcons
.idtree
, in_tid
);
1172 return NT_STATUS_NETWORK_NAME_DELETED
;
1174 tcon
= talloc_get_type_abort(p
, struct smbd_smb2_tcon
);
1176 if (!change_to_user(tcon
->compat_conn
,req
->session
->vuid
)) {
1177 return NT_STATUS_ACCESS_DENIED
;
1180 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1181 if (!set_current_service(tcon
->compat_conn
, 0, true)) {
1182 return NT_STATUS_ACCESS_DENIED
;
1187 if (chained_fixup
) {
1188 /* Fix up our own outhdr. */
1189 outhdr
= (const uint8_t *)req
->out
.vector
[i
].iov_base
;
1190 SIVAL(discard_const_p(uint8_t, outhdr
), SMB2_HDR_TID
, in_tid
);
1193 return NT_STATUS_OK
;
1196 /*************************************************************
1197 Ensure an incoming session_id is a valid one for us to access.
1198 *************************************************************/
1200 static NTSTATUS
smbd_smb2_request_check_session(struct smbd_smb2_request
*req
)
1202 const uint8_t *inhdr
;
1203 const uint8_t *outhdr
;
1204 int i
= req
->current_idx
;
1205 uint64_t in_session_id
;
1207 struct smbd_smb2_session
*session
;
1208 bool chained_fixup
= false;
1210 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1212 in_session_id
= BVAL(inhdr
, SMB2_HDR_SESSION_ID
);
1214 if (in_session_id
== (0xFFFFFFFFFFFFFFFFLL
)) {
1217 * async request - fill in session_id from
1218 * already setup request out.vector[].iov_base.
1220 outhdr
= (const uint8_t *)req
->out
.vector
[i
].iov_base
;
1221 in_session_id
= BVAL(outhdr
, SMB2_HDR_SESSION_ID
);
1224 * Chained request - fill in session_id from
1225 * the previous request out.vector[].iov_base.
1227 outhdr
= (const uint8_t *)req
->out
.vector
[i
-3].iov_base
;
1228 in_session_id
= BVAL(outhdr
, SMB2_HDR_SESSION_ID
);
1229 chained_fixup
= true;
1233 /* lookup an existing session */
1234 p
= idr_find(req
->sconn
->smb2
.sessions
.idtree
, in_session_id
);
1236 return NT_STATUS_USER_SESSION_DELETED
;
1238 session
= talloc_get_type_abort(p
, struct smbd_smb2_session
);
1240 if (!NT_STATUS_IS_OK(session
->status
)) {
1241 return NT_STATUS_ACCESS_DENIED
;
1244 set_current_user_info(session
->session_info
->unix_info
->sanitized_username
,
1245 session
->session_info
->unix_info
->unix_name
,
1246 session
->session_info
->info
->domain_name
);
1248 req
->session
= session
;
1250 if (chained_fixup
) {
1251 /* Fix up our own outhdr. */
1252 outhdr
= (const uint8_t *)req
->out
.vector
[i
].iov_base
;
1253 SBVAL(discard_const_p(uint8_t, outhdr
), SMB2_HDR_SESSION_ID
, in_session_id
);
1255 return NT_STATUS_OK
;
1258 NTSTATUS
smbd_smb2_request_verify_sizes(struct smbd_smb2_request
*req
,
1259 size_t expected_body_size
)
1261 const uint8_t *inhdr
;
1263 const uint8_t *inbody
;
1264 int i
= req
->current_idx
;
1266 size_t min_dyn_size
= expected_body_size
& 0x00000001;
1269 * The following should be checked already.
1271 if ((i
+2) > req
->in
.vector_count
) {
1272 return NT_STATUS_INTERNAL_ERROR
;
1274 if (req
->in
.vector
[i
+0].iov_len
!= SMB2_HDR_BODY
) {
1275 return NT_STATUS_INTERNAL_ERROR
;
1277 if (req
->in
.vector
[i
+1].iov_len
< 2) {
1278 return NT_STATUS_INTERNAL_ERROR
;
1281 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1282 opcode
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
1285 case SMB2_OP_GETINFO
:
1291 * Now check the expected body size,
1292 * where the last byte might be in the
1293 * dynnamic section..
1295 if (req
->in
.vector
[i
+1].iov_len
!= (expected_body_size
& 0xFFFFFFFE)) {
1296 return NT_STATUS_INVALID_PARAMETER
;
1298 if (req
->in
.vector
[i
+2].iov_len
< min_dyn_size
) {
1299 return NT_STATUS_INVALID_PARAMETER
;
1302 inbody
= (const uint8_t *)req
->in
.vector
[i
+1].iov_base
;
1304 body_size
= SVAL(inbody
, 0x00);
1305 if (body_size
!= expected_body_size
) {
1306 return NT_STATUS_INVALID_PARAMETER
;
1309 return NT_STATUS_OK
;
1312 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
1314 const uint8_t *inhdr
;
1315 int i
= req
->current_idx
;
1320 NTSTATUS session_status
;
1321 uint32_t allowed_flags
;
1322 NTSTATUS return_value
;
1324 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1326 /* TODO: verify more things */
1328 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1329 opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1330 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1331 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1332 smb2_opcode_name(opcode
),
1333 (unsigned long long)mid
));
1335 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
1336 SMB2_HDR_FLAG_SIGNED
|
1338 if (opcode
== SMB2_OP_CANCEL
) {
1339 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
1341 if ((flags
& ~allowed_flags
) != 0) {
1342 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1346 * Check if the client provided a valid session id,
1347 * if so smbd_smb2_request_check_session() calls
1348 * set_current_user_info().
1350 * As some command don't require a valid session id
1351 * we defer the check of the session_status
1353 session_status
= smbd_smb2_request_check_session(req
);
1355 req
->do_signing
= false;
1356 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
1357 if (!NT_STATUS_IS_OK(session_status
)) {
1358 return smbd_smb2_request_error(req
, session_status
);
1361 req
->do_signing
= true;
1362 status
= smb2_signing_check_pdu(req
->session
->session_key
,
1363 &req
->in
.vector
[i
], 3);
1364 if (!NT_STATUS_IS_OK(status
)) {
1365 return smbd_smb2_request_error(req
, status
);
1367 } else if (req
->session
&& req
->session
->do_signing
) {
1368 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
1371 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
1373 * This check is mostly for giving the correct error code
1374 * for compounded requests.
1376 * TODO: we may need to move this after the session
1379 if (!NT_STATUS_IS_OK(req
->next_status
)) {
1380 return smbd_smb2_request_error(req
, req
->next_status
);
1383 req
->compat_chain_fsp
= NULL
;
1386 if (req
->compound_related
) {
1387 req
->sconn
->smb2
.compound_related_in_progress
= true;
1391 case SMB2_OP_NEGPROT
:
1392 /* This call needs to be run as root */
1393 change_to_root_user();
1396 START_PROFILE(smb2_negprot
);
1397 return_value
= smbd_smb2_request_process_negprot(req
);
1398 END_PROFILE(smb2_negprot
);
1402 case SMB2_OP_SESSSETUP
:
1403 /* This call needs to be run as root */
1404 change_to_root_user();
1407 START_PROFILE(smb2_sesssetup
);
1408 return_value
= smbd_smb2_request_process_sesssetup(req
);
1409 END_PROFILE(smb2_sesssetup
);
1413 case SMB2_OP_LOGOFF
:
1414 if (!NT_STATUS_IS_OK(session_status
)) {
1415 return_value
= smbd_smb2_request_error(req
, session_status
);
1419 /* This call needs to be run as root */
1420 change_to_root_user();
1423 START_PROFILE(smb2_logoff
);
1424 return_value
= smbd_smb2_request_process_logoff(req
);
1425 END_PROFILE(smb2_logoff
);
1430 if (!NT_STATUS_IS_OK(session_status
)) {
1431 return_value
= smbd_smb2_request_error(req
, session_status
);
1436 * This call needs to be run as root.
1438 * smbd_smb2_request_process_tcon()
1439 * calls make_connection_snum(), which will call
1440 * change_to_user(), when needed.
1442 change_to_root_user();
1445 START_PROFILE(smb2_tcon
);
1446 return_value
= smbd_smb2_request_process_tcon(req
);
1447 END_PROFILE(smb2_tcon
);
1452 if (!NT_STATUS_IS_OK(session_status
)) {
1453 return_value
= smbd_smb2_request_error(req
, session_status
);
1457 * This call needs to be run as user.
1459 * smbd_smb2_request_check_tcon()
1460 * calls change_to_user() on success.
1462 status
= smbd_smb2_request_check_tcon(req
);
1463 if (!NT_STATUS_IS_OK(status
)) {
1464 return_value
= smbd_smb2_request_error(req
, status
);
1467 /* This call needs to be run as root */
1468 change_to_root_user();
1472 START_PROFILE(smb2_tdis
);
1473 return_value
= smbd_smb2_request_process_tdis(req
);
1474 END_PROFILE(smb2_tdis
);
1478 case SMB2_OP_CREATE
:
1479 if (!NT_STATUS_IS_OK(session_status
)) {
1480 return_value
= smbd_smb2_request_error(req
, session_status
);
1484 * This call needs to be run as user.
1486 * smbd_smb2_request_check_tcon()
1487 * calls change_to_user() on success.
1489 status
= smbd_smb2_request_check_tcon(req
);
1490 if (!NT_STATUS_IS_OK(status
)) {
1491 return_value
= smbd_smb2_request_error(req
, status
);
1496 START_PROFILE(smb2_create
);
1497 return_value
= smbd_smb2_request_process_create(req
);
1498 END_PROFILE(smb2_create
);
1503 if (!NT_STATUS_IS_OK(session_status
)) {
1504 return_value
= smbd_smb2_request_error(req
, session_status
);
1508 * This call needs to be run as user.
1510 * smbd_smb2_request_check_tcon()
1511 * calls change_to_user() on success.
1513 status
= smbd_smb2_request_check_tcon(req
);
1514 if (!NT_STATUS_IS_OK(status
)) {
1515 return_value
= smbd_smb2_request_error(req
, status
);
1520 START_PROFILE(smb2_close
);
1521 return_value
= smbd_smb2_request_process_close(req
);
1522 END_PROFILE(smb2_close
);
1527 if (!NT_STATUS_IS_OK(session_status
)) {
1528 return_value
= smbd_smb2_request_error(req
, session_status
);
1532 * This call needs to be run as user.
1534 * smbd_smb2_request_check_tcon()
1535 * calls change_to_user() on success.
1537 status
= smbd_smb2_request_check_tcon(req
);
1538 if (!NT_STATUS_IS_OK(status
)) {
1539 return_value
= smbd_smb2_request_error(req
, status
);
1544 START_PROFILE(smb2_flush
);
1545 return_value
= smbd_smb2_request_process_flush(req
);
1546 END_PROFILE(smb2_flush
);
1551 if (!NT_STATUS_IS_OK(session_status
)) {
1552 return_value
= smbd_smb2_request_error(req
, session_status
);
1556 * This call needs to be run as user.
1558 * smbd_smb2_request_check_tcon()
1559 * calls change_to_user() on success.
1561 status
= smbd_smb2_request_check_tcon(req
);
1562 if (!NT_STATUS_IS_OK(status
)) {
1563 return_value
= smbd_smb2_request_error(req
, status
);
1568 START_PROFILE(smb2_read
);
1569 return_value
= smbd_smb2_request_process_read(req
);
1570 END_PROFILE(smb2_read
);
1575 if (!NT_STATUS_IS_OK(session_status
)) {
1576 return_value
= smbd_smb2_request_error(req
, session_status
);
1580 * This call needs to be run as user.
1582 * smbd_smb2_request_check_tcon()
1583 * calls change_to_user() on success.
1585 status
= smbd_smb2_request_check_tcon(req
);
1586 if (!NT_STATUS_IS_OK(status
)) {
1587 return_value
= smbd_smb2_request_error(req
, status
);
1592 START_PROFILE(smb2_write
);
1593 return_value
= smbd_smb2_request_process_write(req
);
1594 END_PROFILE(smb2_write
);
1599 if (!NT_STATUS_IS_OK(session_status
)) {
1600 /* Too ugly to live ? JRA. */
1601 if (NT_STATUS_EQUAL(session_status
,NT_STATUS_USER_SESSION_DELETED
)) {
1602 session_status
= NT_STATUS_FILE_CLOSED
;
1604 return_value
= smbd_smb2_request_error(req
, session_status
);
1608 * This call needs to be run as user.
1610 * smbd_smb2_request_check_tcon()
1611 * calls change_to_user() on success.
1613 status
= smbd_smb2_request_check_tcon(req
);
1614 if (!NT_STATUS_IS_OK(status
)) {
1615 /* Too ugly to live ? JRA. */
1616 if (NT_STATUS_EQUAL(status
,NT_STATUS_NETWORK_NAME_DELETED
)) {
1617 status
= NT_STATUS_FILE_CLOSED
;
1619 return_value
= smbd_smb2_request_error(req
, status
);
1624 START_PROFILE(smb2_lock
);
1625 return_value
= smbd_smb2_request_process_lock(req
);
1626 END_PROFILE(smb2_lock
);
1631 if (!NT_STATUS_IS_OK(session_status
)) {
1632 return_value
= smbd_smb2_request_error(req
, session_status
);
1636 * This call needs to be run as user.
1638 * smbd_smb2_request_check_tcon()
1639 * calls change_to_user() on success.
1641 status
= smbd_smb2_request_check_tcon(req
);
1642 if (!NT_STATUS_IS_OK(status
)) {
1643 return_value
= smbd_smb2_request_error(req
, status
);
1648 START_PROFILE(smb2_ioctl
);
1649 return_value
= smbd_smb2_request_process_ioctl(req
);
1650 END_PROFILE(smb2_ioctl
);
1654 case SMB2_OP_CANCEL
:
1656 * This call needs to be run as root
1658 * That is what we also do in the SMB1 case.
1660 change_to_root_user();
1663 START_PROFILE(smb2_cancel
);
1664 return_value
= smbd_smb2_request_process_cancel(req
);
1665 END_PROFILE(smb2_cancel
);
1669 case SMB2_OP_KEEPALIVE
:
1670 /* This call needs to be run as root */
1671 change_to_root_user();
1674 START_PROFILE(smb2_keepalive
);
1675 return_value
= smbd_smb2_request_process_keepalive(req
);
1676 END_PROFILE(smb2_keepalive
);
1681 if (!NT_STATUS_IS_OK(session_status
)) {
1682 return_value
= smbd_smb2_request_error(req
, session_status
);
1686 * This call needs to be run as user.
1688 * smbd_smb2_request_check_tcon()
1689 * calls change_to_user() on success.
1691 status
= smbd_smb2_request_check_tcon(req
);
1692 if (!NT_STATUS_IS_OK(status
)) {
1693 return_value
= smbd_smb2_request_error(req
, status
);
1698 START_PROFILE(smb2_find
);
1699 return_value
= smbd_smb2_request_process_find(req
);
1700 END_PROFILE(smb2_find
);
1704 case SMB2_OP_NOTIFY
:
1705 if (!NT_STATUS_IS_OK(session_status
)) {
1706 return_value
= smbd_smb2_request_error(req
, session_status
);
1710 * This call needs to be run as user.
1712 * smbd_smb2_request_check_tcon()
1713 * calls change_to_user() on success.
1715 status
= smbd_smb2_request_check_tcon(req
);
1716 if (!NT_STATUS_IS_OK(status
)) {
1717 return_value
= smbd_smb2_request_error(req
, status
);
1722 START_PROFILE(smb2_notify
);
1723 return_value
= smbd_smb2_request_process_notify(req
);
1724 END_PROFILE(smb2_notify
);
1728 case SMB2_OP_GETINFO
:
1729 if (!NT_STATUS_IS_OK(session_status
)) {
1730 return_value
= smbd_smb2_request_error(req
, session_status
);
1734 * This call needs to be run as user.
1736 * smbd_smb2_request_check_tcon()
1737 * calls change_to_user() on success.
1739 status
= smbd_smb2_request_check_tcon(req
);
1740 if (!NT_STATUS_IS_OK(status
)) {
1741 return_value
= smbd_smb2_request_error(req
, status
);
1746 START_PROFILE(smb2_getinfo
);
1747 return_value
= smbd_smb2_request_process_getinfo(req
);
1748 END_PROFILE(smb2_getinfo
);
1752 case SMB2_OP_SETINFO
:
1753 if (!NT_STATUS_IS_OK(session_status
)) {
1754 return_value
= smbd_smb2_request_error(req
, session_status
);
1758 * This call needs to be run as user.
1760 * smbd_smb2_request_check_tcon()
1761 * calls change_to_user() on success.
1763 status
= smbd_smb2_request_check_tcon(req
);
1764 if (!NT_STATUS_IS_OK(status
)) {
1765 return_value
= smbd_smb2_request_error(req
, status
);
1770 START_PROFILE(smb2_setinfo
);
1771 return_value
= smbd_smb2_request_process_setinfo(req
);
1772 END_PROFILE(smb2_setinfo
);
1777 if (!NT_STATUS_IS_OK(session_status
)) {
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 return_value
= smbd_smb2_request_error(req
, status
);
1794 START_PROFILE(smb2_break
);
1795 return_value
= smbd_smb2_request_process_break(req
);
1796 END_PROFILE(smb2_break
);
1801 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1804 return return_value
;
1807 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
1809 struct tevent_req
*subreq
;
1810 int i
= req
->current_idx
;
1814 req
->current_idx
+= 3;
1816 if (req
->current_idx
< req
->out
.vector_count
) {
1818 * We must process the remaining compound
1819 * SMB2 requests before any new incoming SMB2
1820 * requests. This is because incoming SMB2
1821 * requests may include a cancel for a
1822 * compound request we haven't processed
1825 struct tevent_immediate
*im
= tevent_create_immediate(req
);
1827 return NT_STATUS_NO_MEMORY
;
1829 tevent_schedule_immediate(im
,
1830 req
->sconn
->smb2
.event_ctx
,
1831 smbd_smb2_request_dispatch_immediate
,
1833 return NT_STATUS_OK
;
1836 if (req
->compound_related
) {
1837 req
->sconn
->smb2
.compound_related_in_progress
= false;
1840 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
1842 /* Set credit for this operation (zero credits if this
1843 is a final reply for an async operation). */
1844 smb2_set_operation_credit(req
->sconn
,
1846 &req
->out
.vector
[i
]);
1848 if (req
->do_signing
) {
1850 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
1851 &req
->out
.vector
[i
], 3);
1852 if (!NT_STATUS_IS_OK(status
)) {
1857 if (DEBUGLEVEL
>= 10) {
1858 dbgtext("smbd_smb2_request_reply: sending...\n");
1859 print_req_vectors(req
);
1862 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1863 if (req
->out
.vector_count
== 4 &&
1864 req
->out
.vector
[3].iov_base
== NULL
&&
1865 req
->out
.vector
[3].iov_len
!= 0) {
1866 /* Dynamic part is NULL. Chop it off,
1867 We're going to send it via sendfile. */
1868 req
->out
.vector_count
-= 1;
1871 subreq
= tstream_writev_queue_send(req
,
1872 req
->sconn
->smb2
.event_ctx
,
1873 req
->sconn
->smb2
.stream
,
1874 req
->sconn
->smb2
.send_queue
,
1876 req
->out
.vector_count
);
1877 if (subreq
== NULL
) {
1878 return NT_STATUS_NO_MEMORY
;
1880 tevent_req_set_callback(subreq
, smbd_smb2_request_writev_done
, req
);
1882 * We're done with this request -
1883 * move it off the "being processed" queue.
1885 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1887 return NT_STATUS_OK
;
1890 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
);
1892 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
1893 struct tevent_immediate
*im
,
1896 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
1897 struct smbd_smb2_request
);
1898 struct smbd_server_connection
*sconn
= req
->sconn
;
1903 if (DEBUGLEVEL
>= 10) {
1904 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1905 req
->current_idx
, req
->in
.vector_count
));
1906 print_req_vectors(req
);
1909 status
= smbd_smb2_request_dispatch(req
);
1910 if (!NT_STATUS_IS_OK(status
)) {
1911 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1915 status
= smbd_smb2_request_next_incoming(sconn
);
1916 if (!NT_STATUS_IS_OK(status
)) {
1917 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1922 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
)
1924 struct smbd_smb2_request
*req
= tevent_req_callback_data(subreq
,
1925 struct smbd_smb2_request
);
1926 struct smbd_server_connection
*sconn
= req
->sconn
;
1931 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1932 TALLOC_FREE(subreq
);
1935 status
= map_nt_error_from_unix(sys_errno
);
1936 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1937 nt_errstr(status
)));
1938 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1942 status
= smbd_smb2_request_next_incoming(sconn
);
1943 if (!NT_STATUS_IS_OK(status
)) {
1944 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1949 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
1951 DATA_BLOB body
, DATA_BLOB
*dyn
,
1952 const char *location
)
1955 int i
= req
->current_idx
;
1956 uint32_t next_command_ofs
;
1958 DEBUG(10,("smbd_smb2_request_done_ex: "
1959 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1960 i
, nt_errstr(status
), (unsigned int)body
.length
,
1962 (unsigned int)(dyn
? dyn
->length
: 0),
1965 if (body
.length
< 2) {
1966 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
1969 if ((body
.length
% 2) != 0) {
1970 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
1973 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
1975 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
1976 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
1978 req
->out
.vector
[i
+1].iov_base
= (void *)body
.data
;
1979 req
->out
.vector
[i
+1].iov_len
= body
.length
;
1982 req
->out
.vector
[i
+2].iov_base
= (void *)dyn
->data
;
1983 req
->out
.vector
[i
+2].iov_len
= dyn
->length
;
1985 req
->out
.vector
[i
+2].iov_base
= NULL
;
1986 req
->out
.vector
[i
+2].iov_len
= 0;
1989 /* see if we need to recalculate the offset to the next response */
1990 if (next_command_ofs
> 0) {
1991 next_command_ofs
= SMB2_HDR_BODY
;
1992 next_command_ofs
+= req
->out
.vector
[i
+1].iov_len
;
1993 next_command_ofs
+= req
->out
.vector
[i
+2].iov_len
;
1996 if ((next_command_ofs
% 8) != 0) {
1997 size_t pad_size
= 8 - (next_command_ofs
% 8);
1998 if (req
->out
.vector
[i
+2].iov_len
== 0) {
2000 * if the dyn buffer is empty
2001 * we can use it to add padding
2005 pad
= talloc_zero_array(req
->out
.vector
,
2008 return smbd_smb2_request_error(req
,
2009 NT_STATUS_NO_MEMORY
);
2012 req
->out
.vector
[i
+2].iov_base
= (void *)pad
;
2013 req
->out
.vector
[i
+2].iov_len
= pad_size
;
2016 * For now we copy the dynamic buffer
2017 * and add the padding to the new buffer
2024 old_size
= req
->out
.vector
[i
+2].iov_len
;
2025 old_dyn
= (uint8_t *)req
->out
.vector
[i
+2].iov_base
;
2027 new_size
= old_size
+ pad_size
;
2028 new_dyn
= talloc_zero_array(req
->out
.vector
,
2030 if (new_dyn
== NULL
) {
2031 return smbd_smb2_request_error(req
,
2032 NT_STATUS_NO_MEMORY
);
2035 memcpy(new_dyn
, old_dyn
, old_size
);
2036 memset(new_dyn
+ old_size
, 0, pad_size
);
2038 req
->out
.vector
[i
+2].iov_base
= (void *)new_dyn
;
2039 req
->out
.vector
[i
+2].iov_len
= new_size
;
2041 next_command_ofs
+= pad_size
;
2044 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
2046 return smbd_smb2_request_reply(req
);
2049 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
2052 const char *location
)
2055 int i
= req
->current_idx
;
2056 uint8_t *outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
2058 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2059 i
, nt_errstr(status
), info
? " +info" : "",
2062 body
.data
= outhdr
+ SMB2_HDR_BODY
;
2064 SSVAL(body
.data
, 0, 9);
2067 SIVAL(body
.data
, 0x04, info
->length
);
2069 /* Allocated size of req->out.vector[i].iov_base
2070 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2071 * 1 byte without having to do an alloc.
2073 info
= talloc_zero_array(req
->out
.vector
,
2077 return NT_STATUS_NO_MEMORY
;
2079 info
->data
= ((uint8_t *)outhdr
) +
2080 OUTVEC_ALLOC_SIZE
- 1;
2082 SCVAL(info
->data
, 0, 0);
2086 * if a request fails, all other remaining
2087 * compounded requests should fail too
2089 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
2091 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
2095 struct smbd_smb2_send_oplock_break_state
{
2096 struct smbd_server_connection
*sconn
;
2097 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x18];
2098 struct iovec vector
;
2101 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
);
2103 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
2104 uint64_t file_id_persistent
,
2105 uint64_t file_id_volatile
,
2106 uint8_t oplock_level
)
2108 struct smbd_smb2_send_oplock_break_state
*state
;
2109 struct tevent_req
*subreq
;
2113 state
= talloc(sconn
, struct smbd_smb2_send_oplock_break_state
);
2114 if (state
== NULL
) {
2115 return NT_STATUS_NO_MEMORY
;
2117 state
->sconn
= sconn
;
2119 state
->vector
.iov_base
= (void *)state
->buf
;
2120 state
->vector
.iov_len
= sizeof(state
->buf
);
2122 _smb2_setlen(state
->buf
, sizeof(state
->buf
) - 4);
2123 hdr
= state
->buf
+ 4;
2124 body
= hdr
+ SMB2_HDR_BODY
;
2126 SIVAL(hdr
, 0, SMB2_MAGIC
);
2127 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
2128 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
2129 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
2130 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
2131 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
2132 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
2133 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
2134 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
2135 SIVAL(hdr
, SMB2_HDR_PID
, 0);
2136 SIVAL(hdr
, SMB2_HDR_TID
, 0);
2137 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
2138 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
2140 SSVAL(body
, 0x00, 0x18);
2142 SCVAL(body
, 0x02, oplock_level
);
2143 SCVAL(body
, 0x03, 0); /* reserved */
2144 SIVAL(body
, 0x04, 0); /* reserved */
2145 SBVAL(body
, 0x08, file_id_persistent
);
2146 SBVAL(body
, 0x10, file_id_volatile
);
2148 subreq
= tstream_writev_queue_send(state
,
2149 sconn
->smb2
.event_ctx
,
2151 sconn
->smb2
.send_queue
,
2153 if (subreq
== NULL
) {
2154 return NT_STATUS_NO_MEMORY
;
2156 tevent_req_set_callback(subreq
,
2157 smbd_smb2_oplock_break_writev_done
,
2160 return NT_STATUS_OK
;
2163 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
)
2165 struct smbd_smb2_send_oplock_break_state
*state
=
2166 tevent_req_callback_data(subreq
,
2167 struct smbd_smb2_send_oplock_break_state
);
2168 struct smbd_server_connection
*sconn
= state
->sconn
;
2172 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
2173 TALLOC_FREE(subreq
);
2175 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
2176 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2183 struct smbd_smb2_request_read_state
{
2185 bool asked_for_header
;
2186 struct smbd_smb2_request
*smb2_req
;
2189 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2191 TALLOC_CTX
*mem_ctx
,
2192 struct iovec
**_vector
,
2194 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
);
2196 static struct tevent_req
*smbd_smb2_request_read_send(TALLOC_CTX
*mem_ctx
,
2197 struct tevent_context
*ev
,
2198 struct smbd_server_connection
*sconn
)
2200 struct tevent_req
*req
;
2201 struct smbd_smb2_request_read_state
*state
;
2202 struct tevent_req
*subreq
;
2204 req
= tevent_req_create(mem_ctx
, &state
,
2205 struct smbd_smb2_request_read_state
);
2210 state
->asked_for_header
= false;
2212 state
->smb2_req
= smbd_smb2_request_allocate(state
);
2213 if (tevent_req_nomem(state
->smb2_req
, req
)) {
2214 return tevent_req_post(req
, ev
);
2216 state
->smb2_req
->sconn
= sconn
;
2218 subreq
= tstream_readv_pdu_queue_send(state
, ev
, sconn
->smb2
.stream
,
2219 sconn
->smb2
.recv_queue
,
2220 smbd_smb2_request_next_vector
,
2222 if (tevent_req_nomem(subreq
, req
)) {
2223 return tevent_req_post(req
, ev
);
2225 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
2230 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2232 TALLOC_CTX
*mem_ctx
,
2233 struct iovec
**_vector
,
2236 struct smbd_smb2_request_read_state
*state
=
2237 talloc_get_type_abort(private_data
,
2238 struct smbd_smb2_request_read_state
);
2239 struct smbd_smb2_request
*req
= state
->smb2_req
;
2240 struct iovec
*vector
;
2241 int idx
= req
->in
.vector_count
;
2243 uint8_t *buf
= NULL
;
2245 if (req
->in
.vector_count
== 0) {
2247 * first we need to get the NBT header
2249 req
->in
.vector
= talloc_array(req
, struct iovec
,
2250 req
->in
.vector_count
+ 1);
2251 if (req
->in
.vector
== NULL
) {
2254 req
->in
.vector_count
+= 1;
2256 req
->in
.vector
[idx
].iov_base
= (void *)req
->in
.nbt_hdr
;
2257 req
->in
.vector
[idx
].iov_len
= 4;
2259 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2260 if (vector
== NULL
) {
2264 vector
[0] = req
->in
.vector
[idx
];
2271 if (req
->in
.vector_count
== 1) {
2273 * Now we analyze the NBT header
2275 state
->missing
= smb2_len(req
->in
.vector
[0].iov_base
);
2277 if (state
->missing
== 0) {
2278 /* if there're no remaining bytes, we're done */
2284 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2286 req
->in
.vector_count
+ 1);
2287 if (req
->in
.vector
== NULL
) {
2290 req
->in
.vector_count
+= 1;
2292 if (CVAL(req
->in
.vector
[0].iov_base
, 0) != 0) {
2294 * it's a special NBT message,
2295 * so get all remaining bytes
2297 len
= state
->missing
;
2298 } else if (state
->missing
< (SMB2_HDR_BODY
+ 2)) {
2300 * it's an invalid message, just read what we can get
2301 * and let the caller handle the error
2303 len
= state
->missing
;
2306 * We assume it's a SMB2 request,
2307 * and we first get the header and the
2308 * first 2 bytes (the struct size) of the body
2310 len
= SMB2_HDR_BODY
+ 2;
2312 state
->asked_for_header
= true;
2315 state
->missing
-= len
;
2317 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2322 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2323 req
->in
.vector
[idx
].iov_len
= len
;
2325 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2326 if (vector
== NULL
) {
2330 vector
[0] = req
->in
.vector
[idx
];
2337 if (state
->missing
== 0) {
2338 /* if there're no remaining bytes, we're done */
2344 if (state
->asked_for_header
) {
2347 size_t next_command_ofs
;
2352 bool invalid
= false;
2354 state
->asked_for_header
= false;
2357 * We got the SMB2 header and the first 2 bytes
2358 * of the body. We fix the size to just the header
2359 * and manually copy the 2 first bytes to the body section
2361 req
->in
.vector
[idx
-1].iov_len
= SMB2_HDR_BODY
;
2362 hdr
= (const uint8_t *)req
->in
.vector
[idx
-1].iov_base
;
2364 /* allocate vectors for body and dynamic areas */
2365 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2367 req
->in
.vector_count
+ 2);
2368 if (req
->in
.vector
== NULL
) {
2371 req
->in
.vector_count
+= 2;
2373 full_size
= state
->missing
+ SMB2_HDR_BODY
+ 2;
2374 next_command_ofs
= IVAL(hdr
, SMB2_HDR_NEXT_COMMAND
);
2375 body_size
= SVAL(hdr
, SMB2_HDR_BODY
);
2377 if (next_command_ofs
!= 0) {
2378 if (next_command_ofs
< (SMB2_HDR_BODY
+ 2)) {
2380 * this is invalid, just return a zero
2381 * body and let the caller deal with the error
2384 } else if (next_command_ofs
> full_size
) {
2386 * this is invalid, just return a zero
2387 * body and let the caller deal with the error
2391 full_size
= next_command_ofs
;
2396 if (body_size
< 2) {
2398 * this is invalid, just return a zero
2399 * body and let the caller deal with the error
2405 * Mask out the lowest bit, the "dynamic" part
2410 if (body_size
> (full_size
- SMB2_HDR_BODY
)) {
2412 * this is invalid, just return a zero
2413 * body and let the caller deal with the error
2420 /* the caller should check this */
2424 dyn_size
= full_size
- (SMB2_HDR_BODY
+ body_size
);
2426 state
->missing
-= (body_size
- 2) + dyn_size
;
2428 body
= talloc_array(req
->in
.vector
, uint8_t, body_size
);
2433 dyn
= talloc_array(req
->in
.vector
, uint8_t, dyn_size
);
2438 req
->in
.vector
[idx
].iov_base
= (void *)body
;
2439 req
->in
.vector
[idx
].iov_len
= body_size
;
2440 req
->in
.vector
[idx
+1].iov_base
= (void *)dyn
;
2441 req
->in
.vector
[idx
+1].iov_len
= dyn_size
;
2443 vector
= talloc_array(mem_ctx
, struct iovec
, 2);
2444 if (vector
== NULL
) {
2449 * the first 2 bytes of the body were already fetched
2450 * together with the header
2452 memcpy(body
, hdr
+ SMB2_HDR_BODY
, 2);
2453 vector
[0].iov_base
= body
+ 2;
2454 vector
[0].iov_len
= body_size
- 2;
2456 vector
[1] = req
->in
.vector
[idx
+1];
2464 * when we endup here, we're looking for a new SMB2 request
2465 * next. And we ask for its header and the first 2 bytes of
2466 * the body (like we did for the first SMB2 request).
2469 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2471 req
->in
.vector_count
+ 1);
2472 if (req
->in
.vector
== NULL
) {
2475 req
->in
.vector_count
+= 1;
2478 * We assume it's a SMB2 request,
2479 * and we first get the header and the
2480 * first 2 bytes (the struct size) of the body
2482 len
= SMB2_HDR_BODY
+ 2;
2484 if (len
> state
->missing
) {
2485 /* let the caller handle the error */
2486 len
= state
->missing
;
2489 state
->missing
-= len
;
2490 state
->asked_for_header
= true;
2492 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2497 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2498 req
->in
.vector
[idx
].iov_len
= len
;
2500 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2501 if (vector
== NULL
) {
2505 vector
[0] = req
->in
.vector
[idx
];
2512 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
)
2514 struct tevent_req
*req
=
2515 tevent_req_callback_data(subreq
,
2521 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
2523 status
= map_nt_error_from_unix(sys_errno
);
2524 tevent_req_nterror(req
, status
);
2528 tevent_req_done(req
);
2531 static NTSTATUS
smbd_smb2_request_read_recv(struct tevent_req
*req
,
2532 TALLOC_CTX
*mem_ctx
,
2533 struct smbd_smb2_request
**_smb2_req
)
2535 struct smbd_smb2_request_read_state
*state
=
2536 tevent_req_data(req
,
2537 struct smbd_smb2_request_read_state
);
2540 if (tevent_req_is_nterror(req
, &status
)) {
2541 tevent_req_received(req
);
2545 talloc_steal(mem_ctx
, state
->smb2_req
->mem_pool
);
2546 *_smb2_req
= state
->smb2_req
;
2547 tevent_req_received(req
);
2548 return NT_STATUS_OK
;
2551 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
);
2553 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
)
2555 size_t max_send_queue_len
;
2556 size_t cur_send_queue_len
;
2557 struct tevent_req
*subreq
;
2559 if (sconn
->smb2
.compound_related_in_progress
) {
2561 * Can't read another until the related
2564 return NT_STATUS_OK
;
2567 if (tevent_queue_length(sconn
->smb2
.recv_queue
) > 0) {
2569 * if there is already a smbd_smb2_request_read
2570 * pending, we are done.
2572 return NT_STATUS_OK
;
2575 max_send_queue_len
= MAX(1, sconn
->smb2
.max_credits
/16);
2576 cur_send_queue_len
= tevent_queue_length(sconn
->smb2
.send_queue
);
2578 if (cur_send_queue_len
> max_send_queue_len
) {
2580 * if we have a lot of requests to send,
2581 * we wait until they are on the wire until we
2582 * ask for the next request.
2584 return NT_STATUS_OK
;
2587 /* ask for the next request */
2588 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->smb2
.event_ctx
, sconn
);
2589 if (subreq
== NULL
) {
2590 return NT_STATUS_NO_MEMORY
;
2592 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);
2594 return NT_STATUS_OK
;
2597 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
2598 const uint8_t *inbuf
, size_t size
)
2601 struct smbd_smb2_request
*req
= NULL
;
2603 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2604 (unsigned int)size
));
2606 status
= smbd_initialize_smb2(sconn
);
2607 if (!NT_STATUS_IS_OK(status
)) {
2608 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2612 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
2613 if (!NT_STATUS_IS_OK(status
)) {
2614 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2618 status
= smbd_smb2_request_setup_out(req
);
2619 if (!NT_STATUS_IS_OK(status
)) {
2620 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2624 status
= smbd_smb2_request_dispatch(req
);
2625 if (!NT_STATUS_IS_OK(status
)) {
2626 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2630 status
= smbd_smb2_request_next_incoming(sconn
);
2631 if (!NT_STATUS_IS_OK(status
)) {
2632 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2636 sconn
->num_requests
++;
2639 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
)
2641 struct smbd_server_connection
*sconn
= tevent_req_callback_data(subreq
,
2642 struct smbd_server_connection
);
2644 struct smbd_smb2_request
*req
= NULL
;
2646 status
= smbd_smb2_request_read_recv(subreq
, sconn
, &req
);
2647 TALLOC_FREE(subreq
);
2648 if (!NT_STATUS_IS_OK(status
)) {
2649 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2650 nt_errstr(status
)));
2651 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2655 if (req
->in
.nbt_hdr
[0] != 0x00) {
2656 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2657 req
->in
.nbt_hdr
[0]));
2662 req
->current_idx
= 1;
2664 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2665 req
->current_idx
, req
->in
.vector_count
));
2667 status
= smbd_smb2_request_validate(req
);
2668 if (!NT_STATUS_IS_OK(status
)) {
2669 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2673 status
= smbd_smb2_request_setup_out(req
);
2674 if (!NT_STATUS_IS_OK(status
)) {
2675 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2679 status
= smbd_smb2_request_dispatch(req
);
2680 if (!NT_STATUS_IS_OK(status
)) {
2681 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2686 status
= smbd_smb2_request_next_incoming(sconn
);
2687 if (!NT_STATUS_IS_OK(status
)) {
2688 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2692 sconn
->num_requests
++;
2694 /* The timeout_processing function isn't run nearly
2695 often enough to implement 'max log size' without
2696 overrunning the size of the file by many megabytes.
2697 This is especially true if we are running at debug
2698 level 10. Checking every 50 SMB2s is a nice
2699 tradeoff of performance vs log file size overrun. */
2701 if ((sconn
->num_requests
% 50) == 0 &&
2702 need_to_check_log_size()) {
2703 change_to_root_user();