Fix bug 8429 - Compound SMB2 requests on an IPC connection can corrupt the reply...
[Samba.git] / source3 / smbd / smb2_server.c
blob41ef607e4761c20df106231060f9adf3f499fa45
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;
361 count = req->in.vector_count;
363 if (count < 4) {
364 /* It's not a SMB2 request */
365 return NT_STATUS_INVALID_PARAMETER;
368 for (idx=1; idx < count; idx += 3) {
369 const uint8_t *inhdr = NULL;
370 uint32_t flags;
372 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
373 return NT_STATUS_INVALID_PARAMETER;
376 if (req->in.vector[idx+1].iov_len < 2) {
377 return NT_STATUS_INVALID_PARAMETER;
380 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
382 /* Check the SMB2 header */
383 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
384 return NT_STATUS_INVALID_PARAMETER;
387 if (!smb2_validate_message_id(req->sconn, inhdr)) {
388 return NT_STATUS_INVALID_PARAMETER;
391 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
392 if (idx == 1) {
394 * the 1st request should never have the
395 * SMB2_HDR_FLAG_CHAINED flag set
397 if (flags & SMB2_HDR_FLAG_CHAINED) {
398 req->next_status = NT_STATUS_INVALID_PARAMETER;
399 return NT_STATUS_OK;
401 } else if (idx == 4) {
403 * the 2nd request triggers related vs. unrelated
404 * compounded requests
406 if (flags & SMB2_HDR_FLAG_CHAINED) {
407 req->compound_related = true;
409 } else if (idx > 4) {
410 #if 0
412 * It seems the this tests are wrong
413 * see the SMB2-COMPOUND test
417 * all other requests should match the 2nd one
419 if (flags & SMB2_HDR_FLAG_CHAINED) {
420 if (!req->compound_related) {
421 req->next_status =
422 NT_STATUS_INVALID_PARAMETER;
423 return NT_STATUS_OK;
425 } else {
426 if (req->compound_related) {
427 req->next_status =
428 NT_STATUS_INVALID_PARAMETER;
429 return NT_STATUS_OK;
432 #endif
436 return NT_STATUS_OK;
439 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
440 const struct iovec *in_vector,
441 struct iovec *out_vector)
443 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
444 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
445 uint16_t credits_requested;
446 uint32_t out_flags;
447 uint16_t credits_granted = 0;
449 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
450 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
452 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
454 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
456 * In case we already send an async interim
457 * response, we should not grant
458 * credits on the final response.
460 credits_requested = 0;
463 if (credits_requested) {
464 uint16_t modified_credits_requested;
465 uint32_t multiplier;
468 * Split up max_credits into 1/16ths, and then scale
469 * the requested credits by how many 16ths have been
470 * currently granted. Less than 1/16th == grant all
471 * requested (100%), scale down as more have been
472 * granted. Never ask for less than 1 as the client
473 * asked for at least 1. JRA.
476 multiplier = 16 - (((sconn->smb2.credits_granted * 16) / sconn->smb2.max_credits) % 16);
478 modified_credits_requested = (multiplier * credits_requested) / 16;
479 if (modified_credits_requested == 0) {
480 modified_credits_requested = 1;
483 /* Remember what we gave out. */
484 credits_granted = MIN(modified_credits_requested,
485 (sconn->smb2.max_credits - sconn->smb2.credits_granted));
488 if (credits_granted == 0 && sconn->smb2.credits_granted == 0) {
489 /* First negprot packet, or ensure the client credits can
490 never drop to zero. */
491 credits_granted = 1;
494 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
495 sconn->smb2.credits_granted += credits_granted;
497 DEBUG(10,("smb2_set_operation_credit: requested %u, "
498 "granted %u, total granted %u\n",
499 (unsigned int)credits_requested,
500 (unsigned int)credits_granted,
501 (unsigned int)sconn->smb2.credits_granted ));
504 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
505 struct smbd_smb2_request *outreq)
507 int count, idx;
509 count = outreq->out.vector_count;
511 for (idx=1; idx < count; idx += 3) {
512 smb2_set_operation_credit(outreq->sconn,
513 &inreq->in.vector[idx],
514 &outreq->out.vector[idx]);
518 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
520 struct iovec *vector;
521 int count;
522 int idx;
524 count = req->in.vector_count;
525 vector = talloc_zero_array(req, struct iovec, count);
526 if (vector == NULL) {
527 return NT_STATUS_NO_MEMORY;
530 vector[0].iov_base = req->out.nbt_hdr;
531 vector[0].iov_len = 4;
532 SIVAL(req->out.nbt_hdr, 0, 0);
534 for (idx=1; idx < count; idx += 3) {
535 const uint8_t *inhdr = NULL;
536 uint32_t in_flags;
537 uint8_t *outhdr = NULL;
538 uint8_t *outbody = NULL;
539 uint32_t next_command_ofs = 0;
540 struct iovec *current = &vector[idx];
542 if ((idx + 3) < count) {
543 /* we have a next command -
544 * setup for the error case. */
545 next_command_ofs = SMB2_HDR_BODY + 9;
548 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
549 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
551 outhdr = talloc_zero_array(vector, uint8_t,
552 OUTVEC_ALLOC_SIZE);
553 if (outhdr == NULL) {
554 return NT_STATUS_NO_MEMORY;
557 outbody = outhdr + SMB2_HDR_BODY;
559 current[0].iov_base = (void *)outhdr;
560 current[0].iov_len = SMB2_HDR_BODY;
562 current[1].iov_base = (void *)outbody;
563 current[1].iov_len = 8;
565 current[2].iov_base = NULL;
566 current[2].iov_len = 0;
568 /* setup the SMB2 header */
569 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
570 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
571 SSVAL(outhdr, SMB2_HDR_EPOCH, 0);
572 SIVAL(outhdr, SMB2_HDR_STATUS,
573 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
574 SSVAL(outhdr, SMB2_HDR_OPCODE,
575 SVAL(inhdr, SMB2_HDR_OPCODE));
576 SIVAL(outhdr, SMB2_HDR_FLAGS,
577 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
578 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
579 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
580 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
581 SIVAL(outhdr, SMB2_HDR_PID,
582 IVAL(inhdr, SMB2_HDR_PID));
583 SIVAL(outhdr, SMB2_HDR_TID,
584 IVAL(inhdr, SMB2_HDR_TID));
585 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
586 BVAL(inhdr, SMB2_HDR_SESSION_ID));
587 memset(outhdr + SMB2_HDR_SIGNATURE, 0, 16);
589 /* setup error body header */
590 SSVAL(outbody, 0x00, 0x08 + 1);
591 SSVAL(outbody, 0x02, 0);
592 SIVAL(outbody, 0x04, 0);
595 req->out.vector = vector;
596 req->out.vector_count = count;
598 /* setup the length of the NBT packet */
599 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
601 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
603 return NT_STATUS_OK;
606 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
607 const char *reason,
608 const char *location)
610 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
611 reason, location));
612 exit_server_cleanly(reason);
615 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
616 struct iovec *outvec,
617 const struct iovec *srcvec)
619 /* vec[0] is always boilerplate and must
620 * be allocated with size OUTVEC_ALLOC_SIZE. */
622 outvec[0].iov_base = talloc_memdup(ctx,
623 srcvec[0].iov_base,
624 OUTVEC_ALLOC_SIZE);
625 if (!outvec[0].iov_base) {
626 return false;
628 outvec[0].iov_len = SMB2_HDR_BODY;
631 * If this is a "standard" vec[1] of length 8,
632 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
633 * then duplicate this. Else use talloc_memdup().
636 if (srcvec[1].iov_len == 8 &&
637 srcvec[1].iov_base ==
638 ((uint8_t *)srcvec[0].iov_base) +
639 SMB2_HDR_BODY) {
640 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
641 SMB2_HDR_BODY;
642 outvec[1].iov_len = 8;
643 } else {
644 outvec[1].iov_base = talloc_memdup(ctx,
645 srcvec[1].iov_base,
646 srcvec[1].iov_len);
647 if (!outvec[1].iov_base) {
648 return false;
650 outvec[1].iov_len = srcvec[1].iov_len;
654 * If this is a "standard" vec[2] of length 1,
655 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
656 * then duplicate this. Else use talloc_memdup().
659 if (srcvec[2].iov_base &&
660 srcvec[2].iov_len) {
661 if (srcvec[2].iov_base ==
662 ((uint8_t *)srcvec[0].iov_base) +
663 (OUTVEC_ALLOC_SIZE - 1) &&
664 srcvec[2].iov_len == 1) {
665 /* Common SMB2 error packet case. */
666 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
667 (OUTVEC_ALLOC_SIZE - 1);
668 } else {
669 outvec[2].iov_base = talloc_memdup(ctx,
670 srcvec[2].iov_base,
671 srcvec[2].iov_len);
672 if (!outvec[2].iov_base) {
673 return false;
676 outvec[2].iov_len = srcvec[2].iov_len;
677 } else {
678 outvec[2].iov_base = NULL;
679 outvec[2].iov_len = 0;
681 return true;
684 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
686 struct smbd_smb2_request *newreq = NULL;
687 struct iovec *outvec = NULL;
688 int count = req->out.vector_count;
689 int i;
691 newreq = smbd_smb2_request_allocate(req->sconn);
692 if (!newreq) {
693 return NULL;
696 newreq->sconn = req->sconn;
697 newreq->session = req->session;
698 newreq->do_signing = req->do_signing;
699 newreq->current_idx = req->current_idx;
700 newreq->async = false;
701 newreq->cancelled = false;
702 /* Note we are leaving:
703 ->tcon
704 ->smb1req
705 ->compat_chain_fsp
706 uninitialized as NULL here as
707 they're not used in the interim
708 response code. JRA. */
710 outvec = talloc_zero_array(newreq, struct iovec, count);
711 if (!outvec) {
712 TALLOC_FREE(newreq);
713 return NULL;
715 newreq->out.vector = outvec;
716 newreq->out.vector_count = count;
718 /* Setup the outvec's identically to req. */
719 outvec[0].iov_base = newreq->out.nbt_hdr;
720 outvec[0].iov_len = 4;
721 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
723 /* Setup the vectors identically to the ones in req. */
724 for (i = 1; i < count; i += 3) {
725 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
726 break;
730 if (i < count) {
731 /* Alloc failed. */
732 TALLOC_FREE(newreq);
733 return NULL;
736 smb2_setup_nbt_length(newreq->out.vector,
737 newreq->out.vector_count);
739 return newreq;
742 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
744 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
746 int i = 0;
747 uint8_t *outhdr = NULL;
748 struct smbd_smb2_request *nreq = NULL;
750 /* Create a new smb2 request we'll use
751 for the interim return. */
752 nreq = dup_smb2_req(req);
753 if (!nreq) {
754 return NT_STATUS_NO_MEMORY;
757 /* Lose the last 3 out vectors. They're the
758 ones we'll be using for the async reply. */
759 nreq->out.vector_count -= 3;
761 smb2_setup_nbt_length(nreq->out.vector,
762 nreq->out.vector_count);
764 /* Step back to the previous reply. */
765 i = nreq->current_idx - 3;
766 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
767 /* And end the chain. */
768 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
770 /* Calculate outgoing credits */
771 smb2_calculate_credits(req, nreq);
773 /* Re-sign if needed. */
774 if (nreq->do_signing) {
775 NTSTATUS status;
776 status = smb2_signing_sign_pdu(nreq->session->session_key,
777 &nreq->out.vector[i], 3);
778 if (!NT_STATUS_IS_OK(status)) {
779 return status;
782 if (DEBUGLEVEL >= 10) {
783 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
784 (unsigned int)nreq->current_idx );
785 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
786 (unsigned int)nreq->out.vector_count );
787 print_req_vectors(nreq);
789 nreq->subreq = tstream_writev_queue_send(nreq,
790 nreq->sconn->smb2.event_ctx,
791 nreq->sconn->smb2.stream,
792 nreq->sconn->smb2.send_queue,
793 nreq->out.vector,
794 nreq->out.vector_count);
796 if (nreq->subreq == NULL) {
797 return NT_STATUS_NO_MEMORY;
800 tevent_req_set_callback(nreq->subreq,
801 smbd_smb2_request_writev_done,
802 nreq);
804 return NT_STATUS_OK;
807 struct smbd_smb2_request_pending_state {
808 struct smbd_server_connection *sconn;
809 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
810 struct iovec vector[3];
813 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
815 struct smbd_smb2_request_pending_state *state =
816 tevent_req_callback_data(subreq,
817 struct smbd_smb2_request_pending_state);
818 struct smbd_server_connection *sconn = state->sconn;
819 int ret;
820 int sys_errno;
822 ret = tstream_writev_queue_recv(subreq, &sys_errno);
823 TALLOC_FREE(subreq);
824 if (ret == -1) {
825 NTSTATUS status = map_nt_error_from_unix(sys_errno);
826 smbd_server_connection_terminate(sconn, nt_errstr(status));
827 return;
830 TALLOC_FREE(state);
833 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
834 struct tevent_req *subreq)
836 NTSTATUS status;
837 struct smbd_smb2_request_pending_state *state = NULL;
838 int i = req->current_idx;
839 uint8_t *reqhdr = NULL;
840 uint8_t *hdr = NULL;
841 uint8_t *body = NULL;
842 uint32_t flags = 0;
843 uint64_t message_id = 0;
844 uint64_t async_id = 0;
845 struct iovec *outvec = NULL;
847 if (!tevent_req_is_in_progress(subreq)) {
848 return NT_STATUS_OK;
851 req->subreq = subreq;
852 subreq = NULL;
854 if (req->async) {
855 /* We're already async. */
856 return NT_STATUS_OK;
859 if (req->in.vector_count > i + 3) {
861 * We're trying to go async in a compound
862 * request chain. This is not allowed.
863 * Cancel the outstanding request.
865 tevent_req_cancel(req->subreq);
866 return smbd_smb2_request_error(req,
867 NT_STATUS_INSUFFICIENT_RESOURCES);
870 if (DEBUGLEVEL >= 10) {
871 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
872 (unsigned int)req->current_idx );
873 print_req_vectors(req);
876 if (req->out.vector_count > 4) {
877 /* This is a compound reply. We
878 * must do an interim response
879 * followed by the async response
880 * to match W2K8R2.
882 status = smb2_send_async_interim_response(req);
883 if (!NT_STATUS_IS_OK(status)) {
884 return status;
888 * We're splitting off the last SMB2
889 * request in a compound set, and the
890 * smb2_send_async_interim_response()
891 * call above just sent all the replies
892 * for the previous SMB2 requests in
893 * this compound set. So we're no longer
894 * in the "compound_related_in_progress"
895 * state, and this is no longer a compound
896 * request.
898 req->compound_related = false;
899 req->sconn->smb2.compound_related_in_progress = false;
902 /* Don't return an intermediate packet on a pipe read/write. */
903 if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
904 goto ipc_out;
907 reqhdr = (uint8_t *)req->out.vector[i].iov_base;
908 flags = (IVAL(reqhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
909 message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
910 async_id = message_id; /* keep it simple for now... */
913 * What we send is identical to a smbd_smb2_request_error
914 * packet with an error status of STATUS_PENDING. Make use
915 * of this fact sometime when refactoring. JRA.
918 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
919 if (state == NULL) {
920 return NT_STATUS_NO_MEMORY;
922 state->sconn = req->sconn;
924 state->vector[0].iov_base = (void *)state->buf;
925 state->vector[0].iov_len = 4;
927 state->vector[1].iov_base = state->buf + 4;
928 state->vector[1].iov_len = SMB2_HDR_BODY;
930 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
931 state->vector[2].iov_len = 9;
933 smb2_setup_nbt_length(state->vector, 3);
935 hdr = (uint8_t *)state->vector[1].iov_base;
936 body = (uint8_t *)state->vector[2].iov_base;
938 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
939 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
940 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
941 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
942 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(reqhdr, SMB2_HDR_OPCODE));
944 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
945 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
946 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
947 SBVAL(hdr, SMB2_HDR_PID, async_id);
948 SBVAL(hdr, SMB2_HDR_SESSION_ID,
949 BVAL(reqhdr, SMB2_HDR_SESSION_ID));
950 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
952 SSVAL(body, 0x00, 0x08 + 1);
954 SCVAL(body, 0x02, 0);
955 SCVAL(body, 0x03, 0);
956 SIVAL(body, 0x04, 0);
957 /* Match W2K8R2... */
958 SCVAL(body, 0x08, 0x21);
960 /* Ensure we correctly go through crediting. Grant
961 the credits now, and zero credits on the final
962 response. */
963 smb2_set_operation_credit(req->sconn,
964 &req->in.vector[i],
965 &state->vector[1]);
967 if (req->do_signing) {
968 status = smb2_signing_sign_pdu(req->session->session_key,
969 &state->vector[1], 2);
970 if (!NT_STATUS_IS_OK(status)) {
971 return status;
975 subreq = tstream_writev_queue_send(state,
976 req->sconn->smb2.event_ctx,
977 req->sconn->smb2.stream,
978 req->sconn->smb2.send_queue,
979 state->vector,
982 if (subreq == NULL) {
983 return NT_STATUS_NO_MEMORY;
986 tevent_req_set_callback(subreq,
987 smbd_smb2_request_pending_writev_done,
988 state);
990 /* Note we're going async with this request. */
991 req->async = true;
993 ipc_out:
996 * Now manipulate req so that the outstanding async request
997 * is the only one left in the struct smbd_smb2_request.
1000 if (req->current_idx == 1) {
1001 /* There was only one. */
1002 goto out;
1005 /* Re-arrange the in.vectors. */
1006 req->in.vector[1] = req->in.vector[i];
1007 req->in.vector[2] = req->in.vector[i+1];
1008 req->in.vector[3] = req->in.vector[i+2];
1009 req->in.vector_count = 4;
1010 /* Reset the new in size. */
1011 smb2_setup_nbt_length(req->in.vector, 4);
1013 /* Now recreate the out.vectors. */
1014 outvec = talloc_zero_array(req, struct iovec, 4);
1015 if (!outvec) {
1016 return NT_STATUS_NO_MEMORY;
1019 /* 0 is always boilerplate and must
1020 * be of size 4 for the length field. */
1022 outvec[0].iov_base = req->out.nbt_hdr;
1023 outvec[0].iov_len = 4;
1024 SIVAL(req->out.nbt_hdr, 0, 0);
1026 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
1027 return NT_STATUS_NO_MEMORY;
1030 TALLOC_FREE(req->out.vector);
1032 req->out.vector = outvec;
1034 req->current_idx = 1;
1035 req->out.vector_count = 4;
1037 out:
1039 smb2_setup_nbt_length(req->out.vector,
1040 req->out.vector_count);
1042 if (req->async) {
1043 /* Ensure our final reply matches the interim one. */
1044 reqhdr = (uint8_t *)req->out.vector[1].iov_base;
1045 SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1046 SBVAL(reqhdr, SMB2_HDR_PID, async_id);
1049 const uint8_t *inhdr =
1050 (const uint8_t *)req->in.vector[1].iov_base;
1051 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1052 "going async\n",
1053 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1054 (unsigned long long)async_id ));
1058 return NT_STATUS_OK;
1061 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1063 struct smbd_server_connection *sconn = req->sconn;
1064 struct smbd_smb2_request *cur;
1065 const uint8_t *inhdr;
1066 int i = req->current_idx;
1067 uint32_t flags;
1068 uint64_t search_message_id;
1069 uint64_t search_async_id;
1070 uint64_t found_id;
1072 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1074 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1075 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1076 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1079 * we don't need the request anymore
1080 * cancel requests never have a response
1082 DLIST_REMOVE(req->sconn->smb2.requests, req);
1083 TALLOC_FREE(req);
1085 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1086 const uint8_t *outhdr;
1087 uint64_t message_id;
1088 uint64_t async_id;
1090 i = cur->current_idx;
1092 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1094 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1095 async_id = BVAL(outhdr, SMB2_HDR_PID);
1097 if (flags & SMB2_HDR_FLAG_ASYNC) {
1098 if (search_async_id == async_id) {
1099 found_id = async_id;
1100 break;
1102 } else {
1103 if (search_message_id == message_id) {
1104 found_id = message_id;
1105 break;
1110 if (cur && cur->subreq) {
1111 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1112 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1113 "cancel opcode[%s] mid %llu\n",
1114 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1115 (unsigned long long)found_id ));
1116 tevent_req_cancel(cur->subreq);
1119 return NT_STATUS_OK;
1122 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1124 const uint8_t *inhdr;
1125 int i = req->current_idx;
1126 uint16_t opcode;
1127 uint32_t flags;
1128 uint64_t mid;
1129 NTSTATUS status;
1130 NTSTATUS session_status;
1131 uint32_t allowed_flags;
1132 NTSTATUS return_value;
1134 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1136 /* TODO: verify more things */
1138 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1139 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1140 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1141 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1142 smb2_opcode_name(opcode),
1143 (unsigned long long)mid));
1145 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1146 SMB2_HDR_FLAG_SIGNED |
1147 SMB2_HDR_FLAG_DFS;
1148 if (opcode == SMB2_OP_CANCEL) {
1149 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1151 if ((flags & ~allowed_flags) != 0) {
1152 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1156 * Check if the client provided a valid session id,
1157 * if so smbd_smb2_request_check_session() calls
1158 * set_current_user_info().
1160 * As some command don't require a valid session id
1161 * we defer the check of the session_status
1163 session_status = smbd_smb2_request_check_session(req);
1165 req->do_signing = false;
1166 if (flags & SMB2_HDR_FLAG_SIGNED) {
1167 if (!NT_STATUS_IS_OK(session_status)) {
1168 return smbd_smb2_request_error(req, session_status);
1171 req->do_signing = true;
1172 status = smb2_signing_check_pdu(req->session->session_key,
1173 &req->in.vector[i], 3);
1174 if (!NT_STATUS_IS_OK(status)) {
1175 return smbd_smb2_request_error(req, status);
1177 } else if (req->session && req->session->do_signing) {
1178 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1181 if (flags & SMB2_HDR_FLAG_CHAINED) {
1183 * This check is mostly for giving the correct error code
1184 * for compounded requests.
1186 * TODO: we may need to move this after the session
1187 * and tcon checks.
1189 if (!NT_STATUS_IS_OK(req->next_status)) {
1190 return smbd_smb2_request_error(req, req->next_status);
1192 } else {
1193 req->compat_chain_fsp = NULL;
1196 if (req->compound_related) {
1197 req->sconn->smb2.compound_related_in_progress = true;
1200 switch (opcode) {
1201 case SMB2_OP_NEGPROT:
1202 /* This call needs to be run as root */
1203 change_to_root_user();
1206 START_PROFILE(smb2_negprot);
1207 return_value = smbd_smb2_request_process_negprot(req);
1208 END_PROFILE(smb2_negprot);
1210 break;
1212 case SMB2_OP_SESSSETUP:
1213 /* This call needs to be run as root */
1214 change_to_root_user();
1217 START_PROFILE(smb2_sesssetup);
1218 return_value = smbd_smb2_request_process_sesssetup(req);
1219 END_PROFILE(smb2_sesssetup);
1221 break;
1223 case SMB2_OP_LOGOFF:
1224 if (!NT_STATUS_IS_OK(session_status)) {
1225 return_value = smbd_smb2_request_error(req, session_status);
1226 break;
1229 /* This call needs to be run as root */
1230 change_to_root_user();
1233 START_PROFILE(smb2_logoff);
1234 return_value = smbd_smb2_request_process_logoff(req);
1235 END_PROFILE(smb2_logoff);
1237 break;
1239 case SMB2_OP_TCON:
1240 if (!NT_STATUS_IS_OK(session_status)) {
1241 return_value = smbd_smb2_request_error(req, session_status);
1242 break;
1246 * This call needs to be run as root.
1248 * smbd_smb2_request_process_tcon()
1249 * calls make_connection_snum(), which will call
1250 * change_to_user(), when needed.
1252 change_to_root_user();
1255 START_PROFILE(smb2_tcon);
1256 return_value = smbd_smb2_request_process_tcon(req);
1257 END_PROFILE(smb2_tcon);
1259 break;
1261 case SMB2_OP_TDIS:
1262 if (!NT_STATUS_IS_OK(session_status)) {
1263 return_value = smbd_smb2_request_error(req, session_status);
1264 break;
1267 * This call needs to be run as user.
1269 * smbd_smb2_request_check_tcon()
1270 * calls change_to_user() on success.
1272 status = smbd_smb2_request_check_tcon(req);
1273 if (!NT_STATUS_IS_OK(status)) {
1274 return_value = smbd_smb2_request_error(req, status);
1275 break;
1277 /* This call needs to be run as root */
1278 change_to_root_user();
1282 START_PROFILE(smb2_tdis);
1283 return_value = smbd_smb2_request_process_tdis(req);
1284 END_PROFILE(smb2_tdis);
1286 break;
1288 case SMB2_OP_CREATE:
1289 if (!NT_STATUS_IS_OK(session_status)) {
1290 return_value = smbd_smb2_request_error(req, session_status);
1291 break;
1294 * This call needs to be run as user.
1296 * smbd_smb2_request_check_tcon()
1297 * calls change_to_user() on success.
1299 status = smbd_smb2_request_check_tcon(req);
1300 if (!NT_STATUS_IS_OK(status)) {
1301 return_value = smbd_smb2_request_error(req, status);
1302 break;
1306 START_PROFILE(smb2_create);
1307 return_value = smbd_smb2_request_process_create(req);
1308 END_PROFILE(smb2_create);
1310 break;
1312 case SMB2_OP_CLOSE:
1313 if (!NT_STATUS_IS_OK(session_status)) {
1314 return_value = smbd_smb2_request_error(req, session_status);
1315 break;
1318 * This call needs to be run as user.
1320 * smbd_smb2_request_check_tcon()
1321 * calls change_to_user() on success.
1323 status = smbd_smb2_request_check_tcon(req);
1324 if (!NT_STATUS_IS_OK(status)) {
1325 return_value = smbd_smb2_request_error(req, status);
1326 break;
1330 START_PROFILE(smb2_close);
1331 return_value = smbd_smb2_request_process_close(req);
1332 END_PROFILE(smb2_close);
1334 break;
1336 case SMB2_OP_FLUSH:
1337 if (!NT_STATUS_IS_OK(session_status)) {
1338 return_value = smbd_smb2_request_error(req, session_status);
1339 break;
1342 * This call needs to be run as user.
1344 * smbd_smb2_request_check_tcon()
1345 * calls change_to_user() on success.
1347 status = smbd_smb2_request_check_tcon(req);
1348 if (!NT_STATUS_IS_OK(status)) {
1349 return_value = smbd_smb2_request_error(req, status);
1350 break;
1354 START_PROFILE(smb2_flush);
1355 return_value = smbd_smb2_request_process_flush(req);
1356 END_PROFILE(smb2_flush);
1358 break;
1360 case SMB2_OP_READ:
1361 if (!NT_STATUS_IS_OK(session_status)) {
1362 return_value = smbd_smb2_request_error(req, session_status);
1363 break;
1366 * This call needs to be run as user.
1368 * smbd_smb2_request_check_tcon()
1369 * calls change_to_user() on success.
1371 status = smbd_smb2_request_check_tcon(req);
1372 if (!NT_STATUS_IS_OK(status)) {
1373 return_value = smbd_smb2_request_error(req, status);
1374 break;
1378 START_PROFILE(smb2_read);
1379 return_value = smbd_smb2_request_process_read(req);
1380 END_PROFILE(smb2_read);
1382 break;
1384 case SMB2_OP_WRITE:
1385 if (!NT_STATUS_IS_OK(session_status)) {
1386 return_value = smbd_smb2_request_error(req, session_status);
1387 break;
1390 * This call needs to be run as user.
1392 * smbd_smb2_request_check_tcon()
1393 * calls change_to_user() on success.
1395 status = smbd_smb2_request_check_tcon(req);
1396 if (!NT_STATUS_IS_OK(status)) {
1397 return_value = smbd_smb2_request_error(req, status);
1398 break;
1402 START_PROFILE(smb2_write);
1403 return_value = smbd_smb2_request_process_write(req);
1404 END_PROFILE(smb2_write);
1406 break;
1408 case SMB2_OP_LOCK:
1409 if (!NT_STATUS_IS_OK(session_status)) {
1410 /* Too ugly to live ? JRA. */
1411 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1412 session_status = NT_STATUS_FILE_CLOSED;
1414 return_value = smbd_smb2_request_error(req, session_status);
1415 break;
1418 * This call needs to be run as user.
1420 * smbd_smb2_request_check_tcon()
1421 * calls change_to_user() on success.
1423 status = smbd_smb2_request_check_tcon(req);
1424 if (!NT_STATUS_IS_OK(status)) {
1425 /* Too ugly to live ? JRA. */
1426 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1427 status = NT_STATUS_FILE_CLOSED;
1429 return_value = smbd_smb2_request_error(req, status);
1430 break;
1434 START_PROFILE(smb2_lock);
1435 return_value = smbd_smb2_request_process_lock(req);
1436 END_PROFILE(smb2_lock);
1438 break;
1440 case SMB2_OP_IOCTL:
1441 if (!NT_STATUS_IS_OK(session_status)) {
1442 return_value = smbd_smb2_request_error(req, session_status);
1443 break;
1446 * This call needs to be run as user.
1448 * smbd_smb2_request_check_tcon()
1449 * calls change_to_user() on success.
1451 status = smbd_smb2_request_check_tcon(req);
1452 if (!NT_STATUS_IS_OK(status)) {
1453 return_value = smbd_smb2_request_error(req, status);
1454 break;
1458 START_PROFILE(smb2_ioctl);
1459 return_value = smbd_smb2_request_process_ioctl(req);
1460 END_PROFILE(smb2_ioctl);
1462 break;
1464 case SMB2_OP_CANCEL:
1466 * This call needs to be run as root
1468 * That is what we also do in the SMB1 case.
1470 change_to_root_user();
1473 START_PROFILE(smb2_cancel);
1474 return_value = smbd_smb2_request_process_cancel(req);
1475 END_PROFILE(smb2_cancel);
1477 break;
1479 case SMB2_OP_KEEPALIVE:
1480 /* This call needs to be run as root */
1481 change_to_root_user();
1484 START_PROFILE(smb2_keepalive);
1485 return_value = smbd_smb2_request_process_keepalive(req);
1486 END_PROFILE(smb2_keepalive);
1488 break;
1490 case SMB2_OP_FIND:
1491 if (!NT_STATUS_IS_OK(session_status)) {
1492 return_value = smbd_smb2_request_error(req, session_status);
1493 break;
1496 * This call needs to be run as user.
1498 * smbd_smb2_request_check_tcon()
1499 * calls change_to_user() on success.
1501 status = smbd_smb2_request_check_tcon(req);
1502 if (!NT_STATUS_IS_OK(status)) {
1503 return_value = smbd_smb2_request_error(req, status);
1504 break;
1508 START_PROFILE(smb2_find);
1509 return_value = smbd_smb2_request_process_find(req);
1510 END_PROFILE(smb2_find);
1512 break;
1514 case SMB2_OP_NOTIFY:
1515 if (!NT_STATUS_IS_OK(session_status)) {
1516 return_value = smbd_smb2_request_error(req, session_status);
1517 break;
1520 * This call needs to be run as user.
1522 * smbd_smb2_request_check_tcon()
1523 * calls change_to_user() on success.
1525 status = smbd_smb2_request_check_tcon(req);
1526 if (!NT_STATUS_IS_OK(status)) {
1527 return_value = smbd_smb2_request_error(req, status);
1528 break;
1532 START_PROFILE(smb2_notify);
1533 return_value = smbd_smb2_request_process_notify(req);
1534 END_PROFILE(smb2_notify);
1536 break;
1538 case SMB2_OP_GETINFO:
1539 if (!NT_STATUS_IS_OK(session_status)) {
1540 return_value = smbd_smb2_request_error(req, session_status);
1541 break;
1544 * This call needs to be run as user.
1546 * smbd_smb2_request_check_tcon()
1547 * calls change_to_user() on success.
1549 status = smbd_smb2_request_check_tcon(req);
1550 if (!NT_STATUS_IS_OK(status)) {
1551 return_value = smbd_smb2_request_error(req, status);
1552 break;
1556 START_PROFILE(smb2_getinfo);
1557 return_value = smbd_smb2_request_process_getinfo(req);
1558 END_PROFILE(smb2_getinfo);
1560 break;
1562 case SMB2_OP_SETINFO:
1563 if (!NT_STATUS_IS_OK(session_status)) {
1564 return_value = smbd_smb2_request_error(req, session_status);
1565 break;
1568 * This call needs to be run as user.
1570 * smbd_smb2_request_check_tcon()
1571 * calls change_to_user() on success.
1573 status = smbd_smb2_request_check_tcon(req);
1574 if (!NT_STATUS_IS_OK(status)) {
1575 return_value = smbd_smb2_request_error(req, status);
1576 break;
1580 START_PROFILE(smb2_setinfo);
1581 return_value = smbd_smb2_request_process_setinfo(req);
1582 END_PROFILE(smb2_setinfo);
1584 break;
1586 case SMB2_OP_BREAK:
1587 if (!NT_STATUS_IS_OK(session_status)) {
1588 return_value = smbd_smb2_request_error(req, session_status);
1589 break;
1592 * This call needs to be run as user.
1594 * smbd_smb2_request_check_tcon()
1595 * calls change_to_user() on success.
1597 status = smbd_smb2_request_check_tcon(req);
1598 if (!NT_STATUS_IS_OK(status)) {
1599 return_value = smbd_smb2_request_error(req, status);
1600 break;
1604 START_PROFILE(smb2_break);
1605 return_value = smbd_smb2_request_process_break(req);
1606 END_PROFILE(smb2_break);
1608 break;
1610 default:
1611 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1612 break;
1614 return return_value;
1617 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1619 struct tevent_req *subreq;
1620 int i = req->current_idx;
1622 req->subreq = NULL;
1624 req->current_idx += 3;
1626 if (req->current_idx < req->out.vector_count) {
1628 * We must process the remaining compound
1629 * SMB2 requests before any new incoming SMB2
1630 * requests. This is because incoming SMB2
1631 * requests may include a cancel for a
1632 * compound request we haven't processed
1633 * yet.
1635 struct tevent_immediate *im = tevent_create_immediate(req);
1636 if (!im) {
1637 return NT_STATUS_NO_MEMORY;
1639 tevent_schedule_immediate(im,
1640 req->sconn->smb2.event_ctx,
1641 smbd_smb2_request_dispatch_immediate,
1642 req);
1643 return NT_STATUS_OK;
1646 if (req->compound_related) {
1647 req->sconn->smb2.compound_related_in_progress = false;
1650 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1652 /* Set credit for this operation (zero credits if this
1653 is a final reply for an async operation). */
1654 smb2_set_operation_credit(req->sconn,
1655 &req->in.vector[i],
1656 &req->out.vector[i]);
1658 if (req->do_signing) {
1659 NTSTATUS status;
1660 status = smb2_signing_sign_pdu(req->session->session_key,
1661 &req->out.vector[i], 3);
1662 if (!NT_STATUS_IS_OK(status)) {
1663 return status;
1667 if (DEBUGLEVEL >= 10) {
1668 dbgtext("smbd_smb2_request_reply: sending...\n");
1669 print_req_vectors(req);
1672 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1673 if (req->out.vector_count == 4 &&
1674 req->out.vector[3].iov_base == NULL &&
1675 req->out.vector[3].iov_len != 0) {
1676 /* Dynamic part is NULL. Chop it off,
1677 We're going to send it via sendfile. */
1678 req->out.vector_count -= 1;
1681 subreq = tstream_writev_queue_send(req,
1682 req->sconn->smb2.event_ctx,
1683 req->sconn->smb2.stream,
1684 req->sconn->smb2.send_queue,
1685 req->out.vector,
1686 req->out.vector_count);
1687 if (subreq == NULL) {
1688 return NT_STATUS_NO_MEMORY;
1690 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1692 * We're done with this request -
1693 * move it off the "being processed" queue.
1695 DLIST_REMOVE(req->sconn->smb2.requests, req);
1697 return NT_STATUS_OK;
1700 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
1702 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1703 struct tevent_immediate *im,
1704 void *private_data)
1706 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1707 struct smbd_smb2_request);
1708 struct smbd_server_connection *sconn = req->sconn;
1709 NTSTATUS status;
1711 TALLOC_FREE(im);
1713 if (DEBUGLEVEL >= 10) {
1714 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1715 req->current_idx, req->in.vector_count));
1716 print_req_vectors(req);
1719 status = smbd_smb2_request_dispatch(req);
1720 if (!NT_STATUS_IS_OK(status)) {
1721 smbd_server_connection_terminate(sconn, nt_errstr(status));
1722 return;
1725 status = smbd_smb2_request_next_incoming(sconn);
1726 if (!NT_STATUS_IS_OK(status)) {
1727 smbd_server_connection_terminate(sconn, nt_errstr(status));
1728 return;
1732 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1734 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1735 struct smbd_smb2_request);
1736 struct smbd_server_connection *sconn = req->sconn;
1737 int ret;
1738 int sys_errno;
1739 NTSTATUS status;
1741 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1742 TALLOC_FREE(subreq);
1743 TALLOC_FREE(req);
1744 if (ret == -1) {
1745 status = map_nt_error_from_unix(sys_errno);
1746 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1747 nt_errstr(status)));
1748 smbd_server_connection_terminate(sconn, nt_errstr(status));
1749 return;
1752 status = smbd_smb2_request_next_incoming(sconn);
1753 if (!NT_STATUS_IS_OK(status)) {
1754 smbd_server_connection_terminate(sconn, nt_errstr(status));
1755 return;
1759 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1760 NTSTATUS status,
1761 DATA_BLOB body, DATA_BLOB *dyn,
1762 const char *location)
1764 uint8_t *outhdr;
1765 int i = req->current_idx;
1766 uint32_t next_command_ofs;
1768 DEBUG(10,("smbd_smb2_request_done_ex: "
1769 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1770 i, nt_errstr(status), (unsigned int)body.length,
1771 dyn ? "yes": "no",
1772 (unsigned int)(dyn ? dyn->length : 0),
1773 location));
1775 if (body.length < 2) {
1776 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1779 if ((body.length % 2) != 0) {
1780 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1783 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1785 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1786 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1788 req->out.vector[i+1].iov_base = (void *)body.data;
1789 req->out.vector[i+1].iov_len = body.length;
1791 if (dyn) {
1792 req->out.vector[i+2].iov_base = (void *)dyn->data;
1793 req->out.vector[i+2].iov_len = dyn->length;
1794 } else {
1795 req->out.vector[i+2].iov_base = NULL;
1796 req->out.vector[i+2].iov_len = 0;
1799 /* see if we need to recalculate the offset to the next response */
1800 if (next_command_ofs > 0) {
1801 next_command_ofs = SMB2_HDR_BODY;
1802 next_command_ofs += req->out.vector[i+1].iov_len;
1803 next_command_ofs += req->out.vector[i+2].iov_len;
1806 if ((next_command_ofs % 8) != 0) {
1807 size_t pad_size = 8 - (next_command_ofs % 8);
1808 if (req->out.vector[i+2].iov_len == 0) {
1810 * if the dyn buffer is empty
1811 * we can use it to add padding
1813 uint8_t *pad;
1815 pad = talloc_zero_array(req->out.vector,
1816 uint8_t, pad_size);
1817 if (pad == NULL) {
1818 return smbd_smb2_request_error(req,
1819 NT_STATUS_NO_MEMORY);
1822 req->out.vector[i+2].iov_base = (void *)pad;
1823 req->out.vector[i+2].iov_len = pad_size;
1824 } else {
1826 * For now we copy the dynamic buffer
1827 * and add the padding to the new buffer
1829 size_t old_size;
1830 uint8_t *old_dyn;
1831 size_t new_size;
1832 uint8_t *new_dyn;
1834 old_size = req->out.vector[i+2].iov_len;
1835 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
1837 new_size = old_size + pad_size;
1838 new_dyn = talloc_zero_array(req->out.vector,
1839 uint8_t, new_size);
1840 if (new_dyn == NULL) {
1841 return smbd_smb2_request_error(req,
1842 NT_STATUS_NO_MEMORY);
1845 memcpy(new_dyn, old_dyn, old_size);
1846 memset(new_dyn + old_size, 0, pad_size);
1848 req->out.vector[i+2].iov_base = (void *)new_dyn;
1849 req->out.vector[i+2].iov_len = new_size;
1851 next_command_ofs += pad_size;
1854 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1856 return smbd_smb2_request_reply(req);
1859 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
1860 NTSTATUS status,
1861 DATA_BLOB *info,
1862 const char *location)
1864 DATA_BLOB body;
1865 int i = req->current_idx;
1866 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
1868 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1869 i, nt_errstr(status), info ? " +info" : "",
1870 location));
1872 body.data = outhdr + SMB2_HDR_BODY;
1873 body.length = 8;
1874 SSVAL(body.data, 0, 9);
1876 if (info) {
1877 SIVAL(body.data, 0x04, info->length);
1878 } else {
1879 /* Allocated size of req->out.vector[i].iov_base
1880 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
1881 * 1 byte without having to do an alloc.
1883 info = talloc_zero_array(req->out.vector,
1884 DATA_BLOB,
1886 if (!info) {
1887 return NT_STATUS_NO_MEMORY;
1889 info->data = ((uint8_t *)outhdr) +
1890 OUTVEC_ALLOC_SIZE - 1;
1891 info->length = 1;
1892 SCVAL(info->data, 0, 0);
1896 * if a request fails, all other remaining
1897 * compounded requests should fail too
1899 req->next_status = NT_STATUS_INVALID_PARAMETER;
1901 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
1905 struct smbd_smb2_send_oplock_break_state {
1906 struct smbd_server_connection *sconn;
1907 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
1908 struct iovec vector;
1911 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
1913 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
1914 uint64_t file_id_persistent,
1915 uint64_t file_id_volatile,
1916 uint8_t oplock_level)
1918 struct smbd_smb2_send_oplock_break_state *state;
1919 struct tevent_req *subreq;
1920 uint8_t *hdr;
1921 uint8_t *body;
1923 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
1924 if (state == NULL) {
1925 return NT_STATUS_NO_MEMORY;
1927 state->sconn = sconn;
1929 state->vector.iov_base = (void *)state->buf;
1930 state->vector.iov_len = sizeof(state->buf);
1932 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
1933 hdr = state->buf + 4;
1934 body = hdr + SMB2_HDR_BODY;
1936 SIVAL(hdr, 0, SMB2_MAGIC);
1937 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1938 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1939 SIVAL(hdr, SMB2_HDR_STATUS, 0);
1940 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
1941 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
1942 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
1943 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1944 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
1945 SIVAL(hdr, SMB2_HDR_PID, 0);
1946 SIVAL(hdr, SMB2_HDR_TID, 0);
1947 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
1948 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
1950 SSVAL(body, 0x00, 0x18);
1952 SCVAL(body, 0x02, oplock_level);
1953 SCVAL(body, 0x03, 0); /* reserved */
1954 SIVAL(body, 0x04, 0); /* reserved */
1955 SBVAL(body, 0x08, file_id_persistent);
1956 SBVAL(body, 0x10, file_id_volatile);
1958 subreq = tstream_writev_queue_send(state,
1959 sconn->smb2.event_ctx,
1960 sconn->smb2.stream,
1961 sconn->smb2.send_queue,
1962 &state->vector, 1);
1963 if (subreq == NULL) {
1964 return NT_STATUS_NO_MEMORY;
1966 tevent_req_set_callback(subreq,
1967 smbd_smb2_oplock_break_writev_done,
1968 state);
1970 return NT_STATUS_OK;
1973 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
1975 struct smbd_smb2_send_oplock_break_state *state =
1976 tevent_req_callback_data(subreq,
1977 struct smbd_smb2_send_oplock_break_state);
1978 struct smbd_server_connection *sconn = state->sconn;
1979 int ret;
1980 int sys_errno;
1982 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1983 TALLOC_FREE(subreq);
1984 if (ret == -1) {
1985 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1986 smbd_server_connection_terminate(sconn, nt_errstr(status));
1987 return;
1990 TALLOC_FREE(state);
1993 struct smbd_smb2_request_read_state {
1994 size_t missing;
1995 bool asked_for_header;
1996 struct smbd_smb2_request *smb2_req;
1999 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2000 void *private_data,
2001 TALLOC_CTX *mem_ctx,
2002 struct iovec **_vector,
2003 size_t *_count);
2004 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2006 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2007 struct tevent_context *ev,
2008 struct smbd_server_connection *sconn)
2010 struct tevent_req *req;
2011 struct smbd_smb2_request_read_state *state;
2012 struct tevent_req *subreq;
2014 req = tevent_req_create(mem_ctx, &state,
2015 struct smbd_smb2_request_read_state);
2016 if (req == NULL) {
2017 return NULL;
2019 state->missing = 0;
2020 state->asked_for_header = false;
2022 state->smb2_req = smbd_smb2_request_allocate(state);
2023 if (tevent_req_nomem(state->smb2_req, req)) {
2024 return tevent_req_post(req, ev);
2026 state->smb2_req->sconn = sconn;
2028 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2029 sconn->smb2.recv_queue,
2030 smbd_smb2_request_next_vector,
2031 state);
2032 if (tevent_req_nomem(subreq, req)) {
2033 return tevent_req_post(req, ev);
2035 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2037 return req;
2040 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2041 void *private_data,
2042 TALLOC_CTX *mem_ctx,
2043 struct iovec **_vector,
2044 size_t *_count)
2046 struct smbd_smb2_request_read_state *state =
2047 talloc_get_type_abort(private_data,
2048 struct smbd_smb2_request_read_state);
2049 struct smbd_smb2_request *req = state->smb2_req;
2050 struct iovec *vector;
2051 int idx = req->in.vector_count;
2052 size_t len = 0;
2053 uint8_t *buf = NULL;
2055 if (req->in.vector_count == 0) {
2057 * first we need to get the NBT header
2059 req->in.vector = talloc_array(req, struct iovec,
2060 req->in.vector_count + 1);
2061 if (req->in.vector == NULL) {
2062 return -1;
2064 req->in.vector_count += 1;
2066 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2067 req->in.vector[idx].iov_len = 4;
2069 vector = talloc_array(mem_ctx, struct iovec, 1);
2070 if (vector == NULL) {
2071 return -1;
2074 vector[0] = req->in.vector[idx];
2076 *_vector = vector;
2077 *_count = 1;
2078 return 0;
2081 if (req->in.vector_count == 1) {
2083 * Now we analyze the NBT header
2085 state->missing = smb2_len(req->in.vector[0].iov_base);
2087 if (state->missing == 0) {
2088 /* if there're no remaining bytes, we're done */
2089 *_vector = NULL;
2090 *_count = 0;
2091 return 0;
2094 req->in.vector = talloc_realloc(req, req->in.vector,
2095 struct iovec,
2096 req->in.vector_count + 1);
2097 if (req->in.vector == NULL) {
2098 return -1;
2100 req->in.vector_count += 1;
2102 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2104 * it's a special NBT message,
2105 * so get all remaining bytes
2107 len = state->missing;
2108 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2110 * it's an invalid message, just read what we can get
2111 * and let the caller handle the error
2113 len = state->missing;
2114 } else {
2116 * We assume it's a SMB2 request,
2117 * and we first get the header and the
2118 * first 2 bytes (the struct size) of the body
2120 len = SMB2_HDR_BODY + 2;
2122 state->asked_for_header = true;
2125 state->missing -= len;
2127 buf = talloc_array(req->in.vector, uint8_t, len);
2128 if (buf == NULL) {
2129 return -1;
2132 req->in.vector[idx].iov_base = (void *)buf;
2133 req->in.vector[idx].iov_len = len;
2135 vector = talloc_array(mem_ctx, struct iovec, 1);
2136 if (vector == NULL) {
2137 return -1;
2140 vector[0] = req->in.vector[idx];
2142 *_vector = vector;
2143 *_count = 1;
2144 return 0;
2147 if (state->missing == 0) {
2148 /* if there're no remaining bytes, we're done */
2149 *_vector = NULL;
2150 *_count = 0;
2151 return 0;
2154 if (state->asked_for_header) {
2155 const uint8_t *hdr;
2156 size_t full_size;
2157 size_t next_command_ofs;
2158 size_t body_size;
2159 uint8_t *body;
2160 size_t dyn_size;
2161 uint8_t *dyn;
2162 bool invalid = false;
2164 state->asked_for_header = false;
2167 * We got the SMB2 header and the first 2 bytes
2168 * of the body. We fix the size to just the header
2169 * and manually copy the 2 first bytes to the body section
2171 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2172 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2174 /* allocate vectors for body and dynamic areas */
2175 req->in.vector = talloc_realloc(req, req->in.vector,
2176 struct iovec,
2177 req->in.vector_count + 2);
2178 if (req->in.vector == NULL) {
2179 return -1;
2181 req->in.vector_count += 2;
2183 full_size = state->missing + SMB2_HDR_BODY + 2;
2184 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2185 body_size = SVAL(hdr, SMB2_HDR_BODY);
2187 if (next_command_ofs != 0) {
2188 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2190 * this is invalid, just return a zero
2191 * body and let the caller deal with the error
2193 invalid = true;
2194 } else if (next_command_ofs > full_size) {
2196 * this is invalid, just return a zero
2197 * body and let the caller deal with the error
2199 invalid = true;
2200 } else {
2201 full_size = next_command_ofs;
2205 if (!invalid) {
2206 if (body_size < 2) {
2208 * this is invalid, just return a zero
2209 * body and let the caller deal with the error
2211 invalid = true;
2214 if ((body_size % 2) != 0) {
2215 body_size -= 1;
2218 if (body_size > (full_size - SMB2_HDR_BODY)) {
2220 * this is invalid, just return a zero
2221 * body and let the caller deal with the error
2223 invalid = true;
2227 if (invalid) {
2228 /* the caller should check this */
2229 body_size = 2;
2232 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2234 state->missing -= (body_size - 2) + dyn_size;
2236 body = talloc_array(req->in.vector, uint8_t, body_size);
2237 if (body == NULL) {
2238 return -1;
2241 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2242 if (dyn == NULL) {
2243 return -1;
2246 req->in.vector[idx].iov_base = (void *)body;
2247 req->in.vector[idx].iov_len = body_size;
2248 req->in.vector[idx+1].iov_base = (void *)dyn;
2249 req->in.vector[idx+1].iov_len = dyn_size;
2251 vector = talloc_array(mem_ctx, struct iovec, 2);
2252 if (vector == NULL) {
2253 return -1;
2257 * the first 2 bytes of the body were already fetched
2258 * together with the header
2260 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2261 vector[0].iov_base = body + 2;
2262 vector[0].iov_len = body_size - 2;
2264 vector[1] = req->in.vector[idx+1];
2266 *_vector = vector;
2267 *_count = 2;
2268 return 0;
2272 * when we endup here, we're looking for a new SMB2 request
2273 * next. And we ask for its header and the first 2 bytes of
2274 * the body (like we did for the first SMB2 request).
2277 req->in.vector = talloc_realloc(req, req->in.vector,
2278 struct iovec,
2279 req->in.vector_count + 1);
2280 if (req->in.vector == NULL) {
2281 return -1;
2283 req->in.vector_count += 1;
2286 * We assume it's a SMB2 request,
2287 * and we first get the header and the
2288 * first 2 bytes (the struct size) of the body
2290 len = SMB2_HDR_BODY + 2;
2292 if (len > state->missing) {
2293 /* let the caller handle the error */
2294 len = state->missing;
2297 state->missing -= len;
2298 state->asked_for_header = true;
2300 buf = talloc_array(req->in.vector, uint8_t, len);
2301 if (buf == NULL) {
2302 return -1;
2305 req->in.vector[idx].iov_base = (void *)buf;
2306 req->in.vector[idx].iov_len = len;
2308 vector = talloc_array(mem_ctx, struct iovec, 1);
2309 if (vector == NULL) {
2310 return -1;
2313 vector[0] = req->in.vector[idx];
2315 *_vector = vector;
2316 *_count = 1;
2317 return 0;
2320 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2322 struct tevent_req *req =
2323 tevent_req_callback_data(subreq,
2324 struct tevent_req);
2325 int ret;
2326 int sys_errno;
2327 NTSTATUS status;
2329 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2330 if (ret == -1) {
2331 status = map_nt_error_from_unix(sys_errno);
2332 tevent_req_nterror(req, status);
2333 return;
2336 tevent_req_done(req);
2339 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2340 TALLOC_CTX *mem_ctx,
2341 struct smbd_smb2_request **_smb2_req)
2343 struct smbd_smb2_request_read_state *state =
2344 tevent_req_data(req,
2345 struct smbd_smb2_request_read_state);
2346 NTSTATUS status;
2348 if (tevent_req_is_nterror(req, &status)) {
2349 tevent_req_received(req);
2350 return status;
2353 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2354 *_smb2_req = state->smb2_req;
2355 tevent_req_received(req);
2356 return NT_STATUS_OK;
2359 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2361 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2363 size_t max_send_queue_len;
2364 size_t cur_send_queue_len;
2365 struct tevent_req *subreq;
2367 if (sconn->smb2.compound_related_in_progress) {
2369 * Can't read another until the related
2370 * compound is done.
2372 return NT_STATUS_OK;
2375 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2377 * if there is already a smbd_smb2_request_read
2378 * pending, we are done.
2380 return NT_STATUS_OK;
2383 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2384 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2386 if (cur_send_queue_len > max_send_queue_len) {
2388 * if we have a lot of requests to send,
2389 * we wait until they are on the wire until we
2390 * ask for the next request.
2392 return NT_STATUS_OK;
2395 /* ask for the next request */
2396 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2397 if (subreq == NULL) {
2398 return NT_STATUS_NO_MEMORY;
2400 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2402 return NT_STATUS_OK;
2405 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2406 const uint8_t *inbuf, size_t size)
2408 NTSTATUS status;
2409 struct smbd_smb2_request *req = NULL;
2411 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2412 (unsigned int)size));
2414 status = smbd_initialize_smb2(sconn);
2415 if (!NT_STATUS_IS_OK(status)) {
2416 smbd_server_connection_terminate(sconn, nt_errstr(status));
2417 return;
2420 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2421 if (!NT_STATUS_IS_OK(status)) {
2422 smbd_server_connection_terminate(sconn, nt_errstr(status));
2423 return;
2426 status = smbd_smb2_request_setup_out(req);
2427 if (!NT_STATUS_IS_OK(status)) {
2428 smbd_server_connection_terminate(sconn, nt_errstr(status));
2429 return;
2432 status = smbd_smb2_request_dispatch(req);
2433 if (!NT_STATUS_IS_OK(status)) {
2434 smbd_server_connection_terminate(sconn, nt_errstr(status));
2435 return;
2438 status = smbd_smb2_request_next_incoming(sconn);
2439 if (!NT_STATUS_IS_OK(status)) {
2440 smbd_server_connection_terminate(sconn, nt_errstr(status));
2441 return;
2444 sconn->num_requests++;
2447 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2449 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2450 struct smbd_server_connection);
2451 NTSTATUS status;
2452 struct smbd_smb2_request *req = NULL;
2454 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2455 TALLOC_FREE(subreq);
2456 if (!NT_STATUS_IS_OK(status)) {
2457 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2458 nt_errstr(status)));
2459 smbd_server_connection_terminate(sconn, nt_errstr(status));
2460 return;
2463 if (req->in.nbt_hdr[0] != 0x00) {
2464 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2465 req->in.nbt_hdr[0]));
2466 TALLOC_FREE(req);
2467 goto next;
2470 req->current_idx = 1;
2472 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2473 req->current_idx, req->in.vector_count));
2475 status = smbd_smb2_request_validate(req);
2476 if (!NT_STATUS_IS_OK(status)) {
2477 smbd_server_connection_terminate(sconn, nt_errstr(status));
2478 return;
2481 status = smbd_smb2_request_setup_out(req);
2482 if (!NT_STATUS_IS_OK(status)) {
2483 smbd_server_connection_terminate(sconn, nt_errstr(status));
2484 return;
2487 status = smbd_smb2_request_dispatch(req);
2488 if (!NT_STATUS_IS_OK(status)) {
2489 smbd_server_connection_terminate(sconn, nt_errstr(status));
2490 return;
2493 next:
2494 status = smbd_smb2_request_next_incoming(sconn);
2495 if (!NT_STATUS_IS_OK(status)) {
2496 smbd_server_connection_terminate(sconn, nt_errstr(status));
2497 return;
2500 sconn->num_requests++;
2502 /* The timeout_processing function isn't run nearly
2503 often enough to implement 'max log size' without
2504 overrunning the size of the file by many megabytes.
2505 This is especially true if we are running at debug
2506 level 10. Checking every 50 SMB2s is a nice
2507 tradeoff of performance vs log file size overrun. */
2509 if ((sconn->num_requests % 50) == 0 &&
2510 need_to_check_log_size()) {
2511 change_to_root_user();
2512 check_log_size();