s4-lsaprc: Don't call lsa_OpenPolicy2 in lsa_LookupNames4.
[Samba/gebeck_regimport.git] / source3 / smbd / smb2_server.c
blob653a038da5e9d1811b23a054fb8d4b7bd941e434
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.seqnum_low = 0;
112 sconn->smb2.seqnum_range = 1;
113 sconn->smb2.credits_granted = 1;
114 sconn->smb2.max_credits = lp_smb2_max_credits();
115 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
116 sconn->smb2.max_credits);
117 if (sconn->smb2.credits_bitmap == NULL) {
118 return NT_STATUS_NO_MEMORY;
121 ret = tstream_bsd_existing_socket(sconn, sconn->sock,
122 &sconn->smb2.stream);
123 if (ret == -1) {
124 status = map_nt_error_from_unix(errno);
125 return status;
128 /* Ensure child is set to non-blocking mode */
129 set_blocking(sconn->sock, false);
130 return NT_STATUS_OK;
133 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
134 #define _smb2_setlen(_buf,len) do { \
135 uint8_t *buf = (uint8_t *)_buf; \
136 buf[0] = 0; \
137 buf[1] = ((len)&0xFF0000)>>16; \
138 buf[2] = ((len)&0xFF00)>>8; \
139 buf[3] = (len)&0xFF; \
140 } while (0)
142 static void smb2_setup_nbt_length(struct iovec *vector, int count)
144 size_t len = 0;
145 int i;
147 for (i=1; i < count; i++) {
148 len += vector[i].iov_len;
151 _smb2_setlen(vector[0].iov_base, len);
154 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request **req)
156 if (*req) {
157 (*req)->parent = NULL;
158 (*req)->mem_pool = NULL;
161 return 0;
164 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
166 if (req->parent) {
167 *req->parent = NULL;
168 talloc_free(req->mem_pool);
171 return 0;
174 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
176 TALLOC_CTX *mem_pool;
177 struct smbd_smb2_request **parent;
178 struct smbd_smb2_request *req;
180 #if 0
181 /* Enable this to find subtle valgrind errors. */
182 mem_pool = talloc_init("smbd_smb2_request_allocate");
183 #else
184 mem_pool = talloc_pool(mem_ctx, 8192);
185 #endif
186 if (mem_pool == NULL) {
187 return NULL;
190 parent = talloc(mem_pool, struct smbd_smb2_request *);
191 if (parent == NULL) {
192 talloc_free(mem_pool);
193 return NULL;
196 req = talloc_zero(parent, struct smbd_smb2_request);
197 if (req == NULL) {
198 talloc_free(mem_pool);
199 return NULL;
201 *parent = req;
202 req->mem_pool = mem_pool;
203 req->parent = parent;
205 req->last_session_id = UINT64_MAX;
206 req->last_tid = UINT32_MAX;
208 talloc_set_destructor(parent, smbd_smb2_request_parent_destructor);
209 talloc_set_destructor(req, smbd_smb2_request_destructor);
211 return req;
214 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
215 const uint8_t *inbuf, size_t size,
216 struct smbd_smb2_request **_req)
218 struct smbd_smb2_request *req;
219 uint32_t protocol_version;
220 const uint8_t *inhdr = NULL;
221 off_t ofs = 0;
222 uint16_t cmd;
223 uint32_t next_command_ofs;
225 if (size < (4 + SMB2_HDR_BODY + 2)) {
226 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
227 return NT_STATUS_INVALID_PARAMETER;
230 inhdr = inbuf + 4;
232 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
233 if (protocol_version != SMB2_MAGIC) {
234 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
235 protocol_version));
236 return NT_STATUS_INVALID_PARAMETER;
239 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
240 if (cmd != SMB2_OP_NEGPROT) {
241 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
242 cmd));
243 return NT_STATUS_INVALID_PARAMETER;
246 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
247 if (next_command_ofs != 0) {
248 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
249 next_command_ofs));
250 return NT_STATUS_INVALID_PARAMETER;
253 req = smbd_smb2_request_allocate(sconn);
254 if (req == NULL) {
255 return NT_STATUS_NO_MEMORY;
257 req->sconn = sconn;
259 talloc_steal(req, inbuf);
261 req->in.vector = talloc_array(req, struct iovec, 4);
262 if (req->in.vector == NULL) {
263 TALLOC_FREE(req);
264 return NT_STATUS_NO_MEMORY;
266 req->in.vector_count = 4;
268 memcpy(req->in.nbt_hdr, inbuf, 4);
270 ofs = 0;
271 req->in.vector[0].iov_base = discard_const_p(void, req->in.nbt_hdr);
272 req->in.vector[0].iov_len = 4;
273 ofs += req->in.vector[0].iov_len;
275 req->in.vector[1].iov_base = discard_const_p(void, (inbuf + ofs));
276 req->in.vector[1].iov_len = SMB2_HDR_BODY;
277 ofs += req->in.vector[1].iov_len;
279 req->in.vector[2].iov_base = discard_const_p(void, (inbuf + ofs));
280 req->in.vector[2].iov_len = SVAL(inbuf, ofs) & 0xFFFE;
281 ofs += req->in.vector[2].iov_len;
283 if (ofs > size) {
284 return NT_STATUS_INVALID_PARAMETER;
287 req->in.vector[3].iov_base = discard_const_p(void, (inbuf + ofs));
288 req->in.vector[3].iov_len = size - ofs;
289 ofs += req->in.vector[3].iov_len;
291 req->current_idx = 1;
293 *_req = req;
294 return NT_STATUS_OK;
297 static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
298 uint64_t message_id, uint64_t seq_id)
300 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
301 unsigned int offset;
303 if (seq_id < sconn->smb2.seqnum_low) {
304 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
305 "%llu (sequence id %llu) "
306 "(granted = %u, low = %llu, range = %u)\n",
307 (unsigned long long)message_id,
308 (unsigned long long)seq_id,
309 (unsigned int)sconn->smb2.credits_granted,
310 (unsigned long long)sconn->smb2.seqnum_low,
311 (unsigned int)sconn->smb2.seqnum_range));
312 return false;
315 if (seq_id >= sconn->smb2.seqnum_low + sconn->smb2.seqnum_range) {
316 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
317 "%llu (sequence id %llu) "
318 "(granted = %u, low = %llu, range = %u)\n",
319 (unsigned long long)message_id,
320 (unsigned long long)seq_id,
321 (unsigned int)sconn->smb2.credits_granted,
322 (unsigned long long)sconn->smb2.seqnum_low,
323 (unsigned int)sconn->smb2.seqnum_range));
324 return false;
327 offset = seq_id % sconn->smb2.max_credits;
329 if (bitmap_query(credits_bm, offset)) {
330 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
331 "%llu (sequence id %llu) "
332 "(granted = %u, low = %llu, range = %u) "
333 "(bm offset %u)\n",
334 (unsigned long long)message_id,
335 (unsigned long long)seq_id,
336 (unsigned int)sconn->smb2.credits_granted,
337 (unsigned long long)sconn->smb2.seqnum_low,
338 (unsigned int)sconn->smb2.seqnum_range,
339 offset));
340 return false;
343 /* Mark the message_ids as seen in the bitmap. */
344 bitmap_set(credits_bm, offset);
346 if (seq_id != sconn->smb2.seqnum_low) {
347 return true;
351 * Move the window forward by all the message_id's
352 * already seen.
354 while (bitmap_query(credits_bm, offset)) {
355 DEBUG(10,("smb2_validate_sequence_number: clearing "
356 "id %llu (position %u) from bitmap\n",
357 (unsigned long long)(sconn->smb2.seqnum_low),
358 offset));
359 bitmap_clear(credits_bm, offset);
361 sconn->smb2.seqnum_low += 1;
362 sconn->smb2.seqnum_range -= 1;
363 offset = sconn->smb2.seqnum_low % sconn->smb2.max_credits;
366 return true;
369 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
370 const uint8_t *inhdr)
372 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
373 uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
374 uint16_t credit_charge = 1;
375 uint64_t i;
377 if (opcode == SMB2_OP_CANCEL) {
378 /* SMB2_CANCEL requests by definition resend messageids. */
379 return true;
382 if (sconn->smb2.supports_multicredit) {
383 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
384 credit_charge = MAX(credit_charge, 1);
387 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
388 "credits_granted %llu, "
389 "seqnum low/range: %llu/%llu\n",
390 (unsigned long long) message_id,
391 (unsigned long long) credit_charge,
392 (unsigned long long) sconn->smb2.credits_granted,
393 (unsigned long long) sconn->smb2.seqnum_low,
394 (unsigned long long) sconn->smb2.seqnum_range));
396 if (sconn->smb2.credits_granted < credit_charge) {
397 DEBUG(0, ("smb2_validate_message_id: client used more "
398 "credits than granted, mid %llu, charge %llu, "
399 "credits_granted %llu, "
400 "seqnum low/range: %llu/%llu\n",
401 (unsigned long long) message_id,
402 (unsigned long long) credit_charge,
403 (unsigned long long) sconn->smb2.credits_granted,
404 (unsigned long long) sconn->smb2.seqnum_low,
405 (unsigned long long) sconn->smb2.seqnum_range));
406 return false;
410 * now check the message ids
412 * for multi-credit requests we need to check all current mid plus
413 * the implicit mids caused by the credit charge
414 * e.g. current mid = 15, charge 5 => mark 15-19 as used
417 for (i = 0; i <= (credit_charge-1); i++) {
418 uint64_t id = message_id + i;
419 bool ok;
421 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
422 (unsigned long long)message_id,
423 credit_charge,
424 (unsigned long long)id));
426 ok = smb2_validate_sequence_number(sconn, message_id, id);
427 if (!ok) {
428 return false;
432 /* substract used credits */
433 sconn->smb2.credits_granted -= credit_charge;
435 return true;
438 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
440 int count;
441 int idx;
443 count = req->in.vector_count;
445 if (count < 4) {
446 /* It's not a SMB2 request */
447 return NT_STATUS_INVALID_PARAMETER;
450 for (idx=1; idx < count; idx += 3) {
451 const uint8_t *inhdr = NULL;
452 uint32_t flags;
454 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
455 return NT_STATUS_INVALID_PARAMETER;
458 if (req->in.vector[idx+1].iov_len < 2) {
459 return NT_STATUS_INVALID_PARAMETER;
462 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
464 /* Check the SMB2 header */
465 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
466 return NT_STATUS_INVALID_PARAMETER;
469 if (!smb2_validate_message_id(req->sconn, inhdr)) {
470 return NT_STATUS_INVALID_PARAMETER;
473 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
474 if (idx == 1) {
476 * the 1st request should never have the
477 * SMB2_HDR_FLAG_CHAINED flag set
479 if (flags & SMB2_HDR_FLAG_CHAINED) {
480 req->next_status = NT_STATUS_INVALID_PARAMETER;
481 return NT_STATUS_OK;
483 } else if (idx == 4) {
485 * the 2nd request triggers related vs. unrelated
486 * compounded requests
488 if (flags & SMB2_HDR_FLAG_CHAINED) {
489 req->compound_related = true;
491 } else if (idx > 4) {
492 #if 0
494 * It seems the this tests are wrong
495 * see the SMB2-COMPOUND test
499 * all other requests should match the 2nd one
501 if (flags & SMB2_HDR_FLAG_CHAINED) {
502 if (!req->compound_related) {
503 req->next_status =
504 NT_STATUS_INVALID_PARAMETER;
505 return NT_STATUS_OK;
507 } else {
508 if (req->compound_related) {
509 req->next_status =
510 NT_STATUS_INVALID_PARAMETER;
511 return NT_STATUS_OK;
514 #endif
518 return NT_STATUS_OK;
521 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
522 const struct iovec *in_vector,
523 struct iovec *out_vector)
525 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
526 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
527 uint16_t credit_charge = 1;
528 uint16_t credits_requested;
529 uint32_t out_flags;
530 uint16_t cmd;
531 NTSTATUS out_status;
532 uint16_t credits_granted = 0;
533 uint64_t credits_possible;
534 uint16_t current_max_credits;
537 * first we grant only 1/16th of the max range.
539 * Windows also starts with the 1/16th and then grants
540 * more later. I was only able to trigger higher
541 * values, when using a verify high credit charge.
543 * TODO: scale up depending one load, free memory
544 * or other stuff.
545 * Maybe also on the relationship between number
546 * of requests and the used sequence number.
547 * Which means we would grant more credits
548 * for client which use multi credit requests.
550 current_max_credits = sconn->smb2.max_credits / 16;
551 current_max_credits = MAX(current_max_credits, 1);
553 if (sconn->smb2.supports_multicredit) {
554 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
555 credit_charge = MAX(credit_charge, 1);
558 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
559 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
560 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
561 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
563 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
564 SMB_ASSERT(sconn->smb2.max_credits >= credit_charge);
566 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
568 * In case we already send an async interim
569 * response, we should not grant
570 * credits on the final response.
572 credits_granted = 0;
573 } else if (credits_requested > 0) {
574 uint16_t additional_max = 0;
575 uint16_t additional_credits = credits_requested - 1;
577 switch (cmd) {
578 case SMB2_OP_NEGPROT:
579 break;
580 case SMB2_OP_SESSSETUP:
582 * Windows 2012 RC1 starts to grant
583 * additional credits
584 * with a successful session setup
586 if (NT_STATUS_IS_OK(out_status)) {
587 additional_max = 32;
589 break;
590 default:
592 * We match windows and only grant additional credits
593 * in chunks of 32.
595 additional_max = 32;
596 break;
599 additional_credits = MIN(additional_credits, additional_max);
601 credits_granted = credit_charge + additional_credits;
602 } else if (sconn->smb2.credits_granted == 0) {
604 * Make sure the client has always at least one credit
606 credits_granted = 1;
610 * sequence numbers should not wrap
612 * 1. calculate the possible credits until
613 * the sequence numbers start to wrap on 64-bit.
615 * 2. UINT64_MAX is used for Break Notifications.
617 * 2. truncate the possible credits to the maximum
618 * credits we want to grant to the client in total.
620 * 3. remove the range we'll already granted to the client
621 * this makes sure the client consumes the lowest sequence
622 * number, before we can grant additional credits.
624 credits_possible = UINT64_MAX - sconn->smb2.seqnum_low;
625 if (credits_possible > 0) {
626 /* remove UINT64_MAX */
627 credits_possible -= 1;
629 credits_possible = MIN(credits_possible, current_max_credits);
630 credits_possible -= sconn->smb2.seqnum_range;
632 credits_granted = MIN(credits_granted, credits_possible);
634 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
635 sconn->smb2.credits_granted += credits_granted;
636 sconn->smb2.seqnum_range += credits_granted;
638 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
639 "granted %u, current possible/max %u/%u, "
640 "total granted/max/low/range %u/%u/%llu/%u\n",
641 (unsigned int)credits_requested,
642 (unsigned int)credit_charge,
643 (unsigned int)credits_granted,
644 (unsigned int)credits_possible,
645 (unsigned int)current_max_credits,
646 (unsigned int)sconn->smb2.credits_granted,
647 (unsigned int)sconn->smb2.max_credits,
648 (unsigned long long)sconn->smb2.seqnum_low,
649 (unsigned int)sconn->smb2.seqnum_range));
652 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
653 struct smbd_smb2_request *outreq)
655 int count, idx;
656 uint16_t total_credits = 0;
658 count = outreq->out.vector_count;
660 for (idx=1; idx < count; idx += 3) {
661 uint8_t *outhdr = (uint8_t *)outreq->out.vector[idx].iov_base;
662 smb2_set_operation_credit(outreq->sconn,
663 &inreq->in.vector[idx],
664 &outreq->out.vector[idx]);
665 /* To match Windows, count up what we
666 just granted. */
667 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
668 /* Set to zero in all but the last reply. */
669 if (idx + 3 < count) {
670 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
671 } else {
672 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
677 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
679 struct iovec *vector;
680 int count;
681 int idx;
683 req->request_time = timeval_current();
685 count = req->in.vector_count;
686 vector = talloc_zero_array(req, struct iovec, count);
687 if (vector == NULL) {
688 return NT_STATUS_NO_MEMORY;
691 vector[0].iov_base = req->out.nbt_hdr;
692 vector[0].iov_len = 4;
693 SIVAL(req->out.nbt_hdr, 0, 0);
695 for (idx=1; idx < count; idx += 3) {
696 const uint8_t *inhdr = NULL;
697 uint8_t *outhdr = NULL;
698 uint8_t *outbody = NULL;
699 uint32_t next_command_ofs = 0;
700 struct iovec *current = &vector[idx];
702 if ((idx + 3) < count) {
703 /* we have a next command -
704 * setup for the error case. */
705 next_command_ofs = SMB2_HDR_BODY + 9;
708 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
710 outhdr = talloc_zero_array(vector, uint8_t,
711 OUTVEC_ALLOC_SIZE);
712 if (outhdr == NULL) {
713 return NT_STATUS_NO_MEMORY;
716 outbody = outhdr + SMB2_HDR_BODY;
718 current[0].iov_base = (void *)outhdr;
719 current[0].iov_len = SMB2_HDR_BODY;
721 current[1].iov_base = (void *)outbody;
722 current[1].iov_len = 8;
724 current[2].iov_base = NULL;
725 current[2].iov_len = 0;
727 /* setup the SMB2 header */
728 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
729 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
730 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
731 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
732 SIVAL(outhdr, SMB2_HDR_STATUS,
733 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
734 SSVAL(outhdr, SMB2_HDR_OPCODE,
735 SVAL(inhdr, SMB2_HDR_OPCODE));
736 SIVAL(outhdr, SMB2_HDR_FLAGS,
737 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
738 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
739 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
740 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
741 SIVAL(outhdr, SMB2_HDR_PID,
742 IVAL(inhdr, SMB2_HDR_PID));
743 SIVAL(outhdr, SMB2_HDR_TID,
744 IVAL(inhdr, SMB2_HDR_TID));
745 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
746 BVAL(inhdr, SMB2_HDR_SESSION_ID));
747 memcpy(outhdr + SMB2_HDR_SIGNATURE,
748 inhdr + SMB2_HDR_SIGNATURE, 16);
750 /* setup error body header */
751 SSVAL(outbody, 0x00, 0x08 + 1);
752 SSVAL(outbody, 0x02, 0);
753 SIVAL(outbody, 0x04, 0);
756 req->out.vector = vector;
757 req->out.vector_count = count;
759 /* setup the length of the NBT packet */
760 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
762 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
764 return NT_STATUS_OK;
767 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
768 const char *reason,
769 const char *location)
771 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
772 reason, location));
773 exit_server_cleanly(reason);
776 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
777 struct iovec *outvec,
778 const struct iovec *srcvec)
780 /* vec[0] is always boilerplate and must
781 * be allocated with size OUTVEC_ALLOC_SIZE. */
783 outvec[0].iov_base = talloc_memdup(ctx,
784 srcvec[0].iov_base,
785 OUTVEC_ALLOC_SIZE);
786 if (!outvec[0].iov_base) {
787 return false;
789 outvec[0].iov_len = SMB2_HDR_BODY;
792 * If this is a "standard" vec[1] of length 8,
793 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
794 * then duplicate this. Else use talloc_memdup().
797 if (srcvec[1].iov_len == 8 &&
798 srcvec[1].iov_base ==
799 ((uint8_t *)srcvec[0].iov_base) +
800 SMB2_HDR_BODY) {
801 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
802 SMB2_HDR_BODY;
803 outvec[1].iov_len = 8;
804 } else {
805 outvec[1].iov_base = talloc_memdup(ctx,
806 srcvec[1].iov_base,
807 srcvec[1].iov_len);
808 if (!outvec[1].iov_base) {
809 return false;
811 outvec[1].iov_len = srcvec[1].iov_len;
815 * If this is a "standard" vec[2] of length 1,
816 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
817 * then duplicate this. Else use talloc_memdup().
820 if (srcvec[2].iov_base &&
821 srcvec[2].iov_len) {
822 if (srcvec[2].iov_base ==
823 ((uint8_t *)srcvec[0].iov_base) +
824 (OUTVEC_ALLOC_SIZE - 1) &&
825 srcvec[2].iov_len == 1) {
826 /* Common SMB2 error packet case. */
827 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
828 (OUTVEC_ALLOC_SIZE - 1);
829 } else {
830 outvec[2].iov_base = talloc_memdup(ctx,
831 srcvec[2].iov_base,
832 srcvec[2].iov_len);
833 if (!outvec[2].iov_base) {
834 return false;
837 outvec[2].iov_len = srcvec[2].iov_len;
838 } else {
839 outvec[2].iov_base = NULL;
840 outvec[2].iov_len = 0;
842 return true;
845 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
847 struct smbd_smb2_request *newreq = NULL;
848 struct iovec *outvec = NULL;
849 int count = req->out.vector_count;
850 int i;
852 newreq = smbd_smb2_request_allocate(req->sconn);
853 if (!newreq) {
854 return NULL;
857 newreq->sconn = req->sconn;
858 newreq->session = req->session;
859 newreq->do_signing = req->do_signing;
860 newreq->current_idx = req->current_idx;
862 outvec = talloc_zero_array(newreq, struct iovec, count);
863 if (!outvec) {
864 TALLOC_FREE(newreq);
865 return NULL;
867 newreq->out.vector = outvec;
868 newreq->out.vector_count = count;
870 /* Setup the outvec's identically to req. */
871 outvec[0].iov_base = newreq->out.nbt_hdr;
872 outvec[0].iov_len = 4;
873 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
875 /* Setup the vectors identically to the ones in req. */
876 for (i = 1; i < count; i += 3) {
877 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
878 break;
882 if (i < count) {
883 /* Alloc failed. */
884 TALLOC_FREE(newreq);
885 return NULL;
888 smb2_setup_nbt_length(newreq->out.vector,
889 newreq->out.vector_count);
891 return newreq;
894 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
896 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
898 int i = 0;
899 uint8_t *outhdr = NULL;
900 struct smbd_smb2_request *nreq = NULL;
902 /* Create a new smb2 request we'll use
903 for the interim return. */
904 nreq = dup_smb2_req(req);
905 if (!nreq) {
906 return NT_STATUS_NO_MEMORY;
909 /* Lose the last 3 out vectors. They're the
910 ones we'll be using for the async reply. */
911 nreq->out.vector_count -= 3;
913 smb2_setup_nbt_length(nreq->out.vector,
914 nreq->out.vector_count);
916 /* Step back to the previous reply. */
917 i = nreq->current_idx - 3;
918 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
919 /* And end the chain. */
920 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
922 /* Calculate outgoing credits */
923 smb2_calculate_credits(req, nreq);
925 /* Re-sign if needed. */
926 if (nreq->do_signing) {
927 NTSTATUS status;
928 struct smbXsrv_session *x = nreq->session;
929 struct smbXsrv_connection *conn = x->connection;
930 DATA_BLOB signing_key = x->global->channels[0].signing_key;
932 status = smb2_signing_sign_pdu(signing_key,
933 conn->protocol,
934 &nreq->out.vector[i], 3);
935 if (!NT_STATUS_IS_OK(status)) {
936 return status;
939 if (DEBUGLEVEL >= 10) {
940 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
941 (unsigned int)nreq->current_idx );
942 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
943 (unsigned int)nreq->out.vector_count );
944 print_req_vectors(nreq);
946 nreq->subreq = tstream_writev_queue_send(nreq,
947 nreq->sconn->ev_ctx,
948 nreq->sconn->smb2.stream,
949 nreq->sconn->smb2.send_queue,
950 nreq->out.vector,
951 nreq->out.vector_count);
953 if (nreq->subreq == NULL) {
954 return NT_STATUS_NO_MEMORY;
957 tevent_req_set_callback(nreq->subreq,
958 smbd_smb2_request_writev_done,
959 nreq);
961 return NT_STATUS_OK;
964 struct smbd_smb2_request_pending_state {
965 struct smbd_server_connection *sconn;
966 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
967 struct iovec vector[3];
970 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
972 struct smbd_smb2_request_pending_state *state =
973 tevent_req_callback_data(subreq,
974 struct smbd_smb2_request_pending_state);
975 struct smbd_server_connection *sconn = state->sconn;
976 int ret;
977 int sys_errno;
979 ret = tstream_writev_queue_recv(subreq, &sys_errno);
980 TALLOC_FREE(subreq);
981 if (ret == -1) {
982 NTSTATUS status = map_nt_error_from_unix(sys_errno);
983 smbd_server_connection_terminate(sconn, nt_errstr(status));
984 return;
987 TALLOC_FREE(state);
990 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
991 struct tevent_timer *te,
992 struct timeval current_time,
993 void *private_data);
995 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
996 struct tevent_req *subreq,
997 uint32_t defer_time)
999 NTSTATUS status;
1000 int i = req->current_idx;
1001 struct timeval defer_endtime;
1002 uint8_t *outhdr = NULL;
1003 uint32_t flags;
1005 if (!tevent_req_is_in_progress(subreq)) {
1006 return NT_STATUS_OK;
1009 req->subreq = subreq;
1010 subreq = NULL;
1012 if (req->async_te) {
1013 /* We're already async. */
1014 return NT_STATUS_OK;
1017 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1018 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1019 if (flags & SMB2_HDR_FLAG_ASYNC) {
1020 /* We're already async. */
1021 return NT_STATUS_OK;
1024 if (req->in.vector_count > i + 3) {
1026 * We're trying to go async in a compound
1027 * request chain. This is not allowed.
1028 * Cancel the outstanding request.
1030 tevent_req_cancel(req->subreq);
1031 return smbd_smb2_request_error(req,
1032 NT_STATUS_INSUFFICIENT_RESOURCES);
1035 if (DEBUGLEVEL >= 10) {
1036 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1037 (unsigned int)req->current_idx );
1038 print_req_vectors(req);
1041 if (req->out.vector_count > 4) {
1042 struct iovec *outvec = NULL;
1044 /* This is a compound reply. We
1045 * must do an interim response
1046 * followed by the async response
1047 * to match W2K8R2.
1049 status = smb2_send_async_interim_response(req);
1050 if (!NT_STATUS_IS_OK(status)) {
1051 return status;
1055 * We're splitting off the last SMB2
1056 * request in a compound set, and the
1057 * smb2_send_async_interim_response()
1058 * call above just sent all the replies
1059 * for the previous SMB2 requests in
1060 * this compound set. So we're no longer
1061 * in the "compound_related_in_progress"
1062 * state, and this is no longer a compound
1063 * request.
1065 req->compound_related = false;
1066 req->sconn->smb2.compound_related_in_progress = false;
1068 /* Re-arrange the in.vectors. */
1069 req->in.vector[1] = req->in.vector[i];
1070 req->in.vector[2] = req->in.vector[i+1];
1071 req->in.vector[3] = req->in.vector[i+2];
1072 req->in.vector_count = 4;
1074 /* Reset the new in size. */
1075 smb2_setup_nbt_length(req->in.vector, 4);
1077 /* Now recreate the out.vectors. */
1078 outvec = talloc_zero_array(req, struct iovec, 4);
1079 if (!outvec) {
1080 return NT_STATUS_NO_MEMORY;
1083 /* 0 is always boilerplate and must
1084 * be of size 4 for the length field. */
1086 outvec[0].iov_base = req->out.nbt_hdr;
1087 outvec[0].iov_len = 4;
1088 SIVAL(req->out.nbt_hdr, 0, 0);
1090 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
1091 return NT_STATUS_NO_MEMORY;
1094 TALLOC_FREE(req->out.vector);
1096 req->out.vector = outvec;
1098 req->current_idx = 1;
1099 req->out.vector_count = 4;
1101 outhdr = (uint8_t *)req->out.vector[1].iov_base;
1102 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1103 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1106 defer_endtime = timeval_current_ofs_usec(defer_time);
1107 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1108 req, defer_endtime,
1109 smbd_smb2_request_pending_timer,
1110 req);
1111 if (req->async_te == NULL) {
1112 return NT_STATUS_NO_MEMORY;
1115 return NT_STATUS_OK;
1118 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1119 struct tevent_timer *te,
1120 struct timeval current_time,
1121 void *private_data)
1123 struct smbd_smb2_request *req =
1124 talloc_get_type_abort(private_data,
1125 struct smbd_smb2_request);
1126 struct smbd_smb2_request_pending_state *state = NULL;
1127 int i = req->current_idx;
1128 uint8_t *outhdr = NULL;
1129 const uint8_t *inhdr = NULL;
1130 uint8_t *hdr = NULL;
1131 uint8_t *body = NULL;
1132 uint32_t flags = 0;
1133 uint64_t message_id = 0;
1134 uint64_t async_id = 0;
1135 struct tevent_req *subreq = NULL;
1137 TALLOC_FREE(req->async_te);
1139 /* Ensure our final reply matches the interim one. */
1140 inhdr = (const uint8_t *)req->in.vector[1].iov_base;
1141 outhdr = (uint8_t *)req->out.vector[1].iov_base;
1142 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1143 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1145 async_id = message_id; /* keep it simple for now... */
1147 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1148 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1150 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1151 "going async\n",
1152 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1153 (unsigned long long)async_id ));
1156 * What we send is identical to a smbd_smb2_request_error
1157 * packet with an error status of STATUS_PENDING. Make use
1158 * of this fact sometime when refactoring. JRA.
1161 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1162 if (state == NULL) {
1163 smbd_server_connection_terminate(req->sconn,
1164 nt_errstr(NT_STATUS_NO_MEMORY));
1165 return;
1167 state->sconn = req->sconn;
1169 state->vector[0].iov_base = (void *)state->buf;
1170 state->vector[0].iov_len = 4;
1172 state->vector[1].iov_base = state->buf + 4;
1173 state->vector[1].iov_len = SMB2_HDR_BODY;
1175 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
1176 state->vector[2].iov_len = 9;
1178 smb2_setup_nbt_length(state->vector, 3);
1180 hdr = (uint8_t *)state->vector[1].iov_base;
1181 body = (uint8_t *)state->vector[2].iov_base;
1183 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1184 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1185 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1186 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1187 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1189 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1190 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1191 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1192 SBVAL(hdr, SMB2_HDR_PID, async_id);
1193 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1194 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1195 memcpy(hdr+SMB2_HDR_SIGNATURE,
1196 outhdr+SMB2_HDR_SIGNATURE, 16);
1198 SSVAL(body, 0x00, 0x08 + 1);
1200 SCVAL(body, 0x02, 0);
1201 SCVAL(body, 0x03, 0);
1202 SIVAL(body, 0x04, 0);
1203 /* Match W2K8R2... */
1204 SCVAL(body, 0x08, 0x21);
1206 /* Ensure we correctly go through crediting. Grant
1207 the credits now, and zero credits on the final
1208 response. */
1209 smb2_set_operation_credit(req->sconn,
1210 &req->in.vector[i],
1211 &state->vector[1]);
1213 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1215 if (req->do_signing) {
1216 NTSTATUS status;
1217 struct smbXsrv_session *x = req->session;
1218 struct smbXsrv_connection *conn = x->connection;
1219 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1221 status = smb2_signing_sign_pdu(signing_key,
1222 conn->protocol,
1223 &state->vector[1], 2);
1224 if (!NT_STATUS_IS_OK(status)) {
1225 smbd_server_connection_terminate(req->sconn,
1226 nt_errstr(status));
1227 return;
1231 subreq = tstream_writev_queue_send(state,
1232 state->sconn->ev_ctx,
1233 state->sconn->smb2.stream,
1234 state->sconn->smb2.send_queue,
1235 state->vector,
1237 if (subreq == NULL) {
1238 smbd_server_connection_terminate(state->sconn,
1239 nt_errstr(NT_STATUS_NO_MEMORY));
1240 return;
1242 tevent_req_set_callback(subreq,
1243 smbd_smb2_request_pending_writev_done,
1244 state);
1247 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1249 struct smbd_server_connection *sconn = req->sconn;
1250 struct smbd_smb2_request *cur;
1251 const uint8_t *inhdr;
1252 int i = req->current_idx;
1253 uint32_t flags;
1254 uint64_t search_message_id;
1255 uint64_t search_async_id;
1256 uint64_t found_id;
1258 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1260 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1261 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1262 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1265 * we don't need the request anymore
1266 * cancel requests never have a response
1268 DLIST_REMOVE(req->sconn->smb2.requests, req);
1269 TALLOC_FREE(req);
1271 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1272 const uint8_t *outhdr;
1273 uint64_t message_id;
1274 uint64_t async_id;
1276 i = cur->current_idx;
1278 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1280 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1281 async_id = BVAL(outhdr, SMB2_HDR_PID);
1283 if (flags & SMB2_HDR_FLAG_ASYNC) {
1284 if (search_async_id == async_id) {
1285 found_id = async_id;
1286 break;
1288 } else {
1289 if (search_message_id == message_id) {
1290 found_id = message_id;
1291 break;
1296 if (cur && cur->subreq) {
1297 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1298 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1299 "cancel opcode[%s] mid %llu\n",
1300 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1301 (unsigned long long)found_id ));
1302 tevent_req_cancel(cur->subreq);
1305 return NT_STATUS_OK;
1308 /*************************************************************
1309 Ensure an incoming tid is a valid one for us to access.
1310 Change to the associated uid credentials and chdir to the
1311 valid tid directory.
1312 *************************************************************/
1314 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1316 const uint8_t *inhdr;
1317 int i = req->current_idx;
1318 uint32_t in_flags;
1319 uint32_t in_tid;
1320 struct smbXsrv_tcon *tcon;
1321 NTSTATUS status;
1322 NTTIME now = timeval_to_nttime(&req->request_time);
1324 req->tcon = NULL;
1326 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1328 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1329 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1331 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1332 in_tid = req->last_tid;
1335 status = smb2srv_tcon_lookup(req->session,
1336 in_tid, now, &tcon);
1337 if (!NT_STATUS_IS_OK(status)) {
1338 return status;
1341 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1342 return NT_STATUS_ACCESS_DENIED;
1345 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1346 if (!set_current_service(tcon->compat, 0, true)) {
1347 return NT_STATUS_ACCESS_DENIED;
1350 req->tcon = tcon;
1351 req->last_tid = in_tid;
1353 return NT_STATUS_OK;
1356 /*************************************************************
1357 Ensure an incoming session_id is a valid one for us to access.
1358 *************************************************************/
1360 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1362 const uint8_t *inhdr;
1363 int i = req->current_idx;
1364 uint32_t in_flags;
1365 uint16_t in_opcode;
1366 uint64_t in_session_id;
1367 struct smbXsrv_session *session = NULL;
1368 struct auth_session_info *session_info;
1369 NTSTATUS status;
1370 NTTIME now = timeval_to_nttime(&req->request_time);
1372 req->session = NULL;
1373 req->tcon = NULL;
1375 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1377 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1378 in_opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1379 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1381 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1382 in_session_id = req->last_session_id;
1385 /* lookup an existing session */
1386 status = smb2srv_session_lookup(req->sconn->conn,
1387 in_session_id, now,
1388 &session);
1389 if (session) {
1390 req->session = session;
1391 req->last_session_id = in_session_id;
1393 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1394 switch (in_opcode) {
1395 case SMB2_OP_SESSSETUP:
1396 status = NT_STATUS_OK;
1397 break;
1398 default:
1399 break;
1402 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1403 switch (in_opcode) {
1404 case SMB2_OP_TCON:
1405 case SMB2_OP_CREATE:
1406 case SMB2_OP_GETINFO:
1407 case SMB2_OP_SETINFO:
1408 return NT_STATUS_INVALID_HANDLE;
1409 default:
1411 * Notice the check for
1412 * (session_info == NULL)
1413 * below.
1415 status = NT_STATUS_OK;
1416 break;
1419 if (!NT_STATUS_IS_OK(status)) {
1420 return status;
1423 session_info = session->global->auth_session_info;
1424 if (session_info == NULL) {
1425 return NT_STATUS_INVALID_HANDLE;
1428 set_current_user_info(session_info->unix_info->sanitized_username,
1429 session_info->unix_info->unix_name,
1430 session_info->info->domain_name);
1432 return NT_STATUS_OK;
1435 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1436 uint32_t data_length)
1438 uint16_t needed_charge;
1439 uint16_t credit_charge = 1;
1440 const uint8_t *inhdr;
1441 int i = req->current_idx;
1443 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1445 if (req->sconn->smb2.supports_multicredit) {
1446 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1447 credit_charge = MAX(credit_charge, 1);
1450 needed_charge = (data_length - 1)/ 65536 + 1;
1452 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1453 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1454 credit_charge, needed_charge));
1456 if (needed_charge > credit_charge) {
1457 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1458 credit_charge, needed_charge));
1459 return NT_STATUS_INVALID_PARAMETER;
1462 return NT_STATUS_OK;
1465 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1466 size_t expected_body_size)
1468 const uint8_t *inhdr;
1469 uint16_t opcode;
1470 const uint8_t *inbody;
1471 int i = req->current_idx;
1472 size_t body_size;
1473 size_t min_dyn_size = expected_body_size & 0x00000001;
1476 * The following should be checked already.
1478 if ((i+2) > req->in.vector_count) {
1479 return NT_STATUS_INTERNAL_ERROR;
1481 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1482 return NT_STATUS_INTERNAL_ERROR;
1484 if (req->in.vector[i+1].iov_len < 2) {
1485 return NT_STATUS_INTERNAL_ERROR;
1488 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1489 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1491 switch (opcode) {
1492 case SMB2_OP_IOCTL:
1493 case SMB2_OP_GETINFO:
1494 min_dyn_size = 0;
1495 break;
1499 * Now check the expected body size,
1500 * where the last byte might be in the
1501 * dynamic section..
1503 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1504 return NT_STATUS_INVALID_PARAMETER;
1506 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1507 return NT_STATUS_INVALID_PARAMETER;
1510 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1512 body_size = SVAL(inbody, 0x00);
1513 if (body_size != expected_body_size) {
1514 return NT_STATUS_INVALID_PARAMETER;
1517 return NT_STATUS_OK;
1520 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1522 const uint8_t *inhdr;
1523 int i = req->current_idx;
1524 uint16_t opcode;
1525 uint32_t flags;
1526 uint64_t mid;
1527 NTSTATUS status;
1528 NTSTATUS session_status;
1529 uint32_t allowed_flags;
1530 NTSTATUS return_value;
1531 struct smbXsrv_session *x = NULL;
1532 bool signing_required = false;
1534 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1536 /* TODO: verify more things */
1538 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1539 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1540 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1541 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1542 smb2_opcode_name(opcode),
1543 (unsigned long long)mid));
1545 if (get_Protocol() >= PROTOCOL_SMB2_02) {
1547 * once the protocol is negotiated
1548 * SMB2_OP_NEGPROT is not allowed anymore
1550 if (opcode == SMB2_OP_NEGPROT) {
1551 /* drop the connection */
1552 return NT_STATUS_INVALID_PARAMETER;
1554 } else {
1556 * if the protocol is not negotiated yet
1557 * only SMB2_OP_NEGPROT is allowed.
1559 if (opcode != SMB2_OP_NEGPROT) {
1560 /* drop the connection */
1561 return NT_STATUS_INVALID_PARAMETER;
1565 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1566 SMB2_HDR_FLAG_SIGNED |
1567 SMB2_HDR_FLAG_DFS;
1568 if (opcode == SMB2_OP_CANCEL) {
1569 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1571 if ((flags & ~allowed_flags) != 0) {
1572 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1576 * Check if the client provided a valid session id,
1577 * if so smbd_smb2_request_check_session() calls
1578 * set_current_user_info().
1580 * As some command don't require a valid session id
1581 * we defer the check of the session_status
1583 session_status = smbd_smb2_request_check_session(req);
1584 x = req->session;
1586 if (x != NULL) {
1587 signing_required = x->global->signing_required;
1589 if (opcode == SMB2_OP_SESSSETUP &&
1590 x->global->channels[0].signing_key.length) {
1591 signing_required = true;
1595 req->do_signing = false;
1596 if (flags & SMB2_HDR_FLAG_SIGNED) {
1597 struct smbXsrv_connection *conn;
1598 DATA_BLOB signing_key;
1600 if (x == NULL) {
1601 return smbd_smb2_request_error(
1602 req, NT_STATUS_ACCESS_DENIED);
1605 conn = x->connection;
1606 signing_key = x->global->channels[0].signing_key;
1608 if (!NT_STATUS_IS_OK(session_status)) {
1609 return smbd_smb2_request_error(req, session_status);
1612 req->do_signing = true;
1613 status = smb2_signing_check_pdu(signing_key,
1614 conn->protocol,
1615 &req->in.vector[i], 3);
1616 if (!NT_STATUS_IS_OK(status)) {
1617 return smbd_smb2_request_error(req, status);
1619 } else if (opcode == SMB2_OP_CANCEL) {
1620 /* Cancel requests are allowed to skip the signing */
1621 } else if (signing_required) {
1622 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1625 if (flags & SMB2_HDR_FLAG_CHAINED) {
1627 * This check is mostly for giving the correct error code
1628 * for compounded requests.
1630 * TODO: we may need to move this after the session
1631 * and tcon checks.
1633 if (!NT_STATUS_IS_OK(req->next_status)) {
1634 return smbd_smb2_request_error(req, req->next_status);
1636 } else {
1637 req->compat_chain_fsp = NULL;
1640 if (req->compound_related) {
1641 req->sconn->smb2.compound_related_in_progress = true;
1644 switch (opcode) {
1645 case SMB2_OP_NEGPROT:
1646 /* This call needs to be run as root */
1647 change_to_root_user();
1650 START_PROFILE(smb2_negprot);
1651 return_value = smbd_smb2_request_process_negprot(req);
1652 END_PROFILE(smb2_negprot);
1654 break;
1656 case SMB2_OP_SESSSETUP:
1657 /* This call needs to be run as root */
1658 change_to_root_user();
1661 START_PROFILE(smb2_sesssetup);
1662 return_value = smbd_smb2_request_process_sesssetup(req);
1663 END_PROFILE(smb2_sesssetup);
1665 break;
1667 case SMB2_OP_LOGOFF:
1668 if (!NT_STATUS_IS_OK(session_status)) {
1669 return_value = smbd_smb2_request_error(req, session_status);
1670 break;
1673 /* This call needs to be run as root */
1674 change_to_root_user();
1677 START_PROFILE(smb2_logoff);
1678 return_value = smbd_smb2_request_process_logoff(req);
1679 END_PROFILE(smb2_logoff);
1681 break;
1683 case SMB2_OP_TCON:
1684 if (!NT_STATUS_IS_OK(session_status)) {
1685 return_value = smbd_smb2_request_error(req, session_status);
1686 break;
1690 * This call needs to be run as root.
1692 * smbd_smb2_request_process_tcon()
1693 * calls make_connection_snum(), which will call
1694 * change_to_user(), when needed.
1696 change_to_root_user();
1699 START_PROFILE(smb2_tcon);
1700 return_value = smbd_smb2_request_process_tcon(req);
1701 END_PROFILE(smb2_tcon);
1703 break;
1705 case SMB2_OP_TDIS:
1706 if (!NT_STATUS_IS_OK(session_status)) {
1707 return_value = smbd_smb2_request_error(req, session_status);
1708 break;
1711 * This call needs to be run as user.
1713 * smbd_smb2_request_check_tcon()
1714 * calls change_to_user() on success.
1716 status = smbd_smb2_request_check_tcon(req);
1717 if (!NT_STATUS_IS_OK(status)) {
1718 return_value = smbd_smb2_request_error(req, status);
1719 break;
1721 /* This call needs to be run as root */
1722 change_to_root_user();
1726 START_PROFILE(smb2_tdis);
1727 return_value = smbd_smb2_request_process_tdis(req);
1728 END_PROFILE(smb2_tdis);
1730 break;
1732 case SMB2_OP_CREATE:
1733 if (!NT_STATUS_IS_OK(session_status)) {
1734 return_value = smbd_smb2_request_error(req, session_status);
1735 break;
1738 * This call needs to be run as user.
1740 * smbd_smb2_request_check_tcon()
1741 * calls change_to_user() on success.
1743 status = smbd_smb2_request_check_tcon(req);
1744 if (!NT_STATUS_IS_OK(status)) {
1745 return_value = smbd_smb2_request_error(req, status);
1746 break;
1750 START_PROFILE(smb2_create);
1751 return_value = smbd_smb2_request_process_create(req);
1752 END_PROFILE(smb2_create);
1754 break;
1756 case SMB2_OP_CLOSE:
1757 if (!NT_STATUS_IS_OK(session_status)) {
1758 return_value = smbd_smb2_request_error(req, session_status);
1759 break;
1762 * This call needs to be run as user.
1764 * smbd_smb2_request_check_tcon()
1765 * calls change_to_user() on success.
1767 status = smbd_smb2_request_check_tcon(req);
1768 if (!NT_STATUS_IS_OK(status)) {
1769 return_value = smbd_smb2_request_error(req, status);
1770 break;
1774 START_PROFILE(smb2_close);
1775 return_value = smbd_smb2_request_process_close(req);
1776 END_PROFILE(smb2_close);
1778 break;
1780 case SMB2_OP_FLUSH:
1781 if (!NT_STATUS_IS_OK(session_status)) {
1782 return_value = smbd_smb2_request_error(req, session_status);
1783 break;
1786 * This call needs to be run as user.
1788 * smbd_smb2_request_check_tcon()
1789 * calls change_to_user() on success.
1791 status = smbd_smb2_request_check_tcon(req);
1792 if (!NT_STATUS_IS_OK(status)) {
1793 return_value = smbd_smb2_request_error(req, status);
1794 break;
1798 START_PROFILE(smb2_flush);
1799 return_value = smbd_smb2_request_process_flush(req);
1800 END_PROFILE(smb2_flush);
1802 break;
1804 case SMB2_OP_READ:
1805 if (!NT_STATUS_IS_OK(session_status)) {
1806 return_value = smbd_smb2_request_error(req, session_status);
1807 break;
1810 * This call needs to be run as user.
1812 * smbd_smb2_request_check_tcon()
1813 * calls change_to_user() on success.
1815 status = smbd_smb2_request_check_tcon(req);
1816 if (!NT_STATUS_IS_OK(status)) {
1817 return_value = smbd_smb2_request_error(req, status);
1818 break;
1822 START_PROFILE(smb2_read);
1823 return_value = smbd_smb2_request_process_read(req);
1824 END_PROFILE(smb2_read);
1826 break;
1828 case SMB2_OP_WRITE:
1829 if (!NT_STATUS_IS_OK(session_status)) {
1830 return_value = smbd_smb2_request_error(req, session_status);
1831 break;
1834 * This call needs to be run as user.
1836 * smbd_smb2_request_check_tcon()
1837 * calls change_to_user() on success.
1839 status = smbd_smb2_request_check_tcon(req);
1840 if (!NT_STATUS_IS_OK(status)) {
1841 return_value = smbd_smb2_request_error(req, status);
1842 break;
1846 START_PROFILE(smb2_write);
1847 return_value = smbd_smb2_request_process_write(req);
1848 END_PROFILE(smb2_write);
1850 break;
1852 case SMB2_OP_LOCK:
1853 if (!NT_STATUS_IS_OK(session_status)) {
1854 /* Too ugly to live ? JRA. */
1855 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1856 session_status = NT_STATUS_FILE_CLOSED;
1858 return_value = smbd_smb2_request_error(req, session_status);
1859 break;
1862 * This call needs to be run as user.
1864 * smbd_smb2_request_check_tcon()
1865 * calls change_to_user() on success.
1867 status = smbd_smb2_request_check_tcon(req);
1868 if (!NT_STATUS_IS_OK(status)) {
1869 /* Too ugly to live ? JRA. */
1870 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1871 status = NT_STATUS_FILE_CLOSED;
1873 return_value = smbd_smb2_request_error(req, status);
1874 break;
1878 START_PROFILE(smb2_lock);
1879 return_value = smbd_smb2_request_process_lock(req);
1880 END_PROFILE(smb2_lock);
1882 break;
1884 case SMB2_OP_IOCTL:
1885 if (!NT_STATUS_IS_OK(session_status)) {
1886 return_value = smbd_smb2_request_error(req, session_status);
1887 break;
1890 * This call needs to be run as user.
1892 * smbd_smb2_request_check_tcon()
1893 * calls change_to_user() on success.
1895 status = smbd_smb2_request_check_tcon(req);
1896 if (!NT_STATUS_IS_OK(status)) {
1897 return_value = smbd_smb2_request_error(req, status);
1898 break;
1902 START_PROFILE(smb2_ioctl);
1903 return_value = smbd_smb2_request_process_ioctl(req);
1904 END_PROFILE(smb2_ioctl);
1906 break;
1908 case SMB2_OP_CANCEL:
1910 * This call needs to be run as root
1912 * That is what we also do in the SMB1 case.
1914 change_to_root_user();
1917 START_PROFILE(smb2_cancel);
1918 return_value = smbd_smb2_request_process_cancel(req);
1919 END_PROFILE(smb2_cancel);
1921 break;
1923 case SMB2_OP_KEEPALIVE:
1924 /* This call needs to be run as root */
1925 change_to_root_user();
1928 START_PROFILE(smb2_keepalive);
1929 return_value = smbd_smb2_request_process_keepalive(req);
1930 END_PROFILE(smb2_keepalive);
1932 break;
1934 case SMB2_OP_FIND:
1935 if (!NT_STATUS_IS_OK(session_status)) {
1936 return_value = smbd_smb2_request_error(req, session_status);
1937 break;
1940 * This call needs to be run as user.
1942 * smbd_smb2_request_check_tcon()
1943 * calls change_to_user() on success.
1945 status = smbd_smb2_request_check_tcon(req);
1946 if (!NT_STATUS_IS_OK(status)) {
1947 return_value = smbd_smb2_request_error(req, status);
1948 break;
1952 START_PROFILE(smb2_find);
1953 return_value = smbd_smb2_request_process_find(req);
1954 END_PROFILE(smb2_find);
1956 break;
1958 case SMB2_OP_NOTIFY:
1959 if (!NT_STATUS_IS_OK(session_status)) {
1960 return_value = smbd_smb2_request_error(req, session_status);
1961 break;
1964 * This call needs to be run as user.
1966 * smbd_smb2_request_check_tcon()
1967 * calls change_to_user() on success.
1969 status = smbd_smb2_request_check_tcon(req);
1970 if (!NT_STATUS_IS_OK(status)) {
1971 return_value = smbd_smb2_request_error(req, status);
1972 break;
1976 START_PROFILE(smb2_notify);
1977 return_value = smbd_smb2_request_process_notify(req);
1978 END_PROFILE(smb2_notify);
1980 break;
1982 case SMB2_OP_GETINFO:
1983 if (!NT_STATUS_IS_OK(session_status)) {
1984 return_value = smbd_smb2_request_error(req, session_status);
1985 break;
1988 * This call needs to be run as user.
1990 * smbd_smb2_request_check_tcon()
1991 * calls change_to_user() on success.
1993 status = smbd_smb2_request_check_tcon(req);
1994 if (!NT_STATUS_IS_OK(status)) {
1995 return_value = smbd_smb2_request_error(req, status);
1996 break;
2000 START_PROFILE(smb2_getinfo);
2001 return_value = smbd_smb2_request_process_getinfo(req);
2002 END_PROFILE(smb2_getinfo);
2004 break;
2006 case SMB2_OP_SETINFO:
2007 if (!NT_STATUS_IS_OK(session_status)) {
2008 return_value = smbd_smb2_request_error(req, session_status);
2009 break;
2012 * This call needs to be run as user.
2014 * smbd_smb2_request_check_tcon()
2015 * calls change_to_user() on success.
2017 status = smbd_smb2_request_check_tcon(req);
2018 if (!NT_STATUS_IS_OK(status)) {
2019 return_value = smbd_smb2_request_error(req, status);
2020 break;
2024 START_PROFILE(smb2_setinfo);
2025 return_value = smbd_smb2_request_process_setinfo(req);
2026 END_PROFILE(smb2_setinfo);
2028 break;
2030 case SMB2_OP_BREAK:
2031 if (!NT_STATUS_IS_OK(session_status)) {
2032 return_value = smbd_smb2_request_error(req, session_status);
2033 break;
2036 * This call needs to be run as user.
2038 * smbd_smb2_request_check_tcon()
2039 * calls change_to_user() on success.
2041 status = smbd_smb2_request_check_tcon(req);
2042 if (!NT_STATUS_IS_OK(status)) {
2043 return_value = smbd_smb2_request_error(req, status);
2044 break;
2048 START_PROFILE(smb2_break);
2049 return_value = smbd_smb2_request_process_break(req);
2050 END_PROFILE(smb2_break);
2052 break;
2054 default:
2055 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2056 break;
2058 return return_value;
2061 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2063 struct tevent_req *subreq;
2064 int i = req->current_idx;
2066 req->subreq = NULL;
2067 TALLOC_FREE(req->async_te);
2069 req->current_idx += 3;
2071 if (req->current_idx < req->out.vector_count) {
2073 * We must process the remaining compound
2074 * SMB2 requests before any new incoming SMB2
2075 * requests. This is because incoming SMB2
2076 * requests may include a cancel for a
2077 * compound request we haven't processed
2078 * yet.
2080 struct tevent_immediate *im = tevent_create_immediate(req);
2081 if (!im) {
2082 return NT_STATUS_NO_MEMORY;
2084 tevent_schedule_immediate(im,
2085 req->sconn->ev_ctx,
2086 smbd_smb2_request_dispatch_immediate,
2087 req);
2088 return NT_STATUS_OK;
2091 if (req->compound_related) {
2092 req->sconn->smb2.compound_related_in_progress = false;
2095 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2097 /* Set credit for these operations (zero credits if this
2098 is a final reply for an async operation). */
2099 smb2_calculate_credits(req, req);
2101 if (req->do_signing) {
2102 NTSTATUS status;
2103 struct smbXsrv_session *x = req->session;
2104 struct smbXsrv_connection *conn = x->connection;
2105 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2107 status = smb2_signing_sign_pdu(signing_key,
2108 conn->protocol,
2109 &req->out.vector[i], 3);
2110 if (!NT_STATUS_IS_OK(status)) {
2111 return status;
2115 if (DEBUGLEVEL >= 10) {
2116 dbgtext("smbd_smb2_request_reply: sending...\n");
2117 print_req_vectors(req);
2120 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2121 if (req->out.vector_count == 4 &&
2122 req->out.vector[3].iov_base == NULL &&
2123 req->out.vector[3].iov_len != 0) {
2124 /* Dynamic part is NULL. Chop it off,
2125 We're going to send it via sendfile. */
2126 req->out.vector_count -= 1;
2129 subreq = tstream_writev_queue_send(req,
2130 req->sconn->ev_ctx,
2131 req->sconn->smb2.stream,
2132 req->sconn->smb2.send_queue,
2133 req->out.vector,
2134 req->out.vector_count);
2135 if (subreq == NULL) {
2136 return NT_STATUS_NO_MEMORY;
2138 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
2140 * We're done with this request -
2141 * move it off the "being processed" queue.
2143 DLIST_REMOVE(req->sconn->smb2.requests, req);
2145 return NT_STATUS_OK;
2148 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2150 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2151 struct tevent_immediate *im,
2152 void *private_data)
2154 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2155 struct smbd_smb2_request);
2156 struct smbd_server_connection *sconn = req->sconn;
2157 NTSTATUS status;
2159 TALLOC_FREE(im);
2161 if (DEBUGLEVEL >= 10) {
2162 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2163 req->current_idx, req->in.vector_count));
2164 print_req_vectors(req);
2167 status = smbd_smb2_request_dispatch(req);
2168 if (!NT_STATUS_IS_OK(status)) {
2169 smbd_server_connection_terminate(sconn, nt_errstr(status));
2170 return;
2173 status = smbd_smb2_request_next_incoming(sconn);
2174 if (!NT_STATUS_IS_OK(status)) {
2175 smbd_server_connection_terminate(sconn, nt_errstr(status));
2176 return;
2180 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
2182 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
2183 struct smbd_smb2_request);
2184 struct smbd_server_connection *sconn = req->sconn;
2185 int ret;
2186 int sys_errno;
2187 NTSTATUS status;
2189 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2190 TALLOC_FREE(subreq);
2191 TALLOC_FREE(req);
2192 if (ret == -1) {
2193 status = map_nt_error_from_unix(sys_errno);
2194 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2195 nt_errstr(status)));
2196 smbd_server_connection_terminate(sconn, nt_errstr(status));
2197 return;
2200 status = smbd_smb2_request_next_incoming(sconn);
2201 if (!NT_STATUS_IS_OK(status)) {
2202 smbd_server_connection_terminate(sconn, nt_errstr(status));
2203 return;
2207 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2208 NTSTATUS status,
2209 DATA_BLOB body, DATA_BLOB *dyn,
2210 const char *location)
2212 uint8_t *outhdr;
2213 int i = req->current_idx;
2214 uint32_t next_command_ofs;
2216 DEBUG(10,("smbd_smb2_request_done_ex: "
2217 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2218 i, nt_errstr(status), (unsigned int)body.length,
2219 dyn ? "yes": "no",
2220 (unsigned int)(dyn ? dyn->length : 0),
2221 location));
2223 if (body.length < 2) {
2224 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2227 if ((body.length % 2) != 0) {
2228 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2231 outhdr = (uint8_t *)req->out.vector[i].iov_base;
2233 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2234 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2236 req->out.vector[i+1].iov_base = (void *)body.data;
2237 req->out.vector[i+1].iov_len = body.length;
2239 if (dyn) {
2240 req->out.vector[i+2].iov_base = (void *)dyn->data;
2241 req->out.vector[i+2].iov_len = dyn->length;
2242 } else {
2243 req->out.vector[i+2].iov_base = NULL;
2244 req->out.vector[i+2].iov_len = 0;
2247 /* see if we need to recalculate the offset to the next response */
2248 if (next_command_ofs > 0) {
2249 next_command_ofs = SMB2_HDR_BODY;
2250 next_command_ofs += req->out.vector[i+1].iov_len;
2251 next_command_ofs += req->out.vector[i+2].iov_len;
2254 if ((next_command_ofs % 8) != 0) {
2255 size_t pad_size = 8 - (next_command_ofs % 8);
2256 if (req->out.vector[i+2].iov_len == 0) {
2258 * if the dyn buffer is empty
2259 * we can use it to add padding
2261 uint8_t *pad;
2263 pad = talloc_zero_array(req->out.vector,
2264 uint8_t, pad_size);
2265 if (pad == NULL) {
2266 return smbd_smb2_request_error(req,
2267 NT_STATUS_NO_MEMORY);
2270 req->out.vector[i+2].iov_base = (void *)pad;
2271 req->out.vector[i+2].iov_len = pad_size;
2272 } else {
2274 * For now we copy the dynamic buffer
2275 * and add the padding to the new buffer
2277 size_t old_size;
2278 uint8_t *old_dyn;
2279 size_t new_size;
2280 uint8_t *new_dyn;
2282 old_size = req->out.vector[i+2].iov_len;
2283 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2285 new_size = old_size + pad_size;
2286 new_dyn = talloc_zero_array(req->out.vector,
2287 uint8_t, new_size);
2288 if (new_dyn == NULL) {
2289 return smbd_smb2_request_error(req,
2290 NT_STATUS_NO_MEMORY);
2293 memcpy(new_dyn, old_dyn, old_size);
2294 memset(new_dyn + old_size, 0, pad_size);
2296 req->out.vector[i+2].iov_base = (void *)new_dyn;
2297 req->out.vector[i+2].iov_len = new_size;
2299 next_command_ofs += pad_size;
2302 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2304 return smbd_smb2_request_reply(req);
2307 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2308 NTSTATUS status,
2309 DATA_BLOB *info,
2310 const char *location)
2312 DATA_BLOB body;
2313 int i = req->current_idx;
2314 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
2316 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2317 i, nt_errstr(status), info ? " +info" : "",
2318 location));
2320 body.data = outhdr + SMB2_HDR_BODY;
2321 body.length = 8;
2322 SSVAL(body.data, 0, 9);
2324 if (info) {
2325 SIVAL(body.data, 0x04, info->length);
2326 } else {
2327 /* Allocated size of req->out.vector[i].iov_base
2328 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2329 * 1 byte without having to do an alloc.
2331 info = talloc_zero_array(req->out.vector,
2332 DATA_BLOB,
2334 if (!info) {
2335 return NT_STATUS_NO_MEMORY;
2337 info->data = ((uint8_t *)outhdr) +
2338 OUTVEC_ALLOC_SIZE - 1;
2339 info->length = 1;
2340 SCVAL(info->data, 0, 0);
2344 * if a request fails, all other remaining
2345 * compounded requests should fail too
2347 req->next_status = NT_STATUS_INVALID_PARAMETER;
2349 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2353 struct smbd_smb2_send_oplock_break_state {
2354 struct smbd_server_connection *sconn;
2355 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2356 struct iovec vector;
2359 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2361 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2362 uint64_t file_id_persistent,
2363 uint64_t file_id_volatile,
2364 uint8_t oplock_level)
2366 struct smbd_smb2_send_oplock_break_state *state;
2367 struct tevent_req *subreq;
2368 uint8_t *hdr;
2369 uint8_t *body;
2371 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2372 if (state == NULL) {
2373 return NT_STATUS_NO_MEMORY;
2375 state->sconn = sconn;
2377 state->vector.iov_base = (void *)state->buf;
2378 state->vector.iov_len = sizeof(state->buf);
2380 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2381 hdr = state->buf + 4;
2382 body = hdr + SMB2_HDR_BODY;
2384 SIVAL(hdr, 0, SMB2_MAGIC);
2385 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2386 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2387 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2388 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2389 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2390 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2391 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2392 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2393 SIVAL(hdr, SMB2_HDR_PID, 0);
2394 SIVAL(hdr, SMB2_HDR_TID, 0);
2395 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2396 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2398 SSVAL(body, 0x00, 0x18);
2400 SCVAL(body, 0x02, oplock_level);
2401 SCVAL(body, 0x03, 0); /* reserved */
2402 SIVAL(body, 0x04, 0); /* reserved */
2403 SBVAL(body, 0x08, file_id_persistent);
2404 SBVAL(body, 0x10, file_id_volatile);
2406 subreq = tstream_writev_queue_send(state,
2407 sconn->ev_ctx,
2408 sconn->smb2.stream,
2409 sconn->smb2.send_queue,
2410 &state->vector, 1);
2411 if (subreq == NULL) {
2412 return NT_STATUS_NO_MEMORY;
2414 tevent_req_set_callback(subreq,
2415 smbd_smb2_oplock_break_writev_done,
2416 state);
2418 return NT_STATUS_OK;
2421 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2423 struct smbd_smb2_send_oplock_break_state *state =
2424 tevent_req_callback_data(subreq,
2425 struct smbd_smb2_send_oplock_break_state);
2426 struct smbd_server_connection *sconn = state->sconn;
2427 int ret;
2428 int sys_errno;
2430 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2431 TALLOC_FREE(subreq);
2432 if (ret == -1) {
2433 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2434 smbd_server_connection_terminate(sconn, nt_errstr(status));
2435 return;
2438 TALLOC_FREE(state);
2441 struct smbd_smb2_request_read_state {
2442 size_t missing;
2443 bool asked_for_header;
2444 struct smbd_smb2_request *smb2_req;
2447 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2448 void *private_data,
2449 TALLOC_CTX *mem_ctx,
2450 struct iovec **_vector,
2451 size_t *_count);
2452 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2454 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2455 struct tevent_context *ev,
2456 struct smbd_server_connection *sconn)
2458 struct tevent_req *req;
2459 struct smbd_smb2_request_read_state *state;
2460 struct tevent_req *subreq;
2462 req = tevent_req_create(mem_ctx, &state,
2463 struct smbd_smb2_request_read_state);
2464 if (req == NULL) {
2465 return NULL;
2467 state->missing = 0;
2468 state->asked_for_header = false;
2470 state->smb2_req = smbd_smb2_request_allocate(state);
2471 if (tevent_req_nomem(state->smb2_req, req)) {
2472 return tevent_req_post(req, ev);
2474 state->smb2_req->sconn = sconn;
2476 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2477 sconn->smb2.recv_queue,
2478 smbd_smb2_request_next_vector,
2479 state);
2480 if (tevent_req_nomem(subreq, req)) {
2481 return tevent_req_post(req, ev);
2483 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2485 return req;
2488 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2489 void *private_data,
2490 TALLOC_CTX *mem_ctx,
2491 struct iovec **_vector,
2492 size_t *_count)
2494 struct smbd_smb2_request_read_state *state =
2495 talloc_get_type_abort(private_data,
2496 struct smbd_smb2_request_read_state);
2497 struct smbd_smb2_request *req = state->smb2_req;
2498 struct iovec *vector;
2499 int idx = req->in.vector_count;
2500 size_t len = 0;
2501 uint8_t *buf = NULL;
2503 if (req->in.vector_count == 0) {
2505 * first we need to get the NBT header
2507 req->in.vector = talloc_array(req, struct iovec,
2508 req->in.vector_count + 1);
2509 if (req->in.vector == NULL) {
2510 return -1;
2512 req->in.vector_count += 1;
2514 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2515 req->in.vector[idx].iov_len = 4;
2517 vector = talloc_array(mem_ctx, struct iovec, 1);
2518 if (vector == NULL) {
2519 return -1;
2522 vector[0] = req->in.vector[idx];
2524 *_vector = vector;
2525 *_count = 1;
2526 return 0;
2529 if (req->in.vector_count == 1) {
2531 * Now we analyze the NBT header
2533 state->missing = smb2_len(req->in.vector[0].iov_base);
2535 if (state->missing == 0) {
2536 /* if there're no remaining bytes, we're done */
2537 *_vector = NULL;
2538 *_count = 0;
2539 return 0;
2542 req->in.vector = talloc_realloc(req, req->in.vector,
2543 struct iovec,
2544 req->in.vector_count + 1);
2545 if (req->in.vector == NULL) {
2546 return -1;
2548 req->in.vector_count += 1;
2550 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2552 * it's a special NBT message,
2553 * so get all remaining bytes
2555 len = state->missing;
2556 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2558 * it's an invalid message, just read what we can get
2559 * and let the caller handle the error
2561 len = state->missing;
2562 } else {
2564 * We assume it's a SMB2 request,
2565 * and we first get the header and the
2566 * first 2 bytes (the struct size) of the body
2568 len = SMB2_HDR_BODY + 2;
2570 state->asked_for_header = true;
2573 state->missing -= len;
2575 buf = talloc_array(req->in.vector, uint8_t, len);
2576 if (buf == NULL) {
2577 return -1;
2580 req->in.vector[idx].iov_base = (void *)buf;
2581 req->in.vector[idx].iov_len = len;
2583 vector = talloc_array(mem_ctx, struct iovec, 1);
2584 if (vector == NULL) {
2585 return -1;
2588 vector[0] = req->in.vector[idx];
2590 *_vector = vector;
2591 *_count = 1;
2592 return 0;
2595 if (state->missing == 0) {
2596 /* if there're no remaining bytes, we're done */
2597 *_vector = NULL;
2598 *_count = 0;
2599 return 0;
2602 if (state->asked_for_header) {
2603 const uint8_t *hdr;
2604 size_t full_size;
2605 size_t next_command_ofs;
2606 size_t body_size;
2607 uint8_t *body;
2608 size_t dyn_size;
2609 uint8_t *dyn;
2610 bool invalid = false;
2612 state->asked_for_header = false;
2615 * We got the SMB2 header and the first 2 bytes
2616 * of the body. We fix the size to just the header
2617 * and manually copy the 2 first bytes to the body section
2619 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2620 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2622 /* allocate vectors for body and dynamic areas */
2623 req->in.vector = talloc_realloc(req, req->in.vector,
2624 struct iovec,
2625 req->in.vector_count + 2);
2626 if (req->in.vector == NULL) {
2627 return -1;
2629 req->in.vector_count += 2;
2631 full_size = state->missing + SMB2_HDR_BODY + 2;
2632 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2633 body_size = SVAL(hdr, SMB2_HDR_BODY);
2635 if (next_command_ofs != 0) {
2636 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2638 * this is invalid, just return a zero
2639 * body and let the caller deal with the error
2641 invalid = true;
2642 } else if (next_command_ofs > full_size) {
2644 * this is invalid, just return a zero
2645 * body and let the caller deal with the error
2647 invalid = true;
2648 } else {
2649 full_size = next_command_ofs;
2653 if (!invalid) {
2654 if (body_size < 2) {
2656 * this is invalid, just return a zero
2657 * body and let the caller deal with the error
2659 invalid = true;
2663 * Mask out the lowest bit, the "dynamic" part
2664 * of body_size.
2666 body_size &= ~1;
2668 if (body_size > (full_size - SMB2_HDR_BODY)) {
2670 * this is invalid, just return a zero
2671 * body and let the caller deal with the error
2673 invalid = true;
2677 if (invalid) {
2678 /* the caller should check this */
2679 body_size = 2;
2682 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2684 state->missing -= (body_size - 2) + dyn_size;
2686 body = talloc_array(req->in.vector, uint8_t, body_size);
2687 if (body == NULL) {
2688 return -1;
2691 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2692 if (dyn == NULL) {
2693 return -1;
2696 req->in.vector[idx].iov_base = (void *)body;
2697 req->in.vector[idx].iov_len = body_size;
2698 req->in.vector[idx+1].iov_base = (void *)dyn;
2699 req->in.vector[idx+1].iov_len = dyn_size;
2701 vector = talloc_array(mem_ctx, struct iovec, 2);
2702 if (vector == NULL) {
2703 return -1;
2707 * the first 2 bytes of the body were already fetched
2708 * together with the header
2710 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2711 vector[0].iov_base = body + 2;
2712 vector[0].iov_len = body_size - 2;
2714 vector[1] = req->in.vector[idx+1];
2716 *_vector = vector;
2717 *_count = 2;
2718 return 0;
2722 * when we endup here, we're looking for a new SMB2 request
2723 * next. And we ask for its header and the first 2 bytes of
2724 * the body (like we did for the first SMB2 request).
2727 req->in.vector = talloc_realloc(req, req->in.vector,
2728 struct iovec,
2729 req->in.vector_count + 1);
2730 if (req->in.vector == NULL) {
2731 return -1;
2733 req->in.vector_count += 1;
2736 * We assume it's a SMB2 request,
2737 * and we first get the header and the
2738 * first 2 bytes (the struct size) of the body
2740 len = SMB2_HDR_BODY + 2;
2742 if (len > state->missing) {
2743 /* let the caller handle the error */
2744 len = state->missing;
2747 state->missing -= len;
2748 state->asked_for_header = true;
2750 buf = talloc_array(req->in.vector, uint8_t, len);
2751 if (buf == NULL) {
2752 return -1;
2755 req->in.vector[idx].iov_base = (void *)buf;
2756 req->in.vector[idx].iov_len = len;
2758 vector = talloc_array(mem_ctx, struct iovec, 1);
2759 if (vector == NULL) {
2760 return -1;
2763 vector[0] = req->in.vector[idx];
2765 *_vector = vector;
2766 *_count = 1;
2767 return 0;
2770 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2772 struct tevent_req *req =
2773 tevent_req_callback_data(subreq,
2774 struct tevent_req);
2775 int ret;
2776 int sys_errno;
2777 NTSTATUS status;
2779 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2780 if (ret == -1) {
2781 status = map_nt_error_from_unix(sys_errno);
2782 tevent_req_nterror(req, status);
2783 return;
2786 tevent_req_done(req);
2789 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2790 TALLOC_CTX *mem_ctx,
2791 struct smbd_smb2_request **_smb2_req)
2793 struct smbd_smb2_request_read_state *state =
2794 tevent_req_data(req,
2795 struct smbd_smb2_request_read_state);
2796 NTSTATUS status;
2798 if (tevent_req_is_nterror(req, &status)) {
2799 tevent_req_received(req);
2800 return status;
2803 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2804 *_smb2_req = state->smb2_req;
2805 tevent_req_received(req);
2806 return NT_STATUS_OK;
2809 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2811 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2813 size_t max_send_queue_len;
2814 size_t cur_send_queue_len;
2815 struct tevent_req *subreq;
2817 if (sconn->smb2.compound_related_in_progress) {
2819 * Can't read another until the related
2820 * compound is done.
2822 return NT_STATUS_OK;
2825 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2827 * if there is already a smbd_smb2_request_read
2828 * pending, we are done.
2830 return NT_STATUS_OK;
2833 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2834 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2836 if (cur_send_queue_len > max_send_queue_len) {
2838 * if we have a lot of requests to send,
2839 * we wait until they are on the wire until we
2840 * ask for the next request.
2842 return NT_STATUS_OK;
2845 /* ask for the next request */
2846 subreq = smbd_smb2_request_read_send(sconn, sconn->ev_ctx, sconn);
2847 if (subreq == NULL) {
2848 return NT_STATUS_NO_MEMORY;
2850 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2852 return NT_STATUS_OK;
2855 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2856 const uint8_t *inbuf, size_t size)
2858 NTSTATUS status;
2859 struct smbd_smb2_request *req = NULL;
2861 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2862 (unsigned int)size));
2864 status = smbd_initialize_smb2(sconn);
2865 if (!NT_STATUS_IS_OK(status)) {
2866 smbd_server_connection_terminate(sconn, nt_errstr(status));
2867 return;
2870 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2871 if (!NT_STATUS_IS_OK(status)) {
2872 smbd_server_connection_terminate(sconn, nt_errstr(status));
2873 return;
2876 status = smbd_smb2_request_validate(req);
2877 if (!NT_STATUS_IS_OK(status)) {
2878 smbd_server_connection_terminate(sconn, nt_errstr(status));
2879 return;
2882 status = smbd_smb2_request_setup_out(req);
2883 if (!NT_STATUS_IS_OK(status)) {
2884 smbd_server_connection_terminate(sconn, nt_errstr(status));
2885 return;
2888 status = smbd_smb2_request_dispatch(req);
2889 if (!NT_STATUS_IS_OK(status)) {
2890 smbd_server_connection_terminate(sconn, nt_errstr(status));
2891 return;
2894 status = smbd_smb2_request_next_incoming(sconn);
2895 if (!NT_STATUS_IS_OK(status)) {
2896 smbd_server_connection_terminate(sconn, nt_errstr(status));
2897 return;
2900 sconn->num_requests++;
2903 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2905 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2906 struct smbd_server_connection);
2907 NTSTATUS status;
2908 struct smbd_smb2_request *req = NULL;
2910 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2911 TALLOC_FREE(subreq);
2912 if (!NT_STATUS_IS_OK(status)) {
2913 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2914 nt_errstr(status)));
2915 smbd_server_connection_terminate(sconn, nt_errstr(status));
2916 return;
2919 if (req->in.nbt_hdr[0] != 0x00) {
2920 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2921 req->in.nbt_hdr[0]));
2922 TALLOC_FREE(req);
2923 goto next;
2926 req->current_idx = 1;
2928 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2929 req->current_idx, req->in.vector_count));
2931 status = smbd_smb2_request_validate(req);
2932 if (!NT_STATUS_IS_OK(status)) {
2933 smbd_server_connection_terminate(sconn, nt_errstr(status));
2934 return;
2937 status = smbd_smb2_request_setup_out(req);
2938 if (!NT_STATUS_IS_OK(status)) {
2939 smbd_server_connection_terminate(sconn, nt_errstr(status));
2940 return;
2943 status = smbd_smb2_request_dispatch(req);
2944 if (!NT_STATUS_IS_OK(status)) {
2945 smbd_server_connection_terminate(sconn, nt_errstr(status));
2946 return;
2949 next:
2950 status = smbd_smb2_request_next_incoming(sconn);
2951 if (!NT_STATUS_IS_OK(status)) {
2952 smbd_server_connection_terminate(sconn, nt_errstr(status));
2953 return;
2956 sconn->num_requests++;
2958 /* The timeout_processing function isn't run nearly
2959 often enough to implement 'max log size' without
2960 overrunning the size of the file by many megabytes.
2961 This is especially true if we are running at debug
2962 level 10. Checking every 50 SMB2s is a nice
2963 tradeoff of performance vs log file size overrun. */
2965 if ((sconn->num_requests % 50) == 0 &&
2966 need_to_check_log_size()) {
2967 change_to_root_user();
2968 check_log_size();