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"
30 #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9)
32 static const char *smb2_names
[] = {
54 const char *smb2_opcode_name(uint16_t opcode
)
57 return "Bad SMB2 opcode";
59 return smb2_names
[opcode
];
62 static void print_req_vectors(struct smbd_smb2_request
*req
)
66 for (i
= 0; i
< req
->in
.vector_count
; i
++) {
67 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
69 (unsigned int)req
->in
.vector
[i
].iov_len
);
71 for (i
= 0; i
< req
->out
.vector_count
; i
++) {
72 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
74 (unsigned int)req
->out
.vector
[i
].iov_len
);
78 bool smbd_is_smb2_header(const uint8_t *inbuf
, size_t size
)
80 if (size
< (4 + SMB2_HDR_BODY
)) {
84 if (IVAL(inbuf
, 4) != SMB2_MAGIC
) {
91 static NTSTATUS
smbd_initialize_smb2(struct smbd_server_connection
*sconn
)
96 TALLOC_FREE(sconn
->smb1
.fde
);
98 sconn
->smb2
.event_ctx
= smbd_event_context();
100 sconn
->smb2
.recv_queue
= tevent_queue_create(sconn
, "smb2 recv queue");
101 if (sconn
->smb2
.recv_queue
== NULL
) {
102 return NT_STATUS_NO_MEMORY
;
105 sconn
->smb2
.send_queue
= tevent_queue_create(sconn
, "smb2 send queue");
106 if (sconn
->smb2
.send_queue
== NULL
) {
107 return NT_STATUS_NO_MEMORY
;
110 sconn
->smb2
.sessions
.idtree
= idr_init(sconn
);
111 if (sconn
->smb2
.sessions
.idtree
== NULL
) {
112 return NT_STATUS_NO_MEMORY
;
114 sconn
->smb2
.sessions
.limit
= 0x0000FFFE;
115 sconn
->smb2
.sessions
.list
= NULL
;
116 sconn
->smb2
.seqnum_low
= 0;
117 sconn
->smb2
.credits_granted
= 0;
118 sconn
->smb2
.max_credits
= lp_smb2_max_credits();
119 sconn
->smb2
.credits_bitmap
= bitmap_talloc(sconn
,
120 DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
*sconn
->smb2
.max_credits
);
121 if (sconn
->smb2
.credits_bitmap
== NULL
) {
122 return NT_STATUS_NO_MEMORY
;
125 ret
= tstream_bsd_existing_socket(sconn
, sconn
->sock
,
126 &sconn
->smb2
.stream
);
128 status
= map_nt_error_from_unix(errno
);
132 /* Ensure child is set to non-blocking mode */
133 set_blocking(sconn
->sock
, false);
137 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
138 #define _smb2_setlen(_buf,len) do { \
139 uint8_t *buf = (uint8_t *)_buf; \
141 buf[1] = ((len)&0xFF0000)>>16; \
142 buf[2] = ((len)&0xFF00)>>8; \
143 buf[3] = (len)&0xFF; \
146 static void smb2_setup_nbt_length(struct iovec
*vector
, int count
)
151 for (i
=1; i
< count
; i
++) {
152 len
+= vector
[i
].iov_len
;
155 _smb2_setlen(vector
[0].iov_base
, len
);
158 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request
**req
)
161 (*req
)->parent
= NULL
;
162 (*req
)->mem_pool
= NULL
;
168 static int smbd_smb2_request_destructor(struct smbd_smb2_request
*req
)
172 talloc_free(req
->mem_pool
);
178 static struct smbd_smb2_request
*smbd_smb2_request_allocate(TALLOC_CTX
*mem_ctx
)
180 TALLOC_CTX
*mem_pool
;
181 struct smbd_smb2_request
**parent
;
182 struct smbd_smb2_request
*req
;
185 /* Enable this to find subtle valgrind errors. */
186 mem_pool
= talloc_init("smbd_smb2_request_allocate");
188 mem_pool
= talloc_pool(mem_ctx
, 8192);
190 if (mem_pool
== NULL
) {
194 parent
= talloc(mem_pool
, struct smbd_smb2_request
*);
195 if (parent
== NULL
) {
196 talloc_free(mem_pool
);
200 req
= talloc_zero(parent
, struct smbd_smb2_request
);
202 talloc_free(mem_pool
);
206 req
->mem_pool
= mem_pool
;
207 req
->parent
= parent
;
209 talloc_set_destructor(parent
, smbd_smb2_request_parent_destructor
);
210 talloc_set_destructor(req
, smbd_smb2_request_destructor
);
215 static NTSTATUS
smbd_smb2_request_create(struct smbd_server_connection
*sconn
,
216 const uint8_t *inbuf
, size_t size
,
217 struct smbd_smb2_request
**_req
)
219 struct smbd_smb2_request
*req
;
220 uint32_t protocol_version
;
221 const uint8_t *inhdr
= NULL
;
224 uint32_t next_command_ofs
;
226 if (size
< (4 + SMB2_HDR_BODY
+ 2)) {
227 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size
));
228 return NT_STATUS_INVALID_PARAMETER
;
233 protocol_version
= IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
);
234 if (protocol_version
!= SMB2_MAGIC
) {
235 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
237 return NT_STATUS_INVALID_PARAMETER
;
240 cmd
= SVAL(inhdr
, SMB2_HDR_OPCODE
);
241 if (cmd
!= SMB2_OP_NEGPROT
) {
242 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
244 return NT_STATUS_INVALID_PARAMETER
;
247 next_command_ofs
= IVAL(inhdr
, SMB2_HDR_NEXT_COMMAND
);
248 if (next_command_ofs
!= 0) {
249 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
251 return NT_STATUS_INVALID_PARAMETER
;
254 req
= smbd_smb2_request_allocate(sconn
);
256 return NT_STATUS_NO_MEMORY
;
260 talloc_steal(req
, inbuf
);
262 req
->in
.vector
= talloc_array(req
, struct iovec
, 4);
263 if (req
->in
.vector
== NULL
) {
265 return NT_STATUS_NO_MEMORY
;
267 req
->in
.vector_count
= 4;
269 memcpy(req
->in
.nbt_hdr
, inbuf
, 4);
272 req
->in
.vector
[0].iov_base
= (void *)req
->in
.nbt_hdr
;
273 req
->in
.vector
[0].iov_len
= 4;
274 ofs
+= req
->in
.vector
[0].iov_len
;
276 req
->in
.vector
[1].iov_base
= (void *)(inbuf
+ ofs
);
277 req
->in
.vector
[1].iov_len
= SMB2_HDR_BODY
;
278 ofs
+= req
->in
.vector
[1].iov_len
;
280 req
->in
.vector
[2].iov_base
= (void *)(inbuf
+ ofs
);
281 req
->in
.vector
[2].iov_len
= SVAL(inbuf
, ofs
) & 0xFFFE;
282 ofs
+= req
->in
.vector
[2].iov_len
;
285 return NT_STATUS_INVALID_PARAMETER
;
288 req
->in
.vector
[3].iov_base
= (void *)(inbuf
+ ofs
);
289 req
->in
.vector
[3].iov_len
= size
- ofs
;
290 ofs
+= req
->in
.vector
[3].iov_len
;
292 req
->current_idx
= 1;
298 static bool smb2_validate_message_id(struct smbd_server_connection
*sconn
,
299 const uint8_t *inhdr
)
301 uint64_t message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
302 struct bitmap
*credits_bm
= sconn
->smb2
.credits_bitmap
;
303 uint16_t opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
304 unsigned int bitmap_offset
;
306 if (opcode
== SMB2_OP_CANCEL
) {
307 /* SMB2_CANCEL requests by definition resend messageids. */
311 if (message_id
< sconn
->smb2
.seqnum_low
||
312 message_id
> (sconn
->smb2
.seqnum_low
+
313 (sconn
->smb2
.max_credits
* DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
))) {
314 DEBUG(0,("smb2_validate_message_id: bad message_id "
315 "%llu (low = %llu, max = %lu)\n",
316 (unsigned long long)message_id
,
317 (unsigned long long)sconn
->smb2
.seqnum_low
,
318 (unsigned long)sconn
->smb2
.max_credits
));
322 /* client just used a credit. */
323 SMB_ASSERT(sconn
->smb2
.credits_granted
> 0);
324 sconn
->smb2
.credits_granted
-= 1;
326 /* Mark the message_id as seen in the bitmap. */
327 bitmap_offset
= (unsigned int)(message_id
%
328 (uint64_t)(sconn
->smb2
.max_credits
* DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
));
329 if (bitmap_query(credits_bm
, bitmap_offset
)) {
330 DEBUG(0,("smb2_validate_message_id: duplicate message_id "
331 "%llu (bm offset %u)\n",
332 (unsigned long long)message_id
,
336 bitmap_set(credits_bm
, bitmap_offset
);
338 if (message_id
== sconn
->smb2
.seqnum_low
+ 1) {
339 /* Move the window forward by all the message_id's
341 while (bitmap_query(credits_bm
, bitmap_offset
)) {
342 DEBUG(10,("smb2_validate_message_id: clearing "
343 "id %llu (position %u) from bitmap\n",
344 (unsigned long long)(sconn
->smb2
.seqnum_low
+ 1),
346 bitmap_clear(credits_bm
, bitmap_offset
);
347 sconn
->smb2
.seqnum_low
+= 1;
348 bitmap_offset
= (bitmap_offset
+ 1) %
349 (sconn
->smb2
.max_credits
* DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR
);
356 static NTSTATUS
smbd_smb2_request_validate(struct smbd_smb2_request
*req
)
361 count
= req
->in
.vector_count
;
364 /* It's not a SMB2 request */
365 return NT_STATUS_INVALID_PARAMETER
;
368 for (idx
=1; idx
< count
; idx
+= 3) {
369 const uint8_t *inhdr
= NULL
;
372 if (req
->in
.vector
[idx
].iov_len
!= SMB2_HDR_BODY
) {
373 return NT_STATUS_INVALID_PARAMETER
;
376 if (req
->in
.vector
[idx
+1].iov_len
< 2) {
377 return NT_STATUS_INVALID_PARAMETER
;
380 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
382 /* Check the SMB2 header */
383 if (IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
) != SMB2_MAGIC
) {
384 return NT_STATUS_INVALID_PARAMETER
;
387 if (!smb2_validate_message_id(req
->sconn
, inhdr
)) {
388 return NT_STATUS_INVALID_PARAMETER
;
391 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
394 * the 1st request should never have the
395 * SMB2_HDR_FLAG_CHAINED flag set
397 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
398 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
401 } else if (idx
== 4) {
403 * the 2nd request triggers related vs. unrelated
404 * compounded requests
406 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
407 req
->compound_related
= true;
409 } else if (idx
> 4) {
412 * It seems the this tests are wrong
413 * see the SMB2-COMPOUND test
417 * all other requests should match the 2nd one
419 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
420 if (!req
->compound_related
) {
422 NT_STATUS_INVALID_PARAMETER
;
426 if (req
->compound_related
) {
428 NT_STATUS_INVALID_PARAMETER
;
439 static void smb2_set_operation_credit(struct smbd_server_connection
*sconn
,
440 const struct iovec
*in_vector
,
441 struct iovec
*out_vector
)
443 const uint8_t *inhdr
= (const uint8_t *)in_vector
->iov_base
;
444 uint8_t *outhdr
= (uint8_t *)out_vector
->iov_base
;
445 uint16_t credits_requested
;
447 uint16_t credits_granted
= 0;
449 credits_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
450 out_flags
= IVAL(outhdr
, SMB2_HDR_FLAGS
);
452 SMB_ASSERT(sconn
->smb2
.max_credits
>= sconn
->smb2
.credits_granted
);
454 if (out_flags
& SMB2_HDR_FLAG_ASYNC
) {
456 * In case we already send an async interim
457 * response, we should not grant
458 * credits on the final response.
460 credits_requested
= 0;
463 if (credits_requested
) {
464 uint16_t modified_credits_requested
;
468 * Split up max_credits into 1/16ths, and then scale
469 * the requested credits by how many 16ths have been
470 * currently granted. Less than 1/16th == grant all
471 * requested (100%), scale down as more have been
472 * granted. Never ask for less than 1 as the client
473 * asked for at least 1. JRA.
476 multiplier
= 16 - (((sconn
->smb2
.credits_granted
* 16) / sconn
->smb2
.max_credits
) % 16);
478 modified_credits_requested
= (multiplier
* credits_requested
) / 16;
479 if (modified_credits_requested
== 0) {
480 modified_credits_requested
= 1;
483 /* Remember what we gave out. */
484 credits_granted
= MIN(modified_credits_requested
,
485 (sconn
->smb2
.max_credits
- sconn
->smb2
.credits_granted
));
488 if (credits_granted
== 0 && sconn
->smb2
.credits_granted
== 0) {
489 /* First negprot packet, or ensure the client credits can
490 never drop to zero. */
494 SSVAL(outhdr
, SMB2_HDR_CREDIT
, credits_granted
);
495 sconn
->smb2
.credits_granted
+= credits_granted
;
497 DEBUG(10,("smb2_set_operation_credit: requested %u, "
498 "granted %u, total granted %u\n",
499 (unsigned int)credits_requested
,
500 (unsigned int)credits_granted
,
501 (unsigned int)sconn
->smb2
.credits_granted
));
504 static void smb2_calculate_credits(const struct smbd_smb2_request
*inreq
,
505 struct smbd_smb2_request
*outreq
)
509 count
= outreq
->out
.vector_count
;
511 for (idx
=1; idx
< count
; idx
+= 3) {
512 smb2_set_operation_credit(outreq
->sconn
,
513 &inreq
->in
.vector
[idx
],
514 &outreq
->out
.vector
[idx
]);
518 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
)
520 struct iovec
*vector
;
524 count
= req
->in
.vector_count
;
525 vector
= talloc_zero_array(req
, struct iovec
, count
);
526 if (vector
== NULL
) {
527 return NT_STATUS_NO_MEMORY
;
530 vector
[0].iov_base
= req
->out
.nbt_hdr
;
531 vector
[0].iov_len
= 4;
532 SIVAL(req
->out
.nbt_hdr
, 0, 0);
534 for (idx
=1; idx
< count
; idx
+= 3) {
535 const uint8_t *inhdr
= NULL
;
537 uint8_t *outhdr
= NULL
;
538 uint8_t *outbody
= NULL
;
539 uint32_t next_command_ofs
= 0;
540 struct iovec
*current
= &vector
[idx
];
542 if ((idx
+ 3) < count
) {
543 /* we have a next command -
544 * setup for the error case. */
545 next_command_ofs
= SMB2_HDR_BODY
+ 9;
548 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
549 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
551 outhdr
= talloc_zero_array(vector
, uint8_t,
553 if (outhdr
== NULL
) {
554 return NT_STATUS_NO_MEMORY
;
557 outbody
= outhdr
+ SMB2_HDR_BODY
;
559 current
[0].iov_base
= (void *)outhdr
;
560 current
[0].iov_len
= SMB2_HDR_BODY
;
562 current
[1].iov_base
= (void *)outbody
;
563 current
[1].iov_len
= 8;
565 current
[2].iov_base
= NULL
;
566 current
[2].iov_len
= 0;
568 /* setup the SMB2 header */
569 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
570 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
571 SSVAL(outhdr
, SMB2_HDR_EPOCH
, 0);
572 SIVAL(outhdr
, SMB2_HDR_STATUS
,
573 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
574 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
575 SVAL(inhdr
, SMB2_HDR_OPCODE
));
576 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
577 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
578 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
579 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
580 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
581 SIVAL(outhdr
, SMB2_HDR_PID
,
582 IVAL(inhdr
, SMB2_HDR_PID
));
583 SIVAL(outhdr
, SMB2_HDR_TID
,
584 IVAL(inhdr
, SMB2_HDR_TID
));
585 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
586 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
587 memset(outhdr
+ SMB2_HDR_SIGNATURE
, 0, 16);
589 /* setup error body header */
590 SSVAL(outbody
, 0x00, 0x08 + 1);
591 SSVAL(outbody
, 0x02, 0);
592 SIVAL(outbody
, 0x04, 0);
595 req
->out
.vector
= vector
;
596 req
->out
.vector_count
= count
;
598 /* setup the length of the NBT packet */
599 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
601 DLIST_ADD_END(req
->sconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
606 void smbd_server_connection_terminate_ex(struct smbd_server_connection
*sconn
,
608 const char *location
)
610 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
612 exit_server_cleanly(reason
);
615 static bool dup_smb2_vec3(TALLOC_CTX
*ctx
,
616 struct iovec
*outvec
,
617 const struct iovec
*srcvec
)
619 /* vec[0] is always boilerplate and must
620 * be allocated with size OUTVEC_ALLOC_SIZE. */
622 outvec
[0].iov_base
= talloc_memdup(ctx
,
625 if (!outvec
[0].iov_base
) {
628 outvec
[0].iov_len
= SMB2_HDR_BODY
;
631 * If this is a "standard" vec[1] of length 8,
632 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
633 * then duplicate this. Else use talloc_memdup().
636 if (srcvec
[1].iov_len
== 8 &&
637 srcvec
[1].iov_base
==
638 ((uint8_t *)srcvec
[0].iov_base
) +
640 outvec
[1].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
642 outvec
[1].iov_len
= 8;
644 outvec
[1].iov_base
= talloc_memdup(ctx
,
647 if (!outvec
[1].iov_base
) {
650 outvec
[1].iov_len
= srcvec
[1].iov_len
;
654 * If this is a "standard" vec[2] of length 1,
655 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
656 * then duplicate this. Else use talloc_memdup().
659 if (srcvec
[2].iov_base
&&
661 if (srcvec
[2].iov_base
==
662 ((uint8_t *)srcvec
[0].iov_base
) +
663 (OUTVEC_ALLOC_SIZE
- 1) &&
664 srcvec
[2].iov_len
== 1) {
665 /* Common SMB2 error packet case. */
666 outvec
[2].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
667 (OUTVEC_ALLOC_SIZE
- 1);
669 outvec
[2].iov_base
= talloc_memdup(ctx
,
672 if (!outvec
[2].iov_base
) {
676 outvec
[2].iov_len
= srcvec
[2].iov_len
;
678 outvec
[2].iov_base
= NULL
;
679 outvec
[2].iov_len
= 0;
684 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
686 struct smbd_smb2_request
*newreq
= NULL
;
687 struct iovec
*outvec
= NULL
;
688 int count
= req
->out
.vector_count
;
691 newreq
= smbd_smb2_request_allocate(req
->sconn
);
696 newreq
->sconn
= req
->sconn
;
697 newreq
->session
= req
->session
;
698 newreq
->do_signing
= req
->do_signing
;
699 newreq
->current_idx
= req
->current_idx
;
700 newreq
->async
= false;
701 newreq
->cancelled
= false;
702 /* Note we are leaving:
706 uninitialized as NULL here as
707 they're not used in the interim
708 response code. JRA. */
710 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
715 newreq
->out
.vector
= outvec
;
716 newreq
->out
.vector_count
= count
;
718 /* Setup the outvec's identically to req. */
719 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
720 outvec
[0].iov_len
= 4;
721 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
723 /* Setup the vectors identically to the ones in req. */
724 for (i
= 1; i
< count
; i
+= 3) {
725 if (!dup_smb2_vec3(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
736 smb2_setup_nbt_length(newreq
->out
.vector
,
737 newreq
->out
.vector_count
);
742 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
);
744 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
747 uint8_t *outhdr
= NULL
;
748 struct smbd_smb2_request
*nreq
= NULL
;
750 /* Create a new smb2 request we'll use
751 for the interim return. */
752 nreq
= dup_smb2_req(req
);
754 return NT_STATUS_NO_MEMORY
;
757 /* Lose the last 3 out vectors. They're the
758 ones we'll be using for the async reply. */
759 nreq
->out
.vector_count
-= 3;
761 smb2_setup_nbt_length(nreq
->out
.vector
,
762 nreq
->out
.vector_count
);
764 /* Step back to the previous reply. */
765 i
= nreq
->current_idx
- 3;
766 outhdr
= (uint8_t *)nreq
->out
.vector
[i
].iov_base
;
767 /* And end the chain. */
768 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
770 /* Calculate outgoing credits */
771 smb2_calculate_credits(req
, nreq
);
773 /* Re-sign if needed. */
774 if (nreq
->do_signing
) {
776 status
= smb2_signing_sign_pdu(nreq
->session
->session_key
,
777 &nreq
->out
.vector
[i
], 3);
778 if (!NT_STATUS_IS_OK(status
)) {
782 if (DEBUGLEVEL
>= 10) {
783 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
784 (unsigned int)nreq
->current_idx
);
785 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
786 (unsigned int)nreq
->out
.vector_count
);
787 print_req_vectors(nreq
);
789 nreq
->subreq
= tstream_writev_queue_send(nreq
,
790 nreq
->sconn
->smb2
.event_ctx
,
791 nreq
->sconn
->smb2
.stream
,
792 nreq
->sconn
->smb2
.send_queue
,
794 nreq
->out
.vector_count
);
796 if (nreq
->subreq
== NULL
) {
797 return NT_STATUS_NO_MEMORY
;
800 tevent_req_set_callback(nreq
->subreq
,
801 smbd_smb2_request_writev_done
,
807 struct smbd_smb2_request_pending_state
{
808 struct smbd_server_connection
*sconn
;
809 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x08 + 1];
810 struct iovec vector
[3];
813 static void smbd_smb2_request_pending_writev_done(struct tevent_req
*subreq
)
815 struct smbd_smb2_request_pending_state
*state
=
816 tevent_req_callback_data(subreq
,
817 struct smbd_smb2_request_pending_state
);
818 struct smbd_server_connection
*sconn
= state
->sconn
;
822 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
825 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
826 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
833 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
834 struct tevent_req
*subreq
)
837 struct smbd_smb2_request_pending_state
*state
= NULL
;
838 int i
= req
->current_idx
;
839 uint8_t *reqhdr
= NULL
;
841 uint8_t *body
= NULL
;
843 uint64_t message_id
= 0;
844 uint64_t async_id
= 0;
845 struct iovec
*outvec
= NULL
;
847 if (!tevent_req_is_in_progress(subreq
)) {
851 req
->subreq
= subreq
;
855 /* We're already async. */
859 if (req
->in
.vector_count
> i
+ 3) {
861 * We're trying to go async in a compound
862 * request chain. This is not allowed.
863 * Cancel the outstanding request.
865 tevent_req_cancel(req
->subreq
);
866 return smbd_smb2_request_error(req
,
867 NT_STATUS_INSUFFICIENT_RESOURCES
);
870 if (DEBUGLEVEL
>= 10) {
871 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
872 (unsigned int)req
->current_idx
);
873 print_req_vectors(req
);
876 if (req
->out
.vector_count
> 4) {
877 /* This is a compound reply. We
878 * must do an interim response
879 * followed by the async response
882 status
= smb2_send_async_interim_response(req
);
883 if (!NT_STATUS_IS_OK(status
)) {
888 * We're splitting off the last SMB2
889 * request in a compound set, and the
890 * smb2_send_async_interim_response()
891 * call above just sent all the replies
892 * for the previous SMB2 requests in
893 * this compound set. So we're no longer
894 * in the "compound_related_in_progress"
895 * state, and this is no longer a compound
898 req
->compound_related
= false;
899 req
->sconn
->smb2
.compound_related_in_progress
= false;
902 /* Don't return an intermediate packet on a pipe read/write. */
903 if (req
->tcon
&& req
->tcon
->compat_conn
&& IS_IPC(req
->tcon
->compat_conn
)) {
907 reqhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
908 flags
= (IVAL(reqhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
909 message_id
= BVAL(reqhdr
, SMB2_HDR_MESSAGE_ID
);
910 async_id
= message_id
; /* keep it simple for now... */
913 * What we send is identical to a smbd_smb2_request_error
914 * packet with an error status of STATUS_PENDING. Make use
915 * of this fact sometime when refactoring. JRA.
918 state
= talloc_zero(req
->sconn
, struct smbd_smb2_request_pending_state
);
920 return NT_STATUS_NO_MEMORY
;
922 state
->sconn
= req
->sconn
;
924 state
->vector
[0].iov_base
= (void *)state
->buf
;
925 state
->vector
[0].iov_len
= 4;
927 state
->vector
[1].iov_base
= state
->buf
+ 4;
928 state
->vector
[1].iov_len
= SMB2_HDR_BODY
;
930 state
->vector
[2].iov_base
= state
->buf
+ 4 + SMB2_HDR_BODY
;
931 state
->vector
[2].iov_len
= 9;
933 smb2_setup_nbt_length(state
->vector
, 3);
935 hdr
= (uint8_t *)state
->vector
[1].iov_base
;
936 body
= (uint8_t *)state
->vector
[2].iov_base
;
938 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
939 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
940 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
941 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
942 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(reqhdr
, SMB2_HDR_OPCODE
));
944 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
945 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
946 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
947 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
948 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
949 BVAL(reqhdr
, SMB2_HDR_SESSION_ID
));
950 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
952 SSVAL(body
, 0x00, 0x08 + 1);
954 SCVAL(body
, 0x02, 0);
955 SCVAL(body
, 0x03, 0);
956 SIVAL(body
, 0x04, 0);
957 /* Match W2K8R2... */
958 SCVAL(body
, 0x08, 0x21);
960 /* Ensure we correctly go through crediting. Grant
961 the credits now, and zero credits on the final
963 smb2_set_operation_credit(req
->sconn
,
967 if (req
->do_signing
) {
968 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
969 &state
->vector
[1], 2);
970 if (!NT_STATUS_IS_OK(status
)) {
975 subreq
= tstream_writev_queue_send(state
,
976 req
->sconn
->smb2
.event_ctx
,
977 req
->sconn
->smb2
.stream
,
978 req
->sconn
->smb2
.send_queue
,
982 if (subreq
== NULL
) {
983 return NT_STATUS_NO_MEMORY
;
986 tevent_req_set_callback(subreq
,
987 smbd_smb2_request_pending_writev_done
,
990 /* Note we're going async with this request. */
996 * Now manipulate req so that the outstanding async request
997 * is the only one left in the struct smbd_smb2_request.
1000 if (req
->current_idx
== 1) {
1001 /* There was only one. */
1005 /* Re-arrange the in.vectors. */
1006 req
->in
.vector
[1] = req
->in
.vector
[i
];
1007 req
->in
.vector
[2] = req
->in
.vector
[i
+1];
1008 req
->in
.vector
[3] = req
->in
.vector
[i
+2];
1009 req
->in
.vector_count
= 4;
1010 /* Reset the new in size. */
1011 smb2_setup_nbt_length(req
->in
.vector
, 4);
1013 /* Now recreate the out.vectors. */
1014 outvec
= talloc_zero_array(req
, struct iovec
, 4);
1016 return NT_STATUS_NO_MEMORY
;
1019 /* 0 is always boilerplate and must
1020 * be of size 4 for the length field. */
1022 outvec
[0].iov_base
= req
->out
.nbt_hdr
;
1023 outvec
[0].iov_len
= 4;
1024 SIVAL(req
->out
.nbt_hdr
, 0, 0);
1026 if (!dup_smb2_vec3(outvec
, &outvec
[1], &req
->out
.vector
[i
])) {
1027 return NT_STATUS_NO_MEMORY
;
1030 TALLOC_FREE(req
->out
.vector
);
1032 req
->out
.vector
= outvec
;
1034 req
->current_idx
= 1;
1035 req
->out
.vector_count
= 4;
1039 smb2_setup_nbt_length(req
->out
.vector
,
1040 req
->out
.vector_count
);
1043 /* Ensure our final reply matches the interim one. */
1044 reqhdr
= (uint8_t *)req
->out
.vector
[1].iov_base
;
1045 SIVAL(reqhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1046 SBVAL(reqhdr
, SMB2_HDR_PID
, async_id
);
1049 const uint8_t *inhdr
=
1050 (const uint8_t *)req
->in
.vector
[1].iov_base
;
1051 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1053 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1054 (unsigned long long)async_id
));
1058 return NT_STATUS_OK
;
1061 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
1063 struct smbd_server_connection
*sconn
= req
->sconn
;
1064 struct smbd_smb2_request
*cur
;
1065 const uint8_t *inhdr
;
1066 int i
= req
->current_idx
;
1068 uint64_t search_message_id
;
1069 uint64_t search_async_id
;
1072 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1074 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1075 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1076 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
1079 * we don't need the request anymore
1080 * cancel requests never have a response
1082 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1085 for (cur
= sconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
1086 const uint8_t *outhdr
;
1087 uint64_t message_id
;
1090 i
= cur
->current_idx
;
1092 outhdr
= (const uint8_t *)cur
->out
.vector
[i
].iov_base
;
1094 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1095 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
1097 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1098 if (search_async_id
== async_id
) {
1099 found_id
= async_id
;
1103 if (search_message_id
== message_id
) {
1104 found_id
= message_id
;
1110 if (cur
&& cur
->subreq
) {
1111 inhdr
= (const uint8_t *)cur
->in
.vector
[i
].iov_base
;
1112 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1113 "cancel opcode[%s] mid %llu\n",
1114 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1115 (unsigned long long)found_id
));
1116 tevent_req_cancel(cur
->subreq
);
1119 return NT_STATUS_OK
;
1122 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
1124 const uint8_t *inhdr
;
1125 int i
= req
->current_idx
;
1130 NTSTATUS session_status
;
1131 uint32_t allowed_flags
;
1132 NTSTATUS return_value
;
1134 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1136 /* TODO: verify more things */
1138 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1139 opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1140 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1141 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1142 smb2_opcode_name(opcode
),
1143 (unsigned long long)mid
));
1145 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
1146 SMB2_HDR_FLAG_SIGNED
|
1148 if (opcode
== SMB2_OP_CANCEL
) {
1149 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
1151 if ((flags
& ~allowed_flags
) != 0) {
1152 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1156 * Check if the client provided a valid session id,
1157 * if so smbd_smb2_request_check_session() calls
1158 * set_current_user_info().
1160 * As some command don't require a valid session id
1161 * we defer the check of the session_status
1163 session_status
= smbd_smb2_request_check_session(req
);
1165 req
->do_signing
= false;
1166 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
1167 if (!NT_STATUS_IS_OK(session_status
)) {
1168 return smbd_smb2_request_error(req
, session_status
);
1171 req
->do_signing
= true;
1172 status
= smb2_signing_check_pdu(req
->session
->session_key
,
1173 &req
->in
.vector
[i
], 3);
1174 if (!NT_STATUS_IS_OK(status
)) {
1175 return smbd_smb2_request_error(req
, status
);
1177 } else if (req
->session
&& req
->session
->do_signing
) {
1178 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
1181 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
1183 * This check is mostly for giving the correct error code
1184 * for compounded requests.
1186 * TODO: we may need to move this after the session
1189 if (!NT_STATUS_IS_OK(req
->next_status
)) {
1190 return smbd_smb2_request_error(req
, req
->next_status
);
1193 req
->compat_chain_fsp
= NULL
;
1196 if (req
->compound_related
) {
1197 req
->sconn
->smb2
.compound_related_in_progress
= true;
1201 case SMB2_OP_NEGPROT
:
1202 /* This call needs to be run as root */
1203 change_to_root_user();
1206 START_PROFILE(smb2_negprot
);
1207 return_value
= smbd_smb2_request_process_negprot(req
);
1208 END_PROFILE(smb2_negprot
);
1212 case SMB2_OP_SESSSETUP
:
1213 /* This call needs to be run as root */
1214 change_to_root_user();
1217 START_PROFILE(smb2_sesssetup
);
1218 return_value
= smbd_smb2_request_process_sesssetup(req
);
1219 END_PROFILE(smb2_sesssetup
);
1223 case SMB2_OP_LOGOFF
:
1224 if (!NT_STATUS_IS_OK(session_status
)) {
1225 return_value
= smbd_smb2_request_error(req
, session_status
);
1229 /* This call needs to be run as root */
1230 change_to_root_user();
1233 START_PROFILE(smb2_logoff
);
1234 return_value
= smbd_smb2_request_process_logoff(req
);
1235 END_PROFILE(smb2_logoff
);
1240 if (!NT_STATUS_IS_OK(session_status
)) {
1241 return_value
= smbd_smb2_request_error(req
, session_status
);
1246 * This call needs to be run as root.
1248 * smbd_smb2_request_process_tcon()
1249 * calls make_connection_snum(), which will call
1250 * change_to_user(), when needed.
1252 change_to_root_user();
1255 START_PROFILE(smb2_tcon
);
1256 return_value
= smbd_smb2_request_process_tcon(req
);
1257 END_PROFILE(smb2_tcon
);
1262 if (!NT_STATUS_IS_OK(session_status
)) {
1263 return_value
= smbd_smb2_request_error(req
, session_status
);
1267 * This call needs to be run as user.
1269 * smbd_smb2_request_check_tcon()
1270 * calls change_to_user() on success.
1272 status
= smbd_smb2_request_check_tcon(req
);
1273 if (!NT_STATUS_IS_OK(status
)) {
1274 return_value
= smbd_smb2_request_error(req
, status
);
1277 /* This call needs to be run as root */
1278 change_to_root_user();
1282 START_PROFILE(smb2_tdis
);
1283 return_value
= smbd_smb2_request_process_tdis(req
);
1284 END_PROFILE(smb2_tdis
);
1288 case SMB2_OP_CREATE
:
1289 if (!NT_STATUS_IS_OK(session_status
)) {
1290 return_value
= smbd_smb2_request_error(req
, session_status
);
1294 * This call needs to be run as user.
1296 * smbd_smb2_request_check_tcon()
1297 * calls change_to_user() on success.
1299 status
= smbd_smb2_request_check_tcon(req
);
1300 if (!NT_STATUS_IS_OK(status
)) {
1301 return_value
= smbd_smb2_request_error(req
, status
);
1306 START_PROFILE(smb2_create
);
1307 return_value
= smbd_smb2_request_process_create(req
);
1308 END_PROFILE(smb2_create
);
1313 if (!NT_STATUS_IS_OK(session_status
)) {
1314 return_value
= smbd_smb2_request_error(req
, session_status
);
1318 * This call needs to be run as user.
1320 * smbd_smb2_request_check_tcon()
1321 * calls change_to_user() on success.
1323 status
= smbd_smb2_request_check_tcon(req
);
1324 if (!NT_STATUS_IS_OK(status
)) {
1325 return_value
= smbd_smb2_request_error(req
, status
);
1330 START_PROFILE(smb2_close
);
1331 return_value
= smbd_smb2_request_process_close(req
);
1332 END_PROFILE(smb2_close
);
1337 if (!NT_STATUS_IS_OK(session_status
)) {
1338 return_value
= smbd_smb2_request_error(req
, session_status
);
1342 * This call needs to be run as user.
1344 * smbd_smb2_request_check_tcon()
1345 * calls change_to_user() on success.
1347 status
= smbd_smb2_request_check_tcon(req
);
1348 if (!NT_STATUS_IS_OK(status
)) {
1349 return_value
= smbd_smb2_request_error(req
, status
);
1354 START_PROFILE(smb2_flush
);
1355 return_value
= smbd_smb2_request_process_flush(req
);
1356 END_PROFILE(smb2_flush
);
1361 if (!NT_STATUS_IS_OK(session_status
)) {
1362 return_value
= smbd_smb2_request_error(req
, session_status
);
1366 * This call needs to be run as user.
1368 * smbd_smb2_request_check_tcon()
1369 * calls change_to_user() on success.
1371 status
= smbd_smb2_request_check_tcon(req
);
1372 if (!NT_STATUS_IS_OK(status
)) {
1373 return_value
= smbd_smb2_request_error(req
, status
);
1378 START_PROFILE(smb2_read
);
1379 return_value
= smbd_smb2_request_process_read(req
);
1380 END_PROFILE(smb2_read
);
1385 if (!NT_STATUS_IS_OK(session_status
)) {
1386 return_value
= smbd_smb2_request_error(req
, session_status
);
1390 * This call needs to be run as user.
1392 * smbd_smb2_request_check_tcon()
1393 * calls change_to_user() on success.
1395 status
= smbd_smb2_request_check_tcon(req
);
1396 if (!NT_STATUS_IS_OK(status
)) {
1397 return_value
= smbd_smb2_request_error(req
, status
);
1402 START_PROFILE(smb2_write
);
1403 return_value
= smbd_smb2_request_process_write(req
);
1404 END_PROFILE(smb2_write
);
1409 if (!NT_STATUS_IS_OK(session_status
)) {
1410 /* Too ugly to live ? JRA. */
1411 if (NT_STATUS_EQUAL(session_status
,NT_STATUS_USER_SESSION_DELETED
)) {
1412 session_status
= NT_STATUS_FILE_CLOSED
;
1414 return_value
= smbd_smb2_request_error(req
, session_status
);
1418 * This call needs to be run as user.
1420 * smbd_smb2_request_check_tcon()
1421 * calls change_to_user() on success.
1423 status
= smbd_smb2_request_check_tcon(req
);
1424 if (!NT_STATUS_IS_OK(status
)) {
1425 /* Too ugly to live ? JRA. */
1426 if (NT_STATUS_EQUAL(status
,NT_STATUS_NETWORK_NAME_DELETED
)) {
1427 status
= NT_STATUS_FILE_CLOSED
;
1429 return_value
= smbd_smb2_request_error(req
, status
);
1434 START_PROFILE(smb2_lock
);
1435 return_value
= smbd_smb2_request_process_lock(req
);
1436 END_PROFILE(smb2_lock
);
1441 if (!NT_STATUS_IS_OK(session_status
)) {
1442 return_value
= smbd_smb2_request_error(req
, session_status
);
1446 * This call needs to be run as user.
1448 * smbd_smb2_request_check_tcon()
1449 * calls change_to_user() on success.
1451 status
= smbd_smb2_request_check_tcon(req
);
1452 if (!NT_STATUS_IS_OK(status
)) {
1453 return_value
= smbd_smb2_request_error(req
, status
);
1458 START_PROFILE(smb2_ioctl
);
1459 return_value
= smbd_smb2_request_process_ioctl(req
);
1460 END_PROFILE(smb2_ioctl
);
1464 case SMB2_OP_CANCEL
:
1466 * This call needs to be run as root
1468 * That is what we also do in the SMB1 case.
1470 change_to_root_user();
1473 START_PROFILE(smb2_cancel
);
1474 return_value
= smbd_smb2_request_process_cancel(req
);
1475 END_PROFILE(smb2_cancel
);
1479 case SMB2_OP_KEEPALIVE
:
1480 /* This call needs to be run as root */
1481 change_to_root_user();
1484 START_PROFILE(smb2_keepalive
);
1485 return_value
= smbd_smb2_request_process_keepalive(req
);
1486 END_PROFILE(smb2_keepalive
);
1491 if (!NT_STATUS_IS_OK(session_status
)) {
1492 return_value
= smbd_smb2_request_error(req
, session_status
);
1496 * This call needs to be run as user.
1498 * smbd_smb2_request_check_tcon()
1499 * calls change_to_user() on success.
1501 status
= smbd_smb2_request_check_tcon(req
);
1502 if (!NT_STATUS_IS_OK(status
)) {
1503 return_value
= smbd_smb2_request_error(req
, status
);
1508 START_PROFILE(smb2_find
);
1509 return_value
= smbd_smb2_request_process_find(req
);
1510 END_PROFILE(smb2_find
);
1514 case SMB2_OP_NOTIFY
:
1515 if (!NT_STATUS_IS_OK(session_status
)) {
1516 return_value
= smbd_smb2_request_error(req
, session_status
);
1520 * This call needs to be run as user.
1522 * smbd_smb2_request_check_tcon()
1523 * calls change_to_user() on success.
1525 status
= smbd_smb2_request_check_tcon(req
);
1526 if (!NT_STATUS_IS_OK(status
)) {
1527 return_value
= smbd_smb2_request_error(req
, status
);
1532 START_PROFILE(smb2_notify
);
1533 return_value
= smbd_smb2_request_process_notify(req
);
1534 END_PROFILE(smb2_notify
);
1538 case SMB2_OP_GETINFO
:
1539 if (!NT_STATUS_IS_OK(session_status
)) {
1540 return_value
= smbd_smb2_request_error(req
, session_status
);
1544 * This call needs to be run as user.
1546 * smbd_smb2_request_check_tcon()
1547 * calls change_to_user() on success.
1549 status
= smbd_smb2_request_check_tcon(req
);
1550 if (!NT_STATUS_IS_OK(status
)) {
1551 return_value
= smbd_smb2_request_error(req
, status
);
1556 START_PROFILE(smb2_getinfo
);
1557 return_value
= smbd_smb2_request_process_getinfo(req
);
1558 END_PROFILE(smb2_getinfo
);
1562 case SMB2_OP_SETINFO
:
1563 if (!NT_STATUS_IS_OK(session_status
)) {
1564 return_value
= smbd_smb2_request_error(req
, session_status
);
1568 * This call needs to be run as user.
1570 * smbd_smb2_request_check_tcon()
1571 * calls change_to_user() on success.
1573 status
= smbd_smb2_request_check_tcon(req
);
1574 if (!NT_STATUS_IS_OK(status
)) {
1575 return_value
= smbd_smb2_request_error(req
, status
);
1580 START_PROFILE(smb2_setinfo
);
1581 return_value
= smbd_smb2_request_process_setinfo(req
);
1582 END_PROFILE(smb2_setinfo
);
1587 if (!NT_STATUS_IS_OK(session_status
)) {
1588 return_value
= smbd_smb2_request_error(req
, session_status
);
1592 * This call needs to be run as user.
1594 * smbd_smb2_request_check_tcon()
1595 * calls change_to_user() on success.
1597 status
= smbd_smb2_request_check_tcon(req
);
1598 if (!NT_STATUS_IS_OK(status
)) {
1599 return_value
= smbd_smb2_request_error(req
, status
);
1604 START_PROFILE(smb2_break
);
1605 return_value
= smbd_smb2_request_process_break(req
);
1606 END_PROFILE(smb2_break
);
1611 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1614 return return_value
;
1617 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
1619 struct tevent_req
*subreq
;
1620 int i
= req
->current_idx
;
1624 req
->current_idx
+= 3;
1626 if (req
->current_idx
< req
->out
.vector_count
) {
1628 * We must process the remaining compound
1629 * SMB2 requests before any new incoming SMB2
1630 * requests. This is because incoming SMB2
1631 * requests may include a cancel for a
1632 * compound request we haven't processed
1635 struct tevent_immediate
*im
= tevent_create_immediate(req
);
1637 return NT_STATUS_NO_MEMORY
;
1639 tevent_schedule_immediate(im
,
1640 req
->sconn
->smb2
.event_ctx
,
1641 smbd_smb2_request_dispatch_immediate
,
1643 return NT_STATUS_OK
;
1646 if (req
->compound_related
) {
1647 req
->sconn
->smb2
.compound_related_in_progress
= false;
1650 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
1652 /* Set credit for this operation (zero credits if this
1653 is a final reply for an async operation). */
1654 smb2_set_operation_credit(req
->sconn
,
1656 &req
->out
.vector
[i
]);
1658 if (req
->do_signing
) {
1660 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
1661 &req
->out
.vector
[i
], 3);
1662 if (!NT_STATUS_IS_OK(status
)) {
1667 if (DEBUGLEVEL
>= 10) {
1668 dbgtext("smbd_smb2_request_reply: sending...\n");
1669 print_req_vectors(req
);
1672 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1673 if (req
->out
.vector_count
== 4 &&
1674 req
->out
.vector
[3].iov_base
== NULL
&&
1675 req
->out
.vector
[3].iov_len
!= 0) {
1676 /* Dynamic part is NULL. Chop it off,
1677 We're going to send it via sendfile. */
1678 req
->out
.vector_count
-= 1;
1681 subreq
= tstream_writev_queue_send(req
,
1682 req
->sconn
->smb2
.event_ctx
,
1683 req
->sconn
->smb2
.stream
,
1684 req
->sconn
->smb2
.send_queue
,
1686 req
->out
.vector_count
);
1687 if (subreq
== NULL
) {
1688 return NT_STATUS_NO_MEMORY
;
1690 tevent_req_set_callback(subreq
, smbd_smb2_request_writev_done
, req
);
1692 * We're done with this request -
1693 * move it off the "being processed" queue.
1695 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1697 return NT_STATUS_OK
;
1700 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
);
1702 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
1703 struct tevent_immediate
*im
,
1706 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
1707 struct smbd_smb2_request
);
1708 struct smbd_server_connection
*sconn
= req
->sconn
;
1713 if (DEBUGLEVEL
>= 10) {
1714 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1715 req
->current_idx
, req
->in
.vector_count
));
1716 print_req_vectors(req
);
1719 status
= smbd_smb2_request_dispatch(req
);
1720 if (!NT_STATUS_IS_OK(status
)) {
1721 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1725 status
= smbd_smb2_request_next_incoming(sconn
);
1726 if (!NT_STATUS_IS_OK(status
)) {
1727 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1732 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
)
1734 struct smbd_smb2_request
*req
= tevent_req_callback_data(subreq
,
1735 struct smbd_smb2_request
);
1736 struct smbd_server_connection
*sconn
= req
->sconn
;
1741 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1742 TALLOC_FREE(subreq
);
1745 status
= map_nt_error_from_unix(sys_errno
);
1746 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1747 nt_errstr(status
)));
1748 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1752 status
= smbd_smb2_request_next_incoming(sconn
);
1753 if (!NT_STATUS_IS_OK(status
)) {
1754 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1759 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
1761 DATA_BLOB body
, DATA_BLOB
*dyn
,
1762 const char *location
)
1765 int i
= req
->current_idx
;
1766 uint32_t next_command_ofs
;
1768 DEBUG(10,("smbd_smb2_request_done_ex: "
1769 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1770 i
, nt_errstr(status
), (unsigned int)body
.length
,
1772 (unsigned int)(dyn
? dyn
->length
: 0),
1775 if (body
.length
< 2) {
1776 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
1779 if ((body
.length
% 2) != 0) {
1780 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
1783 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
1785 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
1786 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
1788 req
->out
.vector
[i
+1].iov_base
= (void *)body
.data
;
1789 req
->out
.vector
[i
+1].iov_len
= body
.length
;
1792 req
->out
.vector
[i
+2].iov_base
= (void *)dyn
->data
;
1793 req
->out
.vector
[i
+2].iov_len
= dyn
->length
;
1795 req
->out
.vector
[i
+2].iov_base
= NULL
;
1796 req
->out
.vector
[i
+2].iov_len
= 0;
1799 /* see if we need to recalculate the offset to the next response */
1800 if (next_command_ofs
> 0) {
1801 next_command_ofs
= SMB2_HDR_BODY
;
1802 next_command_ofs
+= req
->out
.vector
[i
+1].iov_len
;
1803 next_command_ofs
+= req
->out
.vector
[i
+2].iov_len
;
1806 if ((next_command_ofs
% 8) != 0) {
1807 size_t pad_size
= 8 - (next_command_ofs
% 8);
1808 if (req
->out
.vector
[i
+2].iov_len
== 0) {
1810 * if the dyn buffer is empty
1811 * we can use it to add padding
1815 pad
= talloc_zero_array(req
->out
.vector
,
1818 return smbd_smb2_request_error(req
,
1819 NT_STATUS_NO_MEMORY
);
1822 req
->out
.vector
[i
+2].iov_base
= (void *)pad
;
1823 req
->out
.vector
[i
+2].iov_len
= pad_size
;
1826 * For now we copy the dynamic buffer
1827 * and add the padding to the new buffer
1834 old_size
= req
->out
.vector
[i
+2].iov_len
;
1835 old_dyn
= (uint8_t *)req
->out
.vector
[i
+2].iov_base
;
1837 new_size
= old_size
+ pad_size
;
1838 new_dyn
= talloc_zero_array(req
->out
.vector
,
1840 if (new_dyn
== NULL
) {
1841 return smbd_smb2_request_error(req
,
1842 NT_STATUS_NO_MEMORY
);
1845 memcpy(new_dyn
, old_dyn
, old_size
);
1846 memset(new_dyn
+ old_size
, 0, pad_size
);
1848 req
->out
.vector
[i
+2].iov_base
= (void *)new_dyn
;
1849 req
->out
.vector
[i
+2].iov_len
= new_size
;
1851 next_command_ofs
+= pad_size
;
1854 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
1856 return smbd_smb2_request_reply(req
);
1859 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
1862 const char *location
)
1865 int i
= req
->current_idx
;
1866 uint8_t *outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
1868 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1869 i
, nt_errstr(status
), info
? " +info" : "",
1872 body
.data
= outhdr
+ SMB2_HDR_BODY
;
1874 SSVAL(body
.data
, 0, 9);
1877 SIVAL(body
.data
, 0x04, info
->length
);
1879 /* Allocated size of req->out.vector[i].iov_base
1880 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
1881 * 1 byte without having to do an alloc.
1883 info
= talloc_zero_array(req
->out
.vector
,
1887 return NT_STATUS_NO_MEMORY
;
1889 info
->data
= ((uint8_t *)outhdr
) +
1890 OUTVEC_ALLOC_SIZE
- 1;
1892 SCVAL(info
->data
, 0, 0);
1896 * if a request fails, all other remaining
1897 * compounded requests should fail too
1899 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
1901 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
1905 struct smbd_smb2_send_oplock_break_state
{
1906 struct smbd_server_connection
*sconn
;
1907 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x18];
1908 struct iovec vector
;
1911 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
);
1913 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
1914 uint64_t file_id_persistent
,
1915 uint64_t file_id_volatile
,
1916 uint8_t oplock_level
)
1918 struct smbd_smb2_send_oplock_break_state
*state
;
1919 struct tevent_req
*subreq
;
1923 state
= talloc(sconn
, struct smbd_smb2_send_oplock_break_state
);
1924 if (state
== NULL
) {
1925 return NT_STATUS_NO_MEMORY
;
1927 state
->sconn
= sconn
;
1929 state
->vector
.iov_base
= (void *)state
->buf
;
1930 state
->vector
.iov_len
= sizeof(state
->buf
);
1932 _smb2_setlen(state
->buf
, sizeof(state
->buf
) - 4);
1933 hdr
= state
->buf
+ 4;
1934 body
= hdr
+ SMB2_HDR_BODY
;
1936 SIVAL(hdr
, 0, SMB2_MAGIC
);
1937 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1938 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1939 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
1940 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
1941 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
1942 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
1943 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1944 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
1945 SIVAL(hdr
, SMB2_HDR_PID
, 0);
1946 SIVAL(hdr
, SMB2_HDR_TID
, 0);
1947 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
1948 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
1950 SSVAL(body
, 0x00, 0x18);
1952 SCVAL(body
, 0x02, oplock_level
);
1953 SCVAL(body
, 0x03, 0); /* reserved */
1954 SIVAL(body
, 0x04, 0); /* reserved */
1955 SBVAL(body
, 0x08, file_id_persistent
);
1956 SBVAL(body
, 0x10, file_id_volatile
);
1958 subreq
= tstream_writev_queue_send(state
,
1959 sconn
->smb2
.event_ctx
,
1961 sconn
->smb2
.send_queue
,
1963 if (subreq
== NULL
) {
1964 return NT_STATUS_NO_MEMORY
;
1966 tevent_req_set_callback(subreq
,
1967 smbd_smb2_oplock_break_writev_done
,
1970 return NT_STATUS_OK
;
1973 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
)
1975 struct smbd_smb2_send_oplock_break_state
*state
=
1976 tevent_req_callback_data(subreq
,
1977 struct smbd_smb2_send_oplock_break_state
);
1978 struct smbd_server_connection
*sconn
= state
->sconn
;
1982 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1983 TALLOC_FREE(subreq
);
1985 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
1986 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1993 struct smbd_smb2_request_read_state
{
1995 bool asked_for_header
;
1996 struct smbd_smb2_request
*smb2_req
;
1999 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2001 TALLOC_CTX
*mem_ctx
,
2002 struct iovec
**_vector
,
2004 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
);
2006 static struct tevent_req
*smbd_smb2_request_read_send(TALLOC_CTX
*mem_ctx
,
2007 struct tevent_context
*ev
,
2008 struct smbd_server_connection
*sconn
)
2010 struct tevent_req
*req
;
2011 struct smbd_smb2_request_read_state
*state
;
2012 struct tevent_req
*subreq
;
2014 req
= tevent_req_create(mem_ctx
, &state
,
2015 struct smbd_smb2_request_read_state
);
2020 state
->asked_for_header
= false;
2022 state
->smb2_req
= smbd_smb2_request_allocate(state
);
2023 if (tevent_req_nomem(state
->smb2_req
, req
)) {
2024 return tevent_req_post(req
, ev
);
2026 state
->smb2_req
->sconn
= sconn
;
2028 subreq
= tstream_readv_pdu_queue_send(state
, ev
, sconn
->smb2
.stream
,
2029 sconn
->smb2
.recv_queue
,
2030 smbd_smb2_request_next_vector
,
2032 if (tevent_req_nomem(subreq
, req
)) {
2033 return tevent_req_post(req
, ev
);
2035 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
2040 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
2042 TALLOC_CTX
*mem_ctx
,
2043 struct iovec
**_vector
,
2046 struct smbd_smb2_request_read_state
*state
=
2047 talloc_get_type_abort(private_data
,
2048 struct smbd_smb2_request_read_state
);
2049 struct smbd_smb2_request
*req
= state
->smb2_req
;
2050 struct iovec
*vector
;
2051 int idx
= req
->in
.vector_count
;
2053 uint8_t *buf
= NULL
;
2055 if (req
->in
.vector_count
== 0) {
2057 * first we need to get the NBT header
2059 req
->in
.vector
= talloc_array(req
, struct iovec
,
2060 req
->in
.vector_count
+ 1);
2061 if (req
->in
.vector
== NULL
) {
2064 req
->in
.vector_count
+= 1;
2066 req
->in
.vector
[idx
].iov_base
= (void *)req
->in
.nbt_hdr
;
2067 req
->in
.vector
[idx
].iov_len
= 4;
2069 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2070 if (vector
== NULL
) {
2074 vector
[0] = req
->in
.vector
[idx
];
2081 if (req
->in
.vector_count
== 1) {
2083 * Now we analyze the NBT header
2085 state
->missing
= smb2_len(req
->in
.vector
[0].iov_base
);
2087 if (state
->missing
== 0) {
2088 /* if there're no remaining bytes, we're done */
2094 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2096 req
->in
.vector_count
+ 1);
2097 if (req
->in
.vector
== NULL
) {
2100 req
->in
.vector_count
+= 1;
2102 if (CVAL(req
->in
.vector
[0].iov_base
, 0) != 0) {
2104 * it's a special NBT message,
2105 * so get all remaining bytes
2107 len
= state
->missing
;
2108 } else if (state
->missing
< (SMB2_HDR_BODY
+ 2)) {
2110 * it's an invalid message, just read what we can get
2111 * and let the caller handle the error
2113 len
= state
->missing
;
2116 * We assume it's a SMB2 request,
2117 * and we first get the header and the
2118 * first 2 bytes (the struct size) of the body
2120 len
= SMB2_HDR_BODY
+ 2;
2122 state
->asked_for_header
= true;
2125 state
->missing
-= len
;
2127 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2132 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2133 req
->in
.vector
[idx
].iov_len
= len
;
2135 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2136 if (vector
== NULL
) {
2140 vector
[0] = req
->in
.vector
[idx
];
2147 if (state
->missing
== 0) {
2148 /* if there're no remaining bytes, we're done */
2154 if (state
->asked_for_header
) {
2157 size_t next_command_ofs
;
2162 bool invalid
= false;
2164 state
->asked_for_header
= false;
2167 * We got the SMB2 header and the first 2 bytes
2168 * of the body. We fix the size to just the header
2169 * and manually copy the 2 first bytes to the body section
2171 req
->in
.vector
[idx
-1].iov_len
= SMB2_HDR_BODY
;
2172 hdr
= (const uint8_t *)req
->in
.vector
[idx
-1].iov_base
;
2174 /* allocate vectors for body and dynamic areas */
2175 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2177 req
->in
.vector_count
+ 2);
2178 if (req
->in
.vector
== NULL
) {
2181 req
->in
.vector_count
+= 2;
2183 full_size
= state
->missing
+ SMB2_HDR_BODY
+ 2;
2184 next_command_ofs
= IVAL(hdr
, SMB2_HDR_NEXT_COMMAND
);
2185 body_size
= SVAL(hdr
, SMB2_HDR_BODY
);
2187 if (next_command_ofs
!= 0) {
2188 if (next_command_ofs
< (SMB2_HDR_BODY
+ 2)) {
2190 * this is invalid, just return a zero
2191 * body and let the caller deal with the error
2194 } else if (next_command_ofs
> full_size
) {
2196 * this is invalid, just return a zero
2197 * body and let the caller deal with the error
2201 full_size
= next_command_ofs
;
2206 if (body_size
< 2) {
2208 * this is invalid, just return a zero
2209 * body and let the caller deal with the error
2214 if ((body_size
% 2) != 0) {
2218 if (body_size
> (full_size
- SMB2_HDR_BODY
)) {
2220 * this is invalid, just return a zero
2221 * body and let the caller deal with the error
2228 /* the caller should check this */
2232 dyn_size
= full_size
- (SMB2_HDR_BODY
+ body_size
);
2234 state
->missing
-= (body_size
- 2) + dyn_size
;
2236 body
= talloc_array(req
->in
.vector
, uint8_t, body_size
);
2241 dyn
= talloc_array(req
->in
.vector
, uint8_t, dyn_size
);
2246 req
->in
.vector
[idx
].iov_base
= (void *)body
;
2247 req
->in
.vector
[idx
].iov_len
= body_size
;
2248 req
->in
.vector
[idx
+1].iov_base
= (void *)dyn
;
2249 req
->in
.vector
[idx
+1].iov_len
= dyn_size
;
2251 vector
= talloc_array(mem_ctx
, struct iovec
, 2);
2252 if (vector
== NULL
) {
2257 * the first 2 bytes of the body were already fetched
2258 * together with the header
2260 memcpy(body
, hdr
+ SMB2_HDR_BODY
, 2);
2261 vector
[0].iov_base
= body
+ 2;
2262 vector
[0].iov_len
= body_size
- 2;
2264 vector
[1] = req
->in
.vector
[idx
+1];
2272 * when we endup here, we're looking for a new SMB2 request
2273 * next. And we ask for its header and the first 2 bytes of
2274 * the body (like we did for the first SMB2 request).
2277 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2279 req
->in
.vector_count
+ 1);
2280 if (req
->in
.vector
== NULL
) {
2283 req
->in
.vector_count
+= 1;
2286 * We assume it's a SMB2 request,
2287 * and we first get the header and the
2288 * first 2 bytes (the struct size) of the body
2290 len
= SMB2_HDR_BODY
+ 2;
2292 if (len
> state
->missing
) {
2293 /* let the caller handle the error */
2294 len
= state
->missing
;
2297 state
->missing
-= len
;
2298 state
->asked_for_header
= true;
2300 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2305 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2306 req
->in
.vector
[idx
].iov_len
= len
;
2308 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2309 if (vector
== NULL
) {
2313 vector
[0] = req
->in
.vector
[idx
];
2320 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
)
2322 struct tevent_req
*req
=
2323 tevent_req_callback_data(subreq
,
2329 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
2331 status
= map_nt_error_from_unix(sys_errno
);
2332 tevent_req_nterror(req
, status
);
2336 tevent_req_done(req
);
2339 static NTSTATUS
smbd_smb2_request_read_recv(struct tevent_req
*req
,
2340 TALLOC_CTX
*mem_ctx
,
2341 struct smbd_smb2_request
**_smb2_req
)
2343 struct smbd_smb2_request_read_state
*state
=
2344 tevent_req_data(req
,
2345 struct smbd_smb2_request_read_state
);
2348 if (tevent_req_is_nterror(req
, &status
)) {
2349 tevent_req_received(req
);
2353 talloc_steal(mem_ctx
, state
->smb2_req
->mem_pool
);
2354 *_smb2_req
= state
->smb2_req
;
2355 tevent_req_received(req
);
2356 return NT_STATUS_OK
;
2359 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
);
2361 static NTSTATUS
smbd_smb2_request_next_incoming(struct smbd_server_connection
*sconn
)
2363 size_t max_send_queue_len
;
2364 size_t cur_send_queue_len
;
2365 struct tevent_req
*subreq
;
2367 if (sconn
->smb2
.compound_related_in_progress
) {
2369 * Can't read another until the related
2372 return NT_STATUS_OK
;
2375 if (tevent_queue_length(sconn
->smb2
.recv_queue
) > 0) {
2377 * if there is already a smbd_smb2_request_read
2378 * pending, we are done.
2380 return NT_STATUS_OK
;
2383 max_send_queue_len
= MAX(1, sconn
->smb2
.max_credits
/16);
2384 cur_send_queue_len
= tevent_queue_length(sconn
->smb2
.send_queue
);
2386 if (cur_send_queue_len
> max_send_queue_len
) {
2388 * if we have a lot of requests to send,
2389 * we wait until they are on the wire until we
2390 * ask for the next request.
2392 return NT_STATUS_OK
;
2395 /* ask for the next request */
2396 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->smb2
.event_ctx
, sconn
);
2397 if (subreq
== NULL
) {
2398 return NT_STATUS_NO_MEMORY
;
2400 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);
2402 return NT_STATUS_OK
;
2405 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
2406 const uint8_t *inbuf
, size_t size
)
2409 struct smbd_smb2_request
*req
= NULL
;
2411 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2412 (unsigned int)size
));
2414 status
= smbd_initialize_smb2(sconn
);
2415 if (!NT_STATUS_IS_OK(status
)) {
2416 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2420 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
2421 if (!NT_STATUS_IS_OK(status
)) {
2422 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2426 status
= smbd_smb2_request_setup_out(req
);
2427 if (!NT_STATUS_IS_OK(status
)) {
2428 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2432 status
= smbd_smb2_request_dispatch(req
);
2433 if (!NT_STATUS_IS_OK(status
)) {
2434 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2438 status
= smbd_smb2_request_next_incoming(sconn
);
2439 if (!NT_STATUS_IS_OK(status
)) {
2440 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2444 sconn
->num_requests
++;
2447 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
)
2449 struct smbd_server_connection
*sconn
= tevent_req_callback_data(subreq
,
2450 struct smbd_server_connection
);
2452 struct smbd_smb2_request
*req
= NULL
;
2454 status
= smbd_smb2_request_read_recv(subreq
, sconn
, &req
);
2455 TALLOC_FREE(subreq
);
2456 if (!NT_STATUS_IS_OK(status
)) {
2457 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2458 nt_errstr(status
)));
2459 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2463 if (req
->in
.nbt_hdr
[0] != 0x00) {
2464 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2465 req
->in
.nbt_hdr
[0]));
2470 req
->current_idx
= 1;
2472 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2473 req
->current_idx
, req
->in
.vector_count
));
2475 status
= smbd_smb2_request_validate(req
);
2476 if (!NT_STATUS_IS_OK(status
)) {
2477 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2481 status
= smbd_smb2_request_setup_out(req
);
2482 if (!NT_STATUS_IS_OK(status
)) {
2483 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2487 status
= smbd_smb2_request_dispatch(req
);
2488 if (!NT_STATUS_IS_OK(status
)) {
2489 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2494 status
= smbd_smb2_request_next_incoming(sconn
);
2495 if (!NT_STATUS_IS_OK(status
)) {
2496 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2500 sconn
->num_requests
++;
2502 /* The timeout_processing function isn't run nearly
2503 often enough to implement 'max log size' without
2504 overrunning the size of the file by many megabytes.
2505 This is especially true if we are running at debug
2506 level 10. Checking every 50 SMB2s is a nice
2507 tradeoff of performance vs log file size overrun. */
2509 if ((sconn
->num_requests
% 50) == 0 &&
2510 need_to_check_log_size()) {
2511 change_to_root_user();