Second part of bugfix for bug #8335 - file copy aborts with smb2_validate_message_id...
[Samba.git] / source3 / smbd / smb2_server.c
blobb77c6366c6254589a99380670360b84ea150a191
1 /*
2 Unix SMB/CIFS implementation.
3 Core SMB2 server
5 Copyright (C) Stefan Metzmacher 2009
6 Copyright (C) Jeremy Allison 2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../libcli/smb/smb_common.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "../lib/util/tevent_ntstatus.h"
28 #include "smbprofile.h"
30 #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9)
32 static const char *smb2_names[] = {
33 "SMB2_NEGPROT",
34 "SMB2_SESSSETUP",
35 "SMB2_LOGOFF",
36 "SMB2_TCON",
37 "SMB2_TDIS",
38 "SMB2_CREATE",
39 "SMB2_CLOSE",
40 "SMB2_FLUSH",
41 "SMB2_READ",
42 "SMB2_WRITE",
43 "SMB2_LOCK",
44 "SMB2_IOCTL",
45 "SMB2_CANCEL",
46 "SMB2_KEEPALIVE",
47 "SMB2_FIND",
48 "SMB2_NOTIFY",
49 "SMB2_GETINFO",
50 "SMB2_SETINFO",
51 "SMB2_BREAK"
54 const char *smb2_opcode_name(uint16_t opcode)
56 if (opcode > 0x12) {
57 return "Bad SMB2 opcode";
59 return smb2_names[opcode];
62 static void print_req_vectors(struct smbd_smb2_request *req)
64 int i;
66 for (i = 0; i < req->in.vector_count; i++) {
67 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
68 (unsigned int)i,
69 (unsigned int)req->in.vector[i].iov_len);
71 for (i = 0; i < req->out.vector_count; i++) {
72 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
73 (unsigned int)i,
74 (unsigned int)req->out.vector[i].iov_len);
78 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
80 if (size < (4 + SMB2_HDR_BODY)) {
81 return false;
84 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
85 return false;
88 return true;
91 static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
93 NTSTATUS status;
94 int ret;
96 TALLOC_FREE(sconn->smb1.fde);
98 sconn->smb2.event_ctx = smbd_event_context();
100 sconn->smb2.recv_queue = tevent_queue_create(sconn, "smb2 recv queue");
101 if (sconn->smb2.recv_queue == NULL) {
102 return NT_STATUS_NO_MEMORY;
105 sconn->smb2.send_queue = tevent_queue_create(sconn, "smb2 send queue");
106 if (sconn->smb2.send_queue == NULL) {
107 return NT_STATUS_NO_MEMORY;
110 sconn->smb2.sessions.idtree = idr_init(sconn);
111 if (sconn->smb2.sessions.idtree == NULL) {
112 return NT_STATUS_NO_MEMORY;
114 sconn->smb2.sessions.limit = 0x0000FFFE;
115 sconn->smb2.sessions.list = NULL;
116 sconn->smb2.seqnum_low = 0;
117 sconn->smb2.credits_granted = 0;
118 sconn->smb2.max_credits = lp_smb2_max_credits();
119 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
120 DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR*sconn->smb2.max_credits);
121 if (sconn->smb2.credits_bitmap == NULL) {
122 return NT_STATUS_NO_MEMORY;
125 ret = tstream_bsd_existing_socket(sconn, sconn->sock,
126 &sconn->smb2.stream);
127 if (ret == -1) {
128 status = map_nt_error_from_unix(errno);
129 return status;
132 /* Ensure child is set to non-blocking mode */
133 set_blocking(sconn->sock, false);
134 return NT_STATUS_OK;
137 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
138 #define _smb2_setlen(_buf,len) do { \
139 uint8_t *buf = (uint8_t *)_buf; \
140 buf[0] = 0; \
141 buf[1] = ((len)&0xFF0000)>>16; \
142 buf[2] = ((len)&0xFF00)>>8; \
143 buf[3] = (len)&0xFF; \
144 } while (0)
146 static void smb2_setup_nbt_length(struct iovec *vector, int count)
148 size_t len = 0;
149 int i;
151 for (i=1; i < count; i++) {
152 len += vector[i].iov_len;
155 _smb2_setlen(vector[0].iov_base, len);
158 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request **req)
160 if (*req) {
161 (*req)->parent = NULL;
162 (*req)->mem_pool = NULL;
165 return 0;
168 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
170 if (req->parent) {
171 *req->parent = NULL;
172 talloc_free(req->mem_pool);
175 return 0;
178 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
180 TALLOC_CTX *mem_pool;
181 struct smbd_smb2_request **parent;
182 struct smbd_smb2_request *req;
184 #if 0
185 /* Enable this to find subtle valgrind errors. */
186 mem_pool = talloc_init("smbd_smb2_request_allocate");
187 #else
188 mem_pool = talloc_pool(mem_ctx, 8192);
189 #endif
190 if (mem_pool == NULL) {
191 return NULL;
194 parent = talloc(mem_pool, struct smbd_smb2_request *);
195 if (parent == NULL) {
196 talloc_free(mem_pool);
197 return NULL;
200 req = talloc_zero(parent, struct smbd_smb2_request);
201 if (req == NULL) {
202 talloc_free(mem_pool);
203 return NULL;
205 *parent = req;
206 req->mem_pool = mem_pool;
207 req->parent = parent;
209 talloc_set_destructor(parent, smbd_smb2_request_parent_destructor);
210 talloc_set_destructor(req, smbd_smb2_request_destructor);
212 return req;
215 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
216 const uint8_t *inbuf, size_t size,
217 struct smbd_smb2_request **_req)
219 struct smbd_smb2_request *req;
220 uint32_t protocol_version;
221 const uint8_t *inhdr = NULL;
222 off_t ofs = 0;
223 uint16_t cmd;
224 uint32_t next_command_ofs;
226 if (size < (4 + SMB2_HDR_BODY + 2)) {
227 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
228 return NT_STATUS_INVALID_PARAMETER;
231 inhdr = inbuf + 4;
233 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
234 if (protocol_version != SMB2_MAGIC) {
235 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
236 protocol_version));
237 return NT_STATUS_INVALID_PARAMETER;
240 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
241 if (cmd != SMB2_OP_NEGPROT) {
242 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
243 cmd));
244 return NT_STATUS_INVALID_PARAMETER;
247 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
248 if (next_command_ofs != 0) {
249 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
250 next_command_ofs));
251 return NT_STATUS_INVALID_PARAMETER;
254 req = smbd_smb2_request_allocate(sconn);
255 if (req == NULL) {
256 return NT_STATUS_NO_MEMORY;
258 req->sconn = sconn;
260 talloc_steal(req, inbuf);
262 req->in.vector = talloc_array(req, struct iovec, 4);
263 if (req->in.vector == NULL) {
264 TALLOC_FREE(req);
265 return NT_STATUS_NO_MEMORY;
267 req->in.vector_count = 4;
269 memcpy(req->in.nbt_hdr, inbuf, 4);
271 ofs = 0;
272 req->in.vector[0].iov_base = (void *)req->in.nbt_hdr;
273 req->in.vector[0].iov_len = 4;
274 ofs += req->in.vector[0].iov_len;
276 req->in.vector[1].iov_base = (void *)(inbuf + ofs);
277 req->in.vector[1].iov_len = SMB2_HDR_BODY;
278 ofs += req->in.vector[1].iov_len;
280 req->in.vector[2].iov_base = (void *)(inbuf + ofs);
281 req->in.vector[2].iov_len = SVAL(inbuf, ofs) & 0xFFFE;
282 ofs += req->in.vector[2].iov_len;
284 if (ofs > size) {
285 return NT_STATUS_INVALID_PARAMETER;
288 req->in.vector[3].iov_base = (void *)(inbuf + ofs);
289 req->in.vector[3].iov_len = size - ofs;
290 ofs += req->in.vector[3].iov_len;
292 req->current_idx = 1;
294 *_req = req;
295 return NT_STATUS_OK;
298 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
299 const uint8_t *inhdr)
301 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
302 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
303 uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
304 unsigned int bitmap_offset;
306 if (opcode == SMB2_OP_CANCEL) {
307 /* SMB2_CANCEL requests by definition resend messageids. */
308 return true;
311 if (message_id < sconn->smb2.seqnum_low ||
312 message_id > (sconn->smb2.seqnum_low +
313 (sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR))) {
314 DEBUG(0,("smb2_validate_message_id: bad message_id "
315 "%llu (low = %llu, max = %lu)\n",
316 (unsigned long long)message_id,
317 (unsigned long long)sconn->smb2.seqnum_low,
318 (unsigned long)sconn->smb2.max_credits ));
319 return false;
322 /* client just used a credit. */
323 SMB_ASSERT(sconn->smb2.credits_granted > 0);
324 sconn->smb2.credits_granted -= 1;
326 /* Mark the message_id as seen in the bitmap. */
327 bitmap_offset = (unsigned int)(message_id %
328 (uint64_t)(sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR));
329 if (bitmap_query(credits_bm, bitmap_offset)) {
330 DEBUG(0,("smb2_validate_message_id: duplicate message_id "
331 "%llu (bm offset %u)\n",
332 (unsigned long long)message_id,
333 bitmap_offset));
334 return false;
336 bitmap_set(credits_bm, bitmap_offset);
338 if (message_id == sconn->smb2.seqnum_low + 1) {
339 /* Move the window forward by all the message_id's
340 already seen. */
341 while (bitmap_query(credits_bm, bitmap_offset)) {
342 DEBUG(10,("smb2_validate_message_id: clearing "
343 "id %llu (position %u) from bitmap\n",
344 (unsigned long long)(sconn->smb2.seqnum_low + 1),
345 bitmap_offset ));
346 bitmap_clear(credits_bm, bitmap_offset);
347 sconn->smb2.seqnum_low += 1;
348 bitmap_offset = (bitmap_offset + 1) %
349 (sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR);
353 return true;
356 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
358 int count;
359 int idx;
360 bool compound_related = false;
362 count = req->in.vector_count;
364 if (count < 4) {
365 /* It's not a SMB2 request */
366 return NT_STATUS_INVALID_PARAMETER;
369 for (idx=1; idx < count; idx += 3) {
370 const uint8_t *inhdr = NULL;
371 uint32_t flags;
373 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
374 return NT_STATUS_INVALID_PARAMETER;
377 if (req->in.vector[idx+1].iov_len < 2) {
378 return NT_STATUS_INVALID_PARAMETER;
381 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
383 /* Check the SMB2 header */
384 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
385 return NT_STATUS_INVALID_PARAMETER;
388 if (!smb2_validate_message_id(req->sconn, inhdr)) {
389 return NT_STATUS_INVALID_PARAMETER;
392 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
393 if (idx == 1) {
395 * the 1st request should never have the
396 * SMB2_HDR_FLAG_CHAINED flag set
398 if (flags & SMB2_HDR_FLAG_CHAINED) {
399 req->next_status = NT_STATUS_INVALID_PARAMETER;
400 return NT_STATUS_OK;
402 } else if (idx == 4) {
404 * the 2nd request triggers related vs. unrelated
405 * compounded requests
407 if (flags & SMB2_HDR_FLAG_CHAINED) {
408 compound_related = true;
410 } else if (idx > 4) {
411 #if 0
413 * It seems the this tests are wrong
414 * see the SMB2-COMPOUND test
418 * all other requests should match the 2nd one
420 if (flags & SMB2_HDR_FLAG_CHAINED) {
421 if (!compound_related) {
422 req->next_status =
423 NT_STATUS_INVALID_PARAMETER;
424 return NT_STATUS_OK;
426 } else {
427 if (compound_related) {
428 req->next_status =
429 NT_STATUS_INVALID_PARAMETER;
430 return NT_STATUS_OK;
433 #endif
437 return NT_STATUS_OK;
440 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
441 const struct iovec *in_vector,
442 struct iovec *out_vector)
444 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
445 uint16_t credits_requested = 0;
446 uint16_t credits_granted = 0;
448 if (in_vector != NULL) {
449 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
450 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
453 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
455 if (credits_requested) {
456 uint16_t modified_credits_requested;
457 uint32_t multiplier;
460 * Split up max_credits into 1/16ths, and then scale
461 * the requested credits by how many 16ths have been
462 * currently granted. Less than 1/16th == grant all
463 * requested (100%), scale down as more have been
464 * granted. Never ask for less than 1 as the client
465 * asked for at least 1. JRA.
468 multiplier = 16 - (((sconn->smb2.credits_granted * 16) / sconn->smb2.max_credits) % 16);
470 modified_credits_requested = (multiplier * credits_requested) / 16;
471 if (modified_credits_requested == 0) {
472 modified_credits_requested = 1;
475 /* Remember what we gave out. */
476 credits_granted = MIN(modified_credits_requested,
477 (sconn->smb2.max_credits - sconn->smb2.credits_granted));
480 if (credits_granted == 0 && sconn->smb2.credits_granted == 0) {
481 /* First negprot packet, or ensure the client credits can
482 never drop to zero. */
483 credits_granted = 1;
486 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
487 sconn->smb2.credits_granted += credits_granted;
489 DEBUG(10,("smb2_set_operation_credit: requested %u, "
490 "granted %u, total granted %u\n",
491 (unsigned int)credits_requested,
492 (unsigned int)credits_granted,
493 (unsigned int)sconn->smb2.credits_granted ));
496 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
497 struct smbd_smb2_request *outreq)
499 int count, idx;
501 count = outreq->out.vector_count;
503 for (idx=1; idx < count; idx += 3) {
504 smb2_set_operation_credit(outreq->sconn,
505 &inreq->in.vector[idx],
506 &outreq->out.vector[idx]);
510 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
512 struct iovec *vector;
513 int count;
514 int idx;
516 count = req->in.vector_count;
517 vector = talloc_zero_array(req, struct iovec, count);
518 if (vector == NULL) {
519 return NT_STATUS_NO_MEMORY;
522 vector[0].iov_base = req->out.nbt_hdr;
523 vector[0].iov_len = 4;
524 SIVAL(req->out.nbt_hdr, 0, 0);
526 for (idx=1; idx < count; idx += 3) {
527 const uint8_t *inhdr = NULL;
528 uint32_t in_flags;
529 uint8_t *outhdr = NULL;
530 uint8_t *outbody = NULL;
531 uint32_t next_command_ofs = 0;
532 struct iovec *current = &vector[idx];
534 if ((idx + 3) < count) {
535 /* we have a next command -
536 * setup for the error case. */
537 next_command_ofs = SMB2_HDR_BODY + 9;
540 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
541 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
543 outhdr = talloc_zero_array(vector, uint8_t,
544 OUTVEC_ALLOC_SIZE);
545 if (outhdr == NULL) {
546 return NT_STATUS_NO_MEMORY;
549 outbody = outhdr + SMB2_HDR_BODY;
551 current[0].iov_base = (void *)outhdr;
552 current[0].iov_len = SMB2_HDR_BODY;
554 current[1].iov_base = (void *)outbody;
555 current[1].iov_len = 8;
557 current[2].iov_base = NULL;
558 current[2].iov_len = 0;
560 /* setup the SMB2 header */
561 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
562 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
563 SSVAL(outhdr, SMB2_HDR_EPOCH, 0);
564 SIVAL(outhdr, SMB2_HDR_STATUS,
565 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
566 SSVAL(outhdr, SMB2_HDR_OPCODE,
567 SVAL(inhdr, SMB2_HDR_OPCODE));
568 SIVAL(outhdr, SMB2_HDR_FLAGS,
569 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
570 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
571 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
572 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
573 SIVAL(outhdr, SMB2_HDR_PID,
574 IVAL(inhdr, SMB2_HDR_PID));
575 SIVAL(outhdr, SMB2_HDR_TID,
576 IVAL(inhdr, SMB2_HDR_TID));
577 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
578 BVAL(inhdr, SMB2_HDR_SESSION_ID));
579 memset(outhdr + SMB2_HDR_SIGNATURE, 0, 16);
581 /* setup error body header */
582 SSVAL(outbody, 0x00, 0x08 + 1);
583 SSVAL(outbody, 0x02, 0);
584 SIVAL(outbody, 0x04, 0);
587 req->out.vector = vector;
588 req->out.vector_count = count;
590 /* setup the length of the NBT packet */
591 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
593 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
595 return NT_STATUS_OK;
598 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
599 const char *reason,
600 const char *location)
602 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
603 reason, location));
604 exit_server_cleanly(reason);
607 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
608 struct iovec *outvec,
609 const struct iovec *srcvec)
611 /* vec[0] is always boilerplate and must
612 * be allocated with size OUTVEC_ALLOC_SIZE. */
614 outvec[0].iov_base = talloc_memdup(ctx,
615 srcvec[0].iov_base,
616 OUTVEC_ALLOC_SIZE);
617 if (!outvec[0].iov_base) {
618 return false;
620 outvec[0].iov_len = SMB2_HDR_BODY;
623 * If this is a "standard" vec[1] of length 8,
624 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
625 * then duplicate this. Else use talloc_memdup().
628 if (srcvec[1].iov_len == 8 &&
629 srcvec[1].iov_base ==
630 ((uint8_t *)srcvec[0].iov_base) +
631 SMB2_HDR_BODY) {
632 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
633 SMB2_HDR_BODY;
634 outvec[1].iov_len = 8;
635 } else {
636 outvec[1].iov_base = talloc_memdup(ctx,
637 srcvec[1].iov_base,
638 srcvec[1].iov_len);
639 if (!outvec[1].iov_base) {
640 return false;
642 outvec[1].iov_len = srcvec[1].iov_len;
646 * If this is a "standard" vec[2] of length 1,
647 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
648 * then duplicate this. Else use talloc_memdup().
651 if (srcvec[2].iov_base &&
652 srcvec[2].iov_len) {
653 if (srcvec[2].iov_base ==
654 ((uint8_t *)srcvec[0].iov_base) +
655 (OUTVEC_ALLOC_SIZE - 1) &&
656 srcvec[2].iov_len == 1) {
657 /* Common SMB2 error packet case. */
658 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
659 (OUTVEC_ALLOC_SIZE - 1);
660 } else {
661 outvec[2].iov_base = talloc_memdup(ctx,
662 srcvec[2].iov_base,
663 srcvec[2].iov_len);
664 if (!outvec[2].iov_base) {
665 return false;
668 outvec[2].iov_len = srcvec[2].iov_len;
669 } else {
670 outvec[2].iov_base = NULL;
671 outvec[2].iov_len = 0;
673 return true;
676 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
678 struct smbd_smb2_request *newreq = NULL;
679 struct iovec *outvec = NULL;
680 int count = req->out.vector_count;
681 int i;
683 newreq = smbd_smb2_request_allocate(req->sconn);
684 if (!newreq) {
685 return NULL;
688 newreq->sconn = req->sconn;
689 newreq->session = req->session;
690 newreq->do_signing = req->do_signing;
691 newreq->current_idx = req->current_idx;
692 newreq->async = false;
693 newreq->cancelled = false;
694 /* Note we are leaving:
695 ->tcon
696 ->smb1req
697 ->compat_chain_fsp
698 uninitialized as NULL here as
699 they're not used in the interim
700 response code. JRA. */
702 outvec = talloc_zero_array(newreq, struct iovec, count);
703 if (!outvec) {
704 TALLOC_FREE(newreq);
705 return NULL;
707 newreq->out.vector = outvec;
708 newreq->out.vector_count = count;
710 /* Setup the outvec's identically to req. */
711 outvec[0].iov_base = newreq->out.nbt_hdr;
712 outvec[0].iov_len = 4;
713 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
715 /* Setup the vectors identically to the ones in req. */
716 for (i = 1; i < count; i += 3) {
717 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
718 break;
722 if (i < count) {
723 /* Alloc failed. */
724 TALLOC_FREE(newreq);
725 return NULL;
728 smb2_setup_nbt_length(newreq->out.vector,
729 newreq->out.vector_count);
731 return newreq;
734 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
736 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
738 int i = 0;
739 uint8_t *outhdr = NULL;
740 struct smbd_smb2_request *nreq = NULL;
742 /* Create a new smb2 request we'll use
743 for the interim return. */
744 nreq = dup_smb2_req(req);
745 if (!nreq) {
746 return NT_STATUS_NO_MEMORY;
749 /* Lose the last 3 out vectors. They're the
750 ones we'll be using for the async reply. */
751 nreq->out.vector_count -= 3;
753 smb2_setup_nbt_length(nreq->out.vector,
754 nreq->out.vector_count);
756 /* Step back to the previous reply. */
757 i = nreq->current_idx - 3;
758 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
759 /* And end the chain. */
760 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
762 /* Calculate outgoing credits */
763 smb2_calculate_credits(req, nreq);
765 /* Re-sign if needed. */
766 if (nreq->do_signing) {
767 NTSTATUS status;
768 status = smb2_signing_sign_pdu(nreq->session->session_key,
769 &nreq->out.vector[i], 3);
770 if (!NT_STATUS_IS_OK(status)) {
771 return status;
774 if (DEBUGLEVEL >= 10) {
775 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
776 (unsigned int)nreq->current_idx );
777 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
778 (unsigned int)nreq->out.vector_count );
779 print_req_vectors(nreq);
781 nreq->subreq = tstream_writev_queue_send(nreq,
782 nreq->sconn->smb2.event_ctx,
783 nreq->sconn->smb2.stream,
784 nreq->sconn->smb2.send_queue,
785 nreq->out.vector,
786 nreq->out.vector_count);
788 if (nreq->subreq == NULL) {
789 return NT_STATUS_NO_MEMORY;
792 tevent_req_set_callback(nreq->subreq,
793 smbd_smb2_request_writev_done,
794 nreq);
796 return NT_STATUS_OK;
799 struct smbd_smb2_request_pending_state {
800 struct smbd_server_connection *sconn;
801 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
802 struct iovec vector[3];
805 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
807 struct smbd_smb2_request_pending_state *state =
808 tevent_req_callback_data(subreq,
809 struct smbd_smb2_request_pending_state);
810 struct smbd_server_connection *sconn = state->sconn;
811 int ret;
812 int sys_errno;
814 ret = tstream_writev_queue_recv(subreq, &sys_errno);
815 TALLOC_FREE(subreq);
816 if (ret == -1) {
817 NTSTATUS status = map_nt_error_from_unix(sys_errno);
818 smbd_server_connection_terminate(sconn, nt_errstr(status));
819 return;
822 TALLOC_FREE(state);
825 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
826 struct tevent_req *subreq)
828 NTSTATUS status;
829 struct smbd_smb2_request_pending_state *state = NULL;
830 int i = req->current_idx;
831 uint8_t *reqhdr = NULL;
832 uint8_t *hdr = NULL;
833 uint8_t *body = NULL;
834 uint32_t flags = 0;
835 uint64_t message_id = 0;
836 uint64_t async_id = 0;
837 struct iovec *outvec = NULL;
839 if (!tevent_req_is_in_progress(subreq)) {
840 return NT_STATUS_OK;
843 req->subreq = subreq;
844 subreq = NULL;
846 if (req->async) {
847 /* We're already async. */
848 return NT_STATUS_OK;
851 if (req->in.vector_count > i + 3) {
853 * We're trying to go async in a compound
854 * request chain. This is not allowed.
855 * Cancel the outstanding request.
857 tevent_req_cancel(req->subreq);
858 return smbd_smb2_request_error(req,
859 NT_STATUS_INSUFFICIENT_RESOURCES);
862 if (DEBUGLEVEL >= 10) {
863 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
864 (unsigned int)req->current_idx );
865 print_req_vectors(req);
868 if (req->out.vector_count > 4) {
869 /* This is a compound reply. We
870 * must do an interim response
871 * followed by the async response
872 * to match W2K8R2.
874 status = smb2_send_async_interim_response(req);
875 if (!NT_STATUS_IS_OK(status)) {
876 return status;
880 /* Don't return an intermediate packet on a pipe read/write. */
881 if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
882 return NT_STATUS_OK;
885 reqhdr = (uint8_t *)req->out.vector[i].iov_base;
886 flags = (IVAL(reqhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
887 message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
888 async_id = message_id; /* keep it simple for now... */
891 * What we send is identical to a smbd_smb2_request_error
892 * packet with an error status of STATUS_PENDING. Make use
893 * of this fact sometime when refactoring. JRA.
896 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
897 if (state == NULL) {
898 return NT_STATUS_NO_MEMORY;
900 state->sconn = req->sconn;
902 state->vector[0].iov_base = (void *)state->buf;
903 state->vector[0].iov_len = 4;
905 state->vector[1].iov_base = state->buf + 4;
906 state->vector[1].iov_len = SMB2_HDR_BODY;
908 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
909 state->vector[2].iov_len = 9;
911 smb2_setup_nbt_length(state->vector, 3);
913 hdr = (uint8_t *)state->vector[1].iov_base;
914 body = (uint8_t *)state->vector[2].iov_base;
916 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
917 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
918 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
919 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
920 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(reqhdr, SMB2_HDR_OPCODE));
922 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
923 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
924 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
925 SBVAL(hdr, SMB2_HDR_PID, async_id);
926 SBVAL(hdr, SMB2_HDR_SESSION_ID,
927 BVAL(reqhdr, SMB2_HDR_SESSION_ID));
928 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
930 SSVAL(body, 0x00, 0x08 + 1);
932 SCVAL(body, 0x02, 0);
933 SCVAL(body, 0x03, 0);
934 SIVAL(body, 0x04, 0);
935 /* Match W2K8R2... */
936 SCVAL(body, 0x08, 0x21);
938 /* Ensure we correctly go through crediting. Grant
939 the credits now, and zero credits on the final
940 response. */
941 smb2_set_operation_credit(req->sconn,
942 &req->in.vector[i],
943 &state->vector[1]);
945 if (req->do_signing) {
946 status = smb2_signing_sign_pdu(req->session->session_key,
947 &state->vector[1], 2);
948 if (!NT_STATUS_IS_OK(status)) {
949 return status;
953 subreq = tstream_writev_queue_send(state,
954 req->sconn->smb2.event_ctx,
955 req->sconn->smb2.stream,
956 req->sconn->smb2.send_queue,
957 state->vector,
960 if (subreq == NULL) {
961 return NT_STATUS_NO_MEMORY;
964 tevent_req_set_callback(subreq,
965 smbd_smb2_request_pending_writev_done,
966 state);
968 /* Note we're going async with this request. */
969 req->async = true;
972 * Now manipulate req so that the outstanding async request
973 * is the only one left in the struct smbd_smb2_request.
976 if (req->current_idx == 1) {
977 /* There was only one. */
978 goto out;
981 /* Re-arrange the in.vectors. */
982 req->in.vector[1] = req->in.vector[i];
983 req->in.vector[2] = req->in.vector[i+1];
984 req->in.vector[3] = req->in.vector[i+2];
985 req->in.vector_count = 4;
986 /* Reset the new in size. */
987 smb2_setup_nbt_length(req->in.vector, 4);
989 /* Now recreate the out.vectors. */
990 outvec = talloc_zero_array(req, struct iovec, 4);
991 if (!outvec) {
992 return NT_STATUS_NO_MEMORY;
995 /* 0 is always boilerplate and must
996 * be of size 4 for the length field. */
998 outvec[0].iov_base = req->out.nbt_hdr;
999 outvec[0].iov_len = 4;
1000 SIVAL(req->out.nbt_hdr, 0, 0);
1002 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
1003 return NT_STATUS_NO_MEMORY;
1006 TALLOC_FREE(req->out.vector);
1008 req->out.vector = outvec;
1010 req->current_idx = 1;
1011 req->out.vector_count = 4;
1013 out:
1015 smb2_setup_nbt_length(req->out.vector,
1016 req->out.vector_count);
1018 /* Ensure our final reply matches the interim one. */
1019 reqhdr = (uint8_t *)req->out.vector[1].iov_base;
1020 SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1021 SBVAL(reqhdr, SMB2_HDR_PID, async_id);
1024 const uint8_t *inhdr =
1025 (const uint8_t *)req->in.vector[1].iov_base;
1026 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1027 "going async\n",
1028 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1029 (unsigned long long)async_id ));
1031 return NT_STATUS_OK;
1034 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1036 struct smbd_server_connection *sconn = req->sconn;
1037 struct smbd_smb2_request *cur;
1038 const uint8_t *inhdr;
1039 int i = req->current_idx;
1040 uint32_t flags;
1041 uint64_t search_message_id;
1042 uint64_t search_async_id;
1043 uint64_t found_id;
1045 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1047 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1048 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1049 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1052 * we don't need the request anymore
1053 * cancel requests never have a response
1055 DLIST_REMOVE(req->sconn->smb2.requests, req);
1056 TALLOC_FREE(req);
1058 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1059 const uint8_t *outhdr;
1060 uint64_t message_id;
1061 uint64_t async_id;
1063 i = cur->current_idx;
1065 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1067 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1068 async_id = BVAL(outhdr, SMB2_HDR_PID);
1070 if (flags & SMB2_HDR_FLAG_ASYNC) {
1071 if (search_async_id == async_id) {
1072 found_id = async_id;
1073 break;
1075 } else {
1076 if (search_message_id == message_id) {
1077 found_id = message_id;
1078 break;
1083 if (cur && cur->subreq) {
1084 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1085 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1086 "cancel opcode[%s] mid %llu\n",
1087 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1088 (unsigned long long)found_id ));
1089 tevent_req_cancel(cur->subreq);
1092 return NT_STATUS_OK;
1095 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1097 const uint8_t *inhdr;
1098 int i = req->current_idx;
1099 uint16_t opcode;
1100 uint32_t flags;
1101 uint64_t mid;
1102 NTSTATUS status;
1103 NTSTATUS session_status;
1104 uint32_t allowed_flags;
1105 NTSTATUS return_value;
1107 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1109 /* TODO: verify more things */
1111 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1112 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1113 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1114 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1115 smb2_opcode_name(opcode),
1116 (unsigned long long)mid));
1118 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1119 SMB2_HDR_FLAG_SIGNED |
1120 SMB2_HDR_FLAG_DFS;
1121 if (opcode == SMB2_OP_CANCEL) {
1122 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1124 if ((flags & ~allowed_flags) != 0) {
1125 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1129 * Check if the client provided a valid session id,
1130 * if so smbd_smb2_request_check_session() calls
1131 * set_current_user_info().
1133 * As some command don't require a valid session id
1134 * we defer the check of the session_status
1136 session_status = smbd_smb2_request_check_session(req);
1138 req->do_signing = false;
1139 if (flags & SMB2_HDR_FLAG_SIGNED) {
1140 if (!NT_STATUS_IS_OK(session_status)) {
1141 return smbd_smb2_request_error(req, session_status);
1144 req->do_signing = true;
1145 status = smb2_signing_check_pdu(req->session->session_key,
1146 &req->in.vector[i], 3);
1147 if (!NT_STATUS_IS_OK(status)) {
1148 return smbd_smb2_request_error(req, status);
1150 } else if (req->session && req->session->do_signing) {
1151 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1154 if (flags & SMB2_HDR_FLAG_CHAINED) {
1156 * This check is mostly for giving the correct error code
1157 * for compounded requests.
1159 * TODO: we may need to move this after the session
1160 * and tcon checks.
1162 if (!NT_STATUS_IS_OK(req->next_status)) {
1163 return smbd_smb2_request_error(req, req->next_status);
1165 } else {
1166 req->compat_chain_fsp = NULL;
1169 switch (opcode) {
1170 case SMB2_OP_NEGPROT:
1171 /* This call needs to be run as root */
1172 change_to_root_user();
1175 START_PROFILE(smb2_negprot);
1176 return_value = smbd_smb2_request_process_negprot(req);
1177 END_PROFILE(smb2_negprot);
1179 break;
1181 case SMB2_OP_SESSSETUP:
1182 /* This call needs to be run as root */
1183 change_to_root_user();
1186 START_PROFILE(smb2_sesssetup);
1187 return_value = smbd_smb2_request_process_sesssetup(req);
1188 END_PROFILE(smb2_sesssetup);
1190 break;
1192 case SMB2_OP_LOGOFF:
1193 if (!NT_STATUS_IS_OK(session_status)) {
1194 return_value = smbd_smb2_request_error(req, session_status);
1195 break;
1198 /* This call needs to be run as root */
1199 change_to_root_user();
1202 START_PROFILE(smb2_logoff);
1203 return_value = smbd_smb2_request_process_logoff(req);
1204 END_PROFILE(smb2_logoff);
1206 break;
1208 case SMB2_OP_TCON:
1209 if (!NT_STATUS_IS_OK(session_status)) {
1210 return_value = smbd_smb2_request_error(req, session_status);
1211 break;
1215 * This call needs to be run as root.
1217 * smbd_smb2_request_process_tcon()
1218 * calls make_connection_snum(), which will call
1219 * change_to_user(), when needed.
1221 change_to_root_user();
1224 START_PROFILE(smb2_tcon);
1225 return_value = smbd_smb2_request_process_tcon(req);
1226 END_PROFILE(smb2_tcon);
1228 break;
1230 case SMB2_OP_TDIS:
1231 if (!NT_STATUS_IS_OK(session_status)) {
1232 return_value = smbd_smb2_request_error(req, session_status);
1233 break;
1236 * This call needs to be run as user.
1238 * smbd_smb2_request_check_tcon()
1239 * calls change_to_user() on success.
1241 status = smbd_smb2_request_check_tcon(req);
1242 if (!NT_STATUS_IS_OK(status)) {
1243 return_value = smbd_smb2_request_error(req, status);
1244 break;
1246 /* This call needs to be run as root */
1247 change_to_root_user();
1251 START_PROFILE(smb2_tdis);
1252 return_value = smbd_smb2_request_process_tdis(req);
1253 END_PROFILE(smb2_tdis);
1255 break;
1257 case SMB2_OP_CREATE:
1258 if (!NT_STATUS_IS_OK(session_status)) {
1259 return_value = smbd_smb2_request_error(req, session_status);
1260 break;
1263 * This call needs to be run as user.
1265 * smbd_smb2_request_check_tcon()
1266 * calls change_to_user() on success.
1268 status = smbd_smb2_request_check_tcon(req);
1269 if (!NT_STATUS_IS_OK(status)) {
1270 return_value = smbd_smb2_request_error(req, status);
1271 break;
1275 START_PROFILE(smb2_create);
1276 return_value = smbd_smb2_request_process_create(req);
1277 END_PROFILE(smb2_create);
1279 break;
1281 case SMB2_OP_CLOSE:
1282 if (!NT_STATUS_IS_OK(session_status)) {
1283 return_value = smbd_smb2_request_error(req, session_status);
1284 break;
1287 * This call needs to be run as user.
1289 * smbd_smb2_request_check_tcon()
1290 * calls change_to_user() on success.
1292 status = smbd_smb2_request_check_tcon(req);
1293 if (!NT_STATUS_IS_OK(status)) {
1294 return_value = smbd_smb2_request_error(req, status);
1295 break;
1299 START_PROFILE(smb2_close);
1300 return_value = smbd_smb2_request_process_close(req);
1301 END_PROFILE(smb2_close);
1303 break;
1305 case SMB2_OP_FLUSH:
1306 if (!NT_STATUS_IS_OK(session_status)) {
1307 return_value = smbd_smb2_request_error(req, session_status);
1308 break;
1311 * This call needs to be run as user.
1313 * smbd_smb2_request_check_tcon()
1314 * calls change_to_user() on success.
1316 status = smbd_smb2_request_check_tcon(req);
1317 if (!NT_STATUS_IS_OK(status)) {
1318 return_value = smbd_smb2_request_error(req, status);
1319 break;
1323 START_PROFILE(smb2_flush);
1324 return_value = smbd_smb2_request_process_flush(req);
1325 END_PROFILE(smb2_flush);
1327 break;
1329 case SMB2_OP_READ:
1330 if (!NT_STATUS_IS_OK(session_status)) {
1331 return_value = smbd_smb2_request_error(req, session_status);
1332 break;
1335 * This call needs to be run as user.
1337 * smbd_smb2_request_check_tcon()
1338 * calls change_to_user() on success.
1340 status = smbd_smb2_request_check_tcon(req);
1341 if (!NT_STATUS_IS_OK(status)) {
1342 return_value = smbd_smb2_request_error(req, status);
1343 break;
1347 START_PROFILE(smb2_read);
1348 return_value = smbd_smb2_request_process_read(req);
1349 END_PROFILE(smb2_read);
1351 break;
1353 case SMB2_OP_WRITE:
1354 if (!NT_STATUS_IS_OK(session_status)) {
1355 return_value = smbd_smb2_request_error(req, session_status);
1356 break;
1359 * This call needs to be run as user.
1361 * smbd_smb2_request_check_tcon()
1362 * calls change_to_user() on success.
1364 status = smbd_smb2_request_check_tcon(req);
1365 if (!NT_STATUS_IS_OK(status)) {
1366 return_value = smbd_smb2_request_error(req, status);
1367 break;
1371 START_PROFILE(smb2_write);
1372 return_value = smbd_smb2_request_process_write(req);
1373 END_PROFILE(smb2_write);
1375 break;
1377 case SMB2_OP_LOCK:
1378 if (!NT_STATUS_IS_OK(session_status)) {
1379 /* Too ugly to live ? JRA. */
1380 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1381 session_status = NT_STATUS_FILE_CLOSED;
1383 return_value = smbd_smb2_request_error(req, session_status);
1384 break;
1387 * This call needs to be run as user.
1389 * smbd_smb2_request_check_tcon()
1390 * calls change_to_user() on success.
1392 status = smbd_smb2_request_check_tcon(req);
1393 if (!NT_STATUS_IS_OK(status)) {
1394 /* Too ugly to live ? JRA. */
1395 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1396 status = NT_STATUS_FILE_CLOSED;
1398 return_value = smbd_smb2_request_error(req, status);
1399 break;
1403 START_PROFILE(smb2_lock);
1404 return_value = smbd_smb2_request_process_lock(req);
1405 END_PROFILE(smb2_lock);
1407 break;
1409 case SMB2_OP_IOCTL:
1410 if (!NT_STATUS_IS_OK(session_status)) {
1411 return_value = smbd_smb2_request_error(req, session_status);
1412 break;
1415 * This call needs to be run as user.
1417 * smbd_smb2_request_check_tcon()
1418 * calls change_to_user() on success.
1420 status = smbd_smb2_request_check_tcon(req);
1421 if (!NT_STATUS_IS_OK(status)) {
1422 return_value = smbd_smb2_request_error(req, status);
1423 break;
1427 START_PROFILE(smb2_ioctl);
1428 return_value = smbd_smb2_request_process_ioctl(req);
1429 END_PROFILE(smb2_ioctl);
1431 break;
1433 case SMB2_OP_CANCEL:
1435 * This call needs to be run as root
1437 * That is what we also do in the SMB1 case.
1439 change_to_root_user();
1442 START_PROFILE(smb2_cancel);
1443 return_value = smbd_smb2_request_process_cancel(req);
1444 END_PROFILE(smb2_cancel);
1446 break;
1448 case SMB2_OP_KEEPALIVE:
1449 /* This call needs to be run as root */
1450 change_to_root_user();
1453 START_PROFILE(smb2_keepalive);
1454 return_value = smbd_smb2_request_process_keepalive(req);
1455 END_PROFILE(smb2_keepalive);
1457 break;
1459 case SMB2_OP_FIND:
1460 if (!NT_STATUS_IS_OK(session_status)) {
1461 return_value = smbd_smb2_request_error(req, session_status);
1462 break;
1465 * This call needs to be run as user.
1467 * smbd_smb2_request_check_tcon()
1468 * calls change_to_user() on success.
1470 status = smbd_smb2_request_check_tcon(req);
1471 if (!NT_STATUS_IS_OK(status)) {
1472 return_value = smbd_smb2_request_error(req, status);
1473 break;
1477 START_PROFILE(smb2_find);
1478 return_value = smbd_smb2_request_process_find(req);
1479 END_PROFILE(smb2_find);
1481 break;
1483 case SMB2_OP_NOTIFY:
1484 if (!NT_STATUS_IS_OK(session_status)) {
1485 return_value = smbd_smb2_request_error(req, session_status);
1486 break;
1489 * This call needs to be run as user.
1491 * smbd_smb2_request_check_tcon()
1492 * calls change_to_user() on success.
1494 status = smbd_smb2_request_check_tcon(req);
1495 if (!NT_STATUS_IS_OK(status)) {
1496 return_value = smbd_smb2_request_error(req, status);
1497 break;
1501 START_PROFILE(smb2_notify);
1502 return_value = smbd_smb2_request_process_notify(req);
1503 END_PROFILE(smb2_notify);
1505 break;
1507 case SMB2_OP_GETINFO:
1508 if (!NT_STATUS_IS_OK(session_status)) {
1509 return_value = smbd_smb2_request_error(req, session_status);
1510 break;
1513 * This call needs to be run as user.
1515 * smbd_smb2_request_check_tcon()
1516 * calls change_to_user() on success.
1518 status = smbd_smb2_request_check_tcon(req);
1519 if (!NT_STATUS_IS_OK(status)) {
1520 return_value = smbd_smb2_request_error(req, status);
1521 break;
1525 START_PROFILE(smb2_getinfo);
1526 return_value = smbd_smb2_request_process_getinfo(req);
1527 END_PROFILE(smb2_getinfo);
1529 break;
1531 case SMB2_OP_SETINFO:
1532 if (!NT_STATUS_IS_OK(session_status)) {
1533 return_value = smbd_smb2_request_error(req, session_status);
1534 break;
1537 * This call needs to be run as user.
1539 * smbd_smb2_request_check_tcon()
1540 * calls change_to_user() on success.
1542 status = smbd_smb2_request_check_tcon(req);
1543 if (!NT_STATUS_IS_OK(status)) {
1544 return_value = smbd_smb2_request_error(req, status);
1545 break;
1549 START_PROFILE(smb2_setinfo);
1550 return_value = smbd_smb2_request_process_setinfo(req);
1551 END_PROFILE(smb2_setinfo);
1553 break;
1555 case SMB2_OP_BREAK:
1556 if (!NT_STATUS_IS_OK(session_status)) {
1557 return_value = smbd_smb2_request_error(req, session_status);
1558 break;
1561 * This call needs to be run as user.
1563 * smbd_smb2_request_check_tcon()
1564 * calls change_to_user() on success.
1566 status = smbd_smb2_request_check_tcon(req);
1567 if (!NT_STATUS_IS_OK(status)) {
1568 return_value = smbd_smb2_request_error(req, status);
1569 break;
1573 START_PROFILE(smb2_break);
1574 return_value = smbd_smb2_request_process_break(req);
1575 END_PROFILE(smb2_break);
1577 break;
1579 default:
1580 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1581 break;
1583 return return_value;
1586 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1588 struct tevent_req *subreq;
1589 int i = req->current_idx;
1591 req->subreq = NULL;
1593 req->current_idx += 3;
1595 if (req->current_idx < req->out.vector_count) {
1597 * We must process the remaining compound
1598 * SMB2 requests before any new incoming SMB2
1599 * requests. This is because incoming SMB2
1600 * requests may include a cancel for a
1601 * compound request we haven't processed
1602 * yet.
1604 struct tevent_immediate *im = tevent_create_immediate(req);
1605 if (!im) {
1606 return NT_STATUS_NO_MEMORY;
1608 tevent_schedule_immediate(im,
1609 req->sconn->smb2.event_ctx,
1610 smbd_smb2_request_dispatch_immediate,
1611 req);
1612 return NT_STATUS_OK;
1615 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1617 /* Set credit for this operation (zero credits if this
1618 is a final reply for an async operation). */
1619 smb2_set_operation_credit(req->sconn,
1620 req->async ? NULL : &req->in.vector[i],
1621 &req->out.vector[i]);
1623 if (req->do_signing) {
1624 NTSTATUS status;
1625 status = smb2_signing_sign_pdu(req->session->session_key,
1626 &req->out.vector[i], 3);
1627 if (!NT_STATUS_IS_OK(status)) {
1628 return status;
1632 if (DEBUGLEVEL >= 10) {
1633 dbgtext("smbd_smb2_request_reply: sending...\n");
1634 print_req_vectors(req);
1637 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1638 if (req->out.vector_count == 4 &&
1639 req->out.vector[3].iov_base == NULL &&
1640 req->out.vector[3].iov_len != 0) {
1641 /* Dynamic part is NULL. Chop it off,
1642 We're going to send it via sendfile. */
1643 req->out.vector_count -= 1;
1646 subreq = tstream_writev_queue_send(req,
1647 req->sconn->smb2.event_ctx,
1648 req->sconn->smb2.stream,
1649 req->sconn->smb2.send_queue,
1650 req->out.vector,
1651 req->out.vector_count);
1652 if (subreq == NULL) {
1653 return NT_STATUS_NO_MEMORY;
1655 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1657 * We're done with this request -
1658 * move it off the "being processed" queue.
1660 DLIST_REMOVE(req->sconn->smb2.requests, req);
1662 return NT_STATUS_OK;
1665 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1666 struct tevent_immediate *im,
1667 void *private_data)
1669 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1670 struct smbd_smb2_request);
1671 struct smbd_server_connection *sconn = req->sconn;
1672 NTSTATUS status;
1674 TALLOC_FREE(im);
1676 if (DEBUGLEVEL >= 10) {
1677 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1678 req->current_idx, req->in.vector_count));
1679 print_req_vectors(req);
1682 status = smbd_smb2_request_dispatch(req);
1683 if (!NT_STATUS_IS_OK(status)) {
1684 smbd_server_connection_terminate(sconn, nt_errstr(status));
1685 return;
1689 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1691 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1692 struct smbd_smb2_request);
1693 struct smbd_server_connection *sconn = req->sconn;
1694 int ret;
1695 int sys_errno;
1697 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1698 TALLOC_FREE(subreq);
1699 TALLOC_FREE(req);
1700 if (ret == -1) {
1701 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1702 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1703 nt_errstr(status)));
1704 smbd_server_connection_terminate(sconn, nt_errstr(status));
1705 return;
1709 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1710 NTSTATUS status,
1711 DATA_BLOB body, DATA_BLOB *dyn,
1712 const char *location)
1714 uint8_t *outhdr;
1715 int i = req->current_idx;
1716 uint32_t next_command_ofs;
1718 DEBUG(10,("smbd_smb2_request_done_ex: "
1719 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1720 i, nt_errstr(status), (unsigned int)body.length,
1721 dyn ? "yes": "no",
1722 (unsigned int)(dyn ? dyn->length : 0),
1723 location));
1725 if (body.length < 2) {
1726 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1729 if ((body.length % 2) != 0) {
1730 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1733 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1735 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1736 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1738 req->out.vector[i+1].iov_base = (void *)body.data;
1739 req->out.vector[i+1].iov_len = body.length;
1741 if (dyn) {
1742 req->out.vector[i+2].iov_base = (void *)dyn->data;
1743 req->out.vector[i+2].iov_len = dyn->length;
1744 } else {
1745 req->out.vector[i+2].iov_base = NULL;
1746 req->out.vector[i+2].iov_len = 0;
1749 /* see if we need to recalculate the offset to the next response */
1750 if (next_command_ofs > 0) {
1751 next_command_ofs = SMB2_HDR_BODY;
1752 next_command_ofs += req->out.vector[i+1].iov_len;
1753 next_command_ofs += req->out.vector[i+2].iov_len;
1756 if ((next_command_ofs % 8) != 0) {
1757 size_t pad_size = 8 - (next_command_ofs % 8);
1758 if (req->out.vector[i+2].iov_len == 0) {
1760 * if the dyn buffer is empty
1761 * we can use it to add padding
1763 uint8_t *pad;
1765 pad = talloc_zero_array(req->out.vector,
1766 uint8_t, pad_size);
1767 if (pad == NULL) {
1768 return smbd_smb2_request_error(req,
1769 NT_STATUS_NO_MEMORY);
1772 req->out.vector[i+2].iov_base = (void *)pad;
1773 req->out.vector[i+2].iov_len = pad_size;
1774 } else {
1776 * For now we copy the dynamic buffer
1777 * and add the padding to the new buffer
1779 size_t old_size;
1780 uint8_t *old_dyn;
1781 size_t new_size;
1782 uint8_t *new_dyn;
1784 old_size = req->out.vector[i+2].iov_len;
1785 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
1787 new_size = old_size + pad_size;
1788 new_dyn = talloc_zero_array(req->out.vector,
1789 uint8_t, new_size);
1790 if (new_dyn == NULL) {
1791 return smbd_smb2_request_error(req,
1792 NT_STATUS_NO_MEMORY);
1795 memcpy(new_dyn, old_dyn, old_size);
1796 memset(new_dyn + old_size, 0, pad_size);
1798 req->out.vector[i+2].iov_base = (void *)new_dyn;
1799 req->out.vector[i+2].iov_len = new_size;
1801 next_command_ofs += pad_size;
1804 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1806 return smbd_smb2_request_reply(req);
1809 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
1810 NTSTATUS status,
1811 DATA_BLOB *info,
1812 const char *location)
1814 DATA_BLOB body;
1815 int i = req->current_idx;
1816 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
1818 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1819 i, nt_errstr(status), info ? " +info" : "",
1820 location));
1822 body.data = outhdr + SMB2_HDR_BODY;
1823 body.length = 8;
1824 SSVAL(body.data, 0, 9);
1826 if (info) {
1827 SIVAL(body.data, 0x04, info->length);
1828 } else {
1829 /* Allocated size of req->out.vector[i].iov_base
1830 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
1831 * 1 byte without having to do an alloc.
1833 info = talloc_zero_array(req->out.vector,
1834 DATA_BLOB,
1836 if (!info) {
1837 return NT_STATUS_NO_MEMORY;
1839 info->data = ((uint8_t *)outhdr) +
1840 OUTVEC_ALLOC_SIZE - 1;
1841 info->length = 1;
1842 SCVAL(info->data, 0, 0);
1846 * if a request fails, all other remaining
1847 * compounded requests should fail too
1849 req->next_status = NT_STATUS_INVALID_PARAMETER;
1851 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
1855 struct smbd_smb2_send_oplock_break_state {
1856 struct smbd_server_connection *sconn;
1857 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
1858 struct iovec vector;
1861 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
1863 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
1864 uint64_t file_id_persistent,
1865 uint64_t file_id_volatile,
1866 uint8_t oplock_level)
1868 struct smbd_smb2_send_oplock_break_state *state;
1869 struct tevent_req *subreq;
1870 uint8_t *hdr;
1871 uint8_t *body;
1873 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
1874 if (state == NULL) {
1875 return NT_STATUS_NO_MEMORY;
1877 state->sconn = sconn;
1879 state->vector.iov_base = (void *)state->buf;
1880 state->vector.iov_len = sizeof(state->buf);
1882 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
1883 hdr = state->buf + 4;
1884 body = hdr + SMB2_HDR_BODY;
1886 SIVAL(hdr, 0, SMB2_MAGIC);
1887 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1888 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1889 SIVAL(hdr, SMB2_HDR_STATUS, 0);
1890 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
1891 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
1892 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
1893 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1894 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
1895 SIVAL(hdr, SMB2_HDR_PID, 0);
1896 SIVAL(hdr, SMB2_HDR_TID, 0);
1897 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
1898 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
1900 SSVAL(body, 0x00, 0x18);
1902 SCVAL(body, 0x02, oplock_level);
1903 SCVAL(body, 0x03, 0); /* reserved */
1904 SIVAL(body, 0x04, 0); /* reserved */
1905 SBVAL(body, 0x08, file_id_persistent);
1906 SBVAL(body, 0x10, file_id_volatile);
1908 subreq = tstream_writev_queue_send(state,
1909 sconn->smb2.event_ctx,
1910 sconn->smb2.stream,
1911 sconn->smb2.send_queue,
1912 &state->vector, 1);
1913 if (subreq == NULL) {
1914 return NT_STATUS_NO_MEMORY;
1916 tevent_req_set_callback(subreq,
1917 smbd_smb2_oplock_break_writev_done,
1918 state);
1920 return NT_STATUS_OK;
1923 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
1925 struct smbd_smb2_send_oplock_break_state *state =
1926 tevent_req_callback_data(subreq,
1927 struct smbd_smb2_send_oplock_break_state);
1928 struct smbd_server_connection *sconn = state->sconn;
1929 int ret;
1930 int sys_errno;
1932 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1933 TALLOC_FREE(subreq);
1934 if (ret == -1) {
1935 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1936 smbd_server_connection_terminate(sconn, nt_errstr(status));
1937 return;
1940 TALLOC_FREE(state);
1943 struct smbd_smb2_request_read_state {
1944 size_t missing;
1945 bool asked_for_header;
1946 struct smbd_smb2_request *smb2_req;
1949 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1950 void *private_data,
1951 TALLOC_CTX *mem_ctx,
1952 struct iovec **_vector,
1953 size_t *_count);
1954 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
1956 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
1957 struct tevent_context *ev,
1958 struct smbd_server_connection *sconn)
1960 struct tevent_req *req;
1961 struct smbd_smb2_request_read_state *state;
1962 struct tevent_req *subreq;
1964 req = tevent_req_create(mem_ctx, &state,
1965 struct smbd_smb2_request_read_state);
1966 if (req == NULL) {
1967 return NULL;
1969 state->missing = 0;
1970 state->asked_for_header = false;
1972 state->smb2_req = smbd_smb2_request_allocate(state);
1973 if (tevent_req_nomem(state->smb2_req, req)) {
1974 return tevent_req_post(req, ev);
1976 state->smb2_req->sconn = sconn;
1978 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
1979 sconn->smb2.recv_queue,
1980 smbd_smb2_request_next_vector,
1981 state);
1982 if (tevent_req_nomem(subreq, req)) {
1983 return tevent_req_post(req, ev);
1985 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
1987 return req;
1990 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1991 void *private_data,
1992 TALLOC_CTX *mem_ctx,
1993 struct iovec **_vector,
1994 size_t *_count)
1996 struct smbd_smb2_request_read_state *state =
1997 talloc_get_type_abort(private_data,
1998 struct smbd_smb2_request_read_state);
1999 struct smbd_smb2_request *req = state->smb2_req;
2000 struct iovec *vector;
2001 int idx = req->in.vector_count;
2002 size_t len = 0;
2003 uint8_t *buf = NULL;
2005 if (req->in.vector_count == 0) {
2007 * first we need to get the NBT header
2009 req->in.vector = talloc_array(req, struct iovec,
2010 req->in.vector_count + 1);
2011 if (req->in.vector == NULL) {
2012 return -1;
2014 req->in.vector_count += 1;
2016 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2017 req->in.vector[idx].iov_len = 4;
2019 vector = talloc_array(mem_ctx, struct iovec, 1);
2020 if (vector == NULL) {
2021 return -1;
2024 vector[0] = req->in.vector[idx];
2026 *_vector = vector;
2027 *_count = 1;
2028 return 0;
2031 if (req->in.vector_count == 1) {
2033 * Now we analyze the NBT header
2035 state->missing = smb2_len(req->in.vector[0].iov_base);
2037 if (state->missing == 0) {
2038 /* if there're no remaining bytes, we're done */
2039 *_vector = NULL;
2040 *_count = 0;
2041 return 0;
2044 req->in.vector = talloc_realloc(req, req->in.vector,
2045 struct iovec,
2046 req->in.vector_count + 1);
2047 if (req->in.vector == NULL) {
2048 return -1;
2050 req->in.vector_count += 1;
2052 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2054 * it's a special NBT message,
2055 * so get all remaining bytes
2057 len = state->missing;
2058 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2060 * it's an invalid message, just read what we can get
2061 * and let the caller handle the error
2063 len = state->missing;
2064 } else {
2066 * We assume it's a SMB2 request,
2067 * and we first get the header and the
2068 * first 2 bytes (the struct size) of the body
2070 len = SMB2_HDR_BODY + 2;
2072 state->asked_for_header = true;
2075 state->missing -= len;
2077 buf = talloc_array(req->in.vector, uint8_t, len);
2078 if (buf == NULL) {
2079 return -1;
2082 req->in.vector[idx].iov_base = (void *)buf;
2083 req->in.vector[idx].iov_len = len;
2085 vector = talloc_array(mem_ctx, struct iovec, 1);
2086 if (vector == NULL) {
2087 return -1;
2090 vector[0] = req->in.vector[idx];
2092 *_vector = vector;
2093 *_count = 1;
2094 return 0;
2097 if (state->missing == 0) {
2098 /* if there're no remaining bytes, we're done */
2099 *_vector = NULL;
2100 *_count = 0;
2101 return 0;
2104 if (state->asked_for_header) {
2105 const uint8_t *hdr;
2106 size_t full_size;
2107 size_t next_command_ofs;
2108 size_t body_size;
2109 uint8_t *body;
2110 size_t dyn_size;
2111 uint8_t *dyn;
2112 bool invalid = false;
2114 state->asked_for_header = false;
2117 * We got the SMB2 header and the first 2 bytes
2118 * of the body. We fix the size to just the header
2119 * and manually copy the 2 first bytes to the body section
2121 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2122 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2124 /* allocate vectors for body and dynamic areas */
2125 req->in.vector = talloc_realloc(req, req->in.vector,
2126 struct iovec,
2127 req->in.vector_count + 2);
2128 if (req->in.vector == NULL) {
2129 return -1;
2131 req->in.vector_count += 2;
2133 full_size = state->missing + SMB2_HDR_BODY + 2;
2134 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2135 body_size = SVAL(hdr, SMB2_HDR_BODY);
2137 if (next_command_ofs != 0) {
2138 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2140 * this is invalid, just return a zero
2141 * body and let the caller deal with the error
2143 invalid = true;
2144 } else if (next_command_ofs > full_size) {
2146 * this is invalid, just return a zero
2147 * body and let the caller deal with the error
2149 invalid = true;
2150 } else {
2151 full_size = next_command_ofs;
2155 if (!invalid) {
2156 if (body_size < 2) {
2158 * this is invalid, just return a zero
2159 * body and let the caller deal with the error
2161 invalid = true;
2164 if ((body_size % 2) != 0) {
2165 body_size -= 1;
2168 if (body_size > (full_size - SMB2_HDR_BODY)) {
2170 * this is invalid, just return a zero
2171 * body and let the caller deal with the error
2173 invalid = true;
2177 if (invalid) {
2178 /* the caller should check this */
2179 body_size = 2;
2182 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2184 state->missing -= (body_size - 2) + dyn_size;
2186 body = talloc_array(req->in.vector, uint8_t, body_size);
2187 if (body == NULL) {
2188 return -1;
2191 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2192 if (dyn == NULL) {
2193 return -1;
2196 req->in.vector[idx].iov_base = (void *)body;
2197 req->in.vector[idx].iov_len = body_size;
2198 req->in.vector[idx+1].iov_base = (void *)dyn;
2199 req->in.vector[idx+1].iov_len = dyn_size;
2201 vector = talloc_array(mem_ctx, struct iovec, 2);
2202 if (vector == NULL) {
2203 return -1;
2207 * the first 2 bytes of the body were already fetched
2208 * together with the header
2210 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2211 vector[0].iov_base = body + 2;
2212 vector[0].iov_len = body_size - 2;
2214 vector[1] = req->in.vector[idx+1];
2216 *_vector = vector;
2217 *_count = 2;
2218 return 0;
2222 * when we endup here, we're looking for a new SMB2 request
2223 * next. And we ask for its header and the first 2 bytes of
2224 * the body (like we did for the first SMB2 request).
2227 req->in.vector = talloc_realloc(req, req->in.vector,
2228 struct iovec,
2229 req->in.vector_count + 1);
2230 if (req->in.vector == NULL) {
2231 return -1;
2233 req->in.vector_count += 1;
2236 * We assume it's a SMB2 request,
2237 * and we first get the header and the
2238 * first 2 bytes (the struct size) of the body
2240 len = SMB2_HDR_BODY + 2;
2242 if (len > state->missing) {
2243 /* let the caller handle the error */
2244 len = state->missing;
2247 state->missing -= len;
2248 state->asked_for_header = true;
2250 buf = talloc_array(req->in.vector, uint8_t, len);
2251 if (buf == NULL) {
2252 return -1;
2255 req->in.vector[idx].iov_base = (void *)buf;
2256 req->in.vector[idx].iov_len = len;
2258 vector = talloc_array(mem_ctx, struct iovec, 1);
2259 if (vector == NULL) {
2260 return -1;
2263 vector[0] = req->in.vector[idx];
2265 *_vector = vector;
2266 *_count = 1;
2267 return 0;
2270 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2272 struct tevent_req *req =
2273 tevent_req_callback_data(subreq,
2274 struct tevent_req);
2275 int ret;
2276 int sys_errno;
2277 NTSTATUS status;
2279 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2280 if (ret == -1) {
2281 status = map_nt_error_from_unix(sys_errno);
2282 tevent_req_nterror(req, status);
2283 return;
2286 tevent_req_done(req);
2289 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2290 TALLOC_CTX *mem_ctx,
2291 struct smbd_smb2_request **_smb2_req)
2293 struct smbd_smb2_request_read_state *state =
2294 tevent_req_data(req,
2295 struct smbd_smb2_request_read_state);
2296 NTSTATUS status;
2298 if (tevent_req_is_nterror(req, &status)) {
2299 tevent_req_received(req);
2300 return status;
2303 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2304 *_smb2_req = state->smb2_req;
2305 tevent_req_received(req);
2306 return NT_STATUS_OK;
2309 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2311 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2312 const uint8_t *inbuf, size_t size)
2314 NTSTATUS status;
2315 struct smbd_smb2_request *req = NULL;
2316 struct tevent_req *subreq;
2318 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2319 (unsigned int)size));
2321 status = smbd_initialize_smb2(sconn);
2322 if (!NT_STATUS_IS_OK(status)) {
2323 smbd_server_connection_terminate(sconn, nt_errstr(status));
2324 return;
2327 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2328 if (!NT_STATUS_IS_OK(status)) {
2329 smbd_server_connection_terminate(sconn, nt_errstr(status));
2330 return;
2333 status = smbd_smb2_request_setup_out(req);
2334 if (!NT_STATUS_IS_OK(status)) {
2335 smbd_server_connection_terminate(sconn, nt_errstr(status));
2336 return;
2339 status = smbd_smb2_request_dispatch(req);
2340 if (!NT_STATUS_IS_OK(status)) {
2341 smbd_server_connection_terminate(sconn, nt_errstr(status));
2342 return;
2345 /* ask for the next request */
2346 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2347 if (subreq == NULL) {
2348 smbd_server_connection_terminate(sconn, "no memory for reading");
2349 return;
2351 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2353 sconn->num_requests++;
2356 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2358 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2359 struct smbd_server_connection);
2360 NTSTATUS status;
2361 struct smbd_smb2_request *req = NULL;
2363 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2364 TALLOC_FREE(subreq);
2365 if (!NT_STATUS_IS_OK(status)) {
2366 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2367 nt_errstr(status)));
2368 smbd_server_connection_terminate(sconn, nt_errstr(status));
2369 return;
2372 if (req->in.nbt_hdr[0] != 0x00) {
2373 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2374 req->in.nbt_hdr[0]));
2375 TALLOC_FREE(req);
2376 goto next;
2379 req->current_idx = 1;
2381 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2382 req->current_idx, req->in.vector_count));
2384 status = smbd_smb2_request_validate(req);
2385 if (!NT_STATUS_IS_OK(status)) {
2386 smbd_server_connection_terminate(sconn, nt_errstr(status));
2387 return;
2390 status = smbd_smb2_request_setup_out(req);
2391 if (!NT_STATUS_IS_OK(status)) {
2392 smbd_server_connection_terminate(sconn, nt_errstr(status));
2393 return;
2396 status = smbd_smb2_request_dispatch(req);
2397 if (!NT_STATUS_IS_OK(status)) {
2398 smbd_server_connection_terminate(sconn, nt_errstr(status));
2399 return;
2402 next:
2403 /* ask for the next request (this constructs the main loop) */
2404 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2405 if (subreq == NULL) {
2406 smbd_server_connection_terminate(sconn, "no memory for reading");
2407 return;
2409 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2411 sconn->num_requests++;
2413 /* The timeout_processing function isn't run nearly
2414 often enough to implement 'max log size' without
2415 overrunning the size of the file by many megabytes.
2416 This is especially true if we are running at debug
2417 level 10. Checking every 50 SMB2s is a nice
2418 tradeoff of performance vs log file size overrun. */
2420 if ((sconn->num_requests % 50) == 0 &&
2421 need_to_check_log_size()) {
2422 change_to_root_user();
2423 check_log_size();