s3-waf: Link vfstest only against needed subsystems.
[Samba/id10ts.git] / source3 / smbd / smb2_server.c
bloba51e26ddb9bc294518ee34c96a022d91280c0fc9
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 uint32_t in_flags;
558 uint8_t *outhdr = NULL;
559 uint8_t *outbody = NULL;
560 uint32_t next_command_ofs = 0;
561 struct iovec *current = &vector[idx];
563 if ((idx + 3) < count) {
564 /* we have a next command -
565 * setup for the error case. */
566 next_command_ofs = SMB2_HDR_BODY + 9;
569 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
570 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
572 outhdr = talloc_zero_array(vector, uint8_t,
573 OUTVEC_ALLOC_SIZE);
574 if (outhdr == NULL) {
575 return NT_STATUS_NO_MEMORY;
578 outbody = outhdr + SMB2_HDR_BODY;
580 current[0].iov_base = (void *)outhdr;
581 current[0].iov_len = SMB2_HDR_BODY;
583 current[1].iov_base = (void *)outbody;
584 current[1].iov_len = 8;
586 current[2].iov_base = NULL;
587 current[2].iov_len = 0;
589 /* setup the SMB2 header */
590 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
591 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
592 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
593 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
594 SIVAL(outhdr, SMB2_HDR_STATUS,
595 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
596 SSVAL(outhdr, SMB2_HDR_OPCODE,
597 SVAL(inhdr, SMB2_HDR_OPCODE));
598 SIVAL(outhdr, SMB2_HDR_FLAGS,
599 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
600 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
601 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
602 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
603 SIVAL(outhdr, SMB2_HDR_PID,
604 IVAL(inhdr, SMB2_HDR_PID));
605 SIVAL(outhdr, SMB2_HDR_TID,
606 IVAL(inhdr, SMB2_HDR_TID));
607 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
608 BVAL(inhdr, SMB2_HDR_SESSION_ID));
609 memcpy(outhdr + SMB2_HDR_SIGNATURE,
610 inhdr + SMB2_HDR_SIGNATURE, 16);
612 /* setup error body header */
613 SSVAL(outbody, 0x00, 0x08 + 1);
614 SSVAL(outbody, 0x02, 0);
615 SIVAL(outbody, 0x04, 0);
618 req->out.vector = vector;
619 req->out.vector_count = count;
621 /* setup the length of the NBT packet */
622 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
624 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
626 return NT_STATUS_OK;
629 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
630 const char *reason,
631 const char *location)
633 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
634 reason, location));
635 exit_server_cleanly(reason);
638 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
639 struct iovec *outvec,
640 const struct iovec *srcvec)
642 /* vec[0] is always boilerplate and must
643 * be allocated with size OUTVEC_ALLOC_SIZE. */
645 outvec[0].iov_base = talloc_memdup(ctx,
646 srcvec[0].iov_base,
647 OUTVEC_ALLOC_SIZE);
648 if (!outvec[0].iov_base) {
649 return false;
651 outvec[0].iov_len = SMB2_HDR_BODY;
654 * If this is a "standard" vec[1] of length 8,
655 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
656 * then duplicate this. Else use talloc_memdup().
659 if (srcvec[1].iov_len == 8 &&
660 srcvec[1].iov_base ==
661 ((uint8_t *)srcvec[0].iov_base) +
662 SMB2_HDR_BODY) {
663 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
664 SMB2_HDR_BODY;
665 outvec[1].iov_len = 8;
666 } else {
667 outvec[1].iov_base = talloc_memdup(ctx,
668 srcvec[1].iov_base,
669 srcvec[1].iov_len);
670 if (!outvec[1].iov_base) {
671 return false;
673 outvec[1].iov_len = srcvec[1].iov_len;
677 * If this is a "standard" vec[2] of length 1,
678 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
679 * then duplicate this. Else use talloc_memdup().
682 if (srcvec[2].iov_base &&
683 srcvec[2].iov_len) {
684 if (srcvec[2].iov_base ==
685 ((uint8_t *)srcvec[0].iov_base) +
686 (OUTVEC_ALLOC_SIZE - 1) &&
687 srcvec[2].iov_len == 1) {
688 /* Common SMB2 error packet case. */
689 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
690 (OUTVEC_ALLOC_SIZE - 1);
691 } else {
692 outvec[2].iov_base = talloc_memdup(ctx,
693 srcvec[2].iov_base,
694 srcvec[2].iov_len);
695 if (!outvec[2].iov_base) {
696 return false;
699 outvec[2].iov_len = srcvec[2].iov_len;
700 } else {
701 outvec[2].iov_base = NULL;
702 outvec[2].iov_len = 0;
704 return true;
707 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
709 struct smbd_smb2_request *newreq = NULL;
710 struct iovec *outvec = NULL;
711 int count = req->out.vector_count;
712 int i;
714 newreq = smbd_smb2_request_allocate(req->sconn);
715 if (!newreq) {
716 return NULL;
719 newreq->sconn = req->sconn;
720 newreq->session = req->session;
721 newreq->do_signing = req->do_signing;
722 newreq->current_idx = req->current_idx;
724 outvec = talloc_zero_array(newreq, struct iovec, count);
725 if (!outvec) {
726 TALLOC_FREE(newreq);
727 return NULL;
729 newreq->out.vector = outvec;
730 newreq->out.vector_count = count;
732 /* Setup the outvec's identically to req. */
733 outvec[0].iov_base = newreq->out.nbt_hdr;
734 outvec[0].iov_len = 4;
735 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
737 /* Setup the vectors identically to the ones in req. */
738 for (i = 1; i < count; i += 3) {
739 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
740 break;
744 if (i < count) {
745 /* Alloc failed. */
746 TALLOC_FREE(newreq);
747 return NULL;
750 smb2_setup_nbt_length(newreq->out.vector,
751 newreq->out.vector_count);
753 return newreq;
756 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
758 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
760 int i = 0;
761 uint8_t *outhdr = NULL;
762 struct smbd_smb2_request *nreq = NULL;
764 /* Create a new smb2 request we'll use
765 for the interim return. */
766 nreq = dup_smb2_req(req);
767 if (!nreq) {
768 return NT_STATUS_NO_MEMORY;
771 /* Lose the last 3 out vectors. They're the
772 ones we'll be using for the async reply. */
773 nreq->out.vector_count -= 3;
775 smb2_setup_nbt_length(nreq->out.vector,
776 nreq->out.vector_count);
778 /* Step back to the previous reply. */
779 i = nreq->current_idx - 3;
780 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
781 /* And end the chain. */
782 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
784 /* Calculate outgoing credits */
785 smb2_calculate_credits(req, nreq);
787 /* Re-sign if needed. */
788 if (nreq->do_signing) {
789 NTSTATUS status;
790 status = smb2_signing_sign_pdu(nreq->session->session_key,
791 &nreq->out.vector[i], 3);
792 if (!NT_STATUS_IS_OK(status)) {
793 return status;
796 if (DEBUGLEVEL >= 10) {
797 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
798 (unsigned int)nreq->current_idx );
799 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
800 (unsigned int)nreq->out.vector_count );
801 print_req_vectors(nreq);
803 nreq->subreq = tstream_writev_queue_send(nreq,
804 nreq->sconn->ev_ctx,
805 nreq->sconn->smb2.stream,
806 nreq->sconn->smb2.send_queue,
807 nreq->out.vector,
808 nreq->out.vector_count);
810 if (nreq->subreq == NULL) {
811 return NT_STATUS_NO_MEMORY;
814 tevent_req_set_callback(nreq->subreq,
815 smbd_smb2_request_writev_done,
816 nreq);
818 return NT_STATUS_OK;
821 struct smbd_smb2_request_pending_state {
822 struct smbd_server_connection *sconn;
823 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
824 struct iovec vector[3];
827 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
829 struct smbd_smb2_request_pending_state *state =
830 tevent_req_callback_data(subreq,
831 struct smbd_smb2_request_pending_state);
832 struct smbd_server_connection *sconn = state->sconn;
833 int ret;
834 int sys_errno;
836 ret = tstream_writev_queue_recv(subreq, &sys_errno);
837 TALLOC_FREE(subreq);
838 if (ret == -1) {
839 NTSTATUS status = map_nt_error_from_unix(sys_errno);
840 smbd_server_connection_terminate(sconn, nt_errstr(status));
841 return;
844 TALLOC_FREE(state);
847 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
848 struct tevent_timer *te,
849 struct timeval current_time,
850 void *private_data);
852 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
853 struct tevent_req *subreq,
854 uint32_t defer_time)
856 NTSTATUS status;
857 int i = req->current_idx;
858 struct timeval defer_endtime;
859 uint8_t *outhdr = NULL;
860 uint32_t flags;
862 if (!tevent_req_is_in_progress(subreq)) {
863 return NT_STATUS_OK;
866 req->subreq = subreq;
867 subreq = NULL;
869 if (req->async_te) {
870 /* We're already async. */
871 return NT_STATUS_OK;
874 outhdr = (uint8_t *)req->out.vector[i].iov_base;
875 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
876 if (flags & SMB2_HDR_FLAG_ASYNC) {
877 /* We're already async. */
878 return NT_STATUS_OK;
881 if (req->in.vector_count > i + 3) {
883 * We're trying to go async in a compound
884 * request chain. This is not allowed.
885 * Cancel the outstanding request.
887 tevent_req_cancel(req->subreq);
888 return smbd_smb2_request_error(req,
889 NT_STATUS_INSUFFICIENT_RESOURCES);
892 if (DEBUGLEVEL >= 10) {
893 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
894 (unsigned int)req->current_idx );
895 print_req_vectors(req);
898 if (req->out.vector_count > 4) {
899 struct iovec *outvec = NULL;
901 /* This is a compound reply. We
902 * must do an interim response
903 * followed by the async response
904 * to match W2K8R2.
906 status = smb2_send_async_interim_response(req);
907 if (!NT_STATUS_IS_OK(status)) {
908 return status;
912 * We're splitting off the last SMB2
913 * request in a compound set, and the
914 * smb2_send_async_interim_response()
915 * call above just sent all the replies
916 * for the previous SMB2 requests in
917 * this compound set. So we're no longer
918 * in the "compound_related_in_progress"
919 * state, and this is no longer a compound
920 * request.
922 req->compound_related = false;
923 req->sconn->smb2.compound_related_in_progress = false;
925 /* Re-arrange the in.vectors. */
926 req->in.vector[1] = req->in.vector[i];
927 req->in.vector[2] = req->in.vector[i+1];
928 req->in.vector[3] = req->in.vector[i+2];
929 req->in.vector_count = 4;
931 /* Reset the new in size. */
932 smb2_setup_nbt_length(req->in.vector, 4);
934 /* Now recreate the out.vectors. */
935 outvec = talloc_zero_array(req, struct iovec, 4);
936 if (!outvec) {
937 return NT_STATUS_NO_MEMORY;
940 /* 0 is always boilerplate and must
941 * be of size 4 for the length field. */
943 outvec[0].iov_base = req->out.nbt_hdr;
944 outvec[0].iov_len = 4;
945 SIVAL(req->out.nbt_hdr, 0, 0);
947 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
948 return NT_STATUS_NO_MEMORY;
951 TALLOC_FREE(req->out.vector);
953 req->out.vector = outvec;
955 req->current_idx = 1;
956 req->out.vector_count = 4;
958 outhdr = (uint8_t *)req->out.vector[1].iov_base;
959 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
960 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
963 defer_endtime = timeval_current_ofs_usec(defer_time);
964 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
965 req, defer_endtime,
966 smbd_smb2_request_pending_timer,
967 req);
968 if (req->async_te == NULL) {
969 return NT_STATUS_NO_MEMORY;
972 return NT_STATUS_OK;
975 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
976 struct tevent_timer *te,
977 struct timeval current_time,
978 void *private_data)
980 struct smbd_smb2_request *req =
981 talloc_get_type_abort(private_data,
982 struct smbd_smb2_request);
983 struct smbd_smb2_request_pending_state *state = NULL;
984 int i = req->current_idx;
985 uint8_t *outhdr = NULL;
986 const uint8_t *inhdr = NULL;
987 uint8_t *hdr = NULL;
988 uint8_t *body = NULL;
989 uint32_t flags = 0;
990 uint64_t message_id = 0;
991 uint64_t async_id = 0;
992 struct tevent_req *subreq = NULL;
994 TALLOC_FREE(req->async_te);
996 /* Ensure our final reply matches the interim one. */
997 inhdr = (const uint8_t *)req->in.vector[1].iov_base;
998 outhdr = (uint8_t *)req->out.vector[1].iov_base;
999 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1000 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1002 async_id = message_id; /* keep it simple for now... */
1004 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1005 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1007 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1008 "going async\n",
1009 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1010 (unsigned long long)async_id ));
1013 * What we send is identical to a smbd_smb2_request_error
1014 * packet with an error status of STATUS_PENDING. Make use
1015 * of this fact sometime when refactoring. JRA.
1018 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1019 if (state == NULL) {
1020 smbd_server_connection_terminate(req->sconn,
1021 nt_errstr(NT_STATUS_NO_MEMORY));
1022 return;
1024 state->sconn = req->sconn;
1026 state->vector[0].iov_base = (void *)state->buf;
1027 state->vector[0].iov_len = 4;
1029 state->vector[1].iov_base = state->buf + 4;
1030 state->vector[1].iov_len = SMB2_HDR_BODY;
1032 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
1033 state->vector[2].iov_len = 9;
1035 smb2_setup_nbt_length(state->vector, 3);
1037 hdr = (uint8_t *)state->vector[1].iov_base;
1038 body = (uint8_t *)state->vector[2].iov_base;
1040 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1041 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1042 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1043 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1044 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1046 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1047 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1048 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1049 SBVAL(hdr, SMB2_HDR_PID, async_id);
1050 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1051 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1052 memcpy(hdr+SMB2_HDR_SIGNATURE,
1053 outhdr+SMB2_HDR_SIGNATURE, 16);
1055 SSVAL(body, 0x00, 0x08 + 1);
1057 SCVAL(body, 0x02, 0);
1058 SCVAL(body, 0x03, 0);
1059 SIVAL(body, 0x04, 0);
1060 /* Match W2K8R2... */
1061 SCVAL(body, 0x08, 0x21);
1063 /* Ensure we correctly go through crediting. Grant
1064 the credits now, and zero credits on the final
1065 response. */
1066 smb2_set_operation_credit(req->sconn,
1067 &req->in.vector[i],
1068 &state->vector[1]);
1070 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1072 if (req->do_signing) {
1073 NTSTATUS status;
1075 status = smb2_signing_sign_pdu(req->session->session_key,
1076 &state->vector[1], 2);
1077 if (!NT_STATUS_IS_OK(status)) {
1078 smbd_server_connection_terminate(req->sconn,
1079 nt_errstr(status));
1080 return;
1084 subreq = tstream_writev_queue_send(state,
1085 state->sconn->ev_ctx,
1086 state->sconn->smb2.stream,
1087 state->sconn->smb2.send_queue,
1088 state->vector,
1090 if (subreq == NULL) {
1091 smbd_server_connection_terminate(state->sconn,
1092 nt_errstr(NT_STATUS_NO_MEMORY));
1093 return;
1095 tevent_req_set_callback(subreq,
1096 smbd_smb2_request_pending_writev_done,
1097 state);
1100 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1102 struct smbd_server_connection *sconn = req->sconn;
1103 struct smbd_smb2_request *cur;
1104 const uint8_t *inhdr;
1105 int i = req->current_idx;
1106 uint32_t flags;
1107 uint64_t search_message_id;
1108 uint64_t search_async_id;
1109 uint64_t found_id;
1111 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1113 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1114 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1115 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1118 * we don't need the request anymore
1119 * cancel requests never have a response
1121 DLIST_REMOVE(req->sconn->smb2.requests, req);
1122 TALLOC_FREE(req);
1124 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1125 const uint8_t *outhdr;
1126 uint64_t message_id;
1127 uint64_t async_id;
1129 i = cur->current_idx;
1131 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1133 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1134 async_id = BVAL(outhdr, SMB2_HDR_PID);
1136 if (flags & SMB2_HDR_FLAG_ASYNC) {
1137 if (search_async_id == async_id) {
1138 found_id = async_id;
1139 break;
1141 } else {
1142 if (search_message_id == message_id) {
1143 found_id = message_id;
1144 break;
1149 if (cur && cur->subreq) {
1150 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1151 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1152 "cancel opcode[%s] mid %llu\n",
1153 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1154 (unsigned long long)found_id ));
1155 tevent_req_cancel(cur->subreq);
1158 return NT_STATUS_OK;
1161 /*************************************************************
1162 Ensure an incoming tid is a valid one for us to access.
1163 Change to the associated uid credentials and chdir to the
1164 valid tid directory.
1165 *************************************************************/
1167 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1169 const uint8_t *inhdr;
1170 int i = req->current_idx;
1171 uint32_t in_flags;
1172 uint32_t in_tid;
1173 void *p;
1174 struct smbd_smb2_tcon *tcon;
1176 req->tcon = NULL;
1178 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1180 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1181 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1183 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1184 in_tid = req->last_tid;
1187 /* lookup an existing session */
1188 p = idr_find(req->session->tcons.idtree, in_tid);
1189 if (p == NULL) {
1190 return NT_STATUS_NETWORK_NAME_DELETED;
1192 tcon = talloc_get_type_abort(p, struct smbd_smb2_tcon);
1194 if (!change_to_user(tcon->compat_conn,req->session->vuid)) {
1195 return NT_STATUS_ACCESS_DENIED;
1198 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1199 if (!set_current_service(tcon->compat_conn, 0, true)) {
1200 return NT_STATUS_ACCESS_DENIED;
1203 req->tcon = tcon;
1204 req->last_tid = in_tid;
1206 return NT_STATUS_OK;
1209 /*************************************************************
1210 Ensure an incoming session_id is a valid one for us to access.
1211 *************************************************************/
1213 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1215 const uint8_t *inhdr;
1216 int i = req->current_idx;
1217 uint32_t in_flags;
1218 uint64_t in_session_id;
1219 void *p;
1220 struct smbd_smb2_session *session;
1222 req->session = NULL;
1223 req->tcon = NULL;
1225 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1227 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1228 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1230 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1231 in_session_id = req->last_session_id;
1234 /* lookup an existing session */
1235 p = idr_find(req->sconn->smb2.sessions.idtree, in_session_id);
1236 if (p == NULL) {
1237 return NT_STATUS_USER_SESSION_DELETED;
1239 session = talloc_get_type_abort(p, struct smbd_smb2_session);
1241 if (!NT_STATUS_IS_OK(session->status)) {
1242 return NT_STATUS_ACCESS_DENIED;
1245 set_current_user_info(session->session_info->unix_info->sanitized_username,
1246 session->session_info->unix_info->unix_name,
1247 session->session_info->info->domain_name);
1249 req->session = session;
1250 req->last_session_id = in_session_id;
1252 return NT_STATUS_OK;
1255 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1256 size_t expected_body_size)
1258 const uint8_t *inhdr;
1259 uint16_t opcode;
1260 const uint8_t *inbody;
1261 int i = req->current_idx;
1262 size_t body_size;
1263 size_t min_dyn_size = expected_body_size & 0x00000001;
1266 * The following should be checked already.
1268 if ((i+2) > req->in.vector_count) {
1269 return NT_STATUS_INTERNAL_ERROR;
1271 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1272 return NT_STATUS_INTERNAL_ERROR;
1274 if (req->in.vector[i+1].iov_len < 2) {
1275 return NT_STATUS_INTERNAL_ERROR;
1278 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1279 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1281 switch (opcode) {
1282 case SMB2_OP_IOCTL:
1283 case SMB2_OP_GETINFO:
1284 min_dyn_size = 0;
1285 break;
1289 * Now check the expected body size,
1290 * where the last byte might be in the
1291 * dynnamic section..
1293 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1294 return NT_STATUS_INVALID_PARAMETER;
1296 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1297 return NT_STATUS_INVALID_PARAMETER;
1300 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1302 body_size = SVAL(inbody, 0x00);
1303 if (body_size != expected_body_size) {
1304 return NT_STATUS_INVALID_PARAMETER;
1307 return NT_STATUS_OK;
1310 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1312 const uint8_t *inhdr;
1313 int i = req->current_idx;
1314 uint16_t opcode;
1315 uint32_t flags;
1316 uint64_t mid;
1317 NTSTATUS status;
1318 NTSTATUS session_status;
1319 uint32_t allowed_flags;
1320 NTSTATUS return_value;
1322 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1324 /* TODO: verify more things */
1326 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1327 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1328 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1329 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1330 smb2_opcode_name(opcode),
1331 (unsigned long long)mid));
1333 if (get_Protocol() >= PROTOCOL_SMB2_02) {
1335 * once the protocol is negotiated
1336 * SMB2_OP_NEGPROT is not allowed anymore
1338 if (opcode == SMB2_OP_NEGPROT) {
1339 /* drop the connection */
1340 return NT_STATUS_INVALID_PARAMETER;
1342 } else {
1344 * if the protocol is not negotiated yet
1345 * only SMB2_OP_NEGPROT is allowed.
1347 if (opcode != SMB2_OP_NEGPROT) {
1348 /* drop the connection */
1349 return NT_STATUS_INVALID_PARAMETER;
1353 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1354 SMB2_HDR_FLAG_SIGNED |
1355 SMB2_HDR_FLAG_DFS;
1356 if (opcode == SMB2_OP_CANCEL) {
1357 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1359 if ((flags & ~allowed_flags) != 0) {
1360 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1364 * Check if the client provided a valid session id,
1365 * if so smbd_smb2_request_check_session() calls
1366 * set_current_user_info().
1368 * As some command don't require a valid session id
1369 * we defer the check of the session_status
1371 session_status = smbd_smb2_request_check_session(req);
1373 req->do_signing = false;
1374 if (flags & SMB2_HDR_FLAG_SIGNED) {
1375 if (!NT_STATUS_IS_OK(session_status)) {
1376 return smbd_smb2_request_error(req, session_status);
1379 req->do_signing = true;
1380 status = smb2_signing_check_pdu(req->session->session_key,
1381 &req->in.vector[i], 3);
1382 if (!NT_STATUS_IS_OK(status)) {
1383 return smbd_smb2_request_error(req, status);
1385 } else if (opcode == SMB2_OP_CANCEL) {
1386 /* Cancel requests are allowed to skip the signing */
1387 } else if (req->session && req->session->do_signing) {
1388 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1391 if (flags & SMB2_HDR_FLAG_CHAINED) {
1393 * This check is mostly for giving the correct error code
1394 * for compounded requests.
1396 * TODO: we may need to move this after the session
1397 * and tcon checks.
1399 if (!NT_STATUS_IS_OK(req->next_status)) {
1400 return smbd_smb2_request_error(req, req->next_status);
1402 } else {
1403 req->compat_chain_fsp = NULL;
1406 if (req->compound_related) {
1407 req->sconn->smb2.compound_related_in_progress = true;
1410 switch (opcode) {
1411 case SMB2_OP_NEGPROT:
1412 /* This call needs to be run as root */
1413 change_to_root_user();
1416 START_PROFILE(smb2_negprot);
1417 return_value = smbd_smb2_request_process_negprot(req);
1418 END_PROFILE(smb2_negprot);
1420 break;
1422 case SMB2_OP_SESSSETUP:
1423 /* This call needs to be run as root */
1424 change_to_root_user();
1427 START_PROFILE(smb2_sesssetup);
1428 return_value = smbd_smb2_request_process_sesssetup(req);
1429 END_PROFILE(smb2_sesssetup);
1431 break;
1433 case SMB2_OP_LOGOFF:
1434 if (!NT_STATUS_IS_OK(session_status)) {
1435 return_value = smbd_smb2_request_error(req, session_status);
1436 break;
1439 /* This call needs to be run as root */
1440 change_to_root_user();
1443 START_PROFILE(smb2_logoff);
1444 return_value = smbd_smb2_request_process_logoff(req);
1445 END_PROFILE(smb2_logoff);
1447 break;
1449 case SMB2_OP_TCON:
1450 if (!NT_STATUS_IS_OK(session_status)) {
1451 return_value = smbd_smb2_request_error(req, session_status);
1452 break;
1456 * This call needs to be run as root.
1458 * smbd_smb2_request_process_tcon()
1459 * calls make_connection_snum(), which will call
1460 * change_to_user(), when needed.
1462 change_to_root_user();
1465 START_PROFILE(smb2_tcon);
1466 return_value = smbd_smb2_request_process_tcon(req);
1467 END_PROFILE(smb2_tcon);
1469 break;
1471 case SMB2_OP_TDIS:
1472 if (!NT_STATUS_IS_OK(session_status)) {
1473 return_value = smbd_smb2_request_error(req, session_status);
1474 break;
1477 * This call needs to be run as user.
1479 * smbd_smb2_request_check_tcon()
1480 * calls change_to_user() on success.
1482 status = smbd_smb2_request_check_tcon(req);
1483 if (!NT_STATUS_IS_OK(status)) {
1484 return_value = smbd_smb2_request_error(req, status);
1485 break;
1487 /* This call needs to be run as root */
1488 change_to_root_user();
1492 START_PROFILE(smb2_tdis);
1493 return_value = smbd_smb2_request_process_tdis(req);
1494 END_PROFILE(smb2_tdis);
1496 break;
1498 case SMB2_OP_CREATE:
1499 if (!NT_STATUS_IS_OK(session_status)) {
1500 return_value = smbd_smb2_request_error(req, session_status);
1501 break;
1504 * This call needs to be run as user.
1506 * smbd_smb2_request_check_tcon()
1507 * calls change_to_user() on success.
1509 status = smbd_smb2_request_check_tcon(req);
1510 if (!NT_STATUS_IS_OK(status)) {
1511 return_value = smbd_smb2_request_error(req, status);
1512 break;
1516 START_PROFILE(smb2_create);
1517 return_value = smbd_smb2_request_process_create(req);
1518 END_PROFILE(smb2_create);
1520 break;
1522 case SMB2_OP_CLOSE:
1523 if (!NT_STATUS_IS_OK(session_status)) {
1524 return_value = smbd_smb2_request_error(req, session_status);
1525 break;
1528 * This call needs to be run as user.
1530 * smbd_smb2_request_check_tcon()
1531 * calls change_to_user() on success.
1533 status = smbd_smb2_request_check_tcon(req);
1534 if (!NT_STATUS_IS_OK(status)) {
1535 return_value = smbd_smb2_request_error(req, status);
1536 break;
1540 START_PROFILE(smb2_close);
1541 return_value = smbd_smb2_request_process_close(req);
1542 END_PROFILE(smb2_close);
1544 break;
1546 case SMB2_OP_FLUSH:
1547 if (!NT_STATUS_IS_OK(session_status)) {
1548 return_value = smbd_smb2_request_error(req, session_status);
1549 break;
1552 * This call needs to be run as user.
1554 * smbd_smb2_request_check_tcon()
1555 * calls change_to_user() on success.
1557 status = smbd_smb2_request_check_tcon(req);
1558 if (!NT_STATUS_IS_OK(status)) {
1559 return_value = smbd_smb2_request_error(req, status);
1560 break;
1564 START_PROFILE(smb2_flush);
1565 return_value = smbd_smb2_request_process_flush(req);
1566 END_PROFILE(smb2_flush);
1568 break;
1570 case SMB2_OP_READ:
1571 if (!NT_STATUS_IS_OK(session_status)) {
1572 return_value = smbd_smb2_request_error(req, session_status);
1573 break;
1576 * This call needs to be run as user.
1578 * smbd_smb2_request_check_tcon()
1579 * calls change_to_user() on success.
1581 status = smbd_smb2_request_check_tcon(req);
1582 if (!NT_STATUS_IS_OK(status)) {
1583 return_value = smbd_smb2_request_error(req, status);
1584 break;
1588 START_PROFILE(smb2_read);
1589 return_value = smbd_smb2_request_process_read(req);
1590 END_PROFILE(smb2_read);
1592 break;
1594 case SMB2_OP_WRITE:
1595 if (!NT_STATUS_IS_OK(session_status)) {
1596 return_value = smbd_smb2_request_error(req, session_status);
1597 break;
1600 * This call needs to be run as user.
1602 * smbd_smb2_request_check_tcon()
1603 * calls change_to_user() on success.
1605 status = smbd_smb2_request_check_tcon(req);
1606 if (!NT_STATUS_IS_OK(status)) {
1607 return_value = smbd_smb2_request_error(req, status);
1608 break;
1612 START_PROFILE(smb2_write);
1613 return_value = smbd_smb2_request_process_write(req);
1614 END_PROFILE(smb2_write);
1616 break;
1618 case SMB2_OP_LOCK:
1619 if (!NT_STATUS_IS_OK(session_status)) {
1620 /* Too ugly to live ? JRA. */
1621 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1622 session_status = NT_STATUS_FILE_CLOSED;
1624 return_value = smbd_smb2_request_error(req, session_status);
1625 break;
1628 * This call needs to be run as user.
1630 * smbd_smb2_request_check_tcon()
1631 * calls change_to_user() on success.
1633 status = smbd_smb2_request_check_tcon(req);
1634 if (!NT_STATUS_IS_OK(status)) {
1635 /* Too ugly to live ? JRA. */
1636 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1637 status = NT_STATUS_FILE_CLOSED;
1639 return_value = smbd_smb2_request_error(req, status);
1640 break;
1644 START_PROFILE(smb2_lock);
1645 return_value = smbd_smb2_request_process_lock(req);
1646 END_PROFILE(smb2_lock);
1648 break;
1650 case SMB2_OP_IOCTL:
1651 if (!NT_STATUS_IS_OK(session_status)) {
1652 return_value = smbd_smb2_request_error(req, session_status);
1653 break;
1656 * This call needs to be run as user.
1658 * smbd_smb2_request_check_tcon()
1659 * calls change_to_user() on success.
1661 status = smbd_smb2_request_check_tcon(req);
1662 if (!NT_STATUS_IS_OK(status)) {
1663 return_value = smbd_smb2_request_error(req, status);
1664 break;
1668 START_PROFILE(smb2_ioctl);
1669 return_value = smbd_smb2_request_process_ioctl(req);
1670 END_PROFILE(smb2_ioctl);
1672 break;
1674 case SMB2_OP_CANCEL:
1676 * This call needs to be run as root
1678 * That is what we also do in the SMB1 case.
1680 change_to_root_user();
1683 START_PROFILE(smb2_cancel);
1684 return_value = smbd_smb2_request_process_cancel(req);
1685 END_PROFILE(smb2_cancel);
1687 break;
1689 case SMB2_OP_KEEPALIVE:
1690 /* This call needs to be run as root */
1691 change_to_root_user();
1694 START_PROFILE(smb2_keepalive);
1695 return_value = smbd_smb2_request_process_keepalive(req);
1696 END_PROFILE(smb2_keepalive);
1698 break;
1700 case SMB2_OP_FIND:
1701 if (!NT_STATUS_IS_OK(session_status)) {
1702 return_value = smbd_smb2_request_error(req, session_status);
1703 break;
1706 * This call needs to be run as user.
1708 * smbd_smb2_request_check_tcon()
1709 * calls change_to_user() on success.
1711 status = smbd_smb2_request_check_tcon(req);
1712 if (!NT_STATUS_IS_OK(status)) {
1713 return_value = smbd_smb2_request_error(req, status);
1714 break;
1718 START_PROFILE(smb2_find);
1719 return_value = smbd_smb2_request_process_find(req);
1720 END_PROFILE(smb2_find);
1722 break;
1724 case SMB2_OP_NOTIFY:
1725 if (!NT_STATUS_IS_OK(session_status)) {
1726 return_value = smbd_smb2_request_error(req, session_status);
1727 break;
1730 * This call needs to be run as user.
1732 * smbd_smb2_request_check_tcon()
1733 * calls change_to_user() on success.
1735 status = smbd_smb2_request_check_tcon(req);
1736 if (!NT_STATUS_IS_OK(status)) {
1737 return_value = smbd_smb2_request_error(req, status);
1738 break;
1742 START_PROFILE(smb2_notify);
1743 return_value = smbd_smb2_request_process_notify(req);
1744 END_PROFILE(smb2_notify);
1746 break;
1748 case SMB2_OP_GETINFO:
1749 if (!NT_STATUS_IS_OK(session_status)) {
1750 return_value = smbd_smb2_request_error(req, session_status);
1751 break;
1754 * This call needs to be run as user.
1756 * smbd_smb2_request_check_tcon()
1757 * calls change_to_user() on success.
1759 status = smbd_smb2_request_check_tcon(req);
1760 if (!NT_STATUS_IS_OK(status)) {
1761 return_value = smbd_smb2_request_error(req, status);
1762 break;
1766 START_PROFILE(smb2_getinfo);
1767 return_value = smbd_smb2_request_process_getinfo(req);
1768 END_PROFILE(smb2_getinfo);
1770 break;
1772 case SMB2_OP_SETINFO:
1773 if (!NT_STATUS_IS_OK(session_status)) {
1774 return_value = smbd_smb2_request_error(req, session_status);
1775 break;
1778 * This call needs to be run as user.
1780 * smbd_smb2_request_check_tcon()
1781 * calls change_to_user() on success.
1783 status = smbd_smb2_request_check_tcon(req);
1784 if (!NT_STATUS_IS_OK(status)) {
1785 return_value = smbd_smb2_request_error(req, status);
1786 break;
1790 START_PROFILE(smb2_setinfo);
1791 return_value = smbd_smb2_request_process_setinfo(req);
1792 END_PROFILE(smb2_setinfo);
1794 break;
1796 case SMB2_OP_BREAK:
1797 if (!NT_STATUS_IS_OK(session_status)) {
1798 return_value = smbd_smb2_request_error(req, session_status);
1799 break;
1802 * This call needs to be run as user.
1804 * smbd_smb2_request_check_tcon()
1805 * calls change_to_user() on success.
1807 status = smbd_smb2_request_check_tcon(req);
1808 if (!NT_STATUS_IS_OK(status)) {
1809 return_value = smbd_smb2_request_error(req, status);
1810 break;
1814 START_PROFILE(smb2_break);
1815 return_value = smbd_smb2_request_process_break(req);
1816 END_PROFILE(smb2_break);
1818 break;
1820 default:
1821 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1822 break;
1824 return return_value;
1827 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1829 struct tevent_req *subreq;
1830 int i = req->current_idx;
1832 req->subreq = NULL;
1833 TALLOC_FREE(req->async_te);
1835 req->current_idx += 3;
1837 if (req->current_idx < req->out.vector_count) {
1839 * We must process the remaining compound
1840 * SMB2 requests before any new incoming SMB2
1841 * requests. This is because incoming SMB2
1842 * requests may include a cancel for a
1843 * compound request we haven't processed
1844 * yet.
1846 struct tevent_immediate *im = tevent_create_immediate(req);
1847 if (!im) {
1848 return NT_STATUS_NO_MEMORY;
1850 tevent_schedule_immediate(im,
1851 req->sconn->ev_ctx,
1852 smbd_smb2_request_dispatch_immediate,
1853 req);
1854 return NT_STATUS_OK;
1857 if (req->compound_related) {
1858 req->sconn->smb2.compound_related_in_progress = false;
1861 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1863 /* Set credit for these operations (zero credits if this
1864 is a final reply for an async operation). */
1865 smb2_calculate_credits(req, req);
1867 if (req->do_signing) {
1868 NTSTATUS status;
1869 status = smb2_signing_sign_pdu(req->session->session_key,
1870 &req->out.vector[i], 3);
1871 if (!NT_STATUS_IS_OK(status)) {
1872 return status;
1876 if (DEBUGLEVEL >= 10) {
1877 dbgtext("smbd_smb2_request_reply: sending...\n");
1878 print_req_vectors(req);
1881 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1882 if (req->out.vector_count == 4 &&
1883 req->out.vector[3].iov_base == NULL &&
1884 req->out.vector[3].iov_len != 0) {
1885 /* Dynamic part is NULL. Chop it off,
1886 We're going to send it via sendfile. */
1887 req->out.vector_count -= 1;
1890 subreq = tstream_writev_queue_send(req,
1891 req->sconn->ev_ctx,
1892 req->sconn->smb2.stream,
1893 req->sconn->smb2.send_queue,
1894 req->out.vector,
1895 req->out.vector_count);
1896 if (subreq == NULL) {
1897 return NT_STATUS_NO_MEMORY;
1899 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1901 * We're done with this request -
1902 * move it off the "being processed" queue.
1904 DLIST_REMOVE(req->sconn->smb2.requests, req);
1906 return NT_STATUS_OK;
1909 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
1911 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1912 struct tevent_immediate *im,
1913 void *private_data)
1915 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1916 struct smbd_smb2_request);
1917 struct smbd_server_connection *sconn = req->sconn;
1918 NTSTATUS status;
1920 TALLOC_FREE(im);
1922 if (DEBUGLEVEL >= 10) {
1923 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1924 req->current_idx, req->in.vector_count));
1925 print_req_vectors(req);
1928 status = smbd_smb2_request_dispatch(req);
1929 if (!NT_STATUS_IS_OK(status)) {
1930 smbd_server_connection_terminate(sconn, nt_errstr(status));
1931 return;
1934 status = smbd_smb2_request_next_incoming(sconn);
1935 if (!NT_STATUS_IS_OK(status)) {
1936 smbd_server_connection_terminate(sconn, nt_errstr(status));
1937 return;
1941 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1943 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1944 struct smbd_smb2_request);
1945 struct smbd_server_connection *sconn = req->sconn;
1946 int ret;
1947 int sys_errno;
1948 NTSTATUS status;
1950 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1951 TALLOC_FREE(subreq);
1952 TALLOC_FREE(req);
1953 if (ret == -1) {
1954 status = map_nt_error_from_unix(sys_errno);
1955 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1956 nt_errstr(status)));
1957 smbd_server_connection_terminate(sconn, nt_errstr(status));
1958 return;
1961 status = smbd_smb2_request_next_incoming(sconn);
1962 if (!NT_STATUS_IS_OK(status)) {
1963 smbd_server_connection_terminate(sconn, nt_errstr(status));
1964 return;
1968 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1969 NTSTATUS status,
1970 DATA_BLOB body, DATA_BLOB *dyn,
1971 const char *location)
1973 uint8_t *outhdr;
1974 int i = req->current_idx;
1975 uint32_t next_command_ofs;
1977 DEBUG(10,("smbd_smb2_request_done_ex: "
1978 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1979 i, nt_errstr(status), (unsigned int)body.length,
1980 dyn ? "yes": "no",
1981 (unsigned int)(dyn ? dyn->length : 0),
1982 location));
1984 if (body.length < 2) {
1985 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1988 if ((body.length % 2) != 0) {
1989 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1992 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1994 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1995 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1997 req->out.vector[i+1].iov_base = (void *)body.data;
1998 req->out.vector[i+1].iov_len = body.length;
2000 if (dyn) {
2001 req->out.vector[i+2].iov_base = (void *)dyn->data;
2002 req->out.vector[i+2].iov_len = dyn->length;
2003 } else {
2004 req->out.vector[i+2].iov_base = NULL;
2005 req->out.vector[i+2].iov_len = 0;
2008 /* see if we need to recalculate the offset to the next response */
2009 if (next_command_ofs > 0) {
2010 next_command_ofs = SMB2_HDR_BODY;
2011 next_command_ofs += req->out.vector[i+1].iov_len;
2012 next_command_ofs += req->out.vector[i+2].iov_len;
2015 if ((next_command_ofs % 8) != 0) {
2016 size_t pad_size = 8 - (next_command_ofs % 8);
2017 if (req->out.vector[i+2].iov_len == 0) {
2019 * if the dyn buffer is empty
2020 * we can use it to add padding
2022 uint8_t *pad;
2024 pad = talloc_zero_array(req->out.vector,
2025 uint8_t, pad_size);
2026 if (pad == NULL) {
2027 return smbd_smb2_request_error(req,
2028 NT_STATUS_NO_MEMORY);
2031 req->out.vector[i+2].iov_base = (void *)pad;
2032 req->out.vector[i+2].iov_len = pad_size;
2033 } else {
2035 * For now we copy the dynamic buffer
2036 * and add the padding to the new buffer
2038 size_t old_size;
2039 uint8_t *old_dyn;
2040 size_t new_size;
2041 uint8_t *new_dyn;
2043 old_size = req->out.vector[i+2].iov_len;
2044 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2046 new_size = old_size + pad_size;
2047 new_dyn = talloc_zero_array(req->out.vector,
2048 uint8_t, new_size);
2049 if (new_dyn == NULL) {
2050 return smbd_smb2_request_error(req,
2051 NT_STATUS_NO_MEMORY);
2054 memcpy(new_dyn, old_dyn, old_size);
2055 memset(new_dyn + old_size, 0, pad_size);
2057 req->out.vector[i+2].iov_base = (void *)new_dyn;
2058 req->out.vector[i+2].iov_len = new_size;
2060 next_command_ofs += pad_size;
2063 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2065 return smbd_smb2_request_reply(req);
2068 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2069 NTSTATUS status,
2070 DATA_BLOB *info,
2071 const char *location)
2073 DATA_BLOB body;
2074 int i = req->current_idx;
2075 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
2077 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2078 i, nt_errstr(status), info ? " +info" : "",
2079 location));
2081 body.data = outhdr + SMB2_HDR_BODY;
2082 body.length = 8;
2083 SSVAL(body.data, 0, 9);
2085 if (info) {
2086 SIVAL(body.data, 0x04, info->length);
2087 } else {
2088 /* Allocated size of req->out.vector[i].iov_base
2089 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2090 * 1 byte without having to do an alloc.
2092 info = talloc_zero_array(req->out.vector,
2093 DATA_BLOB,
2095 if (!info) {
2096 return NT_STATUS_NO_MEMORY;
2098 info->data = ((uint8_t *)outhdr) +
2099 OUTVEC_ALLOC_SIZE - 1;
2100 info->length = 1;
2101 SCVAL(info->data, 0, 0);
2105 * if a request fails, all other remaining
2106 * compounded requests should fail too
2108 req->next_status = NT_STATUS_INVALID_PARAMETER;
2110 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2114 struct smbd_smb2_send_oplock_break_state {
2115 struct smbd_server_connection *sconn;
2116 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2117 struct iovec vector;
2120 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2122 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2123 uint64_t file_id_persistent,
2124 uint64_t file_id_volatile,
2125 uint8_t oplock_level)
2127 struct smbd_smb2_send_oplock_break_state *state;
2128 struct tevent_req *subreq;
2129 uint8_t *hdr;
2130 uint8_t *body;
2132 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2133 if (state == NULL) {
2134 return NT_STATUS_NO_MEMORY;
2136 state->sconn = sconn;
2138 state->vector.iov_base = (void *)state->buf;
2139 state->vector.iov_len = sizeof(state->buf);
2141 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2142 hdr = state->buf + 4;
2143 body = hdr + SMB2_HDR_BODY;
2145 SIVAL(hdr, 0, SMB2_MAGIC);
2146 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2147 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2148 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2149 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2150 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2151 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2152 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2153 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2154 SIVAL(hdr, SMB2_HDR_PID, 0);
2155 SIVAL(hdr, SMB2_HDR_TID, 0);
2156 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2157 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2159 SSVAL(body, 0x00, 0x18);
2161 SCVAL(body, 0x02, oplock_level);
2162 SCVAL(body, 0x03, 0); /* reserved */
2163 SIVAL(body, 0x04, 0); /* reserved */
2164 SBVAL(body, 0x08, file_id_persistent);
2165 SBVAL(body, 0x10, file_id_volatile);
2167 subreq = tstream_writev_queue_send(state,
2168 sconn->ev_ctx,
2169 sconn->smb2.stream,
2170 sconn->smb2.send_queue,
2171 &state->vector, 1);
2172 if (subreq == NULL) {
2173 return NT_STATUS_NO_MEMORY;
2175 tevent_req_set_callback(subreq,
2176 smbd_smb2_oplock_break_writev_done,
2177 state);
2179 return NT_STATUS_OK;
2182 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2184 struct smbd_smb2_send_oplock_break_state *state =
2185 tevent_req_callback_data(subreq,
2186 struct smbd_smb2_send_oplock_break_state);
2187 struct smbd_server_connection *sconn = state->sconn;
2188 int ret;
2189 int sys_errno;
2191 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2192 TALLOC_FREE(subreq);
2193 if (ret == -1) {
2194 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2195 smbd_server_connection_terminate(sconn, nt_errstr(status));
2196 return;
2199 TALLOC_FREE(state);
2202 struct smbd_smb2_request_read_state {
2203 size_t missing;
2204 bool asked_for_header;
2205 struct smbd_smb2_request *smb2_req;
2208 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2209 void *private_data,
2210 TALLOC_CTX *mem_ctx,
2211 struct iovec **_vector,
2212 size_t *_count);
2213 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2215 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2216 struct tevent_context *ev,
2217 struct smbd_server_connection *sconn)
2219 struct tevent_req *req;
2220 struct smbd_smb2_request_read_state *state;
2221 struct tevent_req *subreq;
2223 req = tevent_req_create(mem_ctx, &state,
2224 struct smbd_smb2_request_read_state);
2225 if (req == NULL) {
2226 return NULL;
2228 state->missing = 0;
2229 state->asked_for_header = false;
2231 state->smb2_req = smbd_smb2_request_allocate(state);
2232 if (tevent_req_nomem(state->smb2_req, req)) {
2233 return tevent_req_post(req, ev);
2235 state->smb2_req->sconn = sconn;
2237 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2238 sconn->smb2.recv_queue,
2239 smbd_smb2_request_next_vector,
2240 state);
2241 if (tevent_req_nomem(subreq, req)) {
2242 return tevent_req_post(req, ev);
2244 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2246 return req;
2249 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2250 void *private_data,
2251 TALLOC_CTX *mem_ctx,
2252 struct iovec **_vector,
2253 size_t *_count)
2255 struct smbd_smb2_request_read_state *state =
2256 talloc_get_type_abort(private_data,
2257 struct smbd_smb2_request_read_state);
2258 struct smbd_smb2_request *req = state->smb2_req;
2259 struct iovec *vector;
2260 int idx = req->in.vector_count;
2261 size_t len = 0;
2262 uint8_t *buf = NULL;
2264 if (req->in.vector_count == 0) {
2266 * first we need to get the NBT header
2268 req->in.vector = talloc_array(req, struct iovec,
2269 req->in.vector_count + 1);
2270 if (req->in.vector == NULL) {
2271 return -1;
2273 req->in.vector_count += 1;
2275 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2276 req->in.vector[idx].iov_len = 4;
2278 vector = talloc_array(mem_ctx, struct iovec, 1);
2279 if (vector == NULL) {
2280 return -1;
2283 vector[0] = req->in.vector[idx];
2285 *_vector = vector;
2286 *_count = 1;
2287 return 0;
2290 if (req->in.vector_count == 1) {
2292 * Now we analyze the NBT header
2294 state->missing = smb2_len(req->in.vector[0].iov_base);
2296 if (state->missing == 0) {
2297 /* if there're no remaining bytes, we're done */
2298 *_vector = NULL;
2299 *_count = 0;
2300 return 0;
2303 req->in.vector = talloc_realloc(req, req->in.vector,
2304 struct iovec,
2305 req->in.vector_count + 1);
2306 if (req->in.vector == NULL) {
2307 return -1;
2309 req->in.vector_count += 1;
2311 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2313 * it's a special NBT message,
2314 * so get all remaining bytes
2316 len = state->missing;
2317 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2319 * it's an invalid message, just read what we can get
2320 * and let the caller handle the error
2322 len = state->missing;
2323 } else {
2325 * We assume it's a SMB2 request,
2326 * and we first get the header and the
2327 * first 2 bytes (the struct size) of the body
2329 len = SMB2_HDR_BODY + 2;
2331 state->asked_for_header = true;
2334 state->missing -= len;
2336 buf = talloc_array(req->in.vector, uint8_t, len);
2337 if (buf == NULL) {
2338 return -1;
2341 req->in.vector[idx].iov_base = (void *)buf;
2342 req->in.vector[idx].iov_len = len;
2344 vector = talloc_array(mem_ctx, struct iovec, 1);
2345 if (vector == NULL) {
2346 return -1;
2349 vector[0] = req->in.vector[idx];
2351 *_vector = vector;
2352 *_count = 1;
2353 return 0;
2356 if (state->missing == 0) {
2357 /* if there're no remaining bytes, we're done */
2358 *_vector = NULL;
2359 *_count = 0;
2360 return 0;
2363 if (state->asked_for_header) {
2364 const uint8_t *hdr;
2365 size_t full_size;
2366 size_t next_command_ofs;
2367 size_t body_size;
2368 uint8_t *body;
2369 size_t dyn_size;
2370 uint8_t *dyn;
2371 bool invalid = false;
2373 state->asked_for_header = false;
2376 * We got the SMB2 header and the first 2 bytes
2377 * of the body. We fix the size to just the header
2378 * and manually copy the 2 first bytes to the body section
2380 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2381 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2383 /* allocate vectors for body and dynamic areas */
2384 req->in.vector = talloc_realloc(req, req->in.vector,
2385 struct iovec,
2386 req->in.vector_count + 2);
2387 if (req->in.vector == NULL) {
2388 return -1;
2390 req->in.vector_count += 2;
2392 full_size = state->missing + SMB2_HDR_BODY + 2;
2393 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2394 body_size = SVAL(hdr, SMB2_HDR_BODY);
2396 if (next_command_ofs != 0) {
2397 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2399 * this is invalid, just return a zero
2400 * body and let the caller deal with the error
2402 invalid = true;
2403 } else if (next_command_ofs > full_size) {
2405 * this is invalid, just return a zero
2406 * body and let the caller deal with the error
2408 invalid = true;
2409 } else {
2410 full_size = next_command_ofs;
2414 if (!invalid) {
2415 if (body_size < 2) {
2417 * this is invalid, just return a zero
2418 * body and let the caller deal with the error
2420 invalid = true;
2424 * Mask out the lowest bit, the "dynamic" part
2425 * of body_size.
2427 body_size &= ~1;
2429 if (body_size > (full_size - SMB2_HDR_BODY)) {
2431 * this is invalid, just return a zero
2432 * body and let the caller deal with the error
2434 invalid = true;
2438 if (invalid) {
2439 /* the caller should check this */
2440 body_size = 2;
2443 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2445 state->missing -= (body_size - 2) + dyn_size;
2447 body = talloc_array(req->in.vector, uint8_t, body_size);
2448 if (body == NULL) {
2449 return -1;
2452 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2453 if (dyn == NULL) {
2454 return -1;
2457 req->in.vector[idx].iov_base = (void *)body;
2458 req->in.vector[idx].iov_len = body_size;
2459 req->in.vector[idx+1].iov_base = (void *)dyn;
2460 req->in.vector[idx+1].iov_len = dyn_size;
2462 vector = talloc_array(mem_ctx, struct iovec, 2);
2463 if (vector == NULL) {
2464 return -1;
2468 * the first 2 bytes of the body were already fetched
2469 * together with the header
2471 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2472 vector[0].iov_base = body + 2;
2473 vector[0].iov_len = body_size - 2;
2475 vector[1] = req->in.vector[idx+1];
2477 *_vector = vector;
2478 *_count = 2;
2479 return 0;
2483 * when we endup here, we're looking for a new SMB2 request
2484 * next. And we ask for its header and the first 2 bytes of
2485 * the body (like we did for the first SMB2 request).
2488 req->in.vector = talloc_realloc(req, req->in.vector,
2489 struct iovec,
2490 req->in.vector_count + 1);
2491 if (req->in.vector == NULL) {
2492 return -1;
2494 req->in.vector_count += 1;
2497 * We assume it's a SMB2 request,
2498 * and we first get the header and the
2499 * first 2 bytes (the struct size) of the body
2501 len = SMB2_HDR_BODY + 2;
2503 if (len > state->missing) {
2504 /* let the caller handle the error */
2505 len = state->missing;
2508 state->missing -= len;
2509 state->asked_for_header = true;
2511 buf = talloc_array(req->in.vector, uint8_t, len);
2512 if (buf == NULL) {
2513 return -1;
2516 req->in.vector[idx].iov_base = (void *)buf;
2517 req->in.vector[idx].iov_len = len;
2519 vector = talloc_array(mem_ctx, struct iovec, 1);
2520 if (vector == NULL) {
2521 return -1;
2524 vector[0] = req->in.vector[idx];
2526 *_vector = vector;
2527 *_count = 1;
2528 return 0;
2531 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2533 struct tevent_req *req =
2534 tevent_req_callback_data(subreq,
2535 struct tevent_req);
2536 int ret;
2537 int sys_errno;
2538 NTSTATUS status;
2540 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2541 if (ret == -1) {
2542 status = map_nt_error_from_unix(sys_errno);
2543 tevent_req_nterror(req, status);
2544 return;
2547 tevent_req_done(req);
2550 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2551 TALLOC_CTX *mem_ctx,
2552 struct smbd_smb2_request **_smb2_req)
2554 struct smbd_smb2_request_read_state *state =
2555 tevent_req_data(req,
2556 struct smbd_smb2_request_read_state);
2557 NTSTATUS status;
2559 if (tevent_req_is_nterror(req, &status)) {
2560 tevent_req_received(req);
2561 return status;
2564 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2565 *_smb2_req = state->smb2_req;
2566 tevent_req_received(req);
2567 return NT_STATUS_OK;
2570 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2572 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2574 size_t max_send_queue_len;
2575 size_t cur_send_queue_len;
2576 struct tevent_req *subreq;
2578 if (sconn->smb2.compound_related_in_progress) {
2580 * Can't read another until the related
2581 * compound is done.
2583 return NT_STATUS_OK;
2586 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2588 * if there is already a smbd_smb2_request_read
2589 * pending, we are done.
2591 return NT_STATUS_OK;
2594 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2595 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2597 if (cur_send_queue_len > max_send_queue_len) {
2599 * if we have a lot of requests to send,
2600 * we wait until they are on the wire until we
2601 * ask for the next request.
2603 return NT_STATUS_OK;
2606 /* ask for the next request */
2607 subreq = smbd_smb2_request_read_send(sconn, sconn->ev_ctx, sconn);
2608 if (subreq == NULL) {
2609 return NT_STATUS_NO_MEMORY;
2611 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2613 return NT_STATUS_OK;
2616 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2617 const uint8_t *inbuf, size_t size)
2619 NTSTATUS status;
2620 struct smbd_smb2_request *req = NULL;
2622 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2623 (unsigned int)size));
2625 status = smbd_initialize_smb2(sconn);
2626 if (!NT_STATUS_IS_OK(status)) {
2627 smbd_server_connection_terminate(sconn, nt_errstr(status));
2628 return;
2631 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2632 if (!NT_STATUS_IS_OK(status)) {
2633 smbd_server_connection_terminate(sconn, nt_errstr(status));
2634 return;
2637 status = smbd_smb2_request_setup_out(req);
2638 if (!NT_STATUS_IS_OK(status)) {
2639 smbd_server_connection_terminate(sconn, nt_errstr(status));
2640 return;
2643 status = smbd_smb2_request_dispatch(req);
2644 if (!NT_STATUS_IS_OK(status)) {
2645 smbd_server_connection_terminate(sconn, nt_errstr(status));
2646 return;
2649 status = smbd_smb2_request_next_incoming(sconn);
2650 if (!NT_STATUS_IS_OK(status)) {
2651 smbd_server_connection_terminate(sconn, nt_errstr(status));
2652 return;
2655 sconn->num_requests++;
2658 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2660 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2661 struct smbd_server_connection);
2662 NTSTATUS status;
2663 struct smbd_smb2_request *req = NULL;
2665 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2666 TALLOC_FREE(subreq);
2667 if (!NT_STATUS_IS_OK(status)) {
2668 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2669 nt_errstr(status)));
2670 smbd_server_connection_terminate(sconn, nt_errstr(status));
2671 return;
2674 if (req->in.nbt_hdr[0] != 0x00) {
2675 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2676 req->in.nbt_hdr[0]));
2677 TALLOC_FREE(req);
2678 goto next;
2681 req->current_idx = 1;
2683 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2684 req->current_idx, req->in.vector_count));
2686 status = smbd_smb2_request_validate(req);
2687 if (!NT_STATUS_IS_OK(status)) {
2688 smbd_server_connection_terminate(sconn, nt_errstr(status));
2689 return;
2692 status = smbd_smb2_request_setup_out(req);
2693 if (!NT_STATUS_IS_OK(status)) {
2694 smbd_server_connection_terminate(sconn, nt_errstr(status));
2695 return;
2698 status = smbd_smb2_request_dispatch(req);
2699 if (!NT_STATUS_IS_OK(status)) {
2700 smbd_server_connection_terminate(sconn, nt_errstr(status));
2701 return;
2704 next:
2705 status = smbd_smb2_request_next_incoming(sconn);
2706 if (!NT_STATUS_IS_OK(status)) {
2707 smbd_server_connection_terminate(sconn, nt_errstr(status));
2708 return;
2711 sconn->num_requests++;
2713 /* The timeout_processing function isn't run nearly
2714 often enough to implement 'max log size' without
2715 overrunning the size of the file by many megabytes.
2716 This is especially true if we are running at debug
2717 level 10. Checking every 50 SMB2s is a nice
2718 tradeoff of performance vs log file size overrun. */
2720 if ((sconn->num_requests % 50) == 0 &&
2721 need_to_check_log_size()) {
2722 change_to_root_user();
2723 check_log_size();