s3:smbd: add smbXsrv_session infrastructure
[Samba/gebeck_regimport.git] / source3 / smbd / smb2_server.c
blob5d30aa48900f46a152dd8736e60288819eba5a5e
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;
309 uint16_t credit_charge = 1;
310 uint64_t i;
312 if (opcode == SMB2_OP_CANCEL) {
313 /* SMB2_CANCEL requests by definition resend messageids. */
314 return true;
317 if (message_id < sconn->smb2.seqnum_low ||
318 message_id > (sconn->smb2.seqnum_low +
319 (sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR))) {
320 DEBUG(0,("smb2_validate_message_id: bad message_id "
321 "%llu (low = %llu, max = %lu)\n",
322 (unsigned long long)message_id,
323 (unsigned long long)sconn->smb2.seqnum_low,
324 (unsigned long)sconn->smb2.max_credits ));
325 return false;
328 if (sconn->smb2.credits_granted == 0) {
329 DEBUG(0,("smb2_validate_message_id: client used more "
330 "credits than granted, message_id (%llu)\n",
331 (unsigned long long)message_id));
332 return false;
335 if (sconn->smb2.supports_multicredit) {
336 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
337 credit_charge = MAX(credit_charge, 1);
340 DEBUG(11, ("smb2_validate_message_id: mid %llu, credits_granted %llu, "
341 "charge %llu, max_credits %llu, seqnum_low: %llu\n",
342 (unsigned long long) message_id,
343 (unsigned long long) sconn->smb2.credits_granted,
344 (unsigned long long) credit_charge,
345 (unsigned long long) sconn->smb2.max_credits,
346 (unsigned long long) sconn->smb2.seqnum_low));
348 /* substract used credits */
349 sconn->smb2.credits_granted -= credit_charge;
352 * now check the message ids
354 * for multi-credit requests we need to check all current mid plus
355 * the implicit mids caused by the credit charge
356 * e.g. current mid = 15, charge 5 => mark 15-19 as used
359 for (i = message_id; i <= (message_id+credit_charge-1); i++) {
361 DEBUG(11, ("Iterating mid %llu\n", (unsigned long long) i));
363 /* Mark the message_ids as seen in the bitmap. */
364 bitmap_offset = (unsigned int)(i %
365 (uint64_t)(sconn->smb2.max_credits *
366 DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR));
367 if (bitmap_query(credits_bm, bitmap_offset)) {
368 DEBUG(0,("smb2_validate_message_id: duplicate "
369 "message_id %llu (bm offset %u)\n",
370 (unsigned long long)i, bitmap_offset));
371 return false;
373 bitmap_set(credits_bm, bitmap_offset);
375 if (i == sconn->smb2.seqnum_low + 1) {
376 /* Move the window forward by all the message_id's
377 already seen. */
378 while (bitmap_query(credits_bm, bitmap_offset)) {
379 DEBUG(10,("smb2_validate_message_id: clearing "
380 "id %llu (position %u) from bitmap\n",
381 (unsigned long long)(sconn->smb2.seqnum_low + 1),
382 bitmap_offset));
383 bitmap_clear(credits_bm, bitmap_offset);
384 sconn->smb2.seqnum_low += 1;
385 bitmap_offset = (bitmap_offset + 1) %
386 (sconn->smb2.max_credits *
387 DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR);
392 return true;
395 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
397 int count;
398 int idx;
400 count = req->in.vector_count;
402 if (count < 4) {
403 /* It's not a SMB2 request */
404 return NT_STATUS_INVALID_PARAMETER;
407 for (idx=1; idx < count; idx += 3) {
408 const uint8_t *inhdr = NULL;
409 uint32_t flags;
411 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
412 return NT_STATUS_INVALID_PARAMETER;
415 if (req->in.vector[idx+1].iov_len < 2) {
416 return NT_STATUS_INVALID_PARAMETER;
419 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
421 /* Check the SMB2 header */
422 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
423 return NT_STATUS_INVALID_PARAMETER;
426 if (!smb2_validate_message_id(req->sconn, inhdr)) {
427 return NT_STATUS_INVALID_PARAMETER;
430 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
431 if (idx == 1) {
433 * the 1st request should never have the
434 * SMB2_HDR_FLAG_CHAINED flag set
436 if (flags & SMB2_HDR_FLAG_CHAINED) {
437 req->next_status = NT_STATUS_INVALID_PARAMETER;
438 return NT_STATUS_OK;
440 } else if (idx == 4) {
442 * the 2nd request triggers related vs. unrelated
443 * compounded requests
445 if (flags & SMB2_HDR_FLAG_CHAINED) {
446 req->compound_related = true;
448 } else if (idx > 4) {
449 #if 0
451 * It seems the this tests are wrong
452 * see the SMB2-COMPOUND test
456 * all other requests should match the 2nd one
458 if (flags & SMB2_HDR_FLAG_CHAINED) {
459 if (!req->compound_related) {
460 req->next_status =
461 NT_STATUS_INVALID_PARAMETER;
462 return NT_STATUS_OK;
464 } else {
465 if (req->compound_related) {
466 req->next_status =
467 NT_STATUS_INVALID_PARAMETER;
468 return NT_STATUS_OK;
471 #endif
475 return NT_STATUS_OK;
478 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
479 const struct iovec *in_vector,
480 struct iovec *out_vector)
482 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
483 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
484 uint16_t credits_requested;
485 uint32_t out_flags;
486 uint16_t credits_granted = 0;
488 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
489 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
491 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
493 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
495 * In case we already send an async interim
496 * response, we should not grant
497 * credits on the final response.
499 credits_requested = 0;
502 if (credits_requested) {
503 uint16_t modified_credits_requested;
504 uint32_t multiplier;
507 * Split up max_credits into 1/16ths, and then scale
508 * the requested credits by how many 16ths have been
509 * currently granted. Less than 1/16th == grant all
510 * requested (100%), scale down as more have been
511 * granted. Never ask for less than 1 as the client
512 * asked for at least 1. JRA.
515 multiplier = 16 - (((sconn->smb2.credits_granted * 16) / sconn->smb2.max_credits) % 16);
517 modified_credits_requested = (multiplier * credits_requested) / 16;
518 if (modified_credits_requested == 0) {
519 modified_credits_requested = 1;
522 /* Remember what we gave out. */
523 credits_granted = MIN(modified_credits_requested,
524 (sconn->smb2.max_credits - sconn->smb2.credits_granted));
527 if (credits_granted == 0 && sconn->smb2.credits_granted == 0) {
528 /* First negprot packet, or ensure the client credits can
529 never drop to zero. */
530 credits_granted = 1;
533 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
534 sconn->smb2.credits_granted += credits_granted;
536 DEBUG(10,("smb2_set_operation_credit: requested %u, "
537 "granted %u, total granted %u\n",
538 (unsigned int)credits_requested,
539 (unsigned int)credits_granted,
540 (unsigned int)sconn->smb2.credits_granted ));
543 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
544 struct smbd_smb2_request *outreq)
546 int count, idx;
547 uint16_t total_credits = 0;
549 count = outreq->out.vector_count;
551 for (idx=1; idx < count; idx += 3) {
552 uint8_t *outhdr = (uint8_t *)outreq->out.vector[idx].iov_base;
553 smb2_set_operation_credit(outreq->sconn,
554 &inreq->in.vector[idx],
555 &outreq->out.vector[idx]);
556 /* To match Windows, count up what we
557 just granted. */
558 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
559 /* Set to zero in all but the last reply. */
560 if (idx + 3 < count) {
561 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
562 } else {
563 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
568 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
570 struct iovec *vector;
571 int count;
572 int idx;
574 req->request_time = timeval_current();
576 count = req->in.vector_count;
577 vector = talloc_zero_array(req, struct iovec, count);
578 if (vector == NULL) {
579 return NT_STATUS_NO_MEMORY;
582 vector[0].iov_base = req->out.nbt_hdr;
583 vector[0].iov_len = 4;
584 SIVAL(req->out.nbt_hdr, 0, 0);
586 for (idx=1; idx < count; idx += 3) {
587 const uint8_t *inhdr = NULL;
588 uint8_t *outhdr = NULL;
589 uint8_t *outbody = NULL;
590 uint32_t next_command_ofs = 0;
591 struct iovec *current = &vector[idx];
593 if ((idx + 3) < count) {
594 /* we have a next command -
595 * setup for the error case. */
596 next_command_ofs = SMB2_HDR_BODY + 9;
599 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
601 outhdr = talloc_zero_array(vector, uint8_t,
602 OUTVEC_ALLOC_SIZE);
603 if (outhdr == NULL) {
604 return NT_STATUS_NO_MEMORY;
607 outbody = outhdr + SMB2_HDR_BODY;
609 current[0].iov_base = (void *)outhdr;
610 current[0].iov_len = SMB2_HDR_BODY;
612 current[1].iov_base = (void *)outbody;
613 current[1].iov_len = 8;
615 current[2].iov_base = NULL;
616 current[2].iov_len = 0;
618 /* setup the SMB2 header */
619 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
620 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
621 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
622 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
623 SIVAL(outhdr, SMB2_HDR_STATUS,
624 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
625 SSVAL(outhdr, SMB2_HDR_OPCODE,
626 SVAL(inhdr, SMB2_HDR_OPCODE));
627 SIVAL(outhdr, SMB2_HDR_FLAGS,
628 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
629 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
630 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
631 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
632 SIVAL(outhdr, SMB2_HDR_PID,
633 IVAL(inhdr, SMB2_HDR_PID));
634 SIVAL(outhdr, SMB2_HDR_TID,
635 IVAL(inhdr, SMB2_HDR_TID));
636 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
637 BVAL(inhdr, SMB2_HDR_SESSION_ID));
638 memcpy(outhdr + SMB2_HDR_SIGNATURE,
639 inhdr + SMB2_HDR_SIGNATURE, 16);
641 /* setup error body header */
642 SSVAL(outbody, 0x00, 0x08 + 1);
643 SSVAL(outbody, 0x02, 0);
644 SIVAL(outbody, 0x04, 0);
647 req->out.vector = vector;
648 req->out.vector_count = count;
650 /* setup the length of the NBT packet */
651 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
653 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
655 return NT_STATUS_OK;
658 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
659 const char *reason,
660 const char *location)
662 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
663 reason, location));
664 exit_server_cleanly(reason);
667 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
668 struct iovec *outvec,
669 const struct iovec *srcvec)
671 /* vec[0] is always boilerplate and must
672 * be allocated with size OUTVEC_ALLOC_SIZE. */
674 outvec[0].iov_base = talloc_memdup(ctx,
675 srcvec[0].iov_base,
676 OUTVEC_ALLOC_SIZE);
677 if (!outvec[0].iov_base) {
678 return false;
680 outvec[0].iov_len = SMB2_HDR_BODY;
683 * If this is a "standard" vec[1] of length 8,
684 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
685 * then duplicate this. Else use talloc_memdup().
688 if (srcvec[1].iov_len == 8 &&
689 srcvec[1].iov_base ==
690 ((uint8_t *)srcvec[0].iov_base) +
691 SMB2_HDR_BODY) {
692 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
693 SMB2_HDR_BODY;
694 outvec[1].iov_len = 8;
695 } else {
696 outvec[1].iov_base = talloc_memdup(ctx,
697 srcvec[1].iov_base,
698 srcvec[1].iov_len);
699 if (!outvec[1].iov_base) {
700 return false;
702 outvec[1].iov_len = srcvec[1].iov_len;
706 * If this is a "standard" vec[2] of length 1,
707 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
708 * then duplicate this. Else use talloc_memdup().
711 if (srcvec[2].iov_base &&
712 srcvec[2].iov_len) {
713 if (srcvec[2].iov_base ==
714 ((uint8_t *)srcvec[0].iov_base) +
715 (OUTVEC_ALLOC_SIZE - 1) &&
716 srcvec[2].iov_len == 1) {
717 /* Common SMB2 error packet case. */
718 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
719 (OUTVEC_ALLOC_SIZE - 1);
720 } else {
721 outvec[2].iov_base = talloc_memdup(ctx,
722 srcvec[2].iov_base,
723 srcvec[2].iov_len);
724 if (!outvec[2].iov_base) {
725 return false;
728 outvec[2].iov_len = srcvec[2].iov_len;
729 } else {
730 outvec[2].iov_base = NULL;
731 outvec[2].iov_len = 0;
733 return true;
736 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
738 struct smbd_smb2_request *newreq = NULL;
739 struct iovec *outvec = NULL;
740 int count = req->out.vector_count;
741 int i;
743 newreq = smbd_smb2_request_allocate(req->sconn);
744 if (!newreq) {
745 return NULL;
748 newreq->sconn = req->sconn;
749 newreq->session = req->session;
750 newreq->do_signing = req->do_signing;
751 newreq->current_idx = req->current_idx;
753 outvec = talloc_zero_array(newreq, struct iovec, count);
754 if (!outvec) {
755 TALLOC_FREE(newreq);
756 return NULL;
758 newreq->out.vector = outvec;
759 newreq->out.vector_count = count;
761 /* Setup the outvec's identically to req. */
762 outvec[0].iov_base = newreq->out.nbt_hdr;
763 outvec[0].iov_len = 4;
764 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
766 /* Setup the vectors identically to the ones in req. */
767 for (i = 1; i < count; i += 3) {
768 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
769 break;
773 if (i < count) {
774 /* Alloc failed. */
775 TALLOC_FREE(newreq);
776 return NULL;
779 smb2_setup_nbt_length(newreq->out.vector,
780 newreq->out.vector_count);
782 return newreq;
785 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
787 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
789 int i = 0;
790 uint8_t *outhdr = NULL;
791 struct smbd_smb2_request *nreq = NULL;
793 /* Create a new smb2 request we'll use
794 for the interim return. */
795 nreq = dup_smb2_req(req);
796 if (!nreq) {
797 return NT_STATUS_NO_MEMORY;
800 /* Lose the last 3 out vectors. They're the
801 ones we'll be using for the async reply. */
802 nreq->out.vector_count -= 3;
804 smb2_setup_nbt_length(nreq->out.vector,
805 nreq->out.vector_count);
807 /* Step back to the previous reply. */
808 i = nreq->current_idx - 3;
809 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
810 /* And end the chain. */
811 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
813 /* Calculate outgoing credits */
814 smb2_calculate_credits(req, nreq);
816 /* Re-sign if needed. */
817 if (nreq->do_signing) {
818 NTSTATUS status;
819 status = smb2_signing_sign_pdu(nreq->session->session_key,
820 get_Protocol(),
821 &nreq->out.vector[i], 3);
822 if (!NT_STATUS_IS_OK(status)) {
823 return status;
826 if (DEBUGLEVEL >= 10) {
827 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
828 (unsigned int)nreq->current_idx );
829 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
830 (unsigned int)nreq->out.vector_count );
831 print_req_vectors(nreq);
833 nreq->subreq = tstream_writev_queue_send(nreq,
834 nreq->sconn->ev_ctx,
835 nreq->sconn->smb2.stream,
836 nreq->sconn->smb2.send_queue,
837 nreq->out.vector,
838 nreq->out.vector_count);
840 if (nreq->subreq == NULL) {
841 return NT_STATUS_NO_MEMORY;
844 tevent_req_set_callback(nreq->subreq,
845 smbd_smb2_request_writev_done,
846 nreq);
848 return NT_STATUS_OK;
851 struct smbd_smb2_request_pending_state {
852 struct smbd_server_connection *sconn;
853 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
854 struct iovec vector[3];
857 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
859 struct smbd_smb2_request_pending_state *state =
860 tevent_req_callback_data(subreq,
861 struct smbd_smb2_request_pending_state);
862 struct smbd_server_connection *sconn = state->sconn;
863 int ret;
864 int sys_errno;
866 ret = tstream_writev_queue_recv(subreq, &sys_errno);
867 TALLOC_FREE(subreq);
868 if (ret == -1) {
869 NTSTATUS status = map_nt_error_from_unix(sys_errno);
870 smbd_server_connection_terminate(sconn, nt_errstr(status));
871 return;
874 TALLOC_FREE(state);
877 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
878 struct tevent_timer *te,
879 struct timeval current_time,
880 void *private_data);
882 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
883 struct tevent_req *subreq,
884 uint32_t defer_time)
886 NTSTATUS status;
887 int i = req->current_idx;
888 struct timeval defer_endtime;
889 uint8_t *outhdr = NULL;
890 uint32_t flags;
892 if (!tevent_req_is_in_progress(subreq)) {
893 return NT_STATUS_OK;
896 req->subreq = subreq;
897 subreq = NULL;
899 if (req->async_te) {
900 /* We're already async. */
901 return NT_STATUS_OK;
904 outhdr = (uint8_t *)req->out.vector[i].iov_base;
905 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
906 if (flags & SMB2_HDR_FLAG_ASYNC) {
907 /* We're already async. */
908 return NT_STATUS_OK;
911 if (req->in.vector_count > i + 3) {
913 * We're trying to go async in a compound
914 * request chain. This is not allowed.
915 * Cancel the outstanding request.
917 tevent_req_cancel(req->subreq);
918 return smbd_smb2_request_error(req,
919 NT_STATUS_INSUFFICIENT_RESOURCES);
922 if (DEBUGLEVEL >= 10) {
923 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
924 (unsigned int)req->current_idx );
925 print_req_vectors(req);
928 if (req->out.vector_count > 4) {
929 struct iovec *outvec = NULL;
931 /* This is a compound reply. We
932 * must do an interim response
933 * followed by the async response
934 * to match W2K8R2.
936 status = smb2_send_async_interim_response(req);
937 if (!NT_STATUS_IS_OK(status)) {
938 return status;
942 * We're splitting off the last SMB2
943 * request in a compound set, and the
944 * smb2_send_async_interim_response()
945 * call above just sent all the replies
946 * for the previous SMB2 requests in
947 * this compound set. So we're no longer
948 * in the "compound_related_in_progress"
949 * state, and this is no longer a compound
950 * request.
952 req->compound_related = false;
953 req->sconn->smb2.compound_related_in_progress = false;
955 /* Re-arrange the in.vectors. */
956 req->in.vector[1] = req->in.vector[i];
957 req->in.vector[2] = req->in.vector[i+1];
958 req->in.vector[3] = req->in.vector[i+2];
959 req->in.vector_count = 4;
961 /* Reset the new in size. */
962 smb2_setup_nbt_length(req->in.vector, 4);
964 /* Now recreate the out.vectors. */
965 outvec = talloc_zero_array(req, struct iovec, 4);
966 if (!outvec) {
967 return NT_STATUS_NO_MEMORY;
970 /* 0 is always boilerplate and must
971 * be of size 4 for the length field. */
973 outvec[0].iov_base = req->out.nbt_hdr;
974 outvec[0].iov_len = 4;
975 SIVAL(req->out.nbt_hdr, 0, 0);
977 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
978 return NT_STATUS_NO_MEMORY;
981 TALLOC_FREE(req->out.vector);
983 req->out.vector = outvec;
985 req->current_idx = 1;
986 req->out.vector_count = 4;
988 outhdr = (uint8_t *)req->out.vector[1].iov_base;
989 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
990 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
993 defer_endtime = timeval_current_ofs_usec(defer_time);
994 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
995 req, defer_endtime,
996 smbd_smb2_request_pending_timer,
997 req);
998 if (req->async_te == NULL) {
999 return NT_STATUS_NO_MEMORY;
1002 return NT_STATUS_OK;
1005 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1006 struct tevent_timer *te,
1007 struct timeval current_time,
1008 void *private_data)
1010 struct smbd_smb2_request *req =
1011 talloc_get_type_abort(private_data,
1012 struct smbd_smb2_request);
1013 struct smbd_smb2_request_pending_state *state = NULL;
1014 int i = req->current_idx;
1015 uint8_t *outhdr = NULL;
1016 const uint8_t *inhdr = NULL;
1017 uint8_t *hdr = NULL;
1018 uint8_t *body = NULL;
1019 uint32_t flags = 0;
1020 uint64_t message_id = 0;
1021 uint64_t async_id = 0;
1022 struct tevent_req *subreq = NULL;
1024 TALLOC_FREE(req->async_te);
1026 /* Ensure our final reply matches the interim one. */
1027 inhdr = (const uint8_t *)req->in.vector[1].iov_base;
1028 outhdr = (uint8_t *)req->out.vector[1].iov_base;
1029 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1030 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1032 async_id = message_id; /* keep it simple for now... */
1034 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1035 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1037 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1038 "going async\n",
1039 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1040 (unsigned long long)async_id ));
1043 * What we send is identical to a smbd_smb2_request_error
1044 * packet with an error status of STATUS_PENDING. Make use
1045 * of this fact sometime when refactoring. JRA.
1048 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1049 if (state == NULL) {
1050 smbd_server_connection_terminate(req->sconn,
1051 nt_errstr(NT_STATUS_NO_MEMORY));
1052 return;
1054 state->sconn = req->sconn;
1056 state->vector[0].iov_base = (void *)state->buf;
1057 state->vector[0].iov_len = 4;
1059 state->vector[1].iov_base = state->buf + 4;
1060 state->vector[1].iov_len = SMB2_HDR_BODY;
1062 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
1063 state->vector[2].iov_len = 9;
1065 smb2_setup_nbt_length(state->vector, 3);
1067 hdr = (uint8_t *)state->vector[1].iov_base;
1068 body = (uint8_t *)state->vector[2].iov_base;
1070 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1071 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1072 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1073 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1074 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1076 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1077 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1078 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1079 SBVAL(hdr, SMB2_HDR_PID, async_id);
1080 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1081 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1082 memcpy(hdr+SMB2_HDR_SIGNATURE,
1083 outhdr+SMB2_HDR_SIGNATURE, 16);
1085 SSVAL(body, 0x00, 0x08 + 1);
1087 SCVAL(body, 0x02, 0);
1088 SCVAL(body, 0x03, 0);
1089 SIVAL(body, 0x04, 0);
1090 /* Match W2K8R2... */
1091 SCVAL(body, 0x08, 0x21);
1093 /* Ensure we correctly go through crediting. Grant
1094 the credits now, and zero credits on the final
1095 response. */
1096 smb2_set_operation_credit(req->sconn,
1097 &req->in.vector[i],
1098 &state->vector[1]);
1100 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1102 if (req->do_signing) {
1103 NTSTATUS status;
1105 status = smb2_signing_sign_pdu(req->session->session_key,
1106 get_Protocol(),
1107 &state->vector[1], 2);
1108 if (!NT_STATUS_IS_OK(status)) {
1109 smbd_server_connection_terminate(req->sconn,
1110 nt_errstr(status));
1111 return;
1115 subreq = tstream_writev_queue_send(state,
1116 state->sconn->ev_ctx,
1117 state->sconn->smb2.stream,
1118 state->sconn->smb2.send_queue,
1119 state->vector,
1121 if (subreq == NULL) {
1122 smbd_server_connection_terminate(state->sconn,
1123 nt_errstr(NT_STATUS_NO_MEMORY));
1124 return;
1126 tevent_req_set_callback(subreq,
1127 smbd_smb2_request_pending_writev_done,
1128 state);
1131 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1133 struct smbd_server_connection *sconn = req->sconn;
1134 struct smbd_smb2_request *cur;
1135 const uint8_t *inhdr;
1136 int i = req->current_idx;
1137 uint32_t flags;
1138 uint64_t search_message_id;
1139 uint64_t search_async_id;
1140 uint64_t found_id;
1142 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1144 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1145 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1146 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1149 * we don't need the request anymore
1150 * cancel requests never have a response
1152 DLIST_REMOVE(req->sconn->smb2.requests, req);
1153 TALLOC_FREE(req);
1155 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1156 const uint8_t *outhdr;
1157 uint64_t message_id;
1158 uint64_t async_id;
1160 i = cur->current_idx;
1162 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1164 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1165 async_id = BVAL(outhdr, SMB2_HDR_PID);
1167 if (flags & SMB2_HDR_FLAG_ASYNC) {
1168 if (search_async_id == async_id) {
1169 found_id = async_id;
1170 break;
1172 } else {
1173 if (search_message_id == message_id) {
1174 found_id = message_id;
1175 break;
1180 if (cur && cur->subreq) {
1181 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1182 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1183 "cancel opcode[%s] mid %llu\n",
1184 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1185 (unsigned long long)found_id ));
1186 tevent_req_cancel(cur->subreq);
1189 return NT_STATUS_OK;
1192 /*************************************************************
1193 Ensure an incoming tid is a valid one for us to access.
1194 Change to the associated uid credentials and chdir to the
1195 valid tid directory.
1196 *************************************************************/
1198 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1200 const uint8_t *inhdr;
1201 int i = req->current_idx;
1202 uint32_t in_flags;
1203 uint32_t in_tid;
1204 void *p;
1205 struct smbd_smb2_tcon *tcon;
1207 req->tcon = NULL;
1209 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1211 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1212 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1214 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1215 in_tid = req->last_tid;
1218 /* lookup an existing session */
1219 p = idr_find(req->session->tcons.idtree, in_tid);
1220 if (p == NULL) {
1221 return NT_STATUS_NETWORK_NAME_DELETED;
1223 tcon = talloc_get_type_abort(p, struct smbd_smb2_tcon);
1225 if (!change_to_user(tcon->compat_conn,req->session->vuid)) {
1226 return NT_STATUS_ACCESS_DENIED;
1229 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1230 if (!set_current_service(tcon->compat_conn, 0, true)) {
1231 return NT_STATUS_ACCESS_DENIED;
1234 req->tcon = tcon;
1235 req->last_tid = in_tid;
1237 return NT_STATUS_OK;
1240 /*************************************************************
1241 Ensure an incoming session_id is a valid one for us to access.
1242 *************************************************************/
1244 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1246 const uint8_t *inhdr;
1247 int i = req->current_idx;
1248 uint32_t in_flags;
1249 uint64_t in_session_id;
1250 void *p;
1251 struct smbd_smb2_session *session;
1253 req->session = NULL;
1254 req->tcon = NULL;
1256 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1258 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1259 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1261 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1262 in_session_id = req->last_session_id;
1265 /* lookup an existing session */
1266 p = idr_find(req->sconn->smb2.sessions.idtree, in_session_id);
1267 if (p == NULL) {
1268 return NT_STATUS_USER_SESSION_DELETED;
1270 session = talloc_get_type_abort(p, struct smbd_smb2_session);
1272 if (!NT_STATUS_IS_OK(session->status)) {
1273 return NT_STATUS_ACCESS_DENIED;
1276 set_current_user_info(session->session_info->unix_info->sanitized_username,
1277 session->session_info->unix_info->unix_name,
1278 session->session_info->info->domain_name);
1280 req->session = session;
1281 req->last_session_id = in_session_id;
1283 return NT_STATUS_OK;
1286 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1287 uint32_t data_length)
1289 uint16_t needed_charge;
1290 uint16_t credit_charge;
1291 const uint8_t *inhdr;
1292 int i = req->current_idx;
1294 if (!req->sconn->smb2.supports_multicredit) {
1295 if (data_length > 65536) {
1296 return NT_STATUS_INVALID_PARAMETER;
1298 return NT_STATUS_OK;
1301 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1302 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1304 /* requests larger than 64 KB need credit charge */
1305 if (credit_charge == 0 && data_length > 65536) {
1306 DEBUG(2, ("Request larger than 64KB w/o creditcharge\n"));
1307 return NT_STATUS_INVALID_PARAMETER;
1310 needed_charge = (data_length - 1)/ 65536 + 1;
1312 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1313 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1314 credit_charge, needed_charge));
1316 if (needed_charge > credit_charge) {
1317 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1318 credit_charge, needed_charge));
1319 return NT_STATUS_INVALID_PARAMETER;
1322 return NT_STATUS_OK;
1325 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1326 size_t expected_body_size)
1328 const uint8_t *inhdr;
1329 uint16_t opcode;
1330 const uint8_t *inbody;
1331 int i = req->current_idx;
1332 size_t body_size;
1333 size_t min_dyn_size = expected_body_size & 0x00000001;
1336 * The following should be checked already.
1338 if ((i+2) > req->in.vector_count) {
1339 return NT_STATUS_INTERNAL_ERROR;
1341 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1342 return NT_STATUS_INTERNAL_ERROR;
1344 if (req->in.vector[i+1].iov_len < 2) {
1345 return NT_STATUS_INTERNAL_ERROR;
1348 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1349 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1351 switch (opcode) {
1352 case SMB2_OP_IOCTL:
1353 case SMB2_OP_GETINFO:
1354 min_dyn_size = 0;
1355 break;
1359 * Now check the expected body size,
1360 * where the last byte might be in the
1361 * dynamic section..
1363 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1364 return NT_STATUS_INVALID_PARAMETER;
1366 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1367 return NT_STATUS_INVALID_PARAMETER;
1370 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1372 body_size = SVAL(inbody, 0x00);
1373 if (body_size != expected_body_size) {
1374 return NT_STATUS_INVALID_PARAMETER;
1377 return NT_STATUS_OK;
1380 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1382 const uint8_t *inhdr;
1383 int i = req->current_idx;
1384 uint16_t opcode;
1385 uint32_t flags;
1386 uint64_t mid;
1387 NTSTATUS status;
1388 NTSTATUS session_status;
1389 uint32_t allowed_flags;
1390 NTSTATUS return_value;
1392 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1394 /* TODO: verify more things */
1396 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1397 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1398 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1399 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1400 smb2_opcode_name(opcode),
1401 (unsigned long long)mid));
1403 if (get_Protocol() >= PROTOCOL_SMB2_02) {
1405 * once the protocol is negotiated
1406 * SMB2_OP_NEGPROT is not allowed anymore
1408 if (opcode == SMB2_OP_NEGPROT) {
1409 /* drop the connection */
1410 return NT_STATUS_INVALID_PARAMETER;
1412 } else {
1414 * if the protocol is not negotiated yet
1415 * only SMB2_OP_NEGPROT is allowed.
1417 if (opcode != SMB2_OP_NEGPROT) {
1418 /* drop the connection */
1419 return NT_STATUS_INVALID_PARAMETER;
1423 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1424 SMB2_HDR_FLAG_SIGNED |
1425 SMB2_HDR_FLAG_DFS;
1426 if (opcode == SMB2_OP_CANCEL) {
1427 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1429 if ((flags & ~allowed_flags) != 0) {
1430 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1434 * Check if the client provided a valid session id,
1435 * if so smbd_smb2_request_check_session() calls
1436 * set_current_user_info().
1438 * As some command don't require a valid session id
1439 * we defer the check of the session_status
1441 session_status = smbd_smb2_request_check_session(req);
1443 req->do_signing = false;
1444 if (flags & SMB2_HDR_FLAG_SIGNED) {
1445 if (!NT_STATUS_IS_OK(session_status)) {
1446 return smbd_smb2_request_error(req, session_status);
1449 req->do_signing = true;
1450 status = smb2_signing_check_pdu(req->session->session_key,
1451 get_Protocol(),
1452 &req->in.vector[i], 3);
1453 if (!NT_STATUS_IS_OK(status)) {
1454 return smbd_smb2_request_error(req, status);
1456 } else if (opcode == SMB2_OP_CANCEL) {
1457 /* Cancel requests are allowed to skip the signing */
1458 } else if (req->session && req->session->do_signing) {
1459 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1462 if (flags & SMB2_HDR_FLAG_CHAINED) {
1464 * This check is mostly for giving the correct error code
1465 * for compounded requests.
1467 * TODO: we may need to move this after the session
1468 * and tcon checks.
1470 if (!NT_STATUS_IS_OK(req->next_status)) {
1471 return smbd_smb2_request_error(req, req->next_status);
1473 } else {
1474 req->compat_chain_fsp = NULL;
1477 if (req->compound_related) {
1478 req->sconn->smb2.compound_related_in_progress = true;
1481 switch (opcode) {
1482 case SMB2_OP_NEGPROT:
1483 /* This call needs to be run as root */
1484 change_to_root_user();
1487 START_PROFILE(smb2_negprot);
1488 return_value = smbd_smb2_request_process_negprot(req);
1489 END_PROFILE(smb2_negprot);
1491 break;
1493 case SMB2_OP_SESSSETUP:
1494 /* This call needs to be run as root */
1495 change_to_root_user();
1498 START_PROFILE(smb2_sesssetup);
1499 return_value = smbd_smb2_request_process_sesssetup(req);
1500 END_PROFILE(smb2_sesssetup);
1502 break;
1504 case SMB2_OP_LOGOFF:
1505 if (!NT_STATUS_IS_OK(session_status)) {
1506 return_value = smbd_smb2_request_error(req, session_status);
1507 break;
1510 /* This call needs to be run as root */
1511 change_to_root_user();
1514 START_PROFILE(smb2_logoff);
1515 return_value = smbd_smb2_request_process_logoff(req);
1516 END_PROFILE(smb2_logoff);
1518 break;
1520 case SMB2_OP_TCON:
1521 if (!NT_STATUS_IS_OK(session_status)) {
1522 return_value = smbd_smb2_request_error(req, session_status);
1523 break;
1527 * This call needs to be run as root.
1529 * smbd_smb2_request_process_tcon()
1530 * calls make_connection_snum(), which will call
1531 * change_to_user(), when needed.
1533 change_to_root_user();
1536 START_PROFILE(smb2_tcon);
1537 return_value = smbd_smb2_request_process_tcon(req);
1538 END_PROFILE(smb2_tcon);
1540 break;
1542 case SMB2_OP_TDIS:
1543 if (!NT_STATUS_IS_OK(session_status)) {
1544 return_value = smbd_smb2_request_error(req, session_status);
1545 break;
1548 * This call needs to be run as user.
1550 * smbd_smb2_request_check_tcon()
1551 * calls change_to_user() on success.
1553 status = smbd_smb2_request_check_tcon(req);
1554 if (!NT_STATUS_IS_OK(status)) {
1555 return_value = smbd_smb2_request_error(req, status);
1556 break;
1558 /* This call needs to be run as root */
1559 change_to_root_user();
1563 START_PROFILE(smb2_tdis);
1564 return_value = smbd_smb2_request_process_tdis(req);
1565 END_PROFILE(smb2_tdis);
1567 break;
1569 case SMB2_OP_CREATE:
1570 if (!NT_STATUS_IS_OK(session_status)) {
1571 return_value = smbd_smb2_request_error(req, session_status);
1572 break;
1575 * This call needs to be run as user.
1577 * smbd_smb2_request_check_tcon()
1578 * calls change_to_user() on success.
1580 status = smbd_smb2_request_check_tcon(req);
1581 if (!NT_STATUS_IS_OK(status)) {
1582 return_value = smbd_smb2_request_error(req, status);
1583 break;
1587 START_PROFILE(smb2_create);
1588 return_value = smbd_smb2_request_process_create(req);
1589 END_PROFILE(smb2_create);
1591 break;
1593 case SMB2_OP_CLOSE:
1594 if (!NT_STATUS_IS_OK(session_status)) {
1595 return_value = smbd_smb2_request_error(req, session_status);
1596 break;
1599 * This call needs to be run as user.
1601 * smbd_smb2_request_check_tcon()
1602 * calls change_to_user() on success.
1604 status = smbd_smb2_request_check_tcon(req);
1605 if (!NT_STATUS_IS_OK(status)) {
1606 return_value = smbd_smb2_request_error(req, status);
1607 break;
1611 START_PROFILE(smb2_close);
1612 return_value = smbd_smb2_request_process_close(req);
1613 END_PROFILE(smb2_close);
1615 break;
1617 case SMB2_OP_FLUSH:
1618 if (!NT_STATUS_IS_OK(session_status)) {
1619 return_value = smbd_smb2_request_error(req, session_status);
1620 break;
1623 * This call needs to be run as user.
1625 * smbd_smb2_request_check_tcon()
1626 * calls change_to_user() on success.
1628 status = smbd_smb2_request_check_tcon(req);
1629 if (!NT_STATUS_IS_OK(status)) {
1630 return_value = smbd_smb2_request_error(req, status);
1631 break;
1635 START_PROFILE(smb2_flush);
1636 return_value = smbd_smb2_request_process_flush(req);
1637 END_PROFILE(smb2_flush);
1639 break;
1641 case SMB2_OP_READ:
1642 if (!NT_STATUS_IS_OK(session_status)) {
1643 return_value = smbd_smb2_request_error(req, session_status);
1644 break;
1647 * This call needs to be run as user.
1649 * smbd_smb2_request_check_tcon()
1650 * calls change_to_user() on success.
1652 status = smbd_smb2_request_check_tcon(req);
1653 if (!NT_STATUS_IS_OK(status)) {
1654 return_value = smbd_smb2_request_error(req, status);
1655 break;
1659 START_PROFILE(smb2_read);
1660 return_value = smbd_smb2_request_process_read(req);
1661 END_PROFILE(smb2_read);
1663 break;
1665 case SMB2_OP_WRITE:
1666 if (!NT_STATUS_IS_OK(session_status)) {
1667 return_value = smbd_smb2_request_error(req, session_status);
1668 break;
1671 * This call needs to be run as user.
1673 * smbd_smb2_request_check_tcon()
1674 * calls change_to_user() on success.
1676 status = smbd_smb2_request_check_tcon(req);
1677 if (!NT_STATUS_IS_OK(status)) {
1678 return_value = smbd_smb2_request_error(req, status);
1679 break;
1683 START_PROFILE(smb2_write);
1684 return_value = smbd_smb2_request_process_write(req);
1685 END_PROFILE(smb2_write);
1687 break;
1689 case SMB2_OP_LOCK:
1690 if (!NT_STATUS_IS_OK(session_status)) {
1691 /* Too ugly to live ? JRA. */
1692 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1693 session_status = NT_STATUS_FILE_CLOSED;
1695 return_value = smbd_smb2_request_error(req, session_status);
1696 break;
1699 * This call needs to be run as user.
1701 * smbd_smb2_request_check_tcon()
1702 * calls change_to_user() on success.
1704 status = smbd_smb2_request_check_tcon(req);
1705 if (!NT_STATUS_IS_OK(status)) {
1706 /* Too ugly to live ? JRA. */
1707 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1708 status = NT_STATUS_FILE_CLOSED;
1710 return_value = smbd_smb2_request_error(req, status);
1711 break;
1715 START_PROFILE(smb2_lock);
1716 return_value = smbd_smb2_request_process_lock(req);
1717 END_PROFILE(smb2_lock);
1719 break;
1721 case SMB2_OP_IOCTL:
1722 if (!NT_STATUS_IS_OK(session_status)) {
1723 return_value = smbd_smb2_request_error(req, session_status);
1724 break;
1727 * This call needs to be run as user.
1729 * smbd_smb2_request_check_tcon()
1730 * calls change_to_user() on success.
1732 status = smbd_smb2_request_check_tcon(req);
1733 if (!NT_STATUS_IS_OK(status)) {
1734 return_value = smbd_smb2_request_error(req, status);
1735 break;
1739 START_PROFILE(smb2_ioctl);
1740 return_value = smbd_smb2_request_process_ioctl(req);
1741 END_PROFILE(smb2_ioctl);
1743 break;
1745 case SMB2_OP_CANCEL:
1747 * This call needs to be run as root
1749 * That is what we also do in the SMB1 case.
1751 change_to_root_user();
1754 START_PROFILE(smb2_cancel);
1755 return_value = smbd_smb2_request_process_cancel(req);
1756 END_PROFILE(smb2_cancel);
1758 break;
1760 case SMB2_OP_KEEPALIVE:
1761 /* This call needs to be run as root */
1762 change_to_root_user();
1765 START_PROFILE(smb2_keepalive);
1766 return_value = smbd_smb2_request_process_keepalive(req);
1767 END_PROFILE(smb2_keepalive);
1769 break;
1771 case SMB2_OP_FIND:
1772 if (!NT_STATUS_IS_OK(session_status)) {
1773 return_value = smbd_smb2_request_error(req, session_status);
1774 break;
1777 * This call needs to be run as user.
1779 * smbd_smb2_request_check_tcon()
1780 * calls change_to_user() on success.
1782 status = smbd_smb2_request_check_tcon(req);
1783 if (!NT_STATUS_IS_OK(status)) {
1784 return_value = smbd_smb2_request_error(req, status);
1785 break;
1789 START_PROFILE(smb2_find);
1790 return_value = smbd_smb2_request_process_find(req);
1791 END_PROFILE(smb2_find);
1793 break;
1795 case SMB2_OP_NOTIFY:
1796 if (!NT_STATUS_IS_OK(session_status)) {
1797 return_value = smbd_smb2_request_error(req, session_status);
1798 break;
1801 * This call needs to be run as user.
1803 * smbd_smb2_request_check_tcon()
1804 * calls change_to_user() on success.
1806 status = smbd_smb2_request_check_tcon(req);
1807 if (!NT_STATUS_IS_OK(status)) {
1808 return_value = smbd_smb2_request_error(req, status);
1809 break;
1813 START_PROFILE(smb2_notify);
1814 return_value = smbd_smb2_request_process_notify(req);
1815 END_PROFILE(smb2_notify);
1817 break;
1819 case SMB2_OP_GETINFO:
1820 if (!NT_STATUS_IS_OK(session_status)) {
1821 return_value = smbd_smb2_request_error(req, session_status);
1822 break;
1825 * This call needs to be run as user.
1827 * smbd_smb2_request_check_tcon()
1828 * calls change_to_user() on success.
1830 status = smbd_smb2_request_check_tcon(req);
1831 if (!NT_STATUS_IS_OK(status)) {
1832 return_value = smbd_smb2_request_error(req, status);
1833 break;
1837 START_PROFILE(smb2_getinfo);
1838 return_value = smbd_smb2_request_process_getinfo(req);
1839 END_PROFILE(smb2_getinfo);
1841 break;
1843 case SMB2_OP_SETINFO:
1844 if (!NT_STATUS_IS_OK(session_status)) {
1845 return_value = smbd_smb2_request_error(req, session_status);
1846 break;
1849 * This call needs to be run as user.
1851 * smbd_smb2_request_check_tcon()
1852 * calls change_to_user() on success.
1854 status = smbd_smb2_request_check_tcon(req);
1855 if (!NT_STATUS_IS_OK(status)) {
1856 return_value = smbd_smb2_request_error(req, status);
1857 break;
1861 START_PROFILE(smb2_setinfo);
1862 return_value = smbd_smb2_request_process_setinfo(req);
1863 END_PROFILE(smb2_setinfo);
1865 break;
1867 case SMB2_OP_BREAK:
1868 if (!NT_STATUS_IS_OK(session_status)) {
1869 return_value = smbd_smb2_request_error(req, session_status);
1870 break;
1873 * This call needs to be run as user.
1875 * smbd_smb2_request_check_tcon()
1876 * calls change_to_user() on success.
1878 status = smbd_smb2_request_check_tcon(req);
1879 if (!NT_STATUS_IS_OK(status)) {
1880 return_value = smbd_smb2_request_error(req, status);
1881 break;
1885 START_PROFILE(smb2_break);
1886 return_value = smbd_smb2_request_process_break(req);
1887 END_PROFILE(smb2_break);
1889 break;
1891 default:
1892 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1893 break;
1895 return return_value;
1898 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1900 struct tevent_req *subreq;
1901 int i = req->current_idx;
1903 req->subreq = NULL;
1904 TALLOC_FREE(req->async_te);
1906 req->current_idx += 3;
1908 if (req->current_idx < req->out.vector_count) {
1910 * We must process the remaining compound
1911 * SMB2 requests before any new incoming SMB2
1912 * requests. This is because incoming SMB2
1913 * requests may include a cancel for a
1914 * compound request we haven't processed
1915 * yet.
1917 struct tevent_immediate *im = tevent_create_immediate(req);
1918 if (!im) {
1919 return NT_STATUS_NO_MEMORY;
1921 tevent_schedule_immediate(im,
1922 req->sconn->ev_ctx,
1923 smbd_smb2_request_dispatch_immediate,
1924 req);
1925 return NT_STATUS_OK;
1928 if (req->compound_related) {
1929 req->sconn->smb2.compound_related_in_progress = false;
1932 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1934 /* Set credit for these operations (zero credits if this
1935 is a final reply for an async operation). */
1936 smb2_calculate_credits(req, req);
1938 if (req->do_signing) {
1939 NTSTATUS status;
1940 status = smb2_signing_sign_pdu(req->session->session_key,
1941 get_Protocol(),
1942 &req->out.vector[i], 3);
1943 if (!NT_STATUS_IS_OK(status)) {
1944 return status;
1948 if (DEBUGLEVEL >= 10) {
1949 dbgtext("smbd_smb2_request_reply: sending...\n");
1950 print_req_vectors(req);
1953 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1954 if (req->out.vector_count == 4 &&
1955 req->out.vector[3].iov_base == NULL &&
1956 req->out.vector[3].iov_len != 0) {
1957 /* Dynamic part is NULL. Chop it off,
1958 We're going to send it via sendfile. */
1959 req->out.vector_count -= 1;
1962 subreq = tstream_writev_queue_send(req,
1963 req->sconn->ev_ctx,
1964 req->sconn->smb2.stream,
1965 req->sconn->smb2.send_queue,
1966 req->out.vector,
1967 req->out.vector_count);
1968 if (subreq == NULL) {
1969 return NT_STATUS_NO_MEMORY;
1971 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1973 * We're done with this request -
1974 * move it off the "being processed" queue.
1976 DLIST_REMOVE(req->sconn->smb2.requests, req);
1978 return NT_STATUS_OK;
1981 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
1983 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1984 struct tevent_immediate *im,
1985 void *private_data)
1987 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1988 struct smbd_smb2_request);
1989 struct smbd_server_connection *sconn = req->sconn;
1990 NTSTATUS status;
1992 TALLOC_FREE(im);
1994 if (DEBUGLEVEL >= 10) {
1995 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1996 req->current_idx, req->in.vector_count));
1997 print_req_vectors(req);
2000 status = smbd_smb2_request_dispatch(req);
2001 if (!NT_STATUS_IS_OK(status)) {
2002 smbd_server_connection_terminate(sconn, nt_errstr(status));
2003 return;
2006 status = smbd_smb2_request_next_incoming(sconn);
2007 if (!NT_STATUS_IS_OK(status)) {
2008 smbd_server_connection_terminate(sconn, nt_errstr(status));
2009 return;
2013 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
2015 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
2016 struct smbd_smb2_request);
2017 struct smbd_server_connection *sconn = req->sconn;
2018 int ret;
2019 int sys_errno;
2020 NTSTATUS status;
2022 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2023 TALLOC_FREE(subreq);
2024 TALLOC_FREE(req);
2025 if (ret == -1) {
2026 status = map_nt_error_from_unix(sys_errno);
2027 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2028 nt_errstr(status)));
2029 smbd_server_connection_terminate(sconn, nt_errstr(status));
2030 return;
2033 status = smbd_smb2_request_next_incoming(sconn);
2034 if (!NT_STATUS_IS_OK(status)) {
2035 smbd_server_connection_terminate(sconn, nt_errstr(status));
2036 return;
2040 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2041 NTSTATUS status,
2042 DATA_BLOB body, DATA_BLOB *dyn,
2043 const char *location)
2045 uint8_t *outhdr;
2046 int i = req->current_idx;
2047 uint32_t next_command_ofs;
2049 DEBUG(10,("smbd_smb2_request_done_ex: "
2050 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2051 i, nt_errstr(status), (unsigned int)body.length,
2052 dyn ? "yes": "no",
2053 (unsigned int)(dyn ? dyn->length : 0),
2054 location));
2056 if (body.length < 2) {
2057 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2060 if ((body.length % 2) != 0) {
2061 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2064 outhdr = (uint8_t *)req->out.vector[i].iov_base;
2066 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2067 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2069 req->out.vector[i+1].iov_base = (void *)body.data;
2070 req->out.vector[i+1].iov_len = body.length;
2072 if (dyn) {
2073 req->out.vector[i+2].iov_base = (void *)dyn->data;
2074 req->out.vector[i+2].iov_len = dyn->length;
2075 } else {
2076 req->out.vector[i+2].iov_base = NULL;
2077 req->out.vector[i+2].iov_len = 0;
2080 /* see if we need to recalculate the offset to the next response */
2081 if (next_command_ofs > 0) {
2082 next_command_ofs = SMB2_HDR_BODY;
2083 next_command_ofs += req->out.vector[i+1].iov_len;
2084 next_command_ofs += req->out.vector[i+2].iov_len;
2087 if ((next_command_ofs % 8) != 0) {
2088 size_t pad_size = 8 - (next_command_ofs % 8);
2089 if (req->out.vector[i+2].iov_len == 0) {
2091 * if the dyn buffer is empty
2092 * we can use it to add padding
2094 uint8_t *pad;
2096 pad = talloc_zero_array(req->out.vector,
2097 uint8_t, pad_size);
2098 if (pad == NULL) {
2099 return smbd_smb2_request_error(req,
2100 NT_STATUS_NO_MEMORY);
2103 req->out.vector[i+2].iov_base = (void *)pad;
2104 req->out.vector[i+2].iov_len = pad_size;
2105 } else {
2107 * For now we copy the dynamic buffer
2108 * and add the padding to the new buffer
2110 size_t old_size;
2111 uint8_t *old_dyn;
2112 size_t new_size;
2113 uint8_t *new_dyn;
2115 old_size = req->out.vector[i+2].iov_len;
2116 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2118 new_size = old_size + pad_size;
2119 new_dyn = talloc_zero_array(req->out.vector,
2120 uint8_t, new_size);
2121 if (new_dyn == NULL) {
2122 return smbd_smb2_request_error(req,
2123 NT_STATUS_NO_MEMORY);
2126 memcpy(new_dyn, old_dyn, old_size);
2127 memset(new_dyn + old_size, 0, pad_size);
2129 req->out.vector[i+2].iov_base = (void *)new_dyn;
2130 req->out.vector[i+2].iov_len = new_size;
2132 next_command_ofs += pad_size;
2135 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2137 return smbd_smb2_request_reply(req);
2140 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2141 NTSTATUS status,
2142 DATA_BLOB *info,
2143 const char *location)
2145 DATA_BLOB body;
2146 int i = req->current_idx;
2147 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
2149 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2150 i, nt_errstr(status), info ? " +info" : "",
2151 location));
2153 body.data = outhdr + SMB2_HDR_BODY;
2154 body.length = 8;
2155 SSVAL(body.data, 0, 9);
2157 if (info) {
2158 SIVAL(body.data, 0x04, info->length);
2159 } else {
2160 /* Allocated size of req->out.vector[i].iov_base
2161 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2162 * 1 byte without having to do an alloc.
2164 info = talloc_zero_array(req->out.vector,
2165 DATA_BLOB,
2167 if (!info) {
2168 return NT_STATUS_NO_MEMORY;
2170 info->data = ((uint8_t *)outhdr) +
2171 OUTVEC_ALLOC_SIZE - 1;
2172 info->length = 1;
2173 SCVAL(info->data, 0, 0);
2177 * if a request fails, all other remaining
2178 * compounded requests should fail too
2180 req->next_status = NT_STATUS_INVALID_PARAMETER;
2182 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2186 struct smbd_smb2_send_oplock_break_state {
2187 struct smbd_server_connection *sconn;
2188 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2189 struct iovec vector;
2192 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2194 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2195 uint64_t file_id_persistent,
2196 uint64_t file_id_volatile,
2197 uint8_t oplock_level)
2199 struct smbd_smb2_send_oplock_break_state *state;
2200 struct tevent_req *subreq;
2201 uint8_t *hdr;
2202 uint8_t *body;
2204 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2205 if (state == NULL) {
2206 return NT_STATUS_NO_MEMORY;
2208 state->sconn = sconn;
2210 state->vector.iov_base = (void *)state->buf;
2211 state->vector.iov_len = sizeof(state->buf);
2213 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2214 hdr = state->buf + 4;
2215 body = hdr + SMB2_HDR_BODY;
2217 SIVAL(hdr, 0, SMB2_MAGIC);
2218 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2219 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2220 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2221 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2222 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2223 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2224 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2225 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2226 SIVAL(hdr, SMB2_HDR_PID, 0);
2227 SIVAL(hdr, SMB2_HDR_TID, 0);
2228 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2229 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2231 SSVAL(body, 0x00, 0x18);
2233 SCVAL(body, 0x02, oplock_level);
2234 SCVAL(body, 0x03, 0); /* reserved */
2235 SIVAL(body, 0x04, 0); /* reserved */
2236 SBVAL(body, 0x08, file_id_persistent);
2237 SBVAL(body, 0x10, file_id_volatile);
2239 subreq = tstream_writev_queue_send(state,
2240 sconn->ev_ctx,
2241 sconn->smb2.stream,
2242 sconn->smb2.send_queue,
2243 &state->vector, 1);
2244 if (subreq == NULL) {
2245 return NT_STATUS_NO_MEMORY;
2247 tevent_req_set_callback(subreq,
2248 smbd_smb2_oplock_break_writev_done,
2249 state);
2251 return NT_STATUS_OK;
2254 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2256 struct smbd_smb2_send_oplock_break_state *state =
2257 tevent_req_callback_data(subreq,
2258 struct smbd_smb2_send_oplock_break_state);
2259 struct smbd_server_connection *sconn = state->sconn;
2260 int ret;
2261 int sys_errno;
2263 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2264 TALLOC_FREE(subreq);
2265 if (ret == -1) {
2266 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2267 smbd_server_connection_terminate(sconn, nt_errstr(status));
2268 return;
2271 TALLOC_FREE(state);
2274 struct smbd_smb2_request_read_state {
2275 size_t missing;
2276 bool asked_for_header;
2277 struct smbd_smb2_request *smb2_req;
2280 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2281 void *private_data,
2282 TALLOC_CTX *mem_ctx,
2283 struct iovec **_vector,
2284 size_t *_count);
2285 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2287 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2288 struct tevent_context *ev,
2289 struct smbd_server_connection *sconn)
2291 struct tevent_req *req;
2292 struct smbd_smb2_request_read_state *state;
2293 struct tevent_req *subreq;
2295 req = tevent_req_create(mem_ctx, &state,
2296 struct smbd_smb2_request_read_state);
2297 if (req == NULL) {
2298 return NULL;
2300 state->missing = 0;
2301 state->asked_for_header = false;
2303 state->smb2_req = smbd_smb2_request_allocate(state);
2304 if (tevent_req_nomem(state->smb2_req, req)) {
2305 return tevent_req_post(req, ev);
2307 state->smb2_req->sconn = sconn;
2309 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2310 sconn->smb2.recv_queue,
2311 smbd_smb2_request_next_vector,
2312 state);
2313 if (tevent_req_nomem(subreq, req)) {
2314 return tevent_req_post(req, ev);
2316 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2318 return req;
2321 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2322 void *private_data,
2323 TALLOC_CTX *mem_ctx,
2324 struct iovec **_vector,
2325 size_t *_count)
2327 struct smbd_smb2_request_read_state *state =
2328 talloc_get_type_abort(private_data,
2329 struct smbd_smb2_request_read_state);
2330 struct smbd_smb2_request *req = state->smb2_req;
2331 struct iovec *vector;
2332 int idx = req->in.vector_count;
2333 size_t len = 0;
2334 uint8_t *buf = NULL;
2336 if (req->in.vector_count == 0) {
2338 * first we need to get the NBT header
2340 req->in.vector = talloc_array(req, struct iovec,
2341 req->in.vector_count + 1);
2342 if (req->in.vector == NULL) {
2343 return -1;
2345 req->in.vector_count += 1;
2347 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2348 req->in.vector[idx].iov_len = 4;
2350 vector = talloc_array(mem_ctx, struct iovec, 1);
2351 if (vector == NULL) {
2352 return -1;
2355 vector[0] = req->in.vector[idx];
2357 *_vector = vector;
2358 *_count = 1;
2359 return 0;
2362 if (req->in.vector_count == 1) {
2364 * Now we analyze the NBT header
2366 state->missing = smb2_len(req->in.vector[0].iov_base);
2368 if (state->missing == 0) {
2369 /* if there're no remaining bytes, we're done */
2370 *_vector = NULL;
2371 *_count = 0;
2372 return 0;
2375 req->in.vector = talloc_realloc(req, req->in.vector,
2376 struct iovec,
2377 req->in.vector_count + 1);
2378 if (req->in.vector == NULL) {
2379 return -1;
2381 req->in.vector_count += 1;
2383 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2385 * it's a special NBT message,
2386 * so get all remaining bytes
2388 len = state->missing;
2389 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2391 * it's an invalid message, just read what we can get
2392 * and let the caller handle the error
2394 len = state->missing;
2395 } else {
2397 * We assume it's a SMB2 request,
2398 * and we first get the header and the
2399 * first 2 bytes (the struct size) of the body
2401 len = SMB2_HDR_BODY + 2;
2403 state->asked_for_header = true;
2406 state->missing -= len;
2408 buf = talloc_array(req->in.vector, uint8_t, len);
2409 if (buf == NULL) {
2410 return -1;
2413 req->in.vector[idx].iov_base = (void *)buf;
2414 req->in.vector[idx].iov_len = len;
2416 vector = talloc_array(mem_ctx, struct iovec, 1);
2417 if (vector == NULL) {
2418 return -1;
2421 vector[0] = req->in.vector[idx];
2423 *_vector = vector;
2424 *_count = 1;
2425 return 0;
2428 if (state->missing == 0) {
2429 /* if there're no remaining bytes, we're done */
2430 *_vector = NULL;
2431 *_count = 0;
2432 return 0;
2435 if (state->asked_for_header) {
2436 const uint8_t *hdr;
2437 size_t full_size;
2438 size_t next_command_ofs;
2439 size_t body_size;
2440 uint8_t *body;
2441 size_t dyn_size;
2442 uint8_t *dyn;
2443 bool invalid = false;
2445 state->asked_for_header = false;
2448 * We got the SMB2 header and the first 2 bytes
2449 * of the body. We fix the size to just the header
2450 * and manually copy the 2 first bytes to the body section
2452 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2453 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2455 /* allocate vectors for body and dynamic areas */
2456 req->in.vector = talloc_realloc(req, req->in.vector,
2457 struct iovec,
2458 req->in.vector_count + 2);
2459 if (req->in.vector == NULL) {
2460 return -1;
2462 req->in.vector_count += 2;
2464 full_size = state->missing + SMB2_HDR_BODY + 2;
2465 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2466 body_size = SVAL(hdr, SMB2_HDR_BODY);
2468 if (next_command_ofs != 0) {
2469 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2471 * this is invalid, just return a zero
2472 * body and let the caller deal with the error
2474 invalid = true;
2475 } else if (next_command_ofs > full_size) {
2477 * this is invalid, just return a zero
2478 * body and let the caller deal with the error
2480 invalid = true;
2481 } else {
2482 full_size = next_command_ofs;
2486 if (!invalid) {
2487 if (body_size < 2) {
2489 * this is invalid, just return a zero
2490 * body and let the caller deal with the error
2492 invalid = true;
2496 * Mask out the lowest bit, the "dynamic" part
2497 * of body_size.
2499 body_size &= ~1;
2501 if (body_size > (full_size - SMB2_HDR_BODY)) {
2503 * this is invalid, just return a zero
2504 * body and let the caller deal with the error
2506 invalid = true;
2510 if (invalid) {
2511 /* the caller should check this */
2512 body_size = 2;
2515 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2517 state->missing -= (body_size - 2) + dyn_size;
2519 body = talloc_array(req->in.vector, uint8_t, body_size);
2520 if (body == NULL) {
2521 return -1;
2524 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2525 if (dyn == NULL) {
2526 return -1;
2529 req->in.vector[idx].iov_base = (void *)body;
2530 req->in.vector[idx].iov_len = body_size;
2531 req->in.vector[idx+1].iov_base = (void *)dyn;
2532 req->in.vector[idx+1].iov_len = dyn_size;
2534 vector = talloc_array(mem_ctx, struct iovec, 2);
2535 if (vector == NULL) {
2536 return -1;
2540 * the first 2 bytes of the body were already fetched
2541 * together with the header
2543 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2544 vector[0].iov_base = body + 2;
2545 vector[0].iov_len = body_size - 2;
2547 vector[1] = req->in.vector[idx+1];
2549 *_vector = vector;
2550 *_count = 2;
2551 return 0;
2555 * when we endup here, we're looking for a new SMB2 request
2556 * next. And we ask for its header and the first 2 bytes of
2557 * the body (like we did for the first SMB2 request).
2560 req->in.vector = talloc_realloc(req, req->in.vector,
2561 struct iovec,
2562 req->in.vector_count + 1);
2563 if (req->in.vector == NULL) {
2564 return -1;
2566 req->in.vector_count += 1;
2569 * We assume it's a SMB2 request,
2570 * and we first get the header and the
2571 * first 2 bytes (the struct size) of the body
2573 len = SMB2_HDR_BODY + 2;
2575 if (len > state->missing) {
2576 /* let the caller handle the error */
2577 len = state->missing;
2580 state->missing -= len;
2581 state->asked_for_header = true;
2583 buf = talloc_array(req->in.vector, uint8_t, len);
2584 if (buf == NULL) {
2585 return -1;
2588 req->in.vector[idx].iov_base = (void *)buf;
2589 req->in.vector[idx].iov_len = len;
2591 vector = talloc_array(mem_ctx, struct iovec, 1);
2592 if (vector == NULL) {
2593 return -1;
2596 vector[0] = req->in.vector[idx];
2598 *_vector = vector;
2599 *_count = 1;
2600 return 0;
2603 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2605 struct tevent_req *req =
2606 tevent_req_callback_data(subreq,
2607 struct tevent_req);
2608 int ret;
2609 int sys_errno;
2610 NTSTATUS status;
2612 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2613 if (ret == -1) {
2614 status = map_nt_error_from_unix(sys_errno);
2615 tevent_req_nterror(req, status);
2616 return;
2619 tevent_req_done(req);
2622 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2623 TALLOC_CTX *mem_ctx,
2624 struct smbd_smb2_request **_smb2_req)
2626 struct smbd_smb2_request_read_state *state =
2627 tevent_req_data(req,
2628 struct smbd_smb2_request_read_state);
2629 NTSTATUS status;
2631 if (tevent_req_is_nterror(req, &status)) {
2632 tevent_req_received(req);
2633 return status;
2636 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2637 *_smb2_req = state->smb2_req;
2638 tevent_req_received(req);
2639 return NT_STATUS_OK;
2642 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2644 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2646 size_t max_send_queue_len;
2647 size_t cur_send_queue_len;
2648 struct tevent_req *subreq;
2650 if (sconn->smb2.compound_related_in_progress) {
2652 * Can't read another until the related
2653 * compound is done.
2655 return NT_STATUS_OK;
2658 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2660 * if there is already a smbd_smb2_request_read
2661 * pending, we are done.
2663 return NT_STATUS_OK;
2666 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2667 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2669 if (cur_send_queue_len > max_send_queue_len) {
2671 * if we have a lot of requests to send,
2672 * we wait until they are on the wire until we
2673 * ask for the next request.
2675 return NT_STATUS_OK;
2678 /* ask for the next request */
2679 subreq = smbd_smb2_request_read_send(sconn, sconn->ev_ctx, sconn);
2680 if (subreq == NULL) {
2681 return NT_STATUS_NO_MEMORY;
2683 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2685 return NT_STATUS_OK;
2688 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2689 const uint8_t *inbuf, size_t size)
2691 NTSTATUS status;
2692 struct smbd_smb2_request *req = NULL;
2694 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2695 (unsigned int)size));
2697 status = smbd_initialize_smb2(sconn);
2698 if (!NT_STATUS_IS_OK(status)) {
2699 smbd_server_connection_terminate(sconn, nt_errstr(status));
2700 return;
2703 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2704 if (!NT_STATUS_IS_OK(status)) {
2705 smbd_server_connection_terminate(sconn, nt_errstr(status));
2706 return;
2709 status = smbd_smb2_request_setup_out(req);
2710 if (!NT_STATUS_IS_OK(status)) {
2711 smbd_server_connection_terminate(sconn, nt_errstr(status));
2712 return;
2715 status = smbd_smb2_request_dispatch(req);
2716 if (!NT_STATUS_IS_OK(status)) {
2717 smbd_server_connection_terminate(sconn, nt_errstr(status));
2718 return;
2721 status = smbd_smb2_request_next_incoming(sconn);
2722 if (!NT_STATUS_IS_OK(status)) {
2723 smbd_server_connection_terminate(sconn, nt_errstr(status));
2724 return;
2727 sconn->num_requests++;
2730 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2732 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2733 struct smbd_server_connection);
2734 NTSTATUS status;
2735 struct smbd_smb2_request *req = NULL;
2737 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2738 TALLOC_FREE(subreq);
2739 if (!NT_STATUS_IS_OK(status)) {
2740 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2741 nt_errstr(status)));
2742 smbd_server_connection_terminate(sconn, nt_errstr(status));
2743 return;
2746 if (req->in.nbt_hdr[0] != 0x00) {
2747 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2748 req->in.nbt_hdr[0]));
2749 TALLOC_FREE(req);
2750 goto next;
2753 req->current_idx = 1;
2755 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2756 req->current_idx, req->in.vector_count));
2758 status = smbd_smb2_request_validate(req);
2759 if (!NT_STATUS_IS_OK(status)) {
2760 smbd_server_connection_terminate(sconn, nt_errstr(status));
2761 return;
2764 status = smbd_smb2_request_setup_out(req);
2765 if (!NT_STATUS_IS_OK(status)) {
2766 smbd_server_connection_terminate(sconn, nt_errstr(status));
2767 return;
2770 status = smbd_smb2_request_dispatch(req);
2771 if (!NT_STATUS_IS_OK(status)) {
2772 smbd_server_connection_terminate(sconn, nt_errstr(status));
2773 return;
2776 next:
2777 status = smbd_smb2_request_next_incoming(sconn);
2778 if (!NT_STATUS_IS_OK(status)) {
2779 smbd_server_connection_terminate(sconn, nt_errstr(status));
2780 return;
2783 sconn->num_requests++;
2785 /* The timeout_processing function isn't run nearly
2786 often enough to implement 'max log size' without
2787 overrunning the size of the file by many megabytes.
2788 This is especially true if we are running at debug
2789 level 10. Checking every 50 SMB2s is a nice
2790 tradeoff of performance vs log file size overrun. */
2792 if ((sconn->num_requests % 50) == 0 &&
2793 need_to_check_log_size()) {
2794 change_to_root_user();
2795 check_log_size();