s3:smb2_server: make sure we grant credits on async read/write operations (bug #8357)
[Samba.git] / source3 / smbd / smb2_server.c
blob0cc80edcf6cd9a42da3205a709869361dcf5b790
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 /* Don't return an intermediate packet on a pipe read/write. */
890 if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
891 return NT_STATUS_OK;
894 reqhdr = (uint8_t *)req->out.vector[i].iov_base;
895 flags = (IVAL(reqhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
896 message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
897 async_id = message_id; /* keep it simple for now... */
900 * What we send is identical to a smbd_smb2_request_error
901 * packet with an error status of STATUS_PENDING. Make use
902 * of this fact sometime when refactoring. JRA.
905 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
906 if (state == NULL) {
907 return NT_STATUS_NO_MEMORY;
909 state->sconn = req->sconn;
911 state->vector[0].iov_base = (void *)state->buf;
912 state->vector[0].iov_len = 4;
914 state->vector[1].iov_base = state->buf + 4;
915 state->vector[1].iov_len = SMB2_HDR_BODY;
917 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
918 state->vector[2].iov_len = 9;
920 smb2_setup_nbt_length(state->vector, 3);
922 hdr = (uint8_t *)state->vector[1].iov_base;
923 body = (uint8_t *)state->vector[2].iov_base;
925 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
926 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
927 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
928 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
929 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(reqhdr, SMB2_HDR_OPCODE));
931 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
932 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
933 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
934 SBVAL(hdr, SMB2_HDR_PID, async_id);
935 SBVAL(hdr, SMB2_HDR_SESSION_ID,
936 BVAL(reqhdr, SMB2_HDR_SESSION_ID));
937 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
939 SSVAL(body, 0x00, 0x08 + 1);
941 SCVAL(body, 0x02, 0);
942 SCVAL(body, 0x03, 0);
943 SIVAL(body, 0x04, 0);
944 /* Match W2K8R2... */
945 SCVAL(body, 0x08, 0x21);
947 /* Ensure we correctly go through crediting. Grant
948 the credits now, and zero credits on the final
949 response. */
950 smb2_set_operation_credit(req->sconn,
951 &req->in.vector[i],
952 &state->vector[1]);
954 if (req->do_signing) {
955 status = smb2_signing_sign_pdu(req->session->session_key,
956 &state->vector[1], 2);
957 if (!NT_STATUS_IS_OK(status)) {
958 return status;
962 subreq = tstream_writev_queue_send(state,
963 req->sconn->smb2.event_ctx,
964 req->sconn->smb2.stream,
965 req->sconn->smb2.send_queue,
966 state->vector,
969 if (subreq == NULL) {
970 return NT_STATUS_NO_MEMORY;
973 tevent_req_set_callback(subreq,
974 smbd_smb2_request_pending_writev_done,
975 state);
977 /* Note we're going async with this request. */
978 req->async = true;
981 * Now manipulate req so that the outstanding async request
982 * is the only one left in the struct smbd_smb2_request.
985 if (req->current_idx == 1) {
986 /* There was only one. */
987 goto out;
990 /* Re-arrange the in.vectors. */
991 req->in.vector[1] = req->in.vector[i];
992 req->in.vector[2] = req->in.vector[i+1];
993 req->in.vector[3] = req->in.vector[i+2];
994 req->in.vector_count = 4;
995 /* Reset the new in size. */
996 smb2_setup_nbt_length(req->in.vector, 4);
998 /* Now recreate the out.vectors. */
999 outvec = talloc_zero_array(req, struct iovec, 4);
1000 if (!outvec) {
1001 return NT_STATUS_NO_MEMORY;
1004 /* 0 is always boilerplate and must
1005 * be of size 4 for the length field. */
1007 outvec[0].iov_base = req->out.nbt_hdr;
1008 outvec[0].iov_len = 4;
1009 SIVAL(req->out.nbt_hdr, 0, 0);
1011 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
1012 return NT_STATUS_NO_MEMORY;
1015 TALLOC_FREE(req->out.vector);
1017 req->out.vector = outvec;
1019 req->current_idx = 1;
1020 req->out.vector_count = 4;
1022 out:
1024 smb2_setup_nbt_length(req->out.vector,
1025 req->out.vector_count);
1027 /* Ensure our final reply matches the interim one. */
1028 reqhdr = (uint8_t *)req->out.vector[1].iov_base;
1029 SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1030 SBVAL(reqhdr, SMB2_HDR_PID, async_id);
1033 const uint8_t *inhdr =
1034 (const uint8_t *)req->in.vector[1].iov_base;
1035 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1036 "going async\n",
1037 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1038 (unsigned long long)async_id ));
1040 return NT_STATUS_OK;
1043 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1045 struct smbd_server_connection *sconn = req->sconn;
1046 struct smbd_smb2_request *cur;
1047 const uint8_t *inhdr;
1048 int i = req->current_idx;
1049 uint32_t flags;
1050 uint64_t search_message_id;
1051 uint64_t search_async_id;
1052 uint64_t found_id;
1054 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1056 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1057 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1058 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1061 * we don't need the request anymore
1062 * cancel requests never have a response
1064 DLIST_REMOVE(req->sconn->smb2.requests, req);
1065 TALLOC_FREE(req);
1067 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1068 const uint8_t *outhdr;
1069 uint64_t message_id;
1070 uint64_t async_id;
1072 i = cur->current_idx;
1074 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1076 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1077 async_id = BVAL(outhdr, SMB2_HDR_PID);
1079 if (flags & SMB2_HDR_FLAG_ASYNC) {
1080 if (search_async_id == async_id) {
1081 found_id = async_id;
1082 break;
1084 } else {
1085 if (search_message_id == message_id) {
1086 found_id = message_id;
1087 break;
1092 if (cur && cur->subreq) {
1093 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1094 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1095 "cancel opcode[%s] mid %llu\n",
1096 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1097 (unsigned long long)found_id ));
1098 tevent_req_cancel(cur->subreq);
1101 return NT_STATUS_OK;
1104 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1106 const uint8_t *inhdr;
1107 int i = req->current_idx;
1108 uint16_t opcode;
1109 uint32_t flags;
1110 uint64_t mid;
1111 NTSTATUS status;
1112 NTSTATUS session_status;
1113 uint32_t allowed_flags;
1114 NTSTATUS return_value;
1116 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1118 /* TODO: verify more things */
1120 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1121 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1122 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1123 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1124 smb2_opcode_name(opcode),
1125 (unsigned long long)mid));
1127 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1128 SMB2_HDR_FLAG_SIGNED |
1129 SMB2_HDR_FLAG_DFS;
1130 if (opcode == SMB2_OP_CANCEL) {
1131 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1133 if ((flags & ~allowed_flags) != 0) {
1134 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1138 * Check if the client provided a valid session id,
1139 * if so smbd_smb2_request_check_session() calls
1140 * set_current_user_info().
1142 * As some command don't require a valid session id
1143 * we defer the check of the session_status
1145 session_status = smbd_smb2_request_check_session(req);
1147 req->do_signing = false;
1148 if (flags & SMB2_HDR_FLAG_SIGNED) {
1149 if (!NT_STATUS_IS_OK(session_status)) {
1150 return smbd_smb2_request_error(req, session_status);
1153 req->do_signing = true;
1154 status = smb2_signing_check_pdu(req->session->session_key,
1155 &req->in.vector[i], 3);
1156 if (!NT_STATUS_IS_OK(status)) {
1157 return smbd_smb2_request_error(req, status);
1159 } else if (req->session && req->session->do_signing) {
1160 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1163 if (flags & SMB2_HDR_FLAG_CHAINED) {
1165 * This check is mostly for giving the correct error code
1166 * for compounded requests.
1168 * TODO: we may need to move this after the session
1169 * and tcon checks.
1171 if (!NT_STATUS_IS_OK(req->next_status)) {
1172 return smbd_smb2_request_error(req, req->next_status);
1174 } else {
1175 req->compat_chain_fsp = NULL;
1178 switch (opcode) {
1179 case SMB2_OP_NEGPROT:
1180 /* This call needs to be run as root */
1181 change_to_root_user();
1184 START_PROFILE(smb2_negprot);
1185 return_value = smbd_smb2_request_process_negprot(req);
1186 END_PROFILE(smb2_negprot);
1188 break;
1190 case SMB2_OP_SESSSETUP:
1191 /* This call needs to be run as root */
1192 change_to_root_user();
1195 START_PROFILE(smb2_sesssetup);
1196 return_value = smbd_smb2_request_process_sesssetup(req);
1197 END_PROFILE(smb2_sesssetup);
1199 break;
1201 case SMB2_OP_LOGOFF:
1202 if (!NT_STATUS_IS_OK(session_status)) {
1203 return_value = smbd_smb2_request_error(req, session_status);
1204 break;
1207 /* This call needs to be run as root */
1208 change_to_root_user();
1211 START_PROFILE(smb2_logoff);
1212 return_value = smbd_smb2_request_process_logoff(req);
1213 END_PROFILE(smb2_logoff);
1215 break;
1217 case SMB2_OP_TCON:
1218 if (!NT_STATUS_IS_OK(session_status)) {
1219 return_value = smbd_smb2_request_error(req, session_status);
1220 break;
1224 * This call needs to be run as root.
1226 * smbd_smb2_request_process_tcon()
1227 * calls make_connection_snum(), which will call
1228 * change_to_user(), when needed.
1230 change_to_root_user();
1233 START_PROFILE(smb2_tcon);
1234 return_value = smbd_smb2_request_process_tcon(req);
1235 END_PROFILE(smb2_tcon);
1237 break;
1239 case SMB2_OP_TDIS:
1240 if (!NT_STATUS_IS_OK(session_status)) {
1241 return_value = smbd_smb2_request_error(req, session_status);
1242 break;
1245 * This call needs to be run as user.
1247 * smbd_smb2_request_check_tcon()
1248 * calls change_to_user() on success.
1250 status = smbd_smb2_request_check_tcon(req);
1251 if (!NT_STATUS_IS_OK(status)) {
1252 return_value = smbd_smb2_request_error(req, status);
1253 break;
1255 /* This call needs to be run as root */
1256 change_to_root_user();
1260 START_PROFILE(smb2_tdis);
1261 return_value = smbd_smb2_request_process_tdis(req);
1262 END_PROFILE(smb2_tdis);
1264 break;
1266 case SMB2_OP_CREATE:
1267 if (!NT_STATUS_IS_OK(session_status)) {
1268 return_value = smbd_smb2_request_error(req, session_status);
1269 break;
1272 * This call needs to be run as user.
1274 * smbd_smb2_request_check_tcon()
1275 * calls change_to_user() on success.
1277 status = smbd_smb2_request_check_tcon(req);
1278 if (!NT_STATUS_IS_OK(status)) {
1279 return_value = smbd_smb2_request_error(req, status);
1280 break;
1284 START_PROFILE(smb2_create);
1285 return_value = smbd_smb2_request_process_create(req);
1286 END_PROFILE(smb2_create);
1288 break;
1290 case SMB2_OP_CLOSE:
1291 if (!NT_STATUS_IS_OK(session_status)) {
1292 return_value = smbd_smb2_request_error(req, session_status);
1293 break;
1296 * This call needs to be run as user.
1298 * smbd_smb2_request_check_tcon()
1299 * calls change_to_user() on success.
1301 status = smbd_smb2_request_check_tcon(req);
1302 if (!NT_STATUS_IS_OK(status)) {
1303 return_value = smbd_smb2_request_error(req, status);
1304 break;
1308 START_PROFILE(smb2_close);
1309 return_value = smbd_smb2_request_process_close(req);
1310 END_PROFILE(smb2_close);
1312 break;
1314 case SMB2_OP_FLUSH:
1315 if (!NT_STATUS_IS_OK(session_status)) {
1316 return_value = smbd_smb2_request_error(req, session_status);
1317 break;
1320 * This call needs to be run as user.
1322 * smbd_smb2_request_check_tcon()
1323 * calls change_to_user() on success.
1325 status = smbd_smb2_request_check_tcon(req);
1326 if (!NT_STATUS_IS_OK(status)) {
1327 return_value = smbd_smb2_request_error(req, status);
1328 break;
1332 START_PROFILE(smb2_flush);
1333 return_value = smbd_smb2_request_process_flush(req);
1334 END_PROFILE(smb2_flush);
1336 break;
1338 case SMB2_OP_READ:
1339 if (!NT_STATUS_IS_OK(session_status)) {
1340 return_value = smbd_smb2_request_error(req, session_status);
1341 break;
1344 * This call needs to be run as user.
1346 * smbd_smb2_request_check_tcon()
1347 * calls change_to_user() on success.
1349 status = smbd_smb2_request_check_tcon(req);
1350 if (!NT_STATUS_IS_OK(status)) {
1351 return_value = smbd_smb2_request_error(req, status);
1352 break;
1356 START_PROFILE(smb2_read);
1357 return_value = smbd_smb2_request_process_read(req);
1358 END_PROFILE(smb2_read);
1360 break;
1362 case SMB2_OP_WRITE:
1363 if (!NT_STATUS_IS_OK(session_status)) {
1364 return_value = smbd_smb2_request_error(req, session_status);
1365 break;
1368 * This call needs to be run as user.
1370 * smbd_smb2_request_check_tcon()
1371 * calls change_to_user() on success.
1373 status = smbd_smb2_request_check_tcon(req);
1374 if (!NT_STATUS_IS_OK(status)) {
1375 return_value = smbd_smb2_request_error(req, status);
1376 break;
1380 START_PROFILE(smb2_write);
1381 return_value = smbd_smb2_request_process_write(req);
1382 END_PROFILE(smb2_write);
1384 break;
1386 case SMB2_OP_LOCK:
1387 if (!NT_STATUS_IS_OK(session_status)) {
1388 /* Too ugly to live ? JRA. */
1389 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1390 session_status = NT_STATUS_FILE_CLOSED;
1392 return_value = smbd_smb2_request_error(req, session_status);
1393 break;
1396 * This call needs to be run as user.
1398 * smbd_smb2_request_check_tcon()
1399 * calls change_to_user() on success.
1401 status = smbd_smb2_request_check_tcon(req);
1402 if (!NT_STATUS_IS_OK(status)) {
1403 /* Too ugly to live ? JRA. */
1404 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1405 status = NT_STATUS_FILE_CLOSED;
1407 return_value = smbd_smb2_request_error(req, status);
1408 break;
1412 START_PROFILE(smb2_lock);
1413 return_value = smbd_smb2_request_process_lock(req);
1414 END_PROFILE(smb2_lock);
1416 break;
1418 case SMB2_OP_IOCTL:
1419 if (!NT_STATUS_IS_OK(session_status)) {
1420 return_value = smbd_smb2_request_error(req, session_status);
1421 break;
1424 * This call needs to be run as user.
1426 * smbd_smb2_request_check_tcon()
1427 * calls change_to_user() on success.
1429 status = smbd_smb2_request_check_tcon(req);
1430 if (!NT_STATUS_IS_OK(status)) {
1431 return_value = smbd_smb2_request_error(req, status);
1432 break;
1436 START_PROFILE(smb2_ioctl);
1437 return_value = smbd_smb2_request_process_ioctl(req);
1438 END_PROFILE(smb2_ioctl);
1440 break;
1442 case SMB2_OP_CANCEL:
1444 * This call needs to be run as root
1446 * That is what we also do in the SMB1 case.
1448 change_to_root_user();
1451 START_PROFILE(smb2_cancel);
1452 return_value = smbd_smb2_request_process_cancel(req);
1453 END_PROFILE(smb2_cancel);
1455 break;
1457 case SMB2_OP_KEEPALIVE:
1458 /* This call needs to be run as root */
1459 change_to_root_user();
1462 START_PROFILE(smb2_keepalive);
1463 return_value = smbd_smb2_request_process_keepalive(req);
1464 END_PROFILE(smb2_keepalive);
1466 break;
1468 case SMB2_OP_FIND:
1469 if (!NT_STATUS_IS_OK(session_status)) {
1470 return_value = smbd_smb2_request_error(req, session_status);
1471 break;
1474 * This call needs to be run as user.
1476 * smbd_smb2_request_check_tcon()
1477 * calls change_to_user() on success.
1479 status = smbd_smb2_request_check_tcon(req);
1480 if (!NT_STATUS_IS_OK(status)) {
1481 return_value = smbd_smb2_request_error(req, status);
1482 break;
1486 START_PROFILE(smb2_find);
1487 return_value = smbd_smb2_request_process_find(req);
1488 END_PROFILE(smb2_find);
1490 break;
1492 case SMB2_OP_NOTIFY:
1493 if (!NT_STATUS_IS_OK(session_status)) {
1494 return_value = smbd_smb2_request_error(req, session_status);
1495 break;
1498 * This call needs to be run as user.
1500 * smbd_smb2_request_check_tcon()
1501 * calls change_to_user() on success.
1503 status = smbd_smb2_request_check_tcon(req);
1504 if (!NT_STATUS_IS_OK(status)) {
1505 return_value = smbd_smb2_request_error(req, status);
1506 break;
1510 START_PROFILE(smb2_notify);
1511 return_value = smbd_smb2_request_process_notify(req);
1512 END_PROFILE(smb2_notify);
1514 break;
1516 case SMB2_OP_GETINFO:
1517 if (!NT_STATUS_IS_OK(session_status)) {
1518 return_value = smbd_smb2_request_error(req, session_status);
1519 break;
1522 * This call needs to be run as user.
1524 * smbd_smb2_request_check_tcon()
1525 * calls change_to_user() on success.
1527 status = smbd_smb2_request_check_tcon(req);
1528 if (!NT_STATUS_IS_OK(status)) {
1529 return_value = smbd_smb2_request_error(req, status);
1530 break;
1534 START_PROFILE(smb2_getinfo);
1535 return_value = smbd_smb2_request_process_getinfo(req);
1536 END_PROFILE(smb2_getinfo);
1538 break;
1540 case SMB2_OP_SETINFO:
1541 if (!NT_STATUS_IS_OK(session_status)) {
1542 return_value = smbd_smb2_request_error(req, session_status);
1543 break;
1546 * This call needs to be run as user.
1548 * smbd_smb2_request_check_tcon()
1549 * calls change_to_user() on success.
1551 status = smbd_smb2_request_check_tcon(req);
1552 if (!NT_STATUS_IS_OK(status)) {
1553 return_value = smbd_smb2_request_error(req, status);
1554 break;
1558 START_PROFILE(smb2_setinfo);
1559 return_value = smbd_smb2_request_process_setinfo(req);
1560 END_PROFILE(smb2_setinfo);
1562 break;
1564 case SMB2_OP_BREAK:
1565 if (!NT_STATUS_IS_OK(session_status)) {
1566 return_value = smbd_smb2_request_error(req, session_status);
1567 break;
1570 * This call needs to be run as user.
1572 * smbd_smb2_request_check_tcon()
1573 * calls change_to_user() on success.
1575 status = smbd_smb2_request_check_tcon(req);
1576 if (!NT_STATUS_IS_OK(status)) {
1577 return_value = smbd_smb2_request_error(req, status);
1578 break;
1582 START_PROFILE(smb2_break);
1583 return_value = smbd_smb2_request_process_break(req);
1584 END_PROFILE(smb2_break);
1586 break;
1588 default:
1589 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1590 break;
1592 return return_value;
1595 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1597 struct tevent_req *subreq;
1598 int i = req->current_idx;
1600 req->subreq = NULL;
1602 req->current_idx += 3;
1604 if (req->current_idx < req->out.vector_count) {
1606 * We must process the remaining compound
1607 * SMB2 requests before any new incoming SMB2
1608 * requests. This is because incoming SMB2
1609 * requests may include a cancel for a
1610 * compound request we haven't processed
1611 * yet.
1613 struct tevent_immediate *im = tevent_create_immediate(req);
1614 if (!im) {
1615 return NT_STATUS_NO_MEMORY;
1617 tevent_schedule_immediate(im,
1618 req->sconn->smb2.event_ctx,
1619 smbd_smb2_request_dispatch_immediate,
1620 req);
1621 return NT_STATUS_OK;
1624 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1626 /* Set credit for this operation (zero credits if this
1627 is a final reply for an async operation). */
1628 smb2_set_operation_credit(req->sconn,
1629 &req->in.vector[i],
1630 &req->out.vector[i]);
1632 if (req->do_signing) {
1633 NTSTATUS status;
1634 status = smb2_signing_sign_pdu(req->session->session_key,
1635 &req->out.vector[i], 3);
1636 if (!NT_STATUS_IS_OK(status)) {
1637 return status;
1641 if (DEBUGLEVEL >= 10) {
1642 dbgtext("smbd_smb2_request_reply: sending...\n");
1643 print_req_vectors(req);
1646 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1647 if (req->out.vector_count == 4 &&
1648 req->out.vector[3].iov_base == NULL &&
1649 req->out.vector[3].iov_len != 0) {
1650 /* Dynamic part is NULL. Chop it off,
1651 We're going to send it via sendfile. */
1652 req->out.vector_count -= 1;
1655 subreq = tstream_writev_queue_send(req,
1656 req->sconn->smb2.event_ctx,
1657 req->sconn->smb2.stream,
1658 req->sconn->smb2.send_queue,
1659 req->out.vector,
1660 req->out.vector_count);
1661 if (subreq == NULL) {
1662 return NT_STATUS_NO_MEMORY;
1664 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1666 * We're done with this request -
1667 * move it off the "being processed" queue.
1669 DLIST_REMOVE(req->sconn->smb2.requests, req);
1671 return NT_STATUS_OK;
1674 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1675 struct tevent_immediate *im,
1676 void *private_data)
1678 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1679 struct smbd_smb2_request);
1680 struct smbd_server_connection *sconn = req->sconn;
1681 NTSTATUS status;
1683 TALLOC_FREE(im);
1685 if (DEBUGLEVEL >= 10) {
1686 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1687 req->current_idx, req->in.vector_count));
1688 print_req_vectors(req);
1691 status = smbd_smb2_request_dispatch(req);
1692 if (!NT_STATUS_IS_OK(status)) {
1693 smbd_server_connection_terminate(sconn, nt_errstr(status));
1694 return;
1698 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1700 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1701 struct smbd_smb2_request);
1702 struct smbd_server_connection *sconn = req->sconn;
1703 int ret;
1704 int sys_errno;
1706 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1707 TALLOC_FREE(subreq);
1708 TALLOC_FREE(req);
1709 if (ret == -1) {
1710 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1711 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1712 nt_errstr(status)));
1713 smbd_server_connection_terminate(sconn, nt_errstr(status));
1714 return;
1718 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1719 NTSTATUS status,
1720 DATA_BLOB body, DATA_BLOB *dyn,
1721 const char *location)
1723 uint8_t *outhdr;
1724 int i = req->current_idx;
1725 uint32_t next_command_ofs;
1727 DEBUG(10,("smbd_smb2_request_done_ex: "
1728 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1729 i, nt_errstr(status), (unsigned int)body.length,
1730 dyn ? "yes": "no",
1731 (unsigned int)(dyn ? dyn->length : 0),
1732 location));
1734 if (body.length < 2) {
1735 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1738 if ((body.length % 2) != 0) {
1739 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1742 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1744 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1745 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1747 req->out.vector[i+1].iov_base = (void *)body.data;
1748 req->out.vector[i+1].iov_len = body.length;
1750 if (dyn) {
1751 req->out.vector[i+2].iov_base = (void *)dyn->data;
1752 req->out.vector[i+2].iov_len = dyn->length;
1753 } else {
1754 req->out.vector[i+2].iov_base = NULL;
1755 req->out.vector[i+2].iov_len = 0;
1758 /* see if we need to recalculate the offset to the next response */
1759 if (next_command_ofs > 0) {
1760 next_command_ofs = SMB2_HDR_BODY;
1761 next_command_ofs += req->out.vector[i+1].iov_len;
1762 next_command_ofs += req->out.vector[i+2].iov_len;
1765 if ((next_command_ofs % 8) != 0) {
1766 size_t pad_size = 8 - (next_command_ofs % 8);
1767 if (req->out.vector[i+2].iov_len == 0) {
1769 * if the dyn buffer is empty
1770 * we can use it to add padding
1772 uint8_t *pad;
1774 pad = talloc_zero_array(req->out.vector,
1775 uint8_t, pad_size);
1776 if (pad == NULL) {
1777 return smbd_smb2_request_error(req,
1778 NT_STATUS_NO_MEMORY);
1781 req->out.vector[i+2].iov_base = (void *)pad;
1782 req->out.vector[i+2].iov_len = pad_size;
1783 } else {
1785 * For now we copy the dynamic buffer
1786 * and add the padding to the new buffer
1788 size_t old_size;
1789 uint8_t *old_dyn;
1790 size_t new_size;
1791 uint8_t *new_dyn;
1793 old_size = req->out.vector[i+2].iov_len;
1794 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
1796 new_size = old_size + pad_size;
1797 new_dyn = talloc_zero_array(req->out.vector,
1798 uint8_t, new_size);
1799 if (new_dyn == NULL) {
1800 return smbd_smb2_request_error(req,
1801 NT_STATUS_NO_MEMORY);
1804 memcpy(new_dyn, old_dyn, old_size);
1805 memset(new_dyn + old_size, 0, pad_size);
1807 req->out.vector[i+2].iov_base = (void *)new_dyn;
1808 req->out.vector[i+2].iov_len = new_size;
1810 next_command_ofs += pad_size;
1813 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1815 return smbd_smb2_request_reply(req);
1818 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
1819 NTSTATUS status,
1820 DATA_BLOB *info,
1821 const char *location)
1823 DATA_BLOB body;
1824 int i = req->current_idx;
1825 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
1827 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1828 i, nt_errstr(status), info ? " +info" : "",
1829 location));
1831 body.data = outhdr + SMB2_HDR_BODY;
1832 body.length = 8;
1833 SSVAL(body.data, 0, 9);
1835 if (info) {
1836 SIVAL(body.data, 0x04, info->length);
1837 } else {
1838 /* Allocated size of req->out.vector[i].iov_base
1839 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
1840 * 1 byte without having to do an alloc.
1842 info = talloc_zero_array(req->out.vector,
1843 DATA_BLOB,
1845 if (!info) {
1846 return NT_STATUS_NO_MEMORY;
1848 info->data = ((uint8_t *)outhdr) +
1849 OUTVEC_ALLOC_SIZE - 1;
1850 info->length = 1;
1851 SCVAL(info->data, 0, 0);
1855 * if a request fails, all other remaining
1856 * compounded requests should fail too
1858 req->next_status = NT_STATUS_INVALID_PARAMETER;
1860 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
1864 struct smbd_smb2_send_oplock_break_state {
1865 struct smbd_server_connection *sconn;
1866 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
1867 struct iovec vector;
1870 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
1872 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
1873 uint64_t file_id_persistent,
1874 uint64_t file_id_volatile,
1875 uint8_t oplock_level)
1877 struct smbd_smb2_send_oplock_break_state *state;
1878 struct tevent_req *subreq;
1879 uint8_t *hdr;
1880 uint8_t *body;
1882 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
1883 if (state == NULL) {
1884 return NT_STATUS_NO_MEMORY;
1886 state->sconn = sconn;
1888 state->vector.iov_base = (void *)state->buf;
1889 state->vector.iov_len = sizeof(state->buf);
1891 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
1892 hdr = state->buf + 4;
1893 body = hdr + SMB2_HDR_BODY;
1895 SIVAL(hdr, 0, SMB2_MAGIC);
1896 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1897 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1898 SIVAL(hdr, SMB2_HDR_STATUS, 0);
1899 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
1900 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
1901 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
1902 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1903 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
1904 SIVAL(hdr, SMB2_HDR_PID, 0);
1905 SIVAL(hdr, SMB2_HDR_TID, 0);
1906 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
1907 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
1909 SSVAL(body, 0x00, 0x18);
1911 SCVAL(body, 0x02, oplock_level);
1912 SCVAL(body, 0x03, 0); /* reserved */
1913 SIVAL(body, 0x04, 0); /* reserved */
1914 SBVAL(body, 0x08, file_id_persistent);
1915 SBVAL(body, 0x10, file_id_volatile);
1917 subreq = tstream_writev_queue_send(state,
1918 sconn->smb2.event_ctx,
1919 sconn->smb2.stream,
1920 sconn->smb2.send_queue,
1921 &state->vector, 1);
1922 if (subreq == NULL) {
1923 return NT_STATUS_NO_MEMORY;
1925 tevent_req_set_callback(subreq,
1926 smbd_smb2_oplock_break_writev_done,
1927 state);
1929 return NT_STATUS_OK;
1932 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
1934 struct smbd_smb2_send_oplock_break_state *state =
1935 tevent_req_callback_data(subreq,
1936 struct smbd_smb2_send_oplock_break_state);
1937 struct smbd_server_connection *sconn = state->sconn;
1938 int ret;
1939 int sys_errno;
1941 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1942 TALLOC_FREE(subreq);
1943 if (ret == -1) {
1944 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1945 smbd_server_connection_terminate(sconn, nt_errstr(status));
1946 return;
1949 TALLOC_FREE(state);
1952 struct smbd_smb2_request_read_state {
1953 size_t missing;
1954 bool asked_for_header;
1955 struct smbd_smb2_request *smb2_req;
1958 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1959 void *private_data,
1960 TALLOC_CTX *mem_ctx,
1961 struct iovec **_vector,
1962 size_t *_count);
1963 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
1965 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
1966 struct tevent_context *ev,
1967 struct smbd_server_connection *sconn)
1969 struct tevent_req *req;
1970 struct smbd_smb2_request_read_state *state;
1971 struct tevent_req *subreq;
1973 req = tevent_req_create(mem_ctx, &state,
1974 struct smbd_smb2_request_read_state);
1975 if (req == NULL) {
1976 return NULL;
1978 state->missing = 0;
1979 state->asked_for_header = false;
1981 state->smb2_req = smbd_smb2_request_allocate(state);
1982 if (tevent_req_nomem(state->smb2_req, req)) {
1983 return tevent_req_post(req, ev);
1985 state->smb2_req->sconn = sconn;
1987 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
1988 sconn->smb2.recv_queue,
1989 smbd_smb2_request_next_vector,
1990 state);
1991 if (tevent_req_nomem(subreq, req)) {
1992 return tevent_req_post(req, ev);
1994 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
1996 return 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)
2005 struct smbd_smb2_request_read_state *state =
2006 talloc_get_type_abort(private_data,
2007 struct smbd_smb2_request_read_state);
2008 struct smbd_smb2_request *req = state->smb2_req;
2009 struct iovec *vector;
2010 int idx = req->in.vector_count;
2011 size_t len = 0;
2012 uint8_t *buf = NULL;
2014 if (req->in.vector_count == 0) {
2016 * first we need to get the NBT header
2018 req->in.vector = talloc_array(req, struct iovec,
2019 req->in.vector_count + 1);
2020 if (req->in.vector == NULL) {
2021 return -1;
2023 req->in.vector_count += 1;
2025 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2026 req->in.vector[idx].iov_len = 4;
2028 vector = talloc_array(mem_ctx, struct iovec, 1);
2029 if (vector == NULL) {
2030 return -1;
2033 vector[0] = req->in.vector[idx];
2035 *_vector = vector;
2036 *_count = 1;
2037 return 0;
2040 if (req->in.vector_count == 1) {
2042 * Now we analyze the NBT header
2044 state->missing = smb2_len(req->in.vector[0].iov_base);
2046 if (state->missing == 0) {
2047 /* if there're no remaining bytes, we're done */
2048 *_vector = NULL;
2049 *_count = 0;
2050 return 0;
2053 req->in.vector = talloc_realloc(req, req->in.vector,
2054 struct iovec,
2055 req->in.vector_count + 1);
2056 if (req->in.vector == NULL) {
2057 return -1;
2059 req->in.vector_count += 1;
2061 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2063 * it's a special NBT message,
2064 * so get all remaining bytes
2066 len = state->missing;
2067 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2069 * it's an invalid message, just read what we can get
2070 * and let the caller handle the error
2072 len = state->missing;
2073 } else {
2075 * We assume it's a SMB2 request,
2076 * and we first get the header and the
2077 * first 2 bytes (the struct size) of the body
2079 len = SMB2_HDR_BODY + 2;
2081 state->asked_for_header = true;
2084 state->missing -= len;
2086 buf = talloc_array(req->in.vector, uint8_t, len);
2087 if (buf == NULL) {
2088 return -1;
2091 req->in.vector[idx].iov_base = (void *)buf;
2092 req->in.vector[idx].iov_len = len;
2094 vector = talloc_array(mem_ctx, struct iovec, 1);
2095 if (vector == NULL) {
2096 return -1;
2099 vector[0] = req->in.vector[idx];
2101 *_vector = vector;
2102 *_count = 1;
2103 return 0;
2106 if (state->missing == 0) {
2107 /* if there're no remaining bytes, we're done */
2108 *_vector = NULL;
2109 *_count = 0;
2110 return 0;
2113 if (state->asked_for_header) {
2114 const uint8_t *hdr;
2115 size_t full_size;
2116 size_t next_command_ofs;
2117 size_t body_size;
2118 uint8_t *body;
2119 size_t dyn_size;
2120 uint8_t *dyn;
2121 bool invalid = false;
2123 state->asked_for_header = false;
2126 * We got the SMB2 header and the first 2 bytes
2127 * of the body. We fix the size to just the header
2128 * and manually copy the 2 first bytes to the body section
2130 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2131 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2133 /* allocate vectors for body and dynamic areas */
2134 req->in.vector = talloc_realloc(req, req->in.vector,
2135 struct iovec,
2136 req->in.vector_count + 2);
2137 if (req->in.vector == NULL) {
2138 return -1;
2140 req->in.vector_count += 2;
2142 full_size = state->missing + SMB2_HDR_BODY + 2;
2143 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2144 body_size = SVAL(hdr, SMB2_HDR_BODY);
2146 if (next_command_ofs != 0) {
2147 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2149 * this is invalid, just return a zero
2150 * body and let the caller deal with the error
2152 invalid = true;
2153 } else if (next_command_ofs > full_size) {
2155 * this is invalid, just return a zero
2156 * body and let the caller deal with the error
2158 invalid = true;
2159 } else {
2160 full_size = next_command_ofs;
2164 if (!invalid) {
2165 if (body_size < 2) {
2167 * this is invalid, just return a zero
2168 * body and let the caller deal with the error
2170 invalid = true;
2173 if ((body_size % 2) != 0) {
2174 body_size -= 1;
2177 if (body_size > (full_size - SMB2_HDR_BODY)) {
2179 * this is invalid, just return a zero
2180 * body and let the caller deal with the error
2182 invalid = true;
2186 if (invalid) {
2187 /* the caller should check this */
2188 body_size = 2;
2191 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2193 state->missing -= (body_size - 2) + dyn_size;
2195 body = talloc_array(req->in.vector, uint8_t, body_size);
2196 if (body == NULL) {
2197 return -1;
2200 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2201 if (dyn == NULL) {
2202 return -1;
2205 req->in.vector[idx].iov_base = (void *)body;
2206 req->in.vector[idx].iov_len = body_size;
2207 req->in.vector[idx+1].iov_base = (void *)dyn;
2208 req->in.vector[idx+1].iov_len = dyn_size;
2210 vector = talloc_array(mem_ctx, struct iovec, 2);
2211 if (vector == NULL) {
2212 return -1;
2216 * the first 2 bytes of the body were already fetched
2217 * together with the header
2219 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2220 vector[0].iov_base = body + 2;
2221 vector[0].iov_len = body_size - 2;
2223 vector[1] = req->in.vector[idx+1];
2225 *_vector = vector;
2226 *_count = 2;
2227 return 0;
2231 * when we endup here, we're looking for a new SMB2 request
2232 * next. And we ask for its header and the first 2 bytes of
2233 * the body (like we did for the first SMB2 request).
2236 req->in.vector = talloc_realloc(req, req->in.vector,
2237 struct iovec,
2238 req->in.vector_count + 1);
2239 if (req->in.vector == NULL) {
2240 return -1;
2242 req->in.vector_count += 1;
2245 * We assume it's a SMB2 request,
2246 * and we first get the header and the
2247 * first 2 bytes (the struct size) of the body
2249 len = SMB2_HDR_BODY + 2;
2251 if (len > state->missing) {
2252 /* let the caller handle the error */
2253 len = state->missing;
2256 state->missing -= len;
2257 state->asked_for_header = true;
2259 buf = talloc_array(req->in.vector, uint8_t, len);
2260 if (buf == NULL) {
2261 return -1;
2264 req->in.vector[idx].iov_base = (void *)buf;
2265 req->in.vector[idx].iov_len = len;
2267 vector = talloc_array(mem_ctx, struct iovec, 1);
2268 if (vector == NULL) {
2269 return -1;
2272 vector[0] = req->in.vector[idx];
2274 *_vector = vector;
2275 *_count = 1;
2276 return 0;
2279 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2281 struct tevent_req *req =
2282 tevent_req_callback_data(subreq,
2283 struct tevent_req);
2284 int ret;
2285 int sys_errno;
2286 NTSTATUS status;
2288 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2289 if (ret == -1) {
2290 status = map_nt_error_from_unix(sys_errno);
2291 tevent_req_nterror(req, status);
2292 return;
2295 tevent_req_done(req);
2298 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2299 TALLOC_CTX *mem_ctx,
2300 struct smbd_smb2_request **_smb2_req)
2302 struct smbd_smb2_request_read_state *state =
2303 tevent_req_data(req,
2304 struct smbd_smb2_request_read_state);
2305 NTSTATUS status;
2307 if (tevent_req_is_nterror(req, &status)) {
2308 tevent_req_received(req);
2309 return status;
2312 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2313 *_smb2_req = state->smb2_req;
2314 tevent_req_received(req);
2315 return NT_STATUS_OK;
2318 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2320 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2321 const uint8_t *inbuf, size_t size)
2323 NTSTATUS status;
2324 struct smbd_smb2_request *req = NULL;
2325 struct tevent_req *subreq;
2327 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2328 (unsigned int)size));
2330 status = smbd_initialize_smb2(sconn);
2331 if (!NT_STATUS_IS_OK(status)) {
2332 smbd_server_connection_terminate(sconn, nt_errstr(status));
2333 return;
2336 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2337 if (!NT_STATUS_IS_OK(status)) {
2338 smbd_server_connection_terminate(sconn, nt_errstr(status));
2339 return;
2342 status = smbd_smb2_request_setup_out(req);
2343 if (!NT_STATUS_IS_OK(status)) {
2344 smbd_server_connection_terminate(sconn, nt_errstr(status));
2345 return;
2348 status = smbd_smb2_request_dispatch(req);
2349 if (!NT_STATUS_IS_OK(status)) {
2350 smbd_server_connection_terminate(sconn, nt_errstr(status));
2351 return;
2354 /* ask for the next request */
2355 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2356 if (subreq == NULL) {
2357 smbd_server_connection_terminate(sconn, "no memory for reading");
2358 return;
2360 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2362 sconn->num_requests++;
2365 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2367 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2368 struct smbd_server_connection);
2369 NTSTATUS status;
2370 struct smbd_smb2_request *req = NULL;
2372 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2373 TALLOC_FREE(subreq);
2374 if (!NT_STATUS_IS_OK(status)) {
2375 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2376 nt_errstr(status)));
2377 smbd_server_connection_terminate(sconn, nt_errstr(status));
2378 return;
2381 if (req->in.nbt_hdr[0] != 0x00) {
2382 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2383 req->in.nbt_hdr[0]));
2384 TALLOC_FREE(req);
2385 goto next;
2388 req->current_idx = 1;
2390 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2391 req->current_idx, req->in.vector_count));
2393 status = smbd_smb2_request_validate(req);
2394 if (!NT_STATUS_IS_OK(status)) {
2395 smbd_server_connection_terminate(sconn, nt_errstr(status));
2396 return;
2399 status = smbd_smb2_request_setup_out(req);
2400 if (!NT_STATUS_IS_OK(status)) {
2401 smbd_server_connection_terminate(sconn, nt_errstr(status));
2402 return;
2405 status = smbd_smb2_request_dispatch(req);
2406 if (!NT_STATUS_IS_OK(status)) {
2407 smbd_server_connection_terminate(sconn, nt_errstr(status));
2408 return;
2411 next:
2412 /* ask for the next request (this constructs the main loop) */
2413 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2414 if (subreq == NULL) {
2415 smbd_server_connection_terminate(sconn, "no memory for reading");
2416 return;
2418 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2420 sconn->num_requests++;
2422 /* The timeout_processing function isn't run nearly
2423 often enough to implement 'max log size' without
2424 overrunning the size of the file by many megabytes.
2425 This is especially true if we are running at debug
2426 level 10. Checking every 50 SMB2s is a nice
2427 tradeoff of performance vs log file size overrun. */
2429 if ((sconn->num_requests % 50) == 0 &&
2430 need_to_check_log_size()) {
2431 change_to_root_user();
2432 check_log_size();