Fix a bunch of "unused variable" warnings.
[Samba/vl.git] / source3 / smbd / smb2_server.c
blob899de07c2350673b4663a5aeeb11fc30f022f1b2
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"
29 #include "../lib/util/bitmap.h"
30 #include "../librpc/gen_ndr/krb5pac.h"
31 #include "auth.h"
33 #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9)
35 static const char *smb2_names[] = {
36 "SMB2_NEGPROT",
37 "SMB2_SESSSETUP",
38 "SMB2_LOGOFF",
39 "SMB2_TCON",
40 "SMB2_TDIS",
41 "SMB2_CREATE",
42 "SMB2_CLOSE",
43 "SMB2_FLUSH",
44 "SMB2_READ",
45 "SMB2_WRITE",
46 "SMB2_LOCK",
47 "SMB2_IOCTL",
48 "SMB2_CANCEL",
49 "SMB2_KEEPALIVE",
50 "SMB2_FIND",
51 "SMB2_NOTIFY",
52 "SMB2_GETINFO",
53 "SMB2_SETINFO",
54 "SMB2_BREAK"
57 const char *smb2_opcode_name(uint16_t opcode)
59 if (opcode > 0x12) {
60 return "Bad SMB2 opcode";
62 return smb2_names[opcode];
65 static void print_req_vectors(struct smbd_smb2_request *req)
67 int i;
69 for (i = 0; i < req->in.vector_count; i++) {
70 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
71 (unsigned int)i,
72 (unsigned int)req->in.vector[i].iov_len);
74 for (i = 0; i < req->out.vector_count; i++) {
75 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
76 (unsigned int)i,
77 (unsigned int)req->out.vector[i].iov_len);
81 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
83 if (size < (4 + SMB2_HDR_BODY)) {
84 return false;
87 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
88 return false;
91 return true;
94 static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
96 NTSTATUS status;
97 int ret;
99 TALLOC_FREE(sconn->smb1.fde);
101 sconn->smb2.recv_queue = tevent_queue_create(sconn, "smb2 recv queue");
102 if (sconn->smb2.recv_queue == NULL) {
103 return NT_STATUS_NO_MEMORY;
106 sconn->smb2.send_queue = tevent_queue_create(sconn, "smb2 send queue");
107 if (sconn->smb2.send_queue == NULL) {
108 return NT_STATUS_NO_MEMORY;
111 sconn->smb2.sessions.idtree = idr_init(sconn);
112 if (sconn->smb2.sessions.idtree == NULL) {
113 return NT_STATUS_NO_MEMORY;
115 sconn->smb2.sessions.limit = 0x0000FFFE;
116 sconn->smb2.sessions.list = NULL;
117 sconn->smb2.seqnum_low = 0;
118 sconn->smb2.credits_granted = 0;
119 sconn->smb2.max_credits = lp_smb2_max_credits();
120 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
121 DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR*sconn->smb2.max_credits);
122 if (sconn->smb2.credits_bitmap == NULL) {
123 return NT_STATUS_NO_MEMORY;
126 ret = tstream_bsd_existing_socket(sconn, sconn->sock,
127 &sconn->smb2.stream);
128 if (ret == -1) {
129 status = map_nt_error_from_unix(errno);
130 return status;
133 /* Ensure child is set to non-blocking mode */
134 set_blocking(sconn->sock, false);
135 return NT_STATUS_OK;
138 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
139 #define _smb2_setlen(_buf,len) do { \
140 uint8_t *buf = (uint8_t *)_buf; \
141 buf[0] = 0; \
142 buf[1] = ((len)&0xFF0000)>>16; \
143 buf[2] = ((len)&0xFF00)>>8; \
144 buf[3] = (len)&0xFF; \
145 } while (0)
147 static void smb2_setup_nbt_length(struct iovec *vector, int count)
149 size_t len = 0;
150 int i;
152 for (i=1; i < count; i++) {
153 len += vector[i].iov_len;
156 _smb2_setlen(vector[0].iov_base, len);
159 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request **req)
161 if (*req) {
162 (*req)->parent = NULL;
163 (*req)->mem_pool = NULL;
166 return 0;
169 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
171 if (req->parent) {
172 *req->parent = NULL;
173 talloc_free(req->mem_pool);
176 return 0;
179 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
181 TALLOC_CTX *mem_pool;
182 struct smbd_smb2_request **parent;
183 struct smbd_smb2_request *req;
185 #if 0
186 /* Enable this to find subtle valgrind errors. */
187 mem_pool = talloc_init("smbd_smb2_request_allocate");
188 #else
189 mem_pool = talloc_pool(mem_ctx, 8192);
190 #endif
191 if (mem_pool == NULL) {
192 return NULL;
195 parent = talloc(mem_pool, struct smbd_smb2_request *);
196 if (parent == NULL) {
197 talloc_free(mem_pool);
198 return NULL;
201 req = talloc_zero(parent, struct smbd_smb2_request);
202 if (req == NULL) {
203 talloc_free(mem_pool);
204 return NULL;
206 *parent = req;
207 req->mem_pool = mem_pool;
208 req->parent = parent;
210 req->last_session_id = UINT64_MAX;
211 req->last_tid = UINT32_MAX;
213 talloc_set_destructor(parent, smbd_smb2_request_parent_destructor);
214 talloc_set_destructor(req, smbd_smb2_request_destructor);
216 return req;
219 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
220 const uint8_t *inbuf, size_t size,
221 struct smbd_smb2_request **_req)
223 struct smbd_smb2_request *req;
224 uint32_t protocol_version;
225 const uint8_t *inhdr = NULL;
226 off_t ofs = 0;
227 uint16_t cmd;
228 uint32_t next_command_ofs;
230 if (size < (4 + SMB2_HDR_BODY + 2)) {
231 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
232 return NT_STATUS_INVALID_PARAMETER;
235 inhdr = inbuf + 4;
237 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
238 if (protocol_version != SMB2_MAGIC) {
239 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
240 protocol_version));
241 return NT_STATUS_INVALID_PARAMETER;
244 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
245 if (cmd != SMB2_OP_NEGPROT) {
246 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
247 cmd));
248 return NT_STATUS_INVALID_PARAMETER;
251 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
252 if (next_command_ofs != 0) {
253 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
254 next_command_ofs));
255 return NT_STATUS_INVALID_PARAMETER;
258 req = smbd_smb2_request_allocate(sconn);
259 if (req == NULL) {
260 return NT_STATUS_NO_MEMORY;
262 req->sconn = sconn;
264 talloc_steal(req, inbuf);
266 req->in.vector = talloc_array(req, struct iovec, 4);
267 if (req->in.vector == NULL) {
268 TALLOC_FREE(req);
269 return NT_STATUS_NO_MEMORY;
271 req->in.vector_count = 4;
273 memcpy(req->in.nbt_hdr, inbuf, 4);
275 ofs = 0;
276 req->in.vector[0].iov_base = discard_const_p(void, req->in.nbt_hdr);
277 req->in.vector[0].iov_len = 4;
278 ofs += req->in.vector[0].iov_len;
280 req->in.vector[1].iov_base = discard_const_p(void, (inbuf + ofs));
281 req->in.vector[1].iov_len = SMB2_HDR_BODY;
282 ofs += req->in.vector[1].iov_len;
284 req->in.vector[2].iov_base = discard_const_p(void, (inbuf + ofs));
285 req->in.vector[2].iov_len = SVAL(inbuf, ofs) & 0xFFFE;
286 ofs += req->in.vector[2].iov_len;
288 if (ofs > size) {
289 return NT_STATUS_INVALID_PARAMETER;
292 req->in.vector[3].iov_base = discard_const_p(void, (inbuf + ofs));
293 req->in.vector[3].iov_len = size - ofs;
294 ofs += req->in.vector[3].iov_len;
296 req->current_idx = 1;
298 *_req = req;
299 return NT_STATUS_OK;
302 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
303 const uint8_t *inhdr)
305 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
306 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
307 uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
308 unsigned int bitmap_offset;
310 if (opcode == SMB2_OP_CANCEL) {
311 /* SMB2_CANCEL requests by definition resend messageids. */
312 return true;
315 if (message_id < sconn->smb2.seqnum_low ||
316 message_id > (sconn->smb2.seqnum_low +
317 (sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR))) {
318 DEBUG(0,("smb2_validate_message_id: bad message_id "
319 "%llu (low = %llu, max = %lu)\n",
320 (unsigned long long)message_id,
321 (unsigned long long)sconn->smb2.seqnum_low,
322 (unsigned long)sconn->smb2.max_credits ));
323 return false;
326 if (sconn->smb2.credits_granted == 0) {
327 DEBUG(0,("smb2_validate_message_id: client used more "
328 "credits than granted message_id (%llu)\n",
329 (unsigned long long)message_id));
330 return false;
333 /* client just used a credit. */
334 sconn->smb2.credits_granted -= 1;
336 /* Mark the message_id as seen in the bitmap. */
337 bitmap_offset = (unsigned int)(message_id %
338 (uint64_t)(sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR));
339 if (bitmap_query(credits_bm, bitmap_offset)) {
340 DEBUG(0,("smb2_validate_message_id: duplicate message_id "
341 "%llu (bm offset %u)\n",
342 (unsigned long long)message_id,
343 bitmap_offset));
344 return false;
346 bitmap_set(credits_bm, bitmap_offset);
348 if (message_id == sconn->smb2.seqnum_low + 1) {
349 /* Move the window forward by all the message_id's
350 already seen. */
351 while (bitmap_query(credits_bm, bitmap_offset)) {
352 DEBUG(10,("smb2_validate_message_id: clearing "
353 "id %llu (position %u) from bitmap\n",
354 (unsigned long long)(sconn->smb2.seqnum_low + 1),
355 bitmap_offset ));
356 bitmap_clear(credits_bm, bitmap_offset);
357 sconn->smb2.seqnum_low += 1;
358 bitmap_offset = (bitmap_offset + 1) %
359 (sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR);
363 return true;
366 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
368 int count;
369 int idx;
371 count = req->in.vector_count;
373 if (count < 4) {
374 /* It's not a SMB2 request */
375 return NT_STATUS_INVALID_PARAMETER;
378 for (idx=1; idx < count; idx += 3) {
379 const uint8_t *inhdr = NULL;
380 uint32_t flags;
382 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
383 return NT_STATUS_INVALID_PARAMETER;
386 if (req->in.vector[idx+1].iov_len < 2) {
387 return NT_STATUS_INVALID_PARAMETER;
390 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
392 /* Check the SMB2 header */
393 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
394 return NT_STATUS_INVALID_PARAMETER;
397 if (!smb2_validate_message_id(req->sconn, inhdr)) {
398 return NT_STATUS_INVALID_PARAMETER;
401 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
402 if (idx == 1) {
404 * the 1st request should never have the
405 * SMB2_HDR_FLAG_CHAINED flag set
407 if (flags & SMB2_HDR_FLAG_CHAINED) {
408 req->next_status = NT_STATUS_INVALID_PARAMETER;
409 return NT_STATUS_OK;
411 } else if (idx == 4) {
413 * the 2nd request triggers related vs. unrelated
414 * compounded requests
416 if (flags & SMB2_HDR_FLAG_CHAINED) {
417 req->compound_related = true;
419 } else if (idx > 4) {
420 #if 0
422 * It seems the this tests are wrong
423 * see the SMB2-COMPOUND test
427 * all other requests should match the 2nd one
429 if (flags & SMB2_HDR_FLAG_CHAINED) {
430 if (!req->compound_related) {
431 req->next_status =
432 NT_STATUS_INVALID_PARAMETER;
433 return NT_STATUS_OK;
435 } else {
436 if (req->compound_related) {
437 req->next_status =
438 NT_STATUS_INVALID_PARAMETER;
439 return NT_STATUS_OK;
442 #endif
446 return NT_STATUS_OK;
449 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
450 const struct iovec *in_vector,
451 struct iovec *out_vector)
453 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
454 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
455 uint16_t credits_requested;
456 uint32_t out_flags;
457 uint16_t credits_granted = 0;
459 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
460 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
462 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
464 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
466 * In case we already send an async interim
467 * response, we should not grant
468 * credits on the final response.
470 credits_requested = 0;
473 if (credits_requested) {
474 uint16_t modified_credits_requested;
475 uint32_t multiplier;
478 * Split up max_credits into 1/16ths, and then scale
479 * the requested credits by how many 16ths have been
480 * currently granted. Less than 1/16th == grant all
481 * requested (100%), scale down as more have been
482 * granted. Never ask for less than 1 as the client
483 * asked for at least 1. JRA.
486 multiplier = 16 - (((sconn->smb2.credits_granted * 16) / sconn->smb2.max_credits) % 16);
488 modified_credits_requested = (multiplier * credits_requested) / 16;
489 if (modified_credits_requested == 0) {
490 modified_credits_requested = 1;
493 /* Remember what we gave out. */
494 credits_granted = MIN(modified_credits_requested,
495 (sconn->smb2.max_credits - sconn->smb2.credits_granted));
498 if (credits_granted == 0 && sconn->smb2.credits_granted == 0) {
499 /* First negprot packet, or ensure the client credits can
500 never drop to zero. */
501 credits_granted = 1;
504 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
505 sconn->smb2.credits_granted += credits_granted;
507 DEBUG(10,("smb2_set_operation_credit: requested %u, "
508 "granted %u, total granted %u\n",
509 (unsigned int)credits_requested,
510 (unsigned int)credits_granted,
511 (unsigned int)sconn->smb2.credits_granted ));
514 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
515 struct smbd_smb2_request *outreq)
517 int count, idx;
518 uint16_t total_credits = 0;
520 count = outreq->out.vector_count;
522 for (idx=1; idx < count; idx += 3) {
523 uint8_t *outhdr = (uint8_t *)outreq->out.vector[idx].iov_base;
524 smb2_set_operation_credit(outreq->sconn,
525 &inreq->in.vector[idx],
526 &outreq->out.vector[idx]);
527 /* To match Windows, count up what we
528 just granted. */
529 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
530 /* Set to zero in all but the last reply. */
531 if (idx + 3 < count) {
532 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
533 } else {
534 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
539 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
541 struct iovec *vector;
542 int count;
543 int idx;
545 count = req->in.vector_count;
546 vector = talloc_zero_array(req, struct iovec, count);
547 if (vector == NULL) {
548 return NT_STATUS_NO_MEMORY;
551 vector[0].iov_base = req->out.nbt_hdr;
552 vector[0].iov_len = 4;
553 SIVAL(req->out.nbt_hdr, 0, 0);
555 for (idx=1; idx < count; idx += 3) {
556 const uint8_t *inhdr = NULL;
557 uint8_t *outhdr = NULL;
558 uint8_t *outbody = NULL;
559 uint32_t next_command_ofs = 0;
560 struct iovec *current = &vector[idx];
562 if ((idx + 3) < count) {
563 /* we have a next command -
564 * setup for the error case. */
565 next_command_ofs = SMB2_HDR_BODY + 9;
568 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
570 outhdr = talloc_zero_array(vector, uint8_t,
571 OUTVEC_ALLOC_SIZE);
572 if (outhdr == NULL) {
573 return NT_STATUS_NO_MEMORY;
576 outbody = outhdr + SMB2_HDR_BODY;
578 current[0].iov_base = (void *)outhdr;
579 current[0].iov_len = SMB2_HDR_BODY;
581 current[1].iov_base = (void *)outbody;
582 current[1].iov_len = 8;
584 current[2].iov_base = NULL;
585 current[2].iov_len = 0;
587 /* setup the SMB2 header */
588 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
589 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
590 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
591 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
592 SIVAL(outhdr, SMB2_HDR_STATUS,
593 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
594 SSVAL(outhdr, SMB2_HDR_OPCODE,
595 SVAL(inhdr, SMB2_HDR_OPCODE));
596 SIVAL(outhdr, SMB2_HDR_FLAGS,
597 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
598 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
599 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
600 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
601 SIVAL(outhdr, SMB2_HDR_PID,
602 IVAL(inhdr, SMB2_HDR_PID));
603 SIVAL(outhdr, SMB2_HDR_TID,
604 IVAL(inhdr, SMB2_HDR_TID));
605 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
606 BVAL(inhdr, SMB2_HDR_SESSION_ID));
607 memcpy(outhdr + SMB2_HDR_SIGNATURE,
608 inhdr + SMB2_HDR_SIGNATURE, 16);
610 /* setup error body header */
611 SSVAL(outbody, 0x00, 0x08 + 1);
612 SSVAL(outbody, 0x02, 0);
613 SIVAL(outbody, 0x04, 0);
616 req->out.vector = vector;
617 req->out.vector_count = count;
619 /* setup the length of the NBT packet */
620 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
622 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
624 return NT_STATUS_OK;
627 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
628 const char *reason,
629 const char *location)
631 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
632 reason, location));
633 exit_server_cleanly(reason);
636 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
637 struct iovec *outvec,
638 const struct iovec *srcvec)
640 /* vec[0] is always boilerplate and must
641 * be allocated with size OUTVEC_ALLOC_SIZE. */
643 outvec[0].iov_base = talloc_memdup(ctx,
644 srcvec[0].iov_base,
645 OUTVEC_ALLOC_SIZE);
646 if (!outvec[0].iov_base) {
647 return false;
649 outvec[0].iov_len = SMB2_HDR_BODY;
652 * If this is a "standard" vec[1] of length 8,
653 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
654 * then duplicate this. Else use talloc_memdup().
657 if (srcvec[1].iov_len == 8 &&
658 srcvec[1].iov_base ==
659 ((uint8_t *)srcvec[0].iov_base) +
660 SMB2_HDR_BODY) {
661 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
662 SMB2_HDR_BODY;
663 outvec[1].iov_len = 8;
664 } else {
665 outvec[1].iov_base = talloc_memdup(ctx,
666 srcvec[1].iov_base,
667 srcvec[1].iov_len);
668 if (!outvec[1].iov_base) {
669 return false;
671 outvec[1].iov_len = srcvec[1].iov_len;
675 * If this is a "standard" vec[2] of length 1,
676 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
677 * then duplicate this. Else use talloc_memdup().
680 if (srcvec[2].iov_base &&
681 srcvec[2].iov_len) {
682 if (srcvec[2].iov_base ==
683 ((uint8_t *)srcvec[0].iov_base) +
684 (OUTVEC_ALLOC_SIZE - 1) &&
685 srcvec[2].iov_len == 1) {
686 /* Common SMB2 error packet case. */
687 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
688 (OUTVEC_ALLOC_SIZE - 1);
689 } else {
690 outvec[2].iov_base = talloc_memdup(ctx,
691 srcvec[2].iov_base,
692 srcvec[2].iov_len);
693 if (!outvec[2].iov_base) {
694 return false;
697 outvec[2].iov_len = srcvec[2].iov_len;
698 } else {
699 outvec[2].iov_base = NULL;
700 outvec[2].iov_len = 0;
702 return true;
705 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
707 struct smbd_smb2_request *newreq = NULL;
708 struct iovec *outvec = NULL;
709 int count = req->out.vector_count;
710 int i;
712 newreq = smbd_smb2_request_allocate(req->sconn);
713 if (!newreq) {
714 return NULL;
717 newreq->sconn = req->sconn;
718 newreq->session = req->session;
719 newreq->do_signing = req->do_signing;
720 newreq->current_idx = req->current_idx;
722 outvec = talloc_zero_array(newreq, struct iovec, count);
723 if (!outvec) {
724 TALLOC_FREE(newreq);
725 return NULL;
727 newreq->out.vector = outvec;
728 newreq->out.vector_count = count;
730 /* Setup the outvec's identically to req. */
731 outvec[0].iov_base = newreq->out.nbt_hdr;
732 outvec[0].iov_len = 4;
733 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
735 /* Setup the vectors identically to the ones in req. */
736 for (i = 1; i < count; i += 3) {
737 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
738 break;
742 if (i < count) {
743 /* Alloc failed. */
744 TALLOC_FREE(newreq);
745 return NULL;
748 smb2_setup_nbt_length(newreq->out.vector,
749 newreq->out.vector_count);
751 return newreq;
754 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
756 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
758 int i = 0;
759 uint8_t *outhdr = NULL;
760 struct smbd_smb2_request *nreq = NULL;
762 /* Create a new smb2 request we'll use
763 for the interim return. */
764 nreq = dup_smb2_req(req);
765 if (!nreq) {
766 return NT_STATUS_NO_MEMORY;
769 /* Lose the last 3 out vectors. They're the
770 ones we'll be using for the async reply. */
771 nreq->out.vector_count -= 3;
773 smb2_setup_nbt_length(nreq->out.vector,
774 nreq->out.vector_count);
776 /* Step back to the previous reply. */
777 i = nreq->current_idx - 3;
778 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
779 /* And end the chain. */
780 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
782 /* Calculate outgoing credits */
783 smb2_calculate_credits(req, nreq);
785 /* Re-sign if needed. */
786 if (nreq->do_signing) {
787 NTSTATUS status;
788 status = smb2_signing_sign_pdu(nreq->session->session_key,
789 &nreq->out.vector[i], 3);
790 if (!NT_STATUS_IS_OK(status)) {
791 return status;
794 if (DEBUGLEVEL >= 10) {
795 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
796 (unsigned int)nreq->current_idx );
797 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
798 (unsigned int)nreq->out.vector_count );
799 print_req_vectors(nreq);
801 nreq->subreq = tstream_writev_queue_send(nreq,
802 nreq->sconn->ev_ctx,
803 nreq->sconn->smb2.stream,
804 nreq->sconn->smb2.send_queue,
805 nreq->out.vector,
806 nreq->out.vector_count);
808 if (nreq->subreq == NULL) {
809 return NT_STATUS_NO_MEMORY;
812 tevent_req_set_callback(nreq->subreq,
813 smbd_smb2_request_writev_done,
814 nreq);
816 return NT_STATUS_OK;
819 struct smbd_smb2_request_pending_state {
820 struct smbd_server_connection *sconn;
821 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
822 struct iovec vector[3];
825 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
827 struct smbd_smb2_request_pending_state *state =
828 tevent_req_callback_data(subreq,
829 struct smbd_smb2_request_pending_state);
830 struct smbd_server_connection *sconn = state->sconn;
831 int ret;
832 int sys_errno;
834 ret = tstream_writev_queue_recv(subreq, &sys_errno);
835 TALLOC_FREE(subreq);
836 if (ret == -1) {
837 NTSTATUS status = map_nt_error_from_unix(sys_errno);
838 smbd_server_connection_terminate(sconn, nt_errstr(status));
839 return;
842 TALLOC_FREE(state);
845 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
846 struct tevent_timer *te,
847 struct timeval current_time,
848 void *private_data);
850 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
851 struct tevent_req *subreq,
852 uint32_t defer_time)
854 NTSTATUS status;
855 int i = req->current_idx;
856 struct timeval defer_endtime;
857 uint8_t *outhdr = NULL;
858 uint32_t flags;
860 if (!tevent_req_is_in_progress(subreq)) {
861 return NT_STATUS_OK;
864 req->subreq = subreq;
865 subreq = NULL;
867 if (req->async_te) {
868 /* We're already async. */
869 return NT_STATUS_OK;
872 outhdr = (uint8_t *)req->out.vector[i].iov_base;
873 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
874 if (flags & SMB2_HDR_FLAG_ASYNC) {
875 /* We're already async. */
876 return NT_STATUS_OK;
879 if (req->in.vector_count > i + 3) {
881 * We're trying to go async in a compound
882 * request chain. This is not allowed.
883 * Cancel the outstanding request.
885 tevent_req_cancel(req->subreq);
886 return smbd_smb2_request_error(req,
887 NT_STATUS_INSUFFICIENT_RESOURCES);
890 if (DEBUGLEVEL >= 10) {
891 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
892 (unsigned int)req->current_idx );
893 print_req_vectors(req);
896 if (req->out.vector_count > 4) {
897 struct iovec *outvec = NULL;
899 /* This is a compound reply. We
900 * must do an interim response
901 * followed by the async response
902 * to match W2K8R2.
904 status = smb2_send_async_interim_response(req);
905 if (!NT_STATUS_IS_OK(status)) {
906 return status;
910 * We're splitting off the last SMB2
911 * request in a compound set, and the
912 * smb2_send_async_interim_response()
913 * call above just sent all the replies
914 * for the previous SMB2 requests in
915 * this compound set. So we're no longer
916 * in the "compound_related_in_progress"
917 * state, and this is no longer a compound
918 * request.
920 req->compound_related = false;
921 req->sconn->smb2.compound_related_in_progress = false;
923 /* Re-arrange the in.vectors. */
924 req->in.vector[1] = req->in.vector[i];
925 req->in.vector[2] = req->in.vector[i+1];
926 req->in.vector[3] = req->in.vector[i+2];
927 req->in.vector_count = 4;
929 /* Reset the new in size. */
930 smb2_setup_nbt_length(req->in.vector, 4);
932 /* Now recreate the out.vectors. */
933 outvec = talloc_zero_array(req, struct iovec, 4);
934 if (!outvec) {
935 return NT_STATUS_NO_MEMORY;
938 /* 0 is always boilerplate and must
939 * be of size 4 for the length field. */
941 outvec[0].iov_base = req->out.nbt_hdr;
942 outvec[0].iov_len = 4;
943 SIVAL(req->out.nbt_hdr, 0, 0);
945 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
946 return NT_STATUS_NO_MEMORY;
949 TALLOC_FREE(req->out.vector);
951 req->out.vector = outvec;
953 req->current_idx = 1;
954 req->out.vector_count = 4;
956 outhdr = (uint8_t *)req->out.vector[1].iov_base;
957 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
958 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
961 defer_endtime = timeval_current_ofs_usec(defer_time);
962 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
963 req, defer_endtime,
964 smbd_smb2_request_pending_timer,
965 req);
966 if (req->async_te == NULL) {
967 return NT_STATUS_NO_MEMORY;
970 return NT_STATUS_OK;
973 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
974 struct tevent_timer *te,
975 struct timeval current_time,
976 void *private_data)
978 struct smbd_smb2_request *req =
979 talloc_get_type_abort(private_data,
980 struct smbd_smb2_request);
981 struct smbd_smb2_request_pending_state *state = NULL;
982 int i = req->current_idx;
983 uint8_t *outhdr = NULL;
984 const uint8_t *inhdr = NULL;
985 uint8_t *hdr = NULL;
986 uint8_t *body = NULL;
987 uint32_t flags = 0;
988 uint64_t message_id = 0;
989 uint64_t async_id = 0;
990 struct tevent_req *subreq = NULL;
992 TALLOC_FREE(req->async_te);
994 /* Ensure our final reply matches the interim one. */
995 inhdr = (const uint8_t *)req->in.vector[1].iov_base;
996 outhdr = (uint8_t *)req->out.vector[1].iov_base;
997 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
998 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1000 async_id = message_id; /* keep it simple for now... */
1002 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1003 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1005 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1006 "going async\n",
1007 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1008 (unsigned long long)async_id ));
1011 * What we send is identical to a smbd_smb2_request_error
1012 * packet with an error status of STATUS_PENDING. Make use
1013 * of this fact sometime when refactoring. JRA.
1016 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1017 if (state == NULL) {
1018 smbd_server_connection_terminate(req->sconn,
1019 nt_errstr(NT_STATUS_NO_MEMORY));
1020 return;
1022 state->sconn = req->sconn;
1024 state->vector[0].iov_base = (void *)state->buf;
1025 state->vector[0].iov_len = 4;
1027 state->vector[1].iov_base = state->buf + 4;
1028 state->vector[1].iov_len = SMB2_HDR_BODY;
1030 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
1031 state->vector[2].iov_len = 9;
1033 smb2_setup_nbt_length(state->vector, 3);
1035 hdr = (uint8_t *)state->vector[1].iov_base;
1036 body = (uint8_t *)state->vector[2].iov_base;
1038 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1039 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1040 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1041 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1042 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1044 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1045 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1046 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1047 SBVAL(hdr, SMB2_HDR_PID, async_id);
1048 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1049 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1050 memcpy(hdr+SMB2_HDR_SIGNATURE,
1051 outhdr+SMB2_HDR_SIGNATURE, 16);
1053 SSVAL(body, 0x00, 0x08 + 1);
1055 SCVAL(body, 0x02, 0);
1056 SCVAL(body, 0x03, 0);
1057 SIVAL(body, 0x04, 0);
1058 /* Match W2K8R2... */
1059 SCVAL(body, 0x08, 0x21);
1061 /* Ensure we correctly go through crediting. Grant
1062 the credits now, and zero credits on the final
1063 response. */
1064 smb2_set_operation_credit(req->sconn,
1065 &req->in.vector[i],
1066 &state->vector[1]);
1068 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1070 if (req->do_signing) {
1071 NTSTATUS status;
1073 status = smb2_signing_sign_pdu(req->session->session_key,
1074 &state->vector[1], 2);
1075 if (!NT_STATUS_IS_OK(status)) {
1076 smbd_server_connection_terminate(req->sconn,
1077 nt_errstr(status));
1078 return;
1082 subreq = tstream_writev_queue_send(state,
1083 state->sconn->ev_ctx,
1084 state->sconn->smb2.stream,
1085 state->sconn->smb2.send_queue,
1086 state->vector,
1088 if (subreq == NULL) {
1089 smbd_server_connection_terminate(state->sconn,
1090 nt_errstr(NT_STATUS_NO_MEMORY));
1091 return;
1093 tevent_req_set_callback(subreq,
1094 smbd_smb2_request_pending_writev_done,
1095 state);
1098 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1100 struct smbd_server_connection *sconn = req->sconn;
1101 struct smbd_smb2_request *cur;
1102 const uint8_t *inhdr;
1103 int i = req->current_idx;
1104 uint32_t flags;
1105 uint64_t search_message_id;
1106 uint64_t search_async_id;
1107 uint64_t found_id;
1109 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1111 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1112 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1113 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1116 * we don't need the request anymore
1117 * cancel requests never have a response
1119 DLIST_REMOVE(req->sconn->smb2.requests, req);
1120 TALLOC_FREE(req);
1122 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1123 const uint8_t *outhdr;
1124 uint64_t message_id;
1125 uint64_t async_id;
1127 i = cur->current_idx;
1129 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1131 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1132 async_id = BVAL(outhdr, SMB2_HDR_PID);
1134 if (flags & SMB2_HDR_FLAG_ASYNC) {
1135 if (search_async_id == async_id) {
1136 found_id = async_id;
1137 break;
1139 } else {
1140 if (search_message_id == message_id) {
1141 found_id = message_id;
1142 break;
1147 if (cur && cur->subreq) {
1148 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1149 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1150 "cancel opcode[%s] mid %llu\n",
1151 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1152 (unsigned long long)found_id ));
1153 tevent_req_cancel(cur->subreq);
1156 return NT_STATUS_OK;
1159 /*************************************************************
1160 Ensure an incoming tid is a valid one for us to access.
1161 Change to the associated uid credentials and chdir to the
1162 valid tid directory.
1163 *************************************************************/
1165 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1167 const uint8_t *inhdr;
1168 int i = req->current_idx;
1169 uint32_t in_flags;
1170 uint32_t in_tid;
1171 void *p;
1172 struct smbd_smb2_tcon *tcon;
1174 req->tcon = NULL;
1176 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1178 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1179 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1181 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1182 in_tid = req->last_tid;
1185 /* lookup an existing session */
1186 p = idr_find(req->session->tcons.idtree, in_tid);
1187 if (p == NULL) {
1188 return NT_STATUS_NETWORK_NAME_DELETED;
1190 tcon = talloc_get_type_abort(p, struct smbd_smb2_tcon);
1192 if (!change_to_user(tcon->compat_conn,req->session->vuid)) {
1193 return NT_STATUS_ACCESS_DENIED;
1196 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1197 if (!set_current_service(tcon->compat_conn, 0, true)) {
1198 return NT_STATUS_ACCESS_DENIED;
1201 req->tcon = tcon;
1202 req->last_tid = in_tid;
1204 return NT_STATUS_OK;
1207 /*************************************************************
1208 Ensure an incoming session_id is a valid one for us to access.
1209 *************************************************************/
1211 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1213 const uint8_t *inhdr;
1214 int i = req->current_idx;
1215 uint32_t in_flags;
1216 uint64_t in_session_id;
1217 void *p;
1218 struct smbd_smb2_session *session;
1220 req->session = NULL;
1221 req->tcon = NULL;
1223 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1225 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1226 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1228 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1229 in_session_id = req->last_session_id;
1232 /* lookup an existing session */
1233 p = idr_find(req->sconn->smb2.sessions.idtree, in_session_id);
1234 if (p == NULL) {
1235 return NT_STATUS_USER_SESSION_DELETED;
1237 session = talloc_get_type_abort(p, struct smbd_smb2_session);
1239 if (!NT_STATUS_IS_OK(session->status)) {
1240 return NT_STATUS_ACCESS_DENIED;
1243 set_current_user_info(session->session_info->unix_info->sanitized_username,
1244 session->session_info->unix_info->unix_name,
1245 session->session_info->info->domain_name);
1247 req->session = session;
1248 req->last_session_id = in_session_id;
1250 return NT_STATUS_OK;
1253 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1254 size_t expected_body_size)
1256 const uint8_t *inhdr;
1257 uint16_t opcode;
1258 const uint8_t *inbody;
1259 int i = req->current_idx;
1260 size_t body_size;
1261 size_t min_dyn_size = expected_body_size & 0x00000001;
1264 * The following should be checked already.
1266 if ((i+2) > req->in.vector_count) {
1267 return NT_STATUS_INTERNAL_ERROR;
1269 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1270 return NT_STATUS_INTERNAL_ERROR;
1272 if (req->in.vector[i+1].iov_len < 2) {
1273 return NT_STATUS_INTERNAL_ERROR;
1276 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1277 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1279 switch (opcode) {
1280 case SMB2_OP_IOCTL:
1281 case SMB2_OP_GETINFO:
1282 min_dyn_size = 0;
1283 break;
1287 * Now check the expected body size,
1288 * where the last byte might be in the
1289 * dynnamic section..
1291 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1292 return NT_STATUS_INVALID_PARAMETER;
1294 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1295 return NT_STATUS_INVALID_PARAMETER;
1298 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1300 body_size = SVAL(inbody, 0x00);
1301 if (body_size != expected_body_size) {
1302 return NT_STATUS_INVALID_PARAMETER;
1305 return NT_STATUS_OK;
1308 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1310 const uint8_t *inhdr;
1311 int i = req->current_idx;
1312 uint16_t opcode;
1313 uint32_t flags;
1314 uint64_t mid;
1315 NTSTATUS status;
1316 NTSTATUS session_status;
1317 uint32_t allowed_flags;
1318 NTSTATUS return_value;
1320 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1322 /* TODO: verify more things */
1324 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1325 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1326 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1327 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1328 smb2_opcode_name(opcode),
1329 (unsigned long long)mid));
1331 if (get_Protocol() >= PROTOCOL_SMB2_02) {
1333 * once the protocol is negotiated
1334 * SMB2_OP_NEGPROT is not allowed anymore
1336 if (opcode == SMB2_OP_NEGPROT) {
1337 /* drop the connection */
1338 return NT_STATUS_INVALID_PARAMETER;
1340 } else {
1342 * if the protocol is not negotiated yet
1343 * only SMB2_OP_NEGPROT is allowed.
1345 if (opcode != SMB2_OP_NEGPROT) {
1346 /* drop the connection */
1347 return NT_STATUS_INVALID_PARAMETER;
1351 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1352 SMB2_HDR_FLAG_SIGNED |
1353 SMB2_HDR_FLAG_DFS;
1354 if (opcode == SMB2_OP_CANCEL) {
1355 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1357 if ((flags & ~allowed_flags) != 0) {
1358 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1362 * Check if the client provided a valid session id,
1363 * if so smbd_smb2_request_check_session() calls
1364 * set_current_user_info().
1366 * As some command don't require a valid session id
1367 * we defer the check of the session_status
1369 session_status = smbd_smb2_request_check_session(req);
1371 req->do_signing = false;
1372 if (flags & SMB2_HDR_FLAG_SIGNED) {
1373 if (!NT_STATUS_IS_OK(session_status)) {
1374 return smbd_smb2_request_error(req, session_status);
1377 req->do_signing = true;
1378 status = smb2_signing_check_pdu(req->session->session_key,
1379 &req->in.vector[i], 3);
1380 if (!NT_STATUS_IS_OK(status)) {
1381 return smbd_smb2_request_error(req, status);
1383 } else if (opcode == SMB2_OP_CANCEL) {
1384 /* Cancel requests are allowed to skip the signing */
1385 } else if (req->session && req->session->do_signing) {
1386 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1389 if (flags & SMB2_HDR_FLAG_CHAINED) {
1391 * This check is mostly for giving the correct error code
1392 * for compounded requests.
1394 * TODO: we may need to move this after the session
1395 * and tcon checks.
1397 if (!NT_STATUS_IS_OK(req->next_status)) {
1398 return smbd_smb2_request_error(req, req->next_status);
1400 } else {
1401 req->compat_chain_fsp = NULL;
1404 if (req->compound_related) {
1405 req->sconn->smb2.compound_related_in_progress = true;
1408 switch (opcode) {
1409 case SMB2_OP_NEGPROT:
1410 /* This call needs to be run as root */
1411 change_to_root_user();
1414 START_PROFILE(smb2_negprot);
1415 return_value = smbd_smb2_request_process_negprot(req);
1416 END_PROFILE(smb2_negprot);
1418 break;
1420 case SMB2_OP_SESSSETUP:
1421 /* This call needs to be run as root */
1422 change_to_root_user();
1425 START_PROFILE(smb2_sesssetup);
1426 return_value = smbd_smb2_request_process_sesssetup(req);
1427 END_PROFILE(smb2_sesssetup);
1429 break;
1431 case SMB2_OP_LOGOFF:
1432 if (!NT_STATUS_IS_OK(session_status)) {
1433 return_value = smbd_smb2_request_error(req, session_status);
1434 break;
1437 /* This call needs to be run as root */
1438 change_to_root_user();
1441 START_PROFILE(smb2_logoff);
1442 return_value = smbd_smb2_request_process_logoff(req);
1443 END_PROFILE(smb2_logoff);
1445 break;
1447 case SMB2_OP_TCON:
1448 if (!NT_STATUS_IS_OK(session_status)) {
1449 return_value = smbd_smb2_request_error(req, session_status);
1450 break;
1454 * This call needs to be run as root.
1456 * smbd_smb2_request_process_tcon()
1457 * calls make_connection_snum(), which will call
1458 * change_to_user(), when needed.
1460 change_to_root_user();
1463 START_PROFILE(smb2_tcon);
1464 return_value = smbd_smb2_request_process_tcon(req);
1465 END_PROFILE(smb2_tcon);
1467 break;
1469 case SMB2_OP_TDIS:
1470 if (!NT_STATUS_IS_OK(session_status)) {
1471 return_value = smbd_smb2_request_error(req, session_status);
1472 break;
1475 * This call needs to be run as user.
1477 * smbd_smb2_request_check_tcon()
1478 * calls change_to_user() on success.
1480 status = smbd_smb2_request_check_tcon(req);
1481 if (!NT_STATUS_IS_OK(status)) {
1482 return_value = smbd_smb2_request_error(req, status);
1483 break;
1485 /* This call needs to be run as root */
1486 change_to_root_user();
1490 START_PROFILE(smb2_tdis);
1491 return_value = smbd_smb2_request_process_tdis(req);
1492 END_PROFILE(smb2_tdis);
1494 break;
1496 case SMB2_OP_CREATE:
1497 if (!NT_STATUS_IS_OK(session_status)) {
1498 return_value = smbd_smb2_request_error(req, session_status);
1499 break;
1502 * This call needs to be run as user.
1504 * smbd_smb2_request_check_tcon()
1505 * calls change_to_user() on success.
1507 status = smbd_smb2_request_check_tcon(req);
1508 if (!NT_STATUS_IS_OK(status)) {
1509 return_value = smbd_smb2_request_error(req, status);
1510 break;
1514 START_PROFILE(smb2_create);
1515 return_value = smbd_smb2_request_process_create(req);
1516 END_PROFILE(smb2_create);
1518 break;
1520 case SMB2_OP_CLOSE:
1521 if (!NT_STATUS_IS_OK(session_status)) {
1522 return_value = smbd_smb2_request_error(req, session_status);
1523 break;
1526 * This call needs to be run as user.
1528 * smbd_smb2_request_check_tcon()
1529 * calls change_to_user() on success.
1531 status = smbd_smb2_request_check_tcon(req);
1532 if (!NT_STATUS_IS_OK(status)) {
1533 return_value = smbd_smb2_request_error(req, status);
1534 break;
1538 START_PROFILE(smb2_close);
1539 return_value = smbd_smb2_request_process_close(req);
1540 END_PROFILE(smb2_close);
1542 break;
1544 case SMB2_OP_FLUSH:
1545 if (!NT_STATUS_IS_OK(session_status)) {
1546 return_value = smbd_smb2_request_error(req, session_status);
1547 break;
1550 * This call needs to be run as user.
1552 * smbd_smb2_request_check_tcon()
1553 * calls change_to_user() on success.
1555 status = smbd_smb2_request_check_tcon(req);
1556 if (!NT_STATUS_IS_OK(status)) {
1557 return_value = smbd_smb2_request_error(req, status);
1558 break;
1562 START_PROFILE(smb2_flush);
1563 return_value = smbd_smb2_request_process_flush(req);
1564 END_PROFILE(smb2_flush);
1566 break;
1568 case SMB2_OP_READ:
1569 if (!NT_STATUS_IS_OK(session_status)) {
1570 return_value = smbd_smb2_request_error(req, session_status);
1571 break;
1574 * This call needs to be run as user.
1576 * smbd_smb2_request_check_tcon()
1577 * calls change_to_user() on success.
1579 status = smbd_smb2_request_check_tcon(req);
1580 if (!NT_STATUS_IS_OK(status)) {
1581 return_value = smbd_smb2_request_error(req, status);
1582 break;
1586 START_PROFILE(smb2_read);
1587 return_value = smbd_smb2_request_process_read(req);
1588 END_PROFILE(smb2_read);
1590 break;
1592 case SMB2_OP_WRITE:
1593 if (!NT_STATUS_IS_OK(session_status)) {
1594 return_value = smbd_smb2_request_error(req, session_status);
1595 break;
1598 * This call needs to be run as user.
1600 * smbd_smb2_request_check_tcon()
1601 * calls change_to_user() on success.
1603 status = smbd_smb2_request_check_tcon(req);
1604 if (!NT_STATUS_IS_OK(status)) {
1605 return_value = smbd_smb2_request_error(req, status);
1606 break;
1610 START_PROFILE(smb2_write);
1611 return_value = smbd_smb2_request_process_write(req);
1612 END_PROFILE(smb2_write);
1614 break;
1616 case SMB2_OP_LOCK:
1617 if (!NT_STATUS_IS_OK(session_status)) {
1618 /* Too ugly to live ? JRA. */
1619 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1620 session_status = NT_STATUS_FILE_CLOSED;
1622 return_value = smbd_smb2_request_error(req, session_status);
1623 break;
1626 * This call needs to be run as user.
1628 * smbd_smb2_request_check_tcon()
1629 * calls change_to_user() on success.
1631 status = smbd_smb2_request_check_tcon(req);
1632 if (!NT_STATUS_IS_OK(status)) {
1633 /* Too ugly to live ? JRA. */
1634 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1635 status = NT_STATUS_FILE_CLOSED;
1637 return_value = smbd_smb2_request_error(req, status);
1638 break;
1642 START_PROFILE(smb2_lock);
1643 return_value = smbd_smb2_request_process_lock(req);
1644 END_PROFILE(smb2_lock);
1646 break;
1648 case SMB2_OP_IOCTL:
1649 if (!NT_STATUS_IS_OK(session_status)) {
1650 return_value = smbd_smb2_request_error(req, session_status);
1651 break;
1654 * This call needs to be run as user.
1656 * smbd_smb2_request_check_tcon()
1657 * calls change_to_user() on success.
1659 status = smbd_smb2_request_check_tcon(req);
1660 if (!NT_STATUS_IS_OK(status)) {
1661 return_value = smbd_smb2_request_error(req, status);
1662 break;
1666 START_PROFILE(smb2_ioctl);
1667 return_value = smbd_smb2_request_process_ioctl(req);
1668 END_PROFILE(smb2_ioctl);
1670 break;
1672 case SMB2_OP_CANCEL:
1674 * This call needs to be run as root
1676 * That is what we also do in the SMB1 case.
1678 change_to_root_user();
1681 START_PROFILE(smb2_cancel);
1682 return_value = smbd_smb2_request_process_cancel(req);
1683 END_PROFILE(smb2_cancel);
1685 break;
1687 case SMB2_OP_KEEPALIVE:
1688 /* This call needs to be run as root */
1689 change_to_root_user();
1692 START_PROFILE(smb2_keepalive);
1693 return_value = smbd_smb2_request_process_keepalive(req);
1694 END_PROFILE(smb2_keepalive);
1696 break;
1698 case SMB2_OP_FIND:
1699 if (!NT_STATUS_IS_OK(session_status)) {
1700 return_value = smbd_smb2_request_error(req, session_status);
1701 break;
1704 * This call needs to be run as user.
1706 * smbd_smb2_request_check_tcon()
1707 * calls change_to_user() on success.
1709 status = smbd_smb2_request_check_tcon(req);
1710 if (!NT_STATUS_IS_OK(status)) {
1711 return_value = smbd_smb2_request_error(req, status);
1712 break;
1716 START_PROFILE(smb2_find);
1717 return_value = smbd_smb2_request_process_find(req);
1718 END_PROFILE(smb2_find);
1720 break;
1722 case SMB2_OP_NOTIFY:
1723 if (!NT_STATUS_IS_OK(session_status)) {
1724 return_value = smbd_smb2_request_error(req, session_status);
1725 break;
1728 * This call needs to be run as user.
1730 * smbd_smb2_request_check_tcon()
1731 * calls change_to_user() on success.
1733 status = smbd_smb2_request_check_tcon(req);
1734 if (!NT_STATUS_IS_OK(status)) {
1735 return_value = smbd_smb2_request_error(req, status);
1736 break;
1740 START_PROFILE(smb2_notify);
1741 return_value = smbd_smb2_request_process_notify(req);
1742 END_PROFILE(smb2_notify);
1744 break;
1746 case SMB2_OP_GETINFO:
1747 if (!NT_STATUS_IS_OK(session_status)) {
1748 return_value = smbd_smb2_request_error(req, session_status);
1749 break;
1752 * This call needs to be run as user.
1754 * smbd_smb2_request_check_tcon()
1755 * calls change_to_user() on success.
1757 status = smbd_smb2_request_check_tcon(req);
1758 if (!NT_STATUS_IS_OK(status)) {
1759 return_value = smbd_smb2_request_error(req, status);
1760 break;
1764 START_PROFILE(smb2_getinfo);
1765 return_value = smbd_smb2_request_process_getinfo(req);
1766 END_PROFILE(smb2_getinfo);
1768 break;
1770 case SMB2_OP_SETINFO:
1771 if (!NT_STATUS_IS_OK(session_status)) {
1772 return_value = smbd_smb2_request_error(req, session_status);
1773 break;
1776 * This call needs to be run as user.
1778 * smbd_smb2_request_check_tcon()
1779 * calls change_to_user() on success.
1781 status = smbd_smb2_request_check_tcon(req);
1782 if (!NT_STATUS_IS_OK(status)) {
1783 return_value = smbd_smb2_request_error(req, status);
1784 break;
1788 START_PROFILE(smb2_setinfo);
1789 return_value = smbd_smb2_request_process_setinfo(req);
1790 END_PROFILE(smb2_setinfo);
1792 break;
1794 case SMB2_OP_BREAK:
1795 if (!NT_STATUS_IS_OK(session_status)) {
1796 return_value = smbd_smb2_request_error(req, session_status);
1797 break;
1800 * This call needs to be run as user.
1802 * smbd_smb2_request_check_tcon()
1803 * calls change_to_user() on success.
1805 status = smbd_smb2_request_check_tcon(req);
1806 if (!NT_STATUS_IS_OK(status)) {
1807 return_value = smbd_smb2_request_error(req, status);
1808 break;
1812 START_PROFILE(smb2_break);
1813 return_value = smbd_smb2_request_process_break(req);
1814 END_PROFILE(smb2_break);
1816 break;
1818 default:
1819 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1820 break;
1822 return return_value;
1825 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1827 struct tevent_req *subreq;
1828 int i = req->current_idx;
1830 req->subreq = NULL;
1831 TALLOC_FREE(req->async_te);
1833 req->current_idx += 3;
1835 if (req->current_idx < req->out.vector_count) {
1837 * We must process the remaining compound
1838 * SMB2 requests before any new incoming SMB2
1839 * requests. This is because incoming SMB2
1840 * requests may include a cancel for a
1841 * compound request we haven't processed
1842 * yet.
1844 struct tevent_immediate *im = tevent_create_immediate(req);
1845 if (!im) {
1846 return NT_STATUS_NO_MEMORY;
1848 tevent_schedule_immediate(im,
1849 req->sconn->ev_ctx,
1850 smbd_smb2_request_dispatch_immediate,
1851 req);
1852 return NT_STATUS_OK;
1855 if (req->compound_related) {
1856 req->sconn->smb2.compound_related_in_progress = false;
1859 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1861 /* Set credit for these operations (zero credits if this
1862 is a final reply for an async operation). */
1863 smb2_calculate_credits(req, req);
1865 if (req->do_signing) {
1866 NTSTATUS status;
1867 status = smb2_signing_sign_pdu(req->session->session_key,
1868 &req->out.vector[i], 3);
1869 if (!NT_STATUS_IS_OK(status)) {
1870 return status;
1874 if (DEBUGLEVEL >= 10) {
1875 dbgtext("smbd_smb2_request_reply: sending...\n");
1876 print_req_vectors(req);
1879 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1880 if (req->out.vector_count == 4 &&
1881 req->out.vector[3].iov_base == NULL &&
1882 req->out.vector[3].iov_len != 0) {
1883 /* Dynamic part is NULL. Chop it off,
1884 We're going to send it via sendfile. */
1885 req->out.vector_count -= 1;
1888 subreq = tstream_writev_queue_send(req,
1889 req->sconn->ev_ctx,
1890 req->sconn->smb2.stream,
1891 req->sconn->smb2.send_queue,
1892 req->out.vector,
1893 req->out.vector_count);
1894 if (subreq == NULL) {
1895 return NT_STATUS_NO_MEMORY;
1897 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1899 * We're done with this request -
1900 * move it off the "being processed" queue.
1902 DLIST_REMOVE(req->sconn->smb2.requests, req);
1904 return NT_STATUS_OK;
1907 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
1909 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1910 struct tevent_immediate *im,
1911 void *private_data)
1913 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1914 struct smbd_smb2_request);
1915 struct smbd_server_connection *sconn = req->sconn;
1916 NTSTATUS status;
1918 TALLOC_FREE(im);
1920 if (DEBUGLEVEL >= 10) {
1921 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1922 req->current_idx, req->in.vector_count));
1923 print_req_vectors(req);
1926 status = smbd_smb2_request_dispatch(req);
1927 if (!NT_STATUS_IS_OK(status)) {
1928 smbd_server_connection_terminate(sconn, nt_errstr(status));
1929 return;
1932 status = smbd_smb2_request_next_incoming(sconn);
1933 if (!NT_STATUS_IS_OK(status)) {
1934 smbd_server_connection_terminate(sconn, nt_errstr(status));
1935 return;
1939 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1941 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1942 struct smbd_smb2_request);
1943 struct smbd_server_connection *sconn = req->sconn;
1944 int ret;
1945 int sys_errno;
1946 NTSTATUS status;
1948 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1949 TALLOC_FREE(subreq);
1950 TALLOC_FREE(req);
1951 if (ret == -1) {
1952 status = map_nt_error_from_unix(sys_errno);
1953 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1954 nt_errstr(status)));
1955 smbd_server_connection_terminate(sconn, nt_errstr(status));
1956 return;
1959 status = smbd_smb2_request_next_incoming(sconn);
1960 if (!NT_STATUS_IS_OK(status)) {
1961 smbd_server_connection_terminate(sconn, nt_errstr(status));
1962 return;
1966 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1967 NTSTATUS status,
1968 DATA_BLOB body, DATA_BLOB *dyn,
1969 const char *location)
1971 uint8_t *outhdr;
1972 int i = req->current_idx;
1973 uint32_t next_command_ofs;
1975 DEBUG(10,("smbd_smb2_request_done_ex: "
1976 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1977 i, nt_errstr(status), (unsigned int)body.length,
1978 dyn ? "yes": "no",
1979 (unsigned int)(dyn ? dyn->length : 0),
1980 location));
1982 if (body.length < 2) {
1983 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1986 if ((body.length % 2) != 0) {
1987 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1990 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1992 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1993 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1995 req->out.vector[i+1].iov_base = (void *)body.data;
1996 req->out.vector[i+1].iov_len = body.length;
1998 if (dyn) {
1999 req->out.vector[i+2].iov_base = (void *)dyn->data;
2000 req->out.vector[i+2].iov_len = dyn->length;
2001 } else {
2002 req->out.vector[i+2].iov_base = NULL;
2003 req->out.vector[i+2].iov_len = 0;
2006 /* see if we need to recalculate the offset to the next response */
2007 if (next_command_ofs > 0) {
2008 next_command_ofs = SMB2_HDR_BODY;
2009 next_command_ofs += req->out.vector[i+1].iov_len;
2010 next_command_ofs += req->out.vector[i+2].iov_len;
2013 if ((next_command_ofs % 8) != 0) {
2014 size_t pad_size = 8 - (next_command_ofs % 8);
2015 if (req->out.vector[i+2].iov_len == 0) {
2017 * if the dyn buffer is empty
2018 * we can use it to add padding
2020 uint8_t *pad;
2022 pad = talloc_zero_array(req->out.vector,
2023 uint8_t, pad_size);
2024 if (pad == NULL) {
2025 return smbd_smb2_request_error(req,
2026 NT_STATUS_NO_MEMORY);
2029 req->out.vector[i+2].iov_base = (void *)pad;
2030 req->out.vector[i+2].iov_len = pad_size;
2031 } else {
2033 * For now we copy the dynamic buffer
2034 * and add the padding to the new buffer
2036 size_t old_size;
2037 uint8_t *old_dyn;
2038 size_t new_size;
2039 uint8_t *new_dyn;
2041 old_size = req->out.vector[i+2].iov_len;
2042 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2044 new_size = old_size + pad_size;
2045 new_dyn = talloc_zero_array(req->out.vector,
2046 uint8_t, new_size);
2047 if (new_dyn == NULL) {
2048 return smbd_smb2_request_error(req,
2049 NT_STATUS_NO_MEMORY);
2052 memcpy(new_dyn, old_dyn, old_size);
2053 memset(new_dyn + old_size, 0, pad_size);
2055 req->out.vector[i+2].iov_base = (void *)new_dyn;
2056 req->out.vector[i+2].iov_len = new_size;
2058 next_command_ofs += pad_size;
2061 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2063 return smbd_smb2_request_reply(req);
2066 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2067 NTSTATUS status,
2068 DATA_BLOB *info,
2069 const char *location)
2071 DATA_BLOB body;
2072 int i = req->current_idx;
2073 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
2075 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2076 i, nt_errstr(status), info ? " +info" : "",
2077 location));
2079 body.data = outhdr + SMB2_HDR_BODY;
2080 body.length = 8;
2081 SSVAL(body.data, 0, 9);
2083 if (info) {
2084 SIVAL(body.data, 0x04, info->length);
2085 } else {
2086 /* Allocated size of req->out.vector[i].iov_base
2087 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2088 * 1 byte without having to do an alloc.
2090 info = talloc_zero_array(req->out.vector,
2091 DATA_BLOB,
2093 if (!info) {
2094 return NT_STATUS_NO_MEMORY;
2096 info->data = ((uint8_t *)outhdr) +
2097 OUTVEC_ALLOC_SIZE - 1;
2098 info->length = 1;
2099 SCVAL(info->data, 0, 0);
2103 * if a request fails, all other remaining
2104 * compounded requests should fail too
2106 req->next_status = NT_STATUS_INVALID_PARAMETER;
2108 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2112 struct smbd_smb2_send_oplock_break_state {
2113 struct smbd_server_connection *sconn;
2114 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2115 struct iovec vector;
2118 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2120 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2121 uint64_t file_id_persistent,
2122 uint64_t file_id_volatile,
2123 uint8_t oplock_level)
2125 struct smbd_smb2_send_oplock_break_state *state;
2126 struct tevent_req *subreq;
2127 uint8_t *hdr;
2128 uint8_t *body;
2130 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2131 if (state == NULL) {
2132 return NT_STATUS_NO_MEMORY;
2134 state->sconn = sconn;
2136 state->vector.iov_base = (void *)state->buf;
2137 state->vector.iov_len = sizeof(state->buf);
2139 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2140 hdr = state->buf + 4;
2141 body = hdr + SMB2_HDR_BODY;
2143 SIVAL(hdr, 0, SMB2_MAGIC);
2144 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2145 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2146 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2147 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2148 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2149 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2150 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2151 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2152 SIVAL(hdr, SMB2_HDR_PID, 0);
2153 SIVAL(hdr, SMB2_HDR_TID, 0);
2154 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2155 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2157 SSVAL(body, 0x00, 0x18);
2159 SCVAL(body, 0x02, oplock_level);
2160 SCVAL(body, 0x03, 0); /* reserved */
2161 SIVAL(body, 0x04, 0); /* reserved */
2162 SBVAL(body, 0x08, file_id_persistent);
2163 SBVAL(body, 0x10, file_id_volatile);
2165 subreq = tstream_writev_queue_send(state,
2166 sconn->ev_ctx,
2167 sconn->smb2.stream,
2168 sconn->smb2.send_queue,
2169 &state->vector, 1);
2170 if (subreq == NULL) {
2171 return NT_STATUS_NO_MEMORY;
2173 tevent_req_set_callback(subreq,
2174 smbd_smb2_oplock_break_writev_done,
2175 state);
2177 return NT_STATUS_OK;
2180 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2182 struct smbd_smb2_send_oplock_break_state *state =
2183 tevent_req_callback_data(subreq,
2184 struct smbd_smb2_send_oplock_break_state);
2185 struct smbd_server_connection *sconn = state->sconn;
2186 int ret;
2187 int sys_errno;
2189 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2190 TALLOC_FREE(subreq);
2191 if (ret == -1) {
2192 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2193 smbd_server_connection_terminate(sconn, nt_errstr(status));
2194 return;
2197 TALLOC_FREE(state);
2200 struct smbd_smb2_request_read_state {
2201 size_t missing;
2202 bool asked_for_header;
2203 struct smbd_smb2_request *smb2_req;
2206 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2207 void *private_data,
2208 TALLOC_CTX *mem_ctx,
2209 struct iovec **_vector,
2210 size_t *_count);
2211 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2213 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2214 struct tevent_context *ev,
2215 struct smbd_server_connection *sconn)
2217 struct tevent_req *req;
2218 struct smbd_smb2_request_read_state *state;
2219 struct tevent_req *subreq;
2221 req = tevent_req_create(mem_ctx, &state,
2222 struct smbd_smb2_request_read_state);
2223 if (req == NULL) {
2224 return NULL;
2226 state->missing = 0;
2227 state->asked_for_header = false;
2229 state->smb2_req = smbd_smb2_request_allocate(state);
2230 if (tevent_req_nomem(state->smb2_req, req)) {
2231 return tevent_req_post(req, ev);
2233 state->smb2_req->sconn = sconn;
2235 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2236 sconn->smb2.recv_queue,
2237 smbd_smb2_request_next_vector,
2238 state);
2239 if (tevent_req_nomem(subreq, req)) {
2240 return tevent_req_post(req, ev);
2242 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2244 return req;
2247 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2248 void *private_data,
2249 TALLOC_CTX *mem_ctx,
2250 struct iovec **_vector,
2251 size_t *_count)
2253 struct smbd_smb2_request_read_state *state =
2254 talloc_get_type_abort(private_data,
2255 struct smbd_smb2_request_read_state);
2256 struct smbd_smb2_request *req = state->smb2_req;
2257 struct iovec *vector;
2258 int idx = req->in.vector_count;
2259 size_t len = 0;
2260 uint8_t *buf = NULL;
2262 if (req->in.vector_count == 0) {
2264 * first we need to get the NBT header
2266 req->in.vector = talloc_array(req, struct iovec,
2267 req->in.vector_count + 1);
2268 if (req->in.vector == NULL) {
2269 return -1;
2271 req->in.vector_count += 1;
2273 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2274 req->in.vector[idx].iov_len = 4;
2276 vector = talloc_array(mem_ctx, struct iovec, 1);
2277 if (vector == NULL) {
2278 return -1;
2281 vector[0] = req->in.vector[idx];
2283 *_vector = vector;
2284 *_count = 1;
2285 return 0;
2288 if (req->in.vector_count == 1) {
2290 * Now we analyze the NBT header
2292 state->missing = smb2_len(req->in.vector[0].iov_base);
2294 if (state->missing == 0) {
2295 /* if there're no remaining bytes, we're done */
2296 *_vector = NULL;
2297 *_count = 0;
2298 return 0;
2301 req->in.vector = talloc_realloc(req, req->in.vector,
2302 struct iovec,
2303 req->in.vector_count + 1);
2304 if (req->in.vector == NULL) {
2305 return -1;
2307 req->in.vector_count += 1;
2309 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2311 * it's a special NBT message,
2312 * so get all remaining bytes
2314 len = state->missing;
2315 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2317 * it's an invalid message, just read what we can get
2318 * and let the caller handle the error
2320 len = state->missing;
2321 } else {
2323 * We assume it's a SMB2 request,
2324 * and we first get the header and the
2325 * first 2 bytes (the struct size) of the body
2327 len = SMB2_HDR_BODY + 2;
2329 state->asked_for_header = true;
2332 state->missing -= len;
2334 buf = talloc_array(req->in.vector, uint8_t, len);
2335 if (buf == NULL) {
2336 return -1;
2339 req->in.vector[idx].iov_base = (void *)buf;
2340 req->in.vector[idx].iov_len = len;
2342 vector = talloc_array(mem_ctx, struct iovec, 1);
2343 if (vector == NULL) {
2344 return -1;
2347 vector[0] = req->in.vector[idx];
2349 *_vector = vector;
2350 *_count = 1;
2351 return 0;
2354 if (state->missing == 0) {
2355 /* if there're no remaining bytes, we're done */
2356 *_vector = NULL;
2357 *_count = 0;
2358 return 0;
2361 if (state->asked_for_header) {
2362 const uint8_t *hdr;
2363 size_t full_size;
2364 size_t next_command_ofs;
2365 size_t body_size;
2366 uint8_t *body;
2367 size_t dyn_size;
2368 uint8_t *dyn;
2369 bool invalid = false;
2371 state->asked_for_header = false;
2374 * We got the SMB2 header and the first 2 bytes
2375 * of the body. We fix the size to just the header
2376 * and manually copy the 2 first bytes to the body section
2378 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2379 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2381 /* allocate vectors for body and dynamic areas */
2382 req->in.vector = talloc_realloc(req, req->in.vector,
2383 struct iovec,
2384 req->in.vector_count + 2);
2385 if (req->in.vector == NULL) {
2386 return -1;
2388 req->in.vector_count += 2;
2390 full_size = state->missing + SMB2_HDR_BODY + 2;
2391 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2392 body_size = SVAL(hdr, SMB2_HDR_BODY);
2394 if (next_command_ofs != 0) {
2395 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2397 * this is invalid, just return a zero
2398 * body and let the caller deal with the error
2400 invalid = true;
2401 } else if (next_command_ofs > full_size) {
2403 * this is invalid, just return a zero
2404 * body and let the caller deal with the error
2406 invalid = true;
2407 } else {
2408 full_size = next_command_ofs;
2412 if (!invalid) {
2413 if (body_size < 2) {
2415 * this is invalid, just return a zero
2416 * body and let the caller deal with the error
2418 invalid = true;
2422 * Mask out the lowest bit, the "dynamic" part
2423 * of body_size.
2425 body_size &= ~1;
2427 if (body_size > (full_size - SMB2_HDR_BODY)) {
2429 * this is invalid, just return a zero
2430 * body and let the caller deal with the error
2432 invalid = true;
2436 if (invalid) {
2437 /* the caller should check this */
2438 body_size = 2;
2441 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2443 state->missing -= (body_size - 2) + dyn_size;
2445 body = talloc_array(req->in.vector, uint8_t, body_size);
2446 if (body == NULL) {
2447 return -1;
2450 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2451 if (dyn == NULL) {
2452 return -1;
2455 req->in.vector[idx].iov_base = (void *)body;
2456 req->in.vector[idx].iov_len = body_size;
2457 req->in.vector[idx+1].iov_base = (void *)dyn;
2458 req->in.vector[idx+1].iov_len = dyn_size;
2460 vector = talloc_array(mem_ctx, struct iovec, 2);
2461 if (vector == NULL) {
2462 return -1;
2466 * the first 2 bytes of the body were already fetched
2467 * together with the header
2469 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2470 vector[0].iov_base = body + 2;
2471 vector[0].iov_len = body_size - 2;
2473 vector[1] = req->in.vector[idx+1];
2475 *_vector = vector;
2476 *_count = 2;
2477 return 0;
2481 * when we endup here, we're looking for a new SMB2 request
2482 * next. And we ask for its header and the first 2 bytes of
2483 * the body (like we did for the first SMB2 request).
2486 req->in.vector = talloc_realloc(req, req->in.vector,
2487 struct iovec,
2488 req->in.vector_count + 1);
2489 if (req->in.vector == NULL) {
2490 return -1;
2492 req->in.vector_count += 1;
2495 * We assume it's a SMB2 request,
2496 * and we first get the header and the
2497 * first 2 bytes (the struct size) of the body
2499 len = SMB2_HDR_BODY + 2;
2501 if (len > state->missing) {
2502 /* let the caller handle the error */
2503 len = state->missing;
2506 state->missing -= len;
2507 state->asked_for_header = true;
2509 buf = talloc_array(req->in.vector, uint8_t, len);
2510 if (buf == NULL) {
2511 return -1;
2514 req->in.vector[idx].iov_base = (void *)buf;
2515 req->in.vector[idx].iov_len = len;
2517 vector = talloc_array(mem_ctx, struct iovec, 1);
2518 if (vector == NULL) {
2519 return -1;
2522 vector[0] = req->in.vector[idx];
2524 *_vector = vector;
2525 *_count = 1;
2526 return 0;
2529 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2531 struct tevent_req *req =
2532 tevent_req_callback_data(subreq,
2533 struct tevent_req);
2534 int ret;
2535 int sys_errno;
2536 NTSTATUS status;
2538 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2539 if (ret == -1) {
2540 status = map_nt_error_from_unix(sys_errno);
2541 tevent_req_nterror(req, status);
2542 return;
2545 tevent_req_done(req);
2548 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2549 TALLOC_CTX *mem_ctx,
2550 struct smbd_smb2_request **_smb2_req)
2552 struct smbd_smb2_request_read_state *state =
2553 tevent_req_data(req,
2554 struct smbd_smb2_request_read_state);
2555 NTSTATUS status;
2557 if (tevent_req_is_nterror(req, &status)) {
2558 tevent_req_received(req);
2559 return status;
2562 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2563 *_smb2_req = state->smb2_req;
2564 tevent_req_received(req);
2565 return NT_STATUS_OK;
2568 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2570 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2572 size_t max_send_queue_len;
2573 size_t cur_send_queue_len;
2574 struct tevent_req *subreq;
2576 if (sconn->smb2.compound_related_in_progress) {
2578 * Can't read another until the related
2579 * compound is done.
2581 return NT_STATUS_OK;
2584 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2586 * if there is already a smbd_smb2_request_read
2587 * pending, we are done.
2589 return NT_STATUS_OK;
2592 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2593 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2595 if (cur_send_queue_len > max_send_queue_len) {
2597 * if we have a lot of requests to send,
2598 * we wait until they are on the wire until we
2599 * ask for the next request.
2601 return NT_STATUS_OK;
2604 /* ask for the next request */
2605 subreq = smbd_smb2_request_read_send(sconn, sconn->ev_ctx, sconn);
2606 if (subreq == NULL) {
2607 return NT_STATUS_NO_MEMORY;
2609 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2611 return NT_STATUS_OK;
2614 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2615 const uint8_t *inbuf, size_t size)
2617 NTSTATUS status;
2618 struct smbd_smb2_request *req = NULL;
2620 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2621 (unsigned int)size));
2623 status = smbd_initialize_smb2(sconn);
2624 if (!NT_STATUS_IS_OK(status)) {
2625 smbd_server_connection_terminate(sconn, nt_errstr(status));
2626 return;
2629 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2630 if (!NT_STATUS_IS_OK(status)) {
2631 smbd_server_connection_terminate(sconn, nt_errstr(status));
2632 return;
2635 status = smbd_smb2_request_setup_out(req);
2636 if (!NT_STATUS_IS_OK(status)) {
2637 smbd_server_connection_terminate(sconn, nt_errstr(status));
2638 return;
2641 status = smbd_smb2_request_dispatch(req);
2642 if (!NT_STATUS_IS_OK(status)) {
2643 smbd_server_connection_terminate(sconn, nt_errstr(status));
2644 return;
2647 status = smbd_smb2_request_next_incoming(sconn);
2648 if (!NT_STATUS_IS_OK(status)) {
2649 smbd_server_connection_terminate(sconn, nt_errstr(status));
2650 return;
2653 sconn->num_requests++;
2656 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2658 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2659 struct smbd_server_connection);
2660 NTSTATUS status;
2661 struct smbd_smb2_request *req = NULL;
2663 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2664 TALLOC_FREE(subreq);
2665 if (!NT_STATUS_IS_OK(status)) {
2666 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2667 nt_errstr(status)));
2668 smbd_server_connection_terminate(sconn, nt_errstr(status));
2669 return;
2672 if (req->in.nbt_hdr[0] != 0x00) {
2673 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2674 req->in.nbt_hdr[0]));
2675 TALLOC_FREE(req);
2676 goto next;
2679 req->current_idx = 1;
2681 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2682 req->current_idx, req->in.vector_count));
2684 status = smbd_smb2_request_validate(req);
2685 if (!NT_STATUS_IS_OK(status)) {
2686 smbd_server_connection_terminate(sconn, nt_errstr(status));
2687 return;
2690 status = smbd_smb2_request_setup_out(req);
2691 if (!NT_STATUS_IS_OK(status)) {
2692 smbd_server_connection_terminate(sconn, nt_errstr(status));
2693 return;
2696 status = smbd_smb2_request_dispatch(req);
2697 if (!NT_STATUS_IS_OK(status)) {
2698 smbd_server_connection_terminate(sconn, nt_errstr(status));
2699 return;
2702 next:
2703 status = smbd_smb2_request_next_incoming(sconn);
2704 if (!NT_STATUS_IS_OK(status)) {
2705 smbd_server_connection_terminate(sconn, nt_errstr(status));
2706 return;
2709 sconn->num_requests++;
2711 /* The timeout_processing function isn't run nearly
2712 often enough to implement 'max log size' without
2713 overrunning the size of the file by many megabytes.
2714 This is especially true if we are running at debug
2715 level 10. Checking every 50 SMB2s is a nice
2716 tradeoff of performance vs log file size overrun. */
2718 if ((sconn->num_requests % 50) == 0 &&
2719 need_to_check_log_size()) {
2720 change_to_root_user();
2721 check_log_size();