s3:smb2_server: check the already granted credits like in the master branch
[Samba.git] / source3 / smbd / smb2_server.c
bloba73c2cc9be2aa26e45511f4302b7a374bf82bf9a
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.credits_granted = 1;
118 sconn->smb2.max_credits = lp_smb2_max_credits();
119 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
120 sconn->smb2.max_credits);
121 if (sconn->smb2.credits_bitmap == NULL) {
122 return NT_STATUS_NO_MEMORY;
125 ret = tstream_bsd_existing_socket(sconn, sconn->sock,
126 &sconn->smb2.stream);
127 if (ret == -1) {
128 status = map_nt_error_from_unix(errno);
129 return status;
132 /* Ensure child is set to non-blocking mode */
133 set_blocking(sconn->sock, false);
134 return NT_STATUS_OK;
137 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
138 #define _smb2_setlen(_buf,len) do { \
139 uint8_t *buf = (uint8_t *)_buf; \
140 buf[0] = 0; \
141 buf[1] = ((len)&0xFF0000)>>16; \
142 buf[2] = ((len)&0xFF00)>>8; \
143 buf[3] = (len)&0xFF; \
144 } while (0)
146 static void smb2_setup_nbt_length(struct iovec *vector, int count)
148 size_t len = 0;
149 int i;
151 for (i=1; i < count; i++) {
152 len += vector[i].iov_len;
155 _smb2_setlen(vector[0].iov_base, len);
158 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request **req)
160 if (*req) {
161 (*req)->parent = NULL;
162 (*req)->mem_pool = NULL;
165 return 0;
168 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
170 if (req->parent) {
171 *req->parent = NULL;
172 talloc_free(req->mem_pool);
175 return 0;
178 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
180 TALLOC_CTX *mem_pool;
181 struct smbd_smb2_request **parent;
182 struct smbd_smb2_request *req;
184 #if 0
185 /* Enable this to find subtle valgrind errors. */
186 mem_pool = talloc_init("smbd_smb2_request_allocate");
187 #else
188 mem_pool = talloc_pool(mem_ctx, 8192);
189 #endif
190 if (mem_pool == NULL) {
191 return NULL;
194 parent = talloc(mem_pool, struct smbd_smb2_request *);
195 if (parent == NULL) {
196 talloc_free(mem_pool);
197 return NULL;
200 req = talloc_zero(parent, struct smbd_smb2_request);
201 if (req == NULL) {
202 talloc_free(mem_pool);
203 return NULL;
205 *parent = req;
206 req->mem_pool = mem_pool;
207 req->parent = parent;
209 req->last_session_id = UINT64_MAX;
210 req->last_tid = UINT32_MAX;
212 talloc_set_destructor(parent, smbd_smb2_request_parent_destructor);
213 talloc_set_destructor(req, smbd_smb2_request_destructor);
215 return req;
218 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
219 const uint8_t *inbuf, size_t size,
220 struct smbd_smb2_request **_req)
222 struct smbd_smb2_request *req;
223 uint32_t protocol_version;
224 const uint8_t *inhdr = NULL;
225 off_t ofs = 0;
226 uint16_t cmd;
227 uint32_t next_command_ofs;
229 if (size < (4 + SMB2_HDR_BODY + 2)) {
230 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
231 return NT_STATUS_INVALID_PARAMETER;
234 inhdr = inbuf + 4;
236 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
237 if (protocol_version != SMB2_MAGIC) {
238 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
239 protocol_version));
240 return NT_STATUS_INVALID_PARAMETER;
243 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
244 if (cmd != SMB2_OP_NEGPROT) {
245 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
246 cmd));
247 return NT_STATUS_INVALID_PARAMETER;
250 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
251 if (next_command_ofs != 0) {
252 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
253 next_command_ofs));
254 return NT_STATUS_INVALID_PARAMETER;
257 req = smbd_smb2_request_allocate(sconn);
258 if (req == NULL) {
259 return NT_STATUS_NO_MEMORY;
261 req->sconn = sconn;
263 talloc_steal(req, inbuf);
265 req->in.vector = talloc_array(req, struct iovec, 4);
266 if (req->in.vector == NULL) {
267 TALLOC_FREE(req);
268 return NT_STATUS_NO_MEMORY;
270 req->in.vector_count = 4;
272 memcpy(req->in.nbt_hdr, inbuf, 4);
274 ofs = 0;
275 req->in.vector[0].iov_base = (void *)req->in.nbt_hdr;
276 req->in.vector[0].iov_len = 4;
277 ofs += req->in.vector[0].iov_len;
279 req->in.vector[1].iov_base = (void *)(inbuf + ofs);
280 req->in.vector[1].iov_len = SMB2_HDR_BODY;
281 ofs += req->in.vector[1].iov_len;
283 req->in.vector[2].iov_base = (void *)(inbuf + ofs);
284 req->in.vector[2].iov_len = SVAL(inbuf, ofs) & 0xFFFE;
285 ofs += req->in.vector[2].iov_len;
287 if (ofs > size) {
288 return NT_STATUS_INVALID_PARAMETER;
291 req->in.vector[3].iov_base = (void *)(inbuf + ofs);
292 req->in.vector[3].iov_len = size - ofs;
293 ofs += req->in.vector[3].iov_len;
295 req->current_idx = 1;
297 *_req = req;
298 return NT_STATUS_OK;
301 static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
302 uint64_t message_id, uint64_t seq_id)
304 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
305 unsigned int offset;
307 if (seq_id < sconn->smb2.seqnum_low) {
308 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
309 "%llu (sequence id %llu) (low = %llu, max = %lu)\n",
310 (unsigned long long)message_id,
311 (unsigned long long)seq_id,
312 (unsigned long long)sconn->smb2.seqnum_low,
313 (unsigned long)sconn->smb2.max_credits));
314 return false;
317 if (seq_id > (sconn->smb2.seqnum_low + sconn->smb2.max_credits)) {
318 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
319 "%llu (sequence id %llu) (low = %llu, max = %lu)\n",
320 (unsigned long long)message_id,
321 (unsigned long long)seq_id,
322 (unsigned long long)sconn->smb2.seqnum_low,
323 (unsigned long)sconn->smb2.max_credits));
324 return false;
327 offset = seq_id % sconn->smb2.max_credits;
329 if (bitmap_query(credits_bm, offset)) {
330 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
331 "%llu (sequence id %llu) (low = %llu, max = %lu) "
332 "(bm offset %u)\n",
333 (unsigned long long)message_id,
334 (unsigned long long)seq_id,
335 (unsigned long long)sconn->smb2.seqnum_low,
336 (unsigned long)sconn->smb2.max_credits,
337 offset));
338 return false;
341 /* Mark the message_ids as seen in the bitmap. */
342 bitmap_set(credits_bm, offset);
344 if (seq_id != sconn->smb2.seqnum_low) {
345 return true;
349 * Move the window forward by all the message_id's
350 * already seen.
352 while (bitmap_query(credits_bm, offset)) {
353 DEBUG(10,("smb2_validate_sequence_number: clearing "
354 "id %llu (position %u) from bitmap\n",
355 (unsigned long long)(sconn->smb2.seqnum_low),
356 offset));
357 bitmap_clear(credits_bm, offset);
359 sconn->smb2.seqnum_low += 1;
360 offset = sconn->smb2.seqnum_low % sconn->smb2.max_credits;
363 return true;
366 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
367 const uint8_t *inhdr)
369 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
370 uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
371 bool ok;
373 if (opcode == SMB2_OP_CANCEL) {
374 /* SMB2_CANCEL requests by definition resend messageids. */
375 return true;
378 DEBUG(11, ("smb2_validate_message_id: mid %llu, credits_granted %llu, "
379 "max_credits %llu, seqnum_low: %llu\n",
380 (unsigned long long) message_id,
381 (unsigned long long) sconn->smb2.credits_granted,
382 (unsigned long long) sconn->smb2.max_credits,
383 (unsigned long long) sconn->smb2.seqnum_low));
385 if (sconn->smb2.credits_granted < 1) {
386 DEBUG(0, ("smb2_validate_message_id: client used more "
387 "credits than granted, mid %llu, credits_granted %llu, "
388 "max_credits %llu, seqnum_low: %llu\n",
389 (unsigned long long) message_id,
390 (unsigned long long) sconn->smb2.credits_granted,
391 (unsigned long long) sconn->smb2.max_credits,
392 (unsigned long long) sconn->smb2.seqnum_low));
393 return false;
396 ok = smb2_validate_sequence_number(sconn, message_id, message_id);
397 if (!ok) {
398 return false;
401 /* substract used credits */
402 sconn->smb2.credits_granted -= 1;
404 return true;
407 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
409 int count;
410 int idx;
412 count = req->in.vector_count;
414 if (count < 4) {
415 /* It's not a SMB2 request */
416 return NT_STATUS_INVALID_PARAMETER;
419 for (idx=1; idx < count; idx += 3) {
420 const uint8_t *inhdr = NULL;
421 uint32_t flags;
423 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
424 return NT_STATUS_INVALID_PARAMETER;
427 if (req->in.vector[idx+1].iov_len < 2) {
428 return NT_STATUS_INVALID_PARAMETER;
431 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
433 /* Check the SMB2 header */
434 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
435 return NT_STATUS_INVALID_PARAMETER;
438 if (!smb2_validate_message_id(req->sconn, inhdr)) {
439 return NT_STATUS_INVALID_PARAMETER;
442 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
443 if (idx == 1) {
445 * the 1st request should never have the
446 * SMB2_HDR_FLAG_CHAINED flag set
448 if (flags & SMB2_HDR_FLAG_CHAINED) {
449 req->next_status = NT_STATUS_INVALID_PARAMETER;
450 return NT_STATUS_OK;
452 } else if (idx == 4) {
454 * the 2nd request triggers related vs. unrelated
455 * compounded requests
457 if (flags & SMB2_HDR_FLAG_CHAINED) {
458 req->compound_related = true;
460 } else if (idx > 4) {
461 #if 0
463 * It seems the this tests are wrong
464 * see the SMB2-COMPOUND test
468 * all other requests should match the 2nd one
470 if (flags & SMB2_HDR_FLAG_CHAINED) {
471 if (!req->compound_related) {
472 req->next_status =
473 NT_STATUS_INVALID_PARAMETER;
474 return NT_STATUS_OK;
476 } else {
477 if (req->compound_related) {
478 req->next_status =
479 NT_STATUS_INVALID_PARAMETER;
480 return NT_STATUS_OK;
483 #endif
487 return NT_STATUS_OK;
490 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
491 const struct iovec *in_vector,
492 struct iovec *out_vector)
494 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
495 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
496 uint16_t credits_requested;
497 uint32_t out_flags;
498 uint16_t credits_granted = 0;
500 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
501 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
503 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
505 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
507 * In case we already send an async interim
508 * response, we should not grant
509 * credits on the final response.
511 credits_requested = 0;
514 if (credits_requested) {
515 uint16_t modified_credits_requested;
516 uint32_t multiplier;
519 * Split up max_credits into 1/16ths, and then scale
520 * the requested credits by how many 16ths have been
521 * currently granted. Less than 1/16th == grant all
522 * requested (100%), scale down as more have been
523 * granted. Never ask for less than 1 as the client
524 * asked for at least 1. JRA.
527 multiplier = 16 - (((sconn->smb2.credits_granted * 16) / sconn->smb2.max_credits) % 16);
529 modified_credits_requested = (multiplier * credits_requested) / 16;
530 if (modified_credits_requested == 0) {
531 modified_credits_requested = 1;
534 /* Remember what we gave out. */
535 credits_granted = MIN(modified_credits_requested,
536 (sconn->smb2.max_credits - sconn->smb2.credits_granted));
539 if (credits_granted == 0 && sconn->smb2.credits_granted == 0) {
540 /* First negprot packet, or ensure the client credits can
541 never drop to zero. */
542 credits_granted = 1;
545 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
546 sconn->smb2.credits_granted += credits_granted;
548 DEBUG(10,("smb2_set_operation_credit: requested %u, "
549 "granted %u, total granted %u\n",
550 (unsigned int)credits_requested,
551 (unsigned int)credits_granted,
552 (unsigned int)sconn->smb2.credits_granted ));
555 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
556 struct smbd_smb2_request *outreq)
558 int count, idx;
559 uint16_t total_credits = 0;
561 count = outreq->out.vector_count;
563 for (idx=1; idx < count; idx += 3) {
564 uint8_t *outhdr = (uint8_t *)outreq->out.vector[idx].iov_base;
565 smb2_set_operation_credit(outreq->sconn,
566 &inreq->in.vector[idx],
567 &outreq->out.vector[idx]);
568 /* To match Windows, count up what we
569 just granted. */
570 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
571 /* Set to zero in all but the last reply. */
572 if (idx + 3 < count) {
573 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
574 } else {
575 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
580 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
582 struct iovec *vector;
583 int count;
584 int idx;
586 count = req->in.vector_count;
587 vector = talloc_zero_array(req, struct iovec, count);
588 if (vector == NULL) {
589 return NT_STATUS_NO_MEMORY;
592 vector[0].iov_base = req->out.nbt_hdr;
593 vector[0].iov_len = 4;
594 SIVAL(req->out.nbt_hdr, 0, 0);
596 for (idx=1; idx < count; idx += 3) {
597 const uint8_t *inhdr = NULL;
598 uint32_t in_flags;
599 uint8_t *outhdr = NULL;
600 uint8_t *outbody = NULL;
601 uint32_t next_command_ofs = 0;
602 struct iovec *current = &vector[idx];
604 if ((idx + 3) < count) {
605 /* we have a next command -
606 * setup for the error case. */
607 next_command_ofs = SMB2_HDR_BODY + 9;
610 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
611 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
613 outhdr = talloc_zero_array(vector, uint8_t,
614 OUTVEC_ALLOC_SIZE);
615 if (outhdr == NULL) {
616 return NT_STATUS_NO_MEMORY;
619 outbody = outhdr + SMB2_HDR_BODY;
621 current[0].iov_base = (void *)outhdr;
622 current[0].iov_len = SMB2_HDR_BODY;
624 current[1].iov_base = (void *)outbody;
625 current[1].iov_len = 8;
627 current[2].iov_base = NULL;
628 current[2].iov_len = 0;
630 /* setup the SMB2 header */
631 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
632 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
633 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
634 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
635 SIVAL(outhdr, SMB2_HDR_STATUS,
636 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
637 SSVAL(outhdr, SMB2_HDR_OPCODE,
638 SVAL(inhdr, SMB2_HDR_OPCODE));
639 SIVAL(outhdr, SMB2_HDR_FLAGS,
640 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
641 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
642 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
643 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
644 SIVAL(outhdr, SMB2_HDR_PID,
645 IVAL(inhdr, SMB2_HDR_PID));
646 SIVAL(outhdr, SMB2_HDR_TID,
647 IVAL(inhdr, SMB2_HDR_TID));
648 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
649 BVAL(inhdr, SMB2_HDR_SESSION_ID));
650 memcpy(outhdr + SMB2_HDR_SIGNATURE,
651 inhdr + SMB2_HDR_SIGNATURE, 16);
653 /* setup error body header */
654 SSVAL(outbody, 0x00, 0x08 + 1);
655 SSVAL(outbody, 0x02, 0);
656 SIVAL(outbody, 0x04, 0);
659 req->out.vector = vector;
660 req->out.vector_count = count;
662 /* setup the length of the NBT packet */
663 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
665 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
667 return NT_STATUS_OK;
670 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
671 const char *reason,
672 const char *location)
674 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
675 reason, location));
676 exit_server_cleanly(reason);
679 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
680 struct iovec *outvec,
681 const struct iovec *srcvec)
683 /* vec[0] is always boilerplate and must
684 * be allocated with size OUTVEC_ALLOC_SIZE. */
686 outvec[0].iov_base = talloc_memdup(ctx,
687 srcvec[0].iov_base,
688 OUTVEC_ALLOC_SIZE);
689 if (!outvec[0].iov_base) {
690 return false;
692 outvec[0].iov_len = SMB2_HDR_BODY;
695 * If this is a "standard" vec[1] of length 8,
696 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
697 * then duplicate this. Else use talloc_memdup().
700 if (srcvec[1].iov_len == 8 &&
701 srcvec[1].iov_base ==
702 ((uint8_t *)srcvec[0].iov_base) +
703 SMB2_HDR_BODY) {
704 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
705 SMB2_HDR_BODY;
706 outvec[1].iov_len = 8;
707 } else {
708 outvec[1].iov_base = talloc_memdup(ctx,
709 srcvec[1].iov_base,
710 srcvec[1].iov_len);
711 if (!outvec[1].iov_base) {
712 return false;
714 outvec[1].iov_len = srcvec[1].iov_len;
718 * If this is a "standard" vec[2] of length 1,
719 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
720 * then duplicate this. Else use talloc_memdup().
723 if (srcvec[2].iov_base &&
724 srcvec[2].iov_len) {
725 if (srcvec[2].iov_base ==
726 ((uint8_t *)srcvec[0].iov_base) +
727 (OUTVEC_ALLOC_SIZE - 1) &&
728 srcvec[2].iov_len == 1) {
729 /* Common SMB2 error packet case. */
730 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
731 (OUTVEC_ALLOC_SIZE - 1);
732 } else {
733 outvec[2].iov_base = talloc_memdup(ctx,
734 srcvec[2].iov_base,
735 srcvec[2].iov_len);
736 if (!outvec[2].iov_base) {
737 return false;
740 outvec[2].iov_len = srcvec[2].iov_len;
741 } else {
742 outvec[2].iov_base = NULL;
743 outvec[2].iov_len = 0;
745 return true;
748 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
750 struct smbd_smb2_request *newreq = NULL;
751 struct iovec *outvec = NULL;
752 int count = req->out.vector_count;
753 int i;
755 newreq = smbd_smb2_request_allocate(req->sconn);
756 if (!newreq) {
757 return NULL;
760 newreq->sconn = req->sconn;
761 newreq->session = req->session;
762 newreq->do_signing = req->do_signing;
763 newreq->current_idx = req->current_idx;
764 newreq->async = false;
765 newreq->cancelled = false;
766 /* Note we are leaving:
767 ->tcon
768 ->smb1req
769 ->compat_chain_fsp
770 uninitialized as NULL here as
771 they're not used in the interim
772 response code. JRA. */
774 outvec = talloc_zero_array(newreq, struct iovec, count);
775 if (!outvec) {
776 TALLOC_FREE(newreq);
777 return NULL;
779 newreq->out.vector = outvec;
780 newreq->out.vector_count = count;
782 /* Setup the outvec's identically to req. */
783 outvec[0].iov_base = newreq->out.nbt_hdr;
784 outvec[0].iov_len = 4;
785 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
787 /* Setup the vectors identically to the ones in req. */
788 for (i = 1; i < count; i += 3) {
789 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
790 break;
794 if (i < count) {
795 /* Alloc failed. */
796 TALLOC_FREE(newreq);
797 return NULL;
800 smb2_setup_nbt_length(newreq->out.vector,
801 newreq->out.vector_count);
803 return newreq;
806 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
808 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
810 int i = 0;
811 uint8_t *outhdr = NULL;
812 struct smbd_smb2_request *nreq = NULL;
814 /* Create a new smb2 request we'll use
815 for the interim return. */
816 nreq = dup_smb2_req(req);
817 if (!nreq) {
818 return NT_STATUS_NO_MEMORY;
821 /* Lose the last 3 out vectors. They're the
822 ones we'll be using for the async reply. */
823 nreq->out.vector_count -= 3;
825 smb2_setup_nbt_length(nreq->out.vector,
826 nreq->out.vector_count);
828 /* Step back to the previous reply. */
829 i = nreq->current_idx - 3;
830 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
831 /* And end the chain. */
832 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
834 /* Calculate outgoing credits */
835 smb2_calculate_credits(req, nreq);
837 /* Re-sign if needed. */
838 if (nreq->do_signing) {
839 NTSTATUS status;
840 status = smb2_signing_sign_pdu(nreq->session->session_key,
841 &nreq->out.vector[i], 3);
842 if (!NT_STATUS_IS_OK(status)) {
843 return status;
846 if (DEBUGLEVEL >= 10) {
847 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
848 (unsigned int)nreq->current_idx );
849 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
850 (unsigned int)nreq->out.vector_count );
851 print_req_vectors(nreq);
853 nreq->subreq = tstream_writev_queue_send(nreq,
854 nreq->sconn->smb2.event_ctx,
855 nreq->sconn->smb2.stream,
856 nreq->sconn->smb2.send_queue,
857 nreq->out.vector,
858 nreq->out.vector_count);
860 if (nreq->subreq == NULL) {
861 return NT_STATUS_NO_MEMORY;
864 tevent_req_set_callback(nreq->subreq,
865 smbd_smb2_request_writev_done,
866 nreq);
868 return NT_STATUS_OK;
871 struct smbd_smb2_request_pending_state {
872 struct smbd_server_connection *sconn;
873 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
874 struct iovec vector[3];
877 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
879 struct smbd_smb2_request_pending_state *state =
880 tevent_req_callback_data(subreq,
881 struct smbd_smb2_request_pending_state);
882 struct smbd_server_connection *sconn = state->sconn;
883 int ret;
884 int sys_errno;
886 ret = tstream_writev_queue_recv(subreq, &sys_errno);
887 TALLOC_FREE(subreq);
888 if (ret == -1) {
889 NTSTATUS status = map_nt_error_from_unix(sys_errno);
890 smbd_server_connection_terminate(sconn, nt_errstr(status));
891 return;
894 TALLOC_FREE(state);
897 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
898 struct tevent_req *subreq)
900 NTSTATUS status;
901 struct smbd_smb2_request_pending_state *state = NULL;
902 int i = req->current_idx;
903 uint8_t *reqhdr = NULL;
904 uint8_t *hdr = NULL;
905 uint8_t *body = NULL;
906 uint32_t flags = 0;
907 uint64_t message_id = 0;
908 uint64_t async_id = 0;
909 struct iovec *outvec = NULL;
911 if (!tevent_req_is_in_progress(subreq)) {
912 return NT_STATUS_OK;
915 req->subreq = subreq;
916 subreq = NULL;
918 if (req->async) {
919 /* We're already async. */
920 return NT_STATUS_OK;
923 if (req->in.vector_count > i + 3) {
925 * We're trying to go async in a compound
926 * request chain. This is not allowed.
927 * Cancel the outstanding request.
929 tevent_req_cancel(req->subreq);
930 return smbd_smb2_request_error(req,
931 NT_STATUS_INSUFFICIENT_RESOURCES);
934 if (DEBUGLEVEL >= 10) {
935 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
936 (unsigned int)req->current_idx );
937 print_req_vectors(req);
940 if (req->out.vector_count > 4) {
941 /* This is a compound reply. We
942 * must do an interim response
943 * followed by the async response
944 * to match W2K8R2.
946 status = smb2_send_async_interim_response(req);
947 if (!NT_STATUS_IS_OK(status)) {
948 return status;
952 * We're splitting off the last SMB2
953 * request in a compound set, and the
954 * smb2_send_async_interim_response()
955 * call above just sent all the replies
956 * for the previous SMB2 requests in
957 * this compound set. So we're no longer
958 * in the "compound_related_in_progress"
959 * state, and this is no longer a compound
960 * request.
962 req->compound_related = false;
963 req->sconn->smb2.compound_related_in_progress = false;
966 /* Don't return an intermediate packet on a pipe read/write. */
967 if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
968 goto ipc_out;
971 reqhdr = (uint8_t *)req->out.vector[i].iov_base;
972 flags = (IVAL(reqhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
973 message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
974 async_id = message_id; /* keep it simple for now... */
977 * What we send is identical to a smbd_smb2_request_error
978 * packet with an error status of STATUS_PENDING. Make use
979 * of this fact sometime when refactoring. JRA.
982 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
983 if (state == NULL) {
984 return NT_STATUS_NO_MEMORY;
986 state->sconn = req->sconn;
988 state->vector[0].iov_base = (void *)state->buf;
989 state->vector[0].iov_len = 4;
991 state->vector[1].iov_base = state->buf + 4;
992 state->vector[1].iov_len = SMB2_HDR_BODY;
994 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
995 state->vector[2].iov_len = 9;
997 smb2_setup_nbt_length(state->vector, 3);
999 hdr = (uint8_t *)state->vector[1].iov_base;
1000 body = (uint8_t *)state->vector[2].iov_base;
1002 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1003 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1004 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1005 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1006 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(reqhdr, SMB2_HDR_OPCODE));
1008 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1009 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1010 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1011 SBVAL(hdr, SMB2_HDR_PID, async_id);
1012 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1013 BVAL(reqhdr, SMB2_HDR_SESSION_ID));
1014 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
1016 SSVAL(body, 0x00, 0x08 + 1);
1018 SCVAL(body, 0x02, 0);
1019 SCVAL(body, 0x03, 0);
1020 SIVAL(body, 0x04, 0);
1021 /* Match W2K8R2... */
1022 SCVAL(body, 0x08, 0x21);
1024 /* Ensure we correctly go through crediting. Grant
1025 the credits now, and zero credits on the final
1026 response. */
1027 smb2_set_operation_credit(req->sconn,
1028 &req->in.vector[i],
1029 &state->vector[1]);
1031 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1033 if (req->do_signing) {
1034 status = smb2_signing_sign_pdu(req->session->session_key,
1035 &state->vector[1], 2);
1036 if (!NT_STATUS_IS_OK(status)) {
1037 return status;
1041 subreq = tstream_writev_queue_send(state,
1042 req->sconn->smb2.event_ctx,
1043 req->sconn->smb2.stream,
1044 req->sconn->smb2.send_queue,
1045 state->vector,
1048 if (subreq == NULL) {
1049 return NT_STATUS_NO_MEMORY;
1052 tevent_req_set_callback(subreq,
1053 smbd_smb2_request_pending_writev_done,
1054 state);
1056 /* Note we're going async with this request. */
1057 req->async = true;
1059 ipc_out:
1062 * Now manipulate req so that the outstanding async request
1063 * is the only one left in the struct smbd_smb2_request.
1066 if (req->current_idx == 1) {
1067 /* There was only one. */
1068 goto out;
1071 /* Re-arrange the in.vectors. */
1072 req->in.vector[1] = req->in.vector[i];
1073 req->in.vector[2] = req->in.vector[i+1];
1074 req->in.vector[3] = req->in.vector[i+2];
1075 req->in.vector_count = 4;
1076 /* Reset the new in size. */
1077 smb2_setup_nbt_length(req->in.vector, 4);
1079 /* Now recreate the out.vectors. */
1080 outvec = talloc_zero_array(req, struct iovec, 4);
1081 if (!outvec) {
1082 return NT_STATUS_NO_MEMORY;
1085 /* 0 is always boilerplate and must
1086 * be of size 4 for the length field. */
1088 outvec[0].iov_base = req->out.nbt_hdr;
1089 outvec[0].iov_len = 4;
1090 SIVAL(req->out.nbt_hdr, 0, 0);
1092 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
1093 return NT_STATUS_NO_MEMORY;
1096 TALLOC_FREE(req->out.vector);
1098 req->out.vector = outvec;
1100 req->current_idx = 1;
1101 req->out.vector_count = 4;
1103 out:
1105 smb2_setup_nbt_length(req->out.vector,
1106 req->out.vector_count);
1108 if (req->async) {
1109 /* Ensure our final reply matches the interim one. */
1110 reqhdr = (uint8_t *)req->out.vector[1].iov_base;
1111 SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1112 SBVAL(reqhdr, SMB2_HDR_PID, async_id);
1115 const uint8_t *inhdr =
1116 (const uint8_t *)req->in.vector[1].iov_base;
1117 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1118 "going async\n",
1119 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1120 (unsigned long long)async_id ));
1124 return NT_STATUS_OK;
1127 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1129 struct smbd_server_connection *sconn = req->sconn;
1130 struct smbd_smb2_request *cur;
1131 const uint8_t *inhdr;
1132 int i = req->current_idx;
1133 uint32_t flags;
1134 uint64_t search_message_id;
1135 uint64_t search_async_id;
1136 uint64_t found_id;
1138 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1140 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1141 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1142 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1145 * we don't need the request anymore
1146 * cancel requests never have a response
1148 DLIST_REMOVE(req->sconn->smb2.requests, req);
1149 TALLOC_FREE(req);
1151 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1152 const uint8_t *outhdr;
1153 uint64_t message_id;
1154 uint64_t async_id;
1156 i = cur->current_idx;
1158 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1160 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1161 async_id = BVAL(outhdr, SMB2_HDR_PID);
1163 if (flags & SMB2_HDR_FLAG_ASYNC) {
1164 if (search_async_id == async_id) {
1165 found_id = async_id;
1166 break;
1168 } else {
1169 if (search_message_id == message_id) {
1170 found_id = message_id;
1171 break;
1176 if (cur && cur->subreq) {
1177 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1178 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1179 "cancel opcode[%s] mid %llu\n",
1180 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1181 (unsigned long long)found_id ));
1182 tevent_req_cancel(cur->subreq);
1185 return NT_STATUS_OK;
1188 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1189 size_t expected_body_size)
1191 const uint8_t *inhdr;
1192 uint16_t opcode;
1193 const uint8_t *inbody;
1194 int i = req->current_idx;
1195 size_t body_size;
1196 size_t min_dyn_size = expected_body_size & 0x00000001;
1199 * The following should be checked already.
1201 if ((i+2) > req->in.vector_count) {
1202 return NT_STATUS_INTERNAL_ERROR;
1204 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1205 return NT_STATUS_INTERNAL_ERROR;
1207 if (req->in.vector[i+1].iov_len < 2) {
1208 return NT_STATUS_INTERNAL_ERROR;
1211 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1212 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1214 switch (opcode) {
1215 case SMB2_OP_IOCTL:
1216 case SMB2_OP_GETINFO:
1217 min_dyn_size = 0;
1218 break;
1222 * Now check the expected body size,
1223 * where the last byte might be in the
1224 * dynnamic section..
1226 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1227 return NT_STATUS_INVALID_PARAMETER;
1229 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1230 return NT_STATUS_INVALID_PARAMETER;
1233 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1235 body_size = SVAL(inbody, 0x00);
1236 if (body_size != expected_body_size) {
1237 return NT_STATUS_INVALID_PARAMETER;
1240 return NT_STATUS_OK;
1243 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1245 const uint8_t *inhdr;
1246 int i = req->current_idx;
1247 uint16_t opcode;
1248 uint32_t flags;
1249 uint64_t mid;
1250 NTSTATUS status;
1251 NTSTATUS session_status;
1252 uint32_t allowed_flags;
1253 NTSTATUS return_value;
1255 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1257 /* TODO: verify more things */
1259 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1260 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1261 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1262 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1263 smb2_opcode_name(opcode),
1264 (unsigned long long)mid));
1266 if (get_Protocol() >= PROTOCOL_SMB2) {
1268 * once the protocol is negotiated
1269 * SMB2_OP_NEGPROT is not allowed anymore
1271 if (opcode == SMB2_OP_NEGPROT) {
1272 /* drop the connection */
1273 return NT_STATUS_INVALID_PARAMETER;
1275 } else {
1277 * if the protocol is not negotiated yet
1278 * only SMB2_OP_NEGPROT is allowed.
1280 if (opcode != SMB2_OP_NEGPROT) {
1281 /* drop the connection */
1282 return NT_STATUS_INVALID_PARAMETER;
1286 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1287 SMB2_HDR_FLAG_SIGNED |
1288 SMB2_HDR_FLAG_DFS;
1289 if (opcode == SMB2_OP_CANCEL) {
1290 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1292 if ((flags & ~allowed_flags) != 0) {
1293 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1297 * Check if the client provided a valid session id,
1298 * if so smbd_smb2_request_check_session() calls
1299 * set_current_user_info().
1301 * As some command don't require a valid session id
1302 * we defer the check of the session_status
1304 session_status = smbd_smb2_request_check_session(req);
1306 req->do_signing = false;
1307 if (flags & SMB2_HDR_FLAG_SIGNED) {
1308 if (!NT_STATUS_IS_OK(session_status)) {
1309 return smbd_smb2_request_error(req, session_status);
1312 req->do_signing = true;
1313 status = smb2_signing_check_pdu(req->session->session_key,
1314 &req->in.vector[i], 3);
1315 if (!NT_STATUS_IS_OK(status)) {
1316 return smbd_smb2_request_error(req, status);
1318 } else if (opcode == SMB2_OP_CANCEL) {
1319 /* Cancel requests are allowed to skip the signing */
1320 } else if (req->session && req->session->do_signing) {
1321 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1324 if (flags & SMB2_HDR_FLAG_CHAINED) {
1326 * This check is mostly for giving the correct error code
1327 * for compounded requests.
1329 * TODO: we may need to move this after the session
1330 * and tcon checks.
1332 if (!NT_STATUS_IS_OK(req->next_status)) {
1333 return smbd_smb2_request_error(req, req->next_status);
1335 } else {
1336 req->compat_chain_fsp = NULL;
1339 if (req->compound_related) {
1340 req->sconn->smb2.compound_related_in_progress = true;
1343 switch (opcode) {
1344 case SMB2_OP_NEGPROT:
1345 /* This call needs to be run as root */
1346 change_to_root_user();
1349 START_PROFILE(smb2_negprot);
1350 return_value = smbd_smb2_request_process_negprot(req);
1351 END_PROFILE(smb2_negprot);
1353 break;
1355 case SMB2_OP_SESSSETUP:
1356 /* This call needs to be run as root */
1357 change_to_root_user();
1360 START_PROFILE(smb2_sesssetup);
1361 return_value = smbd_smb2_request_process_sesssetup(req);
1362 END_PROFILE(smb2_sesssetup);
1364 break;
1366 case SMB2_OP_LOGOFF:
1367 if (!NT_STATUS_IS_OK(session_status)) {
1368 return_value = smbd_smb2_request_error(req, session_status);
1369 break;
1372 /* This call needs to be run as root */
1373 change_to_root_user();
1376 START_PROFILE(smb2_logoff);
1377 return_value = smbd_smb2_request_process_logoff(req);
1378 END_PROFILE(smb2_logoff);
1380 break;
1382 case SMB2_OP_TCON:
1383 if (!NT_STATUS_IS_OK(session_status)) {
1384 return_value = smbd_smb2_request_error(req, session_status);
1385 break;
1389 * This call needs to be run as root.
1391 * smbd_smb2_request_process_tcon()
1392 * calls make_connection_snum(), which will call
1393 * change_to_user(), when needed.
1395 change_to_root_user();
1398 START_PROFILE(smb2_tcon);
1399 return_value = smbd_smb2_request_process_tcon(req);
1400 END_PROFILE(smb2_tcon);
1402 break;
1404 case SMB2_OP_TDIS:
1405 if (!NT_STATUS_IS_OK(session_status)) {
1406 return_value = smbd_smb2_request_error(req, session_status);
1407 break;
1410 * This call needs to be run as user.
1412 * smbd_smb2_request_check_tcon()
1413 * calls change_to_user() on success.
1415 status = smbd_smb2_request_check_tcon(req);
1416 if (!NT_STATUS_IS_OK(status)) {
1417 return_value = smbd_smb2_request_error(req, status);
1418 break;
1420 /* This call needs to be run as root */
1421 change_to_root_user();
1425 START_PROFILE(smb2_tdis);
1426 return_value = smbd_smb2_request_process_tdis(req);
1427 END_PROFILE(smb2_tdis);
1429 break;
1431 case SMB2_OP_CREATE:
1432 if (!NT_STATUS_IS_OK(session_status)) {
1433 return_value = smbd_smb2_request_error(req, session_status);
1434 break;
1437 * This call needs to be run as user.
1439 * smbd_smb2_request_check_tcon()
1440 * calls change_to_user() on success.
1442 status = smbd_smb2_request_check_tcon(req);
1443 if (!NT_STATUS_IS_OK(status)) {
1444 return_value = smbd_smb2_request_error(req, status);
1445 break;
1449 START_PROFILE(smb2_create);
1450 return_value = smbd_smb2_request_process_create(req);
1451 END_PROFILE(smb2_create);
1453 break;
1455 case SMB2_OP_CLOSE:
1456 if (!NT_STATUS_IS_OK(session_status)) {
1457 return_value = smbd_smb2_request_error(req, session_status);
1458 break;
1461 * This call needs to be run as user.
1463 * smbd_smb2_request_check_tcon()
1464 * calls change_to_user() on success.
1466 status = smbd_smb2_request_check_tcon(req);
1467 if (!NT_STATUS_IS_OK(status)) {
1468 return_value = smbd_smb2_request_error(req, status);
1469 break;
1473 START_PROFILE(smb2_close);
1474 return_value = smbd_smb2_request_process_close(req);
1475 END_PROFILE(smb2_close);
1477 break;
1479 case SMB2_OP_FLUSH:
1480 if (!NT_STATUS_IS_OK(session_status)) {
1481 return_value = smbd_smb2_request_error(req, session_status);
1482 break;
1485 * This call needs to be run as user.
1487 * smbd_smb2_request_check_tcon()
1488 * calls change_to_user() on success.
1490 status = smbd_smb2_request_check_tcon(req);
1491 if (!NT_STATUS_IS_OK(status)) {
1492 return_value = smbd_smb2_request_error(req, status);
1493 break;
1497 START_PROFILE(smb2_flush);
1498 return_value = smbd_smb2_request_process_flush(req);
1499 END_PROFILE(smb2_flush);
1501 break;
1503 case SMB2_OP_READ:
1504 if (!NT_STATUS_IS_OK(session_status)) {
1505 return_value = smbd_smb2_request_error(req, session_status);
1506 break;
1509 * This call needs to be run as user.
1511 * smbd_smb2_request_check_tcon()
1512 * calls change_to_user() on success.
1514 status = smbd_smb2_request_check_tcon(req);
1515 if (!NT_STATUS_IS_OK(status)) {
1516 return_value = smbd_smb2_request_error(req, status);
1517 break;
1521 START_PROFILE(smb2_read);
1522 return_value = smbd_smb2_request_process_read(req);
1523 END_PROFILE(smb2_read);
1525 break;
1527 case SMB2_OP_WRITE:
1528 if (!NT_STATUS_IS_OK(session_status)) {
1529 return_value = smbd_smb2_request_error(req, session_status);
1530 break;
1533 * This call needs to be run as user.
1535 * smbd_smb2_request_check_tcon()
1536 * calls change_to_user() on success.
1538 status = smbd_smb2_request_check_tcon(req);
1539 if (!NT_STATUS_IS_OK(status)) {
1540 return_value = smbd_smb2_request_error(req, status);
1541 break;
1545 START_PROFILE(smb2_write);
1546 return_value = smbd_smb2_request_process_write(req);
1547 END_PROFILE(smb2_write);
1549 break;
1551 case SMB2_OP_LOCK:
1552 if (!NT_STATUS_IS_OK(session_status)) {
1553 /* Too ugly to live ? JRA. */
1554 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1555 session_status = NT_STATUS_FILE_CLOSED;
1557 return_value = smbd_smb2_request_error(req, session_status);
1558 break;
1561 * This call needs to be run as user.
1563 * smbd_smb2_request_check_tcon()
1564 * calls change_to_user() on success.
1566 status = smbd_smb2_request_check_tcon(req);
1567 if (!NT_STATUS_IS_OK(status)) {
1568 /* Too ugly to live ? JRA. */
1569 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1570 status = NT_STATUS_FILE_CLOSED;
1572 return_value = smbd_smb2_request_error(req, status);
1573 break;
1577 START_PROFILE(smb2_lock);
1578 return_value = smbd_smb2_request_process_lock(req);
1579 END_PROFILE(smb2_lock);
1581 break;
1583 case SMB2_OP_IOCTL:
1584 if (!NT_STATUS_IS_OK(session_status)) {
1585 return_value = smbd_smb2_request_error(req, session_status);
1586 break;
1589 * This call needs to be run as user.
1591 * smbd_smb2_request_check_tcon()
1592 * calls change_to_user() on success.
1594 status = smbd_smb2_request_check_tcon(req);
1595 if (!NT_STATUS_IS_OK(status)) {
1596 return_value = smbd_smb2_request_error(req, status);
1597 break;
1601 START_PROFILE(smb2_ioctl);
1602 return_value = smbd_smb2_request_process_ioctl(req);
1603 END_PROFILE(smb2_ioctl);
1605 break;
1607 case SMB2_OP_CANCEL:
1609 * This call needs to be run as root
1611 * That is what we also do in the SMB1 case.
1613 change_to_root_user();
1616 START_PROFILE(smb2_cancel);
1617 return_value = smbd_smb2_request_process_cancel(req);
1618 END_PROFILE(smb2_cancel);
1620 break;
1622 case SMB2_OP_KEEPALIVE:
1623 /* This call needs to be run as root */
1624 change_to_root_user();
1627 START_PROFILE(smb2_keepalive);
1628 return_value = smbd_smb2_request_process_keepalive(req);
1629 END_PROFILE(smb2_keepalive);
1631 break;
1633 case SMB2_OP_FIND:
1634 if (!NT_STATUS_IS_OK(session_status)) {
1635 return_value = smbd_smb2_request_error(req, session_status);
1636 break;
1639 * This call needs to be run as user.
1641 * smbd_smb2_request_check_tcon()
1642 * calls change_to_user() on success.
1644 status = smbd_smb2_request_check_tcon(req);
1645 if (!NT_STATUS_IS_OK(status)) {
1646 return_value = smbd_smb2_request_error(req, status);
1647 break;
1651 START_PROFILE(smb2_find);
1652 return_value = smbd_smb2_request_process_find(req);
1653 END_PROFILE(smb2_find);
1655 break;
1657 case SMB2_OP_NOTIFY:
1658 if (!NT_STATUS_IS_OK(session_status)) {
1659 return_value = smbd_smb2_request_error(req, session_status);
1660 break;
1663 * This call needs to be run as user.
1665 * smbd_smb2_request_check_tcon()
1666 * calls change_to_user() on success.
1668 status = smbd_smb2_request_check_tcon(req);
1669 if (!NT_STATUS_IS_OK(status)) {
1670 return_value = smbd_smb2_request_error(req, status);
1671 break;
1675 START_PROFILE(smb2_notify);
1676 return_value = smbd_smb2_request_process_notify(req);
1677 END_PROFILE(smb2_notify);
1679 break;
1681 case SMB2_OP_GETINFO:
1682 if (!NT_STATUS_IS_OK(session_status)) {
1683 return_value = smbd_smb2_request_error(req, session_status);
1684 break;
1687 * This call needs to be run as user.
1689 * smbd_smb2_request_check_tcon()
1690 * calls change_to_user() on success.
1692 status = smbd_smb2_request_check_tcon(req);
1693 if (!NT_STATUS_IS_OK(status)) {
1694 return_value = smbd_smb2_request_error(req, status);
1695 break;
1699 START_PROFILE(smb2_getinfo);
1700 return_value = smbd_smb2_request_process_getinfo(req);
1701 END_PROFILE(smb2_getinfo);
1703 break;
1705 case SMB2_OP_SETINFO:
1706 if (!NT_STATUS_IS_OK(session_status)) {
1707 return_value = smbd_smb2_request_error(req, session_status);
1708 break;
1711 * This call needs to be run as user.
1713 * smbd_smb2_request_check_tcon()
1714 * calls change_to_user() on success.
1716 status = smbd_smb2_request_check_tcon(req);
1717 if (!NT_STATUS_IS_OK(status)) {
1718 return_value = smbd_smb2_request_error(req, status);
1719 break;
1723 START_PROFILE(smb2_setinfo);
1724 return_value = smbd_smb2_request_process_setinfo(req);
1725 END_PROFILE(smb2_setinfo);
1727 break;
1729 case SMB2_OP_BREAK:
1730 if (!NT_STATUS_IS_OK(session_status)) {
1731 return_value = smbd_smb2_request_error(req, session_status);
1732 break;
1735 * This call needs to be run as user.
1737 * smbd_smb2_request_check_tcon()
1738 * calls change_to_user() on success.
1740 status = smbd_smb2_request_check_tcon(req);
1741 if (!NT_STATUS_IS_OK(status)) {
1742 return_value = smbd_smb2_request_error(req, status);
1743 break;
1747 START_PROFILE(smb2_break);
1748 return_value = smbd_smb2_request_process_break(req);
1749 END_PROFILE(smb2_break);
1751 break;
1753 default:
1754 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1755 break;
1757 return return_value;
1760 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1762 struct tevent_req *subreq;
1763 int i = req->current_idx;
1765 req->subreq = NULL;
1767 req->current_idx += 3;
1769 if (req->current_idx < req->out.vector_count) {
1771 * We must process the remaining compound
1772 * SMB2 requests before any new incoming SMB2
1773 * requests. This is because incoming SMB2
1774 * requests may include a cancel for a
1775 * compound request we haven't processed
1776 * yet.
1778 struct tevent_immediate *im = tevent_create_immediate(req);
1779 if (!im) {
1780 return NT_STATUS_NO_MEMORY;
1782 tevent_schedule_immediate(im,
1783 req->sconn->smb2.event_ctx,
1784 smbd_smb2_request_dispatch_immediate,
1785 req);
1786 return NT_STATUS_OK;
1789 if (req->compound_related) {
1790 req->sconn->smb2.compound_related_in_progress = false;
1793 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1795 /* Set credit for these operations (zero credits if this
1796 is a final reply for an async operation). */
1797 smb2_calculate_credits(req, req);
1799 if (req->do_signing) {
1800 NTSTATUS status;
1801 status = smb2_signing_sign_pdu(req->session->session_key,
1802 &req->out.vector[i], 3);
1803 if (!NT_STATUS_IS_OK(status)) {
1804 return status;
1808 if (DEBUGLEVEL >= 10) {
1809 dbgtext("smbd_smb2_request_reply: sending...\n");
1810 print_req_vectors(req);
1813 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1814 if (req->out.vector_count == 4 &&
1815 req->out.vector[3].iov_base == NULL &&
1816 req->out.vector[3].iov_len != 0) {
1817 /* Dynamic part is NULL. Chop it off,
1818 We're going to send it via sendfile. */
1819 req->out.vector_count -= 1;
1822 subreq = tstream_writev_queue_send(req,
1823 req->sconn->smb2.event_ctx,
1824 req->sconn->smb2.stream,
1825 req->sconn->smb2.send_queue,
1826 req->out.vector,
1827 req->out.vector_count);
1828 if (subreq == NULL) {
1829 return NT_STATUS_NO_MEMORY;
1831 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1833 * We're done with this request -
1834 * move it off the "being processed" queue.
1836 DLIST_REMOVE(req->sconn->smb2.requests, req);
1838 return NT_STATUS_OK;
1841 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
1843 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1844 struct tevent_immediate *im,
1845 void *private_data)
1847 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1848 struct smbd_smb2_request);
1849 struct smbd_server_connection *sconn = req->sconn;
1850 NTSTATUS status;
1852 TALLOC_FREE(im);
1854 if (DEBUGLEVEL >= 10) {
1855 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1856 req->current_idx, req->in.vector_count));
1857 print_req_vectors(req);
1860 status = smbd_smb2_request_dispatch(req);
1861 if (!NT_STATUS_IS_OK(status)) {
1862 smbd_server_connection_terminate(sconn, nt_errstr(status));
1863 return;
1866 status = smbd_smb2_request_next_incoming(sconn);
1867 if (!NT_STATUS_IS_OK(status)) {
1868 smbd_server_connection_terminate(sconn, nt_errstr(status));
1869 return;
1873 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1875 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1876 struct smbd_smb2_request);
1877 struct smbd_server_connection *sconn = req->sconn;
1878 int ret;
1879 int sys_errno;
1880 NTSTATUS status;
1882 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1883 TALLOC_FREE(subreq);
1884 TALLOC_FREE(req);
1885 if (ret == -1) {
1886 status = map_nt_error_from_unix(sys_errno);
1887 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1888 nt_errstr(status)));
1889 smbd_server_connection_terminate(sconn, nt_errstr(status));
1890 return;
1893 status = smbd_smb2_request_next_incoming(sconn);
1894 if (!NT_STATUS_IS_OK(status)) {
1895 smbd_server_connection_terminate(sconn, nt_errstr(status));
1896 return;
1900 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1901 NTSTATUS status,
1902 DATA_BLOB body, DATA_BLOB *dyn,
1903 const char *location)
1905 uint8_t *outhdr;
1906 int i = req->current_idx;
1907 uint32_t next_command_ofs;
1909 DEBUG(10,("smbd_smb2_request_done_ex: "
1910 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1911 i, nt_errstr(status), (unsigned int)body.length,
1912 dyn ? "yes": "no",
1913 (unsigned int)(dyn ? dyn->length : 0),
1914 location));
1916 if (body.length < 2) {
1917 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1920 if ((body.length % 2) != 0) {
1921 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1924 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1926 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1927 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1929 req->out.vector[i+1].iov_base = (void *)body.data;
1930 req->out.vector[i+1].iov_len = body.length;
1932 if (dyn) {
1933 req->out.vector[i+2].iov_base = (void *)dyn->data;
1934 req->out.vector[i+2].iov_len = dyn->length;
1935 } else {
1936 req->out.vector[i+2].iov_base = NULL;
1937 req->out.vector[i+2].iov_len = 0;
1940 /* see if we need to recalculate the offset to the next response */
1941 if (next_command_ofs > 0) {
1942 next_command_ofs = SMB2_HDR_BODY;
1943 next_command_ofs += req->out.vector[i+1].iov_len;
1944 next_command_ofs += req->out.vector[i+2].iov_len;
1947 if ((next_command_ofs % 8) != 0) {
1948 size_t pad_size = 8 - (next_command_ofs % 8);
1949 if (req->out.vector[i+2].iov_len == 0) {
1951 * if the dyn buffer is empty
1952 * we can use it to add padding
1954 uint8_t *pad;
1956 pad = talloc_zero_array(req->out.vector,
1957 uint8_t, pad_size);
1958 if (pad == NULL) {
1959 return smbd_smb2_request_error(req,
1960 NT_STATUS_NO_MEMORY);
1963 req->out.vector[i+2].iov_base = (void *)pad;
1964 req->out.vector[i+2].iov_len = pad_size;
1965 } else {
1967 * For now we copy the dynamic buffer
1968 * and add the padding to the new buffer
1970 size_t old_size;
1971 uint8_t *old_dyn;
1972 size_t new_size;
1973 uint8_t *new_dyn;
1975 old_size = req->out.vector[i+2].iov_len;
1976 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
1978 new_size = old_size + pad_size;
1979 new_dyn = talloc_zero_array(req->out.vector,
1980 uint8_t, new_size);
1981 if (new_dyn == NULL) {
1982 return smbd_smb2_request_error(req,
1983 NT_STATUS_NO_MEMORY);
1986 memcpy(new_dyn, old_dyn, old_size);
1987 memset(new_dyn + old_size, 0, pad_size);
1989 req->out.vector[i+2].iov_base = (void *)new_dyn;
1990 req->out.vector[i+2].iov_len = new_size;
1992 next_command_ofs += pad_size;
1995 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1997 return smbd_smb2_request_reply(req);
2000 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2001 NTSTATUS status,
2002 DATA_BLOB *info,
2003 const char *location)
2005 DATA_BLOB body;
2006 int i = req->current_idx;
2007 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
2009 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2010 i, nt_errstr(status), info ? " +info" : "",
2011 location));
2013 body.data = outhdr + SMB2_HDR_BODY;
2014 body.length = 8;
2015 SSVAL(body.data, 0, 9);
2017 if (info) {
2018 SIVAL(body.data, 0x04, info->length);
2019 } else {
2020 /* Allocated size of req->out.vector[i].iov_base
2021 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2022 * 1 byte without having to do an alloc.
2024 info = talloc_zero_array(req->out.vector,
2025 DATA_BLOB,
2027 if (!info) {
2028 return NT_STATUS_NO_MEMORY;
2030 info->data = ((uint8_t *)outhdr) +
2031 OUTVEC_ALLOC_SIZE - 1;
2032 info->length = 1;
2033 SCVAL(info->data, 0, 0);
2037 * if a request fails, all other remaining
2038 * compounded requests should fail too
2040 req->next_status = NT_STATUS_INVALID_PARAMETER;
2042 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2046 struct smbd_smb2_send_oplock_break_state {
2047 struct smbd_server_connection *sconn;
2048 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2049 struct iovec vector;
2052 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2054 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2055 uint64_t file_id_persistent,
2056 uint64_t file_id_volatile,
2057 uint8_t oplock_level)
2059 struct smbd_smb2_send_oplock_break_state *state;
2060 struct tevent_req *subreq;
2061 uint8_t *hdr;
2062 uint8_t *body;
2064 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2065 if (state == NULL) {
2066 return NT_STATUS_NO_MEMORY;
2068 state->sconn = sconn;
2070 state->vector.iov_base = (void *)state->buf;
2071 state->vector.iov_len = sizeof(state->buf);
2073 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2074 hdr = state->buf + 4;
2075 body = hdr + SMB2_HDR_BODY;
2077 SIVAL(hdr, 0, SMB2_MAGIC);
2078 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2079 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2080 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2081 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2082 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2083 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2084 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2085 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2086 SIVAL(hdr, SMB2_HDR_PID, 0);
2087 SIVAL(hdr, SMB2_HDR_TID, 0);
2088 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2089 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2091 SSVAL(body, 0x00, 0x18);
2093 SCVAL(body, 0x02, oplock_level);
2094 SCVAL(body, 0x03, 0); /* reserved */
2095 SIVAL(body, 0x04, 0); /* reserved */
2096 SBVAL(body, 0x08, file_id_persistent);
2097 SBVAL(body, 0x10, file_id_volatile);
2099 subreq = tstream_writev_queue_send(state,
2100 sconn->smb2.event_ctx,
2101 sconn->smb2.stream,
2102 sconn->smb2.send_queue,
2103 &state->vector, 1);
2104 if (subreq == NULL) {
2105 return NT_STATUS_NO_MEMORY;
2107 tevent_req_set_callback(subreq,
2108 smbd_smb2_oplock_break_writev_done,
2109 state);
2111 return NT_STATUS_OK;
2114 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2116 struct smbd_smb2_send_oplock_break_state *state =
2117 tevent_req_callback_data(subreq,
2118 struct smbd_smb2_send_oplock_break_state);
2119 struct smbd_server_connection *sconn = state->sconn;
2120 int ret;
2121 int sys_errno;
2123 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2124 TALLOC_FREE(subreq);
2125 if (ret == -1) {
2126 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2127 smbd_server_connection_terminate(sconn, nt_errstr(status));
2128 return;
2131 TALLOC_FREE(state);
2134 struct smbd_smb2_request_read_state {
2135 size_t missing;
2136 bool asked_for_header;
2137 struct smbd_smb2_request *smb2_req;
2140 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2141 void *private_data,
2142 TALLOC_CTX *mem_ctx,
2143 struct iovec **_vector,
2144 size_t *_count);
2145 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2147 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2148 struct tevent_context *ev,
2149 struct smbd_server_connection *sconn)
2151 struct tevent_req *req;
2152 struct smbd_smb2_request_read_state *state;
2153 struct tevent_req *subreq;
2155 req = tevent_req_create(mem_ctx, &state,
2156 struct smbd_smb2_request_read_state);
2157 if (req == NULL) {
2158 return NULL;
2160 state->missing = 0;
2161 state->asked_for_header = false;
2163 state->smb2_req = smbd_smb2_request_allocate(state);
2164 if (tevent_req_nomem(state->smb2_req, req)) {
2165 return tevent_req_post(req, ev);
2167 state->smb2_req->sconn = sconn;
2169 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2170 sconn->smb2.recv_queue,
2171 smbd_smb2_request_next_vector,
2172 state);
2173 if (tevent_req_nomem(subreq, req)) {
2174 return tevent_req_post(req, ev);
2176 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2178 return req;
2181 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2182 void *private_data,
2183 TALLOC_CTX *mem_ctx,
2184 struct iovec **_vector,
2185 size_t *_count)
2187 struct smbd_smb2_request_read_state *state =
2188 talloc_get_type_abort(private_data,
2189 struct smbd_smb2_request_read_state);
2190 struct smbd_smb2_request *req = state->smb2_req;
2191 struct iovec *vector;
2192 int idx = req->in.vector_count;
2193 size_t len = 0;
2194 uint8_t *buf = NULL;
2196 if (req->in.vector_count == 0) {
2198 * first we need to get the NBT header
2200 req->in.vector = talloc_array(req, struct iovec,
2201 req->in.vector_count + 1);
2202 if (req->in.vector == NULL) {
2203 return -1;
2205 req->in.vector_count += 1;
2207 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2208 req->in.vector[idx].iov_len = 4;
2210 vector = talloc_array(mem_ctx, struct iovec, 1);
2211 if (vector == NULL) {
2212 return -1;
2215 vector[0] = req->in.vector[idx];
2217 *_vector = vector;
2218 *_count = 1;
2219 return 0;
2222 if (req->in.vector_count == 1) {
2224 * Now we analyze the NBT header
2226 state->missing = smb2_len(req->in.vector[0].iov_base);
2228 if (state->missing == 0) {
2229 /* if there're no remaining bytes, we're done */
2230 *_vector = NULL;
2231 *_count = 0;
2232 return 0;
2235 req->in.vector = talloc_realloc(req, req->in.vector,
2236 struct iovec,
2237 req->in.vector_count + 1);
2238 if (req->in.vector == NULL) {
2239 return -1;
2241 req->in.vector_count += 1;
2243 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2245 * it's a special NBT message,
2246 * so get all remaining bytes
2248 len = state->missing;
2249 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2251 * it's an invalid message, just read what we can get
2252 * and let the caller handle the error
2254 len = state->missing;
2255 } else {
2257 * We assume it's a SMB2 request,
2258 * and we first get the header and the
2259 * first 2 bytes (the struct size) of the body
2261 len = SMB2_HDR_BODY + 2;
2263 state->asked_for_header = true;
2266 state->missing -= len;
2268 buf = talloc_array(req->in.vector, uint8_t, len);
2269 if (buf == NULL) {
2270 return -1;
2273 req->in.vector[idx].iov_base = (void *)buf;
2274 req->in.vector[idx].iov_len = len;
2276 vector = talloc_array(mem_ctx, struct iovec, 1);
2277 if (vector == NULL) {
2278 return -1;
2281 vector[0] = req->in.vector[idx];
2283 *_vector = vector;
2284 *_count = 1;
2285 return 0;
2288 if (state->missing == 0) {
2289 /* if there're no remaining bytes, we're done */
2290 *_vector = NULL;
2291 *_count = 0;
2292 return 0;
2295 if (state->asked_for_header) {
2296 const uint8_t *hdr;
2297 size_t full_size;
2298 size_t next_command_ofs;
2299 size_t body_size;
2300 uint8_t *body;
2301 size_t dyn_size;
2302 uint8_t *dyn;
2303 bool invalid = false;
2305 state->asked_for_header = false;
2308 * We got the SMB2 header and the first 2 bytes
2309 * of the body. We fix the size to just the header
2310 * and manually copy the 2 first bytes to the body section
2312 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2313 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2315 /* allocate vectors for body and dynamic areas */
2316 req->in.vector = talloc_realloc(req, req->in.vector,
2317 struct iovec,
2318 req->in.vector_count + 2);
2319 if (req->in.vector == NULL) {
2320 return -1;
2322 req->in.vector_count += 2;
2324 full_size = state->missing + SMB2_HDR_BODY + 2;
2325 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2326 body_size = SVAL(hdr, SMB2_HDR_BODY);
2328 if (next_command_ofs != 0) {
2329 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2331 * this is invalid, just return a zero
2332 * body and let the caller deal with the error
2334 invalid = true;
2335 } else if (next_command_ofs > full_size) {
2337 * this is invalid, just return a zero
2338 * body and let the caller deal with the error
2340 invalid = true;
2341 } else {
2342 full_size = next_command_ofs;
2346 if (!invalid) {
2347 if (body_size < 2) {
2349 * this is invalid, just return a zero
2350 * body and let the caller deal with the error
2352 invalid = true;
2355 if ((body_size % 2) != 0) {
2356 body_size -= 1;
2359 if (body_size > (full_size - SMB2_HDR_BODY)) {
2361 * this is invalid, just return a zero
2362 * body and let the caller deal with the error
2364 invalid = true;
2368 if (invalid) {
2369 /* the caller should check this */
2370 body_size = 2;
2373 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2375 state->missing -= (body_size - 2) + dyn_size;
2377 body = talloc_array(req->in.vector, uint8_t, body_size);
2378 if (body == NULL) {
2379 return -1;
2382 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2383 if (dyn == NULL) {
2384 return -1;
2387 req->in.vector[idx].iov_base = (void *)body;
2388 req->in.vector[idx].iov_len = body_size;
2389 req->in.vector[idx+1].iov_base = (void *)dyn;
2390 req->in.vector[idx+1].iov_len = dyn_size;
2392 vector = talloc_array(mem_ctx, struct iovec, 2);
2393 if (vector == NULL) {
2394 return -1;
2398 * the first 2 bytes of the body were already fetched
2399 * together with the header
2401 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2402 vector[0].iov_base = body + 2;
2403 vector[0].iov_len = body_size - 2;
2405 vector[1] = req->in.vector[idx+1];
2407 *_vector = vector;
2408 *_count = 2;
2409 return 0;
2413 * when we endup here, we're looking for a new SMB2 request
2414 * next. And we ask for its header and the first 2 bytes of
2415 * the body (like we did for the first SMB2 request).
2418 req->in.vector = talloc_realloc(req, req->in.vector,
2419 struct iovec,
2420 req->in.vector_count + 1);
2421 if (req->in.vector == NULL) {
2422 return -1;
2424 req->in.vector_count += 1;
2427 * We assume it's a SMB2 request,
2428 * and we first get the header and the
2429 * first 2 bytes (the struct size) of the body
2431 len = SMB2_HDR_BODY + 2;
2433 if (len > state->missing) {
2434 /* let the caller handle the error */
2435 len = state->missing;
2438 state->missing -= len;
2439 state->asked_for_header = true;
2441 buf = talloc_array(req->in.vector, uint8_t, len);
2442 if (buf == NULL) {
2443 return -1;
2446 req->in.vector[idx].iov_base = (void *)buf;
2447 req->in.vector[idx].iov_len = len;
2449 vector = talloc_array(mem_ctx, struct iovec, 1);
2450 if (vector == NULL) {
2451 return -1;
2454 vector[0] = req->in.vector[idx];
2456 *_vector = vector;
2457 *_count = 1;
2458 return 0;
2461 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2463 struct tevent_req *req =
2464 tevent_req_callback_data(subreq,
2465 struct tevent_req);
2466 int ret;
2467 int sys_errno;
2468 NTSTATUS status;
2470 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2471 if (ret == -1) {
2472 status = map_nt_error_from_unix(sys_errno);
2473 tevent_req_nterror(req, status);
2474 return;
2477 tevent_req_done(req);
2480 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2481 TALLOC_CTX *mem_ctx,
2482 struct smbd_smb2_request **_smb2_req)
2484 struct smbd_smb2_request_read_state *state =
2485 tevent_req_data(req,
2486 struct smbd_smb2_request_read_state);
2487 NTSTATUS status;
2489 if (tevent_req_is_nterror(req, &status)) {
2490 tevent_req_received(req);
2491 return status;
2494 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2495 *_smb2_req = state->smb2_req;
2496 tevent_req_received(req);
2497 return NT_STATUS_OK;
2500 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2502 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2504 size_t max_send_queue_len;
2505 size_t cur_send_queue_len;
2506 struct tevent_req *subreq;
2508 if (sconn->smb2.compound_related_in_progress) {
2510 * Can't read another until the related
2511 * compound is done.
2513 return NT_STATUS_OK;
2516 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2518 * if there is already a smbd_smb2_request_read
2519 * pending, we are done.
2521 return NT_STATUS_OK;
2524 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2525 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2527 if (cur_send_queue_len > max_send_queue_len) {
2529 * if we have a lot of requests to send,
2530 * we wait until they are on the wire until we
2531 * ask for the next request.
2533 return NT_STATUS_OK;
2536 /* ask for the next request */
2537 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2538 if (subreq == NULL) {
2539 return NT_STATUS_NO_MEMORY;
2541 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2543 return NT_STATUS_OK;
2546 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2547 const uint8_t *inbuf, size_t size)
2549 NTSTATUS status;
2550 struct smbd_smb2_request *req = NULL;
2552 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2553 (unsigned int)size));
2555 status = smbd_initialize_smb2(sconn);
2556 if (!NT_STATUS_IS_OK(status)) {
2557 smbd_server_connection_terminate(sconn, nt_errstr(status));
2558 return;
2561 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2562 if (!NT_STATUS_IS_OK(status)) {
2563 smbd_server_connection_terminate(sconn, nt_errstr(status));
2564 return;
2567 status = smbd_smb2_request_validate(req);
2568 if (!NT_STATUS_IS_OK(status)) {
2569 smbd_server_connection_terminate(sconn, nt_errstr(status));
2570 return;
2573 status = smbd_smb2_request_setup_out(req);
2574 if (!NT_STATUS_IS_OK(status)) {
2575 smbd_server_connection_terminate(sconn, nt_errstr(status));
2576 return;
2579 status = smbd_smb2_request_dispatch(req);
2580 if (!NT_STATUS_IS_OK(status)) {
2581 smbd_server_connection_terminate(sconn, nt_errstr(status));
2582 return;
2585 status = smbd_smb2_request_next_incoming(sconn);
2586 if (!NT_STATUS_IS_OK(status)) {
2587 smbd_server_connection_terminate(sconn, nt_errstr(status));
2588 return;
2591 sconn->num_requests++;
2594 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2596 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2597 struct smbd_server_connection);
2598 NTSTATUS status;
2599 struct smbd_smb2_request *req = NULL;
2601 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2602 TALLOC_FREE(subreq);
2603 if (!NT_STATUS_IS_OK(status)) {
2604 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2605 nt_errstr(status)));
2606 smbd_server_connection_terminate(sconn, nt_errstr(status));
2607 return;
2610 if (req->in.nbt_hdr[0] != 0x00) {
2611 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2612 req->in.nbt_hdr[0]));
2613 TALLOC_FREE(req);
2614 goto next;
2617 req->current_idx = 1;
2619 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2620 req->current_idx, req->in.vector_count));
2622 status = smbd_smb2_request_validate(req);
2623 if (!NT_STATUS_IS_OK(status)) {
2624 smbd_server_connection_terminate(sconn, nt_errstr(status));
2625 return;
2628 status = smbd_smb2_request_setup_out(req);
2629 if (!NT_STATUS_IS_OK(status)) {
2630 smbd_server_connection_terminate(sconn, nt_errstr(status));
2631 return;
2634 status = smbd_smb2_request_dispatch(req);
2635 if (!NT_STATUS_IS_OK(status)) {
2636 smbd_server_connection_terminate(sconn, nt_errstr(status));
2637 return;
2640 next:
2641 status = smbd_smb2_request_next_incoming(sconn);
2642 if (!NT_STATUS_IS_OK(status)) {
2643 smbd_server_connection_terminate(sconn, nt_errstr(status));
2644 return;
2647 sconn->num_requests++;
2649 /* The timeout_processing function isn't run nearly
2650 often enough to implement 'max log size' without
2651 overrunning the size of the file by many megabytes.
2652 This is especially true if we are running at debug
2653 level 10. Checking every 50 SMB2s is a nice
2654 tradeoff of performance vs log file size overrun. */
2656 if ((sconn->num_requests % 50) == 0 &&
2657 need_to_check_log_size()) {
2658 change_to_root_user();
2659 check_log_size();