s3: Fix a 64-bit warning
[Samba/gebeck_regimport.git] / source3 / smbd / smb2_server.c
blob617081895f561a64df835a5bde865b7be2045f96
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 count = req->in.vector_count;
575 vector = talloc_zero_array(req, struct iovec, count);
576 if (vector == NULL) {
577 return NT_STATUS_NO_MEMORY;
580 vector[0].iov_base = req->out.nbt_hdr;
581 vector[0].iov_len = 4;
582 SIVAL(req->out.nbt_hdr, 0, 0);
584 for (idx=1; idx < count; idx += 3) {
585 const uint8_t *inhdr = NULL;
586 uint8_t *outhdr = NULL;
587 uint8_t *outbody = NULL;
588 uint32_t next_command_ofs = 0;
589 struct iovec *current = &vector[idx];
591 if ((idx + 3) < count) {
592 /* we have a next command -
593 * setup for the error case. */
594 next_command_ofs = SMB2_HDR_BODY + 9;
597 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
599 outhdr = talloc_zero_array(vector, uint8_t,
600 OUTVEC_ALLOC_SIZE);
601 if (outhdr == NULL) {
602 return NT_STATUS_NO_MEMORY;
605 outbody = outhdr + SMB2_HDR_BODY;
607 current[0].iov_base = (void *)outhdr;
608 current[0].iov_len = SMB2_HDR_BODY;
610 current[1].iov_base = (void *)outbody;
611 current[1].iov_len = 8;
613 current[2].iov_base = NULL;
614 current[2].iov_len = 0;
616 /* setup the SMB2 header */
617 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
618 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
619 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
620 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
621 SIVAL(outhdr, SMB2_HDR_STATUS,
622 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
623 SSVAL(outhdr, SMB2_HDR_OPCODE,
624 SVAL(inhdr, SMB2_HDR_OPCODE));
625 SIVAL(outhdr, SMB2_HDR_FLAGS,
626 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
627 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
628 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
629 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
630 SIVAL(outhdr, SMB2_HDR_PID,
631 IVAL(inhdr, SMB2_HDR_PID));
632 SIVAL(outhdr, SMB2_HDR_TID,
633 IVAL(inhdr, SMB2_HDR_TID));
634 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
635 BVAL(inhdr, SMB2_HDR_SESSION_ID));
636 memcpy(outhdr + SMB2_HDR_SIGNATURE,
637 inhdr + SMB2_HDR_SIGNATURE, 16);
639 /* setup error body header */
640 SSVAL(outbody, 0x00, 0x08 + 1);
641 SSVAL(outbody, 0x02, 0);
642 SIVAL(outbody, 0x04, 0);
645 req->out.vector = vector;
646 req->out.vector_count = count;
648 /* setup the length of the NBT packet */
649 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
651 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
653 return NT_STATUS_OK;
656 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
657 const char *reason,
658 const char *location)
660 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
661 reason, location));
662 exit_server_cleanly(reason);
665 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
666 struct iovec *outvec,
667 const struct iovec *srcvec)
669 /* vec[0] is always boilerplate and must
670 * be allocated with size OUTVEC_ALLOC_SIZE. */
672 outvec[0].iov_base = talloc_memdup(ctx,
673 srcvec[0].iov_base,
674 OUTVEC_ALLOC_SIZE);
675 if (!outvec[0].iov_base) {
676 return false;
678 outvec[0].iov_len = SMB2_HDR_BODY;
681 * If this is a "standard" vec[1] of length 8,
682 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
683 * then duplicate this. Else use talloc_memdup().
686 if (srcvec[1].iov_len == 8 &&
687 srcvec[1].iov_base ==
688 ((uint8_t *)srcvec[0].iov_base) +
689 SMB2_HDR_BODY) {
690 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
691 SMB2_HDR_BODY;
692 outvec[1].iov_len = 8;
693 } else {
694 outvec[1].iov_base = talloc_memdup(ctx,
695 srcvec[1].iov_base,
696 srcvec[1].iov_len);
697 if (!outvec[1].iov_base) {
698 return false;
700 outvec[1].iov_len = srcvec[1].iov_len;
704 * If this is a "standard" vec[2] of length 1,
705 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
706 * then duplicate this. Else use talloc_memdup().
709 if (srcvec[2].iov_base &&
710 srcvec[2].iov_len) {
711 if (srcvec[2].iov_base ==
712 ((uint8_t *)srcvec[0].iov_base) +
713 (OUTVEC_ALLOC_SIZE - 1) &&
714 srcvec[2].iov_len == 1) {
715 /* Common SMB2 error packet case. */
716 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
717 (OUTVEC_ALLOC_SIZE - 1);
718 } else {
719 outvec[2].iov_base = talloc_memdup(ctx,
720 srcvec[2].iov_base,
721 srcvec[2].iov_len);
722 if (!outvec[2].iov_base) {
723 return false;
726 outvec[2].iov_len = srcvec[2].iov_len;
727 } else {
728 outvec[2].iov_base = NULL;
729 outvec[2].iov_len = 0;
731 return true;
734 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
736 struct smbd_smb2_request *newreq = NULL;
737 struct iovec *outvec = NULL;
738 int count = req->out.vector_count;
739 int i;
741 newreq = smbd_smb2_request_allocate(req->sconn);
742 if (!newreq) {
743 return NULL;
746 newreq->sconn = req->sconn;
747 newreq->session = req->session;
748 newreq->do_signing = req->do_signing;
749 newreq->current_idx = req->current_idx;
751 outvec = talloc_zero_array(newreq, struct iovec, count);
752 if (!outvec) {
753 TALLOC_FREE(newreq);
754 return NULL;
756 newreq->out.vector = outvec;
757 newreq->out.vector_count = count;
759 /* Setup the outvec's identically to req. */
760 outvec[0].iov_base = newreq->out.nbt_hdr;
761 outvec[0].iov_len = 4;
762 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
764 /* Setup the vectors identically to the ones in req. */
765 for (i = 1; i < count; i += 3) {
766 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
767 break;
771 if (i < count) {
772 /* Alloc failed. */
773 TALLOC_FREE(newreq);
774 return NULL;
777 smb2_setup_nbt_length(newreq->out.vector,
778 newreq->out.vector_count);
780 return newreq;
783 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
785 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
787 int i = 0;
788 uint8_t *outhdr = NULL;
789 struct smbd_smb2_request *nreq = NULL;
791 /* Create a new smb2 request we'll use
792 for the interim return. */
793 nreq = dup_smb2_req(req);
794 if (!nreq) {
795 return NT_STATUS_NO_MEMORY;
798 /* Lose the last 3 out vectors. They're the
799 ones we'll be using for the async reply. */
800 nreq->out.vector_count -= 3;
802 smb2_setup_nbt_length(nreq->out.vector,
803 nreq->out.vector_count);
805 /* Step back to the previous reply. */
806 i = nreq->current_idx - 3;
807 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
808 /* And end the chain. */
809 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
811 /* Calculate outgoing credits */
812 smb2_calculate_credits(req, nreq);
814 /* Re-sign if needed. */
815 if (nreq->do_signing) {
816 NTSTATUS status;
817 status = smb2_signing_sign_pdu(nreq->session->session_key,
818 get_Protocol(),
819 &nreq->out.vector[i], 3);
820 if (!NT_STATUS_IS_OK(status)) {
821 return status;
824 if (DEBUGLEVEL >= 10) {
825 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
826 (unsigned int)nreq->current_idx );
827 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
828 (unsigned int)nreq->out.vector_count );
829 print_req_vectors(nreq);
831 nreq->subreq = tstream_writev_queue_send(nreq,
832 nreq->sconn->ev_ctx,
833 nreq->sconn->smb2.stream,
834 nreq->sconn->smb2.send_queue,
835 nreq->out.vector,
836 nreq->out.vector_count);
838 if (nreq->subreq == NULL) {
839 return NT_STATUS_NO_MEMORY;
842 tevent_req_set_callback(nreq->subreq,
843 smbd_smb2_request_writev_done,
844 nreq);
846 return NT_STATUS_OK;
849 struct smbd_smb2_request_pending_state {
850 struct smbd_server_connection *sconn;
851 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
852 struct iovec vector[3];
855 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
857 struct smbd_smb2_request_pending_state *state =
858 tevent_req_callback_data(subreq,
859 struct smbd_smb2_request_pending_state);
860 struct smbd_server_connection *sconn = state->sconn;
861 int ret;
862 int sys_errno;
864 ret = tstream_writev_queue_recv(subreq, &sys_errno);
865 TALLOC_FREE(subreq);
866 if (ret == -1) {
867 NTSTATUS status = map_nt_error_from_unix(sys_errno);
868 smbd_server_connection_terminate(sconn, nt_errstr(status));
869 return;
872 TALLOC_FREE(state);
875 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
876 struct tevent_timer *te,
877 struct timeval current_time,
878 void *private_data);
880 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
881 struct tevent_req *subreq,
882 uint32_t defer_time)
884 NTSTATUS status;
885 int i = req->current_idx;
886 struct timeval defer_endtime;
887 uint8_t *outhdr = NULL;
888 uint32_t flags;
890 if (!tevent_req_is_in_progress(subreq)) {
891 return NT_STATUS_OK;
894 req->subreq = subreq;
895 subreq = NULL;
897 if (req->async_te) {
898 /* We're already async. */
899 return NT_STATUS_OK;
902 outhdr = (uint8_t *)req->out.vector[i].iov_base;
903 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
904 if (flags & SMB2_HDR_FLAG_ASYNC) {
905 /* We're already async. */
906 return NT_STATUS_OK;
909 if (req->in.vector_count > i + 3) {
911 * We're trying to go async in a compound
912 * request chain. This is not allowed.
913 * Cancel the outstanding request.
915 tevent_req_cancel(req->subreq);
916 return smbd_smb2_request_error(req,
917 NT_STATUS_INSUFFICIENT_RESOURCES);
920 if (DEBUGLEVEL >= 10) {
921 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
922 (unsigned int)req->current_idx );
923 print_req_vectors(req);
926 if (req->out.vector_count > 4) {
927 struct iovec *outvec = NULL;
929 /* This is a compound reply. We
930 * must do an interim response
931 * followed by the async response
932 * to match W2K8R2.
934 status = smb2_send_async_interim_response(req);
935 if (!NT_STATUS_IS_OK(status)) {
936 return status;
940 * We're splitting off the last SMB2
941 * request in a compound set, and the
942 * smb2_send_async_interim_response()
943 * call above just sent all the replies
944 * for the previous SMB2 requests in
945 * this compound set. So we're no longer
946 * in the "compound_related_in_progress"
947 * state, and this is no longer a compound
948 * request.
950 req->compound_related = false;
951 req->sconn->smb2.compound_related_in_progress = false;
953 /* Re-arrange the in.vectors. */
954 req->in.vector[1] = req->in.vector[i];
955 req->in.vector[2] = req->in.vector[i+1];
956 req->in.vector[3] = req->in.vector[i+2];
957 req->in.vector_count = 4;
959 /* Reset the new in size. */
960 smb2_setup_nbt_length(req->in.vector, 4);
962 /* Now recreate the out.vectors. */
963 outvec = talloc_zero_array(req, struct iovec, 4);
964 if (!outvec) {
965 return NT_STATUS_NO_MEMORY;
968 /* 0 is always boilerplate and must
969 * be of size 4 for the length field. */
971 outvec[0].iov_base = req->out.nbt_hdr;
972 outvec[0].iov_len = 4;
973 SIVAL(req->out.nbt_hdr, 0, 0);
975 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
976 return NT_STATUS_NO_MEMORY;
979 TALLOC_FREE(req->out.vector);
981 req->out.vector = outvec;
983 req->current_idx = 1;
984 req->out.vector_count = 4;
986 outhdr = (uint8_t *)req->out.vector[1].iov_base;
987 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
988 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
991 defer_endtime = timeval_current_ofs_usec(defer_time);
992 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
993 req, defer_endtime,
994 smbd_smb2_request_pending_timer,
995 req);
996 if (req->async_te == NULL) {
997 return NT_STATUS_NO_MEMORY;
1000 return NT_STATUS_OK;
1003 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1004 struct tevent_timer *te,
1005 struct timeval current_time,
1006 void *private_data)
1008 struct smbd_smb2_request *req =
1009 talloc_get_type_abort(private_data,
1010 struct smbd_smb2_request);
1011 struct smbd_smb2_request_pending_state *state = NULL;
1012 int i = req->current_idx;
1013 uint8_t *outhdr = NULL;
1014 const uint8_t *inhdr = NULL;
1015 uint8_t *hdr = NULL;
1016 uint8_t *body = NULL;
1017 uint32_t flags = 0;
1018 uint64_t message_id = 0;
1019 uint64_t async_id = 0;
1020 struct tevent_req *subreq = NULL;
1022 TALLOC_FREE(req->async_te);
1024 /* Ensure our final reply matches the interim one. */
1025 inhdr = (const uint8_t *)req->in.vector[1].iov_base;
1026 outhdr = (uint8_t *)req->out.vector[1].iov_base;
1027 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1028 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1030 async_id = message_id; /* keep it simple for now... */
1032 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1033 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1035 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1036 "going async\n",
1037 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1038 (unsigned long long)async_id ));
1041 * What we send is identical to a smbd_smb2_request_error
1042 * packet with an error status of STATUS_PENDING. Make use
1043 * of this fact sometime when refactoring. JRA.
1046 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1047 if (state == NULL) {
1048 smbd_server_connection_terminate(req->sconn,
1049 nt_errstr(NT_STATUS_NO_MEMORY));
1050 return;
1052 state->sconn = req->sconn;
1054 state->vector[0].iov_base = (void *)state->buf;
1055 state->vector[0].iov_len = 4;
1057 state->vector[1].iov_base = state->buf + 4;
1058 state->vector[1].iov_len = SMB2_HDR_BODY;
1060 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
1061 state->vector[2].iov_len = 9;
1063 smb2_setup_nbt_length(state->vector, 3);
1065 hdr = (uint8_t *)state->vector[1].iov_base;
1066 body = (uint8_t *)state->vector[2].iov_base;
1068 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1069 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1070 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1071 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1072 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1074 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1075 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1076 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1077 SBVAL(hdr, SMB2_HDR_PID, async_id);
1078 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1079 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1080 memcpy(hdr+SMB2_HDR_SIGNATURE,
1081 outhdr+SMB2_HDR_SIGNATURE, 16);
1083 SSVAL(body, 0x00, 0x08 + 1);
1085 SCVAL(body, 0x02, 0);
1086 SCVAL(body, 0x03, 0);
1087 SIVAL(body, 0x04, 0);
1088 /* Match W2K8R2... */
1089 SCVAL(body, 0x08, 0x21);
1091 /* Ensure we correctly go through crediting. Grant
1092 the credits now, and zero credits on the final
1093 response. */
1094 smb2_set_operation_credit(req->sconn,
1095 &req->in.vector[i],
1096 &state->vector[1]);
1098 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1100 if (req->do_signing) {
1101 NTSTATUS status;
1103 status = smb2_signing_sign_pdu(req->session->session_key,
1104 get_Protocol(),
1105 &state->vector[1], 2);
1106 if (!NT_STATUS_IS_OK(status)) {
1107 smbd_server_connection_terminate(req->sconn,
1108 nt_errstr(status));
1109 return;
1113 subreq = tstream_writev_queue_send(state,
1114 state->sconn->ev_ctx,
1115 state->sconn->smb2.stream,
1116 state->sconn->smb2.send_queue,
1117 state->vector,
1119 if (subreq == NULL) {
1120 smbd_server_connection_terminate(state->sconn,
1121 nt_errstr(NT_STATUS_NO_MEMORY));
1122 return;
1124 tevent_req_set_callback(subreq,
1125 smbd_smb2_request_pending_writev_done,
1126 state);
1129 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1131 struct smbd_server_connection *sconn = req->sconn;
1132 struct smbd_smb2_request *cur;
1133 const uint8_t *inhdr;
1134 int i = req->current_idx;
1135 uint32_t flags;
1136 uint64_t search_message_id;
1137 uint64_t search_async_id;
1138 uint64_t found_id;
1140 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1142 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1143 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1144 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1147 * we don't need the request anymore
1148 * cancel requests never have a response
1150 DLIST_REMOVE(req->sconn->smb2.requests, req);
1151 TALLOC_FREE(req);
1153 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1154 const uint8_t *outhdr;
1155 uint64_t message_id;
1156 uint64_t async_id;
1158 i = cur->current_idx;
1160 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1162 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1163 async_id = BVAL(outhdr, SMB2_HDR_PID);
1165 if (flags & SMB2_HDR_FLAG_ASYNC) {
1166 if (search_async_id == async_id) {
1167 found_id = async_id;
1168 break;
1170 } else {
1171 if (search_message_id == message_id) {
1172 found_id = message_id;
1173 break;
1178 if (cur && cur->subreq) {
1179 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1180 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1181 "cancel opcode[%s] mid %llu\n",
1182 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1183 (unsigned long long)found_id ));
1184 tevent_req_cancel(cur->subreq);
1187 return NT_STATUS_OK;
1190 /*************************************************************
1191 Ensure an incoming tid is a valid one for us to access.
1192 Change to the associated uid credentials and chdir to the
1193 valid tid directory.
1194 *************************************************************/
1196 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1198 const uint8_t *inhdr;
1199 int i = req->current_idx;
1200 uint32_t in_flags;
1201 uint32_t in_tid;
1202 void *p;
1203 struct smbd_smb2_tcon *tcon;
1205 req->tcon = NULL;
1207 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1209 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1210 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1212 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1213 in_tid = req->last_tid;
1216 /* lookup an existing session */
1217 p = idr_find(req->session->tcons.idtree, in_tid);
1218 if (p == NULL) {
1219 return NT_STATUS_NETWORK_NAME_DELETED;
1221 tcon = talloc_get_type_abort(p, struct smbd_smb2_tcon);
1223 if (!change_to_user(tcon->compat_conn,req->session->vuid)) {
1224 return NT_STATUS_ACCESS_DENIED;
1227 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1228 if (!set_current_service(tcon->compat_conn, 0, true)) {
1229 return NT_STATUS_ACCESS_DENIED;
1232 req->tcon = tcon;
1233 req->last_tid = in_tid;
1235 return NT_STATUS_OK;
1238 /*************************************************************
1239 Ensure an incoming session_id is a valid one for us to access.
1240 *************************************************************/
1242 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1244 const uint8_t *inhdr;
1245 int i = req->current_idx;
1246 uint32_t in_flags;
1247 uint64_t in_session_id;
1248 void *p;
1249 struct smbd_smb2_session *session;
1251 req->session = NULL;
1252 req->tcon = NULL;
1254 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1256 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1257 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1259 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1260 in_session_id = req->last_session_id;
1263 /* lookup an existing session */
1264 p = idr_find(req->sconn->smb2.sessions.idtree, in_session_id);
1265 if (p == NULL) {
1266 return NT_STATUS_USER_SESSION_DELETED;
1268 session = talloc_get_type_abort(p, struct smbd_smb2_session);
1270 if (!NT_STATUS_IS_OK(session->status)) {
1271 return NT_STATUS_ACCESS_DENIED;
1274 set_current_user_info(session->session_info->unix_info->sanitized_username,
1275 session->session_info->unix_info->unix_name,
1276 session->session_info->info->domain_name);
1278 req->session = session;
1279 req->last_session_id = in_session_id;
1281 return NT_STATUS_OK;
1284 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1285 uint32_t data_length)
1287 uint16_t needed_charge;
1288 uint16_t credit_charge;
1289 const uint8_t *inhdr;
1290 int i = req->current_idx;
1292 if (!req->sconn->smb2.supports_multicredit) {
1293 if (data_length > 65536) {
1294 return NT_STATUS_INVALID_PARAMETER;
1296 return NT_STATUS_OK;
1299 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1300 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1302 /* requests larger than 64 KB need credit charge */
1303 if (credit_charge == 0 && data_length > 65536) {
1304 DEBUG(2, ("Request larger than 64KB w/o creditcharge\n"));
1305 return NT_STATUS_INVALID_PARAMETER;
1308 needed_charge = (data_length - 1)/ 65536 + 1;
1310 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1311 BVAL(inhdr, SMB2_HDR_MESSAGE_ID), credit_charge,
1312 needed_charge));
1314 if (needed_charge > credit_charge) {
1315 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1316 credit_charge, needed_charge));
1317 return NT_STATUS_INVALID_PARAMETER;
1320 return NT_STATUS_OK;
1323 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1324 size_t expected_body_size)
1326 const uint8_t *inhdr;
1327 uint16_t opcode;
1328 const uint8_t *inbody;
1329 int i = req->current_idx;
1330 size_t body_size;
1331 size_t min_dyn_size = expected_body_size & 0x00000001;
1334 * The following should be checked already.
1336 if ((i+2) > req->in.vector_count) {
1337 return NT_STATUS_INTERNAL_ERROR;
1339 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1340 return NT_STATUS_INTERNAL_ERROR;
1342 if (req->in.vector[i+1].iov_len < 2) {
1343 return NT_STATUS_INTERNAL_ERROR;
1346 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1347 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1349 switch (opcode) {
1350 case SMB2_OP_IOCTL:
1351 case SMB2_OP_GETINFO:
1352 min_dyn_size = 0;
1353 break;
1357 * Now check the expected body size,
1358 * where the last byte might be in the
1359 * dynamic section..
1361 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1362 return NT_STATUS_INVALID_PARAMETER;
1364 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1365 return NT_STATUS_INVALID_PARAMETER;
1368 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1370 body_size = SVAL(inbody, 0x00);
1371 if (body_size != expected_body_size) {
1372 return NT_STATUS_INVALID_PARAMETER;
1375 return NT_STATUS_OK;
1378 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1380 const uint8_t *inhdr;
1381 int i = req->current_idx;
1382 uint16_t opcode;
1383 uint32_t flags;
1384 uint64_t mid;
1385 NTSTATUS status;
1386 NTSTATUS session_status;
1387 uint32_t allowed_flags;
1388 NTSTATUS return_value;
1390 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1392 /* TODO: verify more things */
1394 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1395 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1396 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1397 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1398 smb2_opcode_name(opcode),
1399 (unsigned long long)mid));
1401 if (get_Protocol() >= PROTOCOL_SMB2_02) {
1403 * once the protocol is negotiated
1404 * SMB2_OP_NEGPROT is not allowed anymore
1406 if (opcode == SMB2_OP_NEGPROT) {
1407 /* drop the connection */
1408 return NT_STATUS_INVALID_PARAMETER;
1410 } else {
1412 * if the protocol is not negotiated yet
1413 * only SMB2_OP_NEGPROT is allowed.
1415 if (opcode != SMB2_OP_NEGPROT) {
1416 /* drop the connection */
1417 return NT_STATUS_INVALID_PARAMETER;
1421 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1422 SMB2_HDR_FLAG_SIGNED |
1423 SMB2_HDR_FLAG_DFS;
1424 if (opcode == SMB2_OP_CANCEL) {
1425 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1427 if ((flags & ~allowed_flags) != 0) {
1428 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1432 * Check if the client provided a valid session id,
1433 * if so smbd_smb2_request_check_session() calls
1434 * set_current_user_info().
1436 * As some command don't require a valid session id
1437 * we defer the check of the session_status
1439 session_status = smbd_smb2_request_check_session(req);
1441 req->do_signing = false;
1442 if (flags & SMB2_HDR_FLAG_SIGNED) {
1443 if (!NT_STATUS_IS_OK(session_status)) {
1444 return smbd_smb2_request_error(req, session_status);
1447 req->do_signing = true;
1448 status = smb2_signing_check_pdu(req->session->session_key,
1449 get_Protocol(),
1450 &req->in.vector[i], 3);
1451 if (!NT_STATUS_IS_OK(status)) {
1452 return smbd_smb2_request_error(req, status);
1454 } else if (opcode == SMB2_OP_CANCEL) {
1455 /* Cancel requests are allowed to skip the signing */
1456 } else if (req->session && req->session->do_signing) {
1457 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1460 if (flags & SMB2_HDR_FLAG_CHAINED) {
1462 * This check is mostly for giving the correct error code
1463 * for compounded requests.
1465 * TODO: we may need to move this after the session
1466 * and tcon checks.
1468 if (!NT_STATUS_IS_OK(req->next_status)) {
1469 return smbd_smb2_request_error(req, req->next_status);
1471 } else {
1472 req->compat_chain_fsp = NULL;
1475 if (req->compound_related) {
1476 req->sconn->smb2.compound_related_in_progress = true;
1479 switch (opcode) {
1480 case SMB2_OP_NEGPROT:
1481 /* This call needs to be run as root */
1482 change_to_root_user();
1485 START_PROFILE(smb2_negprot);
1486 return_value = smbd_smb2_request_process_negprot(req);
1487 END_PROFILE(smb2_negprot);
1489 break;
1491 case SMB2_OP_SESSSETUP:
1492 /* This call needs to be run as root */
1493 change_to_root_user();
1496 START_PROFILE(smb2_sesssetup);
1497 return_value = smbd_smb2_request_process_sesssetup(req);
1498 END_PROFILE(smb2_sesssetup);
1500 break;
1502 case SMB2_OP_LOGOFF:
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 root */
1509 change_to_root_user();
1512 START_PROFILE(smb2_logoff);
1513 return_value = smbd_smb2_request_process_logoff(req);
1514 END_PROFILE(smb2_logoff);
1516 break;
1518 case SMB2_OP_TCON:
1519 if (!NT_STATUS_IS_OK(session_status)) {
1520 return_value = smbd_smb2_request_error(req, session_status);
1521 break;
1525 * This call needs to be run as root.
1527 * smbd_smb2_request_process_tcon()
1528 * calls make_connection_snum(), which will call
1529 * change_to_user(), when needed.
1531 change_to_root_user();
1534 START_PROFILE(smb2_tcon);
1535 return_value = smbd_smb2_request_process_tcon(req);
1536 END_PROFILE(smb2_tcon);
1538 break;
1540 case SMB2_OP_TDIS:
1541 if (!NT_STATUS_IS_OK(session_status)) {
1542 return_value = smbd_smb2_request_error(req, session_status);
1543 break;
1546 * This call needs to be run as user.
1548 * smbd_smb2_request_check_tcon()
1549 * calls change_to_user() on success.
1551 status = smbd_smb2_request_check_tcon(req);
1552 if (!NT_STATUS_IS_OK(status)) {
1553 return_value = smbd_smb2_request_error(req, status);
1554 break;
1556 /* This call needs to be run as root */
1557 change_to_root_user();
1561 START_PROFILE(smb2_tdis);
1562 return_value = smbd_smb2_request_process_tdis(req);
1563 END_PROFILE(smb2_tdis);
1565 break;
1567 case SMB2_OP_CREATE:
1568 if (!NT_STATUS_IS_OK(session_status)) {
1569 return_value = smbd_smb2_request_error(req, session_status);
1570 break;
1573 * This call needs to be run as user.
1575 * smbd_smb2_request_check_tcon()
1576 * calls change_to_user() on success.
1578 status = smbd_smb2_request_check_tcon(req);
1579 if (!NT_STATUS_IS_OK(status)) {
1580 return_value = smbd_smb2_request_error(req, status);
1581 break;
1585 START_PROFILE(smb2_create);
1586 return_value = smbd_smb2_request_process_create(req);
1587 END_PROFILE(smb2_create);
1589 break;
1591 case SMB2_OP_CLOSE:
1592 if (!NT_STATUS_IS_OK(session_status)) {
1593 return_value = smbd_smb2_request_error(req, session_status);
1594 break;
1597 * This call needs to be run as user.
1599 * smbd_smb2_request_check_tcon()
1600 * calls change_to_user() on success.
1602 status = smbd_smb2_request_check_tcon(req);
1603 if (!NT_STATUS_IS_OK(status)) {
1604 return_value = smbd_smb2_request_error(req, status);
1605 break;
1609 START_PROFILE(smb2_close);
1610 return_value = smbd_smb2_request_process_close(req);
1611 END_PROFILE(smb2_close);
1613 break;
1615 case SMB2_OP_FLUSH:
1616 if (!NT_STATUS_IS_OK(session_status)) {
1617 return_value = smbd_smb2_request_error(req, session_status);
1618 break;
1621 * This call needs to be run as user.
1623 * smbd_smb2_request_check_tcon()
1624 * calls change_to_user() on success.
1626 status = smbd_smb2_request_check_tcon(req);
1627 if (!NT_STATUS_IS_OK(status)) {
1628 return_value = smbd_smb2_request_error(req, status);
1629 break;
1633 START_PROFILE(smb2_flush);
1634 return_value = smbd_smb2_request_process_flush(req);
1635 END_PROFILE(smb2_flush);
1637 break;
1639 case SMB2_OP_READ:
1640 if (!NT_STATUS_IS_OK(session_status)) {
1641 return_value = smbd_smb2_request_error(req, session_status);
1642 break;
1645 * This call needs to be run as user.
1647 * smbd_smb2_request_check_tcon()
1648 * calls change_to_user() on success.
1650 status = smbd_smb2_request_check_tcon(req);
1651 if (!NT_STATUS_IS_OK(status)) {
1652 return_value = smbd_smb2_request_error(req, status);
1653 break;
1657 START_PROFILE(smb2_read);
1658 return_value = smbd_smb2_request_process_read(req);
1659 END_PROFILE(smb2_read);
1661 break;
1663 case SMB2_OP_WRITE:
1664 if (!NT_STATUS_IS_OK(session_status)) {
1665 return_value = smbd_smb2_request_error(req, session_status);
1666 break;
1669 * This call needs to be run as user.
1671 * smbd_smb2_request_check_tcon()
1672 * calls change_to_user() on success.
1674 status = smbd_smb2_request_check_tcon(req);
1675 if (!NT_STATUS_IS_OK(status)) {
1676 return_value = smbd_smb2_request_error(req, status);
1677 break;
1681 START_PROFILE(smb2_write);
1682 return_value = smbd_smb2_request_process_write(req);
1683 END_PROFILE(smb2_write);
1685 break;
1687 case SMB2_OP_LOCK:
1688 if (!NT_STATUS_IS_OK(session_status)) {
1689 /* Too ugly to live ? JRA. */
1690 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1691 session_status = NT_STATUS_FILE_CLOSED;
1693 return_value = smbd_smb2_request_error(req, session_status);
1694 break;
1697 * This call needs to be run as user.
1699 * smbd_smb2_request_check_tcon()
1700 * calls change_to_user() on success.
1702 status = smbd_smb2_request_check_tcon(req);
1703 if (!NT_STATUS_IS_OK(status)) {
1704 /* Too ugly to live ? JRA. */
1705 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1706 status = NT_STATUS_FILE_CLOSED;
1708 return_value = smbd_smb2_request_error(req, status);
1709 break;
1713 START_PROFILE(smb2_lock);
1714 return_value = smbd_smb2_request_process_lock(req);
1715 END_PROFILE(smb2_lock);
1717 break;
1719 case SMB2_OP_IOCTL:
1720 if (!NT_STATUS_IS_OK(session_status)) {
1721 return_value = smbd_smb2_request_error(req, session_status);
1722 break;
1725 * This call needs to be run as user.
1727 * smbd_smb2_request_check_tcon()
1728 * calls change_to_user() on success.
1730 status = smbd_smb2_request_check_tcon(req);
1731 if (!NT_STATUS_IS_OK(status)) {
1732 return_value = smbd_smb2_request_error(req, status);
1733 break;
1737 START_PROFILE(smb2_ioctl);
1738 return_value = smbd_smb2_request_process_ioctl(req);
1739 END_PROFILE(smb2_ioctl);
1741 break;
1743 case SMB2_OP_CANCEL:
1745 * This call needs to be run as root
1747 * That is what we also do in the SMB1 case.
1749 change_to_root_user();
1752 START_PROFILE(smb2_cancel);
1753 return_value = smbd_smb2_request_process_cancel(req);
1754 END_PROFILE(smb2_cancel);
1756 break;
1758 case SMB2_OP_KEEPALIVE:
1759 /* This call needs to be run as root */
1760 change_to_root_user();
1763 START_PROFILE(smb2_keepalive);
1764 return_value = smbd_smb2_request_process_keepalive(req);
1765 END_PROFILE(smb2_keepalive);
1767 break;
1769 case SMB2_OP_FIND:
1770 if (!NT_STATUS_IS_OK(session_status)) {
1771 return_value = smbd_smb2_request_error(req, session_status);
1772 break;
1775 * This call needs to be run as user.
1777 * smbd_smb2_request_check_tcon()
1778 * calls change_to_user() on success.
1780 status = smbd_smb2_request_check_tcon(req);
1781 if (!NT_STATUS_IS_OK(status)) {
1782 return_value = smbd_smb2_request_error(req, status);
1783 break;
1787 START_PROFILE(smb2_find);
1788 return_value = smbd_smb2_request_process_find(req);
1789 END_PROFILE(smb2_find);
1791 break;
1793 case SMB2_OP_NOTIFY:
1794 if (!NT_STATUS_IS_OK(session_status)) {
1795 return_value = smbd_smb2_request_error(req, session_status);
1796 break;
1799 * This call needs to be run as user.
1801 * smbd_smb2_request_check_tcon()
1802 * calls change_to_user() on success.
1804 status = smbd_smb2_request_check_tcon(req);
1805 if (!NT_STATUS_IS_OK(status)) {
1806 return_value = smbd_smb2_request_error(req, status);
1807 break;
1811 START_PROFILE(smb2_notify);
1812 return_value = smbd_smb2_request_process_notify(req);
1813 END_PROFILE(smb2_notify);
1815 break;
1817 case SMB2_OP_GETINFO:
1818 if (!NT_STATUS_IS_OK(session_status)) {
1819 return_value = smbd_smb2_request_error(req, session_status);
1820 break;
1823 * This call needs to be run as user.
1825 * smbd_smb2_request_check_tcon()
1826 * calls change_to_user() on success.
1828 status = smbd_smb2_request_check_tcon(req);
1829 if (!NT_STATUS_IS_OK(status)) {
1830 return_value = smbd_smb2_request_error(req, status);
1831 break;
1835 START_PROFILE(smb2_getinfo);
1836 return_value = smbd_smb2_request_process_getinfo(req);
1837 END_PROFILE(smb2_getinfo);
1839 break;
1841 case SMB2_OP_SETINFO:
1842 if (!NT_STATUS_IS_OK(session_status)) {
1843 return_value = smbd_smb2_request_error(req, session_status);
1844 break;
1847 * This call needs to be run as user.
1849 * smbd_smb2_request_check_tcon()
1850 * calls change_to_user() on success.
1852 status = smbd_smb2_request_check_tcon(req);
1853 if (!NT_STATUS_IS_OK(status)) {
1854 return_value = smbd_smb2_request_error(req, status);
1855 break;
1859 START_PROFILE(smb2_setinfo);
1860 return_value = smbd_smb2_request_process_setinfo(req);
1861 END_PROFILE(smb2_setinfo);
1863 break;
1865 case SMB2_OP_BREAK:
1866 if (!NT_STATUS_IS_OK(session_status)) {
1867 return_value = smbd_smb2_request_error(req, session_status);
1868 break;
1871 * This call needs to be run as user.
1873 * smbd_smb2_request_check_tcon()
1874 * calls change_to_user() on success.
1876 status = smbd_smb2_request_check_tcon(req);
1877 if (!NT_STATUS_IS_OK(status)) {
1878 return_value = smbd_smb2_request_error(req, status);
1879 break;
1883 START_PROFILE(smb2_break);
1884 return_value = smbd_smb2_request_process_break(req);
1885 END_PROFILE(smb2_break);
1887 break;
1889 default:
1890 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1891 break;
1893 return return_value;
1896 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1898 struct tevent_req *subreq;
1899 int i = req->current_idx;
1901 req->subreq = NULL;
1902 TALLOC_FREE(req->async_te);
1904 req->current_idx += 3;
1906 if (req->current_idx < req->out.vector_count) {
1908 * We must process the remaining compound
1909 * SMB2 requests before any new incoming SMB2
1910 * requests. This is because incoming SMB2
1911 * requests may include a cancel for a
1912 * compound request we haven't processed
1913 * yet.
1915 struct tevent_immediate *im = tevent_create_immediate(req);
1916 if (!im) {
1917 return NT_STATUS_NO_MEMORY;
1919 tevent_schedule_immediate(im,
1920 req->sconn->ev_ctx,
1921 smbd_smb2_request_dispatch_immediate,
1922 req);
1923 return NT_STATUS_OK;
1926 if (req->compound_related) {
1927 req->sconn->smb2.compound_related_in_progress = false;
1930 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1932 /* Set credit for these operations (zero credits if this
1933 is a final reply for an async operation). */
1934 smb2_calculate_credits(req, req);
1936 if (req->do_signing) {
1937 NTSTATUS status;
1938 status = smb2_signing_sign_pdu(req->session->session_key,
1939 get_Protocol(),
1940 &req->out.vector[i], 3);
1941 if (!NT_STATUS_IS_OK(status)) {
1942 return status;
1946 if (DEBUGLEVEL >= 10) {
1947 dbgtext("smbd_smb2_request_reply: sending...\n");
1948 print_req_vectors(req);
1951 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1952 if (req->out.vector_count == 4 &&
1953 req->out.vector[3].iov_base == NULL &&
1954 req->out.vector[3].iov_len != 0) {
1955 /* Dynamic part is NULL. Chop it off,
1956 We're going to send it via sendfile. */
1957 req->out.vector_count -= 1;
1960 subreq = tstream_writev_queue_send(req,
1961 req->sconn->ev_ctx,
1962 req->sconn->smb2.stream,
1963 req->sconn->smb2.send_queue,
1964 req->out.vector,
1965 req->out.vector_count);
1966 if (subreq == NULL) {
1967 return NT_STATUS_NO_MEMORY;
1969 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1971 * We're done with this request -
1972 * move it off the "being processed" queue.
1974 DLIST_REMOVE(req->sconn->smb2.requests, req);
1976 return NT_STATUS_OK;
1979 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
1981 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1982 struct tevent_immediate *im,
1983 void *private_data)
1985 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1986 struct smbd_smb2_request);
1987 struct smbd_server_connection *sconn = req->sconn;
1988 NTSTATUS status;
1990 TALLOC_FREE(im);
1992 if (DEBUGLEVEL >= 10) {
1993 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1994 req->current_idx, req->in.vector_count));
1995 print_req_vectors(req);
1998 status = smbd_smb2_request_dispatch(req);
1999 if (!NT_STATUS_IS_OK(status)) {
2000 smbd_server_connection_terminate(sconn, nt_errstr(status));
2001 return;
2004 status = smbd_smb2_request_next_incoming(sconn);
2005 if (!NT_STATUS_IS_OK(status)) {
2006 smbd_server_connection_terminate(sconn, nt_errstr(status));
2007 return;
2011 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
2013 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
2014 struct smbd_smb2_request);
2015 struct smbd_server_connection *sconn = req->sconn;
2016 int ret;
2017 int sys_errno;
2018 NTSTATUS status;
2020 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2021 TALLOC_FREE(subreq);
2022 TALLOC_FREE(req);
2023 if (ret == -1) {
2024 status = map_nt_error_from_unix(sys_errno);
2025 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2026 nt_errstr(status)));
2027 smbd_server_connection_terminate(sconn, nt_errstr(status));
2028 return;
2031 status = smbd_smb2_request_next_incoming(sconn);
2032 if (!NT_STATUS_IS_OK(status)) {
2033 smbd_server_connection_terminate(sconn, nt_errstr(status));
2034 return;
2038 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2039 NTSTATUS status,
2040 DATA_BLOB body, DATA_BLOB *dyn,
2041 const char *location)
2043 uint8_t *outhdr;
2044 int i = req->current_idx;
2045 uint32_t next_command_ofs;
2047 DEBUG(10,("smbd_smb2_request_done_ex: "
2048 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2049 i, nt_errstr(status), (unsigned int)body.length,
2050 dyn ? "yes": "no",
2051 (unsigned int)(dyn ? dyn->length : 0),
2052 location));
2054 if (body.length < 2) {
2055 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2058 if ((body.length % 2) != 0) {
2059 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2062 outhdr = (uint8_t *)req->out.vector[i].iov_base;
2064 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2065 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2067 req->out.vector[i+1].iov_base = (void *)body.data;
2068 req->out.vector[i+1].iov_len = body.length;
2070 if (dyn) {
2071 req->out.vector[i+2].iov_base = (void *)dyn->data;
2072 req->out.vector[i+2].iov_len = dyn->length;
2073 } else {
2074 req->out.vector[i+2].iov_base = NULL;
2075 req->out.vector[i+2].iov_len = 0;
2078 /* see if we need to recalculate the offset to the next response */
2079 if (next_command_ofs > 0) {
2080 next_command_ofs = SMB2_HDR_BODY;
2081 next_command_ofs += req->out.vector[i+1].iov_len;
2082 next_command_ofs += req->out.vector[i+2].iov_len;
2085 if ((next_command_ofs % 8) != 0) {
2086 size_t pad_size = 8 - (next_command_ofs % 8);
2087 if (req->out.vector[i+2].iov_len == 0) {
2089 * if the dyn buffer is empty
2090 * we can use it to add padding
2092 uint8_t *pad;
2094 pad = talloc_zero_array(req->out.vector,
2095 uint8_t, pad_size);
2096 if (pad == NULL) {
2097 return smbd_smb2_request_error(req,
2098 NT_STATUS_NO_MEMORY);
2101 req->out.vector[i+2].iov_base = (void *)pad;
2102 req->out.vector[i+2].iov_len = pad_size;
2103 } else {
2105 * For now we copy the dynamic buffer
2106 * and add the padding to the new buffer
2108 size_t old_size;
2109 uint8_t *old_dyn;
2110 size_t new_size;
2111 uint8_t *new_dyn;
2113 old_size = req->out.vector[i+2].iov_len;
2114 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2116 new_size = old_size + pad_size;
2117 new_dyn = talloc_zero_array(req->out.vector,
2118 uint8_t, new_size);
2119 if (new_dyn == NULL) {
2120 return smbd_smb2_request_error(req,
2121 NT_STATUS_NO_MEMORY);
2124 memcpy(new_dyn, old_dyn, old_size);
2125 memset(new_dyn + old_size, 0, pad_size);
2127 req->out.vector[i+2].iov_base = (void *)new_dyn;
2128 req->out.vector[i+2].iov_len = new_size;
2130 next_command_ofs += pad_size;
2133 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2135 return smbd_smb2_request_reply(req);
2138 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2139 NTSTATUS status,
2140 DATA_BLOB *info,
2141 const char *location)
2143 DATA_BLOB body;
2144 int i = req->current_idx;
2145 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
2147 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2148 i, nt_errstr(status), info ? " +info" : "",
2149 location));
2151 body.data = outhdr + SMB2_HDR_BODY;
2152 body.length = 8;
2153 SSVAL(body.data, 0, 9);
2155 if (info) {
2156 SIVAL(body.data, 0x04, info->length);
2157 } else {
2158 /* Allocated size of req->out.vector[i].iov_base
2159 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2160 * 1 byte without having to do an alloc.
2162 info = talloc_zero_array(req->out.vector,
2163 DATA_BLOB,
2165 if (!info) {
2166 return NT_STATUS_NO_MEMORY;
2168 info->data = ((uint8_t *)outhdr) +
2169 OUTVEC_ALLOC_SIZE - 1;
2170 info->length = 1;
2171 SCVAL(info->data, 0, 0);
2175 * if a request fails, all other remaining
2176 * compounded requests should fail too
2178 req->next_status = NT_STATUS_INVALID_PARAMETER;
2180 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2184 struct smbd_smb2_send_oplock_break_state {
2185 struct smbd_server_connection *sconn;
2186 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2187 struct iovec vector;
2190 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2192 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2193 uint64_t file_id_persistent,
2194 uint64_t file_id_volatile,
2195 uint8_t oplock_level)
2197 struct smbd_smb2_send_oplock_break_state *state;
2198 struct tevent_req *subreq;
2199 uint8_t *hdr;
2200 uint8_t *body;
2202 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2203 if (state == NULL) {
2204 return NT_STATUS_NO_MEMORY;
2206 state->sconn = sconn;
2208 state->vector.iov_base = (void *)state->buf;
2209 state->vector.iov_len = sizeof(state->buf);
2211 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2212 hdr = state->buf + 4;
2213 body = hdr + SMB2_HDR_BODY;
2215 SIVAL(hdr, 0, SMB2_MAGIC);
2216 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2217 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2218 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2219 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2220 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2221 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2222 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2223 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2224 SIVAL(hdr, SMB2_HDR_PID, 0);
2225 SIVAL(hdr, SMB2_HDR_TID, 0);
2226 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2227 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2229 SSVAL(body, 0x00, 0x18);
2231 SCVAL(body, 0x02, oplock_level);
2232 SCVAL(body, 0x03, 0); /* reserved */
2233 SIVAL(body, 0x04, 0); /* reserved */
2234 SBVAL(body, 0x08, file_id_persistent);
2235 SBVAL(body, 0x10, file_id_volatile);
2237 subreq = tstream_writev_queue_send(state,
2238 sconn->ev_ctx,
2239 sconn->smb2.stream,
2240 sconn->smb2.send_queue,
2241 &state->vector, 1);
2242 if (subreq == NULL) {
2243 return NT_STATUS_NO_MEMORY;
2245 tevent_req_set_callback(subreq,
2246 smbd_smb2_oplock_break_writev_done,
2247 state);
2249 return NT_STATUS_OK;
2252 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2254 struct smbd_smb2_send_oplock_break_state *state =
2255 tevent_req_callback_data(subreq,
2256 struct smbd_smb2_send_oplock_break_state);
2257 struct smbd_server_connection *sconn = state->sconn;
2258 int ret;
2259 int sys_errno;
2261 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2262 TALLOC_FREE(subreq);
2263 if (ret == -1) {
2264 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2265 smbd_server_connection_terminate(sconn, nt_errstr(status));
2266 return;
2269 TALLOC_FREE(state);
2272 struct smbd_smb2_request_read_state {
2273 size_t missing;
2274 bool asked_for_header;
2275 struct smbd_smb2_request *smb2_req;
2278 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2279 void *private_data,
2280 TALLOC_CTX *mem_ctx,
2281 struct iovec **_vector,
2282 size_t *_count);
2283 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2285 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2286 struct tevent_context *ev,
2287 struct smbd_server_connection *sconn)
2289 struct tevent_req *req;
2290 struct smbd_smb2_request_read_state *state;
2291 struct tevent_req *subreq;
2293 req = tevent_req_create(mem_ctx, &state,
2294 struct smbd_smb2_request_read_state);
2295 if (req == NULL) {
2296 return NULL;
2298 state->missing = 0;
2299 state->asked_for_header = false;
2301 state->smb2_req = smbd_smb2_request_allocate(state);
2302 if (tevent_req_nomem(state->smb2_req, req)) {
2303 return tevent_req_post(req, ev);
2305 state->smb2_req->sconn = sconn;
2307 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2308 sconn->smb2.recv_queue,
2309 smbd_smb2_request_next_vector,
2310 state);
2311 if (tevent_req_nomem(subreq, req)) {
2312 return tevent_req_post(req, ev);
2314 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2316 return req;
2319 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2320 void *private_data,
2321 TALLOC_CTX *mem_ctx,
2322 struct iovec **_vector,
2323 size_t *_count)
2325 struct smbd_smb2_request_read_state *state =
2326 talloc_get_type_abort(private_data,
2327 struct smbd_smb2_request_read_state);
2328 struct smbd_smb2_request *req = state->smb2_req;
2329 struct iovec *vector;
2330 int idx = req->in.vector_count;
2331 size_t len = 0;
2332 uint8_t *buf = NULL;
2334 if (req->in.vector_count == 0) {
2336 * first we need to get the NBT header
2338 req->in.vector = talloc_array(req, struct iovec,
2339 req->in.vector_count + 1);
2340 if (req->in.vector == NULL) {
2341 return -1;
2343 req->in.vector_count += 1;
2345 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2346 req->in.vector[idx].iov_len = 4;
2348 vector = talloc_array(mem_ctx, struct iovec, 1);
2349 if (vector == NULL) {
2350 return -1;
2353 vector[0] = req->in.vector[idx];
2355 *_vector = vector;
2356 *_count = 1;
2357 return 0;
2360 if (req->in.vector_count == 1) {
2362 * Now we analyze the NBT header
2364 state->missing = smb2_len(req->in.vector[0].iov_base);
2366 if (state->missing == 0) {
2367 /* if there're no remaining bytes, we're done */
2368 *_vector = NULL;
2369 *_count = 0;
2370 return 0;
2373 req->in.vector = talloc_realloc(req, req->in.vector,
2374 struct iovec,
2375 req->in.vector_count + 1);
2376 if (req->in.vector == NULL) {
2377 return -1;
2379 req->in.vector_count += 1;
2381 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2383 * it's a special NBT message,
2384 * so get all remaining bytes
2386 len = state->missing;
2387 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2389 * it's an invalid message, just read what we can get
2390 * and let the caller handle the error
2392 len = state->missing;
2393 } else {
2395 * We assume it's a SMB2 request,
2396 * and we first get the header and the
2397 * first 2 bytes (the struct size) of the body
2399 len = SMB2_HDR_BODY + 2;
2401 state->asked_for_header = true;
2404 state->missing -= len;
2406 buf = talloc_array(req->in.vector, uint8_t, len);
2407 if (buf == NULL) {
2408 return -1;
2411 req->in.vector[idx].iov_base = (void *)buf;
2412 req->in.vector[idx].iov_len = len;
2414 vector = talloc_array(mem_ctx, struct iovec, 1);
2415 if (vector == NULL) {
2416 return -1;
2419 vector[0] = req->in.vector[idx];
2421 *_vector = vector;
2422 *_count = 1;
2423 return 0;
2426 if (state->missing == 0) {
2427 /* if there're no remaining bytes, we're done */
2428 *_vector = NULL;
2429 *_count = 0;
2430 return 0;
2433 if (state->asked_for_header) {
2434 const uint8_t *hdr;
2435 size_t full_size;
2436 size_t next_command_ofs;
2437 size_t body_size;
2438 uint8_t *body;
2439 size_t dyn_size;
2440 uint8_t *dyn;
2441 bool invalid = false;
2443 state->asked_for_header = false;
2446 * We got the SMB2 header and the first 2 bytes
2447 * of the body. We fix the size to just the header
2448 * and manually copy the 2 first bytes to the body section
2450 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2451 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2453 /* allocate vectors for body and dynamic areas */
2454 req->in.vector = talloc_realloc(req, req->in.vector,
2455 struct iovec,
2456 req->in.vector_count + 2);
2457 if (req->in.vector == NULL) {
2458 return -1;
2460 req->in.vector_count += 2;
2462 full_size = state->missing + SMB2_HDR_BODY + 2;
2463 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2464 body_size = SVAL(hdr, SMB2_HDR_BODY);
2466 if (next_command_ofs != 0) {
2467 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2469 * this is invalid, just return a zero
2470 * body and let the caller deal with the error
2472 invalid = true;
2473 } else if (next_command_ofs > full_size) {
2475 * this is invalid, just return a zero
2476 * body and let the caller deal with the error
2478 invalid = true;
2479 } else {
2480 full_size = next_command_ofs;
2484 if (!invalid) {
2485 if (body_size < 2) {
2487 * this is invalid, just return a zero
2488 * body and let the caller deal with the error
2490 invalid = true;
2494 * Mask out the lowest bit, the "dynamic" part
2495 * of body_size.
2497 body_size &= ~1;
2499 if (body_size > (full_size - SMB2_HDR_BODY)) {
2501 * this is invalid, just return a zero
2502 * body and let the caller deal with the error
2504 invalid = true;
2508 if (invalid) {
2509 /* the caller should check this */
2510 body_size = 2;
2513 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2515 state->missing -= (body_size - 2) + dyn_size;
2517 body = talloc_array(req->in.vector, uint8_t, body_size);
2518 if (body == NULL) {
2519 return -1;
2522 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2523 if (dyn == NULL) {
2524 return -1;
2527 req->in.vector[idx].iov_base = (void *)body;
2528 req->in.vector[idx].iov_len = body_size;
2529 req->in.vector[idx+1].iov_base = (void *)dyn;
2530 req->in.vector[idx+1].iov_len = dyn_size;
2532 vector = talloc_array(mem_ctx, struct iovec, 2);
2533 if (vector == NULL) {
2534 return -1;
2538 * the first 2 bytes of the body were already fetched
2539 * together with the header
2541 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2542 vector[0].iov_base = body + 2;
2543 vector[0].iov_len = body_size - 2;
2545 vector[1] = req->in.vector[idx+1];
2547 *_vector = vector;
2548 *_count = 2;
2549 return 0;
2553 * when we endup here, we're looking for a new SMB2 request
2554 * next. And we ask for its header and the first 2 bytes of
2555 * the body (like we did for the first SMB2 request).
2558 req->in.vector = talloc_realloc(req, req->in.vector,
2559 struct iovec,
2560 req->in.vector_count + 1);
2561 if (req->in.vector == NULL) {
2562 return -1;
2564 req->in.vector_count += 1;
2567 * We assume it's a SMB2 request,
2568 * and we first get the header and the
2569 * first 2 bytes (the struct size) of the body
2571 len = SMB2_HDR_BODY + 2;
2573 if (len > state->missing) {
2574 /* let the caller handle the error */
2575 len = state->missing;
2578 state->missing -= len;
2579 state->asked_for_header = true;
2581 buf = talloc_array(req->in.vector, uint8_t, len);
2582 if (buf == NULL) {
2583 return -1;
2586 req->in.vector[idx].iov_base = (void *)buf;
2587 req->in.vector[idx].iov_len = len;
2589 vector = talloc_array(mem_ctx, struct iovec, 1);
2590 if (vector == NULL) {
2591 return -1;
2594 vector[0] = req->in.vector[idx];
2596 *_vector = vector;
2597 *_count = 1;
2598 return 0;
2601 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2603 struct tevent_req *req =
2604 tevent_req_callback_data(subreq,
2605 struct tevent_req);
2606 int ret;
2607 int sys_errno;
2608 NTSTATUS status;
2610 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2611 if (ret == -1) {
2612 status = map_nt_error_from_unix(sys_errno);
2613 tevent_req_nterror(req, status);
2614 return;
2617 tevent_req_done(req);
2620 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2621 TALLOC_CTX *mem_ctx,
2622 struct smbd_smb2_request **_smb2_req)
2624 struct smbd_smb2_request_read_state *state =
2625 tevent_req_data(req,
2626 struct smbd_smb2_request_read_state);
2627 NTSTATUS status;
2629 if (tevent_req_is_nterror(req, &status)) {
2630 tevent_req_received(req);
2631 return status;
2634 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2635 *_smb2_req = state->smb2_req;
2636 tevent_req_received(req);
2637 return NT_STATUS_OK;
2640 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2642 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2644 size_t max_send_queue_len;
2645 size_t cur_send_queue_len;
2646 struct tevent_req *subreq;
2648 if (sconn->smb2.compound_related_in_progress) {
2650 * Can't read another until the related
2651 * compound is done.
2653 return NT_STATUS_OK;
2656 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2658 * if there is already a smbd_smb2_request_read
2659 * pending, we are done.
2661 return NT_STATUS_OK;
2664 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2665 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2667 if (cur_send_queue_len > max_send_queue_len) {
2669 * if we have a lot of requests to send,
2670 * we wait until they are on the wire until we
2671 * ask for the next request.
2673 return NT_STATUS_OK;
2676 /* ask for the next request */
2677 subreq = smbd_smb2_request_read_send(sconn, sconn->ev_ctx, sconn);
2678 if (subreq == NULL) {
2679 return NT_STATUS_NO_MEMORY;
2681 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2683 return NT_STATUS_OK;
2686 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2687 const uint8_t *inbuf, size_t size)
2689 NTSTATUS status;
2690 struct smbd_smb2_request *req = NULL;
2692 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2693 (unsigned int)size));
2695 status = smbd_initialize_smb2(sconn);
2696 if (!NT_STATUS_IS_OK(status)) {
2697 smbd_server_connection_terminate(sconn, nt_errstr(status));
2698 return;
2701 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2702 if (!NT_STATUS_IS_OK(status)) {
2703 smbd_server_connection_terminate(sconn, nt_errstr(status));
2704 return;
2707 status = smbd_smb2_request_setup_out(req);
2708 if (!NT_STATUS_IS_OK(status)) {
2709 smbd_server_connection_terminate(sconn, nt_errstr(status));
2710 return;
2713 status = smbd_smb2_request_dispatch(req);
2714 if (!NT_STATUS_IS_OK(status)) {
2715 smbd_server_connection_terminate(sconn, nt_errstr(status));
2716 return;
2719 status = smbd_smb2_request_next_incoming(sconn);
2720 if (!NT_STATUS_IS_OK(status)) {
2721 smbd_server_connection_terminate(sconn, nt_errstr(status));
2722 return;
2725 sconn->num_requests++;
2728 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2730 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2731 struct smbd_server_connection);
2732 NTSTATUS status;
2733 struct smbd_smb2_request *req = NULL;
2735 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2736 TALLOC_FREE(subreq);
2737 if (!NT_STATUS_IS_OK(status)) {
2738 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2739 nt_errstr(status)));
2740 smbd_server_connection_terminate(sconn, nt_errstr(status));
2741 return;
2744 if (req->in.nbt_hdr[0] != 0x00) {
2745 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2746 req->in.nbt_hdr[0]));
2747 TALLOC_FREE(req);
2748 goto next;
2751 req->current_idx = 1;
2753 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2754 req->current_idx, req->in.vector_count));
2756 status = smbd_smb2_request_validate(req);
2757 if (!NT_STATUS_IS_OK(status)) {
2758 smbd_server_connection_terminate(sconn, nt_errstr(status));
2759 return;
2762 status = smbd_smb2_request_setup_out(req);
2763 if (!NT_STATUS_IS_OK(status)) {
2764 smbd_server_connection_terminate(sconn, nt_errstr(status));
2765 return;
2768 status = smbd_smb2_request_dispatch(req);
2769 if (!NT_STATUS_IS_OK(status)) {
2770 smbd_server_connection_terminate(sconn, nt_errstr(status));
2771 return;
2774 next:
2775 status = smbd_smb2_request_next_incoming(sconn);
2776 if (!NT_STATUS_IS_OK(status)) {
2777 smbd_server_connection_terminate(sconn, nt_errstr(status));
2778 return;
2781 sconn->num_requests++;
2783 /* The timeout_processing function isn't run nearly
2784 often enough to implement 'max log size' without
2785 overrunning the size of the file by many megabytes.
2786 This is especially true if we are running at debug
2787 level 10. Checking every 50 SMB2s is a nice
2788 tradeoff of performance vs log file size overrun. */
2790 if ((sconn->num_requests % 50) == 0 &&
2791 need_to_check_log_size()) {
2792 change_to_root_user();
2793 check_log_size();