docs-xml: fix pid directory example
[Samba.git] / source3 / smbd / smb2_server.c
blob979a179c1d3c3328ad93185957ddeff6a9bfffe5
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 struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
156 TALLOC_CTX *mem_pool;
157 struct smbd_smb2_request *req;
159 #if 0
160 /* Enable this to find subtle valgrind errors. */
161 mem_pool = talloc_init("smbd_smb2_request_allocate");
162 #else
163 mem_pool = talloc_pool(mem_ctx, 8192);
164 #endif
165 if (mem_pool == NULL) {
166 return NULL;
169 req = talloc_zero(mem_pool, struct smbd_smb2_request);
170 if (req == NULL) {
171 talloc_free(mem_pool);
172 return NULL;
174 talloc_reparent(mem_pool, mem_ctx, req);
175 TALLOC_FREE(mem_pool);
177 req->last_session_id = UINT64_MAX;
178 req->last_tid = UINT32_MAX;
180 return req;
183 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
184 const uint8_t *inbuf, size_t size,
185 struct smbd_smb2_request **_req)
187 struct smbd_smb2_request *req;
188 uint32_t protocol_version;
189 const uint8_t *inhdr = NULL;
190 off_t ofs = 0;
191 uint16_t cmd;
192 uint32_t next_command_ofs;
194 if (size < (4 + SMB2_HDR_BODY + 2)) {
195 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
196 return NT_STATUS_INVALID_PARAMETER;
199 inhdr = inbuf + 4;
201 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
202 if (protocol_version != SMB2_MAGIC) {
203 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
204 protocol_version));
205 return NT_STATUS_INVALID_PARAMETER;
208 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
209 if (cmd != SMB2_OP_NEGPROT) {
210 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
211 cmd));
212 return NT_STATUS_INVALID_PARAMETER;
215 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
216 if (next_command_ofs != 0) {
217 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
218 next_command_ofs));
219 return NT_STATUS_INVALID_PARAMETER;
222 req = smbd_smb2_request_allocate(sconn);
223 if (req == NULL) {
224 return NT_STATUS_NO_MEMORY;
226 req->sconn = sconn;
228 talloc_steal(req, inbuf);
230 req->in.vector = talloc_array(req, struct iovec, 4);
231 if (req->in.vector == NULL) {
232 TALLOC_FREE(req);
233 return NT_STATUS_NO_MEMORY;
235 req->in.vector_count = 4;
237 memcpy(req->in.nbt_hdr, inbuf, 4);
239 ofs = 0;
240 req->in.vector[0].iov_base = discard_const_p(void, req->in.nbt_hdr);
241 req->in.vector[0].iov_len = 4;
242 ofs += req->in.vector[0].iov_len;
244 req->in.vector[1].iov_base = discard_const_p(void, (inbuf + ofs));
245 req->in.vector[1].iov_len = SMB2_HDR_BODY;
246 ofs += req->in.vector[1].iov_len;
248 req->in.vector[2].iov_base = discard_const_p(void, (inbuf + ofs));
249 req->in.vector[2].iov_len = SVAL(inbuf, ofs) & 0xFFFE;
250 ofs += req->in.vector[2].iov_len;
252 if (ofs > size) {
253 return NT_STATUS_INVALID_PARAMETER;
256 req->in.vector[3].iov_base = discard_const_p(void, (inbuf + ofs));
257 req->in.vector[3].iov_len = size - ofs;
258 ofs += req->in.vector[3].iov_len;
260 req->current_idx = 1;
262 *_req = req;
263 return NT_STATUS_OK;
266 static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
267 uint64_t message_id, uint64_t seq_id)
269 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
270 unsigned int offset;
272 if (seq_id < sconn->smb2.seqnum_low) {
273 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
274 "%llu (sequence id %llu) "
275 "(granted = %u, low = %llu, range = %u)\n",
276 (unsigned long long)message_id,
277 (unsigned long long)seq_id,
278 (unsigned int)sconn->smb2.credits_granted,
279 (unsigned long long)sconn->smb2.seqnum_low,
280 (unsigned int)sconn->smb2.seqnum_range));
281 return false;
284 if (seq_id >= sconn->smb2.seqnum_low + sconn->smb2.seqnum_range) {
285 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
286 "%llu (sequence id %llu) "
287 "(granted = %u, low = %llu, range = %u)\n",
288 (unsigned long long)message_id,
289 (unsigned long long)seq_id,
290 (unsigned int)sconn->smb2.credits_granted,
291 (unsigned long long)sconn->smb2.seqnum_low,
292 (unsigned int)sconn->smb2.seqnum_range));
293 return false;
296 offset = seq_id % sconn->smb2.max_credits;
298 if (bitmap_query(credits_bm, offset)) {
299 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
300 "%llu (sequence id %llu) "
301 "(granted = %u, low = %llu, range = %u) "
302 "(bm offset %u)\n",
303 (unsigned long long)message_id,
304 (unsigned long long)seq_id,
305 (unsigned int)sconn->smb2.credits_granted,
306 (unsigned long long)sconn->smb2.seqnum_low,
307 (unsigned int)sconn->smb2.seqnum_range,
308 offset));
309 return false;
312 /* Mark the message_ids as seen in the bitmap. */
313 bitmap_set(credits_bm, offset);
315 if (seq_id != sconn->smb2.seqnum_low) {
316 return true;
320 * Move the window forward by all the message_id's
321 * already seen.
323 while (bitmap_query(credits_bm, offset)) {
324 DEBUG(10,("smb2_validate_sequence_number: clearing "
325 "id %llu (position %u) from bitmap\n",
326 (unsigned long long)(sconn->smb2.seqnum_low),
327 offset));
328 bitmap_clear(credits_bm, offset);
330 sconn->smb2.seqnum_low += 1;
331 sconn->smb2.seqnum_range -= 1;
332 offset = sconn->smb2.seqnum_low % sconn->smb2.max_credits;
335 return true;
338 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
339 const uint8_t *inhdr)
341 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
342 uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
343 uint16_t credit_charge = 1;
344 uint64_t i;
346 if (opcode == SMB2_OP_CANCEL) {
347 /* SMB2_CANCEL requests by definition resend messageids. */
348 return true;
351 if (sconn->smb2.supports_multicredit) {
352 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
353 credit_charge = MAX(credit_charge, 1);
356 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
357 "credits_granted %llu, "
358 "seqnum low/range: %llu/%llu\n",
359 (unsigned long long) message_id,
360 (unsigned long long) credit_charge,
361 (unsigned long long) sconn->smb2.credits_granted,
362 (unsigned long long) sconn->smb2.seqnum_low,
363 (unsigned long long) sconn->smb2.seqnum_range));
365 if (sconn->smb2.credits_granted < credit_charge) {
366 DEBUG(0, ("smb2_validate_message_id: client used more "
367 "credits than granted, mid %llu, charge %llu, "
368 "credits_granted %llu, "
369 "seqnum low/range: %llu/%llu\n",
370 (unsigned long long) message_id,
371 (unsigned long long) credit_charge,
372 (unsigned long long) sconn->smb2.credits_granted,
373 (unsigned long long) sconn->smb2.seqnum_low,
374 (unsigned long long) sconn->smb2.seqnum_range));
375 return false;
379 * now check the message ids
381 * for multi-credit requests we need to check all current mid plus
382 * the implicit mids caused by the credit charge
383 * e.g. current mid = 15, charge 5 => mark 15-19 as used
386 for (i = 0; i <= (credit_charge-1); i++) {
387 uint64_t id = message_id + i;
388 bool ok;
390 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
391 (unsigned long long)message_id,
392 credit_charge,
393 (unsigned long long)id));
395 ok = smb2_validate_sequence_number(sconn, message_id, id);
396 if (!ok) {
397 return false;
401 /* substract used credits */
402 sconn->smb2.credits_granted -= credit_charge;
404 return true;
407 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
409 int count;
410 int idx;
412 count = req->in.vector_count;
414 if (count < 4) {
415 /* It's not a SMB2 request */
416 return NT_STATUS_INVALID_PARAMETER;
419 for (idx=1; idx < count; idx += 3) {
420 const uint8_t *inhdr = NULL;
421 uint32_t flags;
423 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
424 return NT_STATUS_INVALID_PARAMETER;
427 if (req->in.vector[idx+1].iov_len < 2) {
428 return NT_STATUS_INVALID_PARAMETER;
431 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
433 /* Check the SMB2 header */
434 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
435 return NT_STATUS_INVALID_PARAMETER;
438 if (!smb2_validate_message_id(req->sconn, inhdr)) {
439 return NT_STATUS_INVALID_PARAMETER;
442 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
443 if (idx == 1) {
445 * the 1st request should never have the
446 * SMB2_HDR_FLAG_CHAINED flag set
448 if (flags & SMB2_HDR_FLAG_CHAINED) {
449 req->next_status = NT_STATUS_INVALID_PARAMETER;
450 return NT_STATUS_OK;
452 } else if (idx == 4) {
454 * the 2nd request triggers related vs. unrelated
455 * compounded requests
457 if (flags & SMB2_HDR_FLAG_CHAINED) {
458 req->compound_related = true;
460 } else if (idx > 4) {
461 #if 0
463 * It seems the this tests are wrong
464 * see the SMB2-COMPOUND test
468 * all other requests should match the 2nd one
470 if (flags & SMB2_HDR_FLAG_CHAINED) {
471 if (!req->compound_related) {
472 req->next_status =
473 NT_STATUS_INVALID_PARAMETER;
474 return NT_STATUS_OK;
476 } else {
477 if (req->compound_related) {
478 req->next_status =
479 NT_STATUS_INVALID_PARAMETER;
480 return NT_STATUS_OK;
483 #endif
487 return NT_STATUS_OK;
490 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
491 const struct iovec *in_vector,
492 struct iovec *out_vector)
494 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
495 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
496 uint16_t credit_charge = 1;
497 uint16_t credits_requested;
498 uint32_t out_flags;
499 uint16_t cmd;
500 NTSTATUS out_status;
501 uint16_t credits_granted = 0;
502 uint64_t credits_possible;
503 uint16_t current_max_credits;
506 * first we grant only 1/16th of the max range.
508 * Windows also starts with the 1/16th and then grants
509 * more later. I was only able to trigger higher
510 * values, when using a verify high credit charge.
512 * TODO: scale up depending one load, free memory
513 * or other stuff.
514 * Maybe also on the relationship between number
515 * of requests and the used sequence number.
516 * Which means we would grant more credits
517 * for client which use multi credit requests.
519 current_max_credits = sconn->smb2.max_credits / 16;
520 current_max_credits = MAX(current_max_credits, 1);
522 if (sconn->smb2.supports_multicredit) {
523 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
524 credit_charge = MAX(credit_charge, 1);
527 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
528 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
529 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
530 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
532 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
533 SMB_ASSERT(sconn->smb2.max_credits >= credit_charge);
535 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
537 * In case we already send an async interim
538 * response, we should not grant
539 * credits on the final response.
541 credits_granted = 0;
542 } else if (credits_requested > 0) {
543 uint16_t additional_max = 0;
544 uint16_t additional_credits = credits_requested - 1;
546 switch (cmd) {
547 case SMB2_OP_NEGPROT:
548 break;
549 case SMB2_OP_SESSSETUP:
551 * Windows 2012 RC1 starts to grant
552 * additional credits
553 * with a successful session setup
555 if (NT_STATUS_IS_OK(out_status)) {
556 additional_max = 32;
558 break;
559 default:
561 * We match windows and only grant additional credits
562 * in chunks of 32.
564 additional_max = 32;
565 break;
568 additional_credits = MIN(additional_credits, additional_max);
570 credits_granted = credit_charge + additional_credits;
571 } else if (sconn->smb2.credits_granted == 0) {
573 * Make sure the client has always at least one credit
575 credits_granted = 1;
579 * sequence numbers should not wrap
581 * 1. calculate the possible credits until
582 * the sequence numbers start to wrap on 64-bit.
584 * 2. UINT64_MAX is used for Break Notifications.
586 * 2. truncate the possible credits to the maximum
587 * credits we want to grant to the client in total.
589 * 3. remove the range we'll already granted to the client
590 * this makes sure the client consumes the lowest sequence
591 * number, before we can grant additional credits.
593 credits_possible = UINT64_MAX - sconn->smb2.seqnum_low;
594 if (credits_possible > 0) {
595 /* remove UINT64_MAX */
596 credits_possible -= 1;
598 credits_possible = MIN(credits_possible, current_max_credits);
599 credits_possible -= sconn->smb2.seqnum_range;
601 credits_granted = MIN(credits_granted, credits_possible);
603 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
604 sconn->smb2.credits_granted += credits_granted;
605 sconn->smb2.seqnum_range += credits_granted;
607 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
608 "granted %u, current possible/max %u/%u, "
609 "total granted/max/low/range %u/%u/%llu/%u\n",
610 (unsigned int)credits_requested,
611 (unsigned int)credit_charge,
612 (unsigned int)credits_granted,
613 (unsigned int)credits_possible,
614 (unsigned int)current_max_credits,
615 (unsigned int)sconn->smb2.credits_granted,
616 (unsigned int)sconn->smb2.max_credits,
617 (unsigned long long)sconn->smb2.seqnum_low,
618 (unsigned int)sconn->smb2.seqnum_range));
621 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
622 struct smbd_smb2_request *outreq)
624 int count, idx;
625 uint16_t total_credits = 0;
627 count = outreq->out.vector_count;
629 for (idx=1; idx < count; idx += 3) {
630 uint8_t *outhdr = (uint8_t *)outreq->out.vector[idx].iov_base;
631 smb2_set_operation_credit(outreq->sconn,
632 &inreq->in.vector[idx],
633 &outreq->out.vector[idx]);
634 /* To match Windows, count up what we
635 just granted. */
636 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
637 /* Set to zero in all but the last reply. */
638 if (idx + 3 < count) {
639 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
640 } else {
641 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
646 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
648 struct iovec *vector;
649 int count;
650 int idx;
652 req->request_time = timeval_current();
654 count = req->in.vector_count;
655 vector = talloc_zero_array(req, struct iovec, count);
656 if (vector == NULL) {
657 return NT_STATUS_NO_MEMORY;
660 vector[0].iov_base = req->out.nbt_hdr;
661 vector[0].iov_len = 4;
662 SIVAL(req->out.nbt_hdr, 0, 0);
664 for (idx=1; idx < count; idx += 3) {
665 const uint8_t *inhdr = NULL;
666 uint8_t *outhdr = NULL;
667 uint8_t *outbody = NULL;
668 uint32_t next_command_ofs = 0;
669 struct iovec *current = &vector[idx];
671 if ((idx + 3) < count) {
672 /* we have a next command -
673 * setup for the error case. */
674 next_command_ofs = SMB2_HDR_BODY + 9;
677 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
679 outhdr = talloc_zero_array(vector, uint8_t,
680 OUTVEC_ALLOC_SIZE);
681 if (outhdr == NULL) {
682 return NT_STATUS_NO_MEMORY;
685 outbody = outhdr + SMB2_HDR_BODY;
687 current[0].iov_base = (void *)outhdr;
688 current[0].iov_len = SMB2_HDR_BODY;
690 current[1].iov_base = (void *)outbody;
691 current[1].iov_len = 8;
693 current[2].iov_base = NULL;
694 current[2].iov_len = 0;
696 /* setup the SMB2 header */
697 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
698 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
699 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
700 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
701 SIVAL(outhdr, SMB2_HDR_STATUS,
702 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
703 SSVAL(outhdr, SMB2_HDR_OPCODE,
704 SVAL(inhdr, SMB2_HDR_OPCODE));
705 SIVAL(outhdr, SMB2_HDR_FLAGS,
706 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
707 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
708 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
709 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
710 SIVAL(outhdr, SMB2_HDR_PID,
711 IVAL(inhdr, SMB2_HDR_PID));
712 SIVAL(outhdr, SMB2_HDR_TID,
713 IVAL(inhdr, SMB2_HDR_TID));
714 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
715 BVAL(inhdr, SMB2_HDR_SESSION_ID));
716 memcpy(outhdr + SMB2_HDR_SIGNATURE,
717 inhdr + SMB2_HDR_SIGNATURE, 16);
719 /* setup error body header */
720 SSVAL(outbody, 0x00, 0x08 + 1);
721 SSVAL(outbody, 0x02, 0);
722 SIVAL(outbody, 0x04, 0);
725 req->out.vector = vector;
726 req->out.vector_count = count;
728 /* setup the length of the NBT packet */
729 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
731 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
733 return NT_STATUS_OK;
736 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
737 const char *reason,
738 const char *location)
740 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
741 reason, location));
742 exit_server_cleanly(reason);
745 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
746 struct iovec *outvec,
747 const struct iovec *srcvec)
749 /* vec[0] is always boilerplate and must
750 * be allocated with size OUTVEC_ALLOC_SIZE. */
752 outvec[0].iov_base = talloc_memdup(ctx,
753 srcvec[0].iov_base,
754 OUTVEC_ALLOC_SIZE);
755 if (!outvec[0].iov_base) {
756 return false;
758 outvec[0].iov_len = SMB2_HDR_BODY;
761 * If this is a "standard" vec[1] of length 8,
762 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
763 * then duplicate this. Else use talloc_memdup().
766 if (srcvec[1].iov_len == 8 &&
767 srcvec[1].iov_base ==
768 ((uint8_t *)srcvec[0].iov_base) +
769 SMB2_HDR_BODY) {
770 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
771 SMB2_HDR_BODY;
772 outvec[1].iov_len = 8;
773 } else {
774 outvec[1].iov_base = talloc_memdup(ctx,
775 srcvec[1].iov_base,
776 srcvec[1].iov_len);
777 if (!outvec[1].iov_base) {
778 return false;
780 outvec[1].iov_len = srcvec[1].iov_len;
784 * If this is a "standard" vec[2] of length 1,
785 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
786 * then duplicate this. Else use talloc_memdup().
789 if (srcvec[2].iov_base &&
790 srcvec[2].iov_len) {
791 if (srcvec[2].iov_base ==
792 ((uint8_t *)srcvec[0].iov_base) +
793 (OUTVEC_ALLOC_SIZE - 1) &&
794 srcvec[2].iov_len == 1) {
795 /* Common SMB2 error packet case. */
796 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
797 (OUTVEC_ALLOC_SIZE - 1);
798 } else {
799 outvec[2].iov_base = talloc_memdup(ctx,
800 srcvec[2].iov_base,
801 srcvec[2].iov_len);
802 if (!outvec[2].iov_base) {
803 return false;
806 outvec[2].iov_len = srcvec[2].iov_len;
807 } else {
808 outvec[2].iov_base = NULL;
809 outvec[2].iov_len = 0;
811 return true;
814 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
816 struct smbd_smb2_request *newreq = NULL;
817 struct iovec *outvec = NULL;
818 int count = req->out.vector_count;
819 int i;
821 newreq = smbd_smb2_request_allocate(req->sconn);
822 if (!newreq) {
823 return NULL;
826 newreq->sconn = req->sconn;
827 newreq->session = req->session;
828 newreq->do_signing = req->do_signing;
829 newreq->current_idx = req->current_idx;
831 outvec = talloc_zero_array(newreq, struct iovec, count);
832 if (!outvec) {
833 TALLOC_FREE(newreq);
834 return NULL;
836 newreq->out.vector = outvec;
837 newreq->out.vector_count = count;
839 /* Setup the outvec's identically to req. */
840 outvec[0].iov_base = newreq->out.nbt_hdr;
841 outvec[0].iov_len = 4;
842 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
844 /* Setup the vectors identically to the ones in req. */
845 for (i = 1; i < count; i += 3) {
846 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
847 break;
851 if (i < count) {
852 /* Alloc failed. */
853 TALLOC_FREE(newreq);
854 return NULL;
857 smb2_setup_nbt_length(newreq->out.vector,
858 newreq->out.vector_count);
860 return newreq;
863 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
865 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
867 int i = 0;
868 uint8_t *outhdr = NULL;
869 struct smbd_smb2_request *nreq = NULL;
871 /* Create a new smb2 request we'll use
872 for the interim return. */
873 nreq = dup_smb2_req(req);
874 if (!nreq) {
875 return NT_STATUS_NO_MEMORY;
878 /* Lose the last 3 out vectors. They're the
879 ones we'll be using for the async reply. */
880 nreq->out.vector_count -= 3;
882 smb2_setup_nbt_length(nreq->out.vector,
883 nreq->out.vector_count);
885 /* Step back to the previous reply. */
886 i = nreq->current_idx - 3;
887 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
888 /* And end the chain. */
889 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
891 /* Calculate outgoing credits */
892 smb2_calculate_credits(req, nreq);
894 /* Re-sign if needed. */
895 if (nreq->do_signing) {
896 NTSTATUS status;
897 struct smbXsrv_session *x = nreq->session;
898 struct smbXsrv_connection *conn = x->connection;
899 DATA_BLOB signing_key = x->global->channels[0].signing_key;
901 status = smb2_signing_sign_pdu(signing_key,
902 conn->protocol,
903 &nreq->out.vector[i], 3);
904 if (!NT_STATUS_IS_OK(status)) {
905 return status;
908 if (DEBUGLEVEL >= 10) {
909 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
910 (unsigned int)nreq->current_idx );
911 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
912 (unsigned int)nreq->out.vector_count );
913 print_req_vectors(nreq);
915 nreq->subreq = tstream_writev_queue_send(nreq,
916 nreq->sconn->ev_ctx,
917 nreq->sconn->smb2.stream,
918 nreq->sconn->smb2.send_queue,
919 nreq->out.vector,
920 nreq->out.vector_count);
922 if (nreq->subreq == NULL) {
923 return NT_STATUS_NO_MEMORY;
926 tevent_req_set_callback(nreq->subreq,
927 smbd_smb2_request_writev_done,
928 nreq);
930 return NT_STATUS_OK;
933 struct smbd_smb2_request_pending_state {
934 struct smbd_server_connection *sconn;
935 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
936 struct iovec vector[3];
939 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
941 struct smbd_smb2_request_pending_state *state =
942 tevent_req_callback_data(subreq,
943 struct smbd_smb2_request_pending_state);
944 struct smbd_server_connection *sconn = state->sconn;
945 int ret;
946 int sys_errno;
948 ret = tstream_writev_queue_recv(subreq, &sys_errno);
949 TALLOC_FREE(subreq);
950 if (ret == -1) {
951 NTSTATUS status = map_nt_error_from_unix(sys_errno);
952 smbd_server_connection_terminate(sconn, nt_errstr(status));
953 return;
956 TALLOC_FREE(state);
959 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
960 struct tevent_timer *te,
961 struct timeval current_time,
962 void *private_data);
964 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
965 struct tevent_req *subreq,
966 uint32_t defer_time)
968 NTSTATUS status;
969 int i = req->current_idx;
970 struct timeval defer_endtime;
971 uint8_t *outhdr = NULL;
972 uint32_t flags;
974 if (!tevent_req_is_in_progress(subreq)) {
975 return NT_STATUS_OK;
978 req->subreq = subreq;
979 subreq = NULL;
981 if (req->async_te) {
982 /* We're already async. */
983 return NT_STATUS_OK;
986 outhdr = (uint8_t *)req->out.vector[i].iov_base;
987 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
988 if (flags & SMB2_HDR_FLAG_ASYNC) {
989 /* We're already async. */
990 return NT_STATUS_OK;
993 if (req->in.vector_count > i + 3) {
995 * We're trying to go async in a compound
996 * request chain. This is not allowed.
997 * Cancel the outstanding request.
999 tevent_req_cancel(req->subreq);
1000 return smbd_smb2_request_error(req,
1001 NT_STATUS_INSUFFICIENT_RESOURCES);
1004 if (DEBUGLEVEL >= 10) {
1005 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1006 (unsigned int)req->current_idx );
1007 print_req_vectors(req);
1010 if (req->out.vector_count > 4) {
1011 struct iovec *outvec = NULL;
1013 /* This is a compound reply. We
1014 * must do an interim response
1015 * followed by the async response
1016 * to match W2K8R2.
1018 status = smb2_send_async_interim_response(req);
1019 if (!NT_STATUS_IS_OK(status)) {
1020 return status;
1024 * We're splitting off the last SMB2
1025 * request in a compound set, and the
1026 * smb2_send_async_interim_response()
1027 * call above just sent all the replies
1028 * for the previous SMB2 requests in
1029 * this compound set. So we're no longer
1030 * in the "compound_related_in_progress"
1031 * state, and this is no longer a compound
1032 * request.
1034 req->compound_related = false;
1035 req->sconn->smb2.compound_related_in_progress = false;
1037 /* Re-arrange the in.vectors. */
1038 req->in.vector[1] = req->in.vector[i];
1039 req->in.vector[2] = req->in.vector[i+1];
1040 req->in.vector[3] = req->in.vector[i+2];
1041 req->in.vector_count = 4;
1043 /* Reset the new in size. */
1044 smb2_setup_nbt_length(req->in.vector, 4);
1046 /* Now recreate the out.vectors. */
1047 outvec = talloc_zero_array(req, struct iovec, 4);
1048 if (!outvec) {
1049 return NT_STATUS_NO_MEMORY;
1052 /* 0 is always boilerplate and must
1053 * be of size 4 for the length field. */
1055 outvec[0].iov_base = req->out.nbt_hdr;
1056 outvec[0].iov_len = 4;
1057 SIVAL(req->out.nbt_hdr, 0, 0);
1059 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
1060 return NT_STATUS_NO_MEMORY;
1063 TALLOC_FREE(req->out.vector);
1065 req->out.vector = outvec;
1067 req->current_idx = 1;
1068 req->out.vector_count = 4;
1070 outhdr = (uint8_t *)req->out.vector[1].iov_base;
1071 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1072 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1075 defer_endtime = timeval_current_ofs_usec(defer_time);
1076 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1077 req, defer_endtime,
1078 smbd_smb2_request_pending_timer,
1079 req);
1080 if (req->async_te == NULL) {
1081 return NT_STATUS_NO_MEMORY;
1084 return NT_STATUS_OK;
1087 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1088 struct tevent_timer *te,
1089 struct timeval current_time,
1090 void *private_data)
1092 struct smbd_smb2_request *req =
1093 talloc_get_type_abort(private_data,
1094 struct smbd_smb2_request);
1095 struct smbd_smb2_request_pending_state *state = NULL;
1096 int i = req->current_idx;
1097 uint8_t *outhdr = NULL;
1098 const uint8_t *inhdr = NULL;
1099 uint8_t *hdr = NULL;
1100 uint8_t *body = NULL;
1101 uint32_t flags = 0;
1102 uint64_t message_id = 0;
1103 uint64_t async_id = 0;
1104 struct tevent_req *subreq = NULL;
1106 TALLOC_FREE(req->async_te);
1108 /* Ensure our final reply matches the interim one. */
1109 inhdr = (const uint8_t *)req->in.vector[1].iov_base;
1110 outhdr = (uint8_t *)req->out.vector[1].iov_base;
1111 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1112 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1114 async_id = message_id; /* keep it simple for now... */
1116 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1117 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1119 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1120 "going async\n",
1121 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1122 (unsigned long long)async_id ));
1125 * What we send is identical to a smbd_smb2_request_error
1126 * packet with an error status of STATUS_PENDING. Make use
1127 * of this fact sometime when refactoring. JRA.
1130 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1131 if (state == NULL) {
1132 smbd_server_connection_terminate(req->sconn,
1133 nt_errstr(NT_STATUS_NO_MEMORY));
1134 return;
1136 state->sconn = req->sconn;
1138 state->vector[0].iov_base = (void *)state->buf;
1139 state->vector[0].iov_len = 4;
1141 state->vector[1].iov_base = state->buf + 4;
1142 state->vector[1].iov_len = SMB2_HDR_BODY;
1144 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
1145 state->vector[2].iov_len = 9;
1147 smb2_setup_nbt_length(state->vector, 3);
1149 hdr = (uint8_t *)state->vector[1].iov_base;
1150 body = (uint8_t *)state->vector[2].iov_base;
1152 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1153 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1154 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1155 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1156 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1158 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1159 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1160 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1161 SBVAL(hdr, SMB2_HDR_PID, async_id);
1162 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1163 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1164 memcpy(hdr+SMB2_HDR_SIGNATURE,
1165 outhdr+SMB2_HDR_SIGNATURE, 16);
1167 SSVAL(body, 0x00, 0x08 + 1);
1169 SCVAL(body, 0x02, 0);
1170 SCVAL(body, 0x03, 0);
1171 SIVAL(body, 0x04, 0);
1172 /* Match W2K8R2... */
1173 SCVAL(body, 0x08, 0x21);
1175 /* Ensure we correctly go through crediting. Grant
1176 the credits now, and zero credits on the final
1177 response. */
1178 smb2_set_operation_credit(req->sconn,
1179 &req->in.vector[i],
1180 &state->vector[1]);
1182 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1184 if (req->do_signing) {
1185 NTSTATUS status;
1186 struct smbXsrv_session *x = req->session;
1187 struct smbXsrv_connection *conn = x->connection;
1188 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1190 status = smb2_signing_sign_pdu(signing_key,
1191 conn->protocol,
1192 &state->vector[1], 2);
1193 if (!NT_STATUS_IS_OK(status)) {
1194 smbd_server_connection_terminate(req->sconn,
1195 nt_errstr(status));
1196 return;
1200 subreq = tstream_writev_queue_send(state,
1201 state->sconn->ev_ctx,
1202 state->sconn->smb2.stream,
1203 state->sconn->smb2.send_queue,
1204 state->vector,
1206 if (subreq == NULL) {
1207 smbd_server_connection_terminate(state->sconn,
1208 nt_errstr(NT_STATUS_NO_MEMORY));
1209 return;
1211 tevent_req_set_callback(subreq,
1212 smbd_smb2_request_pending_writev_done,
1213 state);
1216 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1218 struct smbd_server_connection *sconn = req->sconn;
1219 struct smbd_smb2_request *cur;
1220 const uint8_t *inhdr;
1221 int i = req->current_idx;
1222 uint32_t flags;
1223 uint64_t search_message_id;
1224 uint64_t search_async_id;
1225 uint64_t found_id;
1227 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1229 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1230 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1231 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1234 * we don't need the request anymore
1235 * cancel requests never have a response
1237 DLIST_REMOVE(req->sconn->smb2.requests, req);
1238 TALLOC_FREE(req);
1240 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1241 const uint8_t *outhdr;
1242 uint64_t message_id;
1243 uint64_t async_id;
1245 i = cur->current_idx;
1247 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1249 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1250 async_id = BVAL(outhdr, SMB2_HDR_PID);
1252 if (flags & SMB2_HDR_FLAG_ASYNC) {
1253 if (search_async_id == async_id) {
1254 found_id = async_id;
1255 break;
1257 } else {
1258 if (search_message_id == message_id) {
1259 found_id = message_id;
1260 break;
1265 if (cur && cur->subreq) {
1266 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1267 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1268 "cancel opcode[%s] mid %llu\n",
1269 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1270 (unsigned long long)found_id ));
1271 tevent_req_cancel(cur->subreq);
1274 return NT_STATUS_OK;
1277 /*************************************************************
1278 Ensure an incoming tid is a valid one for us to access.
1279 Change to the associated uid credentials and chdir to the
1280 valid tid directory.
1281 *************************************************************/
1283 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1285 const uint8_t *inhdr;
1286 int i = req->current_idx;
1287 uint32_t in_flags;
1288 uint32_t in_tid;
1289 struct smbXsrv_tcon *tcon;
1290 NTSTATUS status;
1291 NTTIME now = timeval_to_nttime(&req->request_time);
1293 req->tcon = NULL;
1295 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1297 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1298 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1300 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1301 in_tid = req->last_tid;
1304 status = smb2srv_tcon_lookup(req->session,
1305 in_tid, now, &tcon);
1306 if (!NT_STATUS_IS_OK(status)) {
1307 return status;
1310 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1311 return NT_STATUS_ACCESS_DENIED;
1314 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1315 if (!set_current_service(tcon->compat, 0, true)) {
1316 return NT_STATUS_ACCESS_DENIED;
1319 req->tcon = tcon;
1320 req->last_tid = in_tid;
1322 return NT_STATUS_OK;
1325 /*************************************************************
1326 Ensure an incoming session_id is a valid one for us to access.
1327 *************************************************************/
1329 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1331 const uint8_t *inhdr;
1332 int i = req->current_idx;
1333 uint32_t in_flags;
1334 uint16_t in_opcode;
1335 uint64_t in_session_id;
1336 struct smbXsrv_session *session = NULL;
1337 struct auth_session_info *session_info;
1338 NTSTATUS status;
1339 NTTIME now = timeval_to_nttime(&req->request_time);
1341 req->session = NULL;
1342 req->tcon = NULL;
1344 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1346 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1347 in_opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1348 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1350 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1351 in_session_id = req->last_session_id;
1354 /* lookup an existing session */
1355 status = smb2srv_session_lookup(req->sconn->conn,
1356 in_session_id, now,
1357 &session);
1358 if (session) {
1359 req->session = session;
1360 req->last_session_id = in_session_id;
1362 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1363 switch (in_opcode) {
1364 case SMB2_OP_SESSSETUP:
1365 status = NT_STATUS_OK;
1366 break;
1367 default:
1368 break;
1371 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1372 switch (in_opcode) {
1373 case SMB2_OP_TCON:
1374 case SMB2_OP_CREATE:
1375 case SMB2_OP_GETINFO:
1376 case SMB2_OP_SETINFO:
1377 return NT_STATUS_INVALID_HANDLE;
1378 default:
1380 * Notice the check for
1381 * (session_info == NULL)
1382 * below.
1384 status = NT_STATUS_OK;
1385 break;
1388 if (!NT_STATUS_IS_OK(status)) {
1389 return status;
1392 session_info = session->global->auth_session_info;
1393 if (session_info == NULL) {
1394 return NT_STATUS_INVALID_HANDLE;
1397 set_current_user_info(session_info->unix_info->sanitized_username,
1398 session_info->unix_info->unix_name,
1399 session_info->info->domain_name);
1401 return NT_STATUS_OK;
1404 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1405 uint32_t data_length)
1407 uint16_t needed_charge;
1408 uint16_t credit_charge = 1;
1409 const uint8_t *inhdr;
1410 int i = req->current_idx;
1412 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1414 if (req->sconn->smb2.supports_multicredit) {
1415 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1416 credit_charge = MAX(credit_charge, 1);
1419 needed_charge = (data_length - 1)/ 65536 + 1;
1421 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1422 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1423 credit_charge, needed_charge));
1425 if (needed_charge > credit_charge) {
1426 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1427 credit_charge, needed_charge));
1428 return NT_STATUS_INVALID_PARAMETER;
1431 return NT_STATUS_OK;
1434 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1435 size_t expected_body_size)
1437 const uint8_t *inhdr;
1438 uint16_t opcode;
1439 const uint8_t *inbody;
1440 int i = req->current_idx;
1441 size_t body_size;
1442 size_t min_dyn_size = expected_body_size & 0x00000001;
1445 * The following should be checked already.
1447 if ((i+2) > req->in.vector_count) {
1448 return NT_STATUS_INTERNAL_ERROR;
1450 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1451 return NT_STATUS_INTERNAL_ERROR;
1453 if (req->in.vector[i+1].iov_len < 2) {
1454 return NT_STATUS_INTERNAL_ERROR;
1457 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1458 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1460 switch (opcode) {
1461 case SMB2_OP_IOCTL:
1462 case SMB2_OP_GETINFO:
1463 min_dyn_size = 0;
1464 break;
1468 * Now check the expected body size,
1469 * where the last byte might be in the
1470 * dynamic section..
1472 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1473 return NT_STATUS_INVALID_PARAMETER;
1475 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1476 return NT_STATUS_INVALID_PARAMETER;
1479 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1481 body_size = SVAL(inbody, 0x00);
1482 if (body_size != expected_body_size) {
1483 return NT_STATUS_INVALID_PARAMETER;
1486 return NT_STATUS_OK;
1489 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1491 const uint8_t *inhdr;
1492 int i = req->current_idx;
1493 uint16_t opcode;
1494 uint32_t flags;
1495 uint64_t mid;
1496 NTSTATUS status;
1497 NTSTATUS session_status;
1498 uint32_t allowed_flags;
1499 NTSTATUS return_value;
1500 struct smbXsrv_session *x = NULL;
1501 bool signing_required = false;
1503 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1505 /* TODO: verify more things */
1507 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1508 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1509 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1510 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1511 smb2_opcode_name(opcode),
1512 (unsigned long long)mid));
1514 if (get_Protocol() >= PROTOCOL_SMB2_02) {
1516 * once the protocol is negotiated
1517 * SMB2_OP_NEGPROT is not allowed anymore
1519 if (opcode == SMB2_OP_NEGPROT) {
1520 /* drop the connection */
1521 return NT_STATUS_INVALID_PARAMETER;
1523 } else {
1525 * if the protocol is not negotiated yet
1526 * only SMB2_OP_NEGPROT is allowed.
1528 if (opcode != SMB2_OP_NEGPROT) {
1529 /* drop the connection */
1530 return NT_STATUS_INVALID_PARAMETER;
1534 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1535 SMB2_HDR_FLAG_SIGNED |
1536 SMB2_HDR_FLAG_DFS;
1537 if (opcode == SMB2_OP_CANCEL) {
1538 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1540 if ((flags & ~allowed_flags) != 0) {
1541 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1545 * Check if the client provided a valid session id,
1546 * if so smbd_smb2_request_check_session() calls
1547 * set_current_user_info().
1549 * As some command don't require a valid session id
1550 * we defer the check of the session_status
1552 session_status = smbd_smb2_request_check_session(req);
1553 x = req->session;
1555 if (x != NULL) {
1556 signing_required = x->global->signing_required;
1558 if (opcode == SMB2_OP_SESSSETUP &&
1559 x->global->channels[0].signing_key.length) {
1560 signing_required = true;
1564 req->do_signing = false;
1565 if (flags & SMB2_HDR_FLAG_SIGNED) {
1566 struct smbXsrv_connection *conn;
1567 DATA_BLOB signing_key;
1569 if (x == NULL) {
1570 return smbd_smb2_request_error(
1571 req, NT_STATUS_ACCESS_DENIED);
1574 conn = x->connection;
1575 signing_key = x->global->channels[0].signing_key;
1577 if (!NT_STATUS_IS_OK(session_status)) {
1578 return smbd_smb2_request_error(req, session_status);
1581 req->do_signing = true;
1582 status = smb2_signing_check_pdu(signing_key,
1583 conn->protocol,
1584 &req->in.vector[i], 3);
1585 if (!NT_STATUS_IS_OK(status)) {
1586 return smbd_smb2_request_error(req, status);
1588 } else if (opcode == SMB2_OP_CANCEL) {
1589 /* Cancel requests are allowed to skip the signing */
1590 } else if (signing_required) {
1591 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1594 if (flags & SMB2_HDR_FLAG_CHAINED) {
1596 * This check is mostly for giving the correct error code
1597 * for compounded requests.
1599 * TODO: we may need to move this after the session
1600 * and tcon checks.
1602 if (!NT_STATUS_IS_OK(req->next_status)) {
1603 return smbd_smb2_request_error(req, req->next_status);
1605 } else {
1606 req->compat_chain_fsp = NULL;
1609 if (req->compound_related) {
1610 req->sconn->smb2.compound_related_in_progress = true;
1613 switch (opcode) {
1614 case SMB2_OP_NEGPROT:
1615 /* This call needs to be run as root */
1616 change_to_root_user();
1619 START_PROFILE(smb2_negprot);
1620 return_value = smbd_smb2_request_process_negprot(req);
1621 END_PROFILE(smb2_negprot);
1623 break;
1625 case SMB2_OP_SESSSETUP:
1626 /* This call needs to be run as root */
1627 change_to_root_user();
1630 START_PROFILE(smb2_sesssetup);
1631 return_value = smbd_smb2_request_process_sesssetup(req);
1632 END_PROFILE(smb2_sesssetup);
1634 break;
1636 case SMB2_OP_LOGOFF:
1637 if (!NT_STATUS_IS_OK(session_status)) {
1638 return_value = smbd_smb2_request_error(req, session_status);
1639 break;
1642 /* This call needs to be run as root */
1643 change_to_root_user();
1646 START_PROFILE(smb2_logoff);
1647 return_value = smbd_smb2_request_process_logoff(req);
1648 END_PROFILE(smb2_logoff);
1650 break;
1652 case SMB2_OP_TCON:
1653 if (!NT_STATUS_IS_OK(session_status)) {
1654 return_value = smbd_smb2_request_error(req, session_status);
1655 break;
1659 * This call needs to be run as root.
1661 * smbd_smb2_request_process_tcon()
1662 * calls make_connection_snum(), which will call
1663 * change_to_user(), when needed.
1665 change_to_root_user();
1668 START_PROFILE(smb2_tcon);
1669 return_value = smbd_smb2_request_process_tcon(req);
1670 END_PROFILE(smb2_tcon);
1672 break;
1674 case SMB2_OP_TDIS:
1675 if (!NT_STATUS_IS_OK(session_status)) {
1676 return_value = smbd_smb2_request_error(req, session_status);
1677 break;
1680 * This call needs to be run as user.
1682 * smbd_smb2_request_check_tcon()
1683 * calls change_to_user() on success.
1685 status = smbd_smb2_request_check_tcon(req);
1686 if (!NT_STATUS_IS_OK(status)) {
1687 return_value = smbd_smb2_request_error(req, status);
1688 break;
1690 /* This call needs to be run as root */
1691 change_to_root_user();
1695 START_PROFILE(smb2_tdis);
1696 return_value = smbd_smb2_request_process_tdis(req);
1697 END_PROFILE(smb2_tdis);
1699 break;
1701 case SMB2_OP_CREATE:
1702 if (!NT_STATUS_IS_OK(session_status)) {
1703 return_value = smbd_smb2_request_error(req, session_status);
1704 break;
1707 * This call needs to be run as user.
1709 * smbd_smb2_request_check_tcon()
1710 * calls change_to_user() on success.
1712 status = smbd_smb2_request_check_tcon(req);
1713 if (!NT_STATUS_IS_OK(status)) {
1714 return_value = smbd_smb2_request_error(req, status);
1715 break;
1719 START_PROFILE(smb2_create);
1720 return_value = smbd_smb2_request_process_create(req);
1721 END_PROFILE(smb2_create);
1723 break;
1725 case SMB2_OP_CLOSE:
1726 if (!NT_STATUS_IS_OK(session_status)) {
1727 return_value = smbd_smb2_request_error(req, session_status);
1728 break;
1731 * This call needs to be run as user.
1733 * smbd_smb2_request_check_tcon()
1734 * calls change_to_user() on success.
1736 status = smbd_smb2_request_check_tcon(req);
1737 if (!NT_STATUS_IS_OK(status)) {
1738 return_value = smbd_smb2_request_error(req, status);
1739 break;
1743 START_PROFILE(smb2_close);
1744 return_value = smbd_smb2_request_process_close(req);
1745 END_PROFILE(smb2_close);
1747 break;
1749 case SMB2_OP_FLUSH:
1750 if (!NT_STATUS_IS_OK(session_status)) {
1751 return_value = smbd_smb2_request_error(req, session_status);
1752 break;
1755 * This call needs to be run as user.
1757 * smbd_smb2_request_check_tcon()
1758 * calls change_to_user() on success.
1760 status = smbd_smb2_request_check_tcon(req);
1761 if (!NT_STATUS_IS_OK(status)) {
1762 return_value = smbd_smb2_request_error(req, status);
1763 break;
1767 START_PROFILE(smb2_flush);
1768 return_value = smbd_smb2_request_process_flush(req);
1769 END_PROFILE(smb2_flush);
1771 break;
1773 case SMB2_OP_READ:
1774 if (!NT_STATUS_IS_OK(session_status)) {
1775 return_value = smbd_smb2_request_error(req, session_status);
1776 break;
1779 * This call needs to be run as user.
1781 * smbd_smb2_request_check_tcon()
1782 * calls change_to_user() on success.
1784 status = smbd_smb2_request_check_tcon(req);
1785 if (!NT_STATUS_IS_OK(status)) {
1786 return_value = smbd_smb2_request_error(req, status);
1787 break;
1791 START_PROFILE(smb2_read);
1792 return_value = smbd_smb2_request_process_read(req);
1793 END_PROFILE(smb2_read);
1795 break;
1797 case SMB2_OP_WRITE:
1798 if (!NT_STATUS_IS_OK(session_status)) {
1799 return_value = smbd_smb2_request_error(req, session_status);
1800 break;
1803 * This call needs to be run as user.
1805 * smbd_smb2_request_check_tcon()
1806 * calls change_to_user() on success.
1808 status = smbd_smb2_request_check_tcon(req);
1809 if (!NT_STATUS_IS_OK(status)) {
1810 return_value = smbd_smb2_request_error(req, status);
1811 break;
1815 START_PROFILE(smb2_write);
1816 return_value = smbd_smb2_request_process_write(req);
1817 END_PROFILE(smb2_write);
1819 break;
1821 case SMB2_OP_LOCK:
1822 if (!NT_STATUS_IS_OK(session_status)) {
1823 /* Too ugly to live ? JRA. */
1824 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1825 session_status = NT_STATUS_FILE_CLOSED;
1827 return_value = smbd_smb2_request_error(req, session_status);
1828 break;
1831 * This call needs to be run as user.
1833 * smbd_smb2_request_check_tcon()
1834 * calls change_to_user() on success.
1836 status = smbd_smb2_request_check_tcon(req);
1837 if (!NT_STATUS_IS_OK(status)) {
1838 /* Too ugly to live ? JRA. */
1839 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1840 status = NT_STATUS_FILE_CLOSED;
1842 return_value = smbd_smb2_request_error(req, status);
1843 break;
1847 START_PROFILE(smb2_lock);
1848 return_value = smbd_smb2_request_process_lock(req);
1849 END_PROFILE(smb2_lock);
1851 break;
1853 case SMB2_OP_IOCTL:
1854 if (!NT_STATUS_IS_OK(session_status)) {
1855 return_value = smbd_smb2_request_error(req, session_status);
1856 break;
1859 * This call needs to be run as user.
1861 * smbd_smb2_request_check_tcon()
1862 * calls change_to_user() on success.
1864 status = smbd_smb2_request_check_tcon(req);
1865 if (!NT_STATUS_IS_OK(status)) {
1866 return_value = smbd_smb2_request_error(req, status);
1867 break;
1871 START_PROFILE(smb2_ioctl);
1872 return_value = smbd_smb2_request_process_ioctl(req);
1873 END_PROFILE(smb2_ioctl);
1875 break;
1877 case SMB2_OP_CANCEL:
1879 * This call needs to be run as root
1881 * That is what we also do in the SMB1 case.
1883 change_to_root_user();
1886 START_PROFILE(smb2_cancel);
1887 return_value = smbd_smb2_request_process_cancel(req);
1888 END_PROFILE(smb2_cancel);
1890 break;
1892 case SMB2_OP_KEEPALIVE:
1893 /* This call needs to be run as root */
1894 change_to_root_user();
1897 START_PROFILE(smb2_keepalive);
1898 return_value = smbd_smb2_request_process_keepalive(req);
1899 END_PROFILE(smb2_keepalive);
1901 break;
1903 case SMB2_OP_FIND:
1904 if (!NT_STATUS_IS_OK(session_status)) {
1905 return_value = smbd_smb2_request_error(req, session_status);
1906 break;
1909 * This call needs to be run as user.
1911 * smbd_smb2_request_check_tcon()
1912 * calls change_to_user() on success.
1914 status = smbd_smb2_request_check_tcon(req);
1915 if (!NT_STATUS_IS_OK(status)) {
1916 return_value = smbd_smb2_request_error(req, status);
1917 break;
1921 START_PROFILE(smb2_find);
1922 return_value = smbd_smb2_request_process_find(req);
1923 END_PROFILE(smb2_find);
1925 break;
1927 case SMB2_OP_NOTIFY:
1928 if (!NT_STATUS_IS_OK(session_status)) {
1929 return_value = smbd_smb2_request_error(req, session_status);
1930 break;
1933 * This call needs to be run as user.
1935 * smbd_smb2_request_check_tcon()
1936 * calls change_to_user() on success.
1938 status = smbd_smb2_request_check_tcon(req);
1939 if (!NT_STATUS_IS_OK(status)) {
1940 return_value = smbd_smb2_request_error(req, status);
1941 break;
1945 START_PROFILE(smb2_notify);
1946 return_value = smbd_smb2_request_process_notify(req);
1947 END_PROFILE(smb2_notify);
1949 break;
1951 case SMB2_OP_GETINFO:
1952 if (!NT_STATUS_IS_OK(session_status)) {
1953 return_value = smbd_smb2_request_error(req, session_status);
1954 break;
1957 * This call needs to be run as user.
1959 * smbd_smb2_request_check_tcon()
1960 * calls change_to_user() on success.
1962 status = smbd_smb2_request_check_tcon(req);
1963 if (!NT_STATUS_IS_OK(status)) {
1964 return_value = smbd_smb2_request_error(req, status);
1965 break;
1969 START_PROFILE(smb2_getinfo);
1970 return_value = smbd_smb2_request_process_getinfo(req);
1971 END_PROFILE(smb2_getinfo);
1973 break;
1975 case SMB2_OP_SETINFO:
1976 if (!NT_STATUS_IS_OK(session_status)) {
1977 return_value = smbd_smb2_request_error(req, session_status);
1978 break;
1981 * This call needs to be run as user.
1983 * smbd_smb2_request_check_tcon()
1984 * calls change_to_user() on success.
1986 status = smbd_smb2_request_check_tcon(req);
1987 if (!NT_STATUS_IS_OK(status)) {
1988 return_value = smbd_smb2_request_error(req, status);
1989 break;
1993 START_PROFILE(smb2_setinfo);
1994 return_value = smbd_smb2_request_process_setinfo(req);
1995 END_PROFILE(smb2_setinfo);
1997 break;
1999 case SMB2_OP_BREAK:
2000 if (!NT_STATUS_IS_OK(session_status)) {
2001 return_value = smbd_smb2_request_error(req, session_status);
2002 break;
2005 * This call needs to be run as user.
2007 * smbd_smb2_request_check_tcon()
2008 * calls change_to_user() on success.
2010 status = smbd_smb2_request_check_tcon(req);
2011 if (!NT_STATUS_IS_OK(status)) {
2012 return_value = smbd_smb2_request_error(req, status);
2013 break;
2017 START_PROFILE(smb2_break);
2018 return_value = smbd_smb2_request_process_break(req);
2019 END_PROFILE(smb2_break);
2021 break;
2023 default:
2024 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2025 break;
2027 return return_value;
2030 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2032 struct tevent_req *subreq;
2033 int i = req->current_idx;
2035 req->subreq = NULL;
2036 TALLOC_FREE(req->async_te);
2038 req->current_idx += 3;
2040 if (req->current_idx < req->out.vector_count) {
2042 * We must process the remaining compound
2043 * SMB2 requests before any new incoming SMB2
2044 * requests. This is because incoming SMB2
2045 * requests may include a cancel for a
2046 * compound request we haven't processed
2047 * yet.
2049 struct tevent_immediate *im = tevent_create_immediate(req);
2050 if (!im) {
2051 return NT_STATUS_NO_MEMORY;
2053 tevent_schedule_immediate(im,
2054 req->sconn->ev_ctx,
2055 smbd_smb2_request_dispatch_immediate,
2056 req);
2057 return NT_STATUS_OK;
2060 if (req->compound_related) {
2061 req->sconn->smb2.compound_related_in_progress = false;
2064 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2066 /* Set credit for these operations (zero credits if this
2067 is a final reply for an async operation). */
2068 smb2_calculate_credits(req, req);
2070 if (req->do_signing) {
2071 NTSTATUS status;
2072 struct smbXsrv_session *x = req->session;
2073 struct smbXsrv_connection *conn = x->connection;
2074 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2076 status = smb2_signing_sign_pdu(signing_key,
2077 conn->protocol,
2078 &req->out.vector[i], 3);
2079 if (!NT_STATUS_IS_OK(status)) {
2080 return status;
2084 if (DEBUGLEVEL >= 10) {
2085 dbgtext("smbd_smb2_request_reply: sending...\n");
2086 print_req_vectors(req);
2089 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2090 if (req->out.vector_count == 4 &&
2091 req->out.vector[3].iov_base == NULL &&
2092 req->out.vector[3].iov_len != 0) {
2093 /* Dynamic part is NULL. Chop it off,
2094 We're going to send it via sendfile. */
2095 req->out.vector_count -= 1;
2098 subreq = tstream_writev_queue_send(req,
2099 req->sconn->ev_ctx,
2100 req->sconn->smb2.stream,
2101 req->sconn->smb2.send_queue,
2102 req->out.vector,
2103 req->out.vector_count);
2104 if (subreq == NULL) {
2105 return NT_STATUS_NO_MEMORY;
2107 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
2109 * We're done with this request -
2110 * move it off the "being processed" queue.
2112 DLIST_REMOVE(req->sconn->smb2.requests, req);
2114 return NT_STATUS_OK;
2117 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2119 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2120 struct tevent_immediate *im,
2121 void *private_data)
2123 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2124 struct smbd_smb2_request);
2125 struct smbd_server_connection *sconn = req->sconn;
2126 NTSTATUS status;
2128 TALLOC_FREE(im);
2130 if (DEBUGLEVEL >= 10) {
2131 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2132 req->current_idx, req->in.vector_count));
2133 print_req_vectors(req);
2136 status = smbd_smb2_request_dispatch(req);
2137 if (!NT_STATUS_IS_OK(status)) {
2138 smbd_server_connection_terminate(sconn, nt_errstr(status));
2139 return;
2142 status = smbd_smb2_request_next_incoming(sconn);
2143 if (!NT_STATUS_IS_OK(status)) {
2144 smbd_server_connection_terminate(sconn, nt_errstr(status));
2145 return;
2149 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
2151 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
2152 struct smbd_smb2_request);
2153 struct smbd_server_connection *sconn = req->sconn;
2154 int ret;
2155 int sys_errno;
2156 NTSTATUS status;
2158 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2159 TALLOC_FREE(subreq);
2160 TALLOC_FREE(req);
2161 if (ret == -1) {
2162 status = map_nt_error_from_unix(sys_errno);
2163 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2164 nt_errstr(status)));
2165 smbd_server_connection_terminate(sconn, nt_errstr(status));
2166 return;
2169 status = smbd_smb2_request_next_incoming(sconn);
2170 if (!NT_STATUS_IS_OK(status)) {
2171 smbd_server_connection_terminate(sconn, nt_errstr(status));
2172 return;
2176 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2177 NTSTATUS status,
2178 DATA_BLOB body, DATA_BLOB *dyn,
2179 const char *location)
2181 uint8_t *outhdr;
2182 int i = req->current_idx;
2183 uint32_t next_command_ofs;
2185 DEBUG(10,("smbd_smb2_request_done_ex: "
2186 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2187 i, nt_errstr(status), (unsigned int)body.length,
2188 dyn ? "yes": "no",
2189 (unsigned int)(dyn ? dyn->length : 0),
2190 location));
2192 if (body.length < 2) {
2193 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2196 if ((body.length % 2) != 0) {
2197 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2200 outhdr = (uint8_t *)req->out.vector[i].iov_base;
2202 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2203 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2205 req->out.vector[i+1].iov_base = (void *)body.data;
2206 req->out.vector[i+1].iov_len = body.length;
2208 if (dyn) {
2209 req->out.vector[i+2].iov_base = (void *)dyn->data;
2210 req->out.vector[i+2].iov_len = dyn->length;
2211 } else {
2212 req->out.vector[i+2].iov_base = NULL;
2213 req->out.vector[i+2].iov_len = 0;
2216 /* see if we need to recalculate the offset to the next response */
2217 if (next_command_ofs > 0) {
2218 next_command_ofs = SMB2_HDR_BODY;
2219 next_command_ofs += req->out.vector[i+1].iov_len;
2220 next_command_ofs += req->out.vector[i+2].iov_len;
2223 if ((next_command_ofs % 8) != 0) {
2224 size_t pad_size = 8 - (next_command_ofs % 8);
2225 if (req->out.vector[i+2].iov_len == 0) {
2227 * if the dyn buffer is empty
2228 * we can use it to add padding
2230 uint8_t *pad;
2232 pad = talloc_zero_array(req->out.vector,
2233 uint8_t, pad_size);
2234 if (pad == NULL) {
2235 return smbd_smb2_request_error(req,
2236 NT_STATUS_NO_MEMORY);
2239 req->out.vector[i+2].iov_base = (void *)pad;
2240 req->out.vector[i+2].iov_len = pad_size;
2241 } else {
2243 * For now we copy the dynamic buffer
2244 * and add the padding to the new buffer
2246 size_t old_size;
2247 uint8_t *old_dyn;
2248 size_t new_size;
2249 uint8_t *new_dyn;
2251 old_size = req->out.vector[i+2].iov_len;
2252 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2254 new_size = old_size + pad_size;
2255 new_dyn = talloc_zero_array(req->out.vector,
2256 uint8_t, new_size);
2257 if (new_dyn == NULL) {
2258 return smbd_smb2_request_error(req,
2259 NT_STATUS_NO_MEMORY);
2262 memcpy(new_dyn, old_dyn, old_size);
2263 memset(new_dyn + old_size, 0, pad_size);
2265 req->out.vector[i+2].iov_base = (void *)new_dyn;
2266 req->out.vector[i+2].iov_len = new_size;
2268 next_command_ofs += pad_size;
2271 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2273 return smbd_smb2_request_reply(req);
2276 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2277 NTSTATUS status,
2278 DATA_BLOB *info,
2279 const char *location)
2281 DATA_BLOB body;
2282 int i = req->current_idx;
2283 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
2285 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2286 i, nt_errstr(status), info ? " +info" : "",
2287 location));
2289 body.data = outhdr + SMB2_HDR_BODY;
2290 body.length = 8;
2291 SSVAL(body.data, 0, 9);
2293 if (info) {
2294 SIVAL(body.data, 0x04, info->length);
2295 } else {
2296 /* Allocated size of req->out.vector[i].iov_base
2297 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2298 * 1 byte without having to do an alloc.
2300 info = talloc_zero_array(req->out.vector,
2301 DATA_BLOB,
2303 if (!info) {
2304 return NT_STATUS_NO_MEMORY;
2306 info->data = ((uint8_t *)outhdr) +
2307 OUTVEC_ALLOC_SIZE - 1;
2308 info->length = 1;
2309 SCVAL(info->data, 0, 0);
2313 * if a request fails, all other remaining
2314 * compounded requests should fail too
2316 req->next_status = NT_STATUS_INVALID_PARAMETER;
2318 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2322 struct smbd_smb2_send_oplock_break_state {
2323 struct smbd_server_connection *sconn;
2324 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2325 struct iovec vector;
2328 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2330 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2331 uint64_t file_id_persistent,
2332 uint64_t file_id_volatile,
2333 uint8_t oplock_level)
2335 struct smbd_smb2_send_oplock_break_state *state;
2336 struct tevent_req *subreq;
2337 uint8_t *hdr;
2338 uint8_t *body;
2340 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2341 if (state == NULL) {
2342 return NT_STATUS_NO_MEMORY;
2344 state->sconn = sconn;
2346 state->vector.iov_base = (void *)state->buf;
2347 state->vector.iov_len = sizeof(state->buf);
2349 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2350 hdr = state->buf + 4;
2351 body = hdr + SMB2_HDR_BODY;
2353 SIVAL(hdr, 0, SMB2_MAGIC);
2354 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2355 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2356 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2357 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2358 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2359 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2360 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2361 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2362 SIVAL(hdr, SMB2_HDR_PID, 0);
2363 SIVAL(hdr, SMB2_HDR_TID, 0);
2364 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2365 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2367 SSVAL(body, 0x00, 0x18);
2369 SCVAL(body, 0x02, oplock_level);
2370 SCVAL(body, 0x03, 0); /* reserved */
2371 SIVAL(body, 0x04, 0); /* reserved */
2372 SBVAL(body, 0x08, file_id_persistent);
2373 SBVAL(body, 0x10, file_id_volatile);
2375 subreq = tstream_writev_queue_send(state,
2376 sconn->ev_ctx,
2377 sconn->smb2.stream,
2378 sconn->smb2.send_queue,
2379 &state->vector, 1);
2380 if (subreq == NULL) {
2381 return NT_STATUS_NO_MEMORY;
2383 tevent_req_set_callback(subreq,
2384 smbd_smb2_oplock_break_writev_done,
2385 state);
2387 return NT_STATUS_OK;
2390 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2392 struct smbd_smb2_send_oplock_break_state *state =
2393 tevent_req_callback_data(subreq,
2394 struct smbd_smb2_send_oplock_break_state);
2395 struct smbd_server_connection *sconn = state->sconn;
2396 int ret;
2397 int sys_errno;
2399 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2400 TALLOC_FREE(subreq);
2401 if (ret == -1) {
2402 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2403 smbd_server_connection_terminate(sconn, nt_errstr(status));
2404 return;
2407 TALLOC_FREE(state);
2410 struct smbd_smb2_request_read_state {
2411 size_t missing;
2412 bool asked_for_header;
2413 struct smbd_smb2_request *smb2_req;
2416 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2417 void *private_data,
2418 TALLOC_CTX *mem_ctx,
2419 struct iovec **_vector,
2420 size_t *_count);
2421 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2423 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2424 struct tevent_context *ev,
2425 struct smbd_server_connection *sconn)
2427 struct tevent_req *req;
2428 struct smbd_smb2_request_read_state *state;
2429 struct tevent_req *subreq;
2431 req = tevent_req_create(mem_ctx, &state,
2432 struct smbd_smb2_request_read_state);
2433 if (req == NULL) {
2434 return NULL;
2436 state->missing = 0;
2437 state->asked_for_header = false;
2439 state->smb2_req = smbd_smb2_request_allocate(state);
2440 if (tevent_req_nomem(state->smb2_req, req)) {
2441 return tevent_req_post(req, ev);
2443 state->smb2_req->sconn = sconn;
2445 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2446 sconn->smb2.recv_queue,
2447 smbd_smb2_request_next_vector,
2448 state);
2449 if (tevent_req_nomem(subreq, req)) {
2450 return tevent_req_post(req, ev);
2452 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2454 return req;
2457 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2458 void *private_data,
2459 TALLOC_CTX *mem_ctx,
2460 struct iovec **_vector,
2461 size_t *_count)
2463 struct smbd_smb2_request_read_state *state =
2464 talloc_get_type_abort(private_data,
2465 struct smbd_smb2_request_read_state);
2466 struct smbd_smb2_request *req = state->smb2_req;
2467 struct iovec *vector;
2468 int idx = req->in.vector_count;
2469 size_t len = 0;
2470 uint8_t *buf = NULL;
2472 if (req->in.vector_count == 0) {
2474 * first we need to get the NBT header
2476 req->in.vector = talloc_array(req, struct iovec,
2477 req->in.vector_count + 1);
2478 if (req->in.vector == NULL) {
2479 return -1;
2481 req->in.vector_count += 1;
2483 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2484 req->in.vector[idx].iov_len = 4;
2486 vector = talloc_array(mem_ctx, struct iovec, 1);
2487 if (vector == NULL) {
2488 return -1;
2491 vector[0] = req->in.vector[idx];
2493 *_vector = vector;
2494 *_count = 1;
2495 return 0;
2498 if (req->in.vector_count == 1) {
2500 * Now we analyze the NBT header
2502 state->missing = smb2_len(req->in.vector[0].iov_base);
2504 if (state->missing == 0) {
2505 /* if there're no remaining bytes, we're done */
2506 *_vector = NULL;
2507 *_count = 0;
2508 return 0;
2511 req->in.vector = talloc_realloc(req, req->in.vector,
2512 struct iovec,
2513 req->in.vector_count + 1);
2514 if (req->in.vector == NULL) {
2515 return -1;
2517 req->in.vector_count += 1;
2519 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2521 * it's a special NBT message,
2522 * so get all remaining bytes
2524 len = state->missing;
2525 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2527 * it's an invalid message, just read what we can get
2528 * and let the caller handle the error
2530 len = state->missing;
2531 } else {
2533 * We assume it's a SMB2 request,
2534 * and we first get the header and the
2535 * first 2 bytes (the struct size) of the body
2537 len = SMB2_HDR_BODY + 2;
2539 state->asked_for_header = true;
2542 state->missing -= len;
2544 buf = talloc_array(req->in.vector, uint8_t, len);
2545 if (buf == NULL) {
2546 return -1;
2549 req->in.vector[idx].iov_base = (void *)buf;
2550 req->in.vector[idx].iov_len = len;
2552 vector = talloc_array(mem_ctx, struct iovec, 1);
2553 if (vector == NULL) {
2554 return -1;
2557 vector[0] = req->in.vector[idx];
2559 *_vector = vector;
2560 *_count = 1;
2561 return 0;
2564 if (state->missing == 0) {
2565 /* if there're no remaining bytes, we're done */
2566 *_vector = NULL;
2567 *_count = 0;
2568 return 0;
2571 if (state->asked_for_header) {
2572 const uint8_t *hdr;
2573 size_t full_size;
2574 size_t next_command_ofs;
2575 size_t body_size;
2576 uint8_t *body;
2577 size_t dyn_size;
2578 uint8_t *dyn;
2579 bool invalid = false;
2581 state->asked_for_header = false;
2584 * We got the SMB2 header and the first 2 bytes
2585 * of the body. We fix the size to just the header
2586 * and manually copy the 2 first bytes to the body section
2588 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2589 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2591 /* allocate vectors for body and dynamic areas */
2592 req->in.vector = talloc_realloc(req, req->in.vector,
2593 struct iovec,
2594 req->in.vector_count + 2);
2595 if (req->in.vector == NULL) {
2596 return -1;
2598 req->in.vector_count += 2;
2600 full_size = state->missing + SMB2_HDR_BODY + 2;
2601 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2602 body_size = SVAL(hdr, SMB2_HDR_BODY);
2604 if (next_command_ofs != 0) {
2605 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2607 * this is invalid, just return a zero
2608 * body and let the caller deal with the error
2610 invalid = true;
2611 } else if (next_command_ofs > full_size) {
2613 * this is invalid, just return a zero
2614 * body and let the caller deal with the error
2616 invalid = true;
2617 } else {
2618 full_size = next_command_ofs;
2622 if (!invalid) {
2623 if (body_size < 2) {
2625 * this is invalid, just return a zero
2626 * body and let the caller deal with the error
2628 invalid = true;
2632 * Mask out the lowest bit, the "dynamic" part
2633 * of body_size.
2635 body_size &= ~1;
2637 if (body_size > (full_size - SMB2_HDR_BODY)) {
2639 * this is invalid, just return a zero
2640 * body and let the caller deal with the error
2642 invalid = true;
2646 if (invalid) {
2647 /* the caller should check this */
2648 body_size = 2;
2651 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2653 state->missing -= (body_size - 2) + dyn_size;
2655 body = talloc_array(req->in.vector, uint8_t, body_size);
2656 if (body == NULL) {
2657 return -1;
2660 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2661 if (dyn == NULL) {
2662 return -1;
2665 req->in.vector[idx].iov_base = (void *)body;
2666 req->in.vector[idx].iov_len = body_size;
2667 req->in.vector[idx+1].iov_base = (void *)dyn;
2668 req->in.vector[idx+1].iov_len = dyn_size;
2670 vector = talloc_array(mem_ctx, struct iovec, 2);
2671 if (vector == NULL) {
2672 return -1;
2676 * the first 2 bytes of the body were already fetched
2677 * together with the header
2679 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2680 vector[0].iov_base = body + 2;
2681 vector[0].iov_len = body_size - 2;
2683 vector[1] = req->in.vector[idx+1];
2685 *_vector = vector;
2686 *_count = 2;
2687 return 0;
2691 * when we endup here, we're looking for a new SMB2 request
2692 * next. And we ask for its header and the first 2 bytes of
2693 * the body (like we did for the first SMB2 request).
2696 req->in.vector = talloc_realloc(req, req->in.vector,
2697 struct iovec,
2698 req->in.vector_count + 1);
2699 if (req->in.vector == NULL) {
2700 return -1;
2702 req->in.vector_count += 1;
2705 * We assume it's a SMB2 request,
2706 * and we first get the header and the
2707 * first 2 bytes (the struct size) of the body
2709 len = SMB2_HDR_BODY + 2;
2711 if (len > state->missing) {
2712 /* let the caller handle the error */
2713 len = state->missing;
2716 state->missing -= len;
2717 state->asked_for_header = true;
2719 buf = talloc_array(req->in.vector, uint8_t, len);
2720 if (buf == NULL) {
2721 return -1;
2724 req->in.vector[idx].iov_base = (void *)buf;
2725 req->in.vector[idx].iov_len = len;
2727 vector = talloc_array(mem_ctx, struct iovec, 1);
2728 if (vector == NULL) {
2729 return -1;
2732 vector[0] = req->in.vector[idx];
2734 *_vector = vector;
2735 *_count = 1;
2736 return 0;
2739 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2741 struct tevent_req *req =
2742 tevent_req_callback_data(subreq,
2743 struct tevent_req);
2744 int ret;
2745 int sys_errno;
2746 NTSTATUS status;
2748 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2749 if (ret == -1) {
2750 status = map_nt_error_from_unix(sys_errno);
2751 tevent_req_nterror(req, status);
2752 return;
2755 tevent_req_done(req);
2758 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2759 TALLOC_CTX *mem_ctx,
2760 struct smbd_smb2_request **_smb2_req)
2762 struct smbd_smb2_request_read_state *state =
2763 tevent_req_data(req,
2764 struct smbd_smb2_request_read_state);
2765 NTSTATUS status;
2767 if (tevent_req_is_nterror(req, &status)) {
2768 tevent_req_received(req);
2769 return status;
2772 *_smb2_req = talloc_move(mem_ctx, &state->smb2_req);
2773 tevent_req_received(req);
2774 return NT_STATUS_OK;
2777 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2779 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2781 size_t max_send_queue_len;
2782 size_t cur_send_queue_len;
2783 struct tevent_req *subreq;
2785 if (sconn->smb2.compound_related_in_progress) {
2787 * Can't read another until the related
2788 * compound is done.
2790 return NT_STATUS_OK;
2793 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2795 * if there is already a smbd_smb2_request_read
2796 * pending, we are done.
2798 return NT_STATUS_OK;
2801 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2802 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2804 if (cur_send_queue_len > max_send_queue_len) {
2806 * if we have a lot of requests to send,
2807 * we wait until they are on the wire until we
2808 * ask for the next request.
2810 return NT_STATUS_OK;
2813 /* ask for the next request */
2814 subreq = smbd_smb2_request_read_send(sconn, sconn->ev_ctx, sconn);
2815 if (subreq == NULL) {
2816 return NT_STATUS_NO_MEMORY;
2818 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2820 return NT_STATUS_OK;
2823 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2824 const uint8_t *inbuf, size_t size)
2826 NTSTATUS status;
2827 struct smbd_smb2_request *req = NULL;
2829 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2830 (unsigned int)size));
2832 status = smbd_initialize_smb2(sconn);
2833 if (!NT_STATUS_IS_OK(status)) {
2834 smbd_server_connection_terminate(sconn, nt_errstr(status));
2835 return;
2838 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2839 if (!NT_STATUS_IS_OK(status)) {
2840 smbd_server_connection_terminate(sconn, nt_errstr(status));
2841 return;
2844 status = smbd_smb2_request_validate(req);
2845 if (!NT_STATUS_IS_OK(status)) {
2846 smbd_server_connection_terminate(sconn, nt_errstr(status));
2847 return;
2850 status = smbd_smb2_request_setup_out(req);
2851 if (!NT_STATUS_IS_OK(status)) {
2852 smbd_server_connection_terminate(sconn, nt_errstr(status));
2853 return;
2856 status = smbd_smb2_request_dispatch(req);
2857 if (!NT_STATUS_IS_OK(status)) {
2858 smbd_server_connection_terminate(sconn, nt_errstr(status));
2859 return;
2862 status = smbd_smb2_request_next_incoming(sconn);
2863 if (!NT_STATUS_IS_OK(status)) {
2864 smbd_server_connection_terminate(sconn, nt_errstr(status));
2865 return;
2868 sconn->num_requests++;
2871 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2873 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2874 struct smbd_server_connection);
2875 NTSTATUS status;
2876 struct smbd_smb2_request *req = NULL;
2878 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2879 TALLOC_FREE(subreq);
2880 if (!NT_STATUS_IS_OK(status)) {
2881 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2882 nt_errstr(status)));
2883 smbd_server_connection_terminate(sconn, nt_errstr(status));
2884 return;
2887 if (req->in.nbt_hdr[0] != 0x00) {
2888 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2889 req->in.nbt_hdr[0]));
2890 TALLOC_FREE(req);
2891 goto next;
2894 req->current_idx = 1;
2896 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2897 req->current_idx, req->in.vector_count));
2899 status = smbd_smb2_request_validate(req);
2900 if (!NT_STATUS_IS_OK(status)) {
2901 smbd_server_connection_terminate(sconn, nt_errstr(status));
2902 return;
2905 status = smbd_smb2_request_setup_out(req);
2906 if (!NT_STATUS_IS_OK(status)) {
2907 smbd_server_connection_terminate(sconn, nt_errstr(status));
2908 return;
2911 status = smbd_smb2_request_dispatch(req);
2912 if (!NT_STATUS_IS_OK(status)) {
2913 smbd_server_connection_terminate(sconn, nt_errstr(status));
2914 return;
2917 next:
2918 status = smbd_smb2_request_next_incoming(sconn);
2919 if (!NT_STATUS_IS_OK(status)) {
2920 smbd_server_connection_terminate(sconn, nt_errstr(status));
2921 return;
2924 sconn->num_requests++;
2926 /* The timeout_processing function isn't run nearly
2927 often enough to implement 'max log size' without
2928 overrunning the size of the file by many megabytes.
2929 This is especially true if we are running at debug
2930 level 10. Checking every 50 SMB2s is a nice
2931 tradeoff of performance vs log file size overrun. */
2933 if ((sconn->num_requests % 50) == 0 &&
2934 need_to_check_log_size()) {
2935 change_to_root_user();
2936 check_log_size();