s3-docs: Fix typo.
[Samba/gebeck_regimport.git] / source3 / smbd / smb2_server.c
blob84b55cce7d1ef51d0493d972b0037cf84d791738
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.event_ctx = server_event_context();
103 sconn->smb2.recv_queue = tevent_queue_create(sconn, "smb2 recv queue");
104 if (sconn->smb2.recv_queue == NULL) {
105 return NT_STATUS_NO_MEMORY;
108 sconn->smb2.send_queue = tevent_queue_create(sconn, "smb2 send queue");
109 if (sconn->smb2.send_queue == NULL) {
110 return NT_STATUS_NO_MEMORY;
113 sconn->smb2.sessions.idtree = idr_init(sconn);
114 if (sconn->smb2.sessions.idtree == NULL) {
115 return NT_STATUS_NO_MEMORY;
117 sconn->smb2.sessions.limit = 0x0000FFFE;
118 sconn->smb2.sessions.list = NULL;
119 sconn->smb2.seqnum_low = 0;
120 sconn->smb2.credits_granted = 0;
121 sconn->smb2.max_credits = lp_smb2_max_credits();
122 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
123 DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR*sconn->smb2.max_credits);
124 if (sconn->smb2.credits_bitmap == NULL) {
125 return NT_STATUS_NO_MEMORY;
128 ret = tstream_bsd_existing_socket(sconn, sconn->sock,
129 &sconn->smb2.stream);
130 if (ret == -1) {
131 status = map_nt_error_from_unix(errno);
132 return status;
135 /* Ensure child is set to non-blocking mode */
136 set_blocking(sconn->sock, false);
137 return NT_STATUS_OK;
140 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
141 #define _smb2_setlen(_buf,len) do { \
142 uint8_t *buf = (uint8_t *)_buf; \
143 buf[0] = 0; \
144 buf[1] = ((len)&0xFF0000)>>16; \
145 buf[2] = ((len)&0xFF00)>>8; \
146 buf[3] = (len)&0xFF; \
147 } while (0)
149 static void smb2_setup_nbt_length(struct iovec *vector, int count)
151 size_t len = 0;
152 int i;
154 for (i=1; i < count; i++) {
155 len += vector[i].iov_len;
158 _smb2_setlen(vector[0].iov_base, len);
161 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request **req)
163 if (*req) {
164 (*req)->parent = NULL;
165 (*req)->mem_pool = NULL;
168 return 0;
171 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
173 if (req->parent) {
174 *req->parent = NULL;
175 talloc_free(req->mem_pool);
178 return 0;
181 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
183 TALLOC_CTX *mem_pool;
184 struct smbd_smb2_request **parent;
185 struct smbd_smb2_request *req;
187 #if 0
188 /* Enable this to find subtle valgrind errors. */
189 mem_pool = talloc_init("smbd_smb2_request_allocate");
190 #else
191 mem_pool = talloc_pool(mem_ctx, 8192);
192 #endif
193 if (mem_pool == NULL) {
194 return NULL;
197 parent = talloc(mem_pool, struct smbd_smb2_request *);
198 if (parent == NULL) {
199 talloc_free(mem_pool);
200 return NULL;
203 req = talloc_zero(parent, struct smbd_smb2_request);
204 if (req == NULL) {
205 talloc_free(mem_pool);
206 return NULL;
208 *parent = req;
209 req->mem_pool = mem_pool;
210 req->parent = parent;
212 talloc_set_destructor(parent, smbd_smb2_request_parent_destructor);
213 talloc_set_destructor(req, smbd_smb2_request_destructor);
215 return req;
218 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
219 const uint8_t *inbuf, size_t size,
220 struct smbd_smb2_request **_req)
222 struct smbd_smb2_request *req;
223 uint32_t protocol_version;
224 const uint8_t *inhdr = NULL;
225 off_t ofs = 0;
226 uint16_t cmd;
227 uint32_t next_command_ofs;
229 if (size < (4 + SMB2_HDR_BODY + 2)) {
230 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
231 return NT_STATUS_INVALID_PARAMETER;
234 inhdr = inbuf + 4;
236 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
237 if (protocol_version != SMB2_MAGIC) {
238 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
239 protocol_version));
240 return NT_STATUS_INVALID_PARAMETER;
243 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
244 if (cmd != SMB2_OP_NEGPROT) {
245 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
246 cmd));
247 return NT_STATUS_INVALID_PARAMETER;
250 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
251 if (next_command_ofs != 0) {
252 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
253 next_command_ofs));
254 return NT_STATUS_INVALID_PARAMETER;
257 req = smbd_smb2_request_allocate(sconn);
258 if (req == NULL) {
259 return NT_STATUS_NO_MEMORY;
261 req->sconn = sconn;
263 talloc_steal(req, inbuf);
265 req->in.vector = talloc_array(req, struct iovec, 4);
266 if (req->in.vector == NULL) {
267 TALLOC_FREE(req);
268 return NT_STATUS_NO_MEMORY;
270 req->in.vector_count = 4;
272 memcpy(req->in.nbt_hdr, inbuf, 4);
274 ofs = 0;
275 req->in.vector[0].iov_base = discard_const_p(void, req->in.nbt_hdr);
276 req->in.vector[0].iov_len = 4;
277 ofs += req->in.vector[0].iov_len;
279 req->in.vector[1].iov_base = discard_const_p(void, (inbuf + ofs));
280 req->in.vector[1].iov_len = SMB2_HDR_BODY;
281 ofs += req->in.vector[1].iov_len;
283 req->in.vector[2].iov_base = discard_const_p(void, (inbuf + ofs));
284 req->in.vector[2].iov_len = SVAL(inbuf, ofs) & 0xFFFE;
285 ofs += req->in.vector[2].iov_len;
287 if (ofs > size) {
288 return NT_STATUS_INVALID_PARAMETER;
291 req->in.vector[3].iov_base = discard_const_p(void, (inbuf + ofs));
292 req->in.vector[3].iov_len = size - ofs;
293 ofs += req->in.vector[3].iov_len;
295 req->current_idx = 1;
297 *_req = req;
298 return NT_STATUS_OK;
301 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
302 const uint8_t *inhdr)
304 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
305 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
306 uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
307 unsigned int bitmap_offset;
309 if (opcode == SMB2_OP_CANCEL) {
310 /* SMB2_CANCEL requests by definition resend messageids. */
311 return true;
314 if (message_id < sconn->smb2.seqnum_low ||
315 message_id > (sconn->smb2.seqnum_low +
316 (sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR))) {
317 DEBUG(0,("smb2_validate_message_id: bad message_id "
318 "%llu (low = %llu, max = %lu)\n",
319 (unsigned long long)message_id,
320 (unsigned long long)sconn->smb2.seqnum_low,
321 (unsigned long)sconn->smb2.max_credits ));
322 return false;
325 if (sconn->smb2.credits_granted == 0) {
326 DEBUG(0,("smb2_validate_message_id: client used more "
327 "credits than granted message_id (%llu)\n",
328 (unsigned long long)message_id));
329 return false;
332 /* client just used a credit. */
333 sconn->smb2.credits_granted -= 1;
335 /* Mark the message_id as seen in the bitmap. */
336 bitmap_offset = (unsigned int)(message_id %
337 (uint64_t)(sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR));
338 if (bitmap_query(credits_bm, bitmap_offset)) {
339 DEBUG(0,("smb2_validate_message_id: duplicate message_id "
340 "%llu (bm offset %u)\n",
341 (unsigned long long)message_id,
342 bitmap_offset));
343 return false;
345 bitmap_set(credits_bm, bitmap_offset);
347 if (message_id == sconn->smb2.seqnum_low + 1) {
348 /* Move the window forward by all the message_id's
349 already seen. */
350 while (bitmap_query(credits_bm, bitmap_offset)) {
351 DEBUG(10,("smb2_validate_message_id: clearing "
352 "id %llu (position %u) from bitmap\n",
353 (unsigned long long)(sconn->smb2.seqnum_low + 1),
354 bitmap_offset ));
355 bitmap_clear(credits_bm, bitmap_offset);
356 sconn->smb2.seqnum_low += 1;
357 bitmap_offset = (bitmap_offset + 1) %
358 (sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR);
362 return true;
365 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
367 int count;
368 int idx;
370 count = req->in.vector_count;
372 if (count < 4) {
373 /* It's not a SMB2 request */
374 return NT_STATUS_INVALID_PARAMETER;
377 for (idx=1; idx < count; idx += 3) {
378 const uint8_t *inhdr = NULL;
379 uint32_t flags;
381 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
382 return NT_STATUS_INVALID_PARAMETER;
385 if (req->in.vector[idx+1].iov_len < 2) {
386 return NT_STATUS_INVALID_PARAMETER;
389 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
391 /* Check the SMB2 header */
392 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
393 return NT_STATUS_INVALID_PARAMETER;
396 if (!smb2_validate_message_id(req->sconn, inhdr)) {
397 return NT_STATUS_INVALID_PARAMETER;
400 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
401 if (idx == 1) {
403 * the 1st request should never have the
404 * SMB2_HDR_FLAG_CHAINED flag set
406 if (flags & SMB2_HDR_FLAG_CHAINED) {
407 req->next_status = NT_STATUS_INVALID_PARAMETER;
408 return NT_STATUS_OK;
410 } else if (idx == 4) {
412 * the 2nd request triggers related vs. unrelated
413 * compounded requests
415 if (flags & SMB2_HDR_FLAG_CHAINED) {
416 req->compound_related = true;
418 } else if (idx > 4) {
419 #if 0
421 * It seems the this tests are wrong
422 * see the SMB2-COMPOUND test
426 * all other requests should match the 2nd one
428 if (flags & SMB2_HDR_FLAG_CHAINED) {
429 if (!req->compound_related) {
430 req->next_status =
431 NT_STATUS_INVALID_PARAMETER;
432 return NT_STATUS_OK;
434 } else {
435 if (req->compound_related) {
436 req->next_status =
437 NT_STATUS_INVALID_PARAMETER;
438 return NT_STATUS_OK;
441 #endif
445 return NT_STATUS_OK;
448 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
449 const struct iovec *in_vector,
450 struct iovec *out_vector)
452 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
453 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
454 uint16_t credits_requested;
455 uint32_t out_flags;
456 uint16_t credits_granted = 0;
458 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
459 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
461 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
463 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
465 * In case we already send an async interim
466 * response, we should not grant
467 * credits on the final response.
469 credits_requested = 0;
472 if (credits_requested) {
473 uint16_t modified_credits_requested;
474 uint32_t multiplier;
477 * Split up max_credits into 1/16ths, and then scale
478 * the requested credits by how many 16ths have been
479 * currently granted. Less than 1/16th == grant all
480 * requested (100%), scale down as more have been
481 * granted. Never ask for less than 1 as the client
482 * asked for at least 1. JRA.
485 multiplier = 16 - (((sconn->smb2.credits_granted * 16) / sconn->smb2.max_credits) % 16);
487 modified_credits_requested = (multiplier * credits_requested) / 16;
488 if (modified_credits_requested == 0) {
489 modified_credits_requested = 1;
492 /* Remember what we gave out. */
493 credits_granted = MIN(modified_credits_requested,
494 (sconn->smb2.max_credits - sconn->smb2.credits_granted));
497 if (credits_granted == 0 && sconn->smb2.credits_granted == 0) {
498 /* First negprot packet, or ensure the client credits can
499 never drop to zero. */
500 credits_granted = 1;
503 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
504 sconn->smb2.credits_granted += credits_granted;
506 DEBUG(10,("smb2_set_operation_credit: requested %u, "
507 "granted %u, total granted %u\n",
508 (unsigned int)credits_requested,
509 (unsigned int)credits_granted,
510 (unsigned int)sconn->smb2.credits_granted ));
513 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
514 struct smbd_smb2_request *outreq)
516 int count, idx;
518 count = outreq->out.vector_count;
520 for (idx=1; idx < count; idx += 3) {
521 smb2_set_operation_credit(outreq->sconn,
522 &inreq->in.vector[idx],
523 &outreq->out.vector[idx]);
527 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
529 struct iovec *vector;
530 int count;
531 int idx;
533 count = req->in.vector_count;
534 vector = talloc_zero_array(req, struct iovec, count);
535 if (vector == NULL) {
536 return NT_STATUS_NO_MEMORY;
539 vector[0].iov_base = req->out.nbt_hdr;
540 vector[0].iov_len = 4;
541 SIVAL(req->out.nbt_hdr, 0, 0);
543 for (idx=1; idx < count; idx += 3) {
544 const uint8_t *inhdr = NULL;
545 uint32_t in_flags;
546 uint8_t *outhdr = NULL;
547 uint8_t *outbody = NULL;
548 uint32_t next_command_ofs = 0;
549 struct iovec *current = &vector[idx];
551 if ((idx + 3) < count) {
552 /* we have a next command -
553 * setup for the error case. */
554 next_command_ofs = SMB2_HDR_BODY + 9;
557 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
558 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
560 outhdr = talloc_zero_array(vector, uint8_t,
561 OUTVEC_ALLOC_SIZE);
562 if (outhdr == NULL) {
563 return NT_STATUS_NO_MEMORY;
566 outbody = outhdr + SMB2_HDR_BODY;
568 current[0].iov_base = (void *)outhdr;
569 current[0].iov_len = SMB2_HDR_BODY;
571 current[1].iov_base = (void *)outbody;
572 current[1].iov_len = 8;
574 current[2].iov_base = NULL;
575 current[2].iov_len = 0;
577 /* setup the SMB2 header */
578 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
579 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
580 SSVAL(outhdr, SMB2_HDR_EPOCH, 0);
581 SIVAL(outhdr, SMB2_HDR_STATUS,
582 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
583 SSVAL(outhdr, SMB2_HDR_OPCODE,
584 SVAL(inhdr, SMB2_HDR_OPCODE));
585 SIVAL(outhdr, SMB2_HDR_FLAGS,
586 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
587 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
588 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
589 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
590 SIVAL(outhdr, SMB2_HDR_PID,
591 IVAL(inhdr, SMB2_HDR_PID));
592 SIVAL(outhdr, SMB2_HDR_TID,
593 IVAL(inhdr, SMB2_HDR_TID));
594 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
595 BVAL(inhdr, SMB2_HDR_SESSION_ID));
596 memset(outhdr + SMB2_HDR_SIGNATURE, 0, 16);
598 /* setup error body header */
599 SSVAL(outbody, 0x00, 0x08 + 1);
600 SSVAL(outbody, 0x02, 0);
601 SIVAL(outbody, 0x04, 0);
604 req->out.vector = vector;
605 req->out.vector_count = count;
607 /* setup the length of the NBT packet */
608 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
610 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
612 return NT_STATUS_OK;
615 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
616 const char *reason,
617 const char *location)
619 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
620 reason, location));
621 exit_server_cleanly(reason);
624 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
625 struct iovec *outvec,
626 const struct iovec *srcvec)
628 /* vec[0] is always boilerplate and must
629 * be allocated with size OUTVEC_ALLOC_SIZE. */
631 outvec[0].iov_base = talloc_memdup(ctx,
632 srcvec[0].iov_base,
633 OUTVEC_ALLOC_SIZE);
634 if (!outvec[0].iov_base) {
635 return false;
637 outvec[0].iov_len = SMB2_HDR_BODY;
640 * If this is a "standard" vec[1] of length 8,
641 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
642 * then duplicate this. Else use talloc_memdup().
645 if (srcvec[1].iov_len == 8 &&
646 srcvec[1].iov_base ==
647 ((uint8_t *)srcvec[0].iov_base) +
648 SMB2_HDR_BODY) {
649 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
650 SMB2_HDR_BODY;
651 outvec[1].iov_len = 8;
652 } else {
653 outvec[1].iov_base = talloc_memdup(ctx,
654 srcvec[1].iov_base,
655 srcvec[1].iov_len);
656 if (!outvec[1].iov_base) {
657 return false;
659 outvec[1].iov_len = srcvec[1].iov_len;
663 * If this is a "standard" vec[2] of length 1,
664 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
665 * then duplicate this. Else use talloc_memdup().
668 if (srcvec[2].iov_base &&
669 srcvec[2].iov_len) {
670 if (srcvec[2].iov_base ==
671 ((uint8_t *)srcvec[0].iov_base) +
672 (OUTVEC_ALLOC_SIZE - 1) &&
673 srcvec[2].iov_len == 1) {
674 /* Common SMB2 error packet case. */
675 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
676 (OUTVEC_ALLOC_SIZE - 1);
677 } else {
678 outvec[2].iov_base = talloc_memdup(ctx,
679 srcvec[2].iov_base,
680 srcvec[2].iov_len);
681 if (!outvec[2].iov_base) {
682 return false;
685 outvec[2].iov_len = srcvec[2].iov_len;
686 } else {
687 outvec[2].iov_base = NULL;
688 outvec[2].iov_len = 0;
690 return true;
693 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
695 struct smbd_smb2_request *newreq = NULL;
696 struct iovec *outvec = NULL;
697 int count = req->out.vector_count;
698 int i;
700 newreq = smbd_smb2_request_allocate(req->sconn);
701 if (!newreq) {
702 return NULL;
705 newreq->sconn = req->sconn;
706 newreq->session = req->session;
707 newreq->do_signing = req->do_signing;
708 newreq->current_idx = req->current_idx;
709 newreq->async = false;
710 newreq->cancelled = false;
711 /* Note we are leaving:
712 ->tcon
713 ->smb1req
714 ->compat_chain_fsp
715 uninitialized as NULL here as
716 they're not used in the interim
717 response code. JRA. */
719 outvec = talloc_zero_array(newreq, struct iovec, count);
720 if (!outvec) {
721 TALLOC_FREE(newreq);
722 return NULL;
724 newreq->out.vector = outvec;
725 newreq->out.vector_count = count;
727 /* Setup the outvec's identically to req. */
728 outvec[0].iov_base = newreq->out.nbt_hdr;
729 outvec[0].iov_len = 4;
730 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
732 /* Setup the vectors identically to the ones in req. */
733 for (i = 1; i < count; i += 3) {
734 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
735 break;
739 if (i < count) {
740 /* Alloc failed. */
741 TALLOC_FREE(newreq);
742 return NULL;
745 smb2_setup_nbt_length(newreq->out.vector,
746 newreq->out.vector_count);
748 return newreq;
751 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
753 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
755 int i = 0;
756 uint8_t *outhdr = NULL;
757 struct smbd_smb2_request *nreq = NULL;
759 /* Create a new smb2 request we'll use
760 for the interim return. */
761 nreq = dup_smb2_req(req);
762 if (!nreq) {
763 return NT_STATUS_NO_MEMORY;
766 /* Lose the last 3 out vectors. They're the
767 ones we'll be using for the async reply. */
768 nreq->out.vector_count -= 3;
770 smb2_setup_nbt_length(nreq->out.vector,
771 nreq->out.vector_count);
773 /* Step back to the previous reply. */
774 i = nreq->current_idx - 3;
775 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
776 /* And end the chain. */
777 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
779 /* Calculate outgoing credits */
780 smb2_calculate_credits(req, nreq);
782 /* Re-sign if needed. */
783 if (nreq->do_signing) {
784 NTSTATUS status;
785 status = smb2_signing_sign_pdu(nreq->session->session_key,
786 &nreq->out.vector[i], 3);
787 if (!NT_STATUS_IS_OK(status)) {
788 return status;
791 if (DEBUGLEVEL >= 10) {
792 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
793 (unsigned int)nreq->current_idx );
794 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
795 (unsigned int)nreq->out.vector_count );
796 print_req_vectors(nreq);
798 nreq->subreq = tstream_writev_queue_send(nreq,
799 nreq->sconn->smb2.event_ctx,
800 nreq->sconn->smb2.stream,
801 nreq->sconn->smb2.send_queue,
802 nreq->out.vector,
803 nreq->out.vector_count);
805 if (nreq->subreq == NULL) {
806 return NT_STATUS_NO_MEMORY;
809 tevent_req_set_callback(nreq->subreq,
810 smbd_smb2_request_writev_done,
811 nreq);
813 return NT_STATUS_OK;
816 struct smbd_smb2_request_pending_state {
817 struct smbd_server_connection *sconn;
818 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
819 struct iovec vector[3];
822 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
824 struct smbd_smb2_request_pending_state *state =
825 tevent_req_callback_data(subreq,
826 struct smbd_smb2_request_pending_state);
827 struct smbd_server_connection *sconn = state->sconn;
828 int ret;
829 int sys_errno;
831 ret = tstream_writev_queue_recv(subreq, &sys_errno);
832 TALLOC_FREE(subreq);
833 if (ret == -1) {
834 NTSTATUS status = map_nt_error_from_unix(sys_errno);
835 smbd_server_connection_terminate(sconn, nt_errstr(status));
836 return;
839 TALLOC_FREE(state);
842 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
843 struct tevent_req *subreq)
845 NTSTATUS status;
846 struct smbd_smb2_request_pending_state *state = NULL;
847 int i = req->current_idx;
848 uint8_t *reqhdr = NULL;
849 uint8_t *hdr = NULL;
850 uint8_t *body = NULL;
851 uint32_t flags = 0;
852 uint64_t message_id = 0;
853 uint64_t async_id = 0;
854 struct iovec *outvec = NULL;
856 if (!tevent_req_is_in_progress(subreq)) {
857 return NT_STATUS_OK;
860 req->subreq = subreq;
861 subreq = NULL;
863 if (req->async) {
864 /* We're already async. */
865 return NT_STATUS_OK;
868 if (req->in.vector_count > i + 3) {
870 * We're trying to go async in a compound
871 * request chain. This is not allowed.
872 * Cancel the outstanding request.
874 tevent_req_cancel(req->subreq);
875 return smbd_smb2_request_error(req,
876 NT_STATUS_INSUFFICIENT_RESOURCES);
879 if (DEBUGLEVEL >= 10) {
880 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
881 (unsigned int)req->current_idx );
882 print_req_vectors(req);
885 if (req->out.vector_count > 4) {
886 /* This is a compound reply. We
887 * must do an interim response
888 * followed by the async response
889 * to match W2K8R2.
891 status = smb2_send_async_interim_response(req);
892 if (!NT_STATUS_IS_OK(status)) {
893 return status;
897 * We're splitting off the last SMB2
898 * request in a compound set, and the
899 * smb2_send_async_interim_response()
900 * call above just sent all the replies
901 * for the previous SMB2 requests in
902 * this compound set. So we're no longer
903 * in the "compound_related_in_progress"
904 * state, and this is no longer a compound
905 * request.
907 req->compound_related = false;
908 req->sconn->smb2.compound_related_in_progress = false;
911 /* Don't return an intermediate packet on a pipe read/write. */
912 if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
913 goto ipc_out;
916 reqhdr = (uint8_t *)req->out.vector[i].iov_base;
917 flags = (IVAL(reqhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
918 message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
919 async_id = message_id; /* keep it simple for now... */
922 * What we send is identical to a smbd_smb2_request_error
923 * packet with an error status of STATUS_PENDING. Make use
924 * of this fact sometime when refactoring. JRA.
927 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
928 if (state == NULL) {
929 return NT_STATUS_NO_MEMORY;
931 state->sconn = req->sconn;
933 state->vector[0].iov_base = (void *)state->buf;
934 state->vector[0].iov_len = 4;
936 state->vector[1].iov_base = state->buf + 4;
937 state->vector[1].iov_len = SMB2_HDR_BODY;
939 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
940 state->vector[2].iov_len = 9;
942 smb2_setup_nbt_length(state->vector, 3);
944 hdr = (uint8_t *)state->vector[1].iov_base;
945 body = (uint8_t *)state->vector[2].iov_base;
947 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
948 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
949 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
950 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
951 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(reqhdr, SMB2_HDR_OPCODE));
953 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
954 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
955 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
956 SBVAL(hdr, SMB2_HDR_PID, async_id);
957 SBVAL(hdr, SMB2_HDR_SESSION_ID,
958 BVAL(reqhdr, SMB2_HDR_SESSION_ID));
959 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
961 SSVAL(body, 0x00, 0x08 + 1);
963 SCVAL(body, 0x02, 0);
964 SCVAL(body, 0x03, 0);
965 SIVAL(body, 0x04, 0);
966 /* Match W2K8R2... */
967 SCVAL(body, 0x08, 0x21);
969 /* Ensure we correctly go through crediting. Grant
970 the credits now, and zero credits on the final
971 response. */
972 smb2_set_operation_credit(req->sconn,
973 &req->in.vector[i],
974 &state->vector[1]);
976 if (req->do_signing) {
977 status = smb2_signing_sign_pdu(req->session->session_key,
978 &state->vector[1], 2);
979 if (!NT_STATUS_IS_OK(status)) {
980 return status;
984 subreq = tstream_writev_queue_send(state,
985 req->sconn->smb2.event_ctx,
986 req->sconn->smb2.stream,
987 req->sconn->smb2.send_queue,
988 state->vector,
991 if (subreq == NULL) {
992 return NT_STATUS_NO_MEMORY;
995 tevent_req_set_callback(subreq,
996 smbd_smb2_request_pending_writev_done,
997 state);
999 /* Note we're going async with this request. */
1000 req->async = true;
1002 ipc_out:
1005 * Now manipulate req so that the outstanding async request
1006 * is the only one left in the struct smbd_smb2_request.
1009 if (req->current_idx == 1) {
1010 /* There was only one. */
1011 goto out;
1014 /* Re-arrange the in.vectors. */
1015 req->in.vector[1] = req->in.vector[i];
1016 req->in.vector[2] = req->in.vector[i+1];
1017 req->in.vector[3] = req->in.vector[i+2];
1018 req->in.vector_count = 4;
1019 /* Reset the new in size. */
1020 smb2_setup_nbt_length(req->in.vector, 4);
1022 /* Now recreate the out.vectors. */
1023 outvec = talloc_zero_array(req, struct iovec, 4);
1024 if (!outvec) {
1025 return NT_STATUS_NO_MEMORY;
1028 /* 0 is always boilerplate and must
1029 * be of size 4 for the length field. */
1031 outvec[0].iov_base = req->out.nbt_hdr;
1032 outvec[0].iov_len = 4;
1033 SIVAL(req->out.nbt_hdr, 0, 0);
1035 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
1036 return NT_STATUS_NO_MEMORY;
1039 TALLOC_FREE(req->out.vector);
1041 req->out.vector = outvec;
1043 req->current_idx = 1;
1044 req->out.vector_count = 4;
1046 out:
1048 smb2_setup_nbt_length(req->out.vector,
1049 req->out.vector_count);
1051 if (req->async) {
1052 /* Ensure our final reply matches the interim one. */
1053 reqhdr = (uint8_t *)req->out.vector[1].iov_base;
1054 SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1055 SBVAL(reqhdr, SMB2_HDR_PID, async_id);
1058 const uint8_t *inhdr =
1059 (const uint8_t *)req->in.vector[1].iov_base;
1060 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1061 "going async\n",
1062 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1063 (unsigned long long)async_id ));
1067 return NT_STATUS_OK;
1070 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1072 struct smbd_server_connection *sconn = req->sconn;
1073 struct smbd_smb2_request *cur;
1074 const uint8_t *inhdr;
1075 int i = req->current_idx;
1076 uint32_t flags;
1077 uint64_t search_message_id;
1078 uint64_t search_async_id;
1079 uint64_t found_id;
1081 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1083 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1084 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1085 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1088 * we don't need the request anymore
1089 * cancel requests never have a response
1091 DLIST_REMOVE(req->sconn->smb2.requests, req);
1092 TALLOC_FREE(req);
1094 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1095 const uint8_t *outhdr;
1096 uint64_t message_id;
1097 uint64_t async_id;
1099 i = cur->current_idx;
1101 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1103 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1104 async_id = BVAL(outhdr, SMB2_HDR_PID);
1106 if (flags & SMB2_HDR_FLAG_ASYNC) {
1107 if (search_async_id == async_id) {
1108 found_id = async_id;
1109 break;
1111 } else {
1112 if (search_message_id == message_id) {
1113 found_id = message_id;
1114 break;
1119 if (cur && cur->subreq) {
1120 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1121 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1122 "cancel opcode[%s] mid %llu\n",
1123 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1124 (unsigned long long)found_id ));
1125 tevent_req_cancel(cur->subreq);
1128 return NT_STATUS_OK;
1131 /*************************************************************
1132 Ensure an incoming tid is a valid one for us to access.
1133 Change to the associated uid credentials and chdir to the
1134 valid tid directory.
1135 *************************************************************/
1137 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1139 const uint8_t *inhdr;
1140 const uint8_t *outhdr;
1141 int i = req->current_idx;
1142 uint32_t in_tid;
1143 void *p;
1144 struct smbd_smb2_tcon *tcon;
1145 bool chained_fixup = false;
1147 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1149 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1151 if (in_tid == (0xFFFFFFFF)) {
1152 if (req->async) {
1154 * async request - fill in tid from
1155 * already setup out.vector[].iov_base.
1157 outhdr = (const uint8_t *)req->out.vector[i].iov_base;
1158 in_tid = IVAL(outhdr, SMB2_HDR_TID);
1159 } else if (i > 2) {
1161 * Chained request - fill in tid from
1162 * the previous request out.vector[].iov_base.
1164 outhdr = (const uint8_t *)req->out.vector[i-3].iov_base;
1165 in_tid = IVAL(outhdr, SMB2_HDR_TID);
1166 chained_fixup = true;
1170 /* lookup an existing session */
1171 p = idr_find(req->session->tcons.idtree, in_tid);
1172 if (p == NULL) {
1173 return NT_STATUS_NETWORK_NAME_DELETED;
1175 tcon = talloc_get_type_abort(p, struct smbd_smb2_tcon);
1177 if (!change_to_user(tcon->compat_conn,req->session->vuid)) {
1178 return NT_STATUS_ACCESS_DENIED;
1181 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1182 if (!set_current_service(tcon->compat_conn, 0, true)) {
1183 return NT_STATUS_ACCESS_DENIED;
1186 req->tcon = tcon;
1188 if (chained_fixup) {
1189 /* Fix up our own outhdr. */
1190 outhdr = (const uint8_t *)req->out.vector[i].iov_base;
1191 SIVAL(discard_const_p(uint8_t, outhdr), SMB2_HDR_TID, in_tid);
1194 return NT_STATUS_OK;
1197 /*************************************************************
1198 Ensure an incoming session_id is a valid one for us to access.
1199 *************************************************************/
1201 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1203 const uint8_t *inhdr;
1204 const uint8_t *outhdr;
1205 int i = req->current_idx;
1206 uint64_t in_session_id;
1207 void *p;
1208 struct smbd_smb2_session *session;
1209 bool chained_fixup = false;
1211 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1213 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1215 if (in_session_id == (0xFFFFFFFFFFFFFFFFLL)) {
1216 if (req->async) {
1218 * async request - fill in session_id from
1219 * already setup request out.vector[].iov_base.
1221 outhdr = (const uint8_t *)req->out.vector[i].iov_base;
1222 in_session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1223 } else if (i > 2) {
1225 * Chained request - fill in session_id from
1226 * the previous request out.vector[].iov_base.
1228 outhdr = (const uint8_t *)req->out.vector[i-3].iov_base;
1229 in_session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1230 chained_fixup = true;
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;
1251 if (chained_fixup) {
1252 /* Fix up our own outhdr. */
1253 outhdr = (const uint8_t *)req->out.vector[i].iov_base;
1254 SBVAL(discard_const_p(uint8_t, outhdr), SMB2_HDR_SESSION_ID, in_session_id);
1256 return NT_STATUS_OK;
1259 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1260 size_t expected_body_size)
1262 const uint8_t *inhdr;
1263 uint16_t opcode;
1264 const uint8_t *inbody;
1265 int i = req->current_idx;
1266 size_t body_size;
1267 size_t min_dyn_size = expected_body_size & 0x00000001;
1270 * The following should be checked already.
1272 if ((i+2) > req->in.vector_count) {
1273 return NT_STATUS_INTERNAL_ERROR;
1275 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1276 return NT_STATUS_INTERNAL_ERROR;
1278 if (req->in.vector[i+1].iov_len < 2) {
1279 return NT_STATUS_INTERNAL_ERROR;
1282 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1283 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1285 switch (opcode) {
1286 case SMB2_OP_IOCTL:
1287 case SMB2_OP_GETINFO:
1288 min_dyn_size = 0;
1289 break;
1293 * Now check the expected body size,
1294 * where the last byte might be in the
1295 * dynnamic section..
1297 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1298 return NT_STATUS_INVALID_PARAMETER;
1300 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1301 return NT_STATUS_INVALID_PARAMETER;
1304 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1306 body_size = SVAL(inbody, 0x00);
1307 if (body_size != expected_body_size) {
1308 return NT_STATUS_INVALID_PARAMETER;
1311 return NT_STATUS_OK;
1314 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1316 const uint8_t *inhdr;
1317 int i = req->current_idx;
1318 uint16_t opcode;
1319 uint32_t flags;
1320 uint64_t mid;
1321 NTSTATUS status;
1322 NTSTATUS session_status;
1323 uint32_t allowed_flags;
1324 NTSTATUS return_value;
1326 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1328 /* TODO: verify more things */
1330 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1331 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1332 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1333 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1334 smb2_opcode_name(opcode),
1335 (unsigned long long)mid));
1337 if (get_Protocol() >= PROTOCOL_SMB2_02) {
1339 * once the protocol is negotiated
1340 * SMB2_OP_NEGPROT is not allowed anymore
1342 if (opcode == SMB2_OP_NEGPROT) {
1343 /* drop the connection */
1344 return NT_STATUS_INVALID_PARAMETER;
1346 } else {
1348 * if the protocol is not negotiated yet
1349 * only SMB2_OP_NEGPROT is allowed.
1351 if (opcode != SMB2_OP_NEGPROT) {
1352 /* drop the connection */
1353 return NT_STATUS_INVALID_PARAMETER;
1357 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1358 SMB2_HDR_FLAG_SIGNED |
1359 SMB2_HDR_FLAG_DFS;
1360 if (opcode == SMB2_OP_CANCEL) {
1361 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1363 if ((flags & ~allowed_flags) != 0) {
1364 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1368 * Check if the client provided a valid session id,
1369 * if so smbd_smb2_request_check_session() calls
1370 * set_current_user_info().
1372 * As some command don't require a valid session id
1373 * we defer the check of the session_status
1375 session_status = smbd_smb2_request_check_session(req);
1377 req->do_signing = false;
1378 if (flags & SMB2_HDR_FLAG_SIGNED) {
1379 if (!NT_STATUS_IS_OK(session_status)) {
1380 return smbd_smb2_request_error(req, session_status);
1383 req->do_signing = true;
1384 status = smb2_signing_check_pdu(req->session->session_key,
1385 &req->in.vector[i], 3);
1386 if (!NT_STATUS_IS_OK(status)) {
1387 return smbd_smb2_request_error(req, status);
1389 } else if (opcode == SMB2_OP_CANCEL) {
1390 /* Cancel requests are allowed to skip the signing */
1391 } else if (req->session && req->session->do_signing) {
1392 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1395 if (flags & SMB2_HDR_FLAG_CHAINED) {
1397 * This check is mostly for giving the correct error code
1398 * for compounded requests.
1400 * TODO: we may need to move this after the session
1401 * and tcon checks.
1403 if (!NT_STATUS_IS_OK(req->next_status)) {
1404 return smbd_smb2_request_error(req, req->next_status);
1406 } else {
1407 req->compat_chain_fsp = NULL;
1410 if (req->compound_related) {
1411 req->sconn->smb2.compound_related_in_progress = true;
1414 switch (opcode) {
1415 case SMB2_OP_NEGPROT:
1416 /* This call needs to be run as root */
1417 change_to_root_user();
1420 START_PROFILE(smb2_negprot);
1421 return_value = smbd_smb2_request_process_negprot(req);
1422 END_PROFILE(smb2_negprot);
1424 break;
1426 case SMB2_OP_SESSSETUP:
1427 /* This call needs to be run as root */
1428 change_to_root_user();
1431 START_PROFILE(smb2_sesssetup);
1432 return_value = smbd_smb2_request_process_sesssetup(req);
1433 END_PROFILE(smb2_sesssetup);
1435 break;
1437 case SMB2_OP_LOGOFF:
1438 if (!NT_STATUS_IS_OK(session_status)) {
1439 return_value = smbd_smb2_request_error(req, session_status);
1440 break;
1443 /* This call needs to be run as root */
1444 change_to_root_user();
1447 START_PROFILE(smb2_logoff);
1448 return_value = smbd_smb2_request_process_logoff(req);
1449 END_PROFILE(smb2_logoff);
1451 break;
1453 case SMB2_OP_TCON:
1454 if (!NT_STATUS_IS_OK(session_status)) {
1455 return_value = smbd_smb2_request_error(req, session_status);
1456 break;
1460 * This call needs to be run as root.
1462 * smbd_smb2_request_process_tcon()
1463 * calls make_connection_snum(), which will call
1464 * change_to_user(), when needed.
1466 change_to_root_user();
1469 START_PROFILE(smb2_tcon);
1470 return_value = smbd_smb2_request_process_tcon(req);
1471 END_PROFILE(smb2_tcon);
1473 break;
1475 case SMB2_OP_TDIS:
1476 if (!NT_STATUS_IS_OK(session_status)) {
1477 return_value = smbd_smb2_request_error(req, session_status);
1478 break;
1481 * This call needs to be run as user.
1483 * smbd_smb2_request_check_tcon()
1484 * calls change_to_user() on success.
1486 status = smbd_smb2_request_check_tcon(req);
1487 if (!NT_STATUS_IS_OK(status)) {
1488 return_value = smbd_smb2_request_error(req, status);
1489 break;
1491 /* This call needs to be run as root */
1492 change_to_root_user();
1496 START_PROFILE(smb2_tdis);
1497 return_value = smbd_smb2_request_process_tdis(req);
1498 END_PROFILE(smb2_tdis);
1500 break;
1502 case SMB2_OP_CREATE:
1503 if (!NT_STATUS_IS_OK(session_status)) {
1504 return_value = smbd_smb2_request_error(req, session_status);
1505 break;
1508 * This call needs to be run as user.
1510 * smbd_smb2_request_check_tcon()
1511 * calls change_to_user() on success.
1513 status = smbd_smb2_request_check_tcon(req);
1514 if (!NT_STATUS_IS_OK(status)) {
1515 return_value = smbd_smb2_request_error(req, status);
1516 break;
1520 START_PROFILE(smb2_create);
1521 return_value = smbd_smb2_request_process_create(req);
1522 END_PROFILE(smb2_create);
1524 break;
1526 case SMB2_OP_CLOSE:
1527 if (!NT_STATUS_IS_OK(session_status)) {
1528 return_value = smbd_smb2_request_error(req, session_status);
1529 break;
1532 * This call needs to be run as user.
1534 * smbd_smb2_request_check_tcon()
1535 * calls change_to_user() on success.
1537 status = smbd_smb2_request_check_tcon(req);
1538 if (!NT_STATUS_IS_OK(status)) {
1539 return_value = smbd_smb2_request_error(req, status);
1540 break;
1544 START_PROFILE(smb2_close);
1545 return_value = smbd_smb2_request_process_close(req);
1546 END_PROFILE(smb2_close);
1548 break;
1550 case SMB2_OP_FLUSH:
1551 if (!NT_STATUS_IS_OK(session_status)) {
1552 return_value = smbd_smb2_request_error(req, session_status);
1553 break;
1556 * This call needs to be run as user.
1558 * smbd_smb2_request_check_tcon()
1559 * calls change_to_user() on success.
1561 status = smbd_smb2_request_check_tcon(req);
1562 if (!NT_STATUS_IS_OK(status)) {
1563 return_value = smbd_smb2_request_error(req, status);
1564 break;
1568 START_PROFILE(smb2_flush);
1569 return_value = smbd_smb2_request_process_flush(req);
1570 END_PROFILE(smb2_flush);
1572 break;
1574 case SMB2_OP_READ:
1575 if (!NT_STATUS_IS_OK(session_status)) {
1576 return_value = smbd_smb2_request_error(req, session_status);
1577 break;
1580 * This call needs to be run as user.
1582 * smbd_smb2_request_check_tcon()
1583 * calls change_to_user() on success.
1585 status = smbd_smb2_request_check_tcon(req);
1586 if (!NT_STATUS_IS_OK(status)) {
1587 return_value = smbd_smb2_request_error(req, status);
1588 break;
1592 START_PROFILE(smb2_read);
1593 return_value = smbd_smb2_request_process_read(req);
1594 END_PROFILE(smb2_read);
1596 break;
1598 case SMB2_OP_WRITE:
1599 if (!NT_STATUS_IS_OK(session_status)) {
1600 return_value = smbd_smb2_request_error(req, session_status);
1601 break;
1604 * This call needs to be run as user.
1606 * smbd_smb2_request_check_tcon()
1607 * calls change_to_user() on success.
1609 status = smbd_smb2_request_check_tcon(req);
1610 if (!NT_STATUS_IS_OK(status)) {
1611 return_value = smbd_smb2_request_error(req, status);
1612 break;
1616 START_PROFILE(smb2_write);
1617 return_value = smbd_smb2_request_process_write(req);
1618 END_PROFILE(smb2_write);
1620 break;
1622 case SMB2_OP_LOCK:
1623 if (!NT_STATUS_IS_OK(session_status)) {
1624 /* Too ugly to live ? JRA. */
1625 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1626 session_status = NT_STATUS_FILE_CLOSED;
1628 return_value = smbd_smb2_request_error(req, session_status);
1629 break;
1632 * This call needs to be run as user.
1634 * smbd_smb2_request_check_tcon()
1635 * calls change_to_user() on success.
1637 status = smbd_smb2_request_check_tcon(req);
1638 if (!NT_STATUS_IS_OK(status)) {
1639 /* Too ugly to live ? JRA. */
1640 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1641 status = NT_STATUS_FILE_CLOSED;
1643 return_value = smbd_smb2_request_error(req, status);
1644 break;
1648 START_PROFILE(smb2_lock);
1649 return_value = smbd_smb2_request_process_lock(req);
1650 END_PROFILE(smb2_lock);
1652 break;
1654 case SMB2_OP_IOCTL:
1655 if (!NT_STATUS_IS_OK(session_status)) {
1656 return_value = smbd_smb2_request_error(req, session_status);
1657 break;
1660 * This call needs to be run as user.
1662 * smbd_smb2_request_check_tcon()
1663 * calls change_to_user() on success.
1665 status = smbd_smb2_request_check_tcon(req);
1666 if (!NT_STATUS_IS_OK(status)) {
1667 return_value = smbd_smb2_request_error(req, status);
1668 break;
1672 START_PROFILE(smb2_ioctl);
1673 return_value = smbd_smb2_request_process_ioctl(req);
1674 END_PROFILE(smb2_ioctl);
1676 break;
1678 case SMB2_OP_CANCEL:
1680 * This call needs to be run as root
1682 * That is what we also do in the SMB1 case.
1684 change_to_root_user();
1687 START_PROFILE(smb2_cancel);
1688 return_value = smbd_smb2_request_process_cancel(req);
1689 END_PROFILE(smb2_cancel);
1691 break;
1693 case SMB2_OP_KEEPALIVE:
1694 /* This call needs to be run as root */
1695 change_to_root_user();
1698 START_PROFILE(smb2_keepalive);
1699 return_value = smbd_smb2_request_process_keepalive(req);
1700 END_PROFILE(smb2_keepalive);
1702 break;
1704 case SMB2_OP_FIND:
1705 if (!NT_STATUS_IS_OK(session_status)) {
1706 return_value = smbd_smb2_request_error(req, session_status);
1707 break;
1710 * This call needs to be run as user.
1712 * smbd_smb2_request_check_tcon()
1713 * calls change_to_user() on success.
1715 status = smbd_smb2_request_check_tcon(req);
1716 if (!NT_STATUS_IS_OK(status)) {
1717 return_value = smbd_smb2_request_error(req, status);
1718 break;
1722 START_PROFILE(smb2_find);
1723 return_value = smbd_smb2_request_process_find(req);
1724 END_PROFILE(smb2_find);
1726 break;
1728 case SMB2_OP_NOTIFY:
1729 if (!NT_STATUS_IS_OK(session_status)) {
1730 return_value = smbd_smb2_request_error(req, session_status);
1731 break;
1734 * This call needs to be run as user.
1736 * smbd_smb2_request_check_tcon()
1737 * calls change_to_user() on success.
1739 status = smbd_smb2_request_check_tcon(req);
1740 if (!NT_STATUS_IS_OK(status)) {
1741 return_value = smbd_smb2_request_error(req, status);
1742 break;
1746 START_PROFILE(smb2_notify);
1747 return_value = smbd_smb2_request_process_notify(req);
1748 END_PROFILE(smb2_notify);
1750 break;
1752 case SMB2_OP_GETINFO:
1753 if (!NT_STATUS_IS_OK(session_status)) {
1754 return_value = smbd_smb2_request_error(req, session_status);
1755 break;
1758 * This call needs to be run as user.
1760 * smbd_smb2_request_check_tcon()
1761 * calls change_to_user() on success.
1763 status = smbd_smb2_request_check_tcon(req);
1764 if (!NT_STATUS_IS_OK(status)) {
1765 return_value = smbd_smb2_request_error(req, status);
1766 break;
1770 START_PROFILE(smb2_getinfo);
1771 return_value = smbd_smb2_request_process_getinfo(req);
1772 END_PROFILE(smb2_getinfo);
1774 break;
1776 case SMB2_OP_SETINFO:
1777 if (!NT_STATUS_IS_OK(session_status)) {
1778 return_value = smbd_smb2_request_error(req, session_status);
1779 break;
1782 * This call needs to be run as user.
1784 * smbd_smb2_request_check_tcon()
1785 * calls change_to_user() on success.
1787 status = smbd_smb2_request_check_tcon(req);
1788 if (!NT_STATUS_IS_OK(status)) {
1789 return_value = smbd_smb2_request_error(req, status);
1790 break;
1794 START_PROFILE(smb2_setinfo);
1795 return_value = smbd_smb2_request_process_setinfo(req);
1796 END_PROFILE(smb2_setinfo);
1798 break;
1800 case SMB2_OP_BREAK:
1801 if (!NT_STATUS_IS_OK(session_status)) {
1802 return_value = smbd_smb2_request_error(req, session_status);
1803 break;
1806 * This call needs to be run as user.
1808 * smbd_smb2_request_check_tcon()
1809 * calls change_to_user() on success.
1811 status = smbd_smb2_request_check_tcon(req);
1812 if (!NT_STATUS_IS_OK(status)) {
1813 return_value = smbd_smb2_request_error(req, status);
1814 break;
1818 START_PROFILE(smb2_break);
1819 return_value = smbd_smb2_request_process_break(req);
1820 END_PROFILE(smb2_break);
1822 break;
1824 default:
1825 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1826 break;
1828 return return_value;
1831 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1833 struct tevent_req *subreq;
1834 int i = req->current_idx;
1836 req->subreq = NULL;
1838 req->current_idx += 3;
1840 if (req->current_idx < req->out.vector_count) {
1842 * We must process the remaining compound
1843 * SMB2 requests before any new incoming SMB2
1844 * requests. This is because incoming SMB2
1845 * requests may include a cancel for a
1846 * compound request we haven't processed
1847 * yet.
1849 struct tevent_immediate *im = tevent_create_immediate(req);
1850 if (!im) {
1851 return NT_STATUS_NO_MEMORY;
1853 tevent_schedule_immediate(im,
1854 req->sconn->smb2.event_ctx,
1855 smbd_smb2_request_dispatch_immediate,
1856 req);
1857 return NT_STATUS_OK;
1860 if (req->compound_related) {
1861 req->sconn->smb2.compound_related_in_progress = false;
1864 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1866 /* Set credit for this operation (zero credits if this
1867 is a final reply for an async operation). */
1868 smb2_set_operation_credit(req->sconn,
1869 &req->in.vector[i],
1870 &req->out.vector[i]);
1872 if (req->do_signing) {
1873 NTSTATUS status;
1874 status = smb2_signing_sign_pdu(req->session->session_key,
1875 &req->out.vector[i], 3);
1876 if (!NT_STATUS_IS_OK(status)) {
1877 return status;
1881 if (DEBUGLEVEL >= 10) {
1882 dbgtext("smbd_smb2_request_reply: sending...\n");
1883 print_req_vectors(req);
1886 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1887 if (req->out.vector_count == 4 &&
1888 req->out.vector[3].iov_base == NULL &&
1889 req->out.vector[3].iov_len != 0) {
1890 /* Dynamic part is NULL. Chop it off,
1891 We're going to send it via sendfile. */
1892 req->out.vector_count -= 1;
1895 subreq = tstream_writev_queue_send(req,
1896 req->sconn->smb2.event_ctx,
1897 req->sconn->smb2.stream,
1898 req->sconn->smb2.send_queue,
1899 req->out.vector,
1900 req->out.vector_count);
1901 if (subreq == NULL) {
1902 return NT_STATUS_NO_MEMORY;
1904 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1906 * We're done with this request -
1907 * move it off the "being processed" queue.
1909 DLIST_REMOVE(req->sconn->smb2.requests, req);
1911 return NT_STATUS_OK;
1914 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
1916 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1917 struct tevent_immediate *im,
1918 void *private_data)
1920 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1921 struct smbd_smb2_request);
1922 struct smbd_server_connection *sconn = req->sconn;
1923 NTSTATUS status;
1925 TALLOC_FREE(im);
1927 if (DEBUGLEVEL >= 10) {
1928 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1929 req->current_idx, req->in.vector_count));
1930 print_req_vectors(req);
1933 status = smbd_smb2_request_dispatch(req);
1934 if (!NT_STATUS_IS_OK(status)) {
1935 smbd_server_connection_terminate(sconn, nt_errstr(status));
1936 return;
1939 status = smbd_smb2_request_next_incoming(sconn);
1940 if (!NT_STATUS_IS_OK(status)) {
1941 smbd_server_connection_terminate(sconn, nt_errstr(status));
1942 return;
1946 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1948 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1949 struct smbd_smb2_request);
1950 struct smbd_server_connection *sconn = req->sconn;
1951 int ret;
1952 int sys_errno;
1953 NTSTATUS status;
1955 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1956 TALLOC_FREE(subreq);
1957 TALLOC_FREE(req);
1958 if (ret == -1) {
1959 status = map_nt_error_from_unix(sys_errno);
1960 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1961 nt_errstr(status)));
1962 smbd_server_connection_terminate(sconn, nt_errstr(status));
1963 return;
1966 status = smbd_smb2_request_next_incoming(sconn);
1967 if (!NT_STATUS_IS_OK(status)) {
1968 smbd_server_connection_terminate(sconn, nt_errstr(status));
1969 return;
1973 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1974 NTSTATUS status,
1975 DATA_BLOB body, DATA_BLOB *dyn,
1976 const char *location)
1978 uint8_t *outhdr;
1979 int i = req->current_idx;
1980 uint32_t next_command_ofs;
1982 DEBUG(10,("smbd_smb2_request_done_ex: "
1983 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1984 i, nt_errstr(status), (unsigned int)body.length,
1985 dyn ? "yes": "no",
1986 (unsigned int)(dyn ? dyn->length : 0),
1987 location));
1989 if (body.length < 2) {
1990 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1993 if ((body.length % 2) != 0) {
1994 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1997 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1999 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2000 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2002 req->out.vector[i+1].iov_base = (void *)body.data;
2003 req->out.vector[i+1].iov_len = body.length;
2005 if (dyn) {
2006 req->out.vector[i+2].iov_base = (void *)dyn->data;
2007 req->out.vector[i+2].iov_len = dyn->length;
2008 } else {
2009 req->out.vector[i+2].iov_base = NULL;
2010 req->out.vector[i+2].iov_len = 0;
2013 /* see if we need to recalculate the offset to the next response */
2014 if (next_command_ofs > 0) {
2015 next_command_ofs = SMB2_HDR_BODY;
2016 next_command_ofs += req->out.vector[i+1].iov_len;
2017 next_command_ofs += req->out.vector[i+2].iov_len;
2020 if ((next_command_ofs % 8) != 0) {
2021 size_t pad_size = 8 - (next_command_ofs % 8);
2022 if (req->out.vector[i+2].iov_len == 0) {
2024 * if the dyn buffer is empty
2025 * we can use it to add padding
2027 uint8_t *pad;
2029 pad = talloc_zero_array(req->out.vector,
2030 uint8_t, pad_size);
2031 if (pad == NULL) {
2032 return smbd_smb2_request_error(req,
2033 NT_STATUS_NO_MEMORY);
2036 req->out.vector[i+2].iov_base = (void *)pad;
2037 req->out.vector[i+2].iov_len = pad_size;
2038 } else {
2040 * For now we copy the dynamic buffer
2041 * and add the padding to the new buffer
2043 size_t old_size;
2044 uint8_t *old_dyn;
2045 size_t new_size;
2046 uint8_t *new_dyn;
2048 old_size = req->out.vector[i+2].iov_len;
2049 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2051 new_size = old_size + pad_size;
2052 new_dyn = talloc_zero_array(req->out.vector,
2053 uint8_t, new_size);
2054 if (new_dyn == NULL) {
2055 return smbd_smb2_request_error(req,
2056 NT_STATUS_NO_MEMORY);
2059 memcpy(new_dyn, old_dyn, old_size);
2060 memset(new_dyn + old_size, 0, pad_size);
2062 req->out.vector[i+2].iov_base = (void *)new_dyn;
2063 req->out.vector[i+2].iov_len = new_size;
2065 next_command_ofs += pad_size;
2068 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2070 return smbd_smb2_request_reply(req);
2073 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2074 NTSTATUS status,
2075 DATA_BLOB *info,
2076 const char *location)
2078 DATA_BLOB body;
2079 int i = req->current_idx;
2080 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
2082 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2083 i, nt_errstr(status), info ? " +info" : "",
2084 location));
2086 body.data = outhdr + SMB2_HDR_BODY;
2087 body.length = 8;
2088 SSVAL(body.data, 0, 9);
2090 if (info) {
2091 SIVAL(body.data, 0x04, info->length);
2092 } else {
2093 /* Allocated size of req->out.vector[i].iov_base
2094 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2095 * 1 byte without having to do an alloc.
2097 info = talloc_zero_array(req->out.vector,
2098 DATA_BLOB,
2100 if (!info) {
2101 return NT_STATUS_NO_MEMORY;
2103 info->data = ((uint8_t *)outhdr) +
2104 OUTVEC_ALLOC_SIZE - 1;
2105 info->length = 1;
2106 SCVAL(info->data, 0, 0);
2110 * if a request fails, all other remaining
2111 * compounded requests should fail too
2113 req->next_status = NT_STATUS_INVALID_PARAMETER;
2115 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2119 struct smbd_smb2_send_oplock_break_state {
2120 struct smbd_server_connection *sconn;
2121 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2122 struct iovec vector;
2125 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2127 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2128 uint64_t file_id_persistent,
2129 uint64_t file_id_volatile,
2130 uint8_t oplock_level)
2132 struct smbd_smb2_send_oplock_break_state *state;
2133 struct tevent_req *subreq;
2134 uint8_t *hdr;
2135 uint8_t *body;
2137 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2138 if (state == NULL) {
2139 return NT_STATUS_NO_MEMORY;
2141 state->sconn = sconn;
2143 state->vector.iov_base = (void *)state->buf;
2144 state->vector.iov_len = sizeof(state->buf);
2146 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2147 hdr = state->buf + 4;
2148 body = hdr + SMB2_HDR_BODY;
2150 SIVAL(hdr, 0, SMB2_MAGIC);
2151 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2152 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2153 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2154 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2155 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2156 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2157 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2158 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2159 SIVAL(hdr, SMB2_HDR_PID, 0);
2160 SIVAL(hdr, SMB2_HDR_TID, 0);
2161 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2162 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2164 SSVAL(body, 0x00, 0x18);
2166 SCVAL(body, 0x02, oplock_level);
2167 SCVAL(body, 0x03, 0); /* reserved */
2168 SIVAL(body, 0x04, 0); /* reserved */
2169 SBVAL(body, 0x08, file_id_persistent);
2170 SBVAL(body, 0x10, file_id_volatile);
2172 subreq = tstream_writev_queue_send(state,
2173 sconn->smb2.event_ctx,
2174 sconn->smb2.stream,
2175 sconn->smb2.send_queue,
2176 &state->vector, 1);
2177 if (subreq == NULL) {
2178 return NT_STATUS_NO_MEMORY;
2180 tevent_req_set_callback(subreq,
2181 smbd_smb2_oplock_break_writev_done,
2182 state);
2184 return NT_STATUS_OK;
2187 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2189 struct smbd_smb2_send_oplock_break_state *state =
2190 tevent_req_callback_data(subreq,
2191 struct smbd_smb2_send_oplock_break_state);
2192 struct smbd_server_connection *sconn = state->sconn;
2193 int ret;
2194 int sys_errno;
2196 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2197 TALLOC_FREE(subreq);
2198 if (ret == -1) {
2199 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2200 smbd_server_connection_terminate(sconn, nt_errstr(status));
2201 return;
2204 TALLOC_FREE(state);
2207 struct smbd_smb2_request_read_state {
2208 size_t missing;
2209 bool asked_for_header;
2210 struct smbd_smb2_request *smb2_req;
2213 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2214 void *private_data,
2215 TALLOC_CTX *mem_ctx,
2216 struct iovec **_vector,
2217 size_t *_count);
2218 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2220 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2221 struct tevent_context *ev,
2222 struct smbd_server_connection *sconn)
2224 struct tevent_req *req;
2225 struct smbd_smb2_request_read_state *state;
2226 struct tevent_req *subreq;
2228 req = tevent_req_create(mem_ctx, &state,
2229 struct smbd_smb2_request_read_state);
2230 if (req == NULL) {
2231 return NULL;
2233 state->missing = 0;
2234 state->asked_for_header = false;
2236 state->smb2_req = smbd_smb2_request_allocate(state);
2237 if (tevent_req_nomem(state->smb2_req, req)) {
2238 return tevent_req_post(req, ev);
2240 state->smb2_req->sconn = sconn;
2242 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2243 sconn->smb2.recv_queue,
2244 smbd_smb2_request_next_vector,
2245 state);
2246 if (tevent_req_nomem(subreq, req)) {
2247 return tevent_req_post(req, ev);
2249 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2251 return req;
2254 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2255 void *private_data,
2256 TALLOC_CTX *mem_ctx,
2257 struct iovec **_vector,
2258 size_t *_count)
2260 struct smbd_smb2_request_read_state *state =
2261 talloc_get_type_abort(private_data,
2262 struct smbd_smb2_request_read_state);
2263 struct smbd_smb2_request *req = state->smb2_req;
2264 struct iovec *vector;
2265 int idx = req->in.vector_count;
2266 size_t len = 0;
2267 uint8_t *buf = NULL;
2269 if (req->in.vector_count == 0) {
2271 * first we need to get the NBT header
2273 req->in.vector = talloc_array(req, struct iovec,
2274 req->in.vector_count + 1);
2275 if (req->in.vector == NULL) {
2276 return -1;
2278 req->in.vector_count += 1;
2280 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2281 req->in.vector[idx].iov_len = 4;
2283 vector = talloc_array(mem_ctx, struct iovec, 1);
2284 if (vector == NULL) {
2285 return -1;
2288 vector[0] = req->in.vector[idx];
2290 *_vector = vector;
2291 *_count = 1;
2292 return 0;
2295 if (req->in.vector_count == 1) {
2297 * Now we analyze the NBT header
2299 state->missing = smb2_len(req->in.vector[0].iov_base);
2301 if (state->missing == 0) {
2302 /* if there're no remaining bytes, we're done */
2303 *_vector = NULL;
2304 *_count = 0;
2305 return 0;
2308 req->in.vector = talloc_realloc(req, req->in.vector,
2309 struct iovec,
2310 req->in.vector_count + 1);
2311 if (req->in.vector == NULL) {
2312 return -1;
2314 req->in.vector_count += 1;
2316 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2318 * it's a special NBT message,
2319 * so get all remaining bytes
2321 len = state->missing;
2322 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2324 * it's an invalid message, just read what we can get
2325 * and let the caller handle the error
2327 len = state->missing;
2328 } else {
2330 * We assume it's a SMB2 request,
2331 * and we first get the header and the
2332 * first 2 bytes (the struct size) of the body
2334 len = SMB2_HDR_BODY + 2;
2336 state->asked_for_header = true;
2339 state->missing -= len;
2341 buf = talloc_array(req->in.vector, uint8_t, len);
2342 if (buf == NULL) {
2343 return -1;
2346 req->in.vector[idx].iov_base = (void *)buf;
2347 req->in.vector[idx].iov_len = len;
2349 vector = talloc_array(mem_ctx, struct iovec, 1);
2350 if (vector == NULL) {
2351 return -1;
2354 vector[0] = req->in.vector[idx];
2356 *_vector = vector;
2357 *_count = 1;
2358 return 0;
2361 if (state->missing == 0) {
2362 /* if there're no remaining bytes, we're done */
2363 *_vector = NULL;
2364 *_count = 0;
2365 return 0;
2368 if (state->asked_for_header) {
2369 const uint8_t *hdr;
2370 size_t full_size;
2371 size_t next_command_ofs;
2372 size_t body_size;
2373 uint8_t *body;
2374 size_t dyn_size;
2375 uint8_t *dyn;
2376 bool invalid = false;
2378 state->asked_for_header = false;
2381 * We got the SMB2 header and the first 2 bytes
2382 * of the body. We fix the size to just the header
2383 * and manually copy the 2 first bytes to the body section
2385 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2386 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2388 /* allocate vectors for body and dynamic areas */
2389 req->in.vector = talloc_realloc(req, req->in.vector,
2390 struct iovec,
2391 req->in.vector_count + 2);
2392 if (req->in.vector == NULL) {
2393 return -1;
2395 req->in.vector_count += 2;
2397 full_size = state->missing + SMB2_HDR_BODY + 2;
2398 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2399 body_size = SVAL(hdr, SMB2_HDR_BODY);
2401 if (next_command_ofs != 0) {
2402 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2404 * this is invalid, just return a zero
2405 * body and let the caller deal with the error
2407 invalid = true;
2408 } else if (next_command_ofs > full_size) {
2410 * this is invalid, just return a zero
2411 * body and let the caller deal with the error
2413 invalid = true;
2414 } else {
2415 full_size = next_command_ofs;
2419 if (!invalid) {
2420 if (body_size < 2) {
2422 * this is invalid, just return a zero
2423 * body and let the caller deal with the error
2425 invalid = true;
2429 * Mask out the lowest bit, the "dynamic" part
2430 * of body_size.
2432 body_size &= ~1;
2434 if (body_size > (full_size - SMB2_HDR_BODY)) {
2436 * this is invalid, just return a zero
2437 * body and let the caller deal with the error
2439 invalid = true;
2443 if (invalid) {
2444 /* the caller should check this */
2445 body_size = 2;
2448 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2450 state->missing -= (body_size - 2) + dyn_size;
2452 body = talloc_array(req->in.vector, uint8_t, body_size);
2453 if (body == NULL) {
2454 return -1;
2457 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2458 if (dyn == NULL) {
2459 return -1;
2462 req->in.vector[idx].iov_base = (void *)body;
2463 req->in.vector[idx].iov_len = body_size;
2464 req->in.vector[idx+1].iov_base = (void *)dyn;
2465 req->in.vector[idx+1].iov_len = dyn_size;
2467 vector = talloc_array(mem_ctx, struct iovec, 2);
2468 if (vector == NULL) {
2469 return -1;
2473 * the first 2 bytes of the body were already fetched
2474 * together with the header
2476 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2477 vector[0].iov_base = body + 2;
2478 vector[0].iov_len = body_size - 2;
2480 vector[1] = req->in.vector[idx+1];
2482 *_vector = vector;
2483 *_count = 2;
2484 return 0;
2488 * when we endup here, we're looking for a new SMB2 request
2489 * next. And we ask for its header and the first 2 bytes of
2490 * the body (like we did for the first SMB2 request).
2493 req->in.vector = talloc_realloc(req, req->in.vector,
2494 struct iovec,
2495 req->in.vector_count + 1);
2496 if (req->in.vector == NULL) {
2497 return -1;
2499 req->in.vector_count += 1;
2502 * We assume it's a SMB2 request,
2503 * and we first get the header and the
2504 * first 2 bytes (the struct size) of the body
2506 len = SMB2_HDR_BODY + 2;
2508 if (len > state->missing) {
2509 /* let the caller handle the error */
2510 len = state->missing;
2513 state->missing -= len;
2514 state->asked_for_header = true;
2516 buf = talloc_array(req->in.vector, uint8_t, len);
2517 if (buf == NULL) {
2518 return -1;
2521 req->in.vector[idx].iov_base = (void *)buf;
2522 req->in.vector[idx].iov_len = len;
2524 vector = talloc_array(mem_ctx, struct iovec, 1);
2525 if (vector == NULL) {
2526 return -1;
2529 vector[0] = req->in.vector[idx];
2531 *_vector = vector;
2532 *_count = 1;
2533 return 0;
2536 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2538 struct tevent_req *req =
2539 tevent_req_callback_data(subreq,
2540 struct tevent_req);
2541 int ret;
2542 int sys_errno;
2543 NTSTATUS status;
2545 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2546 if (ret == -1) {
2547 status = map_nt_error_from_unix(sys_errno);
2548 tevent_req_nterror(req, status);
2549 return;
2552 tevent_req_done(req);
2555 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2556 TALLOC_CTX *mem_ctx,
2557 struct smbd_smb2_request **_smb2_req)
2559 struct smbd_smb2_request_read_state *state =
2560 tevent_req_data(req,
2561 struct smbd_smb2_request_read_state);
2562 NTSTATUS status;
2564 if (tevent_req_is_nterror(req, &status)) {
2565 tevent_req_received(req);
2566 return status;
2569 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2570 *_smb2_req = state->smb2_req;
2571 tevent_req_received(req);
2572 return NT_STATUS_OK;
2575 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2577 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2579 size_t max_send_queue_len;
2580 size_t cur_send_queue_len;
2581 struct tevent_req *subreq;
2583 if (sconn->smb2.compound_related_in_progress) {
2585 * Can't read another until the related
2586 * compound is done.
2588 return NT_STATUS_OK;
2591 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2593 * if there is already a smbd_smb2_request_read
2594 * pending, we are done.
2596 return NT_STATUS_OK;
2599 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2600 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2602 if (cur_send_queue_len > max_send_queue_len) {
2604 * if we have a lot of requests to send,
2605 * we wait until they are on the wire until we
2606 * ask for the next request.
2608 return NT_STATUS_OK;
2611 /* ask for the next request */
2612 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2613 if (subreq == NULL) {
2614 return NT_STATUS_NO_MEMORY;
2616 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2618 return NT_STATUS_OK;
2621 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2622 const uint8_t *inbuf, size_t size)
2624 NTSTATUS status;
2625 struct smbd_smb2_request *req = NULL;
2627 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2628 (unsigned int)size));
2630 status = smbd_initialize_smb2(sconn);
2631 if (!NT_STATUS_IS_OK(status)) {
2632 smbd_server_connection_terminate(sconn, nt_errstr(status));
2633 return;
2636 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2637 if (!NT_STATUS_IS_OK(status)) {
2638 smbd_server_connection_terminate(sconn, nt_errstr(status));
2639 return;
2642 status = smbd_smb2_request_setup_out(req);
2643 if (!NT_STATUS_IS_OK(status)) {
2644 smbd_server_connection_terminate(sconn, nt_errstr(status));
2645 return;
2648 status = smbd_smb2_request_dispatch(req);
2649 if (!NT_STATUS_IS_OK(status)) {
2650 smbd_server_connection_terminate(sconn, nt_errstr(status));
2651 return;
2654 status = smbd_smb2_request_next_incoming(sconn);
2655 if (!NT_STATUS_IS_OK(status)) {
2656 smbd_server_connection_terminate(sconn, nt_errstr(status));
2657 return;
2660 sconn->num_requests++;
2663 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2665 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2666 struct smbd_server_connection);
2667 NTSTATUS status;
2668 struct smbd_smb2_request *req = NULL;
2670 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2671 TALLOC_FREE(subreq);
2672 if (!NT_STATUS_IS_OK(status)) {
2673 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2674 nt_errstr(status)));
2675 smbd_server_connection_terminate(sconn, nt_errstr(status));
2676 return;
2679 if (req->in.nbt_hdr[0] != 0x00) {
2680 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2681 req->in.nbt_hdr[0]));
2682 TALLOC_FREE(req);
2683 goto next;
2686 req->current_idx = 1;
2688 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2689 req->current_idx, req->in.vector_count));
2691 status = smbd_smb2_request_validate(req);
2692 if (!NT_STATUS_IS_OK(status)) {
2693 smbd_server_connection_terminate(sconn, nt_errstr(status));
2694 return;
2697 status = smbd_smb2_request_setup_out(req);
2698 if (!NT_STATUS_IS_OK(status)) {
2699 smbd_server_connection_terminate(sconn, nt_errstr(status));
2700 return;
2703 status = smbd_smb2_request_dispatch(req);
2704 if (!NT_STATUS_IS_OK(status)) {
2705 smbd_server_connection_terminate(sconn, nt_errstr(status));
2706 return;
2709 next:
2710 status = smbd_smb2_request_next_incoming(sconn);
2711 if (!NT_STATUS_IS_OK(status)) {
2712 smbd_server_connection_terminate(sconn, nt_errstr(status));
2713 return;
2716 sconn->num_requests++;
2718 /* The timeout_processing function isn't run nearly
2719 often enough to implement 'max log size' without
2720 overrunning the size of the file by many megabytes.
2721 This is especially true if we are running at debug
2722 level 10. Checking every 50 SMB2s is a nice
2723 tradeoff of performance vs log file size overrun. */
2725 if ((sconn->num_requests % 50) == 0 &&
2726 need_to_check_log_size()) {
2727 change_to_root_user();
2728 check_log_size();