Add some const to can_delete_file_in_directory().
[Samba.git] / source3 / smbd / smb2_server.c
blobcef0677ed1dbcf1d3f3c0bca5ae33356cc9c39c6
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"
30 #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9)
32 static const char *smb2_names[] = {
33 "SMB2_NEGPROT",
34 "SMB2_SESSSETUP",
35 "SMB2_LOGOFF",
36 "SMB2_TCON",
37 "SMB2_TDIS",
38 "SMB2_CREATE",
39 "SMB2_CLOSE",
40 "SMB2_FLUSH",
41 "SMB2_READ",
42 "SMB2_WRITE",
43 "SMB2_LOCK",
44 "SMB2_IOCTL",
45 "SMB2_CANCEL",
46 "SMB2_KEEPALIVE",
47 "SMB2_FIND",
48 "SMB2_NOTIFY",
49 "SMB2_GETINFO",
50 "SMB2_SETINFO",
51 "SMB2_BREAK"
54 const char *smb2_opcode_name(uint16_t opcode)
56 if (opcode > 0x12) {
57 return "Bad SMB2 opcode";
59 return smb2_names[opcode];
62 static void print_req_vectors(struct smbd_smb2_request *req)
64 int i;
66 for (i = 0; i < req->in.vector_count; i++) {
67 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
68 (unsigned int)i,
69 (unsigned int)req->in.vector[i].iov_len);
71 for (i = 0; i < req->out.vector_count; i++) {
72 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
73 (unsigned int)i,
74 (unsigned int)req->out.vector[i].iov_len);
78 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
80 if (size < (4 + SMB2_HDR_BODY)) {
81 return false;
84 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
85 return false;
88 return true;
91 static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
93 NTSTATUS status;
94 int ret;
96 TALLOC_FREE(sconn->smb1.fde);
98 sconn->smb2.event_ctx = smbd_event_context();
100 sconn->smb2.recv_queue = tevent_queue_create(sconn, "smb2 recv queue");
101 if (sconn->smb2.recv_queue == NULL) {
102 return NT_STATUS_NO_MEMORY;
105 sconn->smb2.send_queue = tevent_queue_create(sconn, "smb2 send queue");
106 if (sconn->smb2.send_queue == NULL) {
107 return NT_STATUS_NO_MEMORY;
110 sconn->smb2.sessions.idtree = idr_init(sconn);
111 if (sconn->smb2.sessions.idtree == NULL) {
112 return NT_STATUS_NO_MEMORY;
114 sconn->smb2.sessions.limit = 0x0000FFFE;
115 sconn->smb2.sessions.list = NULL;
116 sconn->smb2.seqnum_low = 0;
117 sconn->smb2.seqnum_range = 1;
118 sconn->smb2.credits_granted = 1;
119 sconn->smb2.max_credits = lp_smb2_max_credits();
120 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
121 sconn->smb2.max_credits);
122 if (sconn->smb2.credits_bitmap == NULL) {
123 return NT_STATUS_NO_MEMORY;
126 ret = tstream_bsd_existing_socket(sconn, sconn->sock,
127 &sconn->smb2.stream);
128 if (ret == -1) {
129 status = map_nt_error_from_unix(errno);
130 return status;
133 /* Ensure child is set to non-blocking mode */
134 set_blocking(sconn->sock, false);
135 return NT_STATUS_OK;
138 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
139 #define _smb2_setlen(_buf,len) do { \
140 uint8_t *buf = (uint8_t *)_buf; \
141 buf[0] = 0; \
142 buf[1] = ((len)&0xFF0000)>>16; \
143 buf[2] = ((len)&0xFF00)>>8; \
144 buf[3] = (len)&0xFF; \
145 } while (0)
147 static void smb2_setup_nbt_length(struct iovec *vector, int count)
149 size_t len = 0;
150 int i;
152 for (i=1; i < count; i++) {
153 len += vector[i].iov_len;
156 _smb2_setlen(vector[0].iov_base, len);
159 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request **req)
161 if (*req) {
162 (*req)->parent = NULL;
163 (*req)->mem_pool = NULL;
166 return 0;
169 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
171 if (req->parent) {
172 *req->parent = NULL;
173 talloc_free(req->mem_pool);
176 return 0;
179 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
181 TALLOC_CTX *mem_pool;
182 struct smbd_smb2_request **parent;
183 struct smbd_smb2_request *req;
185 #if 0
186 /* Enable this to find subtle valgrind errors. */
187 mem_pool = talloc_init("smbd_smb2_request_allocate");
188 #else
189 mem_pool = talloc_pool(mem_ctx, 8192);
190 #endif
191 if (mem_pool == NULL) {
192 return NULL;
195 parent = talloc(mem_pool, struct smbd_smb2_request *);
196 if (parent == NULL) {
197 talloc_free(mem_pool);
198 return NULL;
201 req = talloc_zero(parent, struct smbd_smb2_request);
202 if (req == NULL) {
203 talloc_free(mem_pool);
204 return NULL;
206 *parent = req;
207 req->mem_pool = mem_pool;
208 req->parent = parent;
210 req->last_session_id = UINT64_MAX;
211 req->last_tid = UINT32_MAX;
213 talloc_set_destructor(parent, smbd_smb2_request_parent_destructor);
214 talloc_set_destructor(req, smbd_smb2_request_destructor);
216 return req;
219 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
220 const uint8_t *inbuf, size_t size,
221 struct smbd_smb2_request **_req)
223 struct smbd_smb2_request *req;
224 uint32_t protocol_version;
225 const uint8_t *inhdr = NULL;
226 off_t ofs = 0;
227 uint16_t cmd;
228 uint32_t next_command_ofs;
230 if (size < (4 + SMB2_HDR_BODY + 2)) {
231 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
232 return NT_STATUS_INVALID_PARAMETER;
235 inhdr = inbuf + 4;
237 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
238 if (protocol_version != SMB2_MAGIC) {
239 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
240 protocol_version));
241 return NT_STATUS_INVALID_PARAMETER;
244 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
245 if (cmd != SMB2_OP_NEGPROT) {
246 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
247 cmd));
248 return NT_STATUS_INVALID_PARAMETER;
251 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
252 if (next_command_ofs != 0) {
253 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
254 next_command_ofs));
255 return NT_STATUS_INVALID_PARAMETER;
258 req = smbd_smb2_request_allocate(sconn);
259 if (req == NULL) {
260 return NT_STATUS_NO_MEMORY;
262 req->sconn = sconn;
264 talloc_steal(req, inbuf);
266 req->in.vector = talloc_array(req, struct iovec, 4);
267 if (req->in.vector == NULL) {
268 TALLOC_FREE(req);
269 return NT_STATUS_NO_MEMORY;
271 req->in.vector_count = 4;
273 memcpy(req->in.nbt_hdr, inbuf, 4);
275 ofs = 0;
276 req->in.vector[0].iov_base = (void *)req->in.nbt_hdr;
277 req->in.vector[0].iov_len = 4;
278 ofs += req->in.vector[0].iov_len;
280 req->in.vector[1].iov_base = (void *)(inbuf + ofs);
281 req->in.vector[1].iov_len = SMB2_HDR_BODY;
282 ofs += req->in.vector[1].iov_len;
284 req->in.vector[2].iov_base = (void *)(inbuf + ofs);
285 req->in.vector[2].iov_len = SVAL(inbuf, ofs) & 0xFFFE;
286 ofs += req->in.vector[2].iov_len;
288 if (ofs > size) {
289 return NT_STATUS_INVALID_PARAMETER;
292 req->in.vector[3].iov_base = (void *)(inbuf + ofs);
293 req->in.vector[3].iov_len = size - ofs;
294 ofs += req->in.vector[3].iov_len;
296 req->current_idx = 1;
298 *_req = req;
299 return NT_STATUS_OK;
302 static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
303 uint64_t message_id, uint64_t seq_id)
305 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
306 unsigned int offset;
308 if (seq_id < sconn->smb2.seqnum_low) {
309 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
310 "%llu (sequence id %llu) "
311 "(granted = %u, low = %llu, range = %u)\n",
312 (unsigned long long)message_id,
313 (unsigned long long)seq_id,
314 (unsigned int)sconn->smb2.credits_granted,
315 (unsigned long long)sconn->smb2.seqnum_low,
316 (unsigned int)sconn->smb2.seqnum_range));
317 return false;
320 if (seq_id >= sconn->smb2.seqnum_low + sconn->smb2.seqnum_range) {
321 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
322 "%llu (sequence id %llu) "
323 "(granted = %u, low = %llu, range = %u)\n",
324 (unsigned long long)message_id,
325 (unsigned long long)seq_id,
326 (unsigned int)sconn->smb2.credits_granted,
327 (unsigned long long)sconn->smb2.seqnum_low,
328 (unsigned int)sconn->smb2.seqnum_range));
329 return false;
332 offset = seq_id % sconn->smb2.max_credits;
334 if (bitmap_query(credits_bm, offset)) {
335 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
336 "%llu (sequence id %llu) "
337 "(granted = %u, low = %llu, range = %u) "
338 "(bm offset %u)\n",
339 (unsigned long long)message_id,
340 (unsigned long long)seq_id,
341 (unsigned int)sconn->smb2.credits_granted,
342 (unsigned long long)sconn->smb2.seqnum_low,
343 (unsigned int)sconn->smb2.seqnum_range,
344 offset));
345 return false;
348 /* Mark the message_ids as seen in the bitmap. */
349 bitmap_set(credits_bm, offset);
351 if (seq_id != sconn->smb2.seqnum_low) {
352 return true;
356 * Move the window forward by all the message_id's
357 * already seen.
359 while (bitmap_query(credits_bm, offset)) {
360 DEBUG(10,("smb2_validate_sequence_number: clearing "
361 "id %llu (position %u) from bitmap\n",
362 (unsigned long long)(sconn->smb2.seqnum_low),
363 offset));
364 bitmap_clear(credits_bm, offset);
366 sconn->smb2.seqnum_low += 1;
367 sconn->smb2.seqnum_range -= 1;
368 offset = sconn->smb2.seqnum_low % sconn->smb2.max_credits;
371 return true;
374 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
375 const uint8_t *inhdr)
377 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
378 uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
379 bool ok;
381 if (opcode == SMB2_OP_CANCEL) {
382 /* SMB2_CANCEL requests by definition resend messageids. */
383 return true;
386 DEBUG(11, ("smb2_validate_message_id: mid %llu, credits_granted %llu, "
387 "seqnum low/range: %llu/%llu\n",
388 (unsigned long long) message_id,
389 (unsigned long long) sconn->smb2.credits_granted,
390 (unsigned long long) sconn->smb2.seqnum_low,
391 (unsigned long long) sconn->smb2.seqnum_range));
393 if (sconn->smb2.credits_granted < 1) {
394 DEBUG(0, ("smb2_validate_message_id: client used more "
395 "credits than granted, mid %llu, credits_granted %llu, "
396 "seqnum low/range: %llu/%llu\n",
397 (unsigned long long) message_id,
398 (unsigned long long) sconn->smb2.credits_granted,
399 (unsigned long long) sconn->smb2.seqnum_low,
400 (unsigned long long) sconn->smb2.seqnum_range));
401 return false;
404 ok = smb2_validate_sequence_number(sconn, message_id, message_id);
405 if (!ok) {
406 return false;
409 /* substract used credits */
410 sconn->smb2.credits_granted -= 1;
412 return true;
415 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
417 int count;
418 int idx;
420 count = req->in.vector_count;
422 if (count < 4) {
423 /* It's not a SMB2 request */
424 return NT_STATUS_INVALID_PARAMETER;
427 for (idx=1; idx < count; idx += 3) {
428 const uint8_t *inhdr = NULL;
429 uint32_t flags;
431 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
432 return NT_STATUS_INVALID_PARAMETER;
435 if (req->in.vector[idx+1].iov_len < 2) {
436 return NT_STATUS_INVALID_PARAMETER;
439 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
441 /* Check the SMB2 header */
442 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
443 return NT_STATUS_INVALID_PARAMETER;
446 if (!smb2_validate_message_id(req->sconn, inhdr)) {
447 return NT_STATUS_INVALID_PARAMETER;
450 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
451 if (idx == 1) {
453 * the 1st request should never have the
454 * SMB2_HDR_FLAG_CHAINED flag set
456 if (flags & SMB2_HDR_FLAG_CHAINED) {
457 req->next_status = NT_STATUS_INVALID_PARAMETER;
458 return NT_STATUS_OK;
460 } else if (idx == 4) {
462 * the 2nd request triggers related vs. unrelated
463 * compounded requests
465 if (flags & SMB2_HDR_FLAG_CHAINED) {
466 req->compound_related = true;
468 } else if (idx > 4) {
469 #if 0
471 * It seems the this tests are wrong
472 * see the SMB2-COMPOUND test
476 * all other requests should match the 2nd one
478 if (flags & SMB2_HDR_FLAG_CHAINED) {
479 if (!req->compound_related) {
480 req->next_status =
481 NT_STATUS_INVALID_PARAMETER;
482 return NT_STATUS_OK;
484 } else {
485 if (req->compound_related) {
486 req->next_status =
487 NT_STATUS_INVALID_PARAMETER;
488 return NT_STATUS_OK;
491 #endif
495 return NT_STATUS_OK;
498 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
499 const struct iovec *in_vector,
500 struct iovec *out_vector)
502 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
503 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
504 uint16_t credits_requested;
505 uint32_t out_flags;
506 uint16_t cmd;
507 NTSTATUS out_status;
508 uint16_t credits_granted = 0;
509 uint64_t credits_possible;
510 uint16_t current_max_credits;
513 * first we grant only 1/16th of the max range.
515 * Windows also starts with the 1/16th and then grants
516 * more later. I was only able to trigger higher
517 * values, when using a verify high credit charge.
519 * TODO: scale up depending one load, free memory
520 * or other stuff.
521 * Maybe also on the relationship between number
522 * of requests and the used sequence number.
523 * Which means we would grant more credits
524 * for client which use multi credit requests.
526 current_max_credits = sconn->smb2.max_credits / 16;
527 current_max_credits = MAX(current_max_credits, 1);
529 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
530 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
531 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
532 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
534 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
536 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
538 * In case we already send an async interim
539 * response, we should not grant
540 * credits on the final response.
542 credits_granted = 0;
543 } else if (credits_requested > 0) {
544 uint16_t additional_max = 0;
545 uint16_t additional_credits = credits_requested - 1;
547 switch (cmd) {
548 case SMB2_OP_NEGPROT:
549 break;
550 case SMB2_OP_SESSSETUP:
552 * Windows 2012 RC1 starts to grant
553 * additional credits
554 * with a successful session setup
556 if (NT_STATUS_IS_OK(out_status)) {
557 additional_max = 32;
559 break;
560 default:
562 * We match windows and only grant additional credits
563 * in chunks of 32.
565 additional_max = 32;
566 break;
569 additional_credits = MIN(additional_credits, additional_max);
571 credits_granted = 1 + additional_credits;
572 } else if (sconn->smb2.credits_granted == 0) {
574 * Make sure the client has always at least one credit
576 credits_granted = 1;
580 * sequence numbers should not wrap
582 * 1. calculate the possible credits until
583 * the sequence numbers start to wrap on 64-bit.
585 * 2. UINT64_MAX is used for Break Notifications.
587 * 2. truncate the possible credits to the maximum
588 * credits we want to grant to the client in total.
590 * 3. remove the range we'll already granted to the client
591 * this makes sure the client consumes the lowest sequence
592 * number, before we can grant additional credits.
594 credits_possible = UINT64_MAX - sconn->smb2.seqnum_low;
595 if (credits_possible > 0) {
596 /* remove UINT64_MAX */
597 credits_possible -= 1;
599 credits_possible = MIN(credits_possible, current_max_credits);
600 credits_possible -= sconn->smb2.seqnum_range;
602 credits_granted = MIN(credits_granted, credits_possible);
604 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
605 sconn->smb2.credits_granted += credits_granted;
606 sconn->smb2.seqnum_range += credits_granted;
608 DEBUG(10,("smb2_set_operation_credit: requested %u, "
609 "granted %u, current possible/max %u/%u, "
610 "total granted/max/low/range %u/%u/%llu/%u\n",
611 (unsigned int)credits_requested,
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 count = req->in.vector_count;
653 vector = talloc_zero_array(req, struct iovec, count);
654 if (vector == NULL) {
655 return NT_STATUS_NO_MEMORY;
658 vector[0].iov_base = req->out.nbt_hdr;
659 vector[0].iov_len = 4;
660 SIVAL(req->out.nbt_hdr, 0, 0);
662 for (idx=1; idx < count; idx += 3) {
663 const uint8_t *inhdr = NULL;
664 uint32_t in_flags;
665 uint8_t *outhdr = NULL;
666 uint8_t *outbody = NULL;
667 uint32_t next_command_ofs = 0;
668 struct iovec *current = &vector[idx];
670 if ((idx + 3) < count) {
671 /* we have a next command -
672 * setup for the error case. */
673 next_command_ofs = SMB2_HDR_BODY + 9;
676 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
677 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
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;
830 newreq->async = false;
831 newreq->cancelled = false;
832 /* Note we are leaving:
833 ->tcon
834 ->smb1req
835 ->compat_chain_fsp
836 uninitialized as NULL here as
837 they're not used in the interim
838 response code. JRA. */
840 outvec = talloc_zero_array(newreq, struct iovec, count);
841 if (!outvec) {
842 TALLOC_FREE(newreq);
843 return NULL;
845 newreq->out.vector = outvec;
846 newreq->out.vector_count = count;
848 /* Setup the outvec's identically to req. */
849 outvec[0].iov_base = newreq->out.nbt_hdr;
850 outvec[0].iov_len = 4;
851 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
853 /* Setup the vectors identically to the ones in req. */
854 for (i = 1; i < count; i += 3) {
855 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
856 break;
860 if (i < count) {
861 /* Alloc failed. */
862 TALLOC_FREE(newreq);
863 return NULL;
866 smb2_setup_nbt_length(newreq->out.vector,
867 newreq->out.vector_count);
869 return newreq;
872 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
874 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
876 int i = 0;
877 uint8_t *outhdr = NULL;
878 struct smbd_smb2_request *nreq = NULL;
880 /* Create a new smb2 request we'll use
881 for the interim return. */
882 nreq = dup_smb2_req(req);
883 if (!nreq) {
884 return NT_STATUS_NO_MEMORY;
887 /* Lose the last 3 out vectors. They're the
888 ones we'll be using for the async reply. */
889 nreq->out.vector_count -= 3;
891 smb2_setup_nbt_length(nreq->out.vector,
892 nreq->out.vector_count);
894 /* Step back to the previous reply. */
895 i = nreq->current_idx - 3;
896 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
897 /* And end the chain. */
898 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
900 /* Calculate outgoing credits */
901 smb2_calculate_credits(req, nreq);
903 /* Re-sign if needed. */
904 if (nreq->do_signing) {
905 NTSTATUS status;
906 status = smb2_signing_sign_pdu(nreq->session->session_key,
907 &nreq->out.vector[i], 3);
908 if (!NT_STATUS_IS_OK(status)) {
909 return status;
912 if (DEBUGLEVEL >= 10) {
913 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
914 (unsigned int)nreq->current_idx );
915 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
916 (unsigned int)nreq->out.vector_count );
917 print_req_vectors(nreq);
919 nreq->subreq = tstream_writev_queue_send(nreq,
920 nreq->sconn->smb2.event_ctx,
921 nreq->sconn->smb2.stream,
922 nreq->sconn->smb2.send_queue,
923 nreq->out.vector,
924 nreq->out.vector_count);
926 if (nreq->subreq == NULL) {
927 return NT_STATUS_NO_MEMORY;
930 tevent_req_set_callback(nreq->subreq,
931 smbd_smb2_request_writev_done,
932 nreq);
934 return NT_STATUS_OK;
937 struct smbd_smb2_request_pending_state {
938 struct smbd_server_connection *sconn;
939 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
940 struct iovec vector[3];
943 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
945 struct smbd_smb2_request_pending_state *state =
946 tevent_req_callback_data(subreq,
947 struct smbd_smb2_request_pending_state);
948 struct smbd_server_connection *sconn = state->sconn;
949 int ret;
950 int sys_errno;
952 ret = tstream_writev_queue_recv(subreq, &sys_errno);
953 TALLOC_FREE(subreq);
954 if (ret == -1) {
955 NTSTATUS status = map_nt_error_from_unix(sys_errno);
956 smbd_server_connection_terminate(sconn, nt_errstr(status));
957 return;
960 TALLOC_FREE(state);
963 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
964 struct tevent_req *subreq)
966 NTSTATUS status;
967 struct smbd_smb2_request_pending_state *state = NULL;
968 int i = req->current_idx;
969 uint8_t *reqhdr = NULL;
970 uint8_t *hdr = NULL;
971 uint8_t *body = NULL;
972 uint32_t flags = 0;
973 uint64_t message_id = 0;
974 uint64_t async_id = 0;
975 struct iovec *outvec = NULL;
977 if (!tevent_req_is_in_progress(subreq)) {
978 return NT_STATUS_OK;
981 req->subreq = subreq;
982 subreq = NULL;
984 if (req->async) {
985 /* We're already async. */
986 return NT_STATUS_OK;
989 if (req->in.vector_count > i + 3) {
991 * We're trying to go async in a compound
992 * request chain. This is not allowed.
993 * Cancel the outstanding request.
995 tevent_req_cancel(req->subreq);
996 return smbd_smb2_request_error(req,
997 NT_STATUS_INSUFFICIENT_RESOURCES);
1000 if (DEBUGLEVEL >= 10) {
1001 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1002 (unsigned int)req->current_idx );
1003 print_req_vectors(req);
1006 if (req->out.vector_count > 4) {
1007 /* This is a compound reply. We
1008 * must do an interim response
1009 * followed by the async response
1010 * to match W2K8R2.
1012 status = smb2_send_async_interim_response(req);
1013 if (!NT_STATUS_IS_OK(status)) {
1014 return status;
1018 * We're splitting off the last SMB2
1019 * request in a compound set, and the
1020 * smb2_send_async_interim_response()
1021 * call above just sent all the replies
1022 * for the previous SMB2 requests in
1023 * this compound set. So we're no longer
1024 * in the "compound_related_in_progress"
1025 * state, and this is no longer a compound
1026 * request.
1028 req->compound_related = false;
1029 req->sconn->smb2.compound_related_in_progress = false;
1032 /* Don't return an intermediate packet on a pipe read/write. */
1033 if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
1034 goto ipc_out;
1037 reqhdr = (uint8_t *)req->out.vector[i].iov_base;
1038 flags = (IVAL(reqhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1039 message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
1040 async_id = message_id; /* keep it simple for now... */
1043 * What we send is identical to a smbd_smb2_request_error
1044 * packet with an error status of STATUS_PENDING. Make use
1045 * of this fact sometime when refactoring. JRA.
1048 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1049 if (state == NULL) {
1050 return NT_STATUS_NO_MEMORY;
1052 state->sconn = req->sconn;
1054 state->vector[0].iov_base = (void *)state->buf;
1055 state->vector[0].iov_len = 4;
1057 state->vector[1].iov_base = state->buf + 4;
1058 state->vector[1].iov_len = SMB2_HDR_BODY;
1060 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
1061 state->vector[2].iov_len = 9;
1063 smb2_setup_nbt_length(state->vector, 3);
1065 hdr = (uint8_t *)state->vector[1].iov_base;
1066 body = (uint8_t *)state->vector[2].iov_base;
1068 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1069 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1070 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1071 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1072 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(reqhdr, SMB2_HDR_OPCODE));
1074 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1075 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1076 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1077 SBVAL(hdr, SMB2_HDR_PID, async_id);
1078 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1079 BVAL(reqhdr, SMB2_HDR_SESSION_ID));
1080 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
1082 SSVAL(body, 0x00, 0x08 + 1);
1084 SCVAL(body, 0x02, 0);
1085 SCVAL(body, 0x03, 0);
1086 SIVAL(body, 0x04, 0);
1087 /* Match W2K8R2... */
1088 SCVAL(body, 0x08, 0x21);
1090 /* Ensure we correctly go through crediting. Grant
1091 the credits now, and zero credits on the final
1092 response. */
1093 smb2_set_operation_credit(req->sconn,
1094 &req->in.vector[i],
1095 &state->vector[1]);
1097 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1099 if (req->do_signing) {
1100 status = smb2_signing_sign_pdu(req->session->session_key,
1101 &state->vector[1], 2);
1102 if (!NT_STATUS_IS_OK(status)) {
1103 return status;
1107 subreq = tstream_writev_queue_send(state,
1108 req->sconn->smb2.event_ctx,
1109 req->sconn->smb2.stream,
1110 req->sconn->smb2.send_queue,
1111 state->vector,
1114 if (subreq == NULL) {
1115 return NT_STATUS_NO_MEMORY;
1118 tevent_req_set_callback(subreq,
1119 smbd_smb2_request_pending_writev_done,
1120 state);
1122 /* Note we're going async with this request. */
1123 req->async = true;
1125 ipc_out:
1128 * Now manipulate req so that the outstanding async request
1129 * is the only one left in the struct smbd_smb2_request.
1132 if (req->current_idx == 1) {
1133 /* There was only one. */
1134 goto out;
1137 /* Re-arrange the in.vectors. */
1138 req->in.vector[1] = req->in.vector[i];
1139 req->in.vector[2] = req->in.vector[i+1];
1140 req->in.vector[3] = req->in.vector[i+2];
1141 req->in.vector_count = 4;
1142 /* Reset the new in size. */
1143 smb2_setup_nbt_length(req->in.vector, 4);
1145 /* Now recreate the out.vectors. */
1146 outvec = talloc_zero_array(req, struct iovec, 4);
1147 if (!outvec) {
1148 return NT_STATUS_NO_MEMORY;
1151 /* 0 is always boilerplate and must
1152 * be of size 4 for the length field. */
1154 outvec[0].iov_base = req->out.nbt_hdr;
1155 outvec[0].iov_len = 4;
1156 SIVAL(req->out.nbt_hdr, 0, 0);
1158 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
1159 return NT_STATUS_NO_MEMORY;
1162 TALLOC_FREE(req->out.vector);
1164 req->out.vector = outvec;
1166 req->current_idx = 1;
1167 req->out.vector_count = 4;
1169 out:
1171 smb2_setup_nbt_length(req->out.vector,
1172 req->out.vector_count);
1174 if (req->async) {
1175 /* Ensure our final reply matches the interim one. */
1176 reqhdr = (uint8_t *)req->out.vector[1].iov_base;
1177 SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1178 SBVAL(reqhdr, SMB2_HDR_PID, async_id);
1181 const uint8_t *inhdr =
1182 (const uint8_t *)req->in.vector[1].iov_base;
1183 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1184 "going async\n",
1185 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1186 (unsigned long long)async_id ));
1190 return NT_STATUS_OK;
1193 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1195 struct smbd_server_connection *sconn = req->sconn;
1196 struct smbd_smb2_request *cur;
1197 const uint8_t *inhdr;
1198 int i = req->current_idx;
1199 uint32_t flags;
1200 uint64_t search_message_id;
1201 uint64_t search_async_id;
1202 uint64_t found_id;
1204 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1206 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1207 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1208 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1211 * we don't need the request anymore
1212 * cancel requests never have a response
1214 DLIST_REMOVE(req->sconn->smb2.requests, req);
1215 TALLOC_FREE(req);
1217 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1218 const uint8_t *outhdr;
1219 uint64_t message_id;
1220 uint64_t async_id;
1222 i = cur->current_idx;
1224 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1226 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1227 async_id = BVAL(outhdr, SMB2_HDR_PID);
1229 if (flags & SMB2_HDR_FLAG_ASYNC) {
1230 if (search_async_id == async_id) {
1231 found_id = async_id;
1232 break;
1234 } else {
1235 if (search_message_id == message_id) {
1236 found_id = message_id;
1237 break;
1242 if (cur && cur->subreq) {
1243 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1244 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1245 "cancel opcode[%s] mid %llu\n",
1246 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1247 (unsigned long long)found_id ));
1248 tevent_req_cancel(cur->subreq);
1251 return NT_STATUS_OK;
1254 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1255 size_t expected_body_size)
1257 const uint8_t *inhdr;
1258 uint16_t opcode;
1259 const uint8_t *inbody;
1260 int i = req->current_idx;
1261 size_t body_size;
1262 size_t min_dyn_size = expected_body_size & 0x00000001;
1265 * The following should be checked already.
1267 if ((i+2) > req->in.vector_count) {
1268 return NT_STATUS_INTERNAL_ERROR;
1270 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1271 return NT_STATUS_INTERNAL_ERROR;
1273 if (req->in.vector[i+1].iov_len < 2) {
1274 return NT_STATUS_INTERNAL_ERROR;
1277 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1278 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1280 switch (opcode) {
1281 case SMB2_OP_IOCTL:
1282 case SMB2_OP_GETINFO:
1283 min_dyn_size = 0;
1284 break;
1288 * Now check the expected body size,
1289 * where the last byte might be in the
1290 * dynnamic section..
1292 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1293 return NT_STATUS_INVALID_PARAMETER;
1295 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1296 return NT_STATUS_INVALID_PARAMETER;
1299 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1301 body_size = SVAL(inbody, 0x00);
1302 if (body_size != expected_body_size) {
1303 return NT_STATUS_INVALID_PARAMETER;
1306 return NT_STATUS_OK;
1309 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1311 const uint8_t *inhdr;
1312 int i = req->current_idx;
1313 uint16_t opcode;
1314 uint32_t flags;
1315 uint64_t mid;
1316 NTSTATUS status;
1317 NTSTATUS session_status;
1318 uint32_t allowed_flags;
1319 NTSTATUS return_value;
1321 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1323 /* TODO: verify more things */
1325 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1326 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1327 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1328 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1329 smb2_opcode_name(opcode),
1330 (unsigned long long)mid));
1332 if (get_Protocol() >= PROTOCOL_SMB2) {
1334 * once the protocol is negotiated
1335 * SMB2_OP_NEGPROT is not allowed anymore
1337 if (opcode == SMB2_OP_NEGPROT) {
1338 /* drop the connection */
1339 return NT_STATUS_INVALID_PARAMETER;
1341 } else {
1343 * if the protocol is not negotiated yet
1344 * only SMB2_OP_NEGPROT is allowed.
1346 if (opcode != SMB2_OP_NEGPROT) {
1347 /* drop the connection */
1348 return NT_STATUS_INVALID_PARAMETER;
1352 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1353 SMB2_HDR_FLAG_SIGNED |
1354 SMB2_HDR_FLAG_DFS;
1355 if (opcode == SMB2_OP_CANCEL) {
1356 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1358 if ((flags & ~allowed_flags) != 0) {
1359 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1363 * Check if the client provided a valid session id,
1364 * if so smbd_smb2_request_check_session() calls
1365 * set_current_user_info().
1367 * As some command don't require a valid session id
1368 * we defer the check of the session_status
1370 session_status = smbd_smb2_request_check_session(req);
1372 req->do_signing = false;
1373 if (flags & SMB2_HDR_FLAG_SIGNED) {
1374 if (!NT_STATUS_IS_OK(session_status)) {
1375 return smbd_smb2_request_error(req, session_status);
1378 req->do_signing = true;
1379 status = smb2_signing_check_pdu(req->session->session_key,
1380 &req->in.vector[i], 3);
1381 if (!NT_STATUS_IS_OK(status)) {
1382 return smbd_smb2_request_error(req, status);
1384 } else if (opcode == SMB2_OP_CANCEL) {
1385 /* Cancel requests are allowed to skip the signing */
1386 } else if (req->session && req->session->do_signing) {
1387 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1390 if (flags & SMB2_HDR_FLAG_CHAINED) {
1392 * This check is mostly for giving the correct error code
1393 * for compounded requests.
1395 * TODO: we may need to move this after the session
1396 * and tcon checks.
1398 if (!NT_STATUS_IS_OK(req->next_status)) {
1399 return smbd_smb2_request_error(req, req->next_status);
1401 } else {
1402 req->compat_chain_fsp = NULL;
1405 if (req->compound_related) {
1406 req->sconn->smb2.compound_related_in_progress = true;
1409 switch (opcode) {
1410 case SMB2_OP_NEGPROT:
1411 /* This call needs to be run as root */
1412 change_to_root_user();
1415 START_PROFILE(smb2_negprot);
1416 return_value = smbd_smb2_request_process_negprot(req);
1417 END_PROFILE(smb2_negprot);
1419 break;
1421 case SMB2_OP_SESSSETUP:
1422 /* This call needs to be run as root */
1423 change_to_root_user();
1426 START_PROFILE(smb2_sesssetup);
1427 return_value = smbd_smb2_request_process_sesssetup(req);
1428 END_PROFILE(smb2_sesssetup);
1430 break;
1432 case SMB2_OP_LOGOFF:
1433 if (!NT_STATUS_IS_OK(session_status)) {
1434 return_value = smbd_smb2_request_error(req, session_status);
1435 break;
1438 /* This call needs to be run as root */
1439 change_to_root_user();
1442 START_PROFILE(smb2_logoff);
1443 return_value = smbd_smb2_request_process_logoff(req);
1444 END_PROFILE(smb2_logoff);
1446 break;
1448 case SMB2_OP_TCON:
1449 if (!NT_STATUS_IS_OK(session_status)) {
1450 return_value = smbd_smb2_request_error(req, session_status);
1451 break;
1455 * This call needs to be run as root.
1457 * smbd_smb2_request_process_tcon()
1458 * calls make_connection_snum(), which will call
1459 * change_to_user(), when needed.
1461 change_to_root_user();
1464 START_PROFILE(smb2_tcon);
1465 return_value = smbd_smb2_request_process_tcon(req);
1466 END_PROFILE(smb2_tcon);
1468 break;
1470 case SMB2_OP_TDIS:
1471 if (!NT_STATUS_IS_OK(session_status)) {
1472 return_value = smbd_smb2_request_error(req, session_status);
1473 break;
1476 * This call needs to be run as user.
1478 * smbd_smb2_request_check_tcon()
1479 * calls change_to_user() on success.
1481 status = smbd_smb2_request_check_tcon(req);
1482 if (!NT_STATUS_IS_OK(status)) {
1483 return_value = smbd_smb2_request_error(req, status);
1484 break;
1486 /* This call needs to be run as root */
1487 change_to_root_user();
1491 START_PROFILE(smb2_tdis);
1492 return_value = smbd_smb2_request_process_tdis(req);
1493 END_PROFILE(smb2_tdis);
1495 break;
1497 case SMB2_OP_CREATE:
1498 if (!NT_STATUS_IS_OK(session_status)) {
1499 return_value = smbd_smb2_request_error(req, session_status);
1500 break;
1503 * This call needs to be run as user.
1505 * smbd_smb2_request_check_tcon()
1506 * calls change_to_user() on success.
1508 status = smbd_smb2_request_check_tcon(req);
1509 if (!NT_STATUS_IS_OK(status)) {
1510 return_value = smbd_smb2_request_error(req, status);
1511 break;
1515 START_PROFILE(smb2_create);
1516 return_value = smbd_smb2_request_process_create(req);
1517 END_PROFILE(smb2_create);
1519 break;
1521 case SMB2_OP_CLOSE:
1522 if (!NT_STATUS_IS_OK(session_status)) {
1523 return_value = smbd_smb2_request_error(req, session_status);
1524 break;
1527 * This call needs to be run as user.
1529 * smbd_smb2_request_check_tcon()
1530 * calls change_to_user() on success.
1532 status = smbd_smb2_request_check_tcon(req);
1533 if (!NT_STATUS_IS_OK(status)) {
1534 return_value = smbd_smb2_request_error(req, status);
1535 break;
1539 START_PROFILE(smb2_close);
1540 return_value = smbd_smb2_request_process_close(req);
1541 END_PROFILE(smb2_close);
1543 break;
1545 case SMB2_OP_FLUSH:
1546 if (!NT_STATUS_IS_OK(session_status)) {
1547 return_value = smbd_smb2_request_error(req, session_status);
1548 break;
1551 * This call needs to be run as user.
1553 * smbd_smb2_request_check_tcon()
1554 * calls change_to_user() on success.
1556 status = smbd_smb2_request_check_tcon(req);
1557 if (!NT_STATUS_IS_OK(status)) {
1558 return_value = smbd_smb2_request_error(req, status);
1559 break;
1563 START_PROFILE(smb2_flush);
1564 return_value = smbd_smb2_request_process_flush(req);
1565 END_PROFILE(smb2_flush);
1567 break;
1569 case SMB2_OP_READ:
1570 if (!NT_STATUS_IS_OK(session_status)) {
1571 return_value = smbd_smb2_request_error(req, session_status);
1572 break;
1575 * This call needs to be run as user.
1577 * smbd_smb2_request_check_tcon()
1578 * calls change_to_user() on success.
1580 status = smbd_smb2_request_check_tcon(req);
1581 if (!NT_STATUS_IS_OK(status)) {
1582 return_value = smbd_smb2_request_error(req, status);
1583 break;
1587 START_PROFILE(smb2_read);
1588 return_value = smbd_smb2_request_process_read(req);
1589 END_PROFILE(smb2_read);
1591 break;
1593 case SMB2_OP_WRITE:
1594 if (!NT_STATUS_IS_OK(session_status)) {
1595 return_value = smbd_smb2_request_error(req, session_status);
1596 break;
1599 * This call needs to be run as user.
1601 * smbd_smb2_request_check_tcon()
1602 * calls change_to_user() on success.
1604 status = smbd_smb2_request_check_tcon(req);
1605 if (!NT_STATUS_IS_OK(status)) {
1606 return_value = smbd_smb2_request_error(req, status);
1607 break;
1611 START_PROFILE(smb2_write);
1612 return_value = smbd_smb2_request_process_write(req);
1613 END_PROFILE(smb2_write);
1615 break;
1617 case SMB2_OP_LOCK:
1618 if (!NT_STATUS_IS_OK(session_status)) {
1619 /* Too ugly to live ? JRA. */
1620 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1621 session_status = NT_STATUS_FILE_CLOSED;
1623 return_value = smbd_smb2_request_error(req, session_status);
1624 break;
1627 * This call needs to be run as user.
1629 * smbd_smb2_request_check_tcon()
1630 * calls change_to_user() on success.
1632 status = smbd_smb2_request_check_tcon(req);
1633 if (!NT_STATUS_IS_OK(status)) {
1634 /* Too ugly to live ? JRA. */
1635 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1636 status = NT_STATUS_FILE_CLOSED;
1638 return_value = smbd_smb2_request_error(req, status);
1639 break;
1643 START_PROFILE(smb2_lock);
1644 return_value = smbd_smb2_request_process_lock(req);
1645 END_PROFILE(smb2_lock);
1647 break;
1649 case SMB2_OP_IOCTL:
1650 if (!NT_STATUS_IS_OK(session_status)) {
1651 return_value = smbd_smb2_request_error(req, session_status);
1652 break;
1655 * This call needs to be run as user.
1657 * smbd_smb2_request_check_tcon()
1658 * calls change_to_user() on success.
1660 status = smbd_smb2_request_check_tcon(req);
1661 if (!NT_STATUS_IS_OK(status)) {
1662 return_value = smbd_smb2_request_error(req, status);
1663 break;
1667 START_PROFILE(smb2_ioctl);
1668 return_value = smbd_smb2_request_process_ioctl(req);
1669 END_PROFILE(smb2_ioctl);
1671 break;
1673 case SMB2_OP_CANCEL:
1675 * This call needs to be run as root
1677 * That is what we also do in the SMB1 case.
1679 change_to_root_user();
1682 START_PROFILE(smb2_cancel);
1683 return_value = smbd_smb2_request_process_cancel(req);
1684 END_PROFILE(smb2_cancel);
1686 break;
1688 case SMB2_OP_KEEPALIVE:
1689 /* This call needs to be run as root */
1690 change_to_root_user();
1693 START_PROFILE(smb2_keepalive);
1694 return_value = smbd_smb2_request_process_keepalive(req);
1695 END_PROFILE(smb2_keepalive);
1697 break;
1699 case SMB2_OP_FIND:
1700 if (!NT_STATUS_IS_OK(session_status)) {
1701 return_value = smbd_smb2_request_error(req, session_status);
1702 break;
1705 * This call needs to be run as user.
1707 * smbd_smb2_request_check_tcon()
1708 * calls change_to_user() on success.
1710 status = smbd_smb2_request_check_tcon(req);
1711 if (!NT_STATUS_IS_OK(status)) {
1712 return_value = smbd_smb2_request_error(req, status);
1713 break;
1717 START_PROFILE(smb2_find);
1718 return_value = smbd_smb2_request_process_find(req);
1719 END_PROFILE(smb2_find);
1721 break;
1723 case SMB2_OP_NOTIFY:
1724 if (!NT_STATUS_IS_OK(session_status)) {
1725 return_value = smbd_smb2_request_error(req, session_status);
1726 break;
1729 * This call needs to be run as user.
1731 * smbd_smb2_request_check_tcon()
1732 * calls change_to_user() on success.
1734 status = smbd_smb2_request_check_tcon(req);
1735 if (!NT_STATUS_IS_OK(status)) {
1736 return_value = smbd_smb2_request_error(req, status);
1737 break;
1741 START_PROFILE(smb2_notify);
1742 return_value = smbd_smb2_request_process_notify(req);
1743 END_PROFILE(smb2_notify);
1745 break;
1747 case SMB2_OP_GETINFO:
1748 if (!NT_STATUS_IS_OK(session_status)) {
1749 return_value = smbd_smb2_request_error(req, session_status);
1750 break;
1753 * This call needs to be run as user.
1755 * smbd_smb2_request_check_tcon()
1756 * calls change_to_user() on success.
1758 status = smbd_smb2_request_check_tcon(req);
1759 if (!NT_STATUS_IS_OK(status)) {
1760 return_value = smbd_smb2_request_error(req, status);
1761 break;
1765 START_PROFILE(smb2_getinfo);
1766 return_value = smbd_smb2_request_process_getinfo(req);
1767 END_PROFILE(smb2_getinfo);
1769 break;
1771 case SMB2_OP_SETINFO:
1772 if (!NT_STATUS_IS_OK(session_status)) {
1773 return_value = smbd_smb2_request_error(req, session_status);
1774 break;
1777 * This call needs to be run as user.
1779 * smbd_smb2_request_check_tcon()
1780 * calls change_to_user() on success.
1782 status = smbd_smb2_request_check_tcon(req);
1783 if (!NT_STATUS_IS_OK(status)) {
1784 return_value = smbd_smb2_request_error(req, status);
1785 break;
1789 START_PROFILE(smb2_setinfo);
1790 return_value = smbd_smb2_request_process_setinfo(req);
1791 END_PROFILE(smb2_setinfo);
1793 break;
1795 case SMB2_OP_BREAK:
1796 if (!NT_STATUS_IS_OK(session_status)) {
1797 return_value = smbd_smb2_request_error(req, session_status);
1798 break;
1801 * This call needs to be run as user.
1803 * smbd_smb2_request_check_tcon()
1804 * calls change_to_user() on success.
1806 status = smbd_smb2_request_check_tcon(req);
1807 if (!NT_STATUS_IS_OK(status)) {
1808 return_value = smbd_smb2_request_error(req, status);
1809 break;
1813 START_PROFILE(smb2_break);
1814 return_value = smbd_smb2_request_process_break(req);
1815 END_PROFILE(smb2_break);
1817 break;
1819 default:
1820 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1821 break;
1823 return return_value;
1826 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1828 struct tevent_req *subreq;
1829 int i = req->current_idx;
1831 req->subreq = NULL;
1833 req->current_idx += 3;
1835 if (req->current_idx < req->out.vector_count) {
1837 * We must process the remaining compound
1838 * SMB2 requests before any new incoming SMB2
1839 * requests. This is because incoming SMB2
1840 * requests may include a cancel for a
1841 * compound request we haven't processed
1842 * yet.
1844 struct tevent_immediate *im = tevent_create_immediate(req);
1845 if (!im) {
1846 return NT_STATUS_NO_MEMORY;
1848 tevent_schedule_immediate(im,
1849 req->sconn->smb2.event_ctx,
1850 smbd_smb2_request_dispatch_immediate,
1851 req);
1852 return NT_STATUS_OK;
1855 if (req->compound_related) {
1856 req->sconn->smb2.compound_related_in_progress = false;
1859 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1861 /* Set credit for these operations (zero credits if this
1862 is a final reply for an async operation). */
1863 smb2_calculate_credits(req, req);
1865 if (req->do_signing) {
1866 NTSTATUS status;
1867 status = smb2_signing_sign_pdu(req->session->session_key,
1868 &req->out.vector[i], 3);
1869 if (!NT_STATUS_IS_OK(status)) {
1870 return status;
1874 if (DEBUGLEVEL >= 10) {
1875 dbgtext("smbd_smb2_request_reply: sending...\n");
1876 print_req_vectors(req);
1879 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1880 if (req->out.vector_count == 4 &&
1881 req->out.vector[3].iov_base == NULL &&
1882 req->out.vector[3].iov_len != 0) {
1883 /* Dynamic part is NULL. Chop it off,
1884 We're going to send it via sendfile. */
1885 req->out.vector_count -= 1;
1888 subreq = tstream_writev_queue_send(req,
1889 req->sconn->smb2.event_ctx,
1890 req->sconn->smb2.stream,
1891 req->sconn->smb2.send_queue,
1892 req->out.vector,
1893 req->out.vector_count);
1894 if (subreq == NULL) {
1895 return NT_STATUS_NO_MEMORY;
1897 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1899 * We're done with this request -
1900 * move it off the "being processed" queue.
1902 DLIST_REMOVE(req->sconn->smb2.requests, req);
1904 return NT_STATUS_OK;
1907 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
1909 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1910 struct tevent_immediate *im,
1911 void *private_data)
1913 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1914 struct smbd_smb2_request);
1915 struct smbd_server_connection *sconn = req->sconn;
1916 NTSTATUS status;
1918 TALLOC_FREE(im);
1920 if (DEBUGLEVEL >= 10) {
1921 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1922 req->current_idx, req->in.vector_count));
1923 print_req_vectors(req);
1926 status = smbd_smb2_request_dispatch(req);
1927 if (!NT_STATUS_IS_OK(status)) {
1928 smbd_server_connection_terminate(sconn, nt_errstr(status));
1929 return;
1932 status = smbd_smb2_request_next_incoming(sconn);
1933 if (!NT_STATUS_IS_OK(status)) {
1934 smbd_server_connection_terminate(sconn, nt_errstr(status));
1935 return;
1939 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1941 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1942 struct smbd_smb2_request);
1943 struct smbd_server_connection *sconn = req->sconn;
1944 int ret;
1945 int sys_errno;
1946 NTSTATUS status;
1948 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1949 TALLOC_FREE(subreq);
1950 TALLOC_FREE(req);
1951 if (ret == -1) {
1952 status = map_nt_error_from_unix(sys_errno);
1953 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1954 nt_errstr(status)));
1955 smbd_server_connection_terminate(sconn, nt_errstr(status));
1956 return;
1959 status = smbd_smb2_request_next_incoming(sconn);
1960 if (!NT_STATUS_IS_OK(status)) {
1961 smbd_server_connection_terminate(sconn, nt_errstr(status));
1962 return;
1966 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1967 NTSTATUS status,
1968 DATA_BLOB body, DATA_BLOB *dyn,
1969 const char *location)
1971 uint8_t *outhdr;
1972 int i = req->current_idx;
1973 uint32_t next_command_ofs;
1975 DEBUG(10,("smbd_smb2_request_done_ex: "
1976 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1977 i, nt_errstr(status), (unsigned int)body.length,
1978 dyn ? "yes": "no",
1979 (unsigned int)(dyn ? dyn->length : 0),
1980 location));
1982 if (body.length < 2) {
1983 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1986 if ((body.length % 2) != 0) {
1987 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1990 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1992 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1993 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1995 req->out.vector[i+1].iov_base = (void *)body.data;
1996 req->out.vector[i+1].iov_len = body.length;
1998 if (dyn) {
1999 req->out.vector[i+2].iov_base = (void *)dyn->data;
2000 req->out.vector[i+2].iov_len = dyn->length;
2001 } else {
2002 req->out.vector[i+2].iov_base = NULL;
2003 req->out.vector[i+2].iov_len = 0;
2006 /* see if we need to recalculate the offset to the next response */
2007 if (next_command_ofs > 0) {
2008 next_command_ofs = SMB2_HDR_BODY;
2009 next_command_ofs += req->out.vector[i+1].iov_len;
2010 next_command_ofs += req->out.vector[i+2].iov_len;
2013 if ((next_command_ofs % 8) != 0) {
2014 size_t pad_size = 8 - (next_command_ofs % 8);
2015 if (req->out.vector[i+2].iov_len == 0) {
2017 * if the dyn buffer is empty
2018 * we can use it to add padding
2020 uint8_t *pad;
2022 pad = talloc_zero_array(req->out.vector,
2023 uint8_t, pad_size);
2024 if (pad == NULL) {
2025 return smbd_smb2_request_error(req,
2026 NT_STATUS_NO_MEMORY);
2029 req->out.vector[i+2].iov_base = (void *)pad;
2030 req->out.vector[i+2].iov_len = pad_size;
2031 } else {
2033 * For now we copy the dynamic buffer
2034 * and add the padding to the new buffer
2036 size_t old_size;
2037 uint8_t *old_dyn;
2038 size_t new_size;
2039 uint8_t *new_dyn;
2041 old_size = req->out.vector[i+2].iov_len;
2042 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2044 new_size = old_size + pad_size;
2045 new_dyn = talloc_zero_array(req->out.vector,
2046 uint8_t, new_size);
2047 if (new_dyn == NULL) {
2048 return smbd_smb2_request_error(req,
2049 NT_STATUS_NO_MEMORY);
2052 memcpy(new_dyn, old_dyn, old_size);
2053 memset(new_dyn + old_size, 0, pad_size);
2055 req->out.vector[i+2].iov_base = (void *)new_dyn;
2056 req->out.vector[i+2].iov_len = new_size;
2058 next_command_ofs += pad_size;
2061 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2063 return smbd_smb2_request_reply(req);
2066 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2067 NTSTATUS status,
2068 DATA_BLOB *info,
2069 const char *location)
2071 DATA_BLOB body;
2072 int i = req->current_idx;
2073 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
2075 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2076 i, nt_errstr(status), info ? " +info" : "",
2077 location));
2079 body.data = outhdr + SMB2_HDR_BODY;
2080 body.length = 8;
2081 SSVAL(body.data, 0, 9);
2083 if (info) {
2084 SIVAL(body.data, 0x04, info->length);
2085 } else {
2086 /* Allocated size of req->out.vector[i].iov_base
2087 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2088 * 1 byte without having to do an alloc.
2090 info = talloc_zero_array(req->out.vector,
2091 DATA_BLOB,
2093 if (!info) {
2094 return NT_STATUS_NO_MEMORY;
2096 info->data = ((uint8_t *)outhdr) +
2097 OUTVEC_ALLOC_SIZE - 1;
2098 info->length = 1;
2099 SCVAL(info->data, 0, 0);
2103 * if a request fails, all other remaining
2104 * compounded requests should fail too
2106 req->next_status = NT_STATUS_INVALID_PARAMETER;
2108 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2112 struct smbd_smb2_send_oplock_break_state {
2113 struct smbd_server_connection *sconn;
2114 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2115 struct iovec vector;
2118 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2120 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2121 uint64_t file_id_persistent,
2122 uint64_t file_id_volatile,
2123 uint8_t oplock_level)
2125 struct smbd_smb2_send_oplock_break_state *state;
2126 struct tevent_req *subreq;
2127 uint8_t *hdr;
2128 uint8_t *body;
2130 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2131 if (state == NULL) {
2132 return NT_STATUS_NO_MEMORY;
2134 state->sconn = sconn;
2136 state->vector.iov_base = (void *)state->buf;
2137 state->vector.iov_len = sizeof(state->buf);
2139 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2140 hdr = state->buf + 4;
2141 body = hdr + SMB2_HDR_BODY;
2143 SIVAL(hdr, 0, SMB2_MAGIC);
2144 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2145 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2146 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2147 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2148 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2149 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2150 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2151 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2152 SIVAL(hdr, SMB2_HDR_PID, 0);
2153 SIVAL(hdr, SMB2_HDR_TID, 0);
2154 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2155 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2157 SSVAL(body, 0x00, 0x18);
2159 SCVAL(body, 0x02, oplock_level);
2160 SCVAL(body, 0x03, 0); /* reserved */
2161 SIVAL(body, 0x04, 0); /* reserved */
2162 SBVAL(body, 0x08, file_id_persistent);
2163 SBVAL(body, 0x10, file_id_volatile);
2165 subreq = tstream_writev_queue_send(state,
2166 sconn->smb2.event_ctx,
2167 sconn->smb2.stream,
2168 sconn->smb2.send_queue,
2169 &state->vector, 1);
2170 if (subreq == NULL) {
2171 return NT_STATUS_NO_MEMORY;
2173 tevent_req_set_callback(subreq,
2174 smbd_smb2_oplock_break_writev_done,
2175 state);
2177 return NT_STATUS_OK;
2180 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2182 struct smbd_smb2_send_oplock_break_state *state =
2183 tevent_req_callback_data(subreq,
2184 struct smbd_smb2_send_oplock_break_state);
2185 struct smbd_server_connection *sconn = state->sconn;
2186 int ret;
2187 int sys_errno;
2189 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2190 TALLOC_FREE(subreq);
2191 if (ret == -1) {
2192 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2193 smbd_server_connection_terminate(sconn, nt_errstr(status));
2194 return;
2197 TALLOC_FREE(state);
2200 struct smbd_smb2_request_read_state {
2201 size_t missing;
2202 bool asked_for_header;
2203 struct smbd_smb2_request *smb2_req;
2206 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2207 void *private_data,
2208 TALLOC_CTX *mem_ctx,
2209 struct iovec **_vector,
2210 size_t *_count);
2211 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2213 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2214 struct tevent_context *ev,
2215 struct smbd_server_connection *sconn)
2217 struct tevent_req *req;
2218 struct smbd_smb2_request_read_state *state;
2219 struct tevent_req *subreq;
2221 req = tevent_req_create(mem_ctx, &state,
2222 struct smbd_smb2_request_read_state);
2223 if (req == NULL) {
2224 return NULL;
2226 state->missing = 0;
2227 state->asked_for_header = false;
2229 state->smb2_req = smbd_smb2_request_allocate(state);
2230 if (tevent_req_nomem(state->smb2_req, req)) {
2231 return tevent_req_post(req, ev);
2233 state->smb2_req->sconn = sconn;
2235 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2236 sconn->smb2.recv_queue,
2237 smbd_smb2_request_next_vector,
2238 state);
2239 if (tevent_req_nomem(subreq, req)) {
2240 return tevent_req_post(req, ev);
2242 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2244 return req;
2247 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2248 void *private_data,
2249 TALLOC_CTX *mem_ctx,
2250 struct iovec **_vector,
2251 size_t *_count)
2253 struct smbd_smb2_request_read_state *state =
2254 talloc_get_type_abort(private_data,
2255 struct smbd_smb2_request_read_state);
2256 struct smbd_smb2_request *req = state->smb2_req;
2257 struct iovec *vector;
2258 int idx = req->in.vector_count;
2259 size_t len = 0;
2260 uint8_t *buf = NULL;
2262 if (req->in.vector_count == 0) {
2264 * first we need to get the NBT header
2266 req->in.vector = talloc_array(req, struct iovec,
2267 req->in.vector_count + 1);
2268 if (req->in.vector == NULL) {
2269 return -1;
2271 req->in.vector_count += 1;
2273 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2274 req->in.vector[idx].iov_len = 4;
2276 vector = talloc_array(mem_ctx, struct iovec, 1);
2277 if (vector == NULL) {
2278 return -1;
2281 vector[0] = req->in.vector[idx];
2283 *_vector = vector;
2284 *_count = 1;
2285 return 0;
2288 if (req->in.vector_count == 1) {
2290 * Now we analyze the NBT header
2292 state->missing = smb2_len(req->in.vector[0].iov_base);
2294 if (state->missing == 0) {
2295 /* if there're no remaining bytes, we're done */
2296 *_vector = NULL;
2297 *_count = 0;
2298 return 0;
2301 req->in.vector = talloc_realloc(req, req->in.vector,
2302 struct iovec,
2303 req->in.vector_count + 1);
2304 if (req->in.vector == NULL) {
2305 return -1;
2307 req->in.vector_count += 1;
2309 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2311 * it's a special NBT message,
2312 * so get all remaining bytes
2314 len = state->missing;
2315 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2317 * it's an invalid message, just read what we can get
2318 * and let the caller handle the error
2320 len = state->missing;
2321 } else {
2323 * We assume it's a SMB2 request,
2324 * and we first get the header and the
2325 * first 2 bytes (the struct size) of the body
2327 len = SMB2_HDR_BODY + 2;
2329 state->asked_for_header = true;
2332 state->missing -= len;
2334 buf = talloc_array(req->in.vector, uint8_t, len);
2335 if (buf == NULL) {
2336 return -1;
2339 req->in.vector[idx].iov_base = (void *)buf;
2340 req->in.vector[idx].iov_len = len;
2342 vector = talloc_array(mem_ctx, struct iovec, 1);
2343 if (vector == NULL) {
2344 return -1;
2347 vector[0] = req->in.vector[idx];
2349 *_vector = vector;
2350 *_count = 1;
2351 return 0;
2354 if (state->missing == 0) {
2355 /* if there're no remaining bytes, we're done */
2356 *_vector = NULL;
2357 *_count = 0;
2358 return 0;
2361 if (state->asked_for_header) {
2362 const uint8_t *hdr;
2363 size_t full_size;
2364 size_t next_command_ofs;
2365 size_t body_size;
2366 uint8_t *body;
2367 size_t dyn_size;
2368 uint8_t *dyn;
2369 bool invalid = false;
2371 state->asked_for_header = false;
2374 * We got the SMB2 header and the first 2 bytes
2375 * of the body. We fix the size to just the header
2376 * and manually copy the 2 first bytes to the body section
2378 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2379 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2381 /* allocate vectors for body and dynamic areas */
2382 req->in.vector = talloc_realloc(req, req->in.vector,
2383 struct iovec,
2384 req->in.vector_count + 2);
2385 if (req->in.vector == NULL) {
2386 return -1;
2388 req->in.vector_count += 2;
2390 full_size = state->missing + SMB2_HDR_BODY + 2;
2391 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2392 body_size = SVAL(hdr, SMB2_HDR_BODY);
2394 if (next_command_ofs != 0) {
2395 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2397 * this is invalid, just return a zero
2398 * body and let the caller deal with the error
2400 invalid = true;
2401 } else if (next_command_ofs > full_size) {
2403 * this is invalid, just return a zero
2404 * body and let the caller deal with the error
2406 invalid = true;
2407 } else {
2408 full_size = next_command_ofs;
2412 if (!invalid) {
2413 if (body_size < 2) {
2415 * this is invalid, just return a zero
2416 * body and let the caller deal with the error
2418 invalid = true;
2421 if ((body_size % 2) != 0) {
2422 body_size -= 1;
2425 if (body_size > (full_size - SMB2_HDR_BODY)) {
2427 * this is invalid, just return a zero
2428 * body and let the caller deal with the error
2430 invalid = true;
2434 if (invalid) {
2435 /* the caller should check this */
2436 body_size = 2;
2439 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2441 state->missing -= (body_size - 2) + dyn_size;
2443 body = talloc_array(req->in.vector, uint8_t, body_size);
2444 if (body == NULL) {
2445 return -1;
2448 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2449 if (dyn == NULL) {
2450 return -1;
2453 req->in.vector[idx].iov_base = (void *)body;
2454 req->in.vector[idx].iov_len = body_size;
2455 req->in.vector[idx+1].iov_base = (void *)dyn;
2456 req->in.vector[idx+1].iov_len = dyn_size;
2458 vector = talloc_array(mem_ctx, struct iovec, 2);
2459 if (vector == NULL) {
2460 return -1;
2464 * the first 2 bytes of the body were already fetched
2465 * together with the header
2467 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2468 vector[0].iov_base = body + 2;
2469 vector[0].iov_len = body_size - 2;
2471 vector[1] = req->in.vector[idx+1];
2473 *_vector = vector;
2474 *_count = 2;
2475 return 0;
2479 * when we endup here, we're looking for a new SMB2 request
2480 * next. And we ask for its header and the first 2 bytes of
2481 * the body (like we did for the first SMB2 request).
2484 req->in.vector = talloc_realloc(req, req->in.vector,
2485 struct iovec,
2486 req->in.vector_count + 1);
2487 if (req->in.vector == NULL) {
2488 return -1;
2490 req->in.vector_count += 1;
2493 * We assume it's a SMB2 request,
2494 * and we first get the header and the
2495 * first 2 bytes (the struct size) of the body
2497 len = SMB2_HDR_BODY + 2;
2499 if (len > state->missing) {
2500 /* let the caller handle the error */
2501 len = state->missing;
2504 state->missing -= len;
2505 state->asked_for_header = true;
2507 buf = talloc_array(req->in.vector, uint8_t, len);
2508 if (buf == NULL) {
2509 return -1;
2512 req->in.vector[idx].iov_base = (void *)buf;
2513 req->in.vector[idx].iov_len = len;
2515 vector = talloc_array(mem_ctx, struct iovec, 1);
2516 if (vector == NULL) {
2517 return -1;
2520 vector[0] = req->in.vector[idx];
2522 *_vector = vector;
2523 *_count = 1;
2524 return 0;
2527 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2529 struct tevent_req *req =
2530 tevent_req_callback_data(subreq,
2531 struct tevent_req);
2532 int ret;
2533 int sys_errno;
2534 NTSTATUS status;
2536 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2537 if (ret == -1) {
2538 status = map_nt_error_from_unix(sys_errno);
2539 tevent_req_nterror(req, status);
2540 return;
2543 tevent_req_done(req);
2546 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2547 TALLOC_CTX *mem_ctx,
2548 struct smbd_smb2_request **_smb2_req)
2550 struct smbd_smb2_request_read_state *state =
2551 tevent_req_data(req,
2552 struct smbd_smb2_request_read_state);
2553 NTSTATUS status;
2555 if (tevent_req_is_nterror(req, &status)) {
2556 tevent_req_received(req);
2557 return status;
2560 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2561 *_smb2_req = state->smb2_req;
2562 tevent_req_received(req);
2563 return NT_STATUS_OK;
2566 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2568 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2570 size_t max_send_queue_len;
2571 size_t cur_send_queue_len;
2572 struct tevent_req *subreq;
2574 if (sconn->smb2.compound_related_in_progress) {
2576 * Can't read another until the related
2577 * compound is done.
2579 return NT_STATUS_OK;
2582 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2584 * if there is already a smbd_smb2_request_read
2585 * pending, we are done.
2587 return NT_STATUS_OK;
2590 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2591 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2593 if (cur_send_queue_len > max_send_queue_len) {
2595 * if we have a lot of requests to send,
2596 * we wait until they are on the wire until we
2597 * ask for the next request.
2599 return NT_STATUS_OK;
2602 /* ask for the next request */
2603 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2604 if (subreq == NULL) {
2605 return NT_STATUS_NO_MEMORY;
2607 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2609 return NT_STATUS_OK;
2612 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2613 const uint8_t *inbuf, size_t size)
2615 NTSTATUS status;
2616 struct smbd_smb2_request *req = NULL;
2618 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2619 (unsigned int)size));
2621 status = smbd_initialize_smb2(sconn);
2622 if (!NT_STATUS_IS_OK(status)) {
2623 smbd_server_connection_terminate(sconn, nt_errstr(status));
2624 return;
2627 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2628 if (!NT_STATUS_IS_OK(status)) {
2629 smbd_server_connection_terminate(sconn, nt_errstr(status));
2630 return;
2633 status = smbd_smb2_request_validate(req);
2634 if (!NT_STATUS_IS_OK(status)) {
2635 smbd_server_connection_terminate(sconn, nt_errstr(status));
2636 return;
2639 status = smbd_smb2_request_setup_out(req);
2640 if (!NT_STATUS_IS_OK(status)) {
2641 smbd_server_connection_terminate(sconn, nt_errstr(status));
2642 return;
2645 status = smbd_smb2_request_dispatch(req);
2646 if (!NT_STATUS_IS_OK(status)) {
2647 smbd_server_connection_terminate(sconn, nt_errstr(status));
2648 return;
2651 status = smbd_smb2_request_next_incoming(sconn);
2652 if (!NT_STATUS_IS_OK(status)) {
2653 smbd_server_connection_terminate(sconn, nt_errstr(status));
2654 return;
2657 sconn->num_requests++;
2660 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2662 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2663 struct smbd_server_connection);
2664 NTSTATUS status;
2665 struct smbd_smb2_request *req = NULL;
2667 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2668 TALLOC_FREE(subreq);
2669 if (!NT_STATUS_IS_OK(status)) {
2670 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2671 nt_errstr(status)));
2672 smbd_server_connection_terminate(sconn, nt_errstr(status));
2673 return;
2676 if (req->in.nbt_hdr[0] != 0x00) {
2677 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2678 req->in.nbt_hdr[0]));
2679 TALLOC_FREE(req);
2680 goto next;
2683 req->current_idx = 1;
2685 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2686 req->current_idx, req->in.vector_count));
2688 status = smbd_smb2_request_validate(req);
2689 if (!NT_STATUS_IS_OK(status)) {
2690 smbd_server_connection_terminate(sconn, nt_errstr(status));
2691 return;
2694 status = smbd_smb2_request_setup_out(req);
2695 if (!NT_STATUS_IS_OK(status)) {
2696 smbd_server_connection_terminate(sconn, nt_errstr(status));
2697 return;
2700 status = smbd_smb2_request_dispatch(req);
2701 if (!NT_STATUS_IS_OK(status)) {
2702 smbd_server_connection_terminate(sconn, nt_errstr(status));
2703 return;
2706 next:
2707 status = smbd_smb2_request_next_incoming(sconn);
2708 if (!NT_STATUS_IS_OK(status)) {
2709 smbd_server_connection_terminate(sconn, nt_errstr(status));
2710 return;
2713 sconn->num_requests++;
2715 /* The timeout_processing function isn't run nearly
2716 often enough to implement 'max log size' without
2717 overrunning the size of the file by many megabytes.
2718 This is especially true if we are running at debug
2719 level 10. Checking every 50 SMB2s is a nice
2720 tradeoff of performance vs log file size overrun. */
2722 if ((sconn->num_requests % 50) == 0 &&
2723 need_to_check_log_size()) {
2724 change_to_root_user();
2725 check_log_size();