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 /* client just used a credit. */
326 SMB_ASSERT(sconn
->smb2
.credits_granted
> 0);
327 sconn
->smb2
.credits_granted
-= 1;
329 /* Mark the message_id as seen in the bitmap. */
330 bitmap_offset
= (unsigned int)(message_id
%
331 (uint64_t)(sconn
->smb2
.max_credits
* DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
));
332 if (bitmap_query(credits_bm
, bitmap_offset
)) {
333 DEBUG(0,("smb2_validate_message_id: duplicate message_id "
334 "%llu (bm offset %u)\n",
335 (unsigned long long)message_id
,
339 bitmap_set(credits_bm
, bitmap_offset
);
341 if (message_id
== sconn
->smb2
.seqnum_low
+ 1) {
342 /* Move the window forward by all the message_id's
344 while (bitmap_query(credits_bm
, bitmap_offset
)) {
345 DEBUG(10,("smb2_validate_message_id: clearing "
346 "id %llu (position %u) from bitmap\n",
347 (unsigned long long)(sconn
->smb2
.seqnum_low
+ 1),
349 bitmap_clear(credits_bm
, bitmap_offset
);
350 sconn
->smb2
.seqnum_low
+= 1;
351 bitmap_offset
= (bitmap_offset
+ 1) %
352 (sconn
->smb2
.max_credits
* DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
);
359 static NTSTATUS
smbd_smb2_request_validate(struct smbd_smb2_request
*req
)
363 bool compound_related
= false;
365 count
= req
->in
.vector_count
;
368 /* It's not a SMB2 request */
369 return NT_STATUS_INVALID_PARAMETER
;
372 for (idx
=1; idx
< count
; idx
+= 3) {
373 const uint8_t *inhdr
= NULL
;
376 if (req
->in
.vector
[idx
].iov_len
!= SMB2_HDR_BODY
) {
377 return NT_STATUS_INVALID_PARAMETER
;
380 if (req
->in
.vector
[idx
+1].iov_len
< 2) {
381 return NT_STATUS_INVALID_PARAMETER
;
384 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
386 /* Check the SMB2 header */
387 if (IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
) != SMB2_MAGIC
) {
388 return NT_STATUS_INVALID_PARAMETER
;
391 if (!smb2_validate_message_id(req
->sconn
, inhdr
)) {
392 return NT_STATUS_INVALID_PARAMETER
;
395 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
398 * the 1st request should never have the
399 * SMB2_HDR_FLAG_CHAINED flag set
401 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
402 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
405 } else if (idx
== 4) {
407 * the 2nd request triggers related vs. unrelated
408 * compounded requests
410 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
411 compound_related
= true;
413 } else if (idx
> 4) {
416 * It seems the this tests are wrong
417 * see the SMB2-COMPOUND test
421 * all other requests should match the 2nd one
423 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
424 if (!compound_related
) {
426 NT_STATUS_INVALID_PARAMETER
;
430 if (compound_related
) {
432 NT_STATUS_INVALID_PARAMETER
;
443 static void smb2_set_operation_credit(struct smbd_server_connection
*sconn
,
444 const struct iovec
*in_vector
,
445 struct iovec
*out_vector
)
447 const uint8_t *inhdr
= (const uint8_t *)in_vector
->iov_base
;
448 uint8_t *outhdr
= (uint8_t *)out_vector
->iov_base
;
449 uint16_t credits_requested
;
451 uint16_t credits_granted
= 0;
453 credits_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
454 out_flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
456 SMB_ASSERT(sconn
->smb2
.max_credits
>= sconn
->smb2
.credits_granted
);
458 if (out_flags
& SMB2_HDR_FLAG_ASYNC
) {
460 * In case we already send an async interim
461 * response, we should not grant
462 * credits on the final response.
464 credits_requested
= 0;
467 if (credits_requested
) {
468 uint16_t modified_credits_requested
;
472 * Split up max_credits into 1/16ths, and then scale
473 * the requested credits by how many 16ths have been
474 * currently granted. Less than 1/16th == grant all
475 * requested (100%), scale down as more have been
476 * granted. Never ask for less than 1 as the client
477 * asked for at least 1. JRA.
480 multiplier
= 16 - (((sconn
->smb2
.credits_granted
* 16) / sconn
->smb2
.max_credits
) % 16);
482 modified_credits_requested
= (multiplier
* credits_requested
) / 16;
483 if (modified_credits_requested
== 0) {
484 modified_credits_requested
= 1;
487 /* Remember what we gave out. */
488 credits_granted
= MIN(modified_credits_requested
,
489 (sconn
->smb2
.max_credits
- sconn
->smb2
.credits_granted
));
492 if (credits_granted
== 0 && sconn
->smb2
.credits_granted
== 0) {
493 /* First negprot packet, or ensure the client credits can
494 never drop to zero. */
498 SSVAL(outhdr
, SMB2_HDR_CREDIT
, credits_granted
);
499 sconn
->smb2
.credits_granted
+= credits_granted
;
501 DEBUG(10,("smb2_set_operation_credit: requested %u, "
502 "granted %u, total granted %u\n",
503 (unsigned int)credits_requested
,
504 (unsigned int)credits_granted
,
505 (unsigned int)sconn
->smb2
.credits_granted
));
508 static void smb2_calculate_credits(const struct smbd_smb2_request
*inreq
,
509 struct smbd_smb2_request
*outreq
)
513 count
= outreq
->out
.vector_count
;
515 for (idx
=1; idx
< count
; idx
+= 3) {
516 smb2_set_operation_credit(outreq
->sconn
,
517 &inreq
->in
.vector
[idx
],
518 &outreq
->out
.vector
[idx
]);
522 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
)
524 struct iovec
*vector
;
528 count
= req
->in
.vector_count
;
529 vector
= talloc_zero_array(req
, struct iovec
, count
);
530 if (vector
== NULL
) {
531 return NT_STATUS_NO_MEMORY
;
534 vector
[0].iov_base
= req
->out
.nbt_hdr
;
535 vector
[0].iov_len
= 4;
536 SIVAL(req
->out
.nbt_hdr
, 0, 0);
538 for (idx
=1; idx
< count
; idx
+= 3) {
539 const uint8_t *inhdr
= NULL
;
541 uint8_t *outhdr
= NULL
;
542 uint8_t *outbody
= NULL
;
543 uint32_t next_command_ofs
= 0;
544 struct iovec
*current
= &vector
[idx
];
546 if ((idx
+ 3) < count
) {
547 /* we have a next command -
548 * setup for the error case. */
549 next_command_ofs
= SMB2_HDR_BODY
+ 9;
552 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
553 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
555 outhdr
= talloc_zero_array(vector
, uint8_t,
557 if (outhdr
== NULL
) {
558 return NT_STATUS_NO_MEMORY
;
561 outbody
= outhdr
+ SMB2_HDR_BODY
;
563 current
[0].iov_base
= (void *)outhdr
;
564 current
[0].iov_len
= SMB2_HDR_BODY
;
566 current
[1].iov_base
= (void *)outbody
;
567 current
[1].iov_len
= 8;
569 current
[2].iov_base
= NULL
;
570 current
[2].iov_len
= 0;
572 /* setup the SMB2 header */
573 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
574 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
575 SSVAL(outhdr
, SMB2_HDR_EPOCH
, 0);
576 SIVAL(outhdr
, SMB2_HDR_STATUS
,
577 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
578 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
579 SVAL(inhdr
, SMB2_HDR_OPCODE
));
580 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
581 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
582 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
583 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
584 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
585 SIVAL(outhdr
, SMB2_HDR_PID
,
586 IVAL(inhdr
, SMB2_HDR_PID
));
587 SIVAL(outhdr
, SMB2_HDR_TID
,
588 IVAL(inhdr
, SMB2_HDR_TID
));
589 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
590 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
591 memset(outhdr
+ SMB2_HDR_SIGNATURE
, 0, 16);
593 /* setup error body header */
594 SSVAL(outbody
, 0x00, 0x08 + 1);
595 SSVAL(outbody
, 0x02, 0);
596 SIVAL(outbody
, 0x04, 0);
599 req
->out
.vector
= vector
;
600 req
->out
.vector_count
= count
;
602 /* setup the length of the NBT packet */
603 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
605 DLIST_ADD_END(req
->sconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
610 void smbd_server_connection_terminate_ex(struct smbd_server_connection
*sconn
,
612 const char *location
)
614 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
616 exit_server_cleanly(reason
);
619 static bool dup_smb2_vec3(TALLOC_CTX
*ctx
,
620 struct iovec
*outvec
,
621 const struct iovec
*srcvec
)
623 /* vec[0] is always boilerplate and must
624 * be allocated with size OUTVEC_ALLOC_SIZE. */
626 outvec
[0].iov_base
= talloc_memdup(ctx
,
629 if (!outvec
[0].iov_base
) {
632 outvec
[0].iov_len
= SMB2_HDR_BODY
;
635 * If this is a "standard" vec[1] of length 8,
636 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
637 * then duplicate this. Else use talloc_memdup().
640 if (srcvec
[1].iov_len
== 8 &&
641 srcvec
[1].iov_base
==
642 ((uint8_t *)srcvec
[0].iov_base
) +
644 outvec
[1].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
646 outvec
[1].iov_len
= 8;
648 outvec
[1].iov_base
= talloc_memdup(ctx
,
651 if (!outvec
[1].iov_base
) {
654 outvec
[1].iov_len
= srcvec
[1].iov_len
;
658 * If this is a "standard" vec[2] of length 1,
659 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
660 * then duplicate this. Else use talloc_memdup().
663 if (srcvec
[2].iov_base
&&
665 if (srcvec
[2].iov_base
==
666 ((uint8_t *)srcvec
[0].iov_base
) +
667 (OUTVEC_ALLOC_SIZE
- 1) &&
668 srcvec
[2].iov_len
== 1) {
669 /* Common SMB2 error packet case. */
670 outvec
[2].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
671 (OUTVEC_ALLOC_SIZE
- 1);
673 outvec
[2].iov_base
= talloc_memdup(ctx
,
676 if (!outvec
[2].iov_base
) {
680 outvec
[2].iov_len
= srcvec
[2].iov_len
;
682 outvec
[2].iov_base
= NULL
;
683 outvec
[2].iov_len
= 0;
688 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
690 struct smbd_smb2_request
*newreq
= NULL
;
691 struct iovec
*outvec
= NULL
;
692 int count
= req
->out
.vector_count
;
695 newreq
= smbd_smb2_request_allocate(req
->sconn
);
700 newreq
->sconn
= req
->sconn
;
701 newreq
->session
= req
->session
;
702 newreq
->do_signing
= req
->do_signing
;
703 newreq
->current_idx
= req
->current_idx
;
704 newreq
->async
= false;
705 newreq
->cancelled
= false;
706 /* Note we are leaving:
710 uninitialized as NULL here as
711 they're not used in the interim
712 response code. JRA. */
714 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
719 newreq
->out
.vector
= outvec
;
720 newreq
->out
.vector_count
= count
;
722 /* Setup the outvec's identically to req. */
723 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
724 outvec
[0].iov_len
= 4;
725 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
727 /* Setup the vectors identically to the ones in req. */
728 for (i
= 1; i
< count
; i
+= 3) {
729 if (!dup_smb2_vec3(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
740 smb2_setup_nbt_length(newreq
->out
.vector
,
741 newreq
->out
.vector_count
);
746 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
);
748 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
751 uint8_t *outhdr
= NULL
;
752 struct smbd_smb2_request
*nreq
= NULL
;
754 /* Create a new smb2 request we'll use
755 for the interim return. */
756 nreq
= dup_smb2_req(req
);
758 return NT_STATUS_NO_MEMORY
;
761 /* Lose the last 3 out vectors. They're the
762 ones we'll be using for the async reply. */
763 nreq
->out
.vector_count
-= 3;
765 smb2_setup_nbt_length(nreq
->out
.vector
,
766 nreq
->out
.vector_count
);
768 /* Step back to the previous reply. */
769 i
= nreq
->current_idx
- 3;
770 outhdr
= (uint8_t *)nreq
->out
.vector
[i
].iov_base
;
771 /* And end the chain. */
772 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
774 /* Calculate outgoing credits */
775 smb2_calculate_credits(req
, nreq
);
777 /* Re-sign if needed. */
778 if (nreq
->do_signing
) {
780 status
= smb2_signing_sign_pdu(nreq
->session
->session_key
,
781 &nreq
->out
.vector
[i
], 3);
782 if (!NT_STATUS_IS_OK(status
)) {
786 if (DEBUGLEVEL
>= 10) {
787 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
788 (unsigned int)nreq
->current_idx
);
789 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
790 (unsigned int)nreq
->out
.vector_count
);
791 print_req_vectors(nreq
);
793 nreq
->subreq
= tstream_writev_queue_send(nreq
,
794 nreq
->sconn
->smb2
.event_ctx
,
795 nreq
->sconn
->smb2
.stream
,
796 nreq
->sconn
->smb2
.send_queue
,
798 nreq
->out
.vector_count
);
800 if (nreq
->subreq
== NULL
) {
801 return NT_STATUS_NO_MEMORY
;
804 tevent_req_set_callback(nreq
->subreq
,
805 smbd_smb2_request_writev_done
,
811 struct smbd_smb2_request_pending_state
{
812 struct smbd_server_connection
*sconn
;
813 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x08 + 1];
814 struct iovec vector
[3];
817 static void smbd_smb2_request_pending_writev_done(struct tevent_req
*subreq
)
819 struct smbd_smb2_request_pending_state
*state
=
820 tevent_req_callback_data(subreq
,
821 struct smbd_smb2_request_pending_state
);
822 struct smbd_server_connection
*sconn
= state
->sconn
;
826 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
829 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
830 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
837 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
838 struct tevent_req
*subreq
)
841 struct smbd_smb2_request_pending_state
*state
= NULL
;
842 int i
= req
->current_idx
;
843 uint8_t *reqhdr
= NULL
;
845 uint8_t *body
= NULL
;
847 uint64_t message_id
= 0;
848 uint64_t async_id
= 0;
849 struct iovec
*outvec
= NULL
;
851 if (!tevent_req_is_in_progress(subreq
)) {
855 req
->subreq
= subreq
;
859 /* We're already async. */
863 if (req
->in
.vector_count
> i
+ 3) {
865 * We're trying to go async in a compound
866 * request chain. This is not allowed.
867 * Cancel the outstanding request.
869 tevent_req_cancel(req
->subreq
);
870 return smbd_smb2_request_error(req
,
871 NT_STATUS_INSUFFICIENT_RESOURCES
);
874 if (DEBUGLEVEL
>= 10) {
875 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
876 (unsigned int)req
->current_idx
);
877 print_req_vectors(req
);
880 if (req
->out
.vector_count
> 4) {
881 /* This is a compound reply. We
882 * must do an interim response
883 * followed by the async response
886 status
= smb2_send_async_interim_response(req
);
887 if (!NT_STATUS_IS_OK(status
)) {
892 /* Don't return an intermediate packet on a pipe read/write. */
893 if (req
->tcon
&& req
->tcon
->compat_conn
&& IS_IPC(req
->tcon
->compat_conn
)) {
897 reqhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
898 flags
= (IVAL(reqhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
899 message_id
= BVAL(reqhdr
, SMB2_HDR_MESSAGE_ID
);
900 async_id
= message_id
; /* keep it simple for now... */
903 * What we send is identical to a smbd_smb2_request_error
904 * packet with an error status of STATUS_PENDING. Make use
905 * of this fact sometime when refactoring. JRA.
908 state
= talloc_zero(req
->sconn
, struct smbd_smb2_request_pending_state
);
910 return NT_STATUS_NO_MEMORY
;
912 state
->sconn
= req
->sconn
;
914 state
->vector
[0].iov_base
= (void *)state
->buf
;
915 state
->vector
[0].iov_len
= 4;
917 state
->vector
[1].iov_base
= state
->buf
+ 4;
918 state
->vector
[1].iov_len
= SMB2_HDR_BODY
;
920 state
->vector
[2].iov_base
= state
->buf
+ 4 + SMB2_HDR_BODY
;
921 state
->vector
[2].iov_len
= 9;
923 smb2_setup_nbt_length(state
->vector
, 3);
925 hdr
= (uint8_t *)state
->vector
[1].iov_base
;
926 body
= (uint8_t *)state
->vector
[2].iov_base
;
928 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
929 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
930 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
931 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
932 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(reqhdr
, SMB2_HDR_OPCODE
));
934 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
935 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
936 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
937 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
938 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
939 BVAL(reqhdr
, SMB2_HDR_SESSION_ID
));
940 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
942 SSVAL(body
, 0x00, 0x08 + 1);
944 SCVAL(body
, 0x02, 0);
945 SCVAL(body
, 0x03, 0);
946 SIVAL(body
, 0x04, 0);
947 /* Match W2K8R2... */
948 SCVAL(body
, 0x08, 0x21);
950 /* Ensure we correctly go through crediting. Grant
951 the credits now, and zero credits on the final
953 smb2_set_operation_credit(req
->sconn
,
957 if (req
->do_signing
) {
958 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
959 &state
->vector
[1], 2);
960 if (!NT_STATUS_IS_OK(status
)) {
965 subreq
= tstream_writev_queue_send(state
,
966 req
->sconn
->smb2
.event_ctx
,
967 req
->sconn
->smb2
.stream
,
968 req
->sconn
->smb2
.send_queue
,
972 if (subreq
== NULL
) {
973 return NT_STATUS_NO_MEMORY
;
976 tevent_req_set_callback(subreq
,
977 smbd_smb2_request_pending_writev_done
,
980 /* Note we're going async with this request. */
984 * Now manipulate req so that the outstanding async request
985 * is the only one left in the struct smbd_smb2_request.
988 if (req
->current_idx
== 1) {
989 /* There was only one. */
993 /* Re-arrange the in.vectors. */
994 req
->in
.vector
[1] = req
->in
.vector
[i
];
995 req
->in
.vector
[2] = req
->in
.vector
[i
+1];
996 req
->in
.vector
[3] = req
->in
.vector
[i
+2];
997 req
->in
.vector_count
= 4;
998 /* Reset the new in size. */
999 smb2_setup_nbt_length(req
->in
.vector
, 4);
1001 /* Now recreate the out.vectors. */
1002 outvec
= talloc_zero_array(req
, struct iovec
, 4);
1004 return NT_STATUS_NO_MEMORY
;
1007 /* 0 is always boilerplate and must
1008 * be of size 4 for the length field. */
1010 outvec
[0].iov_base
= req
->out
.nbt_hdr
;
1011 outvec
[0].iov_len
= 4;
1012 SIVAL(req
->out
.nbt_hdr
, 0, 0);
1014 if (!dup_smb2_vec3(outvec
, &outvec
[1], &req
->out
.vector
[i
])) {
1015 return NT_STATUS_NO_MEMORY
;
1018 TALLOC_FREE(req
->out
.vector
);
1020 req
->out
.vector
= outvec
;
1022 req
->current_idx
= 1;
1023 req
->out
.vector_count
= 4;
1027 smb2_setup_nbt_length(req
->out
.vector
,
1028 req
->out
.vector_count
);
1030 /* Ensure our final reply matches the interim one. */
1031 reqhdr
= (uint8_t *)req
->out
.vector
[1].iov_base
;
1032 SIVAL(reqhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1033 SBVAL(reqhdr
, SMB2_HDR_PID
, async_id
);
1036 const uint8_t *inhdr
=
1037 (const uint8_t *)req
->in
.vector
[1].iov_base
;
1038 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1040 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1041 (unsigned long long)async_id
));
1043 return NT_STATUS_OK
;
1046 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
1048 struct smbd_server_connection
*sconn
= req
->sconn
;
1049 struct smbd_smb2_request
*cur
;
1050 const uint8_t *inhdr
;
1051 int i
= req
->current_idx
;
1053 uint64_t search_message_id
;
1054 uint64_t search_async_id
;
1057 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1059 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1060 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1061 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
1064 * we don't need the request anymore
1065 * cancel requests never have a response
1067 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1070 for (cur
= sconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
1071 const uint8_t *outhdr
;
1072 uint64_t message_id
;
1075 i
= cur
->current_idx
;
1077 outhdr
= (const uint8_t *)cur
->out
.vector
[i
].iov_base
;
1079 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1080 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
1082 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1083 if (search_async_id
== async_id
) {
1084 found_id
= async_id
;
1088 if (search_message_id
== message_id
) {
1089 found_id
= message_id
;
1095 if (cur
&& cur
->subreq
) {
1096 inhdr
= (const uint8_t *)cur
->in
.vector
[i
].iov_base
;
1097 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1098 "cancel opcode[%s] mid %llu\n",
1099 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1100 (unsigned long long)found_id
));
1101 tevent_req_cancel(cur
->subreq
);
1104 return NT_STATUS_OK
;
1107 /*************************************************************
1108 Ensure an incoming tid is a valid one for us to access.
1109 Change to the associated uid credentials and chdir to the
1110 valid tid directory.
1111 *************************************************************/
1113 static NTSTATUS
smbd_smb2_request_check_tcon(struct smbd_smb2_request
*req
)
1115 const uint8_t *inhdr
;
1116 const uint8_t *outhdr
;
1117 int i
= req
->current_idx
;
1120 struct smbd_smb2_tcon
*tcon
;
1121 bool chained_fixup
= false;
1123 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1125 in_tid
= IVAL(inhdr
, SMB2_HDR_TID
);
1127 if (in_tid
== (0xFFFFFFFF)) {
1130 * async request - fill in tid from
1131 * already setup out.vector[].iov_base.
1133 outhdr
= (const uint8_t *)req
->out
.vector
[i
].iov_base
;
1134 in_tid
= IVAL(outhdr
, SMB2_HDR_TID
);
1137 * Chained request - fill in tid from
1138 * the previous request out.vector[].iov_base.
1140 outhdr
= (const uint8_t *)req
->out
.vector
[i
-3].iov_base
;
1141 in_tid
= IVAL(outhdr
, SMB2_HDR_TID
);
1142 chained_fixup
= true;
1146 /* lookup an existing session */
1147 p
= idr_find(req
->session
->tcons
.idtree
, in_tid
);
1149 return NT_STATUS_NETWORK_NAME_DELETED
;
1151 tcon
= talloc_get_type_abort(p
, struct smbd_smb2_tcon
);
1153 if (!change_to_user(tcon
->compat_conn
,req
->session
->vuid
)) {
1154 return NT_STATUS_ACCESS_DENIED
;
1157 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1158 if (!set_current_service(tcon
->compat_conn
, 0, true)) {
1159 return NT_STATUS_ACCESS_DENIED
;
1164 if (chained_fixup
) {
1165 /* Fix up our own outhdr. */
1166 outhdr
= (const uint8_t *)req
->out
.vector
[i
].iov_base
;
1167 SIVAL(discard_const_p(uint8_t, outhdr
), SMB2_HDR_TID
, in_tid
);
1170 return NT_STATUS_OK
;
1173 /*************************************************************
1174 Ensure an incoming session_id is a valid one for us to access.
1175 *************************************************************/
1177 static NTSTATUS
smbd_smb2_request_check_session(struct smbd_smb2_request
*req
)
1179 const uint8_t *inhdr
;
1180 const uint8_t *outhdr
;
1181 int i
= req
->current_idx
;
1182 uint64_t in_session_id
;
1184 struct smbd_smb2_session
*session
;
1185 bool chained_fixup
= false;
1187 inhdr
= (const uint8_t *)req
->in
.vector
[i
+0].iov_base
;
1189 in_session_id
= BVAL(inhdr
, SMB2_HDR_SESSION_ID
);
1191 if (in_session_id
== (0xFFFFFFFFFFFFFFFFLL
)) {
1194 * async request - fill in session_id from
1195 * already setup request out.vector[].iov_base.
1197 outhdr
= (const uint8_t *)req
->out
.vector
[i
].iov_base
;
1198 in_session_id
= BVAL(outhdr
, SMB2_HDR_SESSION_ID
);
1201 * Chained request - fill in session_id from
1202 * the previous request out.vector[].iov_base.
1204 outhdr
= (const uint8_t *)req
->out
.vector
[i
-3].iov_base
;
1205 in_session_id
= BVAL(outhdr
, SMB2_HDR_SESSION_ID
);
1206 chained_fixup
= true;
1210 /* lookup an existing session */
1211 p
= idr_find(req
->sconn
->smb2
.sessions
.idtree
, in_session_id
);
1213 return NT_STATUS_USER_SESSION_DELETED
;
1215 session
= talloc_get_type_abort(p
, struct smbd_smb2_session
);
1217 if (!NT_STATUS_IS_OK(session
->status
)) {
1218 return NT_STATUS_ACCESS_DENIED
;
1221 set_current_user_info(session
->session_info
->unix_info
->sanitized_username
,
1222 session
->session_info
->unix_info
->unix_name
,
1223 session
->session_info
->info
->domain_name
);
1225 req
->session
= session
;
1227 if (chained_fixup
) {
1228 /* Fix up our own outhdr. */
1229 outhdr
= (const uint8_t *)req
->out
.vector
[i
].iov_base
;
1230 SBVAL(discard_const_p(uint8_t, outhdr
), SMB2_HDR_SESSION_ID
, in_session_id
);
1232 return NT_STATUS_OK
;
1235 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
1237 const uint8_t *inhdr
;
1238 int i
= req
->current_idx
;
1243 NTSTATUS session_status
;
1244 uint32_t allowed_flags
;
1245 NTSTATUS return_value
;
1247 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1249 /* TODO: verify more things */
1251 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1252 opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1253 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1254 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1255 smb2_opcode_name(opcode
),
1256 (unsigned long long)mid
));
1258 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
1259 SMB2_HDR_FLAG_SIGNED
|
1261 if (opcode
== SMB2_OP_CANCEL
) {
1262 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
1264 if ((flags
& ~allowed_flags
) != 0) {
1265 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1269 * Check if the client provided a valid session id,
1270 * if so smbd_smb2_request_check_session() calls
1271 * set_current_user_info().
1273 * As some command don't require a valid session id
1274 * we defer the check of the session_status
1276 session_status
= smbd_smb2_request_check_session(req
);
1278 req
->do_signing
= false;
1279 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
1280 if (!NT_STATUS_IS_OK(session_status
)) {
1281 return smbd_smb2_request_error(req
, session_status
);
1284 req
->do_signing
= true;
1285 status
= smb2_signing_check_pdu(req
->session
->session_key
,
1286 &req
->in
.vector
[i
], 3);
1287 if (!NT_STATUS_IS_OK(status
)) {
1288 return smbd_smb2_request_error(req
, status
);
1290 } else if (req
->session
&& req
->session
->do_signing
) {
1291 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
1294 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
1296 * This check is mostly for giving the correct error code
1297 * for compounded requests.
1299 * TODO: we may need to move this after the session
1302 if (!NT_STATUS_IS_OK(req
->next_status
)) {
1303 return smbd_smb2_request_error(req
, req
->next_status
);
1306 req
->compat_chain_fsp
= NULL
;
1310 case SMB2_OP_NEGPROT
:
1311 /* This call needs to be run as root */
1312 change_to_root_user();
1315 START_PROFILE(smb2_negprot
);
1316 return_value
= smbd_smb2_request_process_negprot(req
);
1317 END_PROFILE(smb2_negprot
);
1321 case SMB2_OP_SESSSETUP
:
1322 /* This call needs to be run as root */
1323 change_to_root_user();
1326 START_PROFILE(smb2_sesssetup
);
1327 return_value
= smbd_smb2_request_process_sesssetup(req
);
1328 END_PROFILE(smb2_sesssetup
);
1332 case SMB2_OP_LOGOFF
:
1333 if (!NT_STATUS_IS_OK(session_status
)) {
1334 return_value
= smbd_smb2_request_error(req
, session_status
);
1338 /* This call needs to be run as root */
1339 change_to_root_user();
1342 START_PROFILE(smb2_logoff
);
1343 return_value
= smbd_smb2_request_process_logoff(req
);
1344 END_PROFILE(smb2_logoff
);
1349 if (!NT_STATUS_IS_OK(session_status
)) {
1350 return_value
= smbd_smb2_request_error(req
, session_status
);
1355 * This call needs to be run as root.
1357 * smbd_smb2_request_process_tcon()
1358 * calls make_connection_snum(), which will call
1359 * change_to_user(), when needed.
1361 change_to_root_user();
1364 START_PROFILE(smb2_tcon
);
1365 return_value
= smbd_smb2_request_process_tcon(req
);
1366 END_PROFILE(smb2_tcon
);
1371 if (!NT_STATUS_IS_OK(session_status
)) {
1372 return_value
= smbd_smb2_request_error(req
, session_status
);
1376 * This call needs to be run as user.
1378 * smbd_smb2_request_check_tcon()
1379 * calls change_to_user() on success.
1381 status
= smbd_smb2_request_check_tcon(req
);
1382 if (!NT_STATUS_IS_OK(status
)) {
1383 return_value
= smbd_smb2_request_error(req
, status
);
1386 /* This call needs to be run as root */
1387 change_to_root_user();
1391 START_PROFILE(smb2_tdis
);
1392 return_value
= smbd_smb2_request_process_tdis(req
);
1393 END_PROFILE(smb2_tdis
);
1397 case SMB2_OP_CREATE
:
1398 if (!NT_STATUS_IS_OK(session_status
)) {
1399 return_value
= smbd_smb2_request_error(req
, session_status
);
1403 * This call needs to be run as user.
1405 * smbd_smb2_request_check_tcon()
1406 * calls change_to_user() on success.
1408 status
= smbd_smb2_request_check_tcon(req
);
1409 if (!NT_STATUS_IS_OK(status
)) {
1410 return_value
= smbd_smb2_request_error(req
, status
);
1415 START_PROFILE(smb2_create
);
1416 return_value
= smbd_smb2_request_process_create(req
);
1417 END_PROFILE(smb2_create
);
1422 if (!NT_STATUS_IS_OK(session_status
)) {
1423 return_value
= smbd_smb2_request_error(req
, session_status
);
1427 * This call needs to be run as user.
1429 * smbd_smb2_request_check_tcon()
1430 * calls change_to_user() on success.
1432 status
= smbd_smb2_request_check_tcon(req
);
1433 if (!NT_STATUS_IS_OK(status
)) {
1434 return_value
= smbd_smb2_request_error(req
, status
);
1439 START_PROFILE(smb2_close
);
1440 return_value
= smbd_smb2_request_process_close(req
);
1441 END_PROFILE(smb2_close
);
1446 if (!NT_STATUS_IS_OK(session_status
)) {
1447 return_value
= smbd_smb2_request_error(req
, session_status
);
1451 * This call needs to be run as user.
1453 * smbd_smb2_request_check_tcon()
1454 * calls change_to_user() on success.
1456 status
= smbd_smb2_request_check_tcon(req
);
1457 if (!NT_STATUS_IS_OK(status
)) {
1458 return_value
= smbd_smb2_request_error(req
, status
);
1463 START_PROFILE(smb2_flush
);
1464 return_value
= smbd_smb2_request_process_flush(req
);
1465 END_PROFILE(smb2_flush
);
1470 if (!NT_STATUS_IS_OK(session_status
)) {
1471 return_value
= smbd_smb2_request_error(req
, session_status
);
1475 * This call needs to be run as user.
1477 * smbd_smb2_request_check_tcon()
1478 * calls change_to_user() on success.
1480 status
= smbd_smb2_request_check_tcon(req
);
1481 if (!NT_STATUS_IS_OK(status
)) {
1482 return_value
= smbd_smb2_request_error(req
, status
);
1487 START_PROFILE(smb2_read
);
1488 return_value
= smbd_smb2_request_process_read(req
);
1489 END_PROFILE(smb2_read
);
1494 if (!NT_STATUS_IS_OK(session_status
)) {
1495 return_value
= smbd_smb2_request_error(req
, session_status
);
1499 * This call needs to be run as user.
1501 * smbd_smb2_request_check_tcon()
1502 * calls change_to_user() on success.
1504 status
= smbd_smb2_request_check_tcon(req
);
1505 if (!NT_STATUS_IS_OK(status
)) {
1506 return_value
= smbd_smb2_request_error(req
, status
);
1511 START_PROFILE(smb2_write
);
1512 return_value
= smbd_smb2_request_process_write(req
);
1513 END_PROFILE(smb2_write
);
1518 if (!NT_STATUS_IS_OK(session_status
)) {
1519 /* Too ugly to live ? JRA. */
1520 if (NT_STATUS_EQUAL(session_status
,NT_STATUS_USER_SESSION_DELETED
)) {
1521 session_status
= NT_STATUS_FILE_CLOSED
;
1523 return_value
= smbd_smb2_request_error(req
, session_status
);
1527 * This call needs to be run as user.
1529 * smbd_smb2_request_check_tcon()
1530 * calls change_to_user() on success.
1532 status
= smbd_smb2_request_check_tcon(req
);
1533 if (!NT_STATUS_IS_OK(status
)) {
1534 /* Too ugly to live ? JRA. */
1535 if (NT_STATUS_EQUAL(status
,NT_STATUS_NETWORK_NAME_DELETED
)) {
1536 status
= NT_STATUS_FILE_CLOSED
;
1538 return_value
= smbd_smb2_request_error(req
, status
);
1543 START_PROFILE(smb2_lock
);
1544 return_value
= smbd_smb2_request_process_lock(req
);
1545 END_PROFILE(smb2_lock
);
1550 if (!NT_STATUS_IS_OK(session_status
)) {
1551 return_value
= smbd_smb2_request_error(req
, session_status
);
1555 * This call needs to be run as user.
1557 * smbd_smb2_request_check_tcon()
1558 * calls change_to_user() on success.
1560 status
= smbd_smb2_request_check_tcon(req
);
1561 if (!NT_STATUS_IS_OK(status
)) {
1562 return_value
= smbd_smb2_request_error(req
, status
);
1567 START_PROFILE(smb2_ioctl
);
1568 return_value
= smbd_smb2_request_process_ioctl(req
);
1569 END_PROFILE(smb2_ioctl
);
1573 case SMB2_OP_CANCEL
:
1575 * This call needs to be run as root
1577 * That is what we also do in the SMB1 case.
1579 change_to_root_user();
1582 START_PROFILE(smb2_cancel
);
1583 return_value
= smbd_smb2_request_process_cancel(req
);
1584 END_PROFILE(smb2_cancel
);
1588 case SMB2_OP_KEEPALIVE
:
1589 /* This call needs to be run as root */
1590 change_to_root_user();
1593 START_PROFILE(smb2_keepalive
);
1594 return_value
= smbd_smb2_request_process_keepalive(req
);
1595 END_PROFILE(smb2_keepalive
);
1600 if (!NT_STATUS_IS_OK(session_status
)) {
1601 return_value
= smbd_smb2_request_error(req
, session_status
);
1605 * This call needs to be run as user.
1607 * smbd_smb2_request_check_tcon()
1608 * calls change_to_user() on success.
1610 status
= smbd_smb2_request_check_tcon(req
);
1611 if (!NT_STATUS_IS_OK(status
)) {
1612 return_value
= smbd_smb2_request_error(req
, status
);
1617 START_PROFILE(smb2_find
);
1618 return_value
= smbd_smb2_request_process_find(req
);
1619 END_PROFILE(smb2_find
);
1623 case SMB2_OP_NOTIFY
:
1624 if (!NT_STATUS_IS_OK(session_status
)) {
1625 return_value
= smbd_smb2_request_error(req
, session_status
);
1629 * This call needs to be run as user.
1631 * smbd_smb2_request_check_tcon()
1632 * calls change_to_user() on success.
1634 status
= smbd_smb2_request_check_tcon(req
);
1635 if (!NT_STATUS_IS_OK(status
)) {
1636 return_value
= smbd_smb2_request_error(req
, status
);
1641 START_PROFILE(smb2_notify
);
1642 return_value
= smbd_smb2_request_process_notify(req
);
1643 END_PROFILE(smb2_notify
);
1647 case SMB2_OP_GETINFO
:
1648 if (!NT_STATUS_IS_OK(session_status
)) {
1649 return_value
= smbd_smb2_request_error(req
, session_status
);
1653 * This call needs to be run as user.
1655 * smbd_smb2_request_check_tcon()
1656 * calls change_to_user() on success.
1658 status
= smbd_smb2_request_check_tcon(req
);
1659 if (!NT_STATUS_IS_OK(status
)) {
1660 return_value
= smbd_smb2_request_error(req
, status
);
1665 START_PROFILE(smb2_getinfo
);
1666 return_value
= smbd_smb2_request_process_getinfo(req
);
1667 END_PROFILE(smb2_getinfo
);
1671 case SMB2_OP_SETINFO
:
1672 if (!NT_STATUS_IS_OK(session_status
)) {
1673 return_value
= smbd_smb2_request_error(req
, session_status
);
1677 * This call needs to be run as user.
1679 * smbd_smb2_request_check_tcon()
1680 * calls change_to_user() on success.
1682 status
= smbd_smb2_request_check_tcon(req
);
1683 if (!NT_STATUS_IS_OK(status
)) {
1684 return_value
= smbd_smb2_request_error(req
, status
);
1689 START_PROFILE(smb2_setinfo
);
1690 return_value
= smbd_smb2_request_process_setinfo(req
);
1691 END_PROFILE(smb2_setinfo
);
1696 if (!NT_STATUS_IS_OK(session_status
)) {
1697 return_value
= smbd_smb2_request_error(req
, session_status
);
1701 * This call needs to be run as user.
1703 * smbd_smb2_request_check_tcon()
1704 * calls change_to_user() on success.
1706 status
= smbd_smb2_request_check_tcon(req
);
1707 if (!NT_STATUS_IS_OK(status
)) {
1708 return_value
= smbd_smb2_request_error(req
, status
);
1713 START_PROFILE(smb2_break
);
1714 return_value
= smbd_smb2_request_process_break(req
);
1715 END_PROFILE(smb2_break
);
1720 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1723 return return_value
;
1726 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
1728 struct tevent_req
*subreq
;
1729 int i
= req
->current_idx
;
1733 req
->current_idx
+= 3;
1735 if (req
->current_idx
< req
->out
.vector_count
) {
1737 * We must process the remaining compound
1738 * SMB2 requests before any new incoming SMB2
1739 * requests. This is because incoming SMB2
1740 * requests may include a cancel for a
1741 * compound request we haven't processed
1744 struct tevent_immediate
*im
= tevent_create_immediate(req
);
1746 return NT_STATUS_NO_MEMORY
;
1748 tevent_schedule_immediate(im
,
1749 req
->sconn
->smb2
.event_ctx
,
1750 smbd_smb2_request_dispatch_immediate
,
1752 return NT_STATUS_OK
;
1755 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
1757 /* Set credit for this operation (zero credits if this
1758 is a final reply for an async operation). */
1759 smb2_set_operation_credit(req
->sconn
,
1761 &req
->out
.vector
[i
]);
1763 if (req
->do_signing
) {
1765 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
1766 &req
->out
.vector
[i
], 3);
1767 if (!NT_STATUS_IS_OK(status
)) {
1772 if (DEBUGLEVEL
>= 10) {
1773 dbgtext("smbd_smb2_request_reply: sending...\n");
1774 print_req_vectors(req
);
1777 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1778 if (req
->out
.vector_count
== 4 &&
1779 req
->out
.vector
[3].iov_base
== NULL
&&
1780 req
->out
.vector
[3].iov_len
!= 0) {
1781 /* Dynamic part is NULL. Chop it off,
1782 We're going to send it via sendfile. */
1783 req
->out
.vector_count
-= 1;
1786 subreq
= tstream_writev_queue_send(req
,
1787 req
->sconn
->smb2
.event_ctx
,
1788 req
->sconn
->smb2
.stream
,
1789 req
->sconn
->smb2
.send_queue
,
1791 req
->out
.vector_count
);
1792 if (subreq
== NULL
) {
1793 return NT_STATUS_NO_MEMORY
;
1795 tevent_req_set_callback(subreq
, smbd_smb2_request_writev_done
, req
);
1797 * We're done with this request -
1798 * move it off the "being processed" queue.
1800 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1802 return NT_STATUS_OK
;
1805 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
1806 struct tevent_immediate
*im
,
1809 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
1810 struct smbd_smb2_request
);
1811 struct smbd_server_connection
*sconn
= req
->sconn
;
1816 if (DEBUGLEVEL
>= 10) {
1817 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1818 req
->current_idx
, req
->in
.vector_count
));
1819 print_req_vectors(req
);
1822 status
= smbd_smb2_request_dispatch(req
);
1823 if (!NT_STATUS_IS_OK(status
)) {
1824 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1829 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
);
1831 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
)
1833 struct smbd_smb2_request
*req
= tevent_req_callback_data(subreq
,
1834 struct smbd_smb2_request
);
1835 struct smbd_server_connection
*sconn
= req
->sconn
;
1840 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1841 TALLOC_FREE(subreq
);
1844 status
= map_nt_error_from_unix(sys_errno
);
1845 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1846 nt_errstr(status
)));
1847 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1851 status
= smbd_smb2_request_next_incoming(sconn
);
1852 if (!NT_STATUS_IS_OK(status
)) {
1853 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1858 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
1860 DATA_BLOB body
, DATA_BLOB
*dyn
,
1861 const char *location
)
1864 int i
= req
->current_idx
;
1865 uint32_t next_command_ofs
;
1867 DEBUG(10,("smbd_smb2_request_done_ex: "
1868 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1869 i
, nt_errstr(status
), (unsigned int)body
.length
,
1871 (unsigned int)(dyn
? dyn
->length
: 0),
1874 if (body
.length
< 2) {
1875 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
1878 if ((body
.length
% 2) != 0) {
1879 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
1882 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
1884 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
1885 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
1887 req
->out
.vector
[i
+1].iov_base
= (void *)body
.data
;
1888 req
->out
.vector
[i
+1].iov_len
= body
.length
;
1891 req
->out
.vector
[i
+2].iov_base
= (void *)dyn
->data
;
1892 req
->out
.vector
[i
+2].iov_len
= dyn
->length
;
1894 req
->out
.vector
[i
+2].iov_base
= NULL
;
1895 req
->out
.vector
[i
+2].iov_len
= 0;
1898 /* see if we need to recalculate the offset to the next response */
1899 if (next_command_ofs
> 0) {
1900 next_command_ofs
= SMB2_HDR_BODY
;
1901 next_command_ofs
+= req
->out
.vector
[i
+1].iov_len
;
1902 next_command_ofs
+= req
->out
.vector
[i
+2].iov_len
;
1905 if ((next_command_ofs
% 8) != 0) {
1906 size_t pad_size
= 8 - (next_command_ofs
% 8);
1907 if (req
->out
.vector
[i
+2].iov_len
== 0) {
1909 * if the dyn buffer is empty
1910 * we can use it to add padding
1914 pad
= talloc_zero_array(req
->out
.vector
,
1917 return smbd_smb2_request_error(req
,
1918 NT_STATUS_NO_MEMORY
);
1921 req
->out
.vector
[i
+2].iov_base
= (void *)pad
;
1922 req
->out
.vector
[i
+2].iov_len
= pad_size
;
1925 * For now we copy the dynamic buffer
1926 * and add the padding to the new buffer
1933 old_size
= req
->out
.vector
[i
+2].iov_len
;
1934 old_dyn
= (uint8_t *)req
->out
.vector
[i
+2].iov_base
;
1936 new_size
= old_size
+ pad_size
;
1937 new_dyn
= talloc_zero_array(req
->out
.vector
,
1939 if (new_dyn
== NULL
) {
1940 return smbd_smb2_request_error(req
,
1941 NT_STATUS_NO_MEMORY
);
1944 memcpy(new_dyn
, old_dyn
, old_size
);
1945 memset(new_dyn
+ old_size
, 0, pad_size
);
1947 req
->out
.vector
[i
+2].iov_base
= (void *)new_dyn
;
1948 req
->out
.vector
[i
+2].iov_len
= new_size
;
1950 next_command_ofs
+= pad_size
;
1953 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
1955 return smbd_smb2_request_reply(req
);
1958 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
1961 const char *location
)
1964 int i
= req
->current_idx
;
1965 uint8_t *outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
1967 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1968 i
, nt_errstr(status
), info
? " +info" : "",
1971 body
.data
= outhdr
+ SMB2_HDR_BODY
;
1973 SSVAL(body
.data
, 0, 9);
1976 SIVAL(body
.data
, 0x04, info
->length
);
1978 /* Allocated size of req->out.vector[i].iov_base
1979 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
1980 * 1 byte without having to do an alloc.
1982 info
= talloc_zero_array(req
->out
.vector
,
1986 return NT_STATUS_NO_MEMORY
;
1988 info
->data
= ((uint8_t *)outhdr
) +
1989 OUTVEC_ALLOC_SIZE
- 1;
1991 SCVAL(info
->data
, 0, 0);
1995 * if a request fails, all other remaining
1996 * compounded requests should fail too
1998 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
2000 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
2004 struct smbd_smb2_send_oplock_break_state
{
2005 struct smbd_server_connection
*sconn
;
2006 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x18];
2007 struct iovec vector
;
2010 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
);
2012 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
2013 uint64_t file_id_persistent
,
2014 uint64_t file_id_volatile
,
2015 uint8_t oplock_level
)
2017 struct smbd_smb2_send_oplock_break_state
*state
;
2018 struct tevent_req
*subreq
;
2022 state
= talloc(sconn
, struct smbd_smb2_send_oplock_break_state
);
2023 if (state
== NULL
) {
2024 return NT_STATUS_NO_MEMORY
;
2026 state
->sconn
= sconn
;
2028 state
->vector
.iov_base
= (void *)state
->buf
;
2029 state
->vector
.iov_len
= sizeof(state
->buf
);
2031 _smb2_setlen(state
->buf
, sizeof(state
->buf
) - 4);
2032 hdr
= state
->buf
+ 4;
2033 body
= hdr
+ SMB2_HDR_BODY
;
2035 SIVAL(hdr
, 0, SMB2_MAGIC
);
2036 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
2037 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
2038 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
2039 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
2040 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
2041 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
2042 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
2043 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
2044 SIVAL(hdr
, SMB2_HDR_PID
, 0);
2045 SIVAL(hdr
, SMB2_HDR_TID
, 0);
2046 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
2047 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
2049 SSVAL(body
, 0x00, 0x18);
2051 SCVAL(body
, 0x02, oplock_level
);
2052 SCVAL(body
, 0x03, 0); /* reserved */
2053 SIVAL(body
, 0x04, 0); /* reserved */
2054 SBVAL(body
, 0x08, file_id_persistent
);
2055 SBVAL(body
, 0x10, file_id_volatile
);
2057 subreq
= tstream_writev_queue_send(state
,
2058 sconn
->smb2
.event_ctx
,
2060 sconn
->smb2
.send_queue
,
2062 if (subreq
== NULL
) {
2063 return NT_STATUS_NO_MEMORY
;
2065 tevent_req_set_callback(subreq
,
2066 smbd_smb2_oplock_break_writev_done
,
2069 return NT_STATUS_OK
;
2072 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
)
2074 struct smbd_smb2_send_oplock_break_state
*state
=
2075 tevent_req_callback_data(subreq
,
2076 struct smbd_smb2_send_oplock_break_state
);
2077 struct smbd_server_connection
*sconn
= state
->sconn
;
2081 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
2082 TALLOC_FREE(subreq
);
2084 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
2085 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2092 struct smbd_smb2_request_read_state
{
2094 bool asked_for_header
;
2095 struct smbd_smb2_request
*smb2_req
;
2098 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2100 TALLOC_CTX
*mem_ctx
,
2101 struct iovec
**_vector
,
2103 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
);
2105 static struct tevent_req
*smbd_smb2_request_read_send(TALLOC_CTX
*mem_ctx
,
2106 struct tevent_context
*ev
,
2107 struct smbd_server_connection
*sconn
)
2109 struct tevent_req
*req
;
2110 struct smbd_smb2_request_read_state
*state
;
2111 struct tevent_req
*subreq
;
2113 req
= tevent_req_create(mem_ctx
, &state
,
2114 struct smbd_smb2_request_read_state
);
2119 state
->asked_for_header
= false;
2121 state
->smb2_req
= smbd_smb2_request_allocate(state
);
2122 if (tevent_req_nomem(state
->smb2_req
, req
)) {
2123 return tevent_req_post(req
, ev
);
2125 state
->smb2_req
->sconn
= sconn
;
2127 subreq
= tstream_readv_pdu_queue_send(state
, ev
, sconn
->smb2
.stream
,
2128 sconn
->smb2
.recv_queue
,
2129 smbd_smb2_request_next_vector
,
2131 if (tevent_req_nomem(subreq
, req
)) {
2132 return tevent_req_post(req
, ev
);
2134 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
2139 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2141 TALLOC_CTX
*mem_ctx
,
2142 struct iovec
**_vector
,
2145 struct smbd_smb2_request_read_state
*state
=
2146 talloc_get_type_abort(private_data
,
2147 struct smbd_smb2_request_read_state
);
2148 struct smbd_smb2_request
*req
= state
->smb2_req
;
2149 struct iovec
*vector
;
2150 int idx
= req
->in
.vector_count
;
2152 uint8_t *buf
= NULL
;
2154 if (req
->in
.vector_count
== 0) {
2156 * first we need to get the NBT header
2158 req
->in
.vector
= talloc_array(req
, struct iovec
,
2159 req
->in
.vector_count
+ 1);
2160 if (req
->in
.vector
== NULL
) {
2163 req
->in
.vector_count
+= 1;
2165 req
->in
.vector
[idx
].iov_base
= (void *)req
->in
.nbt_hdr
;
2166 req
->in
.vector
[idx
].iov_len
= 4;
2168 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2169 if (vector
== NULL
) {
2173 vector
[0] = req
->in
.vector
[idx
];
2180 if (req
->in
.vector_count
== 1) {
2182 * Now we analyze the NBT header
2184 state
->missing
= smb2_len(req
->in
.vector
[0].iov_base
);
2186 if (state
->missing
== 0) {
2187 /* if there're no remaining bytes, we're done */
2193 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2195 req
->in
.vector_count
+ 1);
2196 if (req
->in
.vector
== NULL
) {
2199 req
->in
.vector_count
+= 1;
2201 if (CVAL(req
->in
.vector
[0].iov_base
, 0) != 0) {
2203 * it's a special NBT message,
2204 * so get all remaining bytes
2206 len
= state
->missing
;
2207 } else if (state
->missing
< (SMB2_HDR_BODY
+ 2)) {
2209 * it's an invalid message, just read what we can get
2210 * and let the caller handle the error
2212 len
= state
->missing
;
2215 * We assume it's a SMB2 request,
2216 * and we first get the header and the
2217 * first 2 bytes (the struct size) of the body
2219 len
= SMB2_HDR_BODY
+ 2;
2221 state
->asked_for_header
= true;
2224 state
->missing
-= len
;
2226 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2231 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2232 req
->in
.vector
[idx
].iov_len
= len
;
2234 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2235 if (vector
== NULL
) {
2239 vector
[0] = req
->in
.vector
[idx
];
2246 if (state
->missing
== 0) {
2247 /* if there're no remaining bytes, we're done */
2253 if (state
->asked_for_header
) {
2256 size_t next_command_ofs
;
2261 bool invalid
= false;
2263 state
->asked_for_header
= false;
2266 * We got the SMB2 header and the first 2 bytes
2267 * of the body. We fix the size to just the header
2268 * and manually copy the 2 first bytes to the body section
2270 req
->in
.vector
[idx
-1].iov_len
= SMB2_HDR_BODY
;
2271 hdr
= (const uint8_t *)req
->in
.vector
[idx
-1].iov_base
;
2273 /* allocate vectors for body and dynamic areas */
2274 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2276 req
->in
.vector_count
+ 2);
2277 if (req
->in
.vector
== NULL
) {
2280 req
->in
.vector_count
+= 2;
2282 full_size
= state
->missing
+ SMB2_HDR_BODY
+ 2;
2283 next_command_ofs
= IVAL(hdr
, SMB2_HDR_NEXT_COMMAND
);
2284 body_size
= SVAL(hdr
, SMB2_HDR_BODY
);
2286 if (next_command_ofs
!= 0) {
2287 if (next_command_ofs
< (SMB2_HDR_BODY
+ 2)) {
2289 * this is invalid, just return a zero
2290 * body and let the caller deal with the error
2293 } else if (next_command_ofs
> full_size
) {
2295 * this is invalid, just return a zero
2296 * body and let the caller deal with the error
2300 full_size
= next_command_ofs
;
2305 if (body_size
< 2) {
2307 * this is invalid, just return a zero
2308 * body and let the caller deal with the error
2314 * Mask out the lowest bit, the "dynamic" part
2319 if (body_size
> (full_size
- SMB2_HDR_BODY
)) {
2321 * this is invalid, just return a zero
2322 * body and let the caller deal with the error
2329 /* the caller should check this */
2333 dyn_size
= full_size
- (SMB2_HDR_BODY
+ body_size
);
2335 state
->missing
-= (body_size
- 2) + dyn_size
;
2337 body
= talloc_array(req
->in
.vector
, uint8_t, body_size
);
2342 dyn
= talloc_array(req
->in
.vector
, uint8_t, dyn_size
);
2347 req
->in
.vector
[idx
].iov_base
= (void *)body
;
2348 req
->in
.vector
[idx
].iov_len
= body_size
;
2349 req
->in
.vector
[idx
+1].iov_base
= (void *)dyn
;
2350 req
->in
.vector
[idx
+1].iov_len
= dyn_size
;
2352 vector
= talloc_array(mem_ctx
, struct iovec
, 2);
2353 if (vector
== NULL
) {
2358 * the first 2 bytes of the body were already fetched
2359 * together with the header
2361 memcpy(body
, hdr
+ SMB2_HDR_BODY
, 2);
2362 vector
[0].iov_base
= body
+ 2;
2363 vector
[0].iov_len
= body_size
- 2;
2365 vector
[1] = req
->in
.vector
[idx
+1];
2373 * when we endup here, we're looking for a new SMB2 request
2374 * next. And we ask for its header and the first 2 bytes of
2375 * the body (like we did for the first SMB2 request).
2378 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2380 req
->in
.vector_count
+ 1);
2381 if (req
->in
.vector
== NULL
) {
2384 req
->in
.vector_count
+= 1;
2387 * We assume it's a SMB2 request,
2388 * and we first get the header and the
2389 * first 2 bytes (the struct size) of the body
2391 len
= SMB2_HDR_BODY
+ 2;
2393 if (len
> state
->missing
) {
2394 /* let the caller handle the error */
2395 len
= state
->missing
;
2398 state
->missing
-= len
;
2399 state
->asked_for_header
= true;
2401 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2406 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2407 req
->in
.vector
[idx
].iov_len
= len
;
2409 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2410 if (vector
== NULL
) {
2414 vector
[0] = req
->in
.vector
[idx
];
2421 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
)
2423 struct tevent_req
*req
=
2424 tevent_req_callback_data(subreq
,
2430 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
2432 status
= map_nt_error_from_unix(sys_errno
);
2433 tevent_req_nterror(req
, status
);
2437 tevent_req_done(req
);
2440 static NTSTATUS
smbd_smb2_request_read_recv(struct tevent_req
*req
,
2441 TALLOC_CTX
*mem_ctx
,
2442 struct smbd_smb2_request
**_smb2_req
)
2444 struct smbd_smb2_request_read_state
*state
=
2445 tevent_req_data(req
,
2446 struct smbd_smb2_request_read_state
);
2449 if (tevent_req_is_nterror(req
, &status
)) {
2450 tevent_req_received(req
);
2454 talloc_steal(mem_ctx
, state
->smb2_req
->mem_pool
);
2455 *_smb2_req
= state
->smb2_req
;
2456 tevent_req_received(req
);
2457 return NT_STATUS_OK
;
2460 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
);
2462 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
)
2464 size_t max_send_queue_len
;
2465 size_t cur_send_queue_len
;
2466 struct tevent_req
*subreq
;
2468 if (tevent_queue_length(sconn
->smb2
.recv_queue
) > 0) {
2470 * if there is already a smbd_smb2_request_read
2471 * pending, we are done.
2473 return NT_STATUS_OK
;
2476 max_send_queue_len
= MAX(1, sconn
->smb2
.max_credits
/16);
2477 cur_send_queue_len
= tevent_queue_length(sconn
->smb2
.send_queue
);
2479 if (cur_send_queue_len
> max_send_queue_len
) {
2481 * if we have a lot of requests to send,
2482 * we wait until they are on the wire until we
2483 * ask for the next request.
2485 return NT_STATUS_OK
;
2488 /* ask for the next request */
2489 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->smb2
.event_ctx
, sconn
);
2490 if (subreq
== NULL
) {
2491 return NT_STATUS_NO_MEMORY
;
2493 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);
2495 return NT_STATUS_OK
;
2498 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
2499 const uint8_t *inbuf
, size_t size
)
2502 struct smbd_smb2_request
*req
= NULL
;
2504 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2505 (unsigned int)size
));
2507 status
= smbd_initialize_smb2(sconn
);
2508 if (!NT_STATUS_IS_OK(status
)) {
2509 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2513 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
2514 if (!NT_STATUS_IS_OK(status
)) {
2515 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2519 status
= smbd_smb2_request_setup_out(req
);
2520 if (!NT_STATUS_IS_OK(status
)) {
2521 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2525 status
= smbd_smb2_request_dispatch(req
);
2526 if (!NT_STATUS_IS_OK(status
)) {
2527 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2531 status
= smbd_smb2_request_next_incoming(sconn
);
2532 if (!NT_STATUS_IS_OK(status
)) {
2533 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2537 sconn
->num_requests
++;
2540 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
)
2542 struct smbd_server_connection
*sconn
= tevent_req_callback_data(subreq
,
2543 struct smbd_server_connection
);
2545 struct smbd_smb2_request
*req
= NULL
;
2547 status
= smbd_smb2_request_read_recv(subreq
, sconn
, &req
);
2548 TALLOC_FREE(subreq
);
2549 if (!NT_STATUS_IS_OK(status
)) {
2550 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2551 nt_errstr(status
)));
2552 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2556 if (req
->in
.nbt_hdr
[0] != 0x00) {
2557 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2558 req
->in
.nbt_hdr
[0]));
2563 req
->current_idx
= 1;
2565 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2566 req
->current_idx
, req
->in
.vector_count
));
2568 status
= smbd_smb2_request_validate(req
);
2569 if (!NT_STATUS_IS_OK(status
)) {
2570 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2574 status
= smbd_smb2_request_setup_out(req
);
2575 if (!NT_STATUS_IS_OK(status
)) {
2576 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2580 status
= smbd_smb2_request_dispatch(req
);
2581 if (!NT_STATUS_IS_OK(status
)) {
2582 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2587 status
= smbd_smb2_request_next_incoming(sconn
);
2588 if (!NT_STATUS_IS_OK(status
)) {
2589 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2593 sconn
->num_requests
++;
2595 /* The timeout_processing function isn't run nearly
2596 often enough to implement 'max log size' without
2597 overrunning the size of the file by many megabytes.
2598 This is especially true if we are running at debug
2599 level 10. Checking every 50 SMB2s is a nice
2600 tradeoff of performance vs log file size overrun. */
2602 if ((sconn
->num_requests
% 50) == 0 &&
2603 need_to_check_log_size()) {
2604 change_to_root_user();