smbd: Fix error return for STREAM_INFO
[Samba.git] / source3 / smbd / smb2_server.c
blob96159074d0aa3ccfafd1c051c2cebacd5af0c67c
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;
931 if (!tevent_req_is_in_progress(subreq)) {
932 return NT_STATUS_OK;
935 req->subreq = subreq;
936 subreq = NULL;
938 if (req->async) {
939 /* We're already async. */
940 return NT_STATUS_OK;
943 if (req->in.vector_count > i + 3) {
945 * We're trying to go async in a compound
946 * request chain.
947 * This is only allowed for opens that
948 * cause an oplock break, otherwise it
949 * is not allowed. See [MS-SMB2].pdf
950 * note <194> on Section 3.3.5.2.7.
952 const uint8_t *inhdr =
953 (const uint8_t *)req->in.vector[i].iov_base;
955 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
957 * Cancel the outstanding request.
959 bool ok = tevent_req_cancel(req->subreq);
960 if (ok) {
961 return NT_STATUS_OK;
963 TALLOC_FREE(req->subreq);
964 return smbd_smb2_request_error(req,
965 NT_STATUS_INTERNAL_ERROR);
969 if (DEBUGLEVEL >= 10) {
970 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
971 (unsigned int)req->current_idx );
972 print_req_vectors(req);
975 if (i > 1) {
977 * We're going async in a compound
978 * chain after the first request has
979 * already been processed. Send an
980 * interim response containing the
981 * set of replies already generated.
983 status = smb2_send_async_interim_response(req);
984 if (!NT_STATUS_IS_OK(status)) {
985 return status;
988 req->current_idx = 1;
991 * Re-arrange the in.vectors to remove what
992 * we just sent.
994 memmove(&req->in.vector[1],
995 &req->in.vector[i],
996 sizeof(req->in.vector[0])*(req->in.vector_count - i));
997 req->in.vector_count = 1 + (req->in.vector_count - i);
999 smb2_setup_nbt_length(req->in.vector, req->in.vector_count);
1001 /* Re-arrange the out.vectors to match. */
1002 memmove(&req->out.vector[1],
1003 &req->out.vector[i],
1004 sizeof(req->out.vector[0])*(req->out.vector_count - i));
1005 req->out.vector_count = 1 + (req->out.vector_count - i);
1007 if (req->in.vector_count == 4) {
1008 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
1010 * We only have one remaining request as
1011 * we've processed everything else.
1012 * This is no longer a compound request.
1014 req->compound_related = false;
1015 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1016 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1020 /* Don't return an intermediate packet on a pipe read/write. */
1021 if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
1022 goto out;
1025 reqhdr = (uint8_t *)req->out.vector[i].iov_base;
1026 flags = (IVAL(reqhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1027 message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
1028 async_id = message_id; /* keep it simple for now... */
1031 * What we send is identical to a smbd_smb2_request_error
1032 * packet with an error status of STATUS_PENDING. Make use
1033 * of this fact sometime when refactoring. JRA.
1036 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1037 if (state == NULL) {
1038 return NT_STATUS_NO_MEMORY;
1040 state->sconn = req->sconn;
1042 state->vector[0].iov_base = (void *)state->buf;
1043 state->vector[0].iov_len = 4;
1045 state->vector[1].iov_base = state->buf + 4;
1046 state->vector[1].iov_len = SMB2_HDR_BODY;
1048 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
1049 state->vector[2].iov_len = 9;
1051 smb2_setup_nbt_length(state->vector, 3);
1053 hdr = (uint8_t *)state->vector[1].iov_base;
1054 body = (uint8_t *)state->vector[2].iov_base;
1056 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1057 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1058 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1059 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1060 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(reqhdr, SMB2_HDR_OPCODE));
1062 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1063 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1064 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1065 SBVAL(hdr, SMB2_HDR_PID, async_id);
1066 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1067 BVAL(reqhdr, SMB2_HDR_SESSION_ID));
1068 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
1070 SSVAL(body, 0x00, 0x08 + 1);
1072 SCVAL(body, 0x02, 0);
1073 SCVAL(body, 0x03, 0);
1074 SIVAL(body, 0x04, 0);
1075 /* Match W2K8R2... */
1076 SCVAL(body, 0x08, 0x21);
1078 /* Ensure we correctly go through crediting. Grant
1079 the credits now, and zero credits on the final
1080 response. */
1081 smb2_set_operation_credit(req->sconn,
1082 &req->in.vector[i],
1083 &state->vector[1]);
1085 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1087 if (req->do_signing) {
1088 status = smb2_signing_sign_pdu(req->session->session_key,
1089 &state->vector[1], 2);
1090 if (!NT_STATUS_IS_OK(status)) {
1091 return status;
1095 subreq = tstream_writev_queue_send(state,
1096 req->sconn->smb2.event_ctx,
1097 req->sconn->smb2.stream,
1098 req->sconn->smb2.send_queue,
1099 state->vector,
1102 if (subreq == NULL) {
1103 return NT_STATUS_NO_MEMORY;
1106 tevent_req_set_callback(subreq,
1107 smbd_smb2_request_pending_writev_done,
1108 state);
1110 /* Note we're going async with this request. */
1111 req->async = true;
1113 out:
1115 smb2_setup_nbt_length(req->out.vector,
1116 req->out.vector_count);
1118 if (req->async) {
1119 /* Ensure our final reply matches the interim one. */
1120 reqhdr = (uint8_t *)req->out.vector[1].iov_base;
1121 SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1122 SBVAL(reqhdr, SMB2_HDR_PID, async_id);
1125 const uint8_t *inhdr =
1126 (const uint8_t *)req->in.vector[1].iov_base;
1127 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1128 "going async\n",
1129 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1130 (unsigned long long)async_id ));
1134 return NT_STATUS_OK;
1137 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1139 struct smbd_server_connection *sconn = req->sconn;
1140 struct smbd_smb2_request *cur;
1141 const uint8_t *inhdr;
1142 int i = req->current_idx;
1143 uint32_t flags;
1144 uint64_t search_message_id;
1145 uint64_t search_async_id;
1146 uint64_t found_id;
1148 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1150 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1151 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1152 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1155 * we don't need the request anymore
1156 * cancel requests never have a response
1158 DLIST_REMOVE(req->sconn->smb2.requests, req);
1159 TALLOC_FREE(req);
1161 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1162 const uint8_t *outhdr;
1163 uint64_t message_id;
1164 uint64_t async_id;
1166 if (cur->compound_related) {
1168 * Never cancel anything in a compound request.
1169 * Way too hard to deal with the result.
1171 continue;
1174 i = cur->current_idx;
1176 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1178 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1179 async_id = BVAL(outhdr, SMB2_HDR_PID);
1181 if (flags & SMB2_HDR_FLAG_ASYNC) {
1182 if (search_async_id == async_id) {
1183 found_id = async_id;
1184 break;
1186 } else {
1187 if (search_message_id == message_id) {
1188 found_id = message_id;
1189 break;
1194 if (cur && cur->subreq) {
1195 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1196 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1197 "cancel opcode[%s] mid %llu\n",
1198 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1199 (unsigned long long)found_id ));
1200 tevent_req_cancel(cur->subreq);
1203 return NT_STATUS_OK;
1206 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1207 size_t expected_body_size)
1209 const uint8_t *inhdr;
1210 uint16_t opcode;
1211 const uint8_t *inbody;
1212 int i = req->current_idx;
1213 size_t body_size;
1214 size_t min_dyn_size = expected_body_size & 0x00000001;
1217 * The following should be checked already.
1219 if ((i+2) > req->in.vector_count) {
1220 return NT_STATUS_INTERNAL_ERROR;
1222 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1223 return NT_STATUS_INTERNAL_ERROR;
1225 if (req->in.vector[i+1].iov_len < 2) {
1226 return NT_STATUS_INTERNAL_ERROR;
1229 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1230 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1232 switch (opcode) {
1233 case SMB2_OP_IOCTL:
1234 case SMB2_OP_GETINFO:
1235 min_dyn_size = 0;
1236 break;
1240 * Now check the expected body size,
1241 * where the last byte might be in the
1242 * dynnamic section..
1244 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1245 return NT_STATUS_INVALID_PARAMETER;
1247 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1248 return NT_STATUS_INVALID_PARAMETER;
1251 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1253 body_size = SVAL(inbody, 0x00);
1254 if (body_size != expected_body_size) {
1255 return NT_STATUS_INVALID_PARAMETER;
1258 return NT_STATUS_OK;
1261 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1263 const uint8_t *inhdr;
1264 int i = req->current_idx;
1265 uint16_t opcode;
1266 uint32_t flags;
1267 uint64_t mid;
1268 NTSTATUS status;
1269 NTSTATUS session_status;
1270 uint32_t allowed_flags;
1271 NTSTATUS return_value;
1273 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1275 /* TODO: verify more things */
1277 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1278 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1279 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1280 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1281 smb2_opcode_name(opcode),
1282 (unsigned long long)mid));
1284 if (get_Protocol() >= PROTOCOL_SMB2) {
1286 * once the protocol is negotiated
1287 * SMB2_OP_NEGPROT is not allowed anymore
1289 if (opcode == SMB2_OP_NEGPROT) {
1290 /* drop the connection */
1291 return NT_STATUS_INVALID_PARAMETER;
1293 } else {
1295 * if the protocol is not negotiated yet
1296 * only SMB2_OP_NEGPROT is allowed.
1298 if (opcode != SMB2_OP_NEGPROT) {
1299 /* drop the connection */
1300 return NT_STATUS_INVALID_PARAMETER;
1304 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1305 SMB2_HDR_FLAG_SIGNED |
1306 SMB2_HDR_FLAG_DFS;
1307 if (opcode == SMB2_OP_CANCEL) {
1308 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1310 if ((flags & ~allowed_flags) != 0) {
1311 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1315 * Check if the client provided a valid session id,
1316 * if so smbd_smb2_request_check_session() calls
1317 * set_current_user_info().
1319 * As some command don't require a valid session id
1320 * we defer the check of the session_status
1322 session_status = smbd_smb2_request_check_session(req);
1324 if (flags & SMB2_HDR_FLAG_CHAINED) {
1326 * This check is mostly for giving the correct error code
1327 * for compounded requests.
1329 if (!NT_STATUS_IS_OK(session_status)) {
1330 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1332 } else {
1333 req->compat_chain_fsp = NULL;
1336 req->do_signing = false;
1337 if (flags & SMB2_HDR_FLAG_SIGNED) {
1338 if (!NT_STATUS_IS_OK(session_status)) {
1339 return smbd_smb2_request_error(req, session_status);
1342 req->do_signing = true;
1343 status = smb2_signing_check_pdu(req->session->session_key,
1344 &req->in.vector[i], 3);
1345 if (!NT_STATUS_IS_OK(status)) {
1346 return smbd_smb2_request_error(req, status);
1348 } else if (opcode == SMB2_OP_CANCEL) {
1349 /* Cancel requests are allowed to skip the signing */
1350 } else if (req->session && req->session->do_signing) {
1351 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1354 if (flags & SMB2_HDR_FLAG_CHAINED) {
1355 req->compound_related = true;
1358 switch (opcode) {
1359 case SMB2_OP_NEGPROT:
1360 /* This call needs to be run as root */
1361 change_to_root_user();
1364 START_PROFILE(smb2_negprot);
1365 return_value = smbd_smb2_request_process_negprot(req);
1366 END_PROFILE(smb2_negprot);
1368 break;
1370 case SMB2_OP_SESSSETUP:
1371 /* This call needs to be run as root */
1372 change_to_root_user();
1375 START_PROFILE(smb2_sesssetup);
1376 return_value = smbd_smb2_request_process_sesssetup(req);
1377 END_PROFILE(smb2_sesssetup);
1379 break;
1381 case SMB2_OP_LOGOFF:
1382 if (!NT_STATUS_IS_OK(session_status)) {
1383 return_value = smbd_smb2_request_error(req, session_status);
1384 break;
1387 /* This call needs to be run as root */
1388 change_to_root_user();
1391 START_PROFILE(smb2_logoff);
1392 return_value = smbd_smb2_request_process_logoff(req);
1393 END_PROFILE(smb2_logoff);
1395 break;
1397 case SMB2_OP_TCON:
1398 if (!NT_STATUS_IS_OK(session_status)) {
1399 return_value = smbd_smb2_request_error(req, session_status);
1400 break;
1404 * This call needs to be run as root.
1406 * smbd_smb2_request_process_tcon()
1407 * calls make_connection_snum(), which will call
1408 * change_to_user(), when needed.
1410 change_to_root_user();
1413 START_PROFILE(smb2_tcon);
1414 return_value = smbd_smb2_request_process_tcon(req);
1415 END_PROFILE(smb2_tcon);
1417 break;
1419 case SMB2_OP_TDIS:
1420 if (!NT_STATUS_IS_OK(session_status)) {
1421 return_value = smbd_smb2_request_error(req, session_status);
1422 break;
1425 * This call needs to be run as user.
1427 * smbd_smb2_request_check_tcon()
1428 * calls change_to_user() on success.
1430 status = smbd_smb2_request_check_tcon(req);
1431 if (!NT_STATUS_IS_OK(status)) {
1432 return_value = smbd_smb2_request_error(req, status);
1433 break;
1435 /* This call needs to be run as root */
1436 change_to_root_user();
1440 START_PROFILE(smb2_tdis);
1441 return_value = smbd_smb2_request_process_tdis(req);
1442 END_PROFILE(smb2_tdis);
1444 break;
1446 case SMB2_OP_CREATE:
1447 if (!NT_STATUS_IS_OK(session_status)) {
1448 return_value = smbd_smb2_request_error(req, session_status);
1449 break;
1452 * This call needs to be run as user.
1454 * smbd_smb2_request_check_tcon()
1455 * calls change_to_user() on success.
1457 status = smbd_smb2_request_check_tcon(req);
1458 if (!NT_STATUS_IS_OK(status)) {
1459 return_value = smbd_smb2_request_error(req, status);
1460 break;
1464 START_PROFILE(smb2_create);
1465 return_value = smbd_smb2_request_process_create(req);
1466 END_PROFILE(smb2_create);
1468 break;
1470 case SMB2_OP_CLOSE:
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;
1488 START_PROFILE(smb2_close);
1489 return_value = smbd_smb2_request_process_close(req);
1490 END_PROFILE(smb2_close);
1492 break;
1494 case SMB2_OP_FLUSH:
1495 if (!NT_STATUS_IS_OK(session_status)) {
1496 return_value = smbd_smb2_request_error(req, session_status);
1497 break;
1500 * This call needs to be run as user.
1502 * smbd_smb2_request_check_tcon()
1503 * calls change_to_user() on success.
1505 status = smbd_smb2_request_check_tcon(req);
1506 if (!NT_STATUS_IS_OK(status)) {
1507 return_value = smbd_smb2_request_error(req, status);
1508 break;
1512 START_PROFILE(smb2_flush);
1513 return_value = smbd_smb2_request_process_flush(req);
1514 END_PROFILE(smb2_flush);
1516 break;
1518 case SMB2_OP_READ:
1519 if (!NT_STATUS_IS_OK(session_status)) {
1520 return_value = smbd_smb2_request_error(req, session_status);
1521 break;
1524 * This call needs to be run as user.
1526 * smbd_smb2_request_check_tcon()
1527 * calls change_to_user() on success.
1529 status = smbd_smb2_request_check_tcon(req);
1530 if (!NT_STATUS_IS_OK(status)) {
1531 return_value = smbd_smb2_request_error(req, status);
1532 break;
1536 START_PROFILE(smb2_read);
1537 return_value = smbd_smb2_request_process_read(req);
1538 END_PROFILE(smb2_read);
1540 break;
1542 case SMB2_OP_WRITE:
1543 if (!NT_STATUS_IS_OK(session_status)) {
1544 return_value = smbd_smb2_request_error(req, session_status);
1545 break;
1548 * This call needs to be run as user.
1550 * smbd_smb2_request_check_tcon()
1551 * calls change_to_user() on success.
1553 status = smbd_smb2_request_check_tcon(req);
1554 if (!NT_STATUS_IS_OK(status)) {
1555 return_value = smbd_smb2_request_error(req, status);
1556 break;
1560 START_PROFILE(smb2_write);
1561 return_value = smbd_smb2_request_process_write(req);
1562 END_PROFILE(smb2_write);
1564 break;
1566 case SMB2_OP_LOCK:
1567 if (!NT_STATUS_IS_OK(session_status)) {
1568 /* Too ugly to live ? JRA. */
1569 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1570 session_status = NT_STATUS_FILE_CLOSED;
1572 return_value = smbd_smb2_request_error(req, session_status);
1573 break;
1576 * This call needs to be run as user.
1578 * smbd_smb2_request_check_tcon()
1579 * calls change_to_user() on success.
1581 status = smbd_smb2_request_check_tcon(req);
1582 if (!NT_STATUS_IS_OK(status)) {
1583 /* Too ugly to live ? JRA. */
1584 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1585 status = NT_STATUS_FILE_CLOSED;
1587 return_value = smbd_smb2_request_error(req, status);
1588 break;
1592 START_PROFILE(smb2_lock);
1593 return_value = smbd_smb2_request_process_lock(req);
1594 END_PROFILE(smb2_lock);
1596 break;
1598 case SMB2_OP_IOCTL:
1599 if (!NT_STATUS_IS_OK(session_status)) {
1600 return_value = smbd_smb2_request_error(req, session_status);
1601 break;
1604 * This call needs to be run as user.
1606 * smbd_smb2_request_check_tcon()
1607 * calls change_to_user() on success.
1609 status = smbd_smb2_request_check_tcon(req);
1610 if (!NT_STATUS_IS_OK(status)) {
1611 return_value = smbd_smb2_request_error(req, status);
1612 break;
1616 START_PROFILE(smb2_ioctl);
1617 return_value = smbd_smb2_request_process_ioctl(req);
1618 END_PROFILE(smb2_ioctl);
1620 break;
1622 case SMB2_OP_CANCEL:
1624 * This call needs to be run as root
1626 * That is what we also do in the SMB1 case.
1628 change_to_root_user();
1631 START_PROFILE(smb2_cancel);
1632 return_value = smbd_smb2_request_process_cancel(req);
1633 END_PROFILE(smb2_cancel);
1635 break;
1637 case SMB2_OP_KEEPALIVE:
1638 /* This call needs to be run as root */
1639 change_to_root_user();
1642 START_PROFILE(smb2_keepalive);
1643 return_value = smbd_smb2_request_process_keepalive(req);
1644 END_PROFILE(smb2_keepalive);
1646 break;
1648 case SMB2_OP_FIND:
1649 if (!NT_STATUS_IS_OK(session_status)) {
1650 return_value = smbd_smb2_request_error(req, session_status);
1651 break;
1654 * This call needs to be run as user.
1656 * smbd_smb2_request_check_tcon()
1657 * calls change_to_user() on success.
1659 status = smbd_smb2_request_check_tcon(req);
1660 if (!NT_STATUS_IS_OK(status)) {
1661 return_value = smbd_smb2_request_error(req, status);
1662 break;
1666 START_PROFILE(smb2_find);
1667 return_value = smbd_smb2_request_process_find(req);
1668 END_PROFILE(smb2_find);
1670 break;
1672 case SMB2_OP_NOTIFY:
1673 if (!NT_STATUS_IS_OK(session_status)) {
1674 return_value = smbd_smb2_request_error(req, session_status);
1675 break;
1678 * This call needs to be run as user.
1680 * smbd_smb2_request_check_tcon()
1681 * calls change_to_user() on success.
1683 status = smbd_smb2_request_check_tcon(req);
1684 if (!NT_STATUS_IS_OK(status)) {
1685 return_value = smbd_smb2_request_error(req, status);
1686 break;
1690 START_PROFILE(smb2_notify);
1691 return_value = smbd_smb2_request_process_notify(req);
1692 END_PROFILE(smb2_notify);
1694 break;
1696 case SMB2_OP_GETINFO:
1697 if (!NT_STATUS_IS_OK(session_status)) {
1698 return_value = smbd_smb2_request_error(req, session_status);
1699 break;
1702 * This call needs to be run as user.
1704 * smbd_smb2_request_check_tcon()
1705 * calls change_to_user() on success.
1707 status = smbd_smb2_request_check_tcon(req);
1708 if (!NT_STATUS_IS_OK(status)) {
1709 return_value = smbd_smb2_request_error(req, status);
1710 break;
1714 START_PROFILE(smb2_getinfo);
1715 return_value = smbd_smb2_request_process_getinfo(req);
1716 END_PROFILE(smb2_getinfo);
1718 break;
1720 case SMB2_OP_SETINFO:
1721 if (!NT_STATUS_IS_OK(session_status)) {
1722 return_value = smbd_smb2_request_error(req, session_status);
1723 break;
1726 * This call needs to be run as user.
1728 * smbd_smb2_request_check_tcon()
1729 * calls change_to_user() on success.
1731 status = smbd_smb2_request_check_tcon(req);
1732 if (!NT_STATUS_IS_OK(status)) {
1733 return_value = smbd_smb2_request_error(req, status);
1734 break;
1738 START_PROFILE(smb2_setinfo);
1739 return_value = smbd_smb2_request_process_setinfo(req);
1740 END_PROFILE(smb2_setinfo);
1742 break;
1744 case SMB2_OP_BREAK:
1745 if (!NT_STATUS_IS_OK(session_status)) {
1746 return_value = smbd_smb2_request_error(req, session_status);
1747 break;
1750 * This call needs to be run as user.
1752 * smbd_smb2_request_check_tcon()
1753 * calls change_to_user() on success.
1755 status = smbd_smb2_request_check_tcon(req);
1756 if (!NT_STATUS_IS_OK(status)) {
1757 return_value = smbd_smb2_request_error(req, status);
1758 break;
1762 START_PROFILE(smb2_break);
1763 return_value = smbd_smb2_request_process_break(req);
1764 END_PROFILE(smb2_break);
1766 break;
1768 default:
1769 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1770 break;
1772 return return_value;
1775 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1777 struct tevent_req *subreq;
1778 int i = req->current_idx;
1780 req->subreq = NULL;
1782 req->current_idx += 3;
1784 if (req->current_idx < req->out.vector_count) {
1786 * We must process the remaining compound
1787 * SMB2 requests before any new incoming SMB2
1788 * requests. This is because incoming SMB2
1789 * requests may include a cancel for a
1790 * compound request we haven't processed
1791 * yet.
1793 struct tevent_immediate *im = tevent_create_immediate(req);
1794 if (!im) {
1795 return NT_STATUS_NO_MEMORY;
1798 if (req->do_signing) {
1800 * We sign each reply as we go along.
1801 * We can do this as smb2_calculate_credits()
1802 * grants zero credits on every part of a
1803 * compound reply except the last one,
1804 * which is signed just before calling
1805 * tstream_writev_queue_send().
1807 NTSTATUS status;
1808 status = smb2_signing_sign_pdu(req->session->session_key,
1809 &req->out.vector[i], 3);
1810 if (!NT_STATUS_IS_OK(status)) {
1811 TALLOC_FREE(im);
1812 return status;
1816 tevent_schedule_immediate(im,
1817 req->sconn->smb2.event_ctx,
1818 smbd_smb2_request_dispatch_immediate,
1819 req);
1820 return NT_STATUS_OK;
1823 if (req->compound_related) {
1824 req->compound_related = false;
1827 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1829 /* Set credit for these operations (zero credits if this
1830 is a final reply for an async operation). */
1831 smb2_calculate_credits(req, req);
1833 if (req->do_signing) {
1834 NTSTATUS status;
1835 status = smb2_signing_sign_pdu(req->session->session_key,
1836 &req->out.vector[i], 3);
1837 if (!NT_STATUS_IS_OK(status)) {
1838 return status;
1842 if (DEBUGLEVEL >= 10) {
1843 dbgtext("smbd_smb2_request_reply: sending...\n");
1844 print_req_vectors(req);
1847 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1848 if (req->out.vector_count == 4 &&
1849 req->out.vector[3].iov_base == NULL &&
1850 req->out.vector[3].iov_len != 0) {
1851 /* Dynamic part is NULL. Chop it off,
1852 We're going to send it via sendfile. */
1853 req->out.vector_count -= 1;
1856 subreq = tstream_writev_queue_send(req,
1857 req->sconn->smb2.event_ctx,
1858 req->sconn->smb2.stream,
1859 req->sconn->smb2.send_queue,
1860 req->out.vector,
1861 req->out.vector_count);
1862 if (subreq == NULL) {
1863 return NT_STATUS_NO_MEMORY;
1865 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1867 * We're done with this request -
1868 * move it off the "being processed" queue.
1870 DLIST_REMOVE(req->sconn->smb2.requests, req);
1872 return NT_STATUS_OK;
1875 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
1877 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1878 struct tevent_immediate *im,
1879 void *private_data)
1881 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1882 struct smbd_smb2_request);
1883 struct smbd_server_connection *sconn = req->sconn;
1884 NTSTATUS status;
1886 TALLOC_FREE(im);
1888 if (DEBUGLEVEL >= 10) {
1889 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1890 req->current_idx, req->in.vector_count));
1891 print_req_vectors(req);
1894 status = smbd_smb2_request_dispatch(req);
1895 if (!NT_STATUS_IS_OK(status)) {
1896 smbd_server_connection_terminate(sconn, nt_errstr(status));
1897 return;
1900 status = smbd_smb2_request_next_incoming(sconn);
1901 if (!NT_STATUS_IS_OK(status)) {
1902 smbd_server_connection_terminate(sconn, nt_errstr(status));
1903 return;
1907 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1909 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1910 struct smbd_smb2_request);
1911 struct smbd_server_connection *sconn = req->sconn;
1912 int ret;
1913 int sys_errno;
1914 NTSTATUS status;
1916 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1917 TALLOC_FREE(subreq);
1918 TALLOC_FREE(req);
1919 if (ret == -1) {
1920 status = map_nt_error_from_unix(sys_errno);
1921 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1922 nt_errstr(status)));
1923 smbd_server_connection_terminate(sconn, nt_errstr(status));
1924 return;
1927 status = smbd_smb2_request_next_incoming(sconn);
1928 if (!NT_STATUS_IS_OK(status)) {
1929 smbd_server_connection_terminate(sconn, nt_errstr(status));
1930 return;
1934 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1935 NTSTATUS status,
1936 DATA_BLOB body, DATA_BLOB *dyn,
1937 const char *location)
1939 uint8_t *outhdr;
1940 int i = req->current_idx;
1941 uint32_t next_command_ofs;
1943 DEBUG(10,("smbd_smb2_request_done_ex: "
1944 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1945 i, nt_errstr(status), (unsigned int)body.length,
1946 dyn ? "yes": "no",
1947 (unsigned int)(dyn ? dyn->length : 0),
1948 location));
1950 if (body.length < 2) {
1951 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1954 if ((body.length % 2) != 0) {
1955 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1958 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1960 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1961 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1963 req->out.vector[i+1].iov_base = (void *)body.data;
1964 req->out.vector[i+1].iov_len = body.length;
1966 if (dyn) {
1967 req->out.vector[i+2].iov_base = (void *)dyn->data;
1968 req->out.vector[i+2].iov_len = dyn->length;
1969 } else {
1970 req->out.vector[i+2].iov_base = NULL;
1971 req->out.vector[i+2].iov_len = 0;
1974 /* see if we need to recalculate the offset to the next response */
1975 if (next_command_ofs > 0) {
1976 next_command_ofs = SMB2_HDR_BODY;
1977 next_command_ofs += req->out.vector[i+1].iov_len;
1978 next_command_ofs += req->out.vector[i+2].iov_len;
1981 if ((next_command_ofs % 8) != 0) {
1982 size_t pad_size = 8 - (next_command_ofs % 8);
1983 if (req->out.vector[i+2].iov_len == 0) {
1985 * if the dyn buffer is empty
1986 * we can use it to add padding
1988 uint8_t *pad;
1990 pad = talloc_zero_array(req->out.vector,
1991 uint8_t, pad_size);
1992 if (pad == NULL) {
1993 return smbd_smb2_request_error(req,
1994 NT_STATUS_NO_MEMORY);
1997 req->out.vector[i+2].iov_base = (void *)pad;
1998 req->out.vector[i+2].iov_len = pad_size;
1999 } else {
2001 * For now we copy the dynamic buffer
2002 * and add the padding to the new buffer
2004 size_t old_size;
2005 uint8_t *old_dyn;
2006 size_t new_size;
2007 uint8_t *new_dyn;
2009 old_size = req->out.vector[i+2].iov_len;
2010 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2012 new_size = old_size + pad_size;
2013 new_dyn = talloc_zero_array(req->out.vector,
2014 uint8_t, new_size);
2015 if (new_dyn == NULL) {
2016 return smbd_smb2_request_error(req,
2017 NT_STATUS_NO_MEMORY);
2020 memcpy(new_dyn, old_dyn, old_size);
2021 memset(new_dyn + old_size, 0, pad_size);
2023 req->out.vector[i+2].iov_base = (void *)new_dyn;
2024 req->out.vector[i+2].iov_len = new_size;
2026 next_command_ofs += pad_size;
2029 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2031 return smbd_smb2_request_reply(req);
2034 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2035 NTSTATUS status,
2036 DATA_BLOB *info,
2037 const char *location)
2039 DATA_BLOB body;
2040 int i = req->current_idx;
2041 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
2043 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2044 i, nt_errstr(status), info ? " +info" : "",
2045 location));
2047 body.data = outhdr + SMB2_HDR_BODY;
2048 body.length = 8;
2049 SSVAL(body.data, 0, 9);
2051 if (info) {
2052 SIVAL(body.data, 0x04, info->length);
2053 } else {
2054 /* Allocated size of req->out.vector[i].iov_base
2055 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2056 * 1 byte without having to do an alloc.
2058 info = talloc_zero_array(req->out.vector,
2059 DATA_BLOB,
2061 if (!info) {
2062 return NT_STATUS_NO_MEMORY;
2064 info->data = ((uint8_t *)outhdr) +
2065 OUTVEC_ALLOC_SIZE - 1;
2066 info->length = 1;
2067 SCVAL(info->data, 0, 0);
2071 * Note: Even if there is an error, continue to process the request.
2072 * per MS-SMB2.
2075 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2079 struct smbd_smb2_send_oplock_break_state {
2080 struct smbd_server_connection *sconn;
2081 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2082 struct iovec vector;
2085 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2087 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2088 uint64_t file_id_persistent,
2089 uint64_t file_id_volatile,
2090 uint8_t oplock_level)
2092 struct smbd_smb2_send_oplock_break_state *state;
2093 struct tevent_req *subreq;
2094 uint8_t *hdr;
2095 uint8_t *body;
2097 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2098 if (state == NULL) {
2099 return NT_STATUS_NO_MEMORY;
2101 state->sconn = sconn;
2103 state->vector.iov_base = (void *)state->buf;
2104 state->vector.iov_len = sizeof(state->buf);
2106 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2107 hdr = state->buf + 4;
2108 body = hdr + SMB2_HDR_BODY;
2110 SIVAL(hdr, 0, SMB2_MAGIC);
2111 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2112 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2113 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2114 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2115 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2116 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2117 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2118 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2119 SIVAL(hdr, SMB2_HDR_PID, 0);
2120 SIVAL(hdr, SMB2_HDR_TID, 0);
2121 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2122 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2124 SSVAL(body, 0x00, 0x18);
2126 SCVAL(body, 0x02, oplock_level);
2127 SCVAL(body, 0x03, 0); /* reserved */
2128 SIVAL(body, 0x04, 0); /* reserved */
2129 SBVAL(body, 0x08, file_id_persistent);
2130 SBVAL(body, 0x10, file_id_volatile);
2132 subreq = tstream_writev_queue_send(state,
2133 sconn->smb2.event_ctx,
2134 sconn->smb2.stream,
2135 sconn->smb2.send_queue,
2136 &state->vector, 1);
2137 if (subreq == NULL) {
2138 return NT_STATUS_NO_MEMORY;
2140 tevent_req_set_callback(subreq,
2141 smbd_smb2_oplock_break_writev_done,
2142 state);
2144 return NT_STATUS_OK;
2147 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2149 struct smbd_smb2_send_oplock_break_state *state =
2150 tevent_req_callback_data(subreq,
2151 struct smbd_smb2_send_oplock_break_state);
2152 struct smbd_server_connection *sconn = state->sconn;
2153 int ret;
2154 int sys_errno;
2156 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2157 TALLOC_FREE(subreq);
2158 if (ret == -1) {
2159 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2160 smbd_server_connection_terminate(sconn, nt_errstr(status));
2161 return;
2164 TALLOC_FREE(state);
2167 struct smbd_smb2_request_read_state {
2168 size_t missing;
2169 bool asked_for_header;
2170 struct smbd_smb2_request *smb2_req;
2173 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2174 void *private_data,
2175 TALLOC_CTX *mem_ctx,
2176 struct iovec **_vector,
2177 size_t *_count);
2178 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2180 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2181 struct tevent_context *ev,
2182 struct smbd_server_connection *sconn)
2184 struct tevent_req *req;
2185 struct smbd_smb2_request_read_state *state;
2186 struct tevent_req *subreq;
2188 req = tevent_req_create(mem_ctx, &state,
2189 struct smbd_smb2_request_read_state);
2190 if (req == NULL) {
2191 return NULL;
2193 state->missing = 0;
2194 state->asked_for_header = false;
2196 state->smb2_req = smbd_smb2_request_allocate(state);
2197 if (tevent_req_nomem(state->smb2_req, req)) {
2198 return tevent_req_post(req, ev);
2200 state->smb2_req->sconn = sconn;
2202 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2203 sconn->smb2.recv_queue,
2204 smbd_smb2_request_next_vector,
2205 state);
2206 if (tevent_req_nomem(subreq, req)) {
2207 return tevent_req_post(req, ev);
2209 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2211 return req;
2214 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2215 void *private_data,
2216 TALLOC_CTX *mem_ctx,
2217 struct iovec **_vector,
2218 size_t *_count)
2220 struct smbd_smb2_request_read_state *state =
2221 talloc_get_type_abort(private_data,
2222 struct smbd_smb2_request_read_state);
2223 struct smbd_smb2_request *req = state->smb2_req;
2224 struct iovec *vector;
2225 int idx = req->in.vector_count;
2226 size_t len = 0;
2227 uint8_t *buf = NULL;
2229 if (req->in.vector_count == 0) {
2231 * first we need to get the NBT header
2233 req->in.vector = talloc_array(req, struct iovec,
2234 req->in.vector_count + 1);
2235 if (req->in.vector == NULL) {
2236 return -1;
2238 req->in.vector_count += 1;
2240 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2241 req->in.vector[idx].iov_len = 4;
2243 vector = talloc_array(mem_ctx, struct iovec, 1);
2244 if (vector == NULL) {
2245 return -1;
2248 vector[0] = req->in.vector[idx];
2250 *_vector = vector;
2251 *_count = 1;
2252 return 0;
2255 if (req->in.vector_count == 1) {
2257 * Now we analyze the NBT header
2259 state->missing = smb2_len(req->in.vector[0].iov_base);
2261 if (state->missing == 0) {
2262 /* if there're no remaining bytes, we're done */
2263 *_vector = NULL;
2264 *_count = 0;
2265 return 0;
2268 req->in.vector = talloc_realloc(req, req->in.vector,
2269 struct iovec,
2270 req->in.vector_count + 1);
2271 if (req->in.vector == NULL) {
2272 return -1;
2274 req->in.vector_count += 1;
2276 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2278 * it's a special NBT message,
2279 * so get all remaining bytes
2281 len = state->missing;
2282 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2284 * it's an invalid message, just read what we can get
2285 * and let the caller handle the error
2287 len = state->missing;
2288 } else {
2290 * We assume it's a SMB2 request,
2291 * and we first get the header and the
2292 * first 2 bytes (the struct size) of the body
2294 len = SMB2_HDR_BODY + 2;
2296 state->asked_for_header = true;
2299 state->missing -= len;
2301 buf = talloc_array(req->in.vector, uint8_t, len);
2302 if (buf == NULL) {
2303 return -1;
2306 req->in.vector[idx].iov_base = (void *)buf;
2307 req->in.vector[idx].iov_len = len;
2309 vector = talloc_array(mem_ctx, struct iovec, 1);
2310 if (vector == NULL) {
2311 return -1;
2314 vector[0] = req->in.vector[idx];
2316 *_vector = vector;
2317 *_count = 1;
2318 return 0;
2321 if (state->missing == 0) {
2322 /* if there're no remaining bytes, we're done */
2323 *_vector = NULL;
2324 *_count = 0;
2325 return 0;
2328 if (state->asked_for_header) {
2329 const uint8_t *hdr;
2330 size_t full_size;
2331 size_t next_command_ofs;
2332 size_t body_size;
2333 uint8_t *body;
2334 size_t dyn_size;
2335 uint8_t *dyn;
2336 bool invalid = false;
2338 state->asked_for_header = false;
2341 * We got the SMB2 header and the first 2 bytes
2342 * of the body. We fix the size to just the header
2343 * and manually copy the 2 first bytes to the body section
2345 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2346 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2348 /* allocate vectors for body and dynamic areas */
2349 req->in.vector = talloc_realloc(req, req->in.vector,
2350 struct iovec,
2351 req->in.vector_count + 2);
2352 if (req->in.vector == NULL) {
2353 return -1;
2355 req->in.vector_count += 2;
2357 full_size = state->missing + SMB2_HDR_BODY + 2;
2358 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2359 body_size = SVAL(hdr, SMB2_HDR_BODY);
2361 if (next_command_ofs != 0) {
2362 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2364 * this is invalid, just return a zero
2365 * body and let the caller deal with the error
2367 invalid = true;
2368 } else if (next_command_ofs > full_size) {
2370 * this is invalid, just return a zero
2371 * body and let the caller deal with the error
2373 invalid = true;
2374 } else {
2375 full_size = next_command_ofs;
2379 if (!invalid) {
2380 if (body_size < 2) {
2382 * this is invalid, just return a zero
2383 * body and let the caller deal with the error
2385 invalid = true;
2388 if ((body_size % 2) != 0) {
2389 body_size -= 1;
2392 if (body_size > (full_size - SMB2_HDR_BODY)) {
2394 * this is invalid, just return a zero
2395 * body and let the caller deal with the error
2397 invalid = true;
2401 if (invalid) {
2402 /* the caller should check this */
2403 body_size = 2;
2406 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2408 state->missing -= (body_size - 2) + dyn_size;
2410 body = talloc_array(req->in.vector, uint8_t, body_size);
2411 if (body == NULL) {
2412 return -1;
2415 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2416 if (dyn == NULL) {
2417 return -1;
2420 req->in.vector[idx].iov_base = (void *)body;
2421 req->in.vector[idx].iov_len = body_size;
2422 req->in.vector[idx+1].iov_base = (void *)dyn;
2423 req->in.vector[idx+1].iov_len = dyn_size;
2425 vector = talloc_array(mem_ctx, struct iovec, 2);
2426 if (vector == NULL) {
2427 return -1;
2431 * the first 2 bytes of the body were already fetched
2432 * together with the header
2434 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2435 vector[0].iov_base = body + 2;
2436 vector[0].iov_len = body_size - 2;
2438 vector[1] = req->in.vector[idx+1];
2440 *_vector = vector;
2441 *_count = 2;
2442 return 0;
2446 * when we endup here, we're looking for a new SMB2 request
2447 * next. And we ask for its header and the first 2 bytes of
2448 * the body (like we did for the first SMB2 request).
2451 req->in.vector = talloc_realloc(req, req->in.vector,
2452 struct iovec,
2453 req->in.vector_count + 1);
2454 if (req->in.vector == NULL) {
2455 return -1;
2457 req->in.vector_count += 1;
2460 * We assume it's a SMB2 request,
2461 * and we first get the header and the
2462 * first 2 bytes (the struct size) of the body
2464 len = SMB2_HDR_BODY + 2;
2466 if (len > state->missing) {
2467 /* let the caller handle the error */
2468 len = state->missing;
2471 state->missing -= len;
2472 state->asked_for_header = true;
2474 buf = talloc_array(req->in.vector, uint8_t, len);
2475 if (buf == NULL) {
2476 return -1;
2479 req->in.vector[idx].iov_base = (void *)buf;
2480 req->in.vector[idx].iov_len = len;
2482 vector = talloc_array(mem_ctx, struct iovec, 1);
2483 if (vector == NULL) {
2484 return -1;
2487 vector[0] = req->in.vector[idx];
2489 *_vector = vector;
2490 *_count = 1;
2491 return 0;
2494 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2496 struct tevent_req *req =
2497 tevent_req_callback_data(subreq,
2498 struct tevent_req);
2499 int ret;
2500 int sys_errno;
2501 NTSTATUS status;
2503 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2504 if (ret == -1) {
2505 status = map_nt_error_from_unix(sys_errno);
2506 tevent_req_nterror(req, status);
2507 return;
2510 tevent_req_done(req);
2513 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2514 TALLOC_CTX *mem_ctx,
2515 struct smbd_smb2_request **_smb2_req)
2517 struct smbd_smb2_request_read_state *state =
2518 tevent_req_data(req,
2519 struct smbd_smb2_request_read_state);
2520 NTSTATUS status;
2522 if (tevent_req_is_nterror(req, &status)) {
2523 tevent_req_received(req);
2524 return status;
2527 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2528 *_smb2_req = state->smb2_req;
2529 tevent_req_received(req);
2530 return NT_STATUS_OK;
2533 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2535 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2537 size_t max_send_queue_len;
2538 size_t cur_send_queue_len;
2539 struct tevent_req *subreq;
2541 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2543 * if there is already a smbd_smb2_request_read
2544 * pending, we are done.
2546 return NT_STATUS_OK;
2549 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2550 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2552 if (cur_send_queue_len > max_send_queue_len) {
2554 * if we have a lot of requests to send,
2555 * we wait until they are on the wire until we
2556 * ask for the next request.
2558 return NT_STATUS_OK;
2561 /* ask for the next request */
2562 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2563 if (subreq == NULL) {
2564 return NT_STATUS_NO_MEMORY;
2566 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2568 return NT_STATUS_OK;
2571 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2572 const uint8_t *inbuf, size_t size)
2574 NTSTATUS status;
2575 struct smbd_smb2_request *req = NULL;
2577 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2578 (unsigned int)size));
2580 status = smbd_initialize_smb2(sconn);
2581 if (!NT_STATUS_IS_OK(status)) {
2582 smbd_server_connection_terminate(sconn, nt_errstr(status));
2583 return;
2586 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2587 if (!NT_STATUS_IS_OK(status)) {
2588 smbd_server_connection_terminate(sconn, nt_errstr(status));
2589 return;
2592 status = smbd_smb2_request_validate(req);
2593 if (!NT_STATUS_IS_OK(status)) {
2594 smbd_server_connection_terminate(sconn, nt_errstr(status));
2595 return;
2598 status = smbd_smb2_request_setup_out(req);
2599 if (!NT_STATUS_IS_OK(status)) {
2600 smbd_server_connection_terminate(sconn, nt_errstr(status));
2601 return;
2604 status = smbd_smb2_request_dispatch(req);
2605 if (!NT_STATUS_IS_OK(status)) {
2606 smbd_server_connection_terminate(sconn, nt_errstr(status));
2607 return;
2610 status = smbd_smb2_request_next_incoming(sconn);
2611 if (!NT_STATUS_IS_OK(status)) {
2612 smbd_server_connection_terminate(sconn, nt_errstr(status));
2613 return;
2616 sconn->num_requests++;
2619 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2621 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2622 struct smbd_server_connection);
2623 NTSTATUS status;
2624 struct smbd_smb2_request *req = NULL;
2626 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2627 TALLOC_FREE(subreq);
2628 if (!NT_STATUS_IS_OK(status)) {
2629 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2630 nt_errstr(status)));
2631 smbd_server_connection_terminate(sconn, nt_errstr(status));
2632 return;
2635 if (req->in.nbt_hdr[0] != 0x00) {
2636 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2637 req->in.nbt_hdr[0]));
2638 TALLOC_FREE(req);
2639 goto next;
2642 req->current_idx = 1;
2644 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2645 req->current_idx, req->in.vector_count));
2647 status = smbd_smb2_request_validate(req);
2648 if (!NT_STATUS_IS_OK(status)) {
2649 smbd_server_connection_terminate(sconn, nt_errstr(status));
2650 return;
2653 status = smbd_smb2_request_setup_out(req);
2654 if (!NT_STATUS_IS_OK(status)) {
2655 smbd_server_connection_terminate(sconn, nt_errstr(status));
2656 return;
2659 status = smbd_smb2_request_dispatch(req);
2660 if (!NT_STATUS_IS_OK(status)) {
2661 smbd_server_connection_terminate(sconn, nt_errstr(status));
2662 return;
2665 next:
2666 status = smbd_smb2_request_next_incoming(sconn);
2667 if (!NT_STATUS_IS_OK(status)) {
2668 smbd_server_connection_terminate(sconn, nt_errstr(status));
2669 return;
2672 sconn->num_requests++;
2674 /* The timeout_processing function isn't run nearly
2675 often enough to implement 'max log size' without
2676 overrunning the size of the file by many megabytes.
2677 This is especially true if we are running at debug
2678 level 10. Checking every 50 SMB2s is a nice
2679 tradeoff of performance vs log file size overrun. */
2681 if ((sconn->num_requests % 50) == 0 &&
2682 need_to_check_log_size()) {
2683 change_to_root_user();
2684 check_log_size();