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
)
360 bool compound_related
= false;
362 count
= req
->in
.vector_count
;
365 /* It's not a SMB2 request */
366 return NT_STATUS_INVALID_PARAMETER
;
369 for (idx
=1; idx
< count
; idx
+= 3) {
370 const uint8_t *inhdr
= NULL
;
373 if (req
->in
.vector
[idx
].iov_len
!= SMB2_HDR_BODY
) {
374 return NT_STATUS_INVALID_PARAMETER
;
377 if (req
->in
.vector
[idx
+1].iov_len
< 2) {
378 return NT_STATUS_INVALID_PARAMETER
;
381 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
383 /* Check the SMB2 header */
384 if (IVAL(inhdr
, SMB2_HDR_PROTOCOL_ID
) != SMB2_MAGIC
) {
385 return NT_STATUS_INVALID_PARAMETER
;
388 if (!smb2_validate_message_id(req
->sconn
, inhdr
)) {
389 return NT_STATUS_INVALID_PARAMETER
;
392 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
395 * the 1st request should never have the
396 * SMB2_HDR_FLAG_CHAINED flag set
398 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
399 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
402 } else if (idx
== 4) {
404 * the 2nd request triggers related vs. unrelated
405 * compounded requests
407 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
408 compound_related
= true;
410 } else if (idx
> 4) {
413 * It seems the this tests are wrong
414 * see the SMB2-COMPOUND test
418 * all other requests should match the 2nd one
420 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
421 if (!compound_related
) {
423 NT_STATUS_INVALID_PARAMETER
;
427 if (compound_related
) {
429 NT_STATUS_INVALID_PARAMETER
;
440 static void smb2_set_operation_credit(struct smbd_server_connection
*sconn
,
441 const struct iovec
*in_vector
,
442 struct iovec
*out_vector
)
444 uint8_t *outhdr
= (uint8_t *)out_vector
->iov_base
;
445 uint16_t credits_requested
= 0;
446 uint16_t credits_granted
= 0;
448 if (in_vector
!= NULL
) {
449 const uint8_t *inhdr
= (const uint8_t *)in_vector
->iov_base
;
450 credits_requested
= SVAL(inhdr
, SMB2_HDR_CREDIT
);
453 SMB_ASSERT(sconn
->smb2
.max_credits
>= sconn
->smb2
.credits_granted
);
455 if (credits_requested
) {
456 uint16_t modified_credits_requested
;
460 * Split up max_credits into 1/16ths, and then scale
461 * the requested credits by how many 16ths have been
462 * currently granted. Less than 1/16th == grant all
463 * requested (100%), scale down as more have been
464 * granted. Never ask for less than 1 as the client
465 * asked for at least 1. JRA.
468 multiplier
= 16 - (((sconn
->smb2
.credits_granted
* 16) / sconn
->smb2
.max_credits
) % 16);
470 modified_credits_requested
= (multiplier
* credits_requested
) / 16;
471 if (modified_credits_requested
== 0) {
472 modified_credits_requested
= 1;
475 /* Remember what we gave out. */
476 credits_granted
= MIN(modified_credits_requested
,
477 (sconn
->smb2
.max_credits
- sconn
->smb2
.credits_granted
));
480 if (credits_granted
== 0 && sconn
->smb2
.credits_granted
== 0) {
481 /* First negprot packet, or ensure the client credits can
482 never drop to zero. */
486 SSVAL(outhdr
, SMB2_HDR_CREDIT
, credits_granted
);
487 sconn
->smb2
.credits_granted
+= credits_granted
;
489 DEBUG(10,("smb2_set_operation_credit: requested %u, "
490 "granted %u, total granted %u\n",
491 (unsigned int)credits_requested
,
492 (unsigned int)credits_granted
,
493 (unsigned int)sconn
->smb2
.credits_granted
));
496 static void smb2_calculate_credits(const struct smbd_smb2_request
*inreq
,
497 struct smbd_smb2_request
*outreq
)
501 count
= outreq
->out
.vector_count
;
503 for (idx
=1; idx
< count
; idx
+= 3) {
504 smb2_set_operation_credit(outreq
->sconn
,
505 &inreq
->in
.vector
[idx
],
506 &outreq
->out
.vector
[idx
]);
510 static NTSTATUS
smbd_smb2_request_setup_out(struct smbd_smb2_request
*req
)
512 struct iovec
*vector
;
516 count
= req
->in
.vector_count
;
517 vector
= talloc_zero_array(req
, struct iovec
, count
);
518 if (vector
== NULL
) {
519 return NT_STATUS_NO_MEMORY
;
522 vector
[0].iov_base
= req
->out
.nbt_hdr
;
523 vector
[0].iov_len
= 4;
524 SIVAL(req
->out
.nbt_hdr
, 0, 0);
526 for (idx
=1; idx
< count
; idx
+= 3) {
527 const uint8_t *inhdr
= NULL
;
529 uint8_t *outhdr
= NULL
;
530 uint8_t *outbody
= NULL
;
531 uint32_t next_command_ofs
= 0;
532 struct iovec
*current
= &vector
[idx
];
534 if ((idx
+ 3) < count
) {
535 /* we have a next command -
536 * setup for the error case. */
537 next_command_ofs
= SMB2_HDR_BODY
+ 9;
540 inhdr
= (const uint8_t *)req
->in
.vector
[idx
].iov_base
;
541 in_flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
543 outhdr
= talloc_zero_array(vector
, uint8_t,
545 if (outhdr
== NULL
) {
546 return NT_STATUS_NO_MEMORY
;
549 outbody
= outhdr
+ SMB2_HDR_BODY
;
551 current
[0].iov_base
= (void *)outhdr
;
552 current
[0].iov_len
= SMB2_HDR_BODY
;
554 current
[1].iov_base
= (void *)outbody
;
555 current
[1].iov_len
= 8;
557 current
[2].iov_base
= NULL
;
558 current
[2].iov_len
= 0;
560 /* setup the SMB2 header */
561 SIVAL(outhdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
562 SSVAL(outhdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
563 SSVAL(outhdr
, SMB2_HDR_EPOCH
, 0);
564 SIVAL(outhdr
, SMB2_HDR_STATUS
,
565 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR
));
566 SSVAL(outhdr
, SMB2_HDR_OPCODE
,
567 SVAL(inhdr
, SMB2_HDR_OPCODE
));
568 SIVAL(outhdr
, SMB2_HDR_FLAGS
,
569 IVAL(inhdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_REDIRECT
);
570 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
571 SBVAL(outhdr
, SMB2_HDR_MESSAGE_ID
,
572 BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
));
573 SIVAL(outhdr
, SMB2_HDR_PID
,
574 IVAL(inhdr
, SMB2_HDR_PID
));
575 SIVAL(outhdr
, SMB2_HDR_TID
,
576 IVAL(inhdr
, SMB2_HDR_TID
));
577 SBVAL(outhdr
, SMB2_HDR_SESSION_ID
,
578 BVAL(inhdr
, SMB2_HDR_SESSION_ID
));
579 memset(outhdr
+ SMB2_HDR_SIGNATURE
, 0, 16);
581 /* setup error body header */
582 SSVAL(outbody
, 0x00, 0x08 + 1);
583 SSVAL(outbody
, 0x02, 0);
584 SIVAL(outbody
, 0x04, 0);
587 req
->out
.vector
= vector
;
588 req
->out
.vector_count
= count
;
590 /* setup the length of the NBT packet */
591 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
593 DLIST_ADD_END(req
->sconn
->smb2
.requests
, req
, struct smbd_smb2_request
*);
598 void smbd_server_connection_terminate_ex(struct smbd_server_connection
*sconn
,
600 const char *location
)
602 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
604 exit_server_cleanly(reason
);
607 static bool dup_smb2_vec3(TALLOC_CTX
*ctx
,
608 struct iovec
*outvec
,
609 const struct iovec
*srcvec
)
611 /* vec[0] is always boilerplate and must
612 * be allocated with size OUTVEC_ALLOC_SIZE. */
614 outvec
[0].iov_base
= talloc_memdup(ctx
,
617 if (!outvec
[0].iov_base
) {
620 outvec
[0].iov_len
= SMB2_HDR_BODY
;
623 * If this is a "standard" vec[1] of length 8,
624 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
625 * then duplicate this. Else use talloc_memdup().
628 if (srcvec
[1].iov_len
== 8 &&
629 srcvec
[1].iov_base
==
630 ((uint8_t *)srcvec
[0].iov_base
) +
632 outvec
[1].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
634 outvec
[1].iov_len
= 8;
636 outvec
[1].iov_base
= talloc_memdup(ctx
,
639 if (!outvec
[1].iov_base
) {
642 outvec
[1].iov_len
= srcvec
[1].iov_len
;
646 * If this is a "standard" vec[2] of length 1,
647 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
648 * then duplicate this. Else use talloc_memdup().
651 if (srcvec
[2].iov_base
&&
653 if (srcvec
[2].iov_base
==
654 ((uint8_t *)srcvec
[0].iov_base
) +
655 (OUTVEC_ALLOC_SIZE
- 1) &&
656 srcvec
[2].iov_len
== 1) {
657 /* Common SMB2 error packet case. */
658 outvec
[2].iov_base
= ((uint8_t *)outvec
[0].iov_base
) +
659 (OUTVEC_ALLOC_SIZE
- 1);
661 outvec
[2].iov_base
= talloc_memdup(ctx
,
664 if (!outvec
[2].iov_base
) {
668 outvec
[2].iov_len
= srcvec
[2].iov_len
;
670 outvec
[2].iov_base
= NULL
;
671 outvec
[2].iov_len
= 0;
676 static struct smbd_smb2_request
*dup_smb2_req(const struct smbd_smb2_request
*req
)
678 struct smbd_smb2_request
*newreq
= NULL
;
679 struct iovec
*outvec
= NULL
;
680 int count
= req
->out
.vector_count
;
683 newreq
= smbd_smb2_request_allocate(req
->sconn
);
688 newreq
->sconn
= req
->sconn
;
689 newreq
->session
= req
->session
;
690 newreq
->do_signing
= req
->do_signing
;
691 newreq
->current_idx
= req
->current_idx
;
692 newreq
->async
= false;
693 newreq
->cancelled
= false;
694 /* Note we are leaving:
698 uninitialized as NULL here as
699 they're not used in the interim
700 response code. JRA. */
702 outvec
= talloc_zero_array(newreq
, struct iovec
, count
);
707 newreq
->out
.vector
= outvec
;
708 newreq
->out
.vector_count
= count
;
710 /* Setup the outvec's identically to req. */
711 outvec
[0].iov_base
= newreq
->out
.nbt_hdr
;
712 outvec
[0].iov_len
= 4;
713 memcpy(newreq
->out
.nbt_hdr
, req
->out
.nbt_hdr
, 4);
715 /* Setup the vectors identically to the ones in req. */
716 for (i
= 1; i
< count
; i
+= 3) {
717 if (!dup_smb2_vec3(outvec
, &outvec
[i
], &req
->out
.vector
[i
])) {
728 smb2_setup_nbt_length(newreq
->out
.vector
,
729 newreq
->out
.vector_count
);
734 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
);
736 static NTSTATUS
smb2_send_async_interim_response(const struct smbd_smb2_request
*req
)
739 uint8_t *outhdr
= NULL
;
740 struct smbd_smb2_request
*nreq
= NULL
;
742 /* Create a new smb2 request we'll use
743 for the interim return. */
744 nreq
= dup_smb2_req(req
);
746 return NT_STATUS_NO_MEMORY
;
749 /* Lose the last 3 out vectors. They're the
750 ones we'll be using for the async reply. */
751 nreq
->out
.vector_count
-= 3;
753 smb2_setup_nbt_length(nreq
->out
.vector
,
754 nreq
->out
.vector_count
);
756 /* Step back to the previous reply. */
757 i
= nreq
->current_idx
- 3;
758 outhdr
= (uint8_t *)nreq
->out
.vector
[i
].iov_base
;
759 /* And end the chain. */
760 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, 0);
762 /* Calculate outgoing credits */
763 smb2_calculate_credits(req
, nreq
);
765 /* Re-sign if needed. */
766 if (nreq
->do_signing
) {
768 status
= smb2_signing_sign_pdu(nreq
->session
->session_key
,
769 &nreq
->out
.vector
[i
], 3);
770 if (!NT_STATUS_IS_OK(status
)) {
774 if (DEBUGLEVEL
>= 10) {
775 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
776 (unsigned int)nreq
->current_idx
);
777 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
778 (unsigned int)nreq
->out
.vector_count
);
779 print_req_vectors(nreq
);
781 nreq
->subreq
= tstream_writev_queue_send(nreq
,
782 nreq
->sconn
->smb2
.event_ctx
,
783 nreq
->sconn
->smb2
.stream
,
784 nreq
->sconn
->smb2
.send_queue
,
786 nreq
->out
.vector_count
);
788 if (nreq
->subreq
== NULL
) {
789 return NT_STATUS_NO_MEMORY
;
792 tevent_req_set_callback(nreq
->subreq
,
793 smbd_smb2_request_writev_done
,
799 struct smbd_smb2_request_pending_state
{
800 struct smbd_server_connection
*sconn
;
801 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x08 + 1];
802 struct iovec vector
[3];
805 static void smbd_smb2_request_pending_writev_done(struct tevent_req
*subreq
)
807 struct smbd_smb2_request_pending_state
*state
=
808 tevent_req_callback_data(subreq
,
809 struct smbd_smb2_request_pending_state
);
810 struct smbd_server_connection
*sconn
= state
->sconn
;
814 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
817 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
818 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
825 NTSTATUS
smbd_smb2_request_pending_queue(struct smbd_smb2_request
*req
,
826 struct tevent_req
*subreq
)
829 struct smbd_smb2_request_pending_state
*state
= NULL
;
830 int i
= req
->current_idx
;
831 uint8_t *reqhdr
= NULL
;
833 uint8_t *body
= NULL
;
835 uint64_t message_id
= 0;
836 uint64_t async_id
= 0;
837 struct iovec
*outvec
= NULL
;
839 if (!tevent_req_is_in_progress(subreq
)) {
843 req
->subreq
= subreq
;
847 /* We're already async. */
851 if (req
->in
.vector_count
> i
+ 3) {
853 * We're trying to go async in a compound
854 * request chain. This is not allowed.
855 * Cancel the outstanding request.
857 tevent_req_cancel(req
->subreq
);
858 return smbd_smb2_request_error(req
,
859 NT_STATUS_INSUFFICIENT_RESOURCES
);
862 if (DEBUGLEVEL
>= 10) {
863 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
864 (unsigned int)req
->current_idx
);
865 print_req_vectors(req
);
868 if (req
->out
.vector_count
> 4) {
869 /* This is a compound reply. We
870 * must do an interim response
871 * followed by the async response
874 status
= smb2_send_async_interim_response(req
);
875 if (!NT_STATUS_IS_OK(status
)) {
880 /* Don't return an intermediate packet on a pipe read/write. */
881 if (req
->tcon
&& req
->tcon
->compat_conn
&& IS_IPC(req
->tcon
->compat_conn
)) {
885 reqhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
886 flags
= (IVAL(reqhdr
, SMB2_HDR_FLAGS
) & ~SMB2_HDR_FLAG_CHAINED
);
887 message_id
= BVAL(reqhdr
, SMB2_HDR_MESSAGE_ID
);
888 async_id
= message_id
; /* keep it simple for now... */
891 * What we send is identical to a smbd_smb2_request_error
892 * packet with an error status of STATUS_PENDING. Make use
893 * of this fact sometime when refactoring. JRA.
896 state
= talloc_zero(req
->sconn
, struct smbd_smb2_request_pending_state
);
898 return NT_STATUS_NO_MEMORY
;
900 state
->sconn
= req
->sconn
;
902 state
->vector
[0].iov_base
= (void *)state
->buf
;
903 state
->vector
[0].iov_len
= 4;
905 state
->vector
[1].iov_base
= state
->buf
+ 4;
906 state
->vector
[1].iov_len
= SMB2_HDR_BODY
;
908 state
->vector
[2].iov_base
= state
->buf
+ 4 + SMB2_HDR_BODY
;
909 state
->vector
[2].iov_len
= 9;
911 smb2_setup_nbt_length(state
->vector
, 3);
913 hdr
= (uint8_t *)state
->vector
[1].iov_base
;
914 body
= (uint8_t *)state
->vector
[2].iov_base
;
916 SIVAL(hdr
, SMB2_HDR_PROTOCOL_ID
, SMB2_MAGIC
);
917 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
918 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
919 SIVAL(hdr
, SMB2_HDR_STATUS
, NT_STATUS_V(STATUS_PENDING
));
920 SSVAL(hdr
, SMB2_HDR_OPCODE
, SVAL(reqhdr
, SMB2_HDR_OPCODE
));
922 SIVAL(hdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
923 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
924 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, message_id
);
925 SBVAL(hdr
, SMB2_HDR_PID
, async_id
);
926 SBVAL(hdr
, SMB2_HDR_SESSION_ID
,
927 BVAL(reqhdr
, SMB2_HDR_SESSION_ID
));
928 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
930 SSVAL(body
, 0x00, 0x08 + 1);
932 SCVAL(body
, 0x02, 0);
933 SCVAL(body
, 0x03, 0);
934 SIVAL(body
, 0x04, 0);
935 /* Match W2K8R2... */
936 SCVAL(body
, 0x08, 0x21);
938 /* Ensure we correctly go through crediting. Grant
939 the credits now, and zero credits on the final
941 smb2_set_operation_credit(req
->sconn
,
945 if (req
->do_signing
) {
946 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
947 &state
->vector
[1], 2);
948 if (!NT_STATUS_IS_OK(status
)) {
953 subreq
= tstream_writev_queue_send(state
,
954 req
->sconn
->smb2
.event_ctx
,
955 req
->sconn
->smb2
.stream
,
956 req
->sconn
->smb2
.send_queue
,
960 if (subreq
== NULL
) {
961 return NT_STATUS_NO_MEMORY
;
964 tevent_req_set_callback(subreq
,
965 smbd_smb2_request_pending_writev_done
,
968 /* Note we're going async with this request. */
972 * Now manipulate req so that the outstanding async request
973 * is the only one left in the struct smbd_smb2_request.
976 if (req
->current_idx
== 1) {
977 /* There was only one. */
981 /* Re-arrange the in.vectors. */
982 req
->in
.vector
[1] = req
->in
.vector
[i
];
983 req
->in
.vector
[2] = req
->in
.vector
[i
+1];
984 req
->in
.vector
[3] = req
->in
.vector
[i
+2];
985 req
->in
.vector_count
= 4;
986 /* Reset the new in size. */
987 smb2_setup_nbt_length(req
->in
.vector
, 4);
989 /* Now recreate the out.vectors. */
990 outvec
= talloc_zero_array(req
, struct iovec
, 4);
992 return NT_STATUS_NO_MEMORY
;
995 /* 0 is always boilerplate and must
996 * be of size 4 for the length field. */
998 outvec
[0].iov_base
= req
->out
.nbt_hdr
;
999 outvec
[0].iov_len
= 4;
1000 SIVAL(req
->out
.nbt_hdr
, 0, 0);
1002 if (!dup_smb2_vec3(outvec
, &outvec
[1], &req
->out
.vector
[i
])) {
1003 return NT_STATUS_NO_MEMORY
;
1006 TALLOC_FREE(req
->out
.vector
);
1008 req
->out
.vector
= outvec
;
1010 req
->current_idx
= 1;
1011 req
->out
.vector_count
= 4;
1015 smb2_setup_nbt_length(req
->out
.vector
,
1016 req
->out
.vector_count
);
1018 /* Ensure our final reply matches the interim one. */
1019 reqhdr
= (uint8_t *)req
->out
.vector
[1].iov_base
;
1020 SIVAL(reqhdr
, SMB2_HDR_FLAGS
, flags
| SMB2_HDR_FLAG_ASYNC
);
1021 SBVAL(reqhdr
, SMB2_HDR_PID
, async_id
);
1024 const uint8_t *inhdr
=
1025 (const uint8_t *)req
->in
.vector
[1].iov_base
;
1026 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1028 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1029 (unsigned long long)async_id
));
1031 return NT_STATUS_OK
;
1034 static NTSTATUS
smbd_smb2_request_process_cancel(struct smbd_smb2_request
*req
)
1036 struct smbd_server_connection
*sconn
= req
->sconn
;
1037 struct smbd_smb2_request
*cur
;
1038 const uint8_t *inhdr
;
1039 int i
= req
->current_idx
;
1041 uint64_t search_message_id
;
1042 uint64_t search_async_id
;
1045 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1047 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1048 search_message_id
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1049 search_async_id
= BVAL(inhdr
, SMB2_HDR_PID
);
1052 * we don't need the request anymore
1053 * cancel requests never have a response
1055 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1058 for (cur
= sconn
->smb2
.requests
; cur
; cur
= cur
->next
) {
1059 const uint8_t *outhdr
;
1060 uint64_t message_id
;
1063 i
= cur
->current_idx
;
1065 outhdr
= (const uint8_t *)cur
->out
.vector
[i
].iov_base
;
1067 message_id
= BVAL(outhdr
, SMB2_HDR_MESSAGE_ID
);
1068 async_id
= BVAL(outhdr
, SMB2_HDR_PID
);
1070 if (flags
& SMB2_HDR_FLAG_ASYNC
) {
1071 if (search_async_id
== async_id
) {
1072 found_id
= async_id
;
1076 if (search_message_id
== message_id
) {
1077 found_id
= message_id
;
1083 if (cur
&& cur
->subreq
) {
1084 inhdr
= (const uint8_t *)cur
->in
.vector
[i
].iov_base
;
1085 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1086 "cancel opcode[%s] mid %llu\n",
1087 smb2_opcode_name((uint16_t)IVAL(inhdr
, SMB2_HDR_OPCODE
)),
1088 (unsigned long long)found_id
));
1089 tevent_req_cancel(cur
->subreq
);
1092 return NT_STATUS_OK
;
1095 NTSTATUS
smbd_smb2_request_dispatch(struct smbd_smb2_request
*req
)
1097 const uint8_t *inhdr
;
1098 int i
= req
->current_idx
;
1103 NTSTATUS session_status
;
1104 uint32_t allowed_flags
;
1105 NTSTATUS return_value
;
1107 inhdr
= (const uint8_t *)req
->in
.vector
[i
].iov_base
;
1109 /* TODO: verify more things */
1111 flags
= IVAL(inhdr
, SMB2_HDR_FLAGS
);
1112 opcode
= IVAL(inhdr
, SMB2_HDR_OPCODE
);
1113 mid
= BVAL(inhdr
, SMB2_HDR_MESSAGE_ID
);
1114 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1115 smb2_opcode_name(opcode
),
1116 (unsigned long long)mid
));
1118 allowed_flags
= SMB2_HDR_FLAG_CHAINED
|
1119 SMB2_HDR_FLAG_SIGNED
|
1121 if (opcode
== SMB2_OP_CANCEL
) {
1122 allowed_flags
|= SMB2_HDR_FLAG_ASYNC
;
1124 if ((flags
& ~allowed_flags
) != 0) {
1125 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1129 * Check if the client provided a valid session id,
1130 * if so smbd_smb2_request_check_session() calls
1131 * set_current_user_info().
1133 * As some command don't require a valid session id
1134 * we defer the check of the session_status
1136 session_status
= smbd_smb2_request_check_session(req
);
1138 req
->do_signing
= false;
1139 if (flags
& SMB2_HDR_FLAG_SIGNED
) {
1140 if (!NT_STATUS_IS_OK(session_status
)) {
1141 return smbd_smb2_request_error(req
, session_status
);
1144 req
->do_signing
= true;
1145 status
= smb2_signing_check_pdu(req
->session
->session_key
,
1146 &req
->in
.vector
[i
], 3);
1147 if (!NT_STATUS_IS_OK(status
)) {
1148 return smbd_smb2_request_error(req
, status
);
1150 } else if (req
->session
&& req
->session
->do_signing
) {
1151 return smbd_smb2_request_error(req
, NT_STATUS_ACCESS_DENIED
);
1154 if (flags
& SMB2_HDR_FLAG_CHAINED
) {
1156 * This check is mostly for giving the correct error code
1157 * for compounded requests.
1159 * TODO: we may need to move this after the session
1162 if (!NT_STATUS_IS_OK(req
->next_status
)) {
1163 return smbd_smb2_request_error(req
, req
->next_status
);
1166 req
->compat_chain_fsp
= NULL
;
1170 case SMB2_OP_NEGPROT
:
1171 /* This call needs to be run as root */
1172 change_to_root_user();
1175 START_PROFILE(smb2_negprot
);
1176 return_value
= smbd_smb2_request_process_negprot(req
);
1177 END_PROFILE(smb2_negprot
);
1181 case SMB2_OP_SESSSETUP
:
1182 /* This call needs to be run as root */
1183 change_to_root_user();
1186 START_PROFILE(smb2_sesssetup
);
1187 return_value
= smbd_smb2_request_process_sesssetup(req
);
1188 END_PROFILE(smb2_sesssetup
);
1192 case SMB2_OP_LOGOFF
:
1193 if (!NT_STATUS_IS_OK(session_status
)) {
1194 return_value
= smbd_smb2_request_error(req
, session_status
);
1198 /* This call needs to be run as root */
1199 change_to_root_user();
1202 START_PROFILE(smb2_logoff
);
1203 return_value
= smbd_smb2_request_process_logoff(req
);
1204 END_PROFILE(smb2_logoff
);
1209 if (!NT_STATUS_IS_OK(session_status
)) {
1210 return_value
= smbd_smb2_request_error(req
, session_status
);
1215 * This call needs to be run as root.
1217 * smbd_smb2_request_process_tcon()
1218 * calls make_connection_snum(), which will call
1219 * change_to_user(), when needed.
1221 change_to_root_user();
1224 START_PROFILE(smb2_tcon
);
1225 return_value
= smbd_smb2_request_process_tcon(req
);
1226 END_PROFILE(smb2_tcon
);
1231 if (!NT_STATUS_IS_OK(session_status
)) {
1232 return_value
= smbd_smb2_request_error(req
, session_status
);
1236 * This call needs to be run as user.
1238 * smbd_smb2_request_check_tcon()
1239 * calls change_to_user() on success.
1241 status
= smbd_smb2_request_check_tcon(req
);
1242 if (!NT_STATUS_IS_OK(status
)) {
1243 return_value
= smbd_smb2_request_error(req
, status
);
1246 /* This call needs to be run as root */
1247 change_to_root_user();
1251 START_PROFILE(smb2_tdis
);
1252 return_value
= smbd_smb2_request_process_tdis(req
);
1253 END_PROFILE(smb2_tdis
);
1257 case SMB2_OP_CREATE
:
1258 if (!NT_STATUS_IS_OK(session_status
)) {
1259 return_value
= smbd_smb2_request_error(req
, session_status
);
1263 * This call needs to be run as user.
1265 * smbd_smb2_request_check_tcon()
1266 * calls change_to_user() on success.
1268 status
= smbd_smb2_request_check_tcon(req
);
1269 if (!NT_STATUS_IS_OK(status
)) {
1270 return_value
= smbd_smb2_request_error(req
, status
);
1275 START_PROFILE(smb2_create
);
1276 return_value
= smbd_smb2_request_process_create(req
);
1277 END_PROFILE(smb2_create
);
1282 if (!NT_STATUS_IS_OK(session_status
)) {
1283 return_value
= smbd_smb2_request_error(req
, session_status
);
1287 * This call needs to be run as user.
1289 * smbd_smb2_request_check_tcon()
1290 * calls change_to_user() on success.
1292 status
= smbd_smb2_request_check_tcon(req
);
1293 if (!NT_STATUS_IS_OK(status
)) {
1294 return_value
= smbd_smb2_request_error(req
, status
);
1299 START_PROFILE(smb2_close
);
1300 return_value
= smbd_smb2_request_process_close(req
);
1301 END_PROFILE(smb2_close
);
1306 if (!NT_STATUS_IS_OK(session_status
)) {
1307 return_value
= smbd_smb2_request_error(req
, session_status
);
1311 * This call needs to be run as user.
1313 * smbd_smb2_request_check_tcon()
1314 * calls change_to_user() on success.
1316 status
= smbd_smb2_request_check_tcon(req
);
1317 if (!NT_STATUS_IS_OK(status
)) {
1318 return_value
= smbd_smb2_request_error(req
, status
);
1323 START_PROFILE(smb2_flush
);
1324 return_value
= smbd_smb2_request_process_flush(req
);
1325 END_PROFILE(smb2_flush
);
1330 if (!NT_STATUS_IS_OK(session_status
)) {
1331 return_value
= smbd_smb2_request_error(req
, session_status
);
1335 * This call needs to be run as user.
1337 * smbd_smb2_request_check_tcon()
1338 * calls change_to_user() on success.
1340 status
= smbd_smb2_request_check_tcon(req
);
1341 if (!NT_STATUS_IS_OK(status
)) {
1342 return_value
= smbd_smb2_request_error(req
, status
);
1347 START_PROFILE(smb2_read
);
1348 return_value
= smbd_smb2_request_process_read(req
);
1349 END_PROFILE(smb2_read
);
1354 if (!NT_STATUS_IS_OK(session_status
)) {
1355 return_value
= smbd_smb2_request_error(req
, session_status
);
1359 * This call needs to be run as user.
1361 * smbd_smb2_request_check_tcon()
1362 * calls change_to_user() on success.
1364 status
= smbd_smb2_request_check_tcon(req
);
1365 if (!NT_STATUS_IS_OK(status
)) {
1366 return_value
= smbd_smb2_request_error(req
, status
);
1371 START_PROFILE(smb2_write
);
1372 return_value
= smbd_smb2_request_process_write(req
);
1373 END_PROFILE(smb2_write
);
1378 if (!NT_STATUS_IS_OK(session_status
)) {
1379 /* Too ugly to live ? JRA. */
1380 if (NT_STATUS_EQUAL(session_status
,NT_STATUS_USER_SESSION_DELETED
)) {
1381 session_status
= NT_STATUS_FILE_CLOSED
;
1383 return_value
= smbd_smb2_request_error(req
, session_status
);
1387 * This call needs to be run as user.
1389 * smbd_smb2_request_check_tcon()
1390 * calls change_to_user() on success.
1392 status
= smbd_smb2_request_check_tcon(req
);
1393 if (!NT_STATUS_IS_OK(status
)) {
1394 /* Too ugly to live ? JRA. */
1395 if (NT_STATUS_EQUAL(status
,NT_STATUS_NETWORK_NAME_DELETED
)) {
1396 status
= NT_STATUS_FILE_CLOSED
;
1398 return_value
= smbd_smb2_request_error(req
, status
);
1403 START_PROFILE(smb2_lock
);
1404 return_value
= smbd_smb2_request_process_lock(req
);
1405 END_PROFILE(smb2_lock
);
1410 if (!NT_STATUS_IS_OK(session_status
)) {
1411 return_value
= smbd_smb2_request_error(req
, session_status
);
1415 * This call needs to be run as user.
1417 * smbd_smb2_request_check_tcon()
1418 * calls change_to_user() on success.
1420 status
= smbd_smb2_request_check_tcon(req
);
1421 if (!NT_STATUS_IS_OK(status
)) {
1422 return_value
= smbd_smb2_request_error(req
, status
);
1427 START_PROFILE(smb2_ioctl
);
1428 return_value
= smbd_smb2_request_process_ioctl(req
);
1429 END_PROFILE(smb2_ioctl
);
1433 case SMB2_OP_CANCEL
:
1435 * This call needs to be run as root
1437 * That is what we also do in the SMB1 case.
1439 change_to_root_user();
1442 START_PROFILE(smb2_cancel
);
1443 return_value
= smbd_smb2_request_process_cancel(req
);
1444 END_PROFILE(smb2_cancel
);
1448 case SMB2_OP_KEEPALIVE
:
1449 /* This call needs to be run as root */
1450 change_to_root_user();
1453 START_PROFILE(smb2_keepalive
);
1454 return_value
= smbd_smb2_request_process_keepalive(req
);
1455 END_PROFILE(smb2_keepalive
);
1460 if (!NT_STATUS_IS_OK(session_status
)) {
1461 return_value
= smbd_smb2_request_error(req
, session_status
);
1465 * This call needs to be run as user.
1467 * smbd_smb2_request_check_tcon()
1468 * calls change_to_user() on success.
1470 status
= smbd_smb2_request_check_tcon(req
);
1471 if (!NT_STATUS_IS_OK(status
)) {
1472 return_value
= smbd_smb2_request_error(req
, status
);
1477 START_PROFILE(smb2_find
);
1478 return_value
= smbd_smb2_request_process_find(req
);
1479 END_PROFILE(smb2_find
);
1483 case SMB2_OP_NOTIFY
:
1484 if (!NT_STATUS_IS_OK(session_status
)) {
1485 return_value
= smbd_smb2_request_error(req
, session_status
);
1489 * This call needs to be run as user.
1491 * smbd_smb2_request_check_tcon()
1492 * calls change_to_user() on success.
1494 status
= smbd_smb2_request_check_tcon(req
);
1495 if (!NT_STATUS_IS_OK(status
)) {
1496 return_value
= smbd_smb2_request_error(req
, status
);
1501 START_PROFILE(smb2_notify
);
1502 return_value
= smbd_smb2_request_process_notify(req
);
1503 END_PROFILE(smb2_notify
);
1507 case SMB2_OP_GETINFO
:
1508 if (!NT_STATUS_IS_OK(session_status
)) {
1509 return_value
= smbd_smb2_request_error(req
, session_status
);
1513 * This call needs to be run as user.
1515 * smbd_smb2_request_check_tcon()
1516 * calls change_to_user() on success.
1518 status
= smbd_smb2_request_check_tcon(req
);
1519 if (!NT_STATUS_IS_OK(status
)) {
1520 return_value
= smbd_smb2_request_error(req
, status
);
1525 START_PROFILE(smb2_getinfo
);
1526 return_value
= smbd_smb2_request_process_getinfo(req
);
1527 END_PROFILE(smb2_getinfo
);
1531 case SMB2_OP_SETINFO
:
1532 if (!NT_STATUS_IS_OK(session_status
)) {
1533 return_value
= smbd_smb2_request_error(req
, session_status
);
1537 * This call needs to be run as user.
1539 * smbd_smb2_request_check_tcon()
1540 * calls change_to_user() on success.
1542 status
= smbd_smb2_request_check_tcon(req
);
1543 if (!NT_STATUS_IS_OK(status
)) {
1544 return_value
= smbd_smb2_request_error(req
, status
);
1549 START_PROFILE(smb2_setinfo
);
1550 return_value
= smbd_smb2_request_process_setinfo(req
);
1551 END_PROFILE(smb2_setinfo
);
1556 if (!NT_STATUS_IS_OK(session_status
)) {
1557 return_value
= smbd_smb2_request_error(req
, session_status
);
1561 * This call needs to be run as user.
1563 * smbd_smb2_request_check_tcon()
1564 * calls change_to_user() on success.
1566 status
= smbd_smb2_request_check_tcon(req
);
1567 if (!NT_STATUS_IS_OK(status
)) {
1568 return_value
= smbd_smb2_request_error(req
, status
);
1573 START_PROFILE(smb2_break
);
1574 return_value
= smbd_smb2_request_process_break(req
);
1575 END_PROFILE(smb2_break
);
1580 return_value
= smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
1583 return return_value
;
1586 static NTSTATUS
smbd_smb2_request_reply(struct smbd_smb2_request
*req
)
1588 struct tevent_req
*subreq
;
1589 int i
= req
->current_idx
;
1593 req
->current_idx
+= 3;
1595 if (req
->current_idx
< req
->out
.vector_count
) {
1597 * We must process the remaining compound
1598 * SMB2 requests before any new incoming SMB2
1599 * requests. This is because incoming SMB2
1600 * requests may include a cancel for a
1601 * compound request we haven't processed
1604 struct tevent_immediate
*im
= tevent_create_immediate(req
);
1606 return NT_STATUS_NO_MEMORY
;
1608 tevent_schedule_immediate(im
,
1609 req
->sconn
->smb2
.event_ctx
,
1610 smbd_smb2_request_dispatch_immediate
,
1612 return NT_STATUS_OK
;
1615 smb2_setup_nbt_length(req
->out
.vector
, req
->out
.vector_count
);
1617 /* Set credit for this operation (zero credits if this
1618 is a final reply for an async operation). */
1619 smb2_set_operation_credit(req
->sconn
,
1620 req
->async
? NULL
: &req
->in
.vector
[i
],
1621 &req
->out
.vector
[i
]);
1623 if (req
->do_signing
) {
1625 status
= smb2_signing_sign_pdu(req
->session
->session_key
,
1626 &req
->out
.vector
[i
], 3);
1627 if (!NT_STATUS_IS_OK(status
)) {
1632 if (DEBUGLEVEL
>= 10) {
1633 dbgtext("smbd_smb2_request_reply: sending...\n");
1634 print_req_vectors(req
);
1637 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1638 if (req
->out
.vector_count
== 4 &&
1639 req
->out
.vector
[3].iov_base
== NULL
&&
1640 req
->out
.vector
[3].iov_len
!= 0) {
1641 /* Dynamic part is NULL. Chop it off,
1642 We're going to send it via sendfile. */
1643 req
->out
.vector_count
-= 1;
1646 subreq
= tstream_writev_queue_send(req
,
1647 req
->sconn
->smb2
.event_ctx
,
1648 req
->sconn
->smb2
.stream
,
1649 req
->sconn
->smb2
.send_queue
,
1651 req
->out
.vector_count
);
1652 if (subreq
== NULL
) {
1653 return NT_STATUS_NO_MEMORY
;
1655 tevent_req_set_callback(subreq
, smbd_smb2_request_writev_done
, req
);
1657 * We're done with this request -
1658 * move it off the "being processed" queue.
1660 DLIST_REMOVE(req
->sconn
->smb2
.requests
, req
);
1662 return NT_STATUS_OK
;
1665 void smbd_smb2_request_dispatch_immediate(struct tevent_context
*ctx
,
1666 struct tevent_immediate
*im
,
1669 struct smbd_smb2_request
*req
= talloc_get_type_abort(private_data
,
1670 struct smbd_smb2_request
);
1671 struct smbd_server_connection
*sconn
= req
->sconn
;
1676 if (DEBUGLEVEL
>= 10) {
1677 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1678 req
->current_idx
, req
->in
.vector_count
));
1679 print_req_vectors(req
);
1682 status
= smbd_smb2_request_dispatch(req
);
1683 if (!NT_STATUS_IS_OK(status
)) {
1684 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1689 static void smbd_smb2_request_writev_done(struct tevent_req
*subreq
)
1691 struct smbd_smb2_request
*req
= tevent_req_callback_data(subreq
,
1692 struct smbd_smb2_request
);
1693 struct smbd_server_connection
*sconn
= req
->sconn
;
1697 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1698 TALLOC_FREE(subreq
);
1701 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
1702 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1703 nt_errstr(status
)));
1704 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1709 NTSTATUS
smbd_smb2_request_done_ex(struct smbd_smb2_request
*req
,
1711 DATA_BLOB body
, DATA_BLOB
*dyn
,
1712 const char *location
)
1715 int i
= req
->current_idx
;
1716 uint32_t next_command_ofs
;
1718 DEBUG(10,("smbd_smb2_request_done_ex: "
1719 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1720 i
, nt_errstr(status
), (unsigned int)body
.length
,
1722 (unsigned int)(dyn
? dyn
->length
: 0),
1725 if (body
.length
< 2) {
1726 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
1729 if ((body
.length
% 2) != 0) {
1730 return smbd_smb2_request_error(req
, NT_STATUS_INTERNAL_ERROR
);
1733 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
1735 next_command_ofs
= IVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
);
1736 SIVAL(outhdr
, SMB2_HDR_STATUS
, NT_STATUS_V(status
));
1738 req
->out
.vector
[i
+1].iov_base
= (void *)body
.data
;
1739 req
->out
.vector
[i
+1].iov_len
= body
.length
;
1742 req
->out
.vector
[i
+2].iov_base
= (void *)dyn
->data
;
1743 req
->out
.vector
[i
+2].iov_len
= dyn
->length
;
1745 req
->out
.vector
[i
+2].iov_base
= NULL
;
1746 req
->out
.vector
[i
+2].iov_len
= 0;
1749 /* see if we need to recalculate the offset to the next response */
1750 if (next_command_ofs
> 0) {
1751 next_command_ofs
= SMB2_HDR_BODY
;
1752 next_command_ofs
+= req
->out
.vector
[i
+1].iov_len
;
1753 next_command_ofs
+= req
->out
.vector
[i
+2].iov_len
;
1756 if ((next_command_ofs
% 8) != 0) {
1757 size_t pad_size
= 8 - (next_command_ofs
% 8);
1758 if (req
->out
.vector
[i
+2].iov_len
== 0) {
1760 * if the dyn buffer is empty
1761 * we can use it to add padding
1765 pad
= talloc_zero_array(req
->out
.vector
,
1768 return smbd_smb2_request_error(req
,
1769 NT_STATUS_NO_MEMORY
);
1772 req
->out
.vector
[i
+2].iov_base
= (void *)pad
;
1773 req
->out
.vector
[i
+2].iov_len
= pad_size
;
1776 * For now we copy the dynamic buffer
1777 * and add the padding to the new buffer
1784 old_size
= req
->out
.vector
[i
+2].iov_len
;
1785 old_dyn
= (uint8_t *)req
->out
.vector
[i
+2].iov_base
;
1787 new_size
= old_size
+ pad_size
;
1788 new_dyn
= talloc_zero_array(req
->out
.vector
,
1790 if (new_dyn
== NULL
) {
1791 return smbd_smb2_request_error(req
,
1792 NT_STATUS_NO_MEMORY
);
1795 memcpy(new_dyn
, old_dyn
, old_size
);
1796 memset(new_dyn
+ old_size
, 0, pad_size
);
1798 req
->out
.vector
[i
+2].iov_base
= (void *)new_dyn
;
1799 req
->out
.vector
[i
+2].iov_len
= new_size
;
1801 next_command_ofs
+= pad_size
;
1804 SIVAL(outhdr
, SMB2_HDR_NEXT_COMMAND
, next_command_ofs
);
1806 return smbd_smb2_request_reply(req
);
1809 NTSTATUS
smbd_smb2_request_error_ex(struct smbd_smb2_request
*req
,
1812 const char *location
)
1815 int i
= req
->current_idx
;
1816 uint8_t *outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
1818 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1819 i
, nt_errstr(status
), info
? " +info" : "",
1822 body
.data
= outhdr
+ SMB2_HDR_BODY
;
1824 SSVAL(body
.data
, 0, 9);
1827 SIVAL(body
.data
, 0x04, info
->length
);
1829 /* Allocated size of req->out.vector[i].iov_base
1830 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
1831 * 1 byte without having to do an alloc.
1833 info
= talloc_zero_array(req
->out
.vector
,
1837 return NT_STATUS_NO_MEMORY
;
1839 info
->data
= ((uint8_t *)outhdr
) +
1840 OUTVEC_ALLOC_SIZE
- 1;
1842 SCVAL(info
->data
, 0, 0);
1846 * if a request fails, all other remaining
1847 * compounded requests should fail too
1849 req
->next_status
= NT_STATUS_INVALID_PARAMETER
;
1851 return smbd_smb2_request_done_ex(req
, status
, body
, info
, __location__
);
1855 struct smbd_smb2_send_oplock_break_state
{
1856 struct smbd_server_connection
*sconn
;
1857 uint8_t buf
[4 + SMB2_HDR_BODY
+ 0x18];
1858 struct iovec vector
;
1861 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
);
1863 NTSTATUS
smbd_smb2_send_oplock_break(struct smbd_server_connection
*sconn
,
1864 uint64_t file_id_persistent
,
1865 uint64_t file_id_volatile
,
1866 uint8_t oplock_level
)
1868 struct smbd_smb2_send_oplock_break_state
*state
;
1869 struct tevent_req
*subreq
;
1873 state
= talloc(sconn
, struct smbd_smb2_send_oplock_break_state
);
1874 if (state
== NULL
) {
1875 return NT_STATUS_NO_MEMORY
;
1877 state
->sconn
= sconn
;
1879 state
->vector
.iov_base
= (void *)state
->buf
;
1880 state
->vector
.iov_len
= sizeof(state
->buf
);
1882 _smb2_setlen(state
->buf
, sizeof(state
->buf
) - 4);
1883 hdr
= state
->buf
+ 4;
1884 body
= hdr
+ SMB2_HDR_BODY
;
1886 SIVAL(hdr
, 0, SMB2_MAGIC
);
1887 SSVAL(hdr
, SMB2_HDR_LENGTH
, SMB2_HDR_BODY
);
1888 SSVAL(hdr
, SMB2_HDR_EPOCH
, 0);
1889 SIVAL(hdr
, SMB2_HDR_STATUS
, 0);
1890 SSVAL(hdr
, SMB2_HDR_OPCODE
, SMB2_OP_BREAK
);
1891 SSVAL(hdr
, SMB2_HDR_CREDIT
, 0);
1892 SIVAL(hdr
, SMB2_HDR_FLAGS
, SMB2_HDR_FLAG_REDIRECT
);
1893 SIVAL(hdr
, SMB2_HDR_NEXT_COMMAND
, 0);
1894 SBVAL(hdr
, SMB2_HDR_MESSAGE_ID
, UINT64_MAX
);
1895 SIVAL(hdr
, SMB2_HDR_PID
, 0);
1896 SIVAL(hdr
, SMB2_HDR_TID
, 0);
1897 SBVAL(hdr
, SMB2_HDR_SESSION_ID
, 0);
1898 memset(hdr
+SMB2_HDR_SIGNATURE
, 0, 16);
1900 SSVAL(body
, 0x00, 0x18);
1902 SCVAL(body
, 0x02, oplock_level
);
1903 SCVAL(body
, 0x03, 0); /* reserved */
1904 SIVAL(body
, 0x04, 0); /* reserved */
1905 SBVAL(body
, 0x08, file_id_persistent
);
1906 SBVAL(body
, 0x10, file_id_volatile
);
1908 subreq
= tstream_writev_queue_send(state
,
1909 sconn
->smb2
.event_ctx
,
1911 sconn
->smb2
.send_queue
,
1913 if (subreq
== NULL
) {
1914 return NT_STATUS_NO_MEMORY
;
1916 tevent_req_set_callback(subreq
,
1917 smbd_smb2_oplock_break_writev_done
,
1920 return NT_STATUS_OK
;
1923 static void smbd_smb2_oplock_break_writev_done(struct tevent_req
*subreq
)
1925 struct smbd_smb2_send_oplock_break_state
*state
=
1926 tevent_req_callback_data(subreq
,
1927 struct smbd_smb2_send_oplock_break_state
);
1928 struct smbd_server_connection
*sconn
= state
->sconn
;
1932 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1933 TALLOC_FREE(subreq
);
1935 NTSTATUS status
= map_nt_error_from_unix(sys_errno
);
1936 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
1943 struct smbd_smb2_request_read_state
{
1945 bool asked_for_header
;
1946 struct smbd_smb2_request
*smb2_req
;
1949 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
1951 TALLOC_CTX
*mem_ctx
,
1952 struct iovec
**_vector
,
1954 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
);
1956 static struct tevent_req
*smbd_smb2_request_read_send(TALLOC_CTX
*mem_ctx
,
1957 struct tevent_context
*ev
,
1958 struct smbd_server_connection
*sconn
)
1960 struct tevent_req
*req
;
1961 struct smbd_smb2_request_read_state
*state
;
1962 struct tevent_req
*subreq
;
1964 req
= tevent_req_create(mem_ctx
, &state
,
1965 struct smbd_smb2_request_read_state
);
1970 state
->asked_for_header
= false;
1972 state
->smb2_req
= smbd_smb2_request_allocate(state
);
1973 if (tevent_req_nomem(state
->smb2_req
, req
)) {
1974 return tevent_req_post(req
, ev
);
1976 state
->smb2_req
->sconn
= sconn
;
1978 subreq
= tstream_readv_pdu_queue_send(state
, ev
, sconn
->smb2
.stream
,
1979 sconn
->smb2
.recv_queue
,
1980 smbd_smb2_request_next_vector
,
1982 if (tevent_req_nomem(subreq
, req
)) {
1983 return tevent_req_post(req
, ev
);
1985 tevent_req_set_callback(subreq
, smbd_smb2_request_read_done
, req
);
1990 static int smbd_smb2_request_next_vector(struct tstream_context
*stream
,
1992 TALLOC_CTX
*mem_ctx
,
1993 struct iovec
**_vector
,
1996 struct smbd_smb2_request_read_state
*state
=
1997 talloc_get_type_abort(private_data
,
1998 struct smbd_smb2_request_read_state
);
1999 struct smbd_smb2_request
*req
= state
->smb2_req
;
2000 struct iovec
*vector
;
2001 int idx
= req
->in
.vector_count
;
2003 uint8_t *buf
= NULL
;
2005 if (req
->in
.vector_count
== 0) {
2007 * first we need to get the NBT header
2009 req
->in
.vector
= talloc_array(req
, struct iovec
,
2010 req
->in
.vector_count
+ 1);
2011 if (req
->in
.vector
== NULL
) {
2014 req
->in
.vector_count
+= 1;
2016 req
->in
.vector
[idx
].iov_base
= (void *)req
->in
.nbt_hdr
;
2017 req
->in
.vector
[idx
].iov_len
= 4;
2019 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2020 if (vector
== NULL
) {
2024 vector
[0] = req
->in
.vector
[idx
];
2031 if (req
->in
.vector_count
== 1) {
2033 * Now we analyze the NBT header
2035 state
->missing
= smb2_len(req
->in
.vector
[0].iov_base
);
2037 if (state
->missing
== 0) {
2038 /* if there're no remaining bytes, we're done */
2044 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2046 req
->in
.vector_count
+ 1);
2047 if (req
->in
.vector
== NULL
) {
2050 req
->in
.vector_count
+= 1;
2052 if (CVAL(req
->in
.vector
[0].iov_base
, 0) != 0) {
2054 * it's a special NBT message,
2055 * so get all remaining bytes
2057 len
= state
->missing
;
2058 } else if (state
->missing
< (SMB2_HDR_BODY
+ 2)) {
2060 * it's an invalid message, just read what we can get
2061 * and let the caller handle the error
2063 len
= state
->missing
;
2066 * We assume it's a SMB2 request,
2067 * and we first get the header and the
2068 * first 2 bytes (the struct size) of the body
2070 len
= SMB2_HDR_BODY
+ 2;
2072 state
->asked_for_header
= true;
2075 state
->missing
-= len
;
2077 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2082 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2083 req
->in
.vector
[idx
].iov_len
= len
;
2085 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2086 if (vector
== NULL
) {
2090 vector
[0] = req
->in
.vector
[idx
];
2097 if (state
->missing
== 0) {
2098 /* if there're no remaining bytes, we're done */
2104 if (state
->asked_for_header
) {
2107 size_t next_command_ofs
;
2112 bool invalid
= false;
2114 state
->asked_for_header
= false;
2117 * We got the SMB2 header and the first 2 bytes
2118 * of the body. We fix the size to just the header
2119 * and manually copy the 2 first bytes to the body section
2121 req
->in
.vector
[idx
-1].iov_len
= SMB2_HDR_BODY
;
2122 hdr
= (const uint8_t *)req
->in
.vector
[idx
-1].iov_base
;
2124 /* allocate vectors for body and dynamic areas */
2125 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2127 req
->in
.vector_count
+ 2);
2128 if (req
->in
.vector
== NULL
) {
2131 req
->in
.vector_count
+= 2;
2133 full_size
= state
->missing
+ SMB2_HDR_BODY
+ 2;
2134 next_command_ofs
= IVAL(hdr
, SMB2_HDR_NEXT_COMMAND
);
2135 body_size
= SVAL(hdr
, SMB2_HDR_BODY
);
2137 if (next_command_ofs
!= 0) {
2138 if (next_command_ofs
< (SMB2_HDR_BODY
+ 2)) {
2140 * this is invalid, just return a zero
2141 * body and let the caller deal with the error
2144 } else if (next_command_ofs
> full_size
) {
2146 * this is invalid, just return a zero
2147 * body and let the caller deal with the error
2151 full_size
= next_command_ofs
;
2156 if (body_size
< 2) {
2158 * this is invalid, just return a zero
2159 * body and let the caller deal with the error
2164 if ((body_size
% 2) != 0) {
2168 if (body_size
> (full_size
- SMB2_HDR_BODY
)) {
2170 * this is invalid, just return a zero
2171 * body and let the caller deal with the error
2178 /* the caller should check this */
2182 dyn_size
= full_size
- (SMB2_HDR_BODY
+ body_size
);
2184 state
->missing
-= (body_size
- 2) + dyn_size
;
2186 body
= talloc_array(req
->in
.vector
, uint8_t, body_size
);
2191 dyn
= talloc_array(req
->in
.vector
, uint8_t, dyn_size
);
2196 req
->in
.vector
[idx
].iov_base
= (void *)body
;
2197 req
->in
.vector
[idx
].iov_len
= body_size
;
2198 req
->in
.vector
[idx
+1].iov_base
= (void *)dyn
;
2199 req
->in
.vector
[idx
+1].iov_len
= dyn_size
;
2201 vector
= talloc_array(mem_ctx
, struct iovec
, 2);
2202 if (vector
== NULL
) {
2207 * the first 2 bytes of the body were already fetched
2208 * together with the header
2210 memcpy(body
, hdr
+ SMB2_HDR_BODY
, 2);
2211 vector
[0].iov_base
= body
+ 2;
2212 vector
[0].iov_len
= body_size
- 2;
2214 vector
[1] = req
->in
.vector
[idx
+1];
2222 * when we endup here, we're looking for a new SMB2 request
2223 * next. And we ask for its header and the first 2 bytes of
2224 * the body (like we did for the first SMB2 request).
2227 req
->in
.vector
= talloc_realloc(req
, req
->in
.vector
,
2229 req
->in
.vector_count
+ 1);
2230 if (req
->in
.vector
== NULL
) {
2233 req
->in
.vector_count
+= 1;
2236 * We assume it's a SMB2 request,
2237 * and we first get the header and the
2238 * first 2 bytes (the struct size) of the body
2240 len
= SMB2_HDR_BODY
+ 2;
2242 if (len
> state
->missing
) {
2243 /* let the caller handle the error */
2244 len
= state
->missing
;
2247 state
->missing
-= len
;
2248 state
->asked_for_header
= true;
2250 buf
= talloc_array(req
->in
.vector
, uint8_t, len
);
2255 req
->in
.vector
[idx
].iov_base
= (void *)buf
;
2256 req
->in
.vector
[idx
].iov_len
= len
;
2258 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
2259 if (vector
== NULL
) {
2263 vector
[0] = req
->in
.vector
[idx
];
2270 static void smbd_smb2_request_read_done(struct tevent_req
*subreq
)
2272 struct tevent_req
*req
=
2273 tevent_req_callback_data(subreq
,
2279 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
2281 status
= map_nt_error_from_unix(sys_errno
);
2282 tevent_req_nterror(req
, status
);
2286 tevent_req_done(req
);
2289 static NTSTATUS
smbd_smb2_request_read_recv(struct tevent_req
*req
,
2290 TALLOC_CTX
*mem_ctx
,
2291 struct smbd_smb2_request
**_smb2_req
)
2293 struct smbd_smb2_request_read_state
*state
=
2294 tevent_req_data(req
,
2295 struct smbd_smb2_request_read_state
);
2298 if (tevent_req_is_nterror(req
, &status
)) {
2299 tevent_req_received(req
);
2303 talloc_steal(mem_ctx
, state
->smb2_req
->mem_pool
);
2304 *_smb2_req
= state
->smb2_req
;
2305 tevent_req_received(req
);
2306 return NT_STATUS_OK
;
2309 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
);
2311 void smbd_smb2_first_negprot(struct smbd_server_connection
*sconn
,
2312 const uint8_t *inbuf
, size_t size
)
2315 struct smbd_smb2_request
*req
= NULL
;
2316 struct tevent_req
*subreq
;
2318 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2319 (unsigned int)size
));
2321 status
= smbd_initialize_smb2(sconn
);
2322 if (!NT_STATUS_IS_OK(status
)) {
2323 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2327 status
= smbd_smb2_request_create(sconn
, inbuf
, size
, &req
);
2328 if (!NT_STATUS_IS_OK(status
)) {
2329 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2333 status
= smbd_smb2_request_setup_out(req
);
2334 if (!NT_STATUS_IS_OK(status
)) {
2335 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2339 status
= smbd_smb2_request_dispatch(req
);
2340 if (!NT_STATUS_IS_OK(status
)) {
2341 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2345 /* ask for the next request */
2346 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->smb2
.event_ctx
, sconn
);
2347 if (subreq
== NULL
) {
2348 smbd_server_connection_terminate(sconn
, "no memory for reading");
2351 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);
2353 sconn
->num_requests
++;
2356 static void smbd_smb2_request_incoming(struct tevent_req
*subreq
)
2358 struct smbd_server_connection
*sconn
= tevent_req_callback_data(subreq
,
2359 struct smbd_server_connection
);
2361 struct smbd_smb2_request
*req
= NULL
;
2363 status
= smbd_smb2_request_read_recv(subreq
, sconn
, &req
);
2364 TALLOC_FREE(subreq
);
2365 if (!NT_STATUS_IS_OK(status
)) {
2366 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2367 nt_errstr(status
)));
2368 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2372 if (req
->in
.nbt_hdr
[0] != 0x00) {
2373 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2374 req
->in
.nbt_hdr
[0]));
2379 req
->current_idx
= 1;
2381 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2382 req
->current_idx
, req
->in
.vector_count
));
2384 status
= smbd_smb2_request_validate(req
);
2385 if (!NT_STATUS_IS_OK(status
)) {
2386 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2390 status
= smbd_smb2_request_setup_out(req
);
2391 if (!NT_STATUS_IS_OK(status
)) {
2392 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2396 status
= smbd_smb2_request_dispatch(req
);
2397 if (!NT_STATUS_IS_OK(status
)) {
2398 smbd_server_connection_terminate(sconn
, nt_errstr(status
));
2403 /* ask for the next request (this constructs the main loop) */
2404 subreq
= smbd_smb2_request_read_send(sconn
, sconn
->smb2
.event_ctx
, sconn
);
2405 if (subreq
== NULL
) {
2406 smbd_server_connection_terminate(sconn
, "no memory for reading");
2409 tevent_req_set_callback(subreq
, smbd_smb2_request_incoming
, sconn
);
2411 sconn
->num_requests
++;
2413 /* The timeout_processing function isn't run nearly
2414 often enough to implement 'max log size' without
2415 overrunning the size of the file by many megabytes.
2416 This is especially true if we are running at debug
2417 level 10. Checking every 50 SMB2s is a nice
2418 tradeoff of performance vs log file size overrun. */
2420 if ((sconn
->num_requests
% 50) == 0 &&
2421 need_to_check_log_size()) {
2422 change_to_root_user();