Ensure we don't return uninitialized memory in the pad bytes.
[Samba.git] / source3 / smbd / smb2_server.c
blobcc884c383eb1bdc42e3d8235a3a5e91cd831040c
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;
430 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
431 return NT_STATUS_INVALID_PARAMETER;
434 if (req->in.vector[idx+1].iov_len < 2) {
435 return NT_STATUS_INVALID_PARAMETER;
438 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
440 /* Check the SMB2 header */
441 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
442 return NT_STATUS_INVALID_PARAMETER;
445 if (!smb2_validate_message_id(req->sconn, inhdr)) {
446 return NT_STATUS_INVALID_PARAMETER;
450 return NT_STATUS_OK;
453 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
454 const struct iovec *in_vector,
455 struct iovec *out_vector)
457 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
458 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
459 uint16_t credits_requested;
460 uint32_t out_flags;
461 uint16_t cmd;
462 NTSTATUS out_status;
463 uint16_t credits_granted = 0;
464 uint64_t credits_possible;
465 uint16_t current_max_credits;
468 * first we grant only 1/16th of the max range.
470 * Windows also starts with the 1/16th and then grants
471 * more later. I was only able to trigger higher
472 * values, when using a verify high credit charge.
474 * TODO: scale up depending one load, free memory
475 * or other stuff.
476 * Maybe also on the relationship between number
477 * of requests and the used sequence number.
478 * Which means we would grant more credits
479 * for client which use multi credit requests.
481 current_max_credits = sconn->smb2.max_credits / 16;
482 current_max_credits = MAX(current_max_credits, 1);
484 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
485 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
486 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
487 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
489 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
491 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
493 * In case we already send an async interim
494 * response, we should not grant
495 * credits on the final response.
497 credits_granted = 0;
498 } else if (credits_requested > 0) {
499 uint16_t additional_max = 0;
500 uint16_t additional_credits = credits_requested - 1;
502 switch (cmd) {
503 case SMB2_OP_NEGPROT:
504 break;
505 case SMB2_OP_SESSSETUP:
507 * Windows 2012 RC1 starts to grant
508 * additional credits
509 * with a successful session setup
511 if (NT_STATUS_IS_OK(out_status)) {
512 additional_max = 32;
514 break;
515 default:
517 * We match windows and only grant additional credits
518 * in chunks of 32.
520 additional_max = 32;
521 break;
524 additional_credits = MIN(additional_credits, additional_max);
526 credits_granted = 1 + additional_credits;
527 } else if (sconn->smb2.credits_granted == 0) {
529 * Make sure the client has always at least one credit
531 credits_granted = 1;
535 * sequence numbers should not wrap
537 * 1. calculate the possible credits until
538 * the sequence numbers start to wrap on 64-bit.
540 * 2. UINT64_MAX is used for Break Notifications.
542 * 2. truncate the possible credits to the maximum
543 * credits we want to grant to the client in total.
545 * 3. remove the range we'll already granted to the client
546 * this makes sure the client consumes the lowest sequence
547 * number, before we can grant additional credits.
549 credits_possible = UINT64_MAX - sconn->smb2.seqnum_low;
550 if (credits_possible > 0) {
551 /* remove UINT64_MAX */
552 credits_possible -= 1;
554 credits_possible = MIN(credits_possible, current_max_credits);
555 credits_possible -= sconn->smb2.seqnum_range;
557 credits_granted = MIN(credits_granted, credits_possible);
559 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
560 sconn->smb2.credits_granted += credits_granted;
561 sconn->smb2.seqnum_range += credits_granted;
563 DEBUG(10,("smb2_set_operation_credit: requested %u, "
564 "granted %u, current possible/max %u/%u, "
565 "total granted/max/low/range %u/%u/%llu/%u\n",
566 (unsigned int)credits_requested,
567 (unsigned int)credits_granted,
568 (unsigned int)credits_possible,
569 (unsigned int)current_max_credits,
570 (unsigned int)sconn->smb2.credits_granted,
571 (unsigned int)sconn->smb2.max_credits,
572 (unsigned long long)sconn->smb2.seqnum_low,
573 (unsigned int)sconn->smb2.seqnum_range));
576 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
577 struct smbd_smb2_request *outreq)
579 int count, idx;
580 uint16_t total_credits = 0;
582 count = outreq->out.vector_count;
584 for (idx=1; idx < count; idx += 3) {
585 uint8_t *outhdr = (uint8_t *)outreq->out.vector[idx].iov_base;
586 smb2_set_operation_credit(outreq->sconn,
587 &inreq->in.vector[idx],
588 &outreq->out.vector[idx]);
589 /* To match Windows, count up what we
590 just granted. */
591 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
592 /* Set to zero in all but the last reply. */
593 if (idx + 3 < count) {
594 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
595 } else {
596 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
601 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
603 struct iovec *vector;
604 int count;
605 int idx;
607 count = req->in.vector_count;
608 vector = talloc_zero_array(req, struct iovec, count);
609 if (vector == NULL) {
610 return NT_STATUS_NO_MEMORY;
613 vector[0].iov_base = req->out.nbt_hdr;
614 vector[0].iov_len = 4;
615 SIVAL(req->out.nbt_hdr, 0, 0);
617 for (idx=1; idx < count; idx += 3) {
618 const uint8_t *inhdr = NULL;
619 uint32_t in_flags;
620 uint8_t *outhdr = NULL;
621 uint8_t *outbody = NULL;
622 uint32_t next_command_ofs = 0;
623 struct iovec *current = &vector[idx];
625 if ((idx + 3) < count) {
626 /* we have a next command -
627 * setup for the error case. */
628 next_command_ofs = SMB2_HDR_BODY + 9;
631 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
632 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
634 outhdr = talloc_zero_array(vector, uint8_t,
635 OUTVEC_ALLOC_SIZE);
636 if (outhdr == NULL) {
637 return NT_STATUS_NO_MEMORY;
640 outbody = outhdr + SMB2_HDR_BODY;
642 current[0].iov_base = (void *)outhdr;
643 current[0].iov_len = SMB2_HDR_BODY;
645 current[1].iov_base = (void *)outbody;
646 current[1].iov_len = 8;
648 current[2].iov_base = NULL;
649 current[2].iov_len = 0;
651 /* setup the SMB2 header */
652 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
653 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
654 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
655 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
656 SIVAL(outhdr, SMB2_HDR_STATUS,
657 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
658 SSVAL(outhdr, SMB2_HDR_OPCODE,
659 SVAL(inhdr, SMB2_HDR_OPCODE));
660 SIVAL(outhdr, SMB2_HDR_FLAGS,
661 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
662 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
663 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
664 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
665 SIVAL(outhdr, SMB2_HDR_PID,
666 IVAL(inhdr, SMB2_HDR_PID));
667 SIVAL(outhdr, SMB2_HDR_TID,
668 IVAL(inhdr, SMB2_HDR_TID));
669 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
670 BVAL(inhdr, SMB2_HDR_SESSION_ID));
671 memcpy(outhdr + SMB2_HDR_SIGNATURE,
672 inhdr + SMB2_HDR_SIGNATURE, 16);
674 /* setup error body header */
675 SSVAL(outbody, 0x00, 0x08 + 1);
676 SSVAL(outbody, 0x02, 0);
677 SIVAL(outbody, 0x04, 0);
680 req->out.vector = vector;
681 req->out.vector_count = count;
683 /* setup the length of the NBT packet */
684 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
686 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
688 return NT_STATUS_OK;
691 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
692 const char *reason,
693 const char *location)
695 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
696 reason, location));
697 exit_server_cleanly(reason);
700 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
701 struct iovec *outvec,
702 const struct iovec *srcvec)
704 /* vec[0] is always boilerplate and must
705 * be allocated with size OUTVEC_ALLOC_SIZE. */
707 outvec[0].iov_base = talloc_memdup(ctx,
708 srcvec[0].iov_base,
709 OUTVEC_ALLOC_SIZE);
710 if (!outvec[0].iov_base) {
711 return false;
713 outvec[0].iov_len = SMB2_HDR_BODY;
716 * If this is a "standard" vec[1] of length 8,
717 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
718 * then duplicate this. Else use talloc_memdup().
721 if (srcvec[1].iov_len == 8 &&
722 srcvec[1].iov_base ==
723 ((uint8_t *)srcvec[0].iov_base) +
724 SMB2_HDR_BODY) {
725 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
726 SMB2_HDR_BODY;
727 outvec[1].iov_len = 8;
728 } else {
729 outvec[1].iov_base = talloc_memdup(ctx,
730 srcvec[1].iov_base,
731 srcvec[1].iov_len);
732 if (!outvec[1].iov_base) {
733 return false;
735 outvec[1].iov_len = srcvec[1].iov_len;
739 * If this is a "standard" vec[2] of length 1,
740 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
741 * then duplicate this. Else use talloc_memdup().
744 if (srcvec[2].iov_base &&
745 srcvec[2].iov_len) {
746 if (srcvec[2].iov_base ==
747 ((uint8_t *)srcvec[0].iov_base) +
748 (OUTVEC_ALLOC_SIZE - 1) &&
749 srcvec[2].iov_len == 1) {
750 /* Common SMB2 error packet case. */
751 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
752 (OUTVEC_ALLOC_SIZE - 1);
753 } else {
754 outvec[2].iov_base = talloc_memdup(ctx,
755 srcvec[2].iov_base,
756 srcvec[2].iov_len);
757 if (!outvec[2].iov_base) {
758 return false;
761 outvec[2].iov_len = srcvec[2].iov_len;
762 } else {
763 outvec[2].iov_base = NULL;
764 outvec[2].iov_len = 0;
766 return true;
769 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
771 struct smbd_smb2_request *newreq = NULL;
772 struct iovec *outvec = NULL;
773 int count = req->out.vector_count;
774 int i;
776 newreq = smbd_smb2_request_allocate(req->sconn);
777 if (!newreq) {
778 return NULL;
781 newreq->sconn = req->sconn;
782 newreq->session = req->session;
783 newreq->do_signing = req->do_signing;
784 newreq->current_idx = req->current_idx;
785 newreq->async = false;
786 newreq->cancelled = false;
787 /* Note we are leaving:
788 ->tcon
789 ->smb1req
790 ->compat_chain_fsp
791 uninitialized as NULL here as
792 they're not used in the interim
793 response code. JRA. */
795 outvec = talloc_zero_array(newreq, struct iovec, count);
796 if (!outvec) {
797 TALLOC_FREE(newreq);
798 return NULL;
800 newreq->out.vector = outvec;
801 newreq->out.vector_count = count;
803 /* Setup the outvec's identically to req. */
804 outvec[0].iov_base = newreq->out.nbt_hdr;
805 outvec[0].iov_len = 4;
806 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
808 /* Setup the vectors identically to the ones in req. */
809 for (i = 1; i < count; i += 3) {
810 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
811 break;
815 if (i < count) {
816 /* Alloc failed. */
817 TALLOC_FREE(newreq);
818 return NULL;
821 smb2_setup_nbt_length(newreq->out.vector,
822 newreq->out.vector_count);
824 return newreq;
827 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
829 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
831 int i = 0;
832 uint8_t *outhdr = NULL;
833 struct smbd_smb2_request *nreq = NULL;
835 /* Create a new smb2 request we'll use
836 for the interim return. */
837 nreq = dup_smb2_req(req);
838 if (!nreq) {
839 return NT_STATUS_NO_MEMORY;
842 /* Lose the last 3 out vectors. They're the
843 ones we'll be using for the async reply. */
844 nreq->out.vector_count -= 3;
846 smb2_setup_nbt_length(nreq->out.vector,
847 nreq->out.vector_count);
849 /* Step back to the previous reply. */
850 i = nreq->current_idx - 3;
851 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
852 /* And end the chain. */
853 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
855 /* Calculate outgoing credits */
856 smb2_calculate_credits(req, nreq);
858 /* Re-sign if needed. */
859 if (nreq->do_signing) {
860 NTSTATUS status;
861 status = smb2_signing_sign_pdu(nreq->session->session_key,
862 &nreq->out.vector[i], 3);
863 if (!NT_STATUS_IS_OK(status)) {
864 return status;
867 if (DEBUGLEVEL >= 10) {
868 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
869 (unsigned int)nreq->current_idx );
870 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
871 (unsigned int)nreq->out.vector_count );
872 print_req_vectors(nreq);
874 nreq->subreq = tstream_writev_queue_send(nreq,
875 nreq->sconn->smb2.event_ctx,
876 nreq->sconn->smb2.stream,
877 nreq->sconn->smb2.send_queue,
878 nreq->out.vector,
879 nreq->out.vector_count);
881 if (nreq->subreq == NULL) {
882 return NT_STATUS_NO_MEMORY;
885 tevent_req_set_callback(nreq->subreq,
886 smbd_smb2_request_writev_done,
887 nreq);
889 return NT_STATUS_OK;
892 struct smbd_smb2_request_pending_state {
893 struct smbd_server_connection *sconn;
894 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
895 struct iovec vector[3];
898 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
900 struct smbd_smb2_request_pending_state *state =
901 tevent_req_callback_data(subreq,
902 struct smbd_smb2_request_pending_state);
903 struct smbd_server_connection *sconn = state->sconn;
904 int ret;
905 int sys_errno;
907 ret = tstream_writev_queue_recv(subreq, &sys_errno);
908 TALLOC_FREE(subreq);
909 if (ret == -1) {
910 NTSTATUS status = map_nt_error_from_unix(sys_errno);
911 smbd_server_connection_terminate(sconn, nt_errstr(status));
912 return;
915 TALLOC_FREE(state);
918 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
919 struct tevent_req *subreq)
921 NTSTATUS status;
922 struct smbd_smb2_request_pending_state *state = NULL;
923 int i = req->current_idx;
924 uint8_t *reqhdr = NULL;
925 uint8_t *hdr = NULL;
926 uint8_t *body = NULL;
927 uint32_t flags = 0;
928 uint64_t message_id = 0;
929 uint64_t async_id = 0;
930 struct iovec *outvec = NULL;
932 if (!tevent_req_is_in_progress(subreq)) {
933 return NT_STATUS_OK;
936 req->subreq = subreq;
937 subreq = NULL;
939 if (req->async) {
940 /* We're already async. */
941 return NT_STATUS_OK;
944 if (req->in.vector_count > i + 3) {
946 * We're trying to go async in a compound
947 * request chain. This is not allowed.
948 * Cancel the outstanding request.
950 bool ok = tevent_req_cancel(req->subreq);
951 if (ok) {
952 return NT_STATUS_OK;
954 TALLOC_FREE(req->subreq);
955 return smbd_smb2_request_error(req,
956 NT_STATUS_INTERNAL_ERROR);
959 if (DEBUGLEVEL >= 10) {
960 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
961 (unsigned int)req->current_idx );
962 print_req_vectors(req);
965 if (req->out.vector_count > 4) {
966 /* This is a compound reply. We
967 * must do an interim response
968 * followed by the async response
969 * to match W2K8R2.
971 status = smb2_send_async_interim_response(req);
972 if (!NT_STATUS_IS_OK(status)) {
973 return status;
977 * We're splitting off the last SMB2
978 * request in a compound set, and the
979 * smb2_send_async_interim_response()
980 * call above just sent all the replies
981 * for the previous SMB2 requests in
982 * this compound set. So we're no longer
983 * in the "compound_related_in_progress"
984 * state, and this is no longer a compound
985 * request.
987 req->compound_related = false;
988 req->sconn->smb2.compound_related_in_progress = false;
991 /* Don't return an intermediate packet on a pipe read/write. */
992 if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
993 goto ipc_out;
996 reqhdr = (uint8_t *)req->out.vector[i].iov_base;
997 flags = (IVAL(reqhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
998 message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
999 async_id = message_id; /* keep it simple for now... */
1002 * What we send is identical to a smbd_smb2_request_error
1003 * packet with an error status of STATUS_PENDING. Make use
1004 * of this fact sometime when refactoring. JRA.
1007 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1008 if (state == NULL) {
1009 return NT_STATUS_NO_MEMORY;
1011 state->sconn = req->sconn;
1013 state->vector[0].iov_base = (void *)state->buf;
1014 state->vector[0].iov_len = 4;
1016 state->vector[1].iov_base = state->buf + 4;
1017 state->vector[1].iov_len = SMB2_HDR_BODY;
1019 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
1020 state->vector[2].iov_len = 9;
1022 smb2_setup_nbt_length(state->vector, 3);
1024 hdr = (uint8_t *)state->vector[1].iov_base;
1025 body = (uint8_t *)state->vector[2].iov_base;
1027 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1028 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1029 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1030 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1031 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(reqhdr, SMB2_HDR_OPCODE));
1033 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1034 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1035 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1036 SBVAL(hdr, SMB2_HDR_PID, async_id);
1037 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1038 BVAL(reqhdr, SMB2_HDR_SESSION_ID));
1039 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
1041 SSVAL(body, 0x00, 0x08 + 1);
1043 SCVAL(body, 0x02, 0);
1044 SCVAL(body, 0x03, 0);
1045 SIVAL(body, 0x04, 0);
1046 /* Match W2K8R2... */
1047 SCVAL(body, 0x08, 0x21);
1049 /* Ensure we correctly go through crediting. Grant
1050 the credits now, and zero credits on the final
1051 response. */
1052 smb2_set_operation_credit(req->sconn,
1053 &req->in.vector[i],
1054 &state->vector[1]);
1056 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1058 if (req->do_signing) {
1059 status = smb2_signing_sign_pdu(req->session->session_key,
1060 &state->vector[1], 2);
1061 if (!NT_STATUS_IS_OK(status)) {
1062 return status;
1066 subreq = tstream_writev_queue_send(state,
1067 req->sconn->smb2.event_ctx,
1068 req->sconn->smb2.stream,
1069 req->sconn->smb2.send_queue,
1070 state->vector,
1073 if (subreq == NULL) {
1074 return NT_STATUS_NO_MEMORY;
1077 tevent_req_set_callback(subreq,
1078 smbd_smb2_request_pending_writev_done,
1079 state);
1081 /* Note we're going async with this request. */
1082 req->async = true;
1084 ipc_out:
1087 * Now manipulate req so that the outstanding async request
1088 * is the only one left in the struct smbd_smb2_request.
1091 if (req->current_idx == 1) {
1092 /* There was only one. */
1093 goto out;
1096 /* Re-arrange the in.vectors. */
1097 req->in.vector[1] = req->in.vector[i];
1098 req->in.vector[2] = req->in.vector[i+1];
1099 req->in.vector[3] = req->in.vector[i+2];
1100 req->in.vector_count = 4;
1101 /* Reset the new in size. */
1102 smb2_setup_nbt_length(req->in.vector, 4);
1104 /* Now recreate the out.vectors. */
1105 outvec = talloc_zero_array(req, struct iovec, 4);
1106 if (!outvec) {
1107 return NT_STATUS_NO_MEMORY;
1110 /* 0 is always boilerplate and must
1111 * be of size 4 for the length field. */
1113 outvec[0].iov_base = req->out.nbt_hdr;
1114 outvec[0].iov_len = 4;
1115 SIVAL(req->out.nbt_hdr, 0, 0);
1117 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
1118 return NT_STATUS_NO_MEMORY;
1121 TALLOC_FREE(req->out.vector);
1123 req->out.vector = outvec;
1125 req->current_idx = 1;
1126 req->out.vector_count = 4;
1128 out:
1130 smb2_setup_nbt_length(req->out.vector,
1131 req->out.vector_count);
1133 if (req->async) {
1134 /* Ensure our final reply matches the interim one. */
1135 reqhdr = (uint8_t *)req->out.vector[1].iov_base;
1136 SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1137 SBVAL(reqhdr, SMB2_HDR_PID, async_id);
1140 const uint8_t *inhdr =
1141 (const uint8_t *)req->in.vector[1].iov_base;
1142 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1143 "going async\n",
1144 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1145 (unsigned long long)async_id ));
1149 return NT_STATUS_OK;
1152 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1154 struct smbd_server_connection *sconn = req->sconn;
1155 struct smbd_smb2_request *cur;
1156 const uint8_t *inhdr;
1157 int i = req->current_idx;
1158 uint32_t flags;
1159 uint64_t search_message_id;
1160 uint64_t search_async_id;
1161 uint64_t found_id;
1163 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1165 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1166 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1167 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1170 * we don't need the request anymore
1171 * cancel requests never have a response
1173 DLIST_REMOVE(req->sconn->smb2.requests, req);
1174 TALLOC_FREE(req);
1176 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1177 const uint8_t *outhdr;
1178 uint64_t message_id;
1179 uint64_t async_id;
1181 i = cur->current_idx;
1183 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1185 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1186 async_id = BVAL(outhdr, SMB2_HDR_PID);
1188 if (flags & SMB2_HDR_FLAG_ASYNC) {
1189 if (search_async_id == async_id) {
1190 found_id = async_id;
1191 break;
1193 } else {
1194 if (search_message_id == message_id) {
1195 found_id = message_id;
1196 break;
1201 if (cur && cur->subreq) {
1202 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1203 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1204 "cancel opcode[%s] mid %llu\n",
1205 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1206 (unsigned long long)found_id ));
1207 tevent_req_cancel(cur->subreq);
1210 return NT_STATUS_OK;
1213 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1214 size_t expected_body_size)
1216 const uint8_t *inhdr;
1217 uint16_t opcode;
1218 const uint8_t *inbody;
1219 int i = req->current_idx;
1220 size_t body_size;
1221 size_t min_dyn_size = expected_body_size & 0x00000001;
1224 * The following should be checked already.
1226 if ((i+2) > req->in.vector_count) {
1227 return NT_STATUS_INTERNAL_ERROR;
1229 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1230 return NT_STATUS_INTERNAL_ERROR;
1232 if (req->in.vector[i+1].iov_len < 2) {
1233 return NT_STATUS_INTERNAL_ERROR;
1236 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1237 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1239 switch (opcode) {
1240 case SMB2_OP_IOCTL:
1241 case SMB2_OP_GETINFO:
1242 min_dyn_size = 0;
1243 break;
1247 * Now check the expected body size,
1248 * where the last byte might be in the
1249 * dynnamic section..
1251 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1252 return NT_STATUS_INVALID_PARAMETER;
1254 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1255 return NT_STATUS_INVALID_PARAMETER;
1258 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1260 body_size = SVAL(inbody, 0x00);
1261 if (body_size != expected_body_size) {
1262 return NT_STATUS_INVALID_PARAMETER;
1265 return NT_STATUS_OK;
1268 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1270 const uint8_t *inhdr;
1271 int i = req->current_idx;
1272 uint16_t opcode;
1273 uint32_t flags;
1274 uint64_t mid;
1275 NTSTATUS status;
1276 NTSTATUS session_status;
1277 uint32_t allowed_flags;
1278 NTSTATUS return_value;
1280 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1282 /* TODO: verify more things */
1284 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1285 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1286 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1287 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1288 smb2_opcode_name(opcode),
1289 (unsigned long long)mid));
1291 if (get_Protocol() >= PROTOCOL_SMB2) {
1293 * once the protocol is negotiated
1294 * SMB2_OP_NEGPROT is not allowed anymore
1296 if (opcode == SMB2_OP_NEGPROT) {
1297 /* drop the connection */
1298 return NT_STATUS_INVALID_PARAMETER;
1300 } else {
1302 * if the protocol is not negotiated yet
1303 * only SMB2_OP_NEGPROT is allowed.
1305 if (opcode != SMB2_OP_NEGPROT) {
1306 /* drop the connection */
1307 return NT_STATUS_INVALID_PARAMETER;
1311 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1312 SMB2_HDR_FLAG_SIGNED |
1313 SMB2_HDR_FLAG_DFS;
1314 if (opcode == SMB2_OP_CANCEL) {
1315 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1317 if ((flags & ~allowed_flags) != 0) {
1318 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1322 * Check if the client provided a valid session id,
1323 * if so smbd_smb2_request_check_session() calls
1324 * set_current_user_info().
1326 * As some command don't require a valid session id
1327 * we defer the check of the session_status
1329 session_status = smbd_smb2_request_check_session(req);
1331 if (flags & SMB2_HDR_FLAG_CHAINED) {
1333 * This check is mostly for giving the correct error code
1334 * for compounded requests.
1336 if (!NT_STATUS_IS_OK(session_status)) {
1337 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1339 } else {
1340 req->compat_chain_fsp = NULL;
1343 req->do_signing = false;
1344 if (flags & SMB2_HDR_FLAG_SIGNED) {
1345 if (!NT_STATUS_IS_OK(session_status)) {
1346 return smbd_smb2_request_error(req, session_status);
1349 req->do_signing = true;
1350 status = smb2_signing_check_pdu(req->session->session_key,
1351 &req->in.vector[i], 3);
1352 if (!NT_STATUS_IS_OK(status)) {
1353 return smbd_smb2_request_error(req, status);
1355 } else if (opcode == SMB2_OP_CANCEL) {
1356 /* Cancel requests are allowed to skip the signing */
1357 } else if (req->session && req->session->do_signing) {
1358 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1361 if (flags & SMB2_HDR_FLAG_CHAINED) {
1362 req->compound_related = true;
1363 req->sconn->smb2.compound_related_in_progress = true;
1366 switch (opcode) {
1367 case SMB2_OP_NEGPROT:
1368 /* This call needs to be run as root */
1369 change_to_root_user();
1372 START_PROFILE(smb2_negprot);
1373 return_value = smbd_smb2_request_process_negprot(req);
1374 END_PROFILE(smb2_negprot);
1376 break;
1378 case SMB2_OP_SESSSETUP:
1379 /* This call needs to be run as root */
1380 change_to_root_user();
1383 START_PROFILE(smb2_sesssetup);
1384 return_value = smbd_smb2_request_process_sesssetup(req);
1385 END_PROFILE(smb2_sesssetup);
1387 break;
1389 case SMB2_OP_LOGOFF:
1390 if (!NT_STATUS_IS_OK(session_status)) {
1391 return_value = smbd_smb2_request_error(req, session_status);
1392 break;
1395 /* This call needs to be run as root */
1396 change_to_root_user();
1399 START_PROFILE(smb2_logoff);
1400 return_value = smbd_smb2_request_process_logoff(req);
1401 END_PROFILE(smb2_logoff);
1403 break;
1405 case SMB2_OP_TCON:
1406 if (!NT_STATUS_IS_OK(session_status)) {
1407 return_value = smbd_smb2_request_error(req, session_status);
1408 break;
1412 * This call needs to be run as root.
1414 * smbd_smb2_request_process_tcon()
1415 * calls make_connection_snum(), which will call
1416 * change_to_user(), when needed.
1418 change_to_root_user();
1421 START_PROFILE(smb2_tcon);
1422 return_value = smbd_smb2_request_process_tcon(req);
1423 END_PROFILE(smb2_tcon);
1425 break;
1427 case SMB2_OP_TDIS:
1428 if (!NT_STATUS_IS_OK(session_status)) {
1429 return_value = smbd_smb2_request_error(req, session_status);
1430 break;
1433 * This call needs to be run as user.
1435 * smbd_smb2_request_check_tcon()
1436 * calls change_to_user() on success.
1438 status = smbd_smb2_request_check_tcon(req);
1439 if (!NT_STATUS_IS_OK(status)) {
1440 return_value = smbd_smb2_request_error(req, status);
1441 break;
1443 /* This call needs to be run as root */
1444 change_to_root_user();
1448 START_PROFILE(smb2_tdis);
1449 return_value = smbd_smb2_request_process_tdis(req);
1450 END_PROFILE(smb2_tdis);
1452 break;
1454 case SMB2_OP_CREATE:
1455 if (!NT_STATUS_IS_OK(session_status)) {
1456 return_value = smbd_smb2_request_error(req, session_status);
1457 break;
1460 * This call needs to be run as user.
1462 * smbd_smb2_request_check_tcon()
1463 * calls change_to_user() on success.
1465 status = smbd_smb2_request_check_tcon(req);
1466 if (!NT_STATUS_IS_OK(status)) {
1467 return_value = smbd_smb2_request_error(req, status);
1468 break;
1472 START_PROFILE(smb2_create);
1473 return_value = smbd_smb2_request_process_create(req);
1474 END_PROFILE(smb2_create);
1476 break;
1478 case SMB2_OP_CLOSE:
1479 if (!NT_STATUS_IS_OK(session_status)) {
1480 return_value = smbd_smb2_request_error(req, session_status);
1481 break;
1484 * This call needs to be run as user.
1486 * smbd_smb2_request_check_tcon()
1487 * calls change_to_user() on success.
1489 status = smbd_smb2_request_check_tcon(req);
1490 if (!NT_STATUS_IS_OK(status)) {
1491 return_value = smbd_smb2_request_error(req, status);
1492 break;
1496 START_PROFILE(smb2_close);
1497 return_value = smbd_smb2_request_process_close(req);
1498 END_PROFILE(smb2_close);
1500 break;
1502 case SMB2_OP_FLUSH:
1503 if (!NT_STATUS_IS_OK(session_status)) {
1504 return_value = smbd_smb2_request_error(req, session_status);
1505 break;
1508 * This call needs to be run as user.
1510 * smbd_smb2_request_check_tcon()
1511 * calls change_to_user() on success.
1513 status = smbd_smb2_request_check_tcon(req);
1514 if (!NT_STATUS_IS_OK(status)) {
1515 return_value = smbd_smb2_request_error(req, status);
1516 break;
1520 START_PROFILE(smb2_flush);
1521 return_value = smbd_smb2_request_process_flush(req);
1522 END_PROFILE(smb2_flush);
1524 break;
1526 case SMB2_OP_READ:
1527 if (!NT_STATUS_IS_OK(session_status)) {
1528 return_value = smbd_smb2_request_error(req, session_status);
1529 break;
1532 * This call needs to be run as user.
1534 * smbd_smb2_request_check_tcon()
1535 * calls change_to_user() on success.
1537 status = smbd_smb2_request_check_tcon(req);
1538 if (!NT_STATUS_IS_OK(status)) {
1539 return_value = smbd_smb2_request_error(req, status);
1540 break;
1544 START_PROFILE(smb2_read);
1545 return_value = smbd_smb2_request_process_read(req);
1546 END_PROFILE(smb2_read);
1548 break;
1550 case SMB2_OP_WRITE:
1551 if (!NT_STATUS_IS_OK(session_status)) {
1552 return_value = smbd_smb2_request_error(req, session_status);
1553 break;
1556 * This call needs to be run as user.
1558 * smbd_smb2_request_check_tcon()
1559 * calls change_to_user() on success.
1561 status = smbd_smb2_request_check_tcon(req);
1562 if (!NT_STATUS_IS_OK(status)) {
1563 return_value = smbd_smb2_request_error(req, status);
1564 break;
1568 START_PROFILE(smb2_write);
1569 return_value = smbd_smb2_request_process_write(req);
1570 END_PROFILE(smb2_write);
1572 break;
1574 case SMB2_OP_LOCK:
1575 if (!NT_STATUS_IS_OK(session_status)) {
1576 /* Too ugly to live ? JRA. */
1577 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1578 session_status = NT_STATUS_FILE_CLOSED;
1580 return_value = smbd_smb2_request_error(req, session_status);
1581 break;
1584 * This call needs to be run as user.
1586 * smbd_smb2_request_check_tcon()
1587 * calls change_to_user() on success.
1589 status = smbd_smb2_request_check_tcon(req);
1590 if (!NT_STATUS_IS_OK(status)) {
1591 /* Too ugly to live ? JRA. */
1592 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1593 status = NT_STATUS_FILE_CLOSED;
1595 return_value = smbd_smb2_request_error(req, status);
1596 break;
1600 START_PROFILE(smb2_lock);
1601 return_value = smbd_smb2_request_process_lock(req);
1602 END_PROFILE(smb2_lock);
1604 break;
1606 case SMB2_OP_IOCTL:
1607 if (!NT_STATUS_IS_OK(session_status)) {
1608 return_value = smbd_smb2_request_error(req, session_status);
1609 break;
1612 * This call needs to be run as user.
1614 * smbd_smb2_request_check_tcon()
1615 * calls change_to_user() on success.
1617 status = smbd_smb2_request_check_tcon(req);
1618 if (!NT_STATUS_IS_OK(status)) {
1619 return_value = smbd_smb2_request_error(req, status);
1620 break;
1624 START_PROFILE(smb2_ioctl);
1625 return_value = smbd_smb2_request_process_ioctl(req);
1626 END_PROFILE(smb2_ioctl);
1628 break;
1630 case SMB2_OP_CANCEL:
1632 * This call needs to be run as root
1634 * That is what we also do in the SMB1 case.
1636 change_to_root_user();
1639 START_PROFILE(smb2_cancel);
1640 return_value = smbd_smb2_request_process_cancel(req);
1641 END_PROFILE(smb2_cancel);
1643 break;
1645 case SMB2_OP_KEEPALIVE:
1646 /* This call needs to be run as root */
1647 change_to_root_user();
1650 START_PROFILE(smb2_keepalive);
1651 return_value = smbd_smb2_request_process_keepalive(req);
1652 END_PROFILE(smb2_keepalive);
1654 break;
1656 case SMB2_OP_FIND:
1657 if (!NT_STATUS_IS_OK(session_status)) {
1658 return_value = smbd_smb2_request_error(req, session_status);
1659 break;
1662 * This call needs to be run as user.
1664 * smbd_smb2_request_check_tcon()
1665 * calls change_to_user() on success.
1667 status = smbd_smb2_request_check_tcon(req);
1668 if (!NT_STATUS_IS_OK(status)) {
1669 return_value = smbd_smb2_request_error(req, status);
1670 break;
1674 START_PROFILE(smb2_find);
1675 return_value = smbd_smb2_request_process_find(req);
1676 END_PROFILE(smb2_find);
1678 break;
1680 case SMB2_OP_NOTIFY:
1681 if (!NT_STATUS_IS_OK(session_status)) {
1682 return_value = smbd_smb2_request_error(req, session_status);
1683 break;
1686 * This call needs to be run as user.
1688 * smbd_smb2_request_check_tcon()
1689 * calls change_to_user() on success.
1691 status = smbd_smb2_request_check_tcon(req);
1692 if (!NT_STATUS_IS_OK(status)) {
1693 return_value = smbd_smb2_request_error(req, status);
1694 break;
1698 START_PROFILE(smb2_notify);
1699 return_value = smbd_smb2_request_process_notify(req);
1700 END_PROFILE(smb2_notify);
1702 break;
1704 case SMB2_OP_GETINFO:
1705 if (!NT_STATUS_IS_OK(session_status)) {
1706 return_value = smbd_smb2_request_error(req, session_status);
1707 break;
1710 * This call needs to be run as user.
1712 * smbd_smb2_request_check_tcon()
1713 * calls change_to_user() on success.
1715 status = smbd_smb2_request_check_tcon(req);
1716 if (!NT_STATUS_IS_OK(status)) {
1717 return_value = smbd_smb2_request_error(req, status);
1718 break;
1722 START_PROFILE(smb2_getinfo);
1723 return_value = smbd_smb2_request_process_getinfo(req);
1724 END_PROFILE(smb2_getinfo);
1726 break;
1728 case SMB2_OP_SETINFO:
1729 if (!NT_STATUS_IS_OK(session_status)) {
1730 return_value = smbd_smb2_request_error(req, session_status);
1731 break;
1734 * This call needs to be run as user.
1736 * smbd_smb2_request_check_tcon()
1737 * calls change_to_user() on success.
1739 status = smbd_smb2_request_check_tcon(req);
1740 if (!NT_STATUS_IS_OK(status)) {
1741 return_value = smbd_smb2_request_error(req, status);
1742 break;
1746 START_PROFILE(smb2_setinfo);
1747 return_value = smbd_smb2_request_process_setinfo(req);
1748 END_PROFILE(smb2_setinfo);
1750 break;
1752 case SMB2_OP_BREAK:
1753 if (!NT_STATUS_IS_OK(session_status)) {
1754 return_value = smbd_smb2_request_error(req, session_status);
1755 break;
1758 * This call needs to be run as user.
1760 * smbd_smb2_request_check_tcon()
1761 * calls change_to_user() on success.
1763 status = smbd_smb2_request_check_tcon(req);
1764 if (!NT_STATUS_IS_OK(status)) {
1765 return_value = smbd_smb2_request_error(req, status);
1766 break;
1770 START_PROFILE(smb2_break);
1771 return_value = smbd_smb2_request_process_break(req);
1772 END_PROFILE(smb2_break);
1774 break;
1776 default:
1777 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1778 break;
1780 return return_value;
1783 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1785 struct tevent_req *subreq;
1786 int i = req->current_idx;
1788 req->subreq = NULL;
1790 req->current_idx += 3;
1792 if (req->current_idx < req->out.vector_count) {
1794 * We must process the remaining compound
1795 * SMB2 requests before any new incoming SMB2
1796 * requests. This is because incoming SMB2
1797 * requests may include a cancel for a
1798 * compound request we haven't processed
1799 * yet.
1801 struct tevent_immediate *im = tevent_create_immediate(req);
1802 if (!im) {
1803 return NT_STATUS_NO_MEMORY;
1806 if (req->do_signing) {
1808 * We sign each reply as we go along.
1809 * We can do this as smb2_calculate_credits()
1810 * grants zero credits on every part of a
1811 * compound reply except the last one,
1812 * which is signed just before calling
1813 * tstream_writev_queue_send().
1815 NTSTATUS status;
1816 status = smb2_signing_sign_pdu(req->session->session_key,
1817 &req->out.vector[i], 3);
1818 if (!NT_STATUS_IS_OK(status)) {
1819 TALLOC_FREE(im);
1820 return status;
1824 tevent_schedule_immediate(im,
1825 req->sconn->smb2.event_ctx,
1826 smbd_smb2_request_dispatch_immediate,
1827 req);
1828 return NT_STATUS_OK;
1831 if (req->compound_related) {
1832 req->compound_related = false;
1833 req->sconn->smb2.compound_related_in_progress = false;
1836 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1838 /* Set credit for these operations (zero credits if this
1839 is a final reply for an async operation). */
1840 smb2_calculate_credits(req, req);
1842 if (req->do_signing) {
1843 NTSTATUS status;
1844 status = smb2_signing_sign_pdu(req->session->session_key,
1845 &req->out.vector[i], 3);
1846 if (!NT_STATUS_IS_OK(status)) {
1847 return status;
1851 if (DEBUGLEVEL >= 10) {
1852 dbgtext("smbd_smb2_request_reply: sending...\n");
1853 print_req_vectors(req);
1856 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1857 if (req->out.vector_count == 4 &&
1858 req->out.vector[3].iov_base == NULL &&
1859 req->out.vector[3].iov_len != 0) {
1860 /* Dynamic part is NULL. Chop it off,
1861 We're going to send it via sendfile. */
1862 req->out.vector_count -= 1;
1865 subreq = tstream_writev_queue_send(req,
1866 req->sconn->smb2.event_ctx,
1867 req->sconn->smb2.stream,
1868 req->sconn->smb2.send_queue,
1869 req->out.vector,
1870 req->out.vector_count);
1871 if (subreq == NULL) {
1872 return NT_STATUS_NO_MEMORY;
1874 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1876 * We're done with this request -
1877 * move it off the "being processed" queue.
1879 DLIST_REMOVE(req->sconn->smb2.requests, req);
1881 return NT_STATUS_OK;
1884 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
1886 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1887 struct tevent_immediate *im,
1888 void *private_data)
1890 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1891 struct smbd_smb2_request);
1892 struct smbd_server_connection *sconn = req->sconn;
1893 NTSTATUS status;
1895 TALLOC_FREE(im);
1897 if (DEBUGLEVEL >= 10) {
1898 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1899 req->current_idx, req->in.vector_count));
1900 print_req_vectors(req);
1903 status = smbd_smb2_request_dispatch(req);
1904 if (!NT_STATUS_IS_OK(status)) {
1905 smbd_server_connection_terminate(sconn, nt_errstr(status));
1906 return;
1909 status = smbd_smb2_request_next_incoming(sconn);
1910 if (!NT_STATUS_IS_OK(status)) {
1911 smbd_server_connection_terminate(sconn, nt_errstr(status));
1912 return;
1916 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1918 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1919 struct smbd_smb2_request);
1920 struct smbd_server_connection *sconn = req->sconn;
1921 int ret;
1922 int sys_errno;
1923 NTSTATUS status;
1925 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1926 TALLOC_FREE(subreq);
1927 TALLOC_FREE(req);
1928 if (ret == -1) {
1929 status = map_nt_error_from_unix(sys_errno);
1930 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1931 nt_errstr(status)));
1932 smbd_server_connection_terminate(sconn, nt_errstr(status));
1933 return;
1936 status = smbd_smb2_request_next_incoming(sconn);
1937 if (!NT_STATUS_IS_OK(status)) {
1938 smbd_server_connection_terminate(sconn, nt_errstr(status));
1939 return;
1943 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1944 NTSTATUS status,
1945 DATA_BLOB body, DATA_BLOB *dyn,
1946 const char *location)
1948 uint8_t *outhdr;
1949 int i = req->current_idx;
1950 uint32_t next_command_ofs;
1952 DEBUG(10,("smbd_smb2_request_done_ex: "
1953 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1954 i, nt_errstr(status), (unsigned int)body.length,
1955 dyn ? "yes": "no",
1956 (unsigned int)(dyn ? dyn->length : 0),
1957 location));
1959 if (body.length < 2) {
1960 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1963 if ((body.length % 2) != 0) {
1964 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1967 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1969 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1970 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1972 req->out.vector[i+1].iov_base = (void *)body.data;
1973 req->out.vector[i+1].iov_len = body.length;
1975 if (dyn) {
1976 req->out.vector[i+2].iov_base = (void *)dyn->data;
1977 req->out.vector[i+2].iov_len = dyn->length;
1978 } else {
1979 req->out.vector[i+2].iov_base = NULL;
1980 req->out.vector[i+2].iov_len = 0;
1983 /* see if we need to recalculate the offset to the next response */
1984 if (next_command_ofs > 0) {
1985 next_command_ofs = SMB2_HDR_BODY;
1986 next_command_ofs += req->out.vector[i+1].iov_len;
1987 next_command_ofs += req->out.vector[i+2].iov_len;
1990 if ((next_command_ofs % 8) != 0) {
1991 size_t pad_size = 8 - (next_command_ofs % 8);
1992 if (req->out.vector[i+2].iov_len == 0) {
1994 * if the dyn buffer is empty
1995 * we can use it to add padding
1997 uint8_t *pad;
1999 pad = talloc_zero_array(req->out.vector,
2000 uint8_t, pad_size);
2001 if (pad == NULL) {
2002 return smbd_smb2_request_error(req,
2003 NT_STATUS_NO_MEMORY);
2006 req->out.vector[i+2].iov_base = (void *)pad;
2007 req->out.vector[i+2].iov_len = pad_size;
2008 } else {
2010 * For now we copy the dynamic buffer
2011 * and add the padding to the new buffer
2013 size_t old_size;
2014 uint8_t *old_dyn;
2015 size_t new_size;
2016 uint8_t *new_dyn;
2018 old_size = req->out.vector[i+2].iov_len;
2019 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2021 new_size = old_size + pad_size;
2022 new_dyn = talloc_zero_array(req->out.vector,
2023 uint8_t, new_size);
2024 if (new_dyn == NULL) {
2025 return smbd_smb2_request_error(req,
2026 NT_STATUS_NO_MEMORY);
2029 memcpy(new_dyn, old_dyn, old_size);
2030 memset(new_dyn + old_size, 0, pad_size);
2032 req->out.vector[i+2].iov_base = (void *)new_dyn;
2033 req->out.vector[i+2].iov_len = new_size;
2035 next_command_ofs += pad_size;
2038 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2040 return smbd_smb2_request_reply(req);
2043 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2044 NTSTATUS status,
2045 DATA_BLOB *info,
2046 const char *location)
2048 DATA_BLOB body;
2049 int i = req->current_idx;
2050 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
2052 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2053 i, nt_errstr(status), info ? " +info" : "",
2054 location));
2056 body.data = outhdr + SMB2_HDR_BODY;
2057 body.length = 8;
2058 SSVAL(body.data, 0, 9);
2060 if (info) {
2061 SIVAL(body.data, 0x04, info->length);
2062 } else {
2063 /* Allocated size of req->out.vector[i].iov_base
2064 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2065 * 1 byte without having to do an alloc.
2067 info = talloc_zero_array(req->out.vector,
2068 DATA_BLOB,
2070 if (!info) {
2071 return NT_STATUS_NO_MEMORY;
2073 info->data = ((uint8_t *)outhdr) +
2074 OUTVEC_ALLOC_SIZE - 1;
2075 info->length = 1;
2076 SCVAL(info->data, 0, 0);
2080 * Note: Even if there is an error, continue to process the request.
2081 * per MS-SMB2.
2084 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2088 struct smbd_smb2_send_oplock_break_state {
2089 struct smbd_server_connection *sconn;
2090 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2091 struct iovec vector;
2094 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2096 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2097 uint64_t file_id_persistent,
2098 uint64_t file_id_volatile,
2099 uint8_t oplock_level)
2101 struct smbd_smb2_send_oplock_break_state *state;
2102 struct tevent_req *subreq;
2103 uint8_t *hdr;
2104 uint8_t *body;
2106 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2107 if (state == NULL) {
2108 return NT_STATUS_NO_MEMORY;
2110 state->sconn = sconn;
2112 state->vector.iov_base = (void *)state->buf;
2113 state->vector.iov_len = sizeof(state->buf);
2115 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2116 hdr = state->buf + 4;
2117 body = hdr + SMB2_HDR_BODY;
2119 SIVAL(hdr, 0, SMB2_MAGIC);
2120 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2121 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2122 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2123 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2124 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2125 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2126 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2127 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2128 SIVAL(hdr, SMB2_HDR_PID, 0);
2129 SIVAL(hdr, SMB2_HDR_TID, 0);
2130 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2131 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2133 SSVAL(body, 0x00, 0x18);
2135 SCVAL(body, 0x02, oplock_level);
2136 SCVAL(body, 0x03, 0); /* reserved */
2137 SIVAL(body, 0x04, 0); /* reserved */
2138 SBVAL(body, 0x08, file_id_persistent);
2139 SBVAL(body, 0x10, file_id_volatile);
2141 subreq = tstream_writev_queue_send(state,
2142 sconn->smb2.event_ctx,
2143 sconn->smb2.stream,
2144 sconn->smb2.send_queue,
2145 &state->vector, 1);
2146 if (subreq == NULL) {
2147 return NT_STATUS_NO_MEMORY;
2149 tevent_req_set_callback(subreq,
2150 smbd_smb2_oplock_break_writev_done,
2151 state);
2153 return NT_STATUS_OK;
2156 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2158 struct smbd_smb2_send_oplock_break_state *state =
2159 tevent_req_callback_data(subreq,
2160 struct smbd_smb2_send_oplock_break_state);
2161 struct smbd_server_connection *sconn = state->sconn;
2162 int ret;
2163 int sys_errno;
2165 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2166 TALLOC_FREE(subreq);
2167 if (ret == -1) {
2168 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2169 smbd_server_connection_terminate(sconn, nt_errstr(status));
2170 return;
2173 TALLOC_FREE(state);
2176 struct smbd_smb2_request_read_state {
2177 size_t missing;
2178 bool asked_for_header;
2179 struct smbd_smb2_request *smb2_req;
2182 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2183 void *private_data,
2184 TALLOC_CTX *mem_ctx,
2185 struct iovec **_vector,
2186 size_t *_count);
2187 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2189 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2190 struct tevent_context *ev,
2191 struct smbd_server_connection *sconn)
2193 struct tevent_req *req;
2194 struct smbd_smb2_request_read_state *state;
2195 struct tevent_req *subreq;
2197 req = tevent_req_create(mem_ctx, &state,
2198 struct smbd_smb2_request_read_state);
2199 if (req == NULL) {
2200 return NULL;
2202 state->missing = 0;
2203 state->asked_for_header = false;
2205 state->smb2_req = smbd_smb2_request_allocate(state);
2206 if (tevent_req_nomem(state->smb2_req, req)) {
2207 return tevent_req_post(req, ev);
2209 state->smb2_req->sconn = sconn;
2211 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2212 sconn->smb2.recv_queue,
2213 smbd_smb2_request_next_vector,
2214 state);
2215 if (tevent_req_nomem(subreq, req)) {
2216 return tevent_req_post(req, ev);
2218 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2220 return req;
2223 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2224 void *private_data,
2225 TALLOC_CTX *mem_ctx,
2226 struct iovec **_vector,
2227 size_t *_count)
2229 struct smbd_smb2_request_read_state *state =
2230 talloc_get_type_abort(private_data,
2231 struct smbd_smb2_request_read_state);
2232 struct smbd_smb2_request *req = state->smb2_req;
2233 struct iovec *vector;
2234 int idx = req->in.vector_count;
2235 size_t len = 0;
2236 uint8_t *buf = NULL;
2238 if (req->in.vector_count == 0) {
2240 * first we need to get the NBT header
2242 req->in.vector = talloc_array(req, struct iovec,
2243 req->in.vector_count + 1);
2244 if (req->in.vector == NULL) {
2245 return -1;
2247 req->in.vector_count += 1;
2249 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2250 req->in.vector[idx].iov_len = 4;
2252 vector = talloc_array(mem_ctx, struct iovec, 1);
2253 if (vector == NULL) {
2254 return -1;
2257 vector[0] = req->in.vector[idx];
2259 *_vector = vector;
2260 *_count = 1;
2261 return 0;
2264 if (req->in.vector_count == 1) {
2266 * Now we analyze the NBT header
2268 state->missing = smb2_len(req->in.vector[0].iov_base);
2270 if (state->missing == 0) {
2271 /* if there're no remaining bytes, we're done */
2272 *_vector = NULL;
2273 *_count = 0;
2274 return 0;
2277 req->in.vector = talloc_realloc(req, req->in.vector,
2278 struct iovec,
2279 req->in.vector_count + 1);
2280 if (req->in.vector == NULL) {
2281 return -1;
2283 req->in.vector_count += 1;
2285 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2287 * it's a special NBT message,
2288 * so get all remaining bytes
2290 len = state->missing;
2291 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2293 * it's an invalid message, just read what we can get
2294 * and let the caller handle the error
2296 len = state->missing;
2297 } else {
2299 * We assume it's a SMB2 request,
2300 * and we first get the header and the
2301 * first 2 bytes (the struct size) of the body
2303 len = SMB2_HDR_BODY + 2;
2305 state->asked_for_header = true;
2308 state->missing -= len;
2310 buf = talloc_array(req->in.vector, uint8_t, len);
2311 if (buf == NULL) {
2312 return -1;
2315 req->in.vector[idx].iov_base = (void *)buf;
2316 req->in.vector[idx].iov_len = len;
2318 vector = talloc_array(mem_ctx, struct iovec, 1);
2319 if (vector == NULL) {
2320 return -1;
2323 vector[0] = req->in.vector[idx];
2325 *_vector = vector;
2326 *_count = 1;
2327 return 0;
2330 if (state->missing == 0) {
2331 /* if there're no remaining bytes, we're done */
2332 *_vector = NULL;
2333 *_count = 0;
2334 return 0;
2337 if (state->asked_for_header) {
2338 const uint8_t *hdr;
2339 size_t full_size;
2340 size_t next_command_ofs;
2341 size_t body_size;
2342 uint8_t *body;
2343 size_t dyn_size;
2344 uint8_t *dyn;
2345 bool invalid = false;
2347 state->asked_for_header = false;
2350 * We got the SMB2 header and the first 2 bytes
2351 * of the body. We fix the size to just the header
2352 * and manually copy the 2 first bytes to the body section
2354 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2355 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2357 /* allocate vectors for body and dynamic areas */
2358 req->in.vector = talloc_realloc(req, req->in.vector,
2359 struct iovec,
2360 req->in.vector_count + 2);
2361 if (req->in.vector == NULL) {
2362 return -1;
2364 req->in.vector_count += 2;
2366 full_size = state->missing + SMB2_HDR_BODY + 2;
2367 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2368 body_size = SVAL(hdr, SMB2_HDR_BODY);
2370 if (next_command_ofs != 0) {
2371 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2373 * this is invalid, just return a zero
2374 * body and let the caller deal with the error
2376 invalid = true;
2377 } else if (next_command_ofs > full_size) {
2379 * this is invalid, just return a zero
2380 * body and let the caller deal with the error
2382 invalid = true;
2383 } else {
2384 full_size = next_command_ofs;
2388 if (!invalid) {
2389 if (body_size < 2) {
2391 * this is invalid, just return a zero
2392 * body and let the caller deal with the error
2394 invalid = true;
2397 if ((body_size % 2) != 0) {
2398 body_size -= 1;
2401 if (body_size > (full_size - SMB2_HDR_BODY)) {
2403 * this is invalid, just return a zero
2404 * body and let the caller deal with the error
2406 invalid = true;
2410 if (invalid) {
2411 /* the caller should check this */
2412 body_size = 2;
2415 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2417 state->missing -= (body_size - 2) + dyn_size;
2419 body = talloc_array(req->in.vector, uint8_t, body_size);
2420 if (body == NULL) {
2421 return -1;
2424 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2425 if (dyn == NULL) {
2426 return -1;
2429 req->in.vector[idx].iov_base = (void *)body;
2430 req->in.vector[idx].iov_len = body_size;
2431 req->in.vector[idx+1].iov_base = (void *)dyn;
2432 req->in.vector[idx+1].iov_len = dyn_size;
2434 vector = talloc_array(mem_ctx, struct iovec, 2);
2435 if (vector == NULL) {
2436 return -1;
2440 * the first 2 bytes of the body were already fetched
2441 * together with the header
2443 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2444 vector[0].iov_base = body + 2;
2445 vector[0].iov_len = body_size - 2;
2447 vector[1] = req->in.vector[idx+1];
2449 *_vector = vector;
2450 *_count = 2;
2451 return 0;
2455 * when we endup here, we're looking for a new SMB2 request
2456 * next. And we ask for its header and the first 2 bytes of
2457 * the body (like we did for the first SMB2 request).
2460 req->in.vector = talloc_realloc(req, req->in.vector,
2461 struct iovec,
2462 req->in.vector_count + 1);
2463 if (req->in.vector == NULL) {
2464 return -1;
2466 req->in.vector_count += 1;
2469 * We assume it's a SMB2 request,
2470 * and we first get the header and the
2471 * first 2 bytes (the struct size) of the body
2473 len = SMB2_HDR_BODY + 2;
2475 if (len > state->missing) {
2476 /* let the caller handle the error */
2477 len = state->missing;
2480 state->missing -= len;
2481 state->asked_for_header = true;
2483 buf = talloc_array(req->in.vector, uint8_t, len);
2484 if (buf == NULL) {
2485 return -1;
2488 req->in.vector[idx].iov_base = (void *)buf;
2489 req->in.vector[idx].iov_len = len;
2491 vector = talloc_array(mem_ctx, struct iovec, 1);
2492 if (vector == NULL) {
2493 return -1;
2496 vector[0] = req->in.vector[idx];
2498 *_vector = vector;
2499 *_count = 1;
2500 return 0;
2503 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2505 struct tevent_req *req =
2506 tevent_req_callback_data(subreq,
2507 struct tevent_req);
2508 int ret;
2509 int sys_errno;
2510 NTSTATUS status;
2512 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2513 if (ret == -1) {
2514 status = map_nt_error_from_unix(sys_errno);
2515 tevent_req_nterror(req, status);
2516 return;
2519 tevent_req_done(req);
2522 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2523 TALLOC_CTX *mem_ctx,
2524 struct smbd_smb2_request **_smb2_req)
2526 struct smbd_smb2_request_read_state *state =
2527 tevent_req_data(req,
2528 struct smbd_smb2_request_read_state);
2529 NTSTATUS status;
2531 if (tevent_req_is_nterror(req, &status)) {
2532 tevent_req_received(req);
2533 return status;
2536 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2537 *_smb2_req = state->smb2_req;
2538 tevent_req_received(req);
2539 return NT_STATUS_OK;
2542 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2544 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2546 size_t max_send_queue_len;
2547 size_t cur_send_queue_len;
2548 struct tevent_req *subreq;
2550 if (sconn->smb2.compound_related_in_progress) {
2552 * Can't read another until the related
2553 * compound is done.
2555 return NT_STATUS_OK;
2558 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2560 * if there is already a smbd_smb2_request_read
2561 * pending, we are done.
2563 return NT_STATUS_OK;
2566 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2567 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2569 if (cur_send_queue_len > max_send_queue_len) {
2571 * if we have a lot of requests to send,
2572 * we wait until they are on the wire until we
2573 * ask for the next request.
2575 return NT_STATUS_OK;
2578 /* ask for the next request */
2579 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2580 if (subreq == NULL) {
2581 return NT_STATUS_NO_MEMORY;
2583 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2585 return NT_STATUS_OK;
2588 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2589 const uint8_t *inbuf, size_t size)
2591 NTSTATUS status;
2592 struct smbd_smb2_request *req = NULL;
2594 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2595 (unsigned int)size));
2597 status = smbd_initialize_smb2(sconn);
2598 if (!NT_STATUS_IS_OK(status)) {
2599 smbd_server_connection_terminate(sconn, nt_errstr(status));
2600 return;
2603 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2604 if (!NT_STATUS_IS_OK(status)) {
2605 smbd_server_connection_terminate(sconn, nt_errstr(status));
2606 return;
2609 status = smbd_smb2_request_validate(req);
2610 if (!NT_STATUS_IS_OK(status)) {
2611 smbd_server_connection_terminate(sconn, nt_errstr(status));
2612 return;
2615 status = smbd_smb2_request_setup_out(req);
2616 if (!NT_STATUS_IS_OK(status)) {
2617 smbd_server_connection_terminate(sconn, nt_errstr(status));
2618 return;
2621 status = smbd_smb2_request_dispatch(req);
2622 if (!NT_STATUS_IS_OK(status)) {
2623 smbd_server_connection_terminate(sconn, nt_errstr(status));
2624 return;
2627 status = smbd_smb2_request_next_incoming(sconn);
2628 if (!NT_STATUS_IS_OK(status)) {
2629 smbd_server_connection_terminate(sconn, nt_errstr(status));
2630 return;
2633 sconn->num_requests++;
2636 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2638 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2639 struct smbd_server_connection);
2640 NTSTATUS status;
2641 struct smbd_smb2_request *req = NULL;
2643 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2644 TALLOC_FREE(subreq);
2645 if (!NT_STATUS_IS_OK(status)) {
2646 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2647 nt_errstr(status)));
2648 smbd_server_connection_terminate(sconn, nt_errstr(status));
2649 return;
2652 if (req->in.nbt_hdr[0] != 0x00) {
2653 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2654 req->in.nbt_hdr[0]));
2655 TALLOC_FREE(req);
2656 goto next;
2659 req->current_idx = 1;
2661 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2662 req->current_idx, req->in.vector_count));
2664 status = smbd_smb2_request_validate(req);
2665 if (!NT_STATUS_IS_OK(status)) {
2666 smbd_server_connection_terminate(sconn, nt_errstr(status));
2667 return;
2670 status = smbd_smb2_request_setup_out(req);
2671 if (!NT_STATUS_IS_OK(status)) {
2672 smbd_server_connection_terminate(sconn, nt_errstr(status));
2673 return;
2676 status = smbd_smb2_request_dispatch(req);
2677 if (!NT_STATUS_IS_OK(status)) {
2678 smbd_server_connection_terminate(sconn, nt_errstr(status));
2679 return;
2682 next:
2683 status = smbd_smb2_request_next_incoming(sconn);
2684 if (!NT_STATUS_IS_OK(status)) {
2685 smbd_server_connection_terminate(sconn, nt_errstr(status));
2686 return;
2689 sconn->num_requests++;
2691 /* The timeout_processing function isn't run nearly
2692 often enough to implement 'max log size' without
2693 overrunning the size of the file by many megabytes.
2694 This is especially true if we are running at debug
2695 level 10. Checking every 50 SMB2s is a nice
2696 tradeoff of performance vs log file size overrun. */
2698 if ((sconn->num_requests % 50) == 0 &&
2699 need_to_check_log_size()) {
2700 change_to_root_user();
2701 check_log_size();