Fix bug #8293 - SMB2 doesn't rotate the log files often enough.
[Samba/gebeck_regimport.git] / source3 / smbd / smb2_server.c
blob58825721624e4a401272c01bb40fdb643f2ae99d
1 /*
2 Unix SMB/CIFS implementation.
3 Core SMB2 server
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/>.
22 #include "includes.h"
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[] = {
33 "SMB2_NEGPROT",
34 "SMB2_SESSSETUP",
35 "SMB2_LOGOFF",
36 "SMB2_TCON",
37 "SMB2_TDIS",
38 "SMB2_CREATE",
39 "SMB2_CLOSE",
40 "SMB2_FLUSH",
41 "SMB2_READ",
42 "SMB2_WRITE",
43 "SMB2_LOCK",
44 "SMB2_IOCTL",
45 "SMB2_CANCEL",
46 "SMB2_KEEPALIVE",
47 "SMB2_FIND",
48 "SMB2_NOTIFY",
49 "SMB2_GETINFO",
50 "SMB2_SETINFO",
51 "SMB2_BREAK"
54 const char *smb2_opcode_name(uint16_t opcode)
56 if (opcode > 0x12) {
57 return "Bad SMB2 opcode";
59 return smb2_names[opcode];
62 static void print_req_vectors(struct smbd_smb2_request *req)
64 int i;
66 for (i = 0; i < req->in.vector_count; i++) {
67 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
68 (unsigned int)i,
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",
73 (unsigned int)i,
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)) {
81 return false;
84 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
85 return false;
88 return true;
91 static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
93 NTSTATUS status;
94 int ret;
96 TALLOC_FREE(sconn->smb1.fde);
98 sconn->smb2.event_ctx = server_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);
127 if (ret == -1) {
128 status = map_nt_error_from_unix(errno);
129 return status;
132 /* Ensure child is set to non-blocking mode */
133 set_blocking(sconn->sock, false);
134 return NT_STATUS_OK;
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; \
140 buf[0] = 0; \
141 buf[1] = ((len)&0xFF0000)>>16; \
142 buf[2] = ((len)&0xFF00)>>8; \
143 buf[3] = (len)&0xFF; \
144 } while (0)
146 static void smb2_setup_nbt_length(struct iovec *vector, int count)
148 size_t len = 0;
149 int i;
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)
160 if (*req) {
161 (*req)->parent = NULL;
162 (*req)->mem_pool = NULL;
165 return 0;
168 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
170 if (req->parent) {
171 *req->parent = NULL;
172 talloc_free(req->mem_pool);
175 return 0;
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;
184 #if 0
185 /* Enable this to find subtle valgrind errors. */
186 mem_pool = talloc_init("smbd_smb2_request_allocate");
187 #else
188 mem_pool = talloc_pool(mem_ctx, 8192);
189 #endif
190 if (mem_pool == NULL) {
191 return NULL;
194 parent = talloc(mem_pool, struct smbd_smb2_request *);
195 if (parent == NULL) {
196 talloc_free(mem_pool);
197 return NULL;
200 req = talloc_zero(parent, struct smbd_smb2_request);
201 if (req == NULL) {
202 talloc_free(mem_pool);
203 return NULL;
205 *parent = req;
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);
212 return req;
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;
222 off_t ofs = 0;
223 uint16_t cmd;
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;
231 inhdr = inbuf + 4;
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",
236 protocol_version));
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",
243 cmd));
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",
250 next_command_ofs));
251 return NT_STATUS_INVALID_PARAMETER;
254 req = smbd_smb2_request_allocate(sconn);
255 if (req == NULL) {
256 return NT_STATUS_NO_MEMORY;
258 req->sconn = sconn;
260 talloc_steal(req, inbuf);
262 req->in.vector = talloc_array(req, struct iovec, 4);
263 if (req->in.vector == NULL) {
264 TALLOC_FREE(req);
265 return NT_STATUS_NO_MEMORY;
267 req->in.vector_count = 4;
269 memcpy(req->in.nbt_hdr, inbuf, 4);
271 ofs = 0;
272 req->in.vector[0].iov_base = discard_const_p(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 = discard_const_p(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 = discard_const_p(void, (inbuf + ofs));
281 req->in.vector[2].iov_len = SVAL(inbuf, ofs) & 0xFFFE;
282 ofs += req->in.vector[2].iov_len;
284 if (ofs > size) {
285 return NT_STATUS_INVALID_PARAMETER;
288 req->in.vector[3].iov_base = discard_const_p(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;
294 *_req = req;
295 return NT_STATUS_OK;
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. */
308 return true;
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 ));
319 return false;
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,
333 bitmap_offset));
334 return false;
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
340 already seen. */
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),
345 bitmap_offset ));
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);
353 return true;
356 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
358 int count;
359 int idx;
360 bool compound_related = false;
362 count = req->in.vector_count;
364 if (count < 4) {
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;
371 uint32_t flags;
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);
393 if (idx == 1) {
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;
400 return NT_STATUS_OK;
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) {
411 #if 0
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) {
422 req->next_status =
423 NT_STATUS_INVALID_PARAMETER;
424 return NT_STATUS_OK;
426 } else {
427 if (compound_related) {
428 req->next_status =
429 NT_STATUS_INVALID_PARAMETER;
430 return NT_STATUS_OK;
433 #endif
437 return NT_STATUS_OK;
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 /* Remember what we gave out. */
456 credits_granted = MIN(credits_requested, (sconn->smb2.max_credits -
457 sconn->smb2.credits_granted));
459 if (credits_granted == 0 && sconn->smb2.credits_granted == 0) {
460 /* First negprot packet, or ensure the client credits can
461 never drop to zero. */
462 credits_granted = 1;
465 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
466 sconn->smb2.credits_granted += credits_granted;
468 DEBUG(10,("smb2_set_operation_credit: requested %u, "
469 "granted %u, total granted %u\n",
470 (unsigned int)credits_requested,
471 (unsigned int)credits_granted,
472 (unsigned int)sconn->smb2.credits_granted ));
475 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
476 struct smbd_smb2_request *outreq)
478 int count, idx;
480 count = outreq->out.vector_count;
482 for (idx=1; idx < count; idx += 3) {
483 smb2_set_operation_credit(outreq->sconn,
484 &inreq->in.vector[idx],
485 &outreq->out.vector[idx]);
489 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
491 struct iovec *vector;
492 int count;
493 int idx;
495 count = req->in.vector_count;
496 vector = talloc_zero_array(req, struct iovec, count);
497 if (vector == NULL) {
498 return NT_STATUS_NO_MEMORY;
501 vector[0].iov_base = req->out.nbt_hdr;
502 vector[0].iov_len = 4;
503 SIVAL(req->out.nbt_hdr, 0, 0);
505 for (idx=1; idx < count; idx += 3) {
506 const uint8_t *inhdr = NULL;
507 uint32_t in_flags;
508 uint8_t *outhdr = NULL;
509 uint8_t *outbody = NULL;
510 uint32_t next_command_ofs = 0;
511 struct iovec *current = &vector[idx];
513 if ((idx + 3) < count) {
514 /* we have a next command -
515 * setup for the error case. */
516 next_command_ofs = SMB2_HDR_BODY + 9;
519 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
520 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
522 outhdr = talloc_zero_array(vector, uint8_t,
523 OUTVEC_ALLOC_SIZE);
524 if (outhdr == NULL) {
525 return NT_STATUS_NO_MEMORY;
528 outbody = outhdr + SMB2_HDR_BODY;
530 current[0].iov_base = (void *)outhdr;
531 current[0].iov_len = SMB2_HDR_BODY;
533 current[1].iov_base = (void *)outbody;
534 current[1].iov_len = 8;
536 current[2].iov_base = NULL;
537 current[2].iov_len = 0;
539 /* setup the SMB2 header */
540 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
541 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
542 SSVAL(outhdr, SMB2_HDR_EPOCH, 0);
543 SIVAL(outhdr, SMB2_HDR_STATUS,
544 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
545 SSVAL(outhdr, SMB2_HDR_OPCODE,
546 SVAL(inhdr, SMB2_HDR_OPCODE));
547 SIVAL(outhdr, SMB2_HDR_FLAGS,
548 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
549 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
550 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
551 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
552 SIVAL(outhdr, SMB2_HDR_PID,
553 IVAL(inhdr, SMB2_HDR_PID));
554 SIVAL(outhdr, SMB2_HDR_TID,
555 IVAL(inhdr, SMB2_HDR_TID));
556 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
557 BVAL(inhdr, SMB2_HDR_SESSION_ID));
558 memset(outhdr + SMB2_HDR_SIGNATURE, 0, 16);
560 /* setup error body header */
561 SSVAL(outbody, 0x00, 0x08 + 1);
562 SSVAL(outbody, 0x02, 0);
563 SIVAL(outbody, 0x04, 0);
566 req->out.vector = vector;
567 req->out.vector_count = count;
569 /* setup the length of the NBT packet */
570 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
572 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
574 return NT_STATUS_OK;
577 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
578 const char *reason,
579 const char *location)
581 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
582 reason, location));
583 exit_server_cleanly(reason);
586 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
587 struct iovec *outvec,
588 const struct iovec *srcvec)
590 /* vec[0] is always boilerplate and must
591 * be allocated with size OUTVEC_ALLOC_SIZE. */
593 outvec[0].iov_base = talloc_memdup(ctx,
594 srcvec[0].iov_base,
595 OUTVEC_ALLOC_SIZE);
596 if (!outvec[0].iov_base) {
597 return false;
599 outvec[0].iov_len = SMB2_HDR_BODY;
602 * If this is a "standard" vec[1] of length 8,
603 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
604 * then duplicate this. Else use talloc_memdup().
607 if (srcvec[1].iov_len == 8 &&
608 srcvec[1].iov_base ==
609 ((uint8_t *)srcvec[0].iov_base) +
610 SMB2_HDR_BODY) {
611 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
612 SMB2_HDR_BODY;
613 outvec[1].iov_len = 8;
614 } else {
615 outvec[1].iov_base = talloc_memdup(ctx,
616 srcvec[1].iov_base,
617 srcvec[1].iov_len);
618 if (!outvec[1].iov_base) {
619 return false;
621 outvec[1].iov_len = srcvec[1].iov_len;
625 * If this is a "standard" vec[2] of length 1,
626 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
627 * then duplicate this. Else use talloc_memdup().
630 if (srcvec[2].iov_base &&
631 srcvec[2].iov_len) {
632 if (srcvec[2].iov_base ==
633 ((uint8_t *)srcvec[0].iov_base) +
634 (OUTVEC_ALLOC_SIZE - 1) &&
635 srcvec[2].iov_len == 1) {
636 /* Common SMB2 error packet case. */
637 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
638 (OUTVEC_ALLOC_SIZE - 1);
639 } else {
640 outvec[2].iov_base = talloc_memdup(ctx,
641 srcvec[2].iov_base,
642 srcvec[2].iov_len);
643 if (!outvec[2].iov_base) {
644 return false;
647 outvec[2].iov_len = srcvec[2].iov_len;
648 } else {
649 outvec[2].iov_base = NULL;
650 outvec[2].iov_len = 0;
652 return true;
655 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
657 struct smbd_smb2_request *newreq = NULL;
658 struct iovec *outvec = NULL;
659 int count = req->out.vector_count;
660 int i;
662 newreq = smbd_smb2_request_allocate(req->sconn);
663 if (!newreq) {
664 return NULL;
667 newreq->sconn = req->sconn;
668 newreq->session = req->session;
669 newreq->do_signing = req->do_signing;
670 newreq->current_idx = req->current_idx;
671 newreq->async = false;
672 newreq->cancelled = false;
673 /* Note we are leaving:
674 ->tcon
675 ->smb1req
676 ->compat_chain_fsp
677 uninitialized as NULL here as
678 they're not used in the interim
679 response code. JRA. */
681 outvec = talloc_zero_array(newreq, struct iovec, count);
682 if (!outvec) {
683 TALLOC_FREE(newreq);
684 return NULL;
686 newreq->out.vector = outvec;
687 newreq->out.vector_count = count;
689 /* Setup the outvec's identically to req. */
690 outvec[0].iov_base = newreq->out.nbt_hdr;
691 outvec[0].iov_len = 4;
692 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
694 /* Setup the vectors identically to the ones in req. */
695 for (i = 1; i < count; i += 3) {
696 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
697 break;
701 if (i < count) {
702 /* Alloc failed. */
703 TALLOC_FREE(newreq);
704 return NULL;
707 smb2_setup_nbt_length(newreq->out.vector,
708 newreq->out.vector_count);
710 return newreq;
713 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
715 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
717 int i = 0;
718 uint8_t *outhdr = NULL;
719 struct smbd_smb2_request *nreq = NULL;
721 /* Create a new smb2 request we'll use
722 for the interim return. */
723 nreq = dup_smb2_req(req);
724 if (!nreq) {
725 return NT_STATUS_NO_MEMORY;
728 /* Lose the last 3 out vectors. They're the
729 ones we'll be using for the async reply. */
730 nreq->out.vector_count -= 3;
732 smb2_setup_nbt_length(nreq->out.vector,
733 nreq->out.vector_count);
735 /* Step back to the previous reply. */
736 i = nreq->current_idx - 3;
737 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
738 /* And end the chain. */
739 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
741 /* Calculate outgoing credits */
742 smb2_calculate_credits(req, nreq);
744 /* Re-sign if needed. */
745 if (nreq->do_signing) {
746 NTSTATUS status;
747 status = smb2_signing_sign_pdu(nreq->session->session_key,
748 &nreq->out.vector[i], 3);
749 if (!NT_STATUS_IS_OK(status)) {
750 return status;
753 if (DEBUGLEVEL >= 10) {
754 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
755 (unsigned int)nreq->current_idx );
756 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
757 (unsigned int)nreq->out.vector_count );
758 print_req_vectors(nreq);
760 nreq->subreq = tstream_writev_queue_send(nreq,
761 nreq->sconn->smb2.event_ctx,
762 nreq->sconn->smb2.stream,
763 nreq->sconn->smb2.send_queue,
764 nreq->out.vector,
765 nreq->out.vector_count);
767 if (nreq->subreq == NULL) {
768 return NT_STATUS_NO_MEMORY;
771 tevent_req_set_callback(nreq->subreq,
772 smbd_smb2_request_writev_done,
773 nreq);
775 return NT_STATUS_OK;
778 struct smbd_smb2_request_pending_state {
779 struct smbd_server_connection *sconn;
780 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
781 struct iovec vector[3];
784 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
786 struct smbd_smb2_request_pending_state *state =
787 tevent_req_callback_data(subreq,
788 struct smbd_smb2_request_pending_state);
789 struct smbd_server_connection *sconn = state->sconn;
790 int ret;
791 int sys_errno;
793 ret = tstream_writev_queue_recv(subreq, &sys_errno);
794 TALLOC_FREE(subreq);
795 if (ret == -1) {
796 NTSTATUS status = map_nt_error_from_unix(sys_errno);
797 smbd_server_connection_terminate(sconn, nt_errstr(status));
798 return;
801 TALLOC_FREE(state);
804 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
805 struct tevent_req *subreq)
807 NTSTATUS status;
808 struct smbd_smb2_request_pending_state *state = NULL;
809 int i = req->current_idx;
810 uint8_t *reqhdr = NULL;
811 uint8_t *hdr = NULL;
812 uint8_t *body = NULL;
813 uint32_t flags = 0;
814 uint64_t message_id = 0;
815 uint64_t async_id = 0;
816 struct iovec *outvec = NULL;
818 if (!tevent_req_is_in_progress(subreq)) {
819 return NT_STATUS_OK;
822 req->subreq = subreq;
823 subreq = NULL;
825 if (req->async) {
826 /* We're already async. */
827 return NT_STATUS_OK;
830 if (req->in.vector_count > i + 3) {
832 * We're trying to go async in a compound
833 * request chain. This is not allowed.
834 * Cancel the outstanding request.
836 tevent_req_cancel(req->subreq);
837 return smbd_smb2_request_error(req,
838 NT_STATUS_INSUFFICIENT_RESOURCES);
841 if (DEBUGLEVEL >= 10) {
842 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
843 (unsigned int)req->current_idx );
844 print_req_vectors(req);
847 if (req->out.vector_count > 4) {
848 /* This is a compound reply. We
849 * must do an interim response
850 * followed by the async response
851 * to match W2K8R2.
853 status = smb2_send_async_interim_response(req);
854 if (!NT_STATUS_IS_OK(status)) {
855 return status;
859 /* Don't return an intermediate packet on a pipe read/write. */
860 if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
861 return NT_STATUS_OK;
864 reqhdr = (uint8_t *)req->out.vector[i].iov_base;
865 flags = (IVAL(reqhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
866 message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
867 async_id = message_id; /* keep it simple for now... */
870 * What we send is identical to a smbd_smb2_request_error
871 * packet with an error status of STATUS_PENDING. Make use
872 * of this fact sometime when refactoring. JRA.
875 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
876 if (state == NULL) {
877 return NT_STATUS_NO_MEMORY;
879 state->sconn = req->sconn;
881 state->vector[0].iov_base = (void *)state->buf;
882 state->vector[0].iov_len = 4;
884 state->vector[1].iov_base = state->buf + 4;
885 state->vector[1].iov_len = SMB2_HDR_BODY;
887 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
888 state->vector[2].iov_len = 9;
890 smb2_setup_nbt_length(state->vector, 3);
892 hdr = (uint8_t *)state->vector[1].iov_base;
893 body = (uint8_t *)state->vector[2].iov_base;
895 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
896 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
897 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
898 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
899 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(reqhdr, SMB2_HDR_OPCODE));
901 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
902 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
903 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
904 SBVAL(hdr, SMB2_HDR_PID, async_id);
905 SBVAL(hdr, SMB2_HDR_SESSION_ID,
906 BVAL(reqhdr, SMB2_HDR_SESSION_ID));
907 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
909 SSVAL(body, 0x00, 0x08 + 1);
911 SCVAL(body, 0x02, 0);
912 SCVAL(body, 0x03, 0);
913 SIVAL(body, 0x04, 0);
914 /* Match W2K8R2... */
915 SCVAL(body, 0x08, 0x21);
917 /* Ensure we correctly go through crediting. Grant
918 the credits now, and zero credits on the final
919 response. */
920 smb2_set_operation_credit(req->sconn,
921 &req->in.vector[i],
922 &state->vector[1]);
924 if (req->do_signing) {
925 status = smb2_signing_sign_pdu(req->session->session_key,
926 &state->vector[1], 2);
927 if (!NT_STATUS_IS_OK(status)) {
928 return status;
932 subreq = tstream_writev_queue_send(state,
933 req->sconn->smb2.event_ctx,
934 req->sconn->smb2.stream,
935 req->sconn->smb2.send_queue,
936 state->vector,
939 if (subreq == NULL) {
940 return NT_STATUS_NO_MEMORY;
943 tevent_req_set_callback(subreq,
944 smbd_smb2_request_pending_writev_done,
945 state);
947 /* Note we're going async with this request. */
948 req->async = true;
951 * Now manipulate req so that the outstanding async request
952 * is the only one left in the struct smbd_smb2_request.
955 if (req->current_idx == 1) {
956 /* There was only one. */
957 goto out;
960 /* Re-arrange the in.vectors. */
961 req->in.vector[1] = req->in.vector[i];
962 req->in.vector[2] = req->in.vector[i+1];
963 req->in.vector[3] = req->in.vector[i+2];
964 req->in.vector_count = 4;
965 /* Reset the new in size. */
966 smb2_setup_nbt_length(req->in.vector, 4);
968 /* Now recreate the out.vectors. */
969 outvec = talloc_zero_array(req, struct iovec, 4);
970 if (!outvec) {
971 return NT_STATUS_NO_MEMORY;
974 /* 0 is always boilerplate and must
975 * be of size 4 for the length field. */
977 outvec[0].iov_base = req->out.nbt_hdr;
978 outvec[0].iov_len = 4;
979 SIVAL(req->out.nbt_hdr, 0, 0);
981 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
982 return NT_STATUS_NO_MEMORY;
985 TALLOC_FREE(req->out.vector);
987 req->out.vector = outvec;
989 req->current_idx = 1;
990 req->out.vector_count = 4;
992 out:
994 smb2_setup_nbt_length(req->out.vector,
995 req->out.vector_count);
997 /* Ensure our final reply matches the interim one. */
998 reqhdr = (uint8_t *)req->out.vector[1].iov_base;
999 SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1000 SBVAL(reqhdr, SMB2_HDR_PID, async_id);
1003 const uint8_t *inhdr =
1004 (const uint8_t *)req->in.vector[1].iov_base;
1005 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1006 "going async\n",
1007 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1008 (unsigned long long)async_id ));
1010 return NT_STATUS_OK;
1013 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1015 struct smbd_server_connection *sconn = req->sconn;
1016 struct smbd_smb2_request *cur;
1017 const uint8_t *inhdr;
1018 int i = req->current_idx;
1019 uint32_t flags;
1020 uint64_t search_message_id;
1021 uint64_t search_async_id;
1022 uint64_t found_id;
1024 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1026 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1027 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1028 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1031 * we don't need the request anymore
1032 * cancel requests never have a response
1034 DLIST_REMOVE(req->sconn->smb2.requests, req);
1035 TALLOC_FREE(req);
1037 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1038 const uint8_t *outhdr;
1039 uint64_t message_id;
1040 uint64_t async_id;
1042 i = cur->current_idx;
1044 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1046 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1047 async_id = BVAL(outhdr, SMB2_HDR_PID);
1049 if (flags & SMB2_HDR_FLAG_ASYNC) {
1050 if (search_async_id == async_id) {
1051 found_id = async_id;
1052 break;
1054 } else {
1055 if (search_message_id == message_id) {
1056 found_id = message_id;
1057 break;
1062 if (cur && cur->subreq) {
1063 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1064 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1065 "cancel opcode[%s] mid %llu\n",
1066 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1067 (unsigned long long)found_id ));
1068 tevent_req_cancel(cur->subreq);
1071 return NT_STATUS_OK;
1074 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1076 const uint8_t *inhdr;
1077 int i = req->current_idx;
1078 uint16_t opcode;
1079 uint32_t flags;
1080 uint64_t mid;
1081 NTSTATUS status;
1082 NTSTATUS session_status;
1083 uint32_t allowed_flags;
1084 NTSTATUS return_value;
1086 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1088 /* TODO: verify more things */
1090 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1091 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1092 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1093 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1094 smb2_opcode_name(opcode),
1095 (unsigned long long)mid));
1097 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1098 SMB2_HDR_FLAG_SIGNED |
1099 SMB2_HDR_FLAG_DFS;
1100 if (opcode == SMB2_OP_CANCEL) {
1101 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1103 if ((flags & ~allowed_flags) != 0) {
1104 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1107 session_status = smbd_smb2_request_check_session(req);
1109 req->do_signing = false;
1110 if (flags & SMB2_HDR_FLAG_SIGNED) {
1111 if (!NT_STATUS_IS_OK(session_status)) {
1112 return smbd_smb2_request_error(req, session_status);
1115 req->do_signing = true;
1116 status = smb2_signing_check_pdu(req->session->session_key,
1117 &req->in.vector[i], 3);
1118 if (!NT_STATUS_IS_OK(status)) {
1119 return smbd_smb2_request_error(req, status);
1121 } else if (req->session && req->session->do_signing) {
1122 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1125 if (flags & SMB2_HDR_FLAG_CHAINED) {
1127 * This check is mostly for giving the correct error code
1128 * for compounded requests.
1130 * TODO: we may need to move this after the session
1131 * and tcon checks.
1133 if (!NT_STATUS_IS_OK(req->next_status)) {
1134 return smbd_smb2_request_error(req, req->next_status);
1136 } else {
1137 req->compat_chain_fsp = NULL;
1140 switch (opcode) {
1141 case SMB2_OP_NEGPROT:
1142 /* This call needs to be run as root */
1143 change_to_root_user();
1146 START_PROFILE(smb2_negprot);
1147 return_value = smbd_smb2_request_process_negprot(req);
1148 END_PROFILE(smb2_negprot);
1150 break;
1152 case SMB2_OP_SESSSETUP:
1153 /* This call needs to be run as root */
1154 change_to_root_user();
1157 START_PROFILE(smb2_sesssetup);
1158 return_value = smbd_smb2_request_process_sesssetup(req);
1159 END_PROFILE(smb2_sesssetup);
1161 break;
1163 case SMB2_OP_LOGOFF:
1164 if (!NT_STATUS_IS_OK(session_status)) {
1165 return_value = smbd_smb2_request_error(req, session_status);
1166 break;
1169 /* This call needs to be run as root */
1170 change_to_root_user();
1173 START_PROFILE(smb2_logoff);
1174 return_value = smbd_smb2_request_process_logoff(req);
1175 END_PROFILE(smb2_logoff);
1177 break;
1179 case SMB2_OP_TCON:
1180 if (!NT_STATUS_IS_OK(session_status)) {
1181 return_value = smbd_smb2_request_error(req, session_status);
1182 break;
1185 /* This call needs to be run as root */
1186 change_to_root_user();
1189 START_PROFILE(smb2_tcon);
1190 return_value = smbd_smb2_request_process_tcon(req);
1191 END_PROFILE(smb2_tcon);
1193 break;
1195 case SMB2_OP_TDIS:
1196 if (!NT_STATUS_IS_OK(session_status)) {
1197 return_value = smbd_smb2_request_error(req, session_status);
1198 break;
1200 status = smbd_smb2_request_check_tcon(req);
1201 if (!NT_STATUS_IS_OK(status)) {
1202 return_value = smbd_smb2_request_error(req, status);
1203 break;
1205 /* This call needs to be run as root */
1206 change_to_root_user();
1210 START_PROFILE(smb2_tdis);
1211 return_value = smbd_smb2_request_process_tdis(req);
1212 END_PROFILE(smb2_tdis);
1214 break;
1216 case SMB2_OP_CREATE:
1217 if (!NT_STATUS_IS_OK(session_status)) {
1218 return_value = smbd_smb2_request_error(req, session_status);
1219 break;
1221 status = smbd_smb2_request_check_tcon(req);
1222 if (!NT_STATUS_IS_OK(status)) {
1223 return_value = smbd_smb2_request_error(req, status);
1224 break;
1228 START_PROFILE(smb2_create);
1229 return_value = smbd_smb2_request_process_create(req);
1230 END_PROFILE(smb2_create);
1232 break;
1234 case SMB2_OP_CLOSE:
1235 if (!NT_STATUS_IS_OK(session_status)) {
1236 return_value = smbd_smb2_request_error(req, session_status);
1237 break;
1239 status = smbd_smb2_request_check_tcon(req);
1240 if (!NT_STATUS_IS_OK(status)) {
1241 return_value = smbd_smb2_request_error(req, status);
1242 break;
1246 START_PROFILE(smb2_close);
1247 return_value = smbd_smb2_request_process_close(req);
1248 END_PROFILE(smb2_close);
1250 break;
1252 case SMB2_OP_FLUSH:
1253 if (!NT_STATUS_IS_OK(session_status)) {
1254 return_value = smbd_smb2_request_error(req, session_status);
1255 break;
1257 status = smbd_smb2_request_check_tcon(req);
1258 if (!NT_STATUS_IS_OK(status)) {
1259 return_value = smbd_smb2_request_error(req, status);
1260 break;
1264 START_PROFILE(smb2_flush);
1265 return_value = smbd_smb2_request_process_flush(req);
1266 END_PROFILE(smb2_flush);
1268 break;
1270 case SMB2_OP_READ:
1271 if (!NT_STATUS_IS_OK(session_status)) {
1272 return_value = smbd_smb2_request_error(req, session_status);
1273 break;
1275 status = smbd_smb2_request_check_tcon(req);
1276 if (!NT_STATUS_IS_OK(status)) {
1277 return_value = smbd_smb2_request_error(req, status);
1278 break;
1282 START_PROFILE(smb2_read);
1283 return_value = smbd_smb2_request_process_read(req);
1284 END_PROFILE(smb2_read);
1286 break;
1288 case SMB2_OP_WRITE:
1289 if (!NT_STATUS_IS_OK(session_status)) {
1290 return_value = smbd_smb2_request_error(req, session_status);
1291 break;
1293 status = smbd_smb2_request_check_tcon(req);
1294 if (!NT_STATUS_IS_OK(status)) {
1295 return_value = smbd_smb2_request_error(req, status);
1296 break;
1300 START_PROFILE(smb2_write);
1301 return_value = smbd_smb2_request_process_write(req);
1302 END_PROFILE(smb2_write);
1304 break;
1306 case SMB2_OP_LOCK:
1307 if (!NT_STATUS_IS_OK(session_status)) {
1308 /* Too ugly to live ? JRA. */
1309 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1310 session_status = NT_STATUS_FILE_CLOSED;
1312 return_value = smbd_smb2_request_error(req, session_status);
1313 break;
1315 status = smbd_smb2_request_check_tcon(req);
1316 if (!NT_STATUS_IS_OK(status)) {
1317 /* Too ugly to live ? JRA. */
1318 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1319 status = NT_STATUS_FILE_CLOSED;
1321 return_value = smbd_smb2_request_error(req, status);
1322 break;
1326 START_PROFILE(smb2_lock);
1327 return_value = smbd_smb2_request_process_lock(req);
1328 END_PROFILE(smb2_lock);
1330 break;
1332 case SMB2_OP_IOCTL:
1333 if (!NT_STATUS_IS_OK(session_status)) {
1334 return_value = smbd_smb2_request_error(req, session_status);
1335 break;
1337 status = smbd_smb2_request_check_tcon(req);
1338 if (!NT_STATUS_IS_OK(status)) {
1339 return_value = smbd_smb2_request_error(req, status);
1340 break;
1344 START_PROFILE(smb2_ioctl);
1345 return_value = smbd_smb2_request_process_ioctl(req);
1346 END_PROFILE(smb2_ioctl);
1348 break;
1350 case SMB2_OP_CANCEL:
1351 /* This call needs to be run as root */
1352 change_to_root_user();
1355 START_PROFILE(smb2_cancel);
1356 return_value = smbd_smb2_request_process_cancel(req);
1357 END_PROFILE(smb2_cancel);
1359 break;
1361 case SMB2_OP_KEEPALIVE:
1362 /* This call needs to be run as root */
1363 change_to_root_user();
1366 START_PROFILE(smb2_keepalive);
1367 return_value = smbd_smb2_request_process_keepalive(req);
1368 END_PROFILE(smb2_keepalive);
1370 break;
1372 case SMB2_OP_FIND:
1373 if (!NT_STATUS_IS_OK(session_status)) {
1374 return_value = smbd_smb2_request_error(req, session_status);
1375 break;
1377 status = smbd_smb2_request_check_tcon(req);
1378 if (!NT_STATUS_IS_OK(status)) {
1379 return_value = smbd_smb2_request_error(req, status);
1380 break;
1384 START_PROFILE(smb2_find);
1385 return_value = smbd_smb2_request_process_find(req);
1386 END_PROFILE(smb2_find);
1388 break;
1390 case SMB2_OP_NOTIFY:
1391 if (!NT_STATUS_IS_OK(session_status)) {
1392 return_value = smbd_smb2_request_error(req, session_status);
1393 break;
1395 status = smbd_smb2_request_check_tcon(req);
1396 if (!NT_STATUS_IS_OK(status)) {
1397 return_value = smbd_smb2_request_error(req, status);
1398 break;
1402 START_PROFILE(smb2_notify);
1403 return_value = smbd_smb2_request_process_notify(req);
1404 END_PROFILE(smb2_notify);
1406 break;
1408 case SMB2_OP_GETINFO:
1409 if (!NT_STATUS_IS_OK(session_status)) {
1410 return_value = smbd_smb2_request_error(req, session_status);
1411 break;
1413 status = smbd_smb2_request_check_tcon(req);
1414 if (!NT_STATUS_IS_OK(status)) {
1415 return_value = smbd_smb2_request_error(req, status);
1416 break;
1420 START_PROFILE(smb2_getinfo);
1421 return_value = smbd_smb2_request_process_getinfo(req);
1422 END_PROFILE(smb2_getinfo);
1424 break;
1426 case SMB2_OP_SETINFO:
1427 if (!NT_STATUS_IS_OK(session_status)) {
1428 return_value = smbd_smb2_request_error(req, session_status);
1429 break;
1431 status = smbd_smb2_request_check_tcon(req);
1432 if (!NT_STATUS_IS_OK(status)) {
1433 return_value = smbd_smb2_request_error(req, status);
1434 break;
1438 START_PROFILE(smb2_setinfo);
1439 return_value = smbd_smb2_request_process_setinfo(req);
1440 END_PROFILE(smb2_setinfo);
1442 break;
1444 case SMB2_OP_BREAK:
1445 if (!NT_STATUS_IS_OK(session_status)) {
1446 return_value = smbd_smb2_request_error(req, session_status);
1447 break;
1449 status = smbd_smb2_request_check_tcon(req);
1450 if (!NT_STATUS_IS_OK(status)) {
1451 return_value = smbd_smb2_request_error(req, status);
1452 break;
1456 START_PROFILE(smb2_break);
1457 return_value = smbd_smb2_request_process_break(req);
1458 END_PROFILE(smb2_break);
1460 break;
1462 default:
1463 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1464 break;
1466 return return_value;
1469 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1471 struct tevent_req *subreq;
1472 int i = req->current_idx;
1474 req->subreq = NULL;
1476 req->current_idx += 3;
1478 if (req->current_idx < req->out.vector_count) {
1480 * We must process the remaining compound
1481 * SMB2 requests before any new incoming SMB2
1482 * requests. This is because incoming SMB2
1483 * requests may include a cancel for a
1484 * compound request we haven't processed
1485 * yet.
1487 struct tevent_immediate *im = tevent_create_immediate(req);
1488 if (!im) {
1489 return NT_STATUS_NO_MEMORY;
1491 tevent_schedule_immediate(im,
1492 req->sconn->smb2.event_ctx,
1493 smbd_smb2_request_dispatch_immediate,
1494 req);
1495 return NT_STATUS_OK;
1498 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1500 /* Set credit for this operation (zero credits if this
1501 is a final reply for an async operation). */
1502 smb2_set_operation_credit(req->sconn,
1503 req->async ? NULL : &req->in.vector[i],
1504 &req->out.vector[i]);
1506 if (req->do_signing) {
1507 NTSTATUS status;
1508 status = smb2_signing_sign_pdu(req->session->session_key,
1509 &req->out.vector[i], 3);
1510 if (!NT_STATUS_IS_OK(status)) {
1511 return status;
1515 if (DEBUGLEVEL >= 10) {
1516 dbgtext("smbd_smb2_request_reply: sending...\n");
1517 print_req_vectors(req);
1520 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1521 if (req->out.vector_count == 4 &&
1522 req->out.vector[3].iov_base == NULL &&
1523 req->out.vector[3].iov_len != 0) {
1524 /* Dynamic part is NULL. Chop it off,
1525 We're going to send it via sendfile. */
1526 req->out.vector_count -= 1;
1529 subreq = tstream_writev_queue_send(req,
1530 req->sconn->smb2.event_ctx,
1531 req->sconn->smb2.stream,
1532 req->sconn->smb2.send_queue,
1533 req->out.vector,
1534 req->out.vector_count);
1535 if (subreq == NULL) {
1536 return NT_STATUS_NO_MEMORY;
1538 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1540 * We're done with this request -
1541 * move it off the "being processed" queue.
1543 DLIST_REMOVE(req->sconn->smb2.requests, req);
1545 return NT_STATUS_OK;
1548 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1549 struct tevent_immediate *im,
1550 void *private_data)
1552 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1553 struct smbd_smb2_request);
1554 struct smbd_server_connection *sconn = req->sconn;
1555 NTSTATUS status;
1557 TALLOC_FREE(im);
1559 if (DEBUGLEVEL >= 10) {
1560 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1561 req->current_idx, req->in.vector_count));
1562 print_req_vectors(req);
1565 status = smbd_smb2_request_dispatch(req);
1566 if (!NT_STATUS_IS_OK(status)) {
1567 smbd_server_connection_terminate(sconn, nt_errstr(status));
1568 return;
1572 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1574 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1575 struct smbd_smb2_request);
1576 struct smbd_server_connection *sconn = req->sconn;
1577 int ret;
1578 int sys_errno;
1580 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1581 TALLOC_FREE(subreq);
1582 TALLOC_FREE(req);
1583 if (ret == -1) {
1584 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1585 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1586 nt_errstr(status)));
1587 smbd_server_connection_terminate(sconn, nt_errstr(status));
1588 return;
1592 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1593 NTSTATUS status,
1594 DATA_BLOB body, DATA_BLOB *dyn,
1595 const char *location)
1597 uint8_t *outhdr;
1598 int i = req->current_idx;
1599 uint32_t next_command_ofs;
1601 DEBUG(10,("smbd_smb2_request_done_ex: "
1602 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1603 i, nt_errstr(status), (unsigned int)body.length,
1604 dyn ? "yes": "no",
1605 (unsigned int)(dyn ? dyn->length : 0),
1606 location));
1608 if (body.length < 2) {
1609 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1612 if ((body.length % 2) != 0) {
1613 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1616 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1618 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1619 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1621 req->out.vector[i+1].iov_base = (void *)body.data;
1622 req->out.vector[i+1].iov_len = body.length;
1624 if (dyn) {
1625 req->out.vector[i+2].iov_base = (void *)dyn->data;
1626 req->out.vector[i+2].iov_len = dyn->length;
1627 } else {
1628 req->out.vector[i+2].iov_base = NULL;
1629 req->out.vector[i+2].iov_len = 0;
1632 /* see if we need to recalculate the offset to the next response */
1633 if (next_command_ofs > 0) {
1634 next_command_ofs = SMB2_HDR_BODY;
1635 next_command_ofs += req->out.vector[i+1].iov_len;
1636 next_command_ofs += req->out.vector[i+2].iov_len;
1639 if ((next_command_ofs % 8) != 0) {
1640 size_t pad_size = 8 - (next_command_ofs % 8);
1641 if (req->out.vector[i+2].iov_len == 0) {
1643 * if the dyn buffer is empty
1644 * we can use it to add padding
1646 uint8_t *pad;
1648 pad = talloc_zero_array(req->out.vector,
1649 uint8_t, pad_size);
1650 if (pad == NULL) {
1651 return smbd_smb2_request_error(req,
1652 NT_STATUS_NO_MEMORY);
1655 req->out.vector[i+2].iov_base = (void *)pad;
1656 req->out.vector[i+2].iov_len = pad_size;
1657 } else {
1659 * For now we copy the dynamic buffer
1660 * and add the padding to the new buffer
1662 size_t old_size;
1663 uint8_t *old_dyn;
1664 size_t new_size;
1665 uint8_t *new_dyn;
1667 old_size = req->out.vector[i+2].iov_len;
1668 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
1670 new_size = old_size + pad_size;
1671 new_dyn = talloc_zero_array(req->out.vector,
1672 uint8_t, new_size);
1673 if (new_dyn == NULL) {
1674 return smbd_smb2_request_error(req,
1675 NT_STATUS_NO_MEMORY);
1678 memcpy(new_dyn, old_dyn, old_size);
1679 memset(new_dyn + old_size, 0, pad_size);
1681 req->out.vector[i+2].iov_base = (void *)new_dyn;
1682 req->out.vector[i+2].iov_len = new_size;
1684 next_command_ofs += pad_size;
1687 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1689 return smbd_smb2_request_reply(req);
1692 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
1693 NTSTATUS status,
1694 DATA_BLOB *info,
1695 const char *location)
1697 DATA_BLOB body;
1698 int i = req->current_idx;
1699 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
1701 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1702 i, nt_errstr(status), info ? " +info" : "",
1703 location));
1705 body.data = outhdr + SMB2_HDR_BODY;
1706 body.length = 8;
1707 SSVAL(body.data, 0, 9);
1709 if (info) {
1710 SIVAL(body.data, 0x04, info->length);
1711 } else {
1712 /* Allocated size of req->out.vector[i].iov_base
1713 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
1714 * 1 byte without having to do an alloc.
1716 info = talloc_zero_array(req->out.vector,
1717 DATA_BLOB,
1719 if (!info) {
1720 return NT_STATUS_NO_MEMORY;
1722 info->data = ((uint8_t *)outhdr) +
1723 OUTVEC_ALLOC_SIZE - 1;
1724 info->length = 1;
1725 SCVAL(info->data, 0, 0);
1729 * if a request fails, all other remaining
1730 * compounded requests should fail too
1732 req->next_status = NT_STATUS_INVALID_PARAMETER;
1734 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
1738 struct smbd_smb2_send_oplock_break_state {
1739 struct smbd_server_connection *sconn;
1740 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
1741 struct iovec vector;
1744 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
1746 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
1747 uint64_t file_id_persistent,
1748 uint64_t file_id_volatile,
1749 uint8_t oplock_level)
1751 struct smbd_smb2_send_oplock_break_state *state;
1752 struct tevent_req *subreq;
1753 uint8_t *hdr;
1754 uint8_t *body;
1756 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
1757 if (state == NULL) {
1758 return NT_STATUS_NO_MEMORY;
1760 state->sconn = sconn;
1762 state->vector.iov_base = (void *)state->buf;
1763 state->vector.iov_len = sizeof(state->buf);
1765 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
1766 hdr = state->buf + 4;
1767 body = hdr + SMB2_HDR_BODY;
1769 SIVAL(hdr, 0, SMB2_MAGIC);
1770 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1771 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1772 SIVAL(hdr, SMB2_HDR_STATUS, 0);
1773 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
1774 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
1775 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
1776 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1777 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
1778 SIVAL(hdr, SMB2_HDR_PID, 0);
1779 SIVAL(hdr, SMB2_HDR_TID, 0);
1780 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
1781 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
1783 SSVAL(body, 0x00, 0x18);
1785 SCVAL(body, 0x02, oplock_level);
1786 SCVAL(body, 0x03, 0); /* reserved */
1787 SIVAL(body, 0x04, 0); /* reserved */
1788 SBVAL(body, 0x08, file_id_persistent);
1789 SBVAL(body, 0x10, file_id_volatile);
1791 subreq = tstream_writev_queue_send(state,
1792 sconn->smb2.event_ctx,
1793 sconn->smb2.stream,
1794 sconn->smb2.send_queue,
1795 &state->vector, 1);
1796 if (subreq == NULL) {
1797 return NT_STATUS_NO_MEMORY;
1799 tevent_req_set_callback(subreq,
1800 smbd_smb2_oplock_break_writev_done,
1801 state);
1803 return NT_STATUS_OK;
1806 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
1808 struct smbd_smb2_send_oplock_break_state *state =
1809 tevent_req_callback_data(subreq,
1810 struct smbd_smb2_send_oplock_break_state);
1811 struct smbd_server_connection *sconn = state->sconn;
1812 int ret;
1813 int sys_errno;
1815 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1816 TALLOC_FREE(subreq);
1817 if (ret == -1) {
1818 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1819 smbd_server_connection_terminate(sconn, nt_errstr(status));
1820 return;
1823 TALLOC_FREE(state);
1826 struct smbd_smb2_request_read_state {
1827 size_t missing;
1828 bool asked_for_header;
1829 struct smbd_smb2_request *smb2_req;
1832 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1833 void *private_data,
1834 TALLOC_CTX *mem_ctx,
1835 struct iovec **_vector,
1836 size_t *_count);
1837 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
1839 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
1840 struct tevent_context *ev,
1841 struct smbd_server_connection *sconn)
1843 struct tevent_req *req;
1844 struct smbd_smb2_request_read_state *state;
1845 struct tevent_req *subreq;
1847 req = tevent_req_create(mem_ctx, &state,
1848 struct smbd_smb2_request_read_state);
1849 if (req == NULL) {
1850 return NULL;
1852 state->missing = 0;
1853 state->asked_for_header = false;
1855 state->smb2_req = smbd_smb2_request_allocate(state);
1856 if (tevent_req_nomem(state->smb2_req, req)) {
1857 return tevent_req_post(req, ev);
1859 state->smb2_req->sconn = sconn;
1861 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
1862 sconn->smb2.recv_queue,
1863 smbd_smb2_request_next_vector,
1864 state);
1865 if (tevent_req_nomem(subreq, req)) {
1866 return tevent_req_post(req, ev);
1868 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
1870 return req;
1873 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1874 void *private_data,
1875 TALLOC_CTX *mem_ctx,
1876 struct iovec **_vector,
1877 size_t *_count)
1879 struct smbd_smb2_request_read_state *state =
1880 talloc_get_type_abort(private_data,
1881 struct smbd_smb2_request_read_state);
1882 struct smbd_smb2_request *req = state->smb2_req;
1883 struct iovec *vector;
1884 int idx = req->in.vector_count;
1885 size_t len = 0;
1886 uint8_t *buf = NULL;
1888 if (req->in.vector_count == 0) {
1890 * first we need to get the NBT header
1892 req->in.vector = talloc_array(req, struct iovec,
1893 req->in.vector_count + 1);
1894 if (req->in.vector == NULL) {
1895 return -1;
1897 req->in.vector_count += 1;
1899 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
1900 req->in.vector[idx].iov_len = 4;
1902 vector = talloc_array(mem_ctx, struct iovec, 1);
1903 if (vector == NULL) {
1904 return -1;
1907 vector[0] = req->in.vector[idx];
1909 *_vector = vector;
1910 *_count = 1;
1911 return 0;
1914 if (req->in.vector_count == 1) {
1916 * Now we analyze the NBT header
1918 state->missing = smb2_len(req->in.vector[0].iov_base);
1920 if (state->missing == 0) {
1921 /* if there're no remaining bytes, we're done */
1922 *_vector = NULL;
1923 *_count = 0;
1924 return 0;
1927 req->in.vector = talloc_realloc(req, req->in.vector,
1928 struct iovec,
1929 req->in.vector_count + 1);
1930 if (req->in.vector == NULL) {
1931 return -1;
1933 req->in.vector_count += 1;
1935 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
1937 * it's a special NBT message,
1938 * so get all remaining bytes
1940 len = state->missing;
1941 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
1943 * it's an invalid message, just read what we can get
1944 * and let the caller handle the error
1946 len = state->missing;
1947 } else {
1949 * We assume it's a SMB2 request,
1950 * and we first get the header and the
1951 * first 2 bytes (the struct size) of the body
1953 len = SMB2_HDR_BODY + 2;
1955 state->asked_for_header = true;
1958 state->missing -= len;
1960 buf = talloc_array(req->in.vector, uint8_t, len);
1961 if (buf == NULL) {
1962 return -1;
1965 req->in.vector[idx].iov_base = (void *)buf;
1966 req->in.vector[idx].iov_len = len;
1968 vector = talloc_array(mem_ctx, struct iovec, 1);
1969 if (vector == NULL) {
1970 return -1;
1973 vector[0] = req->in.vector[idx];
1975 *_vector = vector;
1976 *_count = 1;
1977 return 0;
1980 if (state->missing == 0) {
1981 /* if there're no remaining bytes, we're done */
1982 *_vector = NULL;
1983 *_count = 0;
1984 return 0;
1987 if (state->asked_for_header) {
1988 const uint8_t *hdr;
1989 size_t full_size;
1990 size_t next_command_ofs;
1991 size_t body_size;
1992 uint8_t *body;
1993 size_t dyn_size;
1994 uint8_t *dyn;
1995 bool invalid = false;
1997 state->asked_for_header = false;
2000 * We got the SMB2 header and the first 2 bytes
2001 * of the body. We fix the size to just the header
2002 * and manually copy the 2 first bytes to the body section
2004 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2005 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2007 /* allocate vectors for body and dynamic areas */
2008 req->in.vector = talloc_realloc(req, req->in.vector,
2009 struct iovec,
2010 req->in.vector_count + 2);
2011 if (req->in.vector == NULL) {
2012 return -1;
2014 req->in.vector_count += 2;
2016 full_size = state->missing + SMB2_HDR_BODY + 2;
2017 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2018 body_size = SVAL(hdr, SMB2_HDR_BODY);
2020 if (next_command_ofs != 0) {
2021 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2023 * this is invalid, just return a zero
2024 * body and let the caller deal with the error
2026 invalid = true;
2027 } else if (next_command_ofs > full_size) {
2029 * this is invalid, just return a zero
2030 * body and let the caller deal with the error
2032 invalid = true;
2033 } else {
2034 full_size = next_command_ofs;
2038 if (!invalid) {
2039 if (body_size < 2) {
2041 * this is invalid, just return a zero
2042 * body and let the caller deal with the error
2044 invalid = true;
2048 * Mask out the lowest bit, the "dynamic" part
2049 * of body_size.
2051 body_size &= ~1;
2053 if (body_size > (full_size - SMB2_HDR_BODY)) {
2055 * this is invalid, just return a zero
2056 * body and let the caller deal with the error
2058 invalid = true;
2062 if (invalid) {
2063 /* the caller should check this */
2064 body_size = 2;
2067 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2069 state->missing -= (body_size - 2) + dyn_size;
2071 body = talloc_array(req->in.vector, uint8_t, body_size);
2072 if (body == NULL) {
2073 return -1;
2076 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2077 if (dyn == NULL) {
2078 return -1;
2081 req->in.vector[idx].iov_base = (void *)body;
2082 req->in.vector[idx].iov_len = body_size;
2083 req->in.vector[idx+1].iov_base = (void *)dyn;
2084 req->in.vector[idx+1].iov_len = dyn_size;
2086 vector = talloc_array(mem_ctx, struct iovec, 2);
2087 if (vector == NULL) {
2088 return -1;
2092 * the first 2 bytes of the body were already fetched
2093 * together with the header
2095 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2096 vector[0].iov_base = body + 2;
2097 vector[0].iov_len = body_size - 2;
2099 vector[1] = req->in.vector[idx+1];
2101 *_vector = vector;
2102 *_count = 2;
2103 return 0;
2107 * when we endup here, we're looking for a new SMB2 request
2108 * next. And we ask for its header and the first 2 bytes of
2109 * the body (like we did for the first SMB2 request).
2112 req->in.vector = talloc_realloc(req, req->in.vector,
2113 struct iovec,
2114 req->in.vector_count + 1);
2115 if (req->in.vector == NULL) {
2116 return -1;
2118 req->in.vector_count += 1;
2121 * We assume it's a SMB2 request,
2122 * and we first get the header and the
2123 * first 2 bytes (the struct size) of the body
2125 len = SMB2_HDR_BODY + 2;
2127 if (len > state->missing) {
2128 /* let the caller handle the error */
2129 len = state->missing;
2132 state->missing -= len;
2133 state->asked_for_header = true;
2135 buf = talloc_array(req->in.vector, uint8_t, len);
2136 if (buf == NULL) {
2137 return -1;
2140 req->in.vector[idx].iov_base = (void *)buf;
2141 req->in.vector[idx].iov_len = len;
2143 vector = talloc_array(mem_ctx, struct iovec, 1);
2144 if (vector == NULL) {
2145 return -1;
2148 vector[0] = req->in.vector[idx];
2150 *_vector = vector;
2151 *_count = 1;
2152 return 0;
2155 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2157 struct tevent_req *req =
2158 tevent_req_callback_data(subreq,
2159 struct tevent_req);
2160 int ret;
2161 int sys_errno;
2162 NTSTATUS status;
2164 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2165 if (ret == -1) {
2166 status = map_nt_error_from_unix(sys_errno);
2167 tevent_req_nterror(req, status);
2168 return;
2171 tevent_req_done(req);
2174 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2175 TALLOC_CTX *mem_ctx,
2176 struct smbd_smb2_request **_smb2_req)
2178 struct smbd_smb2_request_read_state *state =
2179 tevent_req_data(req,
2180 struct smbd_smb2_request_read_state);
2181 NTSTATUS status;
2183 if (tevent_req_is_nterror(req, &status)) {
2184 tevent_req_received(req);
2185 return status;
2188 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2189 *_smb2_req = state->smb2_req;
2190 tevent_req_received(req);
2191 return NT_STATUS_OK;
2194 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2196 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2197 const uint8_t *inbuf, size_t size)
2199 NTSTATUS status;
2200 struct smbd_smb2_request *req = NULL;
2201 struct tevent_req *subreq;
2203 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2204 (unsigned int)size));
2206 status = smbd_initialize_smb2(sconn);
2207 if (!NT_STATUS_IS_OK(status)) {
2208 smbd_server_connection_terminate(sconn, nt_errstr(status));
2209 return;
2212 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2213 if (!NT_STATUS_IS_OK(status)) {
2214 smbd_server_connection_terminate(sconn, nt_errstr(status));
2215 return;
2218 status = smbd_smb2_request_setup_out(req);
2219 if (!NT_STATUS_IS_OK(status)) {
2220 smbd_server_connection_terminate(sconn, nt_errstr(status));
2221 return;
2224 status = smbd_smb2_request_dispatch(req);
2225 if (!NT_STATUS_IS_OK(status)) {
2226 smbd_server_connection_terminate(sconn, nt_errstr(status));
2227 return;
2230 /* ask for the next request */
2231 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2232 if (subreq == NULL) {
2233 smbd_server_connection_terminate(sconn, "no memory for reading");
2234 return;
2236 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2238 sconn->num_requests++;
2241 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2243 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2244 struct smbd_server_connection);
2245 NTSTATUS status;
2246 struct smbd_smb2_request *req = NULL;
2248 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2249 TALLOC_FREE(subreq);
2250 if (!NT_STATUS_IS_OK(status)) {
2251 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2252 nt_errstr(status)));
2253 smbd_server_connection_terminate(sconn, nt_errstr(status));
2254 return;
2257 if (req->in.nbt_hdr[0] != 0x00) {
2258 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2259 req->in.nbt_hdr[0]));
2260 TALLOC_FREE(req);
2261 goto next;
2264 req->current_idx = 1;
2266 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2267 req->current_idx, req->in.vector_count));
2269 status = smbd_smb2_request_validate(req);
2270 if (!NT_STATUS_IS_OK(status)) {
2271 smbd_server_connection_terminate(sconn, nt_errstr(status));
2272 return;
2275 status = smbd_smb2_request_setup_out(req);
2276 if (!NT_STATUS_IS_OK(status)) {
2277 smbd_server_connection_terminate(sconn, nt_errstr(status));
2278 return;
2281 status = smbd_smb2_request_dispatch(req);
2282 if (!NT_STATUS_IS_OK(status)) {
2283 smbd_server_connection_terminate(sconn, nt_errstr(status));
2284 return;
2287 next:
2288 /* ask for the next request (this constructs the main loop) */
2289 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2290 if (subreq == NULL) {
2291 smbd_server_connection_terminate(sconn, "no memory for reading");
2292 return;
2294 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2296 sconn->num_requests++;
2298 /* The timeout_processing function isn't run nearly
2299 often enough to implement 'max log size' without
2300 overrunning the size of the file by many megabytes.
2301 This is especially true if we are running at debug
2302 level 10. Checking every 50 SMB2s is a nice
2303 tradeoff of performance vs log file size overrun. */
2305 if ((sconn->num_requests % 50) == 0 &&
2306 need_to_check_log_size()) {
2307 change_to_root_user();
2308 check_log_size();