s3:smb2_server: there's no reason to check the session id twice on a smb2_tcon request
[Samba.git] / source3 / smbd / smb2_server.c
blob32c7c8f4fb0335ae694e8cfeb806307e50bdefa1
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 = 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);
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 = (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;
284 if (ofs > size) {
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;
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:
1143 START_PROFILE(smb2_negprot);
1144 return_value = smbd_smb2_request_process_negprot(req);
1145 END_PROFILE(smb2_negprot);
1147 break;
1149 case SMB2_OP_SESSSETUP:
1151 START_PROFILE(smb2_sesssetup);
1152 return_value = smbd_smb2_request_process_sesssetup(req);
1153 END_PROFILE(smb2_sesssetup);
1155 break;
1157 case SMB2_OP_LOGOFF:
1158 if (!NT_STATUS_IS_OK(session_status)) {
1159 return_value = smbd_smb2_request_error(req, session_status);
1160 break;
1164 START_PROFILE(smb2_logoff);
1165 return_value = smbd_smb2_request_process_logoff(req);
1166 END_PROFILE(smb2_logoff);
1168 break;
1170 case SMB2_OP_TCON:
1171 if (!NT_STATUS_IS_OK(session_status)) {
1172 return_value = smbd_smb2_request_error(req, session_status);
1173 break;
1177 START_PROFILE(smb2_tcon);
1178 return_value = smbd_smb2_request_process_tcon(req);
1179 END_PROFILE(smb2_tcon);
1181 break;
1183 case SMB2_OP_TDIS:
1184 if (!NT_STATUS_IS_OK(session_status)) {
1185 return_value = smbd_smb2_request_error(req, session_status);
1186 break;
1188 status = smbd_smb2_request_check_tcon(req);
1189 if (!NT_STATUS_IS_OK(status)) {
1190 return_value = smbd_smb2_request_error(req, status);
1191 break;
1195 START_PROFILE(smb2_tdis);
1196 return_value = smbd_smb2_request_process_tdis(req);
1197 END_PROFILE(smb2_tdis);
1199 break;
1201 case SMB2_OP_CREATE:
1202 if (!NT_STATUS_IS_OK(session_status)) {
1203 return_value = smbd_smb2_request_error(req, session_status);
1204 break;
1206 status = smbd_smb2_request_check_tcon(req);
1207 if (!NT_STATUS_IS_OK(status)) {
1208 return_value = smbd_smb2_request_error(req, status);
1209 break;
1213 START_PROFILE(smb2_create);
1214 return_value = smbd_smb2_request_process_create(req);
1215 END_PROFILE(smb2_create);
1217 break;
1219 case SMB2_OP_CLOSE:
1220 if (!NT_STATUS_IS_OK(session_status)) {
1221 return_value = smbd_smb2_request_error(req, session_status);
1222 break;
1224 status = smbd_smb2_request_check_tcon(req);
1225 if (!NT_STATUS_IS_OK(status)) {
1226 return_value = smbd_smb2_request_error(req, status);
1227 break;
1231 START_PROFILE(smb2_close);
1232 return_value = smbd_smb2_request_process_close(req);
1233 END_PROFILE(smb2_close);
1235 break;
1237 case SMB2_OP_FLUSH:
1238 if (!NT_STATUS_IS_OK(session_status)) {
1239 return_value = smbd_smb2_request_error(req, session_status);
1240 break;
1242 status = smbd_smb2_request_check_tcon(req);
1243 if (!NT_STATUS_IS_OK(status)) {
1244 return_value = smbd_smb2_request_error(req, status);
1245 break;
1249 START_PROFILE(smb2_flush);
1250 return_value = smbd_smb2_request_process_flush(req);
1251 END_PROFILE(smb2_flush);
1253 break;
1255 case SMB2_OP_READ:
1256 if (!NT_STATUS_IS_OK(session_status)) {
1257 return_value = smbd_smb2_request_error(req, session_status);
1258 break;
1260 status = smbd_smb2_request_check_tcon(req);
1261 if (!NT_STATUS_IS_OK(status)) {
1262 return_value = smbd_smb2_request_error(req, status);
1263 break;
1267 START_PROFILE(smb2_read);
1268 return_value = smbd_smb2_request_process_read(req);
1269 END_PROFILE(smb2_read);
1271 break;
1273 case SMB2_OP_WRITE:
1274 if (!NT_STATUS_IS_OK(session_status)) {
1275 return_value = smbd_smb2_request_error(req, session_status);
1276 break;
1278 status = smbd_smb2_request_check_tcon(req);
1279 if (!NT_STATUS_IS_OK(status)) {
1280 return_value = smbd_smb2_request_error(req, status);
1281 break;
1285 START_PROFILE(smb2_write);
1286 return_value = smbd_smb2_request_process_write(req);
1287 END_PROFILE(smb2_write);
1289 break;
1291 case SMB2_OP_LOCK:
1292 if (!NT_STATUS_IS_OK(session_status)) {
1293 /* Too ugly to live ? JRA. */
1294 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1295 session_status = NT_STATUS_FILE_CLOSED;
1297 return_value = smbd_smb2_request_error(req, session_status);
1298 break;
1300 status = smbd_smb2_request_check_tcon(req);
1301 if (!NT_STATUS_IS_OK(status)) {
1302 /* Too ugly to live ? JRA. */
1303 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1304 status = NT_STATUS_FILE_CLOSED;
1306 return_value = smbd_smb2_request_error(req, status);
1307 break;
1311 START_PROFILE(smb2_lock);
1312 return_value = smbd_smb2_request_process_lock(req);
1313 END_PROFILE(smb2_lock);
1315 break;
1317 case SMB2_OP_IOCTL:
1318 if (!NT_STATUS_IS_OK(session_status)) {
1319 return_value = smbd_smb2_request_error(req, session_status);
1320 break;
1322 status = smbd_smb2_request_check_tcon(req);
1323 if (!NT_STATUS_IS_OK(status)) {
1324 return_value = smbd_smb2_request_error(req, status);
1325 break;
1329 START_PROFILE(smb2_ioctl);
1330 return_value = smbd_smb2_request_process_ioctl(req);
1331 END_PROFILE(smb2_ioctl);
1333 break;
1335 case SMB2_OP_CANCEL:
1337 START_PROFILE(smb2_cancel);
1338 return_value = smbd_smb2_request_process_cancel(req);
1339 END_PROFILE(smb2_cancel);
1341 break;
1343 case SMB2_OP_KEEPALIVE:
1344 {START_PROFILE(smb2_keepalive);
1345 return_value = smbd_smb2_request_process_keepalive(req);
1346 END_PROFILE(smb2_keepalive);}
1347 break;
1349 case SMB2_OP_FIND:
1350 if (!NT_STATUS_IS_OK(session_status)) {
1351 return_value = smbd_smb2_request_error(req, session_status);
1352 break;
1354 status = smbd_smb2_request_check_tcon(req);
1355 if (!NT_STATUS_IS_OK(status)) {
1356 return_value = smbd_smb2_request_error(req, status);
1357 break;
1361 START_PROFILE(smb2_find);
1362 return_value = smbd_smb2_request_process_find(req);
1363 END_PROFILE(smb2_find);
1365 break;
1367 case SMB2_OP_NOTIFY:
1368 if (!NT_STATUS_IS_OK(session_status)) {
1369 return_value = smbd_smb2_request_error(req, session_status);
1370 break;
1372 status = smbd_smb2_request_check_tcon(req);
1373 if (!NT_STATUS_IS_OK(status)) {
1374 return_value = smbd_smb2_request_error(req, status);
1375 break;
1379 START_PROFILE(smb2_notify);
1380 return_value = smbd_smb2_request_process_notify(req);
1381 END_PROFILE(smb2_notify);
1383 break;
1385 case SMB2_OP_GETINFO:
1386 if (!NT_STATUS_IS_OK(session_status)) {
1387 return_value = smbd_smb2_request_error(req, session_status);
1388 break;
1390 status = smbd_smb2_request_check_tcon(req);
1391 if (!NT_STATUS_IS_OK(status)) {
1392 return_value = smbd_smb2_request_error(req, status);
1393 break;
1397 START_PROFILE(smb2_getinfo);
1398 return_value = smbd_smb2_request_process_getinfo(req);
1399 END_PROFILE(smb2_getinfo);
1401 break;
1403 case SMB2_OP_SETINFO:
1404 if (!NT_STATUS_IS_OK(session_status)) {
1405 return_value = smbd_smb2_request_error(req, session_status);
1406 break;
1408 status = smbd_smb2_request_check_tcon(req);
1409 if (!NT_STATUS_IS_OK(status)) {
1410 return_value = smbd_smb2_request_error(req, status);
1411 break;
1415 START_PROFILE(smb2_setinfo);
1416 return_value = smbd_smb2_request_process_setinfo(req);
1417 END_PROFILE(smb2_setinfo);
1419 break;
1421 case SMB2_OP_BREAK:
1422 if (!NT_STATUS_IS_OK(session_status)) {
1423 return_value = smbd_smb2_request_error(req, session_status);
1424 break;
1426 status = smbd_smb2_request_check_tcon(req);
1427 if (!NT_STATUS_IS_OK(status)) {
1428 return_value = smbd_smb2_request_error(req, status);
1429 break;
1433 START_PROFILE(smb2_break);
1434 return_value = smbd_smb2_request_process_break(req);
1435 END_PROFILE(smb2_break);
1437 break;
1439 default:
1440 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1441 break;
1443 return return_value;
1446 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1448 struct tevent_req *subreq;
1449 int i = req->current_idx;
1451 req->subreq = NULL;
1453 req->current_idx += 3;
1455 if (req->current_idx < req->out.vector_count) {
1457 * We must process the remaining compound
1458 * SMB2 requests before any new incoming SMB2
1459 * requests. This is because incoming SMB2
1460 * requests may include a cancel for a
1461 * compound request we haven't processed
1462 * yet.
1464 struct tevent_immediate *im = tevent_create_immediate(req);
1465 if (!im) {
1466 return NT_STATUS_NO_MEMORY;
1468 tevent_schedule_immediate(im,
1469 req->sconn->smb2.event_ctx,
1470 smbd_smb2_request_dispatch_immediate,
1471 req);
1472 return NT_STATUS_OK;
1475 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1477 /* Set credit for this operation (zero credits if this
1478 is a final reply for an async operation). */
1479 smb2_set_operation_credit(req->sconn,
1480 req->async ? NULL : &req->in.vector[i],
1481 &req->out.vector[i]);
1483 if (req->do_signing) {
1484 NTSTATUS status;
1485 status = smb2_signing_sign_pdu(req->session->session_key,
1486 &req->out.vector[i], 3);
1487 if (!NT_STATUS_IS_OK(status)) {
1488 return status;
1492 if (DEBUGLEVEL >= 10) {
1493 dbgtext("smbd_smb2_request_reply: sending...\n");
1494 print_req_vectors(req);
1497 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1498 if (req->out.vector_count == 4 &&
1499 req->out.vector[3].iov_base == NULL &&
1500 req->out.vector[3].iov_len != 0) {
1501 /* Dynamic part is NULL. Chop it off,
1502 We're going to send it via sendfile. */
1503 req->out.vector_count -= 1;
1506 subreq = tstream_writev_queue_send(req,
1507 req->sconn->smb2.event_ctx,
1508 req->sconn->smb2.stream,
1509 req->sconn->smb2.send_queue,
1510 req->out.vector,
1511 req->out.vector_count);
1512 if (subreq == NULL) {
1513 return NT_STATUS_NO_MEMORY;
1515 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1517 * We're done with this request -
1518 * move it off the "being processed" queue.
1520 DLIST_REMOVE(req->sconn->smb2.requests, req);
1522 return NT_STATUS_OK;
1525 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1526 struct tevent_immediate *im,
1527 void *private_data)
1529 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1530 struct smbd_smb2_request);
1531 struct smbd_server_connection *sconn = req->sconn;
1532 NTSTATUS status;
1534 TALLOC_FREE(im);
1536 if (DEBUGLEVEL >= 10) {
1537 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1538 req->current_idx, req->in.vector_count));
1539 print_req_vectors(req);
1542 status = smbd_smb2_request_dispatch(req);
1543 if (!NT_STATUS_IS_OK(status)) {
1544 smbd_server_connection_terminate(sconn, nt_errstr(status));
1545 return;
1549 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1551 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1552 struct smbd_smb2_request);
1553 struct smbd_server_connection *sconn = req->sconn;
1554 int ret;
1555 int sys_errno;
1557 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1558 TALLOC_FREE(subreq);
1559 TALLOC_FREE(req);
1560 if (ret == -1) {
1561 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1562 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1563 nt_errstr(status)));
1564 smbd_server_connection_terminate(sconn, nt_errstr(status));
1565 return;
1569 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1570 NTSTATUS status,
1571 DATA_BLOB body, DATA_BLOB *dyn,
1572 const char *location)
1574 uint8_t *outhdr;
1575 int i = req->current_idx;
1576 uint32_t next_command_ofs;
1578 DEBUG(10,("smbd_smb2_request_done_ex: "
1579 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1580 i, nt_errstr(status), (unsigned int)body.length,
1581 dyn ? "yes": "no",
1582 (unsigned int)(dyn ? dyn->length : 0),
1583 location));
1585 if (body.length < 2) {
1586 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1589 if ((body.length % 2) != 0) {
1590 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1593 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1595 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1596 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1598 req->out.vector[i+1].iov_base = (void *)body.data;
1599 req->out.vector[i+1].iov_len = body.length;
1601 if (dyn) {
1602 req->out.vector[i+2].iov_base = (void *)dyn->data;
1603 req->out.vector[i+2].iov_len = dyn->length;
1604 } else {
1605 req->out.vector[i+2].iov_base = NULL;
1606 req->out.vector[i+2].iov_len = 0;
1609 /* see if we need to recalculate the offset to the next response */
1610 if (next_command_ofs > 0) {
1611 next_command_ofs = SMB2_HDR_BODY;
1612 next_command_ofs += req->out.vector[i+1].iov_len;
1613 next_command_ofs += req->out.vector[i+2].iov_len;
1616 if ((next_command_ofs % 8) != 0) {
1617 size_t pad_size = 8 - (next_command_ofs % 8);
1618 if (req->out.vector[i+2].iov_len == 0) {
1620 * if the dyn buffer is empty
1621 * we can use it to add padding
1623 uint8_t *pad;
1625 pad = talloc_zero_array(req->out.vector,
1626 uint8_t, pad_size);
1627 if (pad == NULL) {
1628 return smbd_smb2_request_error(req,
1629 NT_STATUS_NO_MEMORY);
1632 req->out.vector[i+2].iov_base = (void *)pad;
1633 req->out.vector[i+2].iov_len = pad_size;
1634 } else {
1636 * For now we copy the dynamic buffer
1637 * and add the padding to the new buffer
1639 size_t old_size;
1640 uint8_t *old_dyn;
1641 size_t new_size;
1642 uint8_t *new_dyn;
1644 old_size = req->out.vector[i+2].iov_len;
1645 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
1647 new_size = old_size + pad_size;
1648 new_dyn = talloc_zero_array(req->out.vector,
1649 uint8_t, new_size);
1650 if (new_dyn == NULL) {
1651 return smbd_smb2_request_error(req,
1652 NT_STATUS_NO_MEMORY);
1655 memcpy(new_dyn, old_dyn, old_size);
1656 memset(new_dyn + old_size, 0, pad_size);
1658 req->out.vector[i+2].iov_base = (void *)new_dyn;
1659 req->out.vector[i+2].iov_len = new_size;
1661 next_command_ofs += pad_size;
1664 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1666 return smbd_smb2_request_reply(req);
1669 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
1670 NTSTATUS status,
1671 DATA_BLOB *info,
1672 const char *location)
1674 DATA_BLOB body;
1675 int i = req->current_idx;
1676 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
1678 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1679 i, nt_errstr(status), info ? " +info" : "",
1680 location));
1682 body.data = outhdr + SMB2_HDR_BODY;
1683 body.length = 8;
1684 SSVAL(body.data, 0, 9);
1686 if (info) {
1687 SIVAL(body.data, 0x04, info->length);
1688 } else {
1689 /* Allocated size of req->out.vector[i].iov_base
1690 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
1691 * 1 byte without having to do an alloc.
1693 info = talloc_zero_array(req->out.vector,
1694 DATA_BLOB,
1696 if (!info) {
1697 return NT_STATUS_NO_MEMORY;
1699 info->data = ((uint8_t *)outhdr) +
1700 OUTVEC_ALLOC_SIZE - 1;
1701 info->length = 1;
1702 SCVAL(info->data, 0, 0);
1706 * if a request fails, all other remaining
1707 * compounded requests should fail too
1709 req->next_status = NT_STATUS_INVALID_PARAMETER;
1711 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
1715 struct smbd_smb2_send_oplock_break_state {
1716 struct smbd_server_connection *sconn;
1717 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
1718 struct iovec vector;
1721 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
1723 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
1724 uint64_t file_id_persistent,
1725 uint64_t file_id_volatile,
1726 uint8_t oplock_level)
1728 struct smbd_smb2_send_oplock_break_state *state;
1729 struct tevent_req *subreq;
1730 uint8_t *hdr;
1731 uint8_t *body;
1733 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
1734 if (state == NULL) {
1735 return NT_STATUS_NO_MEMORY;
1737 state->sconn = sconn;
1739 state->vector.iov_base = (void *)state->buf;
1740 state->vector.iov_len = sizeof(state->buf);
1742 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
1743 hdr = state->buf + 4;
1744 body = hdr + SMB2_HDR_BODY;
1746 SIVAL(hdr, 0, SMB2_MAGIC);
1747 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1748 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1749 SIVAL(hdr, SMB2_HDR_STATUS, 0);
1750 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
1751 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
1752 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
1753 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1754 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
1755 SIVAL(hdr, SMB2_HDR_PID, 0);
1756 SIVAL(hdr, SMB2_HDR_TID, 0);
1757 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
1758 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
1760 SSVAL(body, 0x00, 0x18);
1762 SCVAL(body, 0x02, oplock_level);
1763 SCVAL(body, 0x03, 0); /* reserved */
1764 SIVAL(body, 0x04, 0); /* reserved */
1765 SBVAL(body, 0x08, file_id_persistent);
1766 SBVAL(body, 0x10, file_id_volatile);
1768 subreq = tstream_writev_queue_send(state,
1769 sconn->smb2.event_ctx,
1770 sconn->smb2.stream,
1771 sconn->smb2.send_queue,
1772 &state->vector, 1);
1773 if (subreq == NULL) {
1774 return NT_STATUS_NO_MEMORY;
1776 tevent_req_set_callback(subreq,
1777 smbd_smb2_oplock_break_writev_done,
1778 state);
1780 return NT_STATUS_OK;
1783 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
1785 struct smbd_smb2_send_oplock_break_state *state =
1786 tevent_req_callback_data(subreq,
1787 struct smbd_smb2_send_oplock_break_state);
1788 struct smbd_server_connection *sconn = state->sconn;
1789 int ret;
1790 int sys_errno;
1792 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1793 TALLOC_FREE(subreq);
1794 if (ret == -1) {
1795 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1796 smbd_server_connection_terminate(sconn, nt_errstr(status));
1797 return;
1800 TALLOC_FREE(state);
1803 struct smbd_smb2_request_read_state {
1804 size_t missing;
1805 bool asked_for_header;
1806 struct smbd_smb2_request *smb2_req;
1809 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1810 void *private_data,
1811 TALLOC_CTX *mem_ctx,
1812 struct iovec **_vector,
1813 size_t *_count);
1814 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
1816 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
1817 struct tevent_context *ev,
1818 struct smbd_server_connection *sconn)
1820 struct tevent_req *req;
1821 struct smbd_smb2_request_read_state *state;
1822 struct tevent_req *subreq;
1824 req = tevent_req_create(mem_ctx, &state,
1825 struct smbd_smb2_request_read_state);
1826 if (req == NULL) {
1827 return NULL;
1829 state->missing = 0;
1830 state->asked_for_header = false;
1832 state->smb2_req = smbd_smb2_request_allocate(state);
1833 if (tevent_req_nomem(state->smb2_req, req)) {
1834 return tevent_req_post(req, ev);
1836 state->smb2_req->sconn = sconn;
1838 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
1839 sconn->smb2.recv_queue,
1840 smbd_smb2_request_next_vector,
1841 state);
1842 if (tevent_req_nomem(subreq, req)) {
1843 return tevent_req_post(req, ev);
1845 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
1847 return req;
1850 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1851 void *private_data,
1852 TALLOC_CTX *mem_ctx,
1853 struct iovec **_vector,
1854 size_t *_count)
1856 struct smbd_smb2_request_read_state *state =
1857 talloc_get_type_abort(private_data,
1858 struct smbd_smb2_request_read_state);
1859 struct smbd_smb2_request *req = state->smb2_req;
1860 struct iovec *vector;
1861 int idx = req->in.vector_count;
1862 size_t len = 0;
1863 uint8_t *buf = NULL;
1865 if (req->in.vector_count == 0) {
1867 * first we need to get the NBT header
1869 req->in.vector = talloc_array(req, struct iovec,
1870 req->in.vector_count + 1);
1871 if (req->in.vector == NULL) {
1872 return -1;
1874 req->in.vector_count += 1;
1876 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
1877 req->in.vector[idx].iov_len = 4;
1879 vector = talloc_array(mem_ctx, struct iovec, 1);
1880 if (vector == NULL) {
1881 return -1;
1884 vector[0] = req->in.vector[idx];
1886 *_vector = vector;
1887 *_count = 1;
1888 return 0;
1891 if (req->in.vector_count == 1) {
1893 * Now we analyze the NBT header
1895 state->missing = smb2_len(req->in.vector[0].iov_base);
1897 if (state->missing == 0) {
1898 /* if there're no remaining bytes, we're done */
1899 *_vector = NULL;
1900 *_count = 0;
1901 return 0;
1904 req->in.vector = talloc_realloc(req, req->in.vector,
1905 struct iovec,
1906 req->in.vector_count + 1);
1907 if (req->in.vector == NULL) {
1908 return -1;
1910 req->in.vector_count += 1;
1912 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
1914 * it's a special NBT message,
1915 * so get all remaining bytes
1917 len = state->missing;
1918 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
1920 * it's an invalid message, just read what we can get
1921 * and let the caller handle the error
1923 len = state->missing;
1924 } else {
1926 * We assume it's a SMB2 request,
1927 * and we first get the header and the
1928 * first 2 bytes (the struct size) of the body
1930 len = SMB2_HDR_BODY + 2;
1932 state->asked_for_header = true;
1935 state->missing -= len;
1937 buf = talloc_array(req->in.vector, uint8_t, len);
1938 if (buf == NULL) {
1939 return -1;
1942 req->in.vector[idx].iov_base = (void *)buf;
1943 req->in.vector[idx].iov_len = len;
1945 vector = talloc_array(mem_ctx, struct iovec, 1);
1946 if (vector == NULL) {
1947 return -1;
1950 vector[0] = req->in.vector[idx];
1952 *_vector = vector;
1953 *_count = 1;
1954 return 0;
1957 if (state->missing == 0) {
1958 /* if there're no remaining bytes, we're done */
1959 *_vector = NULL;
1960 *_count = 0;
1961 return 0;
1964 if (state->asked_for_header) {
1965 const uint8_t *hdr;
1966 size_t full_size;
1967 size_t next_command_ofs;
1968 size_t body_size;
1969 uint8_t *body;
1970 size_t dyn_size;
1971 uint8_t *dyn;
1972 bool invalid = false;
1974 state->asked_for_header = false;
1977 * We got the SMB2 header and the first 2 bytes
1978 * of the body. We fix the size to just the header
1979 * and manually copy the 2 first bytes to the body section
1981 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
1982 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
1984 /* allocate vectors for body and dynamic areas */
1985 req->in.vector = talloc_realloc(req, req->in.vector,
1986 struct iovec,
1987 req->in.vector_count + 2);
1988 if (req->in.vector == NULL) {
1989 return -1;
1991 req->in.vector_count += 2;
1993 full_size = state->missing + SMB2_HDR_BODY + 2;
1994 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
1995 body_size = SVAL(hdr, SMB2_HDR_BODY);
1997 if (next_command_ofs != 0) {
1998 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2000 * this is invalid, just return a zero
2001 * body and let the caller deal with the error
2003 invalid = true;
2004 } else if (next_command_ofs > full_size) {
2006 * this is invalid, just return a zero
2007 * body and let the caller deal with the error
2009 invalid = true;
2010 } else {
2011 full_size = next_command_ofs;
2015 if (!invalid) {
2016 if (body_size < 2) {
2018 * this is invalid, just return a zero
2019 * body and let the caller deal with the error
2021 invalid = true;
2024 if ((body_size % 2) != 0) {
2025 body_size -= 1;
2028 if (body_size > (full_size - SMB2_HDR_BODY)) {
2030 * this is invalid, just return a zero
2031 * body and let the caller deal with the error
2033 invalid = true;
2037 if (invalid) {
2038 /* the caller should check this */
2039 body_size = 2;
2042 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2044 state->missing -= (body_size - 2) + dyn_size;
2046 body = talloc_array(req->in.vector, uint8_t, body_size);
2047 if (body == NULL) {
2048 return -1;
2051 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2052 if (dyn == NULL) {
2053 return -1;
2056 req->in.vector[idx].iov_base = (void *)body;
2057 req->in.vector[idx].iov_len = body_size;
2058 req->in.vector[idx+1].iov_base = (void *)dyn;
2059 req->in.vector[idx+1].iov_len = dyn_size;
2061 vector = talloc_array(mem_ctx, struct iovec, 2);
2062 if (vector == NULL) {
2063 return -1;
2067 * the first 2 bytes of the body were already fetched
2068 * together with the header
2070 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2071 vector[0].iov_base = body + 2;
2072 vector[0].iov_len = body_size - 2;
2074 vector[1] = req->in.vector[idx+1];
2076 *_vector = vector;
2077 *_count = 2;
2078 return 0;
2082 * when we endup here, we're looking for a new SMB2 request
2083 * next. And we ask for its header and the first 2 bytes of
2084 * the body (like we did for the first SMB2 request).
2087 req->in.vector = talloc_realloc(req, req->in.vector,
2088 struct iovec,
2089 req->in.vector_count + 1);
2090 if (req->in.vector == NULL) {
2091 return -1;
2093 req->in.vector_count += 1;
2096 * We assume it's a SMB2 request,
2097 * and we first get the header and the
2098 * first 2 bytes (the struct size) of the body
2100 len = SMB2_HDR_BODY + 2;
2102 if (len > state->missing) {
2103 /* let the caller handle the error */
2104 len = state->missing;
2107 state->missing -= len;
2108 state->asked_for_header = true;
2110 buf = talloc_array(req->in.vector, uint8_t, len);
2111 if (buf == NULL) {
2112 return -1;
2115 req->in.vector[idx].iov_base = (void *)buf;
2116 req->in.vector[idx].iov_len = len;
2118 vector = talloc_array(mem_ctx, struct iovec, 1);
2119 if (vector == NULL) {
2120 return -1;
2123 vector[0] = req->in.vector[idx];
2125 *_vector = vector;
2126 *_count = 1;
2127 return 0;
2130 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2132 struct tevent_req *req =
2133 tevent_req_callback_data(subreq,
2134 struct tevent_req);
2135 int ret;
2136 int sys_errno;
2137 NTSTATUS status;
2139 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2140 if (ret == -1) {
2141 status = map_nt_error_from_unix(sys_errno);
2142 tevent_req_nterror(req, status);
2143 return;
2146 tevent_req_done(req);
2149 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2150 TALLOC_CTX *mem_ctx,
2151 struct smbd_smb2_request **_smb2_req)
2153 struct smbd_smb2_request_read_state *state =
2154 tevent_req_data(req,
2155 struct smbd_smb2_request_read_state);
2156 NTSTATUS status;
2158 if (tevent_req_is_nterror(req, &status)) {
2159 tevent_req_received(req);
2160 return status;
2163 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2164 *_smb2_req = state->smb2_req;
2165 tevent_req_received(req);
2166 return NT_STATUS_OK;
2169 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2171 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2172 const uint8_t *inbuf, size_t size)
2174 NTSTATUS status;
2175 struct smbd_smb2_request *req = NULL;
2176 struct tevent_req *subreq;
2178 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2179 (unsigned int)size));
2181 status = smbd_initialize_smb2(sconn);
2182 if (!NT_STATUS_IS_OK(status)) {
2183 smbd_server_connection_terminate(sconn, nt_errstr(status));
2184 return;
2187 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2188 if (!NT_STATUS_IS_OK(status)) {
2189 smbd_server_connection_terminate(sconn, nt_errstr(status));
2190 return;
2193 status = smbd_smb2_request_setup_out(req);
2194 if (!NT_STATUS_IS_OK(status)) {
2195 smbd_server_connection_terminate(sconn, nt_errstr(status));
2196 return;
2199 status = smbd_smb2_request_dispatch(req);
2200 if (!NT_STATUS_IS_OK(status)) {
2201 smbd_server_connection_terminate(sconn, nt_errstr(status));
2202 return;
2205 /* ask for the next request */
2206 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2207 if (subreq == NULL) {
2208 smbd_server_connection_terminate(sconn, "no memory for reading");
2209 return;
2211 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2213 sconn->num_requests++;
2216 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2218 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2219 struct smbd_server_connection);
2220 NTSTATUS status;
2221 struct smbd_smb2_request *req = NULL;
2223 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2224 TALLOC_FREE(subreq);
2225 if (!NT_STATUS_IS_OK(status)) {
2226 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2227 nt_errstr(status)));
2228 smbd_server_connection_terminate(sconn, nt_errstr(status));
2229 return;
2232 if (req->in.nbt_hdr[0] != 0x00) {
2233 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2234 req->in.nbt_hdr[0]));
2235 TALLOC_FREE(req);
2236 goto next;
2239 req->current_idx = 1;
2241 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2242 req->current_idx, req->in.vector_count));
2244 status = smbd_smb2_request_validate(req);
2245 if (!NT_STATUS_IS_OK(status)) {
2246 smbd_server_connection_terminate(sconn, nt_errstr(status));
2247 return;
2250 status = smbd_smb2_request_setup_out(req);
2251 if (!NT_STATUS_IS_OK(status)) {
2252 smbd_server_connection_terminate(sconn, nt_errstr(status));
2253 return;
2256 status = smbd_smb2_request_dispatch(req);
2257 if (!NT_STATUS_IS_OK(status)) {
2258 smbd_server_connection_terminate(sconn, nt_errstr(status));
2259 return;
2262 next:
2263 /* ask for the next request (this constructs the main loop) */
2264 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2265 if (subreq == NULL) {
2266 smbd_server_connection_terminate(sconn, "no memory for reading");
2267 return;
2269 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2271 sconn->num_requests++;
2273 /* The timeout_processing function isn't run nearly
2274 often enough to implement 'max log size' without
2275 overrunning the size of the file by many megabytes.
2276 This is especially true if we are running at debug
2277 level 10. Checking every 50 SMB2s is a nice
2278 tradeoff of performance vs log file size overrun. */
2280 if ((sconn->num_requests % 50) == 0 &&
2281 need_to_check_log_size()) {
2282 change_to_root_user();
2283 check_log_size();