Based on metze's fix for Bug 8407 - SMB2 server can return requests out-of-order...
[Samba.git] / source3 / smbd / smb2_server.c
blob5661c47bcbfe0cbd3ccc49ad6e607ec70a7bfb2e
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 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
445 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
446 uint16_t credits_requested;
447 uint32_t out_flags;
448 uint16_t credits_granted = 0;
450 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
451 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
453 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
455 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
457 * In case we already send an async interim
458 * response, we should not grant
459 * credits on the final response.
461 credits_requested = 0;
464 if (credits_requested) {
465 uint16_t modified_credits_requested;
466 uint32_t multiplier;
469 * Split up max_credits into 1/16ths, and then scale
470 * the requested credits by how many 16ths have been
471 * currently granted. Less than 1/16th == grant all
472 * requested (100%), scale down as more have been
473 * granted. Never ask for less than 1 as the client
474 * asked for at least 1. JRA.
477 multiplier = 16 - (((sconn->smb2.credits_granted * 16) / sconn->smb2.max_credits) % 16);
479 modified_credits_requested = (multiplier * credits_requested) / 16;
480 if (modified_credits_requested == 0) {
481 modified_credits_requested = 1;
484 /* Remember what we gave out. */
485 credits_granted = MIN(modified_credits_requested,
486 (sconn->smb2.max_credits - sconn->smb2.credits_granted));
489 if (credits_granted == 0 && sconn->smb2.credits_granted == 0) {
490 /* First negprot packet, or ensure the client credits can
491 never drop to zero. */
492 credits_granted = 1;
495 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
496 sconn->smb2.credits_granted += credits_granted;
498 DEBUG(10,("smb2_set_operation_credit: requested %u, "
499 "granted %u, total granted %u\n",
500 (unsigned int)credits_requested,
501 (unsigned int)credits_granted,
502 (unsigned int)sconn->smb2.credits_granted ));
505 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
506 struct smbd_smb2_request *outreq)
508 int count, idx;
510 count = outreq->out.vector_count;
512 for (idx=1; idx < count; idx += 3) {
513 smb2_set_operation_credit(outreq->sconn,
514 &inreq->in.vector[idx],
515 &outreq->out.vector[idx]);
519 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
521 struct iovec *vector;
522 int count;
523 int idx;
525 count = req->in.vector_count;
526 vector = talloc_zero_array(req, struct iovec, count);
527 if (vector == NULL) {
528 return NT_STATUS_NO_MEMORY;
531 vector[0].iov_base = req->out.nbt_hdr;
532 vector[0].iov_len = 4;
533 SIVAL(req->out.nbt_hdr, 0, 0);
535 for (idx=1; idx < count; idx += 3) {
536 const uint8_t *inhdr = NULL;
537 uint32_t in_flags;
538 uint8_t *outhdr = NULL;
539 uint8_t *outbody = NULL;
540 uint32_t next_command_ofs = 0;
541 struct iovec *current = &vector[idx];
543 if ((idx + 3) < count) {
544 /* we have a next command -
545 * setup for the error case. */
546 next_command_ofs = SMB2_HDR_BODY + 9;
549 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
550 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
552 outhdr = talloc_zero_array(vector, uint8_t,
553 OUTVEC_ALLOC_SIZE);
554 if (outhdr == NULL) {
555 return NT_STATUS_NO_MEMORY;
558 outbody = outhdr + SMB2_HDR_BODY;
560 current[0].iov_base = (void *)outhdr;
561 current[0].iov_len = SMB2_HDR_BODY;
563 current[1].iov_base = (void *)outbody;
564 current[1].iov_len = 8;
566 current[2].iov_base = NULL;
567 current[2].iov_len = 0;
569 /* setup the SMB2 header */
570 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
571 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
572 SSVAL(outhdr, SMB2_HDR_EPOCH, 0);
573 SIVAL(outhdr, SMB2_HDR_STATUS,
574 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
575 SSVAL(outhdr, SMB2_HDR_OPCODE,
576 SVAL(inhdr, SMB2_HDR_OPCODE));
577 SIVAL(outhdr, SMB2_HDR_FLAGS,
578 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
579 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
580 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
581 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
582 SIVAL(outhdr, SMB2_HDR_PID,
583 IVAL(inhdr, SMB2_HDR_PID));
584 SIVAL(outhdr, SMB2_HDR_TID,
585 IVAL(inhdr, SMB2_HDR_TID));
586 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
587 BVAL(inhdr, SMB2_HDR_SESSION_ID));
588 memset(outhdr + SMB2_HDR_SIGNATURE, 0, 16);
590 /* setup error body header */
591 SSVAL(outbody, 0x00, 0x08 + 1);
592 SSVAL(outbody, 0x02, 0);
593 SIVAL(outbody, 0x04, 0);
596 req->out.vector = vector;
597 req->out.vector_count = count;
599 /* setup the length of the NBT packet */
600 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
602 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
604 return NT_STATUS_OK;
607 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
608 const char *reason,
609 const char *location)
611 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
612 reason, location));
613 exit_server_cleanly(reason);
616 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
617 struct iovec *outvec,
618 const struct iovec *srcvec)
620 /* vec[0] is always boilerplate and must
621 * be allocated with size OUTVEC_ALLOC_SIZE. */
623 outvec[0].iov_base = talloc_memdup(ctx,
624 srcvec[0].iov_base,
625 OUTVEC_ALLOC_SIZE);
626 if (!outvec[0].iov_base) {
627 return false;
629 outvec[0].iov_len = SMB2_HDR_BODY;
632 * If this is a "standard" vec[1] of length 8,
633 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
634 * then duplicate this. Else use talloc_memdup().
637 if (srcvec[1].iov_len == 8 &&
638 srcvec[1].iov_base ==
639 ((uint8_t *)srcvec[0].iov_base) +
640 SMB2_HDR_BODY) {
641 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
642 SMB2_HDR_BODY;
643 outvec[1].iov_len = 8;
644 } else {
645 outvec[1].iov_base = talloc_memdup(ctx,
646 srcvec[1].iov_base,
647 srcvec[1].iov_len);
648 if (!outvec[1].iov_base) {
649 return false;
651 outvec[1].iov_len = srcvec[1].iov_len;
655 * If this is a "standard" vec[2] of length 1,
656 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
657 * then duplicate this. Else use talloc_memdup().
660 if (srcvec[2].iov_base &&
661 srcvec[2].iov_len) {
662 if (srcvec[2].iov_base ==
663 ((uint8_t *)srcvec[0].iov_base) +
664 (OUTVEC_ALLOC_SIZE - 1) &&
665 srcvec[2].iov_len == 1) {
666 /* Common SMB2 error packet case. */
667 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
668 (OUTVEC_ALLOC_SIZE - 1);
669 } else {
670 outvec[2].iov_base = talloc_memdup(ctx,
671 srcvec[2].iov_base,
672 srcvec[2].iov_len);
673 if (!outvec[2].iov_base) {
674 return false;
677 outvec[2].iov_len = srcvec[2].iov_len;
678 } else {
679 outvec[2].iov_base = NULL;
680 outvec[2].iov_len = 0;
682 return true;
685 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
687 struct smbd_smb2_request *newreq = NULL;
688 struct iovec *outvec = NULL;
689 int count = req->out.vector_count;
690 int i;
692 newreq = smbd_smb2_request_allocate(req->sconn);
693 if (!newreq) {
694 return NULL;
697 newreq->sconn = req->sconn;
698 newreq->session = req->session;
699 newreq->do_signing = req->do_signing;
700 newreq->current_idx = req->current_idx;
701 newreq->async = false;
702 newreq->cancelled = false;
703 /* Note we are leaving:
704 ->tcon
705 ->smb1req
706 ->compat_chain_fsp
707 uninitialized as NULL here as
708 they're not used in the interim
709 response code. JRA. */
711 outvec = talloc_zero_array(newreq, struct iovec, count);
712 if (!outvec) {
713 TALLOC_FREE(newreq);
714 return NULL;
716 newreq->out.vector = outvec;
717 newreq->out.vector_count = count;
719 /* Setup the outvec's identically to req. */
720 outvec[0].iov_base = newreq->out.nbt_hdr;
721 outvec[0].iov_len = 4;
722 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
724 /* Setup the vectors identically to the ones in req. */
725 for (i = 1; i < count; i += 3) {
726 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
727 break;
731 if (i < count) {
732 /* Alloc failed. */
733 TALLOC_FREE(newreq);
734 return NULL;
737 smb2_setup_nbt_length(newreq->out.vector,
738 newreq->out.vector_count);
740 return newreq;
743 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
745 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
747 int i = 0;
748 uint8_t *outhdr = NULL;
749 struct smbd_smb2_request *nreq = NULL;
751 /* Create a new smb2 request we'll use
752 for the interim return. */
753 nreq = dup_smb2_req(req);
754 if (!nreq) {
755 return NT_STATUS_NO_MEMORY;
758 /* Lose the last 3 out vectors. They're the
759 ones we'll be using for the async reply. */
760 nreq->out.vector_count -= 3;
762 smb2_setup_nbt_length(nreq->out.vector,
763 nreq->out.vector_count);
765 /* Step back to the previous reply. */
766 i = nreq->current_idx - 3;
767 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
768 /* And end the chain. */
769 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
771 /* Calculate outgoing credits */
772 smb2_calculate_credits(req, nreq);
774 /* Re-sign if needed. */
775 if (nreq->do_signing) {
776 NTSTATUS status;
777 status = smb2_signing_sign_pdu(nreq->session->session_key,
778 &nreq->out.vector[i], 3);
779 if (!NT_STATUS_IS_OK(status)) {
780 return status;
783 if (DEBUGLEVEL >= 10) {
784 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
785 (unsigned int)nreq->current_idx );
786 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
787 (unsigned int)nreq->out.vector_count );
788 print_req_vectors(nreq);
790 nreq->subreq = tstream_writev_queue_send(nreq,
791 nreq->sconn->smb2.event_ctx,
792 nreq->sconn->smb2.stream,
793 nreq->sconn->smb2.send_queue,
794 nreq->out.vector,
795 nreq->out.vector_count);
797 if (nreq->subreq == NULL) {
798 return NT_STATUS_NO_MEMORY;
801 tevent_req_set_callback(nreq->subreq,
802 smbd_smb2_request_writev_done,
803 nreq);
805 return NT_STATUS_OK;
808 struct smbd_smb2_request_pending_state {
809 struct smbd_server_connection *sconn;
810 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
811 struct iovec vector[3];
814 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
816 struct smbd_smb2_request_pending_state *state =
817 tevent_req_callback_data(subreq,
818 struct smbd_smb2_request_pending_state);
819 struct smbd_server_connection *sconn = state->sconn;
820 int ret;
821 int sys_errno;
823 ret = tstream_writev_queue_recv(subreq, &sys_errno);
824 TALLOC_FREE(subreq);
825 if (ret == -1) {
826 NTSTATUS status = map_nt_error_from_unix(sys_errno);
827 smbd_server_connection_terminate(sconn, nt_errstr(status));
828 return;
831 TALLOC_FREE(state);
834 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
835 struct tevent_req *subreq)
837 NTSTATUS status;
838 struct smbd_smb2_request_pending_state *state = NULL;
839 int i = req->current_idx;
840 uint8_t *reqhdr = NULL;
841 uint8_t *hdr = NULL;
842 uint8_t *body = NULL;
843 uint32_t flags = 0;
844 uint64_t message_id = 0;
845 uint64_t async_id = 0;
846 struct iovec *outvec = NULL;
848 if (!tevent_req_is_in_progress(subreq)) {
849 return NT_STATUS_OK;
852 req->subreq = subreq;
853 subreq = NULL;
855 if (req->async) {
856 /* We're already async. */
857 return NT_STATUS_OK;
860 if (req->in.vector_count > i + 3) {
862 * We're trying to go async in a compound
863 * request chain. This is not allowed.
864 * Cancel the outstanding request.
866 tevent_req_cancel(req->subreq);
867 return smbd_smb2_request_error(req,
868 NT_STATUS_INSUFFICIENT_RESOURCES);
871 if (DEBUGLEVEL >= 10) {
872 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
873 (unsigned int)req->current_idx );
874 print_req_vectors(req);
877 if (req->out.vector_count > 4) {
878 /* This is a compound reply. We
879 * must do an interim response
880 * followed by the async response
881 * to match W2K8R2.
883 status = smb2_send_async_interim_response(req);
884 if (!NT_STATUS_IS_OK(status)) {
885 return status;
889 * We're splitting off the last SMB2
890 * request in a compound set, and the
891 * smb2_send_async_interim_response()
892 * call above just sent all the replies
893 * for the previous SMB2 requests in
894 * this compound set. So we're no longer
895 * in the "compound_related_in_progress"
896 * state, and this is no longer a compound
897 * request.
899 req->compound_related = false;
900 req->sconn->smb2.compound_related_in_progress = false;
903 /* Don't return an intermediate packet on a pipe read/write. */
904 if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
905 return NT_STATUS_OK;
908 reqhdr = (uint8_t *)req->out.vector[i].iov_base;
909 flags = (IVAL(reqhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
910 message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
911 async_id = message_id; /* keep it simple for now... */
914 * What we send is identical to a smbd_smb2_request_error
915 * packet with an error status of STATUS_PENDING. Make use
916 * of this fact sometime when refactoring. JRA.
919 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
920 if (state == NULL) {
921 return NT_STATUS_NO_MEMORY;
923 state->sconn = req->sconn;
925 state->vector[0].iov_base = (void *)state->buf;
926 state->vector[0].iov_len = 4;
928 state->vector[1].iov_base = state->buf + 4;
929 state->vector[1].iov_len = SMB2_HDR_BODY;
931 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
932 state->vector[2].iov_len = 9;
934 smb2_setup_nbt_length(state->vector, 3);
936 hdr = (uint8_t *)state->vector[1].iov_base;
937 body = (uint8_t *)state->vector[2].iov_base;
939 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
940 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
941 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
942 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
943 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(reqhdr, SMB2_HDR_OPCODE));
945 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
946 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
947 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
948 SBVAL(hdr, SMB2_HDR_PID, async_id);
949 SBVAL(hdr, SMB2_HDR_SESSION_ID,
950 BVAL(reqhdr, SMB2_HDR_SESSION_ID));
951 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
953 SSVAL(body, 0x00, 0x08 + 1);
955 SCVAL(body, 0x02, 0);
956 SCVAL(body, 0x03, 0);
957 SIVAL(body, 0x04, 0);
958 /* Match W2K8R2... */
959 SCVAL(body, 0x08, 0x21);
961 /* Ensure we correctly go through crediting. Grant
962 the credits now, and zero credits on the final
963 response. */
964 smb2_set_operation_credit(req->sconn,
965 &req->in.vector[i],
966 &state->vector[1]);
968 if (req->do_signing) {
969 status = smb2_signing_sign_pdu(req->session->session_key,
970 &state->vector[1], 2);
971 if (!NT_STATUS_IS_OK(status)) {
972 return status;
976 subreq = tstream_writev_queue_send(state,
977 req->sconn->smb2.event_ctx,
978 req->sconn->smb2.stream,
979 req->sconn->smb2.send_queue,
980 state->vector,
983 if (subreq == NULL) {
984 return NT_STATUS_NO_MEMORY;
987 tevent_req_set_callback(subreq,
988 smbd_smb2_request_pending_writev_done,
989 state);
991 /* Note we're going async with this request. */
992 req->async = true;
995 * Now manipulate req so that the outstanding async request
996 * is the only one left in the struct smbd_smb2_request.
999 if (req->current_idx == 1) {
1000 /* There was only one. */
1001 goto out;
1004 /* Re-arrange the in.vectors. */
1005 req->in.vector[1] = req->in.vector[i];
1006 req->in.vector[2] = req->in.vector[i+1];
1007 req->in.vector[3] = req->in.vector[i+2];
1008 req->in.vector_count = 4;
1009 /* Reset the new in size. */
1010 smb2_setup_nbt_length(req->in.vector, 4);
1012 /* Now recreate the out.vectors. */
1013 outvec = talloc_zero_array(req, struct iovec, 4);
1014 if (!outvec) {
1015 return NT_STATUS_NO_MEMORY;
1018 /* 0 is always boilerplate and must
1019 * be of size 4 for the length field. */
1021 outvec[0].iov_base = req->out.nbt_hdr;
1022 outvec[0].iov_len = 4;
1023 SIVAL(req->out.nbt_hdr, 0, 0);
1025 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
1026 return NT_STATUS_NO_MEMORY;
1029 TALLOC_FREE(req->out.vector);
1031 req->out.vector = outvec;
1033 req->current_idx = 1;
1034 req->out.vector_count = 4;
1036 out:
1038 smb2_setup_nbt_length(req->out.vector,
1039 req->out.vector_count);
1041 /* Ensure our final reply matches the interim one. */
1042 reqhdr = (uint8_t *)req->out.vector[1].iov_base;
1043 SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1044 SBVAL(reqhdr, SMB2_HDR_PID, async_id);
1047 const uint8_t *inhdr =
1048 (const uint8_t *)req->in.vector[1].iov_base;
1049 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1050 "going async\n",
1051 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1052 (unsigned long long)async_id ));
1054 return NT_STATUS_OK;
1057 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1059 struct smbd_server_connection *sconn = req->sconn;
1060 struct smbd_smb2_request *cur;
1061 const uint8_t *inhdr;
1062 int i = req->current_idx;
1063 uint32_t flags;
1064 uint64_t search_message_id;
1065 uint64_t search_async_id;
1066 uint64_t found_id;
1068 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1070 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1071 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1072 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1075 * we don't need the request anymore
1076 * cancel requests never have a response
1078 DLIST_REMOVE(req->sconn->smb2.requests, req);
1079 TALLOC_FREE(req);
1081 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1082 const uint8_t *outhdr;
1083 uint64_t message_id;
1084 uint64_t async_id;
1086 i = cur->current_idx;
1088 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1090 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1091 async_id = BVAL(outhdr, SMB2_HDR_PID);
1093 if (flags & SMB2_HDR_FLAG_ASYNC) {
1094 if (search_async_id == async_id) {
1095 found_id = async_id;
1096 break;
1098 } else {
1099 if (search_message_id == message_id) {
1100 found_id = message_id;
1101 break;
1106 if (cur && cur->subreq) {
1107 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1108 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1109 "cancel opcode[%s] mid %llu\n",
1110 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1111 (unsigned long long)found_id ));
1112 tevent_req_cancel(cur->subreq);
1115 return NT_STATUS_OK;
1118 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1120 const uint8_t *inhdr;
1121 int i = req->current_idx;
1122 uint16_t opcode;
1123 uint32_t flags;
1124 uint64_t mid;
1125 NTSTATUS status;
1126 NTSTATUS session_status;
1127 uint32_t allowed_flags;
1128 NTSTATUS return_value;
1130 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1132 /* TODO: verify more things */
1134 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1135 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1136 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1137 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1138 smb2_opcode_name(opcode),
1139 (unsigned long long)mid));
1141 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1142 SMB2_HDR_FLAG_SIGNED |
1143 SMB2_HDR_FLAG_DFS;
1144 if (opcode == SMB2_OP_CANCEL) {
1145 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1147 if ((flags & ~allowed_flags) != 0) {
1148 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1152 * Check if the client provided a valid session id,
1153 * if so smbd_smb2_request_check_session() calls
1154 * set_current_user_info().
1156 * As some command don't require a valid session id
1157 * we defer the check of the session_status
1159 session_status = smbd_smb2_request_check_session(req);
1161 req->do_signing = false;
1162 if (flags & SMB2_HDR_FLAG_SIGNED) {
1163 if (!NT_STATUS_IS_OK(session_status)) {
1164 return smbd_smb2_request_error(req, session_status);
1167 req->do_signing = true;
1168 status = smb2_signing_check_pdu(req->session->session_key,
1169 &req->in.vector[i], 3);
1170 if (!NT_STATUS_IS_OK(status)) {
1171 return smbd_smb2_request_error(req, status);
1173 } else if (req->session && req->session->do_signing) {
1174 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1177 if (flags & SMB2_HDR_FLAG_CHAINED) {
1179 * This check is mostly for giving the correct error code
1180 * for compounded requests.
1182 * TODO: we may need to move this after the session
1183 * and tcon checks.
1185 if (!NT_STATUS_IS_OK(req->next_status)) {
1186 return smbd_smb2_request_error(req, req->next_status);
1188 } else {
1189 req->compat_chain_fsp = NULL;
1192 if (req->compound_related) {
1193 req->sconn->smb2.compound_related_in_progress = true;
1196 switch (opcode) {
1197 case SMB2_OP_NEGPROT:
1198 /* This call needs to be run as root */
1199 change_to_root_user();
1202 START_PROFILE(smb2_negprot);
1203 return_value = smbd_smb2_request_process_negprot(req);
1204 END_PROFILE(smb2_negprot);
1206 break;
1208 case SMB2_OP_SESSSETUP:
1209 /* This call needs to be run as root */
1210 change_to_root_user();
1213 START_PROFILE(smb2_sesssetup);
1214 return_value = smbd_smb2_request_process_sesssetup(req);
1215 END_PROFILE(smb2_sesssetup);
1217 break;
1219 case SMB2_OP_LOGOFF:
1220 if (!NT_STATUS_IS_OK(session_status)) {
1221 return_value = smbd_smb2_request_error(req, session_status);
1222 break;
1225 /* This call needs to be run as root */
1226 change_to_root_user();
1229 START_PROFILE(smb2_logoff);
1230 return_value = smbd_smb2_request_process_logoff(req);
1231 END_PROFILE(smb2_logoff);
1233 break;
1235 case SMB2_OP_TCON:
1236 if (!NT_STATUS_IS_OK(session_status)) {
1237 return_value = smbd_smb2_request_error(req, session_status);
1238 break;
1242 * This call needs to be run as root.
1244 * smbd_smb2_request_process_tcon()
1245 * calls make_connection_snum(), which will call
1246 * change_to_user(), when needed.
1248 change_to_root_user();
1251 START_PROFILE(smb2_tcon);
1252 return_value = smbd_smb2_request_process_tcon(req);
1253 END_PROFILE(smb2_tcon);
1255 break;
1257 case SMB2_OP_TDIS:
1258 if (!NT_STATUS_IS_OK(session_status)) {
1259 return_value = smbd_smb2_request_error(req, session_status);
1260 break;
1263 * This call needs to be run as user.
1265 * smbd_smb2_request_check_tcon()
1266 * calls change_to_user() on success.
1268 status = smbd_smb2_request_check_tcon(req);
1269 if (!NT_STATUS_IS_OK(status)) {
1270 return_value = smbd_smb2_request_error(req, status);
1271 break;
1273 /* This call needs to be run as root */
1274 change_to_root_user();
1278 START_PROFILE(smb2_tdis);
1279 return_value = smbd_smb2_request_process_tdis(req);
1280 END_PROFILE(smb2_tdis);
1282 break;
1284 case SMB2_OP_CREATE:
1285 if (!NT_STATUS_IS_OK(session_status)) {
1286 return_value = smbd_smb2_request_error(req, session_status);
1287 break;
1290 * This call needs to be run as user.
1292 * smbd_smb2_request_check_tcon()
1293 * calls change_to_user() on success.
1295 status = smbd_smb2_request_check_tcon(req);
1296 if (!NT_STATUS_IS_OK(status)) {
1297 return_value = smbd_smb2_request_error(req, status);
1298 break;
1302 START_PROFILE(smb2_create);
1303 return_value = smbd_smb2_request_process_create(req);
1304 END_PROFILE(smb2_create);
1306 break;
1308 case SMB2_OP_CLOSE:
1309 if (!NT_STATUS_IS_OK(session_status)) {
1310 return_value = smbd_smb2_request_error(req, session_status);
1311 break;
1314 * This call needs to be run as user.
1316 * smbd_smb2_request_check_tcon()
1317 * calls change_to_user() on success.
1319 status = smbd_smb2_request_check_tcon(req);
1320 if (!NT_STATUS_IS_OK(status)) {
1321 return_value = smbd_smb2_request_error(req, status);
1322 break;
1326 START_PROFILE(smb2_close);
1327 return_value = smbd_smb2_request_process_close(req);
1328 END_PROFILE(smb2_close);
1330 break;
1332 case SMB2_OP_FLUSH:
1333 if (!NT_STATUS_IS_OK(session_status)) {
1334 return_value = smbd_smb2_request_error(req, session_status);
1335 break;
1338 * This call needs to be run as user.
1340 * smbd_smb2_request_check_tcon()
1341 * calls change_to_user() on success.
1343 status = smbd_smb2_request_check_tcon(req);
1344 if (!NT_STATUS_IS_OK(status)) {
1345 return_value = smbd_smb2_request_error(req, status);
1346 break;
1350 START_PROFILE(smb2_flush);
1351 return_value = smbd_smb2_request_process_flush(req);
1352 END_PROFILE(smb2_flush);
1354 break;
1356 case SMB2_OP_READ:
1357 if (!NT_STATUS_IS_OK(session_status)) {
1358 return_value = smbd_smb2_request_error(req, session_status);
1359 break;
1362 * This call needs to be run as user.
1364 * smbd_smb2_request_check_tcon()
1365 * calls change_to_user() on success.
1367 status = smbd_smb2_request_check_tcon(req);
1368 if (!NT_STATUS_IS_OK(status)) {
1369 return_value = smbd_smb2_request_error(req, status);
1370 break;
1374 START_PROFILE(smb2_read);
1375 return_value = smbd_smb2_request_process_read(req);
1376 END_PROFILE(smb2_read);
1378 break;
1380 case SMB2_OP_WRITE:
1381 if (!NT_STATUS_IS_OK(session_status)) {
1382 return_value = smbd_smb2_request_error(req, session_status);
1383 break;
1386 * This call needs to be run as user.
1388 * smbd_smb2_request_check_tcon()
1389 * calls change_to_user() on success.
1391 status = smbd_smb2_request_check_tcon(req);
1392 if (!NT_STATUS_IS_OK(status)) {
1393 return_value = smbd_smb2_request_error(req, status);
1394 break;
1398 START_PROFILE(smb2_write);
1399 return_value = smbd_smb2_request_process_write(req);
1400 END_PROFILE(smb2_write);
1402 break;
1404 case SMB2_OP_LOCK:
1405 if (!NT_STATUS_IS_OK(session_status)) {
1406 /* Too ugly to live ? JRA. */
1407 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1408 session_status = NT_STATUS_FILE_CLOSED;
1410 return_value = smbd_smb2_request_error(req, session_status);
1411 break;
1414 * This call needs to be run as user.
1416 * smbd_smb2_request_check_tcon()
1417 * calls change_to_user() on success.
1419 status = smbd_smb2_request_check_tcon(req);
1420 if (!NT_STATUS_IS_OK(status)) {
1421 /* Too ugly to live ? JRA. */
1422 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1423 status = NT_STATUS_FILE_CLOSED;
1425 return_value = smbd_smb2_request_error(req, status);
1426 break;
1430 START_PROFILE(smb2_lock);
1431 return_value = smbd_smb2_request_process_lock(req);
1432 END_PROFILE(smb2_lock);
1434 break;
1436 case SMB2_OP_IOCTL:
1437 if (!NT_STATUS_IS_OK(session_status)) {
1438 return_value = smbd_smb2_request_error(req, session_status);
1439 break;
1442 * This call needs to be run as user.
1444 * smbd_smb2_request_check_tcon()
1445 * calls change_to_user() on success.
1447 status = smbd_smb2_request_check_tcon(req);
1448 if (!NT_STATUS_IS_OK(status)) {
1449 return_value = smbd_smb2_request_error(req, status);
1450 break;
1454 START_PROFILE(smb2_ioctl);
1455 return_value = smbd_smb2_request_process_ioctl(req);
1456 END_PROFILE(smb2_ioctl);
1458 break;
1460 case SMB2_OP_CANCEL:
1462 * This call needs to be run as root
1464 * That is what we also do in the SMB1 case.
1466 change_to_root_user();
1469 START_PROFILE(smb2_cancel);
1470 return_value = smbd_smb2_request_process_cancel(req);
1471 END_PROFILE(smb2_cancel);
1473 break;
1475 case SMB2_OP_KEEPALIVE:
1476 /* This call needs to be run as root */
1477 change_to_root_user();
1480 START_PROFILE(smb2_keepalive);
1481 return_value = smbd_smb2_request_process_keepalive(req);
1482 END_PROFILE(smb2_keepalive);
1484 break;
1486 case SMB2_OP_FIND:
1487 if (!NT_STATUS_IS_OK(session_status)) {
1488 return_value = smbd_smb2_request_error(req, session_status);
1489 break;
1492 * This call needs to be run as user.
1494 * smbd_smb2_request_check_tcon()
1495 * calls change_to_user() on success.
1497 status = smbd_smb2_request_check_tcon(req);
1498 if (!NT_STATUS_IS_OK(status)) {
1499 return_value = smbd_smb2_request_error(req, status);
1500 break;
1504 START_PROFILE(smb2_find);
1505 return_value = smbd_smb2_request_process_find(req);
1506 END_PROFILE(smb2_find);
1508 break;
1510 case SMB2_OP_NOTIFY:
1511 if (!NT_STATUS_IS_OK(session_status)) {
1512 return_value = smbd_smb2_request_error(req, session_status);
1513 break;
1516 * This call needs to be run as user.
1518 * smbd_smb2_request_check_tcon()
1519 * calls change_to_user() on success.
1521 status = smbd_smb2_request_check_tcon(req);
1522 if (!NT_STATUS_IS_OK(status)) {
1523 return_value = smbd_smb2_request_error(req, status);
1524 break;
1528 START_PROFILE(smb2_notify);
1529 return_value = smbd_smb2_request_process_notify(req);
1530 END_PROFILE(smb2_notify);
1532 break;
1534 case SMB2_OP_GETINFO:
1535 if (!NT_STATUS_IS_OK(session_status)) {
1536 return_value = smbd_smb2_request_error(req, session_status);
1537 break;
1540 * This call needs to be run as user.
1542 * smbd_smb2_request_check_tcon()
1543 * calls change_to_user() on success.
1545 status = smbd_smb2_request_check_tcon(req);
1546 if (!NT_STATUS_IS_OK(status)) {
1547 return_value = smbd_smb2_request_error(req, status);
1548 break;
1552 START_PROFILE(smb2_getinfo);
1553 return_value = smbd_smb2_request_process_getinfo(req);
1554 END_PROFILE(smb2_getinfo);
1556 break;
1558 case SMB2_OP_SETINFO:
1559 if (!NT_STATUS_IS_OK(session_status)) {
1560 return_value = smbd_smb2_request_error(req, session_status);
1561 break;
1564 * This call needs to be run as user.
1566 * smbd_smb2_request_check_tcon()
1567 * calls change_to_user() on success.
1569 status = smbd_smb2_request_check_tcon(req);
1570 if (!NT_STATUS_IS_OK(status)) {
1571 return_value = smbd_smb2_request_error(req, status);
1572 break;
1576 START_PROFILE(smb2_setinfo);
1577 return_value = smbd_smb2_request_process_setinfo(req);
1578 END_PROFILE(smb2_setinfo);
1580 break;
1582 case SMB2_OP_BREAK:
1583 if (!NT_STATUS_IS_OK(session_status)) {
1584 return_value = smbd_smb2_request_error(req, session_status);
1585 break;
1588 * This call needs to be run as user.
1590 * smbd_smb2_request_check_tcon()
1591 * calls change_to_user() on success.
1593 status = smbd_smb2_request_check_tcon(req);
1594 if (!NT_STATUS_IS_OK(status)) {
1595 return_value = smbd_smb2_request_error(req, status);
1596 break;
1600 START_PROFILE(smb2_break);
1601 return_value = smbd_smb2_request_process_break(req);
1602 END_PROFILE(smb2_break);
1604 break;
1606 default:
1607 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1608 break;
1610 return return_value;
1613 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1615 struct tevent_req *subreq;
1616 int i = req->current_idx;
1618 req->subreq = NULL;
1620 req->current_idx += 3;
1622 if (req->current_idx < req->out.vector_count) {
1624 * We must process the remaining compound
1625 * SMB2 requests before any new incoming SMB2
1626 * requests. This is because incoming SMB2
1627 * requests may include a cancel for a
1628 * compound request we haven't processed
1629 * yet.
1631 struct tevent_immediate *im = tevent_create_immediate(req);
1632 if (!im) {
1633 return NT_STATUS_NO_MEMORY;
1635 tevent_schedule_immediate(im,
1636 req->sconn->smb2.event_ctx,
1637 smbd_smb2_request_dispatch_immediate,
1638 req);
1639 return NT_STATUS_OK;
1642 if (req->compound_related) {
1643 req->sconn->smb2.compound_related_in_progress = false;
1646 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1648 /* Set credit for this operation (zero credits if this
1649 is a final reply for an async operation). */
1650 smb2_set_operation_credit(req->sconn,
1651 &req->in.vector[i],
1652 &req->out.vector[i]);
1654 if (req->do_signing) {
1655 NTSTATUS status;
1656 status = smb2_signing_sign_pdu(req->session->session_key,
1657 &req->out.vector[i], 3);
1658 if (!NT_STATUS_IS_OK(status)) {
1659 return status;
1663 if (DEBUGLEVEL >= 10) {
1664 dbgtext("smbd_smb2_request_reply: sending...\n");
1665 print_req_vectors(req);
1668 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1669 if (req->out.vector_count == 4 &&
1670 req->out.vector[3].iov_base == NULL &&
1671 req->out.vector[3].iov_len != 0) {
1672 /* Dynamic part is NULL. Chop it off,
1673 We're going to send it via sendfile. */
1674 req->out.vector_count -= 1;
1677 subreq = tstream_writev_queue_send(req,
1678 req->sconn->smb2.event_ctx,
1679 req->sconn->smb2.stream,
1680 req->sconn->smb2.send_queue,
1681 req->out.vector,
1682 req->out.vector_count);
1683 if (subreq == NULL) {
1684 return NT_STATUS_NO_MEMORY;
1686 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1688 * We're done with this request -
1689 * move it off the "being processed" queue.
1691 DLIST_REMOVE(req->sconn->smb2.requests, req);
1693 return NT_STATUS_OK;
1696 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
1698 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1699 struct tevent_immediate *im,
1700 void *private_data)
1702 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1703 struct smbd_smb2_request);
1704 struct smbd_server_connection *sconn = req->sconn;
1705 NTSTATUS status;
1707 TALLOC_FREE(im);
1709 if (DEBUGLEVEL >= 10) {
1710 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1711 req->current_idx, req->in.vector_count));
1712 print_req_vectors(req);
1715 status = smbd_smb2_request_dispatch(req);
1716 if (!NT_STATUS_IS_OK(status)) {
1717 smbd_server_connection_terminate(sconn, nt_errstr(status));
1718 return;
1721 status = smbd_smb2_request_next_incoming(sconn);
1722 if (!NT_STATUS_IS_OK(status)) {
1723 smbd_server_connection_terminate(sconn, nt_errstr(status));
1724 return;
1728 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1730 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1731 struct smbd_smb2_request);
1732 struct smbd_server_connection *sconn = req->sconn;
1733 int ret;
1734 int sys_errno;
1735 NTSTATUS status;
1737 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1738 TALLOC_FREE(subreq);
1739 TALLOC_FREE(req);
1740 if (ret == -1) {
1741 status = map_nt_error_from_unix(sys_errno);
1742 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1743 nt_errstr(status)));
1744 smbd_server_connection_terminate(sconn, nt_errstr(status));
1745 return;
1748 status = smbd_smb2_request_next_incoming(sconn);
1749 if (!NT_STATUS_IS_OK(status)) {
1750 smbd_server_connection_terminate(sconn, nt_errstr(status));
1751 return;
1755 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1756 NTSTATUS status,
1757 DATA_BLOB body, DATA_BLOB *dyn,
1758 const char *location)
1760 uint8_t *outhdr;
1761 int i = req->current_idx;
1762 uint32_t next_command_ofs;
1764 DEBUG(10,("smbd_smb2_request_done_ex: "
1765 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1766 i, nt_errstr(status), (unsigned int)body.length,
1767 dyn ? "yes": "no",
1768 (unsigned int)(dyn ? dyn->length : 0),
1769 location));
1771 if (body.length < 2) {
1772 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1775 if ((body.length % 2) != 0) {
1776 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1779 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1781 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1782 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1784 req->out.vector[i+1].iov_base = (void *)body.data;
1785 req->out.vector[i+1].iov_len = body.length;
1787 if (dyn) {
1788 req->out.vector[i+2].iov_base = (void *)dyn->data;
1789 req->out.vector[i+2].iov_len = dyn->length;
1790 } else {
1791 req->out.vector[i+2].iov_base = NULL;
1792 req->out.vector[i+2].iov_len = 0;
1795 /* see if we need to recalculate the offset to the next response */
1796 if (next_command_ofs > 0) {
1797 next_command_ofs = SMB2_HDR_BODY;
1798 next_command_ofs += req->out.vector[i+1].iov_len;
1799 next_command_ofs += req->out.vector[i+2].iov_len;
1802 if ((next_command_ofs % 8) != 0) {
1803 size_t pad_size = 8 - (next_command_ofs % 8);
1804 if (req->out.vector[i+2].iov_len == 0) {
1806 * if the dyn buffer is empty
1807 * we can use it to add padding
1809 uint8_t *pad;
1811 pad = talloc_zero_array(req->out.vector,
1812 uint8_t, pad_size);
1813 if (pad == NULL) {
1814 return smbd_smb2_request_error(req,
1815 NT_STATUS_NO_MEMORY);
1818 req->out.vector[i+2].iov_base = (void *)pad;
1819 req->out.vector[i+2].iov_len = pad_size;
1820 } else {
1822 * For now we copy the dynamic buffer
1823 * and add the padding to the new buffer
1825 size_t old_size;
1826 uint8_t *old_dyn;
1827 size_t new_size;
1828 uint8_t *new_dyn;
1830 old_size = req->out.vector[i+2].iov_len;
1831 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
1833 new_size = old_size + pad_size;
1834 new_dyn = talloc_zero_array(req->out.vector,
1835 uint8_t, new_size);
1836 if (new_dyn == NULL) {
1837 return smbd_smb2_request_error(req,
1838 NT_STATUS_NO_MEMORY);
1841 memcpy(new_dyn, old_dyn, old_size);
1842 memset(new_dyn + old_size, 0, pad_size);
1844 req->out.vector[i+2].iov_base = (void *)new_dyn;
1845 req->out.vector[i+2].iov_len = new_size;
1847 next_command_ofs += pad_size;
1850 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1852 return smbd_smb2_request_reply(req);
1855 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
1856 NTSTATUS status,
1857 DATA_BLOB *info,
1858 const char *location)
1860 DATA_BLOB body;
1861 int i = req->current_idx;
1862 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
1864 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1865 i, nt_errstr(status), info ? " +info" : "",
1866 location));
1868 body.data = outhdr + SMB2_HDR_BODY;
1869 body.length = 8;
1870 SSVAL(body.data, 0, 9);
1872 if (info) {
1873 SIVAL(body.data, 0x04, info->length);
1874 } else {
1875 /* Allocated size of req->out.vector[i].iov_base
1876 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
1877 * 1 byte without having to do an alloc.
1879 info = talloc_zero_array(req->out.vector,
1880 DATA_BLOB,
1882 if (!info) {
1883 return NT_STATUS_NO_MEMORY;
1885 info->data = ((uint8_t *)outhdr) +
1886 OUTVEC_ALLOC_SIZE - 1;
1887 info->length = 1;
1888 SCVAL(info->data, 0, 0);
1892 * if a request fails, all other remaining
1893 * compounded requests should fail too
1895 req->next_status = NT_STATUS_INVALID_PARAMETER;
1897 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
1901 struct smbd_smb2_send_oplock_break_state {
1902 struct smbd_server_connection *sconn;
1903 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
1904 struct iovec vector;
1907 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
1909 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
1910 uint64_t file_id_persistent,
1911 uint64_t file_id_volatile,
1912 uint8_t oplock_level)
1914 struct smbd_smb2_send_oplock_break_state *state;
1915 struct tevent_req *subreq;
1916 uint8_t *hdr;
1917 uint8_t *body;
1919 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
1920 if (state == NULL) {
1921 return NT_STATUS_NO_MEMORY;
1923 state->sconn = sconn;
1925 state->vector.iov_base = (void *)state->buf;
1926 state->vector.iov_len = sizeof(state->buf);
1928 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
1929 hdr = state->buf + 4;
1930 body = hdr + SMB2_HDR_BODY;
1932 SIVAL(hdr, 0, SMB2_MAGIC);
1933 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1934 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1935 SIVAL(hdr, SMB2_HDR_STATUS, 0);
1936 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
1937 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
1938 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
1939 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1940 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
1941 SIVAL(hdr, SMB2_HDR_PID, 0);
1942 SIVAL(hdr, SMB2_HDR_TID, 0);
1943 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
1944 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
1946 SSVAL(body, 0x00, 0x18);
1948 SCVAL(body, 0x02, oplock_level);
1949 SCVAL(body, 0x03, 0); /* reserved */
1950 SIVAL(body, 0x04, 0); /* reserved */
1951 SBVAL(body, 0x08, file_id_persistent);
1952 SBVAL(body, 0x10, file_id_volatile);
1954 subreq = tstream_writev_queue_send(state,
1955 sconn->smb2.event_ctx,
1956 sconn->smb2.stream,
1957 sconn->smb2.send_queue,
1958 &state->vector, 1);
1959 if (subreq == NULL) {
1960 return NT_STATUS_NO_MEMORY;
1962 tevent_req_set_callback(subreq,
1963 smbd_smb2_oplock_break_writev_done,
1964 state);
1966 return NT_STATUS_OK;
1969 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
1971 struct smbd_smb2_send_oplock_break_state *state =
1972 tevent_req_callback_data(subreq,
1973 struct smbd_smb2_send_oplock_break_state);
1974 struct smbd_server_connection *sconn = state->sconn;
1975 int ret;
1976 int sys_errno;
1978 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1979 TALLOC_FREE(subreq);
1980 if (ret == -1) {
1981 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1982 smbd_server_connection_terminate(sconn, nt_errstr(status));
1983 return;
1986 TALLOC_FREE(state);
1989 struct smbd_smb2_request_read_state {
1990 size_t missing;
1991 bool asked_for_header;
1992 struct smbd_smb2_request *smb2_req;
1995 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1996 void *private_data,
1997 TALLOC_CTX *mem_ctx,
1998 struct iovec **_vector,
1999 size_t *_count);
2000 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2002 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2003 struct tevent_context *ev,
2004 struct smbd_server_connection *sconn)
2006 struct tevent_req *req;
2007 struct smbd_smb2_request_read_state *state;
2008 struct tevent_req *subreq;
2010 req = tevent_req_create(mem_ctx, &state,
2011 struct smbd_smb2_request_read_state);
2012 if (req == NULL) {
2013 return NULL;
2015 state->missing = 0;
2016 state->asked_for_header = false;
2018 state->smb2_req = smbd_smb2_request_allocate(state);
2019 if (tevent_req_nomem(state->smb2_req, req)) {
2020 return tevent_req_post(req, ev);
2022 state->smb2_req->sconn = sconn;
2024 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2025 sconn->smb2.recv_queue,
2026 smbd_smb2_request_next_vector,
2027 state);
2028 if (tevent_req_nomem(subreq, req)) {
2029 return tevent_req_post(req, ev);
2031 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2033 return req;
2036 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2037 void *private_data,
2038 TALLOC_CTX *mem_ctx,
2039 struct iovec **_vector,
2040 size_t *_count)
2042 struct smbd_smb2_request_read_state *state =
2043 talloc_get_type_abort(private_data,
2044 struct smbd_smb2_request_read_state);
2045 struct smbd_smb2_request *req = state->smb2_req;
2046 struct iovec *vector;
2047 int idx = req->in.vector_count;
2048 size_t len = 0;
2049 uint8_t *buf = NULL;
2051 if (req->in.vector_count == 0) {
2053 * first we need to get the NBT header
2055 req->in.vector = talloc_array(req, struct iovec,
2056 req->in.vector_count + 1);
2057 if (req->in.vector == NULL) {
2058 return -1;
2060 req->in.vector_count += 1;
2062 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2063 req->in.vector[idx].iov_len = 4;
2065 vector = talloc_array(mem_ctx, struct iovec, 1);
2066 if (vector == NULL) {
2067 return -1;
2070 vector[0] = req->in.vector[idx];
2072 *_vector = vector;
2073 *_count = 1;
2074 return 0;
2077 if (req->in.vector_count == 1) {
2079 * Now we analyze the NBT header
2081 state->missing = smb2_len(req->in.vector[0].iov_base);
2083 if (state->missing == 0) {
2084 /* if there're no remaining bytes, we're done */
2085 *_vector = NULL;
2086 *_count = 0;
2087 return 0;
2090 req->in.vector = talloc_realloc(req, req->in.vector,
2091 struct iovec,
2092 req->in.vector_count + 1);
2093 if (req->in.vector == NULL) {
2094 return -1;
2096 req->in.vector_count += 1;
2098 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2100 * it's a special NBT message,
2101 * so get all remaining bytes
2103 len = state->missing;
2104 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2106 * it's an invalid message, just read what we can get
2107 * and let the caller handle the error
2109 len = state->missing;
2110 } else {
2112 * We assume it's a SMB2 request,
2113 * and we first get the header and the
2114 * first 2 bytes (the struct size) of the body
2116 len = SMB2_HDR_BODY + 2;
2118 state->asked_for_header = true;
2121 state->missing -= len;
2123 buf = talloc_array(req->in.vector, uint8_t, len);
2124 if (buf == NULL) {
2125 return -1;
2128 req->in.vector[idx].iov_base = (void *)buf;
2129 req->in.vector[idx].iov_len = len;
2131 vector = talloc_array(mem_ctx, struct iovec, 1);
2132 if (vector == NULL) {
2133 return -1;
2136 vector[0] = req->in.vector[idx];
2138 *_vector = vector;
2139 *_count = 1;
2140 return 0;
2143 if (state->missing == 0) {
2144 /* if there're no remaining bytes, we're done */
2145 *_vector = NULL;
2146 *_count = 0;
2147 return 0;
2150 if (state->asked_for_header) {
2151 const uint8_t *hdr;
2152 size_t full_size;
2153 size_t next_command_ofs;
2154 size_t body_size;
2155 uint8_t *body;
2156 size_t dyn_size;
2157 uint8_t *dyn;
2158 bool invalid = false;
2160 state->asked_for_header = false;
2163 * We got the SMB2 header and the first 2 bytes
2164 * of the body. We fix the size to just the header
2165 * and manually copy the 2 first bytes to the body section
2167 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2168 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2170 /* allocate vectors for body and dynamic areas */
2171 req->in.vector = talloc_realloc(req, req->in.vector,
2172 struct iovec,
2173 req->in.vector_count + 2);
2174 if (req->in.vector == NULL) {
2175 return -1;
2177 req->in.vector_count += 2;
2179 full_size = state->missing + SMB2_HDR_BODY + 2;
2180 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2181 body_size = SVAL(hdr, SMB2_HDR_BODY);
2183 if (next_command_ofs != 0) {
2184 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2186 * this is invalid, just return a zero
2187 * body and let the caller deal with the error
2189 invalid = true;
2190 } else if (next_command_ofs > full_size) {
2192 * this is invalid, just return a zero
2193 * body and let the caller deal with the error
2195 invalid = true;
2196 } else {
2197 full_size = next_command_ofs;
2201 if (!invalid) {
2202 if (body_size < 2) {
2204 * this is invalid, just return a zero
2205 * body and let the caller deal with the error
2207 invalid = true;
2210 if ((body_size % 2) != 0) {
2211 body_size -= 1;
2214 if (body_size > (full_size - SMB2_HDR_BODY)) {
2216 * this is invalid, just return a zero
2217 * body and let the caller deal with the error
2219 invalid = true;
2223 if (invalid) {
2224 /* the caller should check this */
2225 body_size = 2;
2228 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2230 state->missing -= (body_size - 2) + dyn_size;
2232 body = talloc_array(req->in.vector, uint8_t, body_size);
2233 if (body == NULL) {
2234 return -1;
2237 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2238 if (dyn == NULL) {
2239 return -1;
2242 req->in.vector[idx].iov_base = (void *)body;
2243 req->in.vector[idx].iov_len = body_size;
2244 req->in.vector[idx+1].iov_base = (void *)dyn;
2245 req->in.vector[idx+1].iov_len = dyn_size;
2247 vector = talloc_array(mem_ctx, struct iovec, 2);
2248 if (vector == NULL) {
2249 return -1;
2253 * the first 2 bytes of the body were already fetched
2254 * together with the header
2256 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2257 vector[0].iov_base = body + 2;
2258 vector[0].iov_len = body_size - 2;
2260 vector[1] = req->in.vector[idx+1];
2262 *_vector = vector;
2263 *_count = 2;
2264 return 0;
2268 * when we endup here, we're looking for a new SMB2 request
2269 * next. And we ask for its header and the first 2 bytes of
2270 * the body (like we did for the first SMB2 request).
2273 req->in.vector = talloc_realloc(req, req->in.vector,
2274 struct iovec,
2275 req->in.vector_count + 1);
2276 if (req->in.vector == NULL) {
2277 return -1;
2279 req->in.vector_count += 1;
2282 * We assume it's a SMB2 request,
2283 * and we first get the header and the
2284 * first 2 bytes (the struct size) of the body
2286 len = SMB2_HDR_BODY + 2;
2288 if (len > state->missing) {
2289 /* let the caller handle the error */
2290 len = state->missing;
2293 state->missing -= len;
2294 state->asked_for_header = true;
2296 buf = talloc_array(req->in.vector, uint8_t, len);
2297 if (buf == NULL) {
2298 return -1;
2301 req->in.vector[idx].iov_base = (void *)buf;
2302 req->in.vector[idx].iov_len = len;
2304 vector = talloc_array(mem_ctx, struct iovec, 1);
2305 if (vector == NULL) {
2306 return -1;
2309 vector[0] = req->in.vector[idx];
2311 *_vector = vector;
2312 *_count = 1;
2313 return 0;
2316 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2318 struct tevent_req *req =
2319 tevent_req_callback_data(subreq,
2320 struct tevent_req);
2321 int ret;
2322 int sys_errno;
2323 NTSTATUS status;
2325 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2326 if (ret == -1) {
2327 status = map_nt_error_from_unix(sys_errno);
2328 tevent_req_nterror(req, status);
2329 return;
2332 tevent_req_done(req);
2335 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2336 TALLOC_CTX *mem_ctx,
2337 struct smbd_smb2_request **_smb2_req)
2339 struct smbd_smb2_request_read_state *state =
2340 tevent_req_data(req,
2341 struct smbd_smb2_request_read_state);
2342 NTSTATUS status;
2344 if (tevent_req_is_nterror(req, &status)) {
2345 tevent_req_received(req);
2346 return status;
2349 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2350 *_smb2_req = state->smb2_req;
2351 tevent_req_received(req);
2352 return NT_STATUS_OK;
2355 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2357 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2359 size_t max_send_queue_len;
2360 size_t cur_send_queue_len;
2361 struct tevent_req *subreq;
2363 if (sconn->smb2.compound_related_in_progress) {
2365 * Can't read another until the related
2366 * compound is done.
2368 return NT_STATUS_OK;
2371 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2373 * if there is already a smbd_smb2_request_read
2374 * pending, we are done.
2376 return NT_STATUS_OK;
2379 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2380 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2382 if (cur_send_queue_len > max_send_queue_len) {
2384 * if we have a lot of requests to send,
2385 * we wait until they are on the wire until we
2386 * ask for the next request.
2388 return NT_STATUS_OK;
2391 /* ask for the next request */
2392 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2393 if (subreq == NULL) {
2394 return NT_STATUS_NO_MEMORY;
2396 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2398 return NT_STATUS_OK;
2401 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2402 const uint8_t *inbuf, size_t size)
2404 NTSTATUS status;
2405 struct smbd_smb2_request *req = NULL;
2407 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2408 (unsigned int)size));
2410 status = smbd_initialize_smb2(sconn);
2411 if (!NT_STATUS_IS_OK(status)) {
2412 smbd_server_connection_terminate(sconn, nt_errstr(status));
2413 return;
2416 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2417 if (!NT_STATUS_IS_OK(status)) {
2418 smbd_server_connection_terminate(sconn, nt_errstr(status));
2419 return;
2422 status = smbd_smb2_request_setup_out(req);
2423 if (!NT_STATUS_IS_OK(status)) {
2424 smbd_server_connection_terminate(sconn, nt_errstr(status));
2425 return;
2428 status = smbd_smb2_request_dispatch(req);
2429 if (!NT_STATUS_IS_OK(status)) {
2430 smbd_server_connection_terminate(sconn, nt_errstr(status));
2431 return;
2434 status = smbd_smb2_request_next_incoming(sconn);
2435 if (!NT_STATUS_IS_OK(status)) {
2436 smbd_server_connection_terminate(sconn, nt_errstr(status));
2437 return;
2440 sconn->num_requests++;
2443 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2445 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2446 struct smbd_server_connection);
2447 NTSTATUS status;
2448 struct smbd_smb2_request *req = NULL;
2450 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2451 TALLOC_FREE(subreq);
2452 if (!NT_STATUS_IS_OK(status)) {
2453 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2454 nt_errstr(status)));
2455 smbd_server_connection_terminate(sconn, nt_errstr(status));
2456 return;
2459 if (req->in.nbt_hdr[0] != 0x00) {
2460 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2461 req->in.nbt_hdr[0]));
2462 TALLOC_FREE(req);
2463 goto next;
2466 req->current_idx = 1;
2468 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2469 req->current_idx, req->in.vector_count));
2471 status = smbd_smb2_request_validate(req);
2472 if (!NT_STATUS_IS_OK(status)) {
2473 smbd_server_connection_terminate(sconn, nt_errstr(status));
2474 return;
2477 status = smbd_smb2_request_setup_out(req);
2478 if (!NT_STATUS_IS_OK(status)) {
2479 smbd_server_connection_terminate(sconn, nt_errstr(status));
2480 return;
2483 status = smbd_smb2_request_dispatch(req);
2484 if (!NT_STATUS_IS_OK(status)) {
2485 smbd_server_connection_terminate(sconn, nt_errstr(status));
2486 return;
2489 next:
2490 status = smbd_smb2_request_next_incoming(sconn);
2491 if (!NT_STATUS_IS_OK(status)) {
2492 smbd_server_connection_terminate(sconn, nt_errstr(status));
2493 return;
2496 sconn->num_requests++;
2498 /* The timeout_processing function isn't run nearly
2499 often enough to implement 'max log size' without
2500 overrunning the size of the file by many megabytes.
2501 This is especially true if we are running at debug
2502 level 10. Checking every 50 SMB2s is a nice
2503 tradeoff of performance vs log file size overrun. */
2505 if ((sconn->num_requests % 50) == 0 &&
2506 need_to_check_log_size()) {
2507 change_to_root_user();
2508 check_log_size();