s3:smb2_server: split out a smb2_validate_sequence_number() function
[Samba.git] / source3 / smbd / smb2_server.c
blobbbb342b018f97a249c4d4a31e9b2d81dd32fe508
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 if (sconn->smb2.credits_granted == 0) {
379 DEBUG(0,("smb2_validate_message_id: client used more "
380 "credits than granted message_id (%llu)\n",
381 (unsigned long long)message_id));
382 return false;
385 DEBUG(11, ("smb2_validate_message_id: mid %llu, credits_granted %llu, "
386 "max_credits %llu, seqnum_low: %llu\n",
387 (unsigned long long) message_id,
388 (unsigned long long) sconn->smb2.credits_granted,
389 (unsigned long long) sconn->smb2.max_credits,
390 (unsigned long long) sconn->smb2.seqnum_low));
392 ok = smb2_validate_sequence_number(sconn, message_id, message_id);
393 if (!ok) {
394 return false;
397 /* substract used credits */
398 sconn->smb2.credits_granted -= 1;
400 return true;
403 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
405 int count;
406 int idx;
408 count = req->in.vector_count;
410 if (count < 4) {
411 /* It's not a SMB2 request */
412 return NT_STATUS_INVALID_PARAMETER;
415 for (idx=1; idx < count; idx += 3) {
416 const uint8_t *inhdr = NULL;
417 uint32_t flags;
419 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
420 return NT_STATUS_INVALID_PARAMETER;
423 if (req->in.vector[idx+1].iov_len < 2) {
424 return NT_STATUS_INVALID_PARAMETER;
427 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
429 /* Check the SMB2 header */
430 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
431 return NT_STATUS_INVALID_PARAMETER;
434 if (!smb2_validate_message_id(req->sconn, inhdr)) {
435 return NT_STATUS_INVALID_PARAMETER;
438 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
439 if (idx == 1) {
441 * the 1st request should never have the
442 * SMB2_HDR_FLAG_CHAINED flag set
444 if (flags & SMB2_HDR_FLAG_CHAINED) {
445 req->next_status = NT_STATUS_INVALID_PARAMETER;
446 return NT_STATUS_OK;
448 } else if (idx == 4) {
450 * the 2nd request triggers related vs. unrelated
451 * compounded requests
453 if (flags & SMB2_HDR_FLAG_CHAINED) {
454 req->compound_related = true;
456 } else if (idx > 4) {
457 #if 0
459 * It seems the this tests are wrong
460 * see the SMB2-COMPOUND test
464 * all other requests should match the 2nd one
466 if (flags & SMB2_HDR_FLAG_CHAINED) {
467 if (!req->compound_related) {
468 req->next_status =
469 NT_STATUS_INVALID_PARAMETER;
470 return NT_STATUS_OK;
472 } else {
473 if (req->compound_related) {
474 req->next_status =
475 NT_STATUS_INVALID_PARAMETER;
476 return NT_STATUS_OK;
479 #endif
483 return NT_STATUS_OK;
486 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
487 const struct iovec *in_vector,
488 struct iovec *out_vector)
490 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
491 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
492 uint16_t credits_requested;
493 uint32_t out_flags;
494 uint16_t credits_granted = 0;
496 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
497 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
499 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
501 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
503 * In case we already send an async interim
504 * response, we should not grant
505 * credits on the final response.
507 credits_requested = 0;
510 if (credits_requested) {
511 uint16_t modified_credits_requested;
512 uint32_t multiplier;
515 * Split up max_credits into 1/16ths, and then scale
516 * the requested credits by how many 16ths have been
517 * currently granted. Less than 1/16th == grant all
518 * requested (100%), scale down as more have been
519 * granted. Never ask for less than 1 as the client
520 * asked for at least 1. JRA.
523 multiplier = 16 - (((sconn->smb2.credits_granted * 16) / sconn->smb2.max_credits) % 16);
525 modified_credits_requested = (multiplier * credits_requested) / 16;
526 if (modified_credits_requested == 0) {
527 modified_credits_requested = 1;
530 /* Remember what we gave out. */
531 credits_granted = MIN(modified_credits_requested,
532 (sconn->smb2.max_credits - sconn->smb2.credits_granted));
535 if (credits_granted == 0 && sconn->smb2.credits_granted == 0) {
536 /* First negprot packet, or ensure the client credits can
537 never drop to zero. */
538 credits_granted = 1;
541 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
542 sconn->smb2.credits_granted += credits_granted;
544 DEBUG(10,("smb2_set_operation_credit: requested %u, "
545 "granted %u, total granted %u\n",
546 (unsigned int)credits_requested,
547 (unsigned int)credits_granted,
548 (unsigned int)sconn->smb2.credits_granted ));
551 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
552 struct smbd_smb2_request *outreq)
554 int count, idx;
555 uint16_t total_credits = 0;
557 count = outreq->out.vector_count;
559 for (idx=1; idx < count; idx += 3) {
560 uint8_t *outhdr = (uint8_t *)outreq->out.vector[idx].iov_base;
561 smb2_set_operation_credit(outreq->sconn,
562 &inreq->in.vector[idx],
563 &outreq->out.vector[idx]);
564 /* To match Windows, count up what we
565 just granted. */
566 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
567 /* Set to zero in all but the last reply. */
568 if (idx + 3 < count) {
569 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
570 } else {
571 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
576 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
578 struct iovec *vector;
579 int count;
580 int idx;
582 count = req->in.vector_count;
583 vector = talloc_zero_array(req, struct iovec, count);
584 if (vector == NULL) {
585 return NT_STATUS_NO_MEMORY;
588 vector[0].iov_base = req->out.nbt_hdr;
589 vector[0].iov_len = 4;
590 SIVAL(req->out.nbt_hdr, 0, 0);
592 for (idx=1; idx < count; idx += 3) {
593 const uint8_t *inhdr = NULL;
594 uint32_t in_flags;
595 uint8_t *outhdr = NULL;
596 uint8_t *outbody = NULL;
597 uint32_t next_command_ofs = 0;
598 struct iovec *current = &vector[idx];
600 if ((idx + 3) < count) {
601 /* we have a next command -
602 * setup for the error case. */
603 next_command_ofs = SMB2_HDR_BODY + 9;
606 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
607 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
609 outhdr = talloc_zero_array(vector, uint8_t,
610 OUTVEC_ALLOC_SIZE);
611 if (outhdr == NULL) {
612 return NT_STATUS_NO_MEMORY;
615 outbody = outhdr + SMB2_HDR_BODY;
617 current[0].iov_base = (void *)outhdr;
618 current[0].iov_len = SMB2_HDR_BODY;
620 current[1].iov_base = (void *)outbody;
621 current[1].iov_len = 8;
623 current[2].iov_base = NULL;
624 current[2].iov_len = 0;
626 /* setup the SMB2 header */
627 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
628 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
629 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
630 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
631 SIVAL(outhdr, SMB2_HDR_STATUS,
632 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
633 SSVAL(outhdr, SMB2_HDR_OPCODE,
634 SVAL(inhdr, SMB2_HDR_OPCODE));
635 SIVAL(outhdr, SMB2_HDR_FLAGS,
636 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
637 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
638 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
639 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
640 SIVAL(outhdr, SMB2_HDR_PID,
641 IVAL(inhdr, SMB2_HDR_PID));
642 SIVAL(outhdr, SMB2_HDR_TID,
643 IVAL(inhdr, SMB2_HDR_TID));
644 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
645 BVAL(inhdr, SMB2_HDR_SESSION_ID));
646 memcpy(outhdr + SMB2_HDR_SIGNATURE,
647 inhdr + SMB2_HDR_SIGNATURE, 16);
649 /* setup error body header */
650 SSVAL(outbody, 0x00, 0x08 + 1);
651 SSVAL(outbody, 0x02, 0);
652 SIVAL(outbody, 0x04, 0);
655 req->out.vector = vector;
656 req->out.vector_count = count;
658 /* setup the length of the NBT packet */
659 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
661 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
663 return NT_STATUS_OK;
666 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
667 const char *reason,
668 const char *location)
670 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
671 reason, location));
672 exit_server_cleanly(reason);
675 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
676 struct iovec *outvec,
677 const struct iovec *srcvec)
679 /* vec[0] is always boilerplate and must
680 * be allocated with size OUTVEC_ALLOC_SIZE. */
682 outvec[0].iov_base = talloc_memdup(ctx,
683 srcvec[0].iov_base,
684 OUTVEC_ALLOC_SIZE);
685 if (!outvec[0].iov_base) {
686 return false;
688 outvec[0].iov_len = SMB2_HDR_BODY;
691 * If this is a "standard" vec[1] of length 8,
692 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
693 * then duplicate this. Else use talloc_memdup().
696 if (srcvec[1].iov_len == 8 &&
697 srcvec[1].iov_base ==
698 ((uint8_t *)srcvec[0].iov_base) +
699 SMB2_HDR_BODY) {
700 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
701 SMB2_HDR_BODY;
702 outvec[1].iov_len = 8;
703 } else {
704 outvec[1].iov_base = talloc_memdup(ctx,
705 srcvec[1].iov_base,
706 srcvec[1].iov_len);
707 if (!outvec[1].iov_base) {
708 return false;
710 outvec[1].iov_len = srcvec[1].iov_len;
714 * If this is a "standard" vec[2] of length 1,
715 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
716 * then duplicate this. Else use talloc_memdup().
719 if (srcvec[2].iov_base &&
720 srcvec[2].iov_len) {
721 if (srcvec[2].iov_base ==
722 ((uint8_t *)srcvec[0].iov_base) +
723 (OUTVEC_ALLOC_SIZE - 1) &&
724 srcvec[2].iov_len == 1) {
725 /* Common SMB2 error packet case. */
726 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
727 (OUTVEC_ALLOC_SIZE - 1);
728 } else {
729 outvec[2].iov_base = talloc_memdup(ctx,
730 srcvec[2].iov_base,
731 srcvec[2].iov_len);
732 if (!outvec[2].iov_base) {
733 return false;
736 outvec[2].iov_len = srcvec[2].iov_len;
737 } else {
738 outvec[2].iov_base = NULL;
739 outvec[2].iov_len = 0;
741 return true;
744 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
746 struct smbd_smb2_request *newreq = NULL;
747 struct iovec *outvec = NULL;
748 int count = req->out.vector_count;
749 int i;
751 newreq = smbd_smb2_request_allocate(req->sconn);
752 if (!newreq) {
753 return NULL;
756 newreq->sconn = req->sconn;
757 newreq->session = req->session;
758 newreq->do_signing = req->do_signing;
759 newreq->current_idx = req->current_idx;
760 newreq->async = false;
761 newreq->cancelled = false;
762 /* Note we are leaving:
763 ->tcon
764 ->smb1req
765 ->compat_chain_fsp
766 uninitialized as NULL here as
767 they're not used in the interim
768 response code. JRA. */
770 outvec = talloc_zero_array(newreq, struct iovec, count);
771 if (!outvec) {
772 TALLOC_FREE(newreq);
773 return NULL;
775 newreq->out.vector = outvec;
776 newreq->out.vector_count = count;
778 /* Setup the outvec's identically to req. */
779 outvec[0].iov_base = newreq->out.nbt_hdr;
780 outvec[0].iov_len = 4;
781 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
783 /* Setup the vectors identically to the ones in req. */
784 for (i = 1; i < count; i += 3) {
785 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
786 break;
790 if (i < count) {
791 /* Alloc failed. */
792 TALLOC_FREE(newreq);
793 return NULL;
796 smb2_setup_nbt_length(newreq->out.vector,
797 newreq->out.vector_count);
799 return newreq;
802 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
804 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
806 int i = 0;
807 uint8_t *outhdr = NULL;
808 struct smbd_smb2_request *nreq = NULL;
810 /* Create a new smb2 request we'll use
811 for the interim return. */
812 nreq = dup_smb2_req(req);
813 if (!nreq) {
814 return NT_STATUS_NO_MEMORY;
817 /* Lose the last 3 out vectors. They're the
818 ones we'll be using for the async reply. */
819 nreq->out.vector_count -= 3;
821 smb2_setup_nbt_length(nreq->out.vector,
822 nreq->out.vector_count);
824 /* Step back to the previous reply. */
825 i = nreq->current_idx - 3;
826 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
827 /* And end the chain. */
828 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
830 /* Calculate outgoing credits */
831 smb2_calculate_credits(req, nreq);
833 /* Re-sign if needed. */
834 if (nreq->do_signing) {
835 NTSTATUS status;
836 status = smb2_signing_sign_pdu(nreq->session->session_key,
837 &nreq->out.vector[i], 3);
838 if (!NT_STATUS_IS_OK(status)) {
839 return status;
842 if (DEBUGLEVEL >= 10) {
843 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
844 (unsigned int)nreq->current_idx );
845 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
846 (unsigned int)nreq->out.vector_count );
847 print_req_vectors(nreq);
849 nreq->subreq = tstream_writev_queue_send(nreq,
850 nreq->sconn->smb2.event_ctx,
851 nreq->sconn->smb2.stream,
852 nreq->sconn->smb2.send_queue,
853 nreq->out.vector,
854 nreq->out.vector_count);
856 if (nreq->subreq == NULL) {
857 return NT_STATUS_NO_MEMORY;
860 tevent_req_set_callback(nreq->subreq,
861 smbd_smb2_request_writev_done,
862 nreq);
864 return NT_STATUS_OK;
867 struct smbd_smb2_request_pending_state {
868 struct smbd_server_connection *sconn;
869 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
870 struct iovec vector[3];
873 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
875 struct smbd_smb2_request_pending_state *state =
876 tevent_req_callback_data(subreq,
877 struct smbd_smb2_request_pending_state);
878 struct smbd_server_connection *sconn = state->sconn;
879 int ret;
880 int sys_errno;
882 ret = tstream_writev_queue_recv(subreq, &sys_errno);
883 TALLOC_FREE(subreq);
884 if (ret == -1) {
885 NTSTATUS status = map_nt_error_from_unix(sys_errno);
886 smbd_server_connection_terminate(sconn, nt_errstr(status));
887 return;
890 TALLOC_FREE(state);
893 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
894 struct tevent_req *subreq)
896 NTSTATUS status;
897 struct smbd_smb2_request_pending_state *state = NULL;
898 int i = req->current_idx;
899 uint8_t *reqhdr = NULL;
900 uint8_t *hdr = NULL;
901 uint8_t *body = NULL;
902 uint32_t flags = 0;
903 uint64_t message_id = 0;
904 uint64_t async_id = 0;
905 struct iovec *outvec = NULL;
907 if (!tevent_req_is_in_progress(subreq)) {
908 return NT_STATUS_OK;
911 req->subreq = subreq;
912 subreq = NULL;
914 if (req->async) {
915 /* We're already async. */
916 return NT_STATUS_OK;
919 if (req->in.vector_count > i + 3) {
921 * We're trying to go async in a compound
922 * request chain. This is not allowed.
923 * Cancel the outstanding request.
925 tevent_req_cancel(req->subreq);
926 return smbd_smb2_request_error(req,
927 NT_STATUS_INSUFFICIENT_RESOURCES);
930 if (DEBUGLEVEL >= 10) {
931 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
932 (unsigned int)req->current_idx );
933 print_req_vectors(req);
936 if (req->out.vector_count > 4) {
937 /* This is a compound reply. We
938 * must do an interim response
939 * followed by the async response
940 * to match W2K8R2.
942 status = smb2_send_async_interim_response(req);
943 if (!NT_STATUS_IS_OK(status)) {
944 return status;
948 * We're splitting off the last SMB2
949 * request in a compound set, and the
950 * smb2_send_async_interim_response()
951 * call above just sent all the replies
952 * for the previous SMB2 requests in
953 * this compound set. So we're no longer
954 * in the "compound_related_in_progress"
955 * state, and this is no longer a compound
956 * request.
958 req->compound_related = false;
959 req->sconn->smb2.compound_related_in_progress = false;
962 /* Don't return an intermediate packet on a pipe read/write. */
963 if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
964 goto ipc_out;
967 reqhdr = (uint8_t *)req->out.vector[i].iov_base;
968 flags = (IVAL(reqhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
969 message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
970 async_id = message_id; /* keep it simple for now... */
973 * What we send is identical to a smbd_smb2_request_error
974 * packet with an error status of STATUS_PENDING. Make use
975 * of this fact sometime when refactoring. JRA.
978 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
979 if (state == NULL) {
980 return NT_STATUS_NO_MEMORY;
982 state->sconn = req->sconn;
984 state->vector[0].iov_base = (void *)state->buf;
985 state->vector[0].iov_len = 4;
987 state->vector[1].iov_base = state->buf + 4;
988 state->vector[1].iov_len = SMB2_HDR_BODY;
990 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
991 state->vector[2].iov_len = 9;
993 smb2_setup_nbt_length(state->vector, 3);
995 hdr = (uint8_t *)state->vector[1].iov_base;
996 body = (uint8_t *)state->vector[2].iov_base;
998 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
999 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1000 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1001 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1002 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(reqhdr, SMB2_HDR_OPCODE));
1004 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1005 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1006 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1007 SBVAL(hdr, SMB2_HDR_PID, async_id);
1008 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1009 BVAL(reqhdr, SMB2_HDR_SESSION_ID));
1010 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
1012 SSVAL(body, 0x00, 0x08 + 1);
1014 SCVAL(body, 0x02, 0);
1015 SCVAL(body, 0x03, 0);
1016 SIVAL(body, 0x04, 0);
1017 /* Match W2K8R2... */
1018 SCVAL(body, 0x08, 0x21);
1020 /* Ensure we correctly go through crediting. Grant
1021 the credits now, and zero credits on the final
1022 response. */
1023 smb2_set_operation_credit(req->sconn,
1024 &req->in.vector[i],
1025 &state->vector[1]);
1027 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1029 if (req->do_signing) {
1030 status = smb2_signing_sign_pdu(req->session->session_key,
1031 &state->vector[1], 2);
1032 if (!NT_STATUS_IS_OK(status)) {
1033 return status;
1037 subreq = tstream_writev_queue_send(state,
1038 req->sconn->smb2.event_ctx,
1039 req->sconn->smb2.stream,
1040 req->sconn->smb2.send_queue,
1041 state->vector,
1044 if (subreq == NULL) {
1045 return NT_STATUS_NO_MEMORY;
1048 tevent_req_set_callback(subreq,
1049 smbd_smb2_request_pending_writev_done,
1050 state);
1052 /* Note we're going async with this request. */
1053 req->async = true;
1055 ipc_out:
1058 * Now manipulate req so that the outstanding async request
1059 * is the only one left in the struct smbd_smb2_request.
1062 if (req->current_idx == 1) {
1063 /* There was only one. */
1064 goto out;
1067 /* Re-arrange the in.vectors. */
1068 req->in.vector[1] = req->in.vector[i];
1069 req->in.vector[2] = req->in.vector[i+1];
1070 req->in.vector[3] = req->in.vector[i+2];
1071 req->in.vector_count = 4;
1072 /* Reset the new in size. */
1073 smb2_setup_nbt_length(req->in.vector, 4);
1075 /* Now recreate the out.vectors. */
1076 outvec = talloc_zero_array(req, struct iovec, 4);
1077 if (!outvec) {
1078 return NT_STATUS_NO_MEMORY;
1081 /* 0 is always boilerplate and must
1082 * be of size 4 for the length field. */
1084 outvec[0].iov_base = req->out.nbt_hdr;
1085 outvec[0].iov_len = 4;
1086 SIVAL(req->out.nbt_hdr, 0, 0);
1088 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
1089 return NT_STATUS_NO_MEMORY;
1092 TALLOC_FREE(req->out.vector);
1094 req->out.vector = outvec;
1096 req->current_idx = 1;
1097 req->out.vector_count = 4;
1099 out:
1101 smb2_setup_nbt_length(req->out.vector,
1102 req->out.vector_count);
1104 if (req->async) {
1105 /* Ensure our final reply matches the interim one. */
1106 reqhdr = (uint8_t *)req->out.vector[1].iov_base;
1107 SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1108 SBVAL(reqhdr, SMB2_HDR_PID, async_id);
1111 const uint8_t *inhdr =
1112 (const uint8_t *)req->in.vector[1].iov_base;
1113 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1114 "going async\n",
1115 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1116 (unsigned long long)async_id ));
1120 return NT_STATUS_OK;
1123 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1125 struct smbd_server_connection *sconn = req->sconn;
1126 struct smbd_smb2_request *cur;
1127 const uint8_t *inhdr;
1128 int i = req->current_idx;
1129 uint32_t flags;
1130 uint64_t search_message_id;
1131 uint64_t search_async_id;
1132 uint64_t found_id;
1134 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1136 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1137 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1138 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1141 * we don't need the request anymore
1142 * cancel requests never have a response
1144 DLIST_REMOVE(req->sconn->smb2.requests, req);
1145 TALLOC_FREE(req);
1147 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1148 const uint8_t *outhdr;
1149 uint64_t message_id;
1150 uint64_t async_id;
1152 i = cur->current_idx;
1154 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1156 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1157 async_id = BVAL(outhdr, SMB2_HDR_PID);
1159 if (flags & SMB2_HDR_FLAG_ASYNC) {
1160 if (search_async_id == async_id) {
1161 found_id = async_id;
1162 break;
1164 } else {
1165 if (search_message_id == message_id) {
1166 found_id = message_id;
1167 break;
1172 if (cur && cur->subreq) {
1173 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1174 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1175 "cancel opcode[%s] mid %llu\n",
1176 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1177 (unsigned long long)found_id ));
1178 tevent_req_cancel(cur->subreq);
1181 return NT_STATUS_OK;
1184 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1185 size_t expected_body_size)
1187 const uint8_t *inhdr;
1188 uint16_t opcode;
1189 const uint8_t *inbody;
1190 int i = req->current_idx;
1191 size_t body_size;
1192 size_t min_dyn_size = expected_body_size & 0x00000001;
1195 * The following should be checked already.
1197 if ((i+2) > req->in.vector_count) {
1198 return NT_STATUS_INTERNAL_ERROR;
1200 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1201 return NT_STATUS_INTERNAL_ERROR;
1203 if (req->in.vector[i+1].iov_len < 2) {
1204 return NT_STATUS_INTERNAL_ERROR;
1207 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1208 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1210 switch (opcode) {
1211 case SMB2_OP_IOCTL:
1212 case SMB2_OP_GETINFO:
1213 min_dyn_size = 0;
1214 break;
1218 * Now check the expected body size,
1219 * where the last byte might be in the
1220 * dynnamic section..
1222 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1223 return NT_STATUS_INVALID_PARAMETER;
1225 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1226 return NT_STATUS_INVALID_PARAMETER;
1229 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1231 body_size = SVAL(inbody, 0x00);
1232 if (body_size != expected_body_size) {
1233 return NT_STATUS_INVALID_PARAMETER;
1236 return NT_STATUS_OK;
1239 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1241 const uint8_t *inhdr;
1242 int i = req->current_idx;
1243 uint16_t opcode;
1244 uint32_t flags;
1245 uint64_t mid;
1246 NTSTATUS status;
1247 NTSTATUS session_status;
1248 uint32_t allowed_flags;
1249 NTSTATUS return_value;
1251 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1253 /* TODO: verify more things */
1255 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1256 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1257 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1258 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1259 smb2_opcode_name(opcode),
1260 (unsigned long long)mid));
1262 if (get_Protocol() >= PROTOCOL_SMB2) {
1264 * once the protocol is negotiated
1265 * SMB2_OP_NEGPROT is not allowed anymore
1267 if (opcode == SMB2_OP_NEGPROT) {
1268 /* drop the connection */
1269 return NT_STATUS_INVALID_PARAMETER;
1271 } else {
1273 * if the protocol is not negotiated yet
1274 * only SMB2_OP_NEGPROT is allowed.
1276 if (opcode != SMB2_OP_NEGPROT) {
1277 /* drop the connection */
1278 return NT_STATUS_INVALID_PARAMETER;
1282 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1283 SMB2_HDR_FLAG_SIGNED |
1284 SMB2_HDR_FLAG_DFS;
1285 if (opcode == SMB2_OP_CANCEL) {
1286 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1288 if ((flags & ~allowed_flags) != 0) {
1289 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1293 * Check if the client provided a valid session id,
1294 * if so smbd_smb2_request_check_session() calls
1295 * set_current_user_info().
1297 * As some command don't require a valid session id
1298 * we defer the check of the session_status
1300 session_status = smbd_smb2_request_check_session(req);
1302 req->do_signing = false;
1303 if (flags & SMB2_HDR_FLAG_SIGNED) {
1304 if (!NT_STATUS_IS_OK(session_status)) {
1305 return smbd_smb2_request_error(req, session_status);
1308 req->do_signing = true;
1309 status = smb2_signing_check_pdu(req->session->session_key,
1310 &req->in.vector[i], 3);
1311 if (!NT_STATUS_IS_OK(status)) {
1312 return smbd_smb2_request_error(req, status);
1314 } else if (opcode == SMB2_OP_CANCEL) {
1315 /* Cancel requests are allowed to skip the signing */
1316 } else if (req->session && req->session->do_signing) {
1317 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1320 if (flags & SMB2_HDR_FLAG_CHAINED) {
1322 * This check is mostly for giving the correct error code
1323 * for compounded requests.
1325 * TODO: we may need to move this after the session
1326 * and tcon checks.
1328 if (!NT_STATUS_IS_OK(req->next_status)) {
1329 return smbd_smb2_request_error(req, req->next_status);
1331 } else {
1332 req->compat_chain_fsp = NULL;
1335 if (req->compound_related) {
1336 req->sconn->smb2.compound_related_in_progress = true;
1339 switch (opcode) {
1340 case SMB2_OP_NEGPROT:
1341 /* This call needs to be run as root */
1342 change_to_root_user();
1345 START_PROFILE(smb2_negprot);
1346 return_value = smbd_smb2_request_process_negprot(req);
1347 END_PROFILE(smb2_negprot);
1349 break;
1351 case SMB2_OP_SESSSETUP:
1352 /* This call needs to be run as root */
1353 change_to_root_user();
1356 START_PROFILE(smb2_sesssetup);
1357 return_value = smbd_smb2_request_process_sesssetup(req);
1358 END_PROFILE(smb2_sesssetup);
1360 break;
1362 case SMB2_OP_LOGOFF:
1363 if (!NT_STATUS_IS_OK(session_status)) {
1364 return_value = smbd_smb2_request_error(req, session_status);
1365 break;
1368 /* This call needs to be run as root */
1369 change_to_root_user();
1372 START_PROFILE(smb2_logoff);
1373 return_value = smbd_smb2_request_process_logoff(req);
1374 END_PROFILE(smb2_logoff);
1376 break;
1378 case SMB2_OP_TCON:
1379 if (!NT_STATUS_IS_OK(session_status)) {
1380 return_value = smbd_smb2_request_error(req, session_status);
1381 break;
1385 * This call needs to be run as root.
1387 * smbd_smb2_request_process_tcon()
1388 * calls make_connection_snum(), which will call
1389 * change_to_user(), when needed.
1391 change_to_root_user();
1394 START_PROFILE(smb2_tcon);
1395 return_value = smbd_smb2_request_process_tcon(req);
1396 END_PROFILE(smb2_tcon);
1398 break;
1400 case SMB2_OP_TDIS:
1401 if (!NT_STATUS_IS_OK(session_status)) {
1402 return_value = smbd_smb2_request_error(req, session_status);
1403 break;
1406 * This call needs to be run as user.
1408 * smbd_smb2_request_check_tcon()
1409 * calls change_to_user() on success.
1411 status = smbd_smb2_request_check_tcon(req);
1412 if (!NT_STATUS_IS_OK(status)) {
1413 return_value = smbd_smb2_request_error(req, status);
1414 break;
1416 /* This call needs to be run as root */
1417 change_to_root_user();
1421 START_PROFILE(smb2_tdis);
1422 return_value = smbd_smb2_request_process_tdis(req);
1423 END_PROFILE(smb2_tdis);
1425 break;
1427 case SMB2_OP_CREATE:
1428 if (!NT_STATUS_IS_OK(session_status)) {
1429 return_value = smbd_smb2_request_error(req, session_status);
1430 break;
1433 * This call needs to be run as user.
1435 * smbd_smb2_request_check_tcon()
1436 * calls change_to_user() on success.
1438 status = smbd_smb2_request_check_tcon(req);
1439 if (!NT_STATUS_IS_OK(status)) {
1440 return_value = smbd_smb2_request_error(req, status);
1441 break;
1445 START_PROFILE(smb2_create);
1446 return_value = smbd_smb2_request_process_create(req);
1447 END_PROFILE(smb2_create);
1449 break;
1451 case SMB2_OP_CLOSE:
1452 if (!NT_STATUS_IS_OK(session_status)) {
1453 return_value = smbd_smb2_request_error(req, session_status);
1454 break;
1457 * This call needs to be run as user.
1459 * smbd_smb2_request_check_tcon()
1460 * calls change_to_user() on success.
1462 status = smbd_smb2_request_check_tcon(req);
1463 if (!NT_STATUS_IS_OK(status)) {
1464 return_value = smbd_smb2_request_error(req, status);
1465 break;
1469 START_PROFILE(smb2_close);
1470 return_value = smbd_smb2_request_process_close(req);
1471 END_PROFILE(smb2_close);
1473 break;
1475 case SMB2_OP_FLUSH:
1476 if (!NT_STATUS_IS_OK(session_status)) {
1477 return_value = smbd_smb2_request_error(req, session_status);
1478 break;
1481 * This call needs to be run as user.
1483 * smbd_smb2_request_check_tcon()
1484 * calls change_to_user() on success.
1486 status = smbd_smb2_request_check_tcon(req);
1487 if (!NT_STATUS_IS_OK(status)) {
1488 return_value = smbd_smb2_request_error(req, status);
1489 break;
1493 START_PROFILE(smb2_flush);
1494 return_value = smbd_smb2_request_process_flush(req);
1495 END_PROFILE(smb2_flush);
1497 break;
1499 case SMB2_OP_READ:
1500 if (!NT_STATUS_IS_OK(session_status)) {
1501 return_value = smbd_smb2_request_error(req, session_status);
1502 break;
1505 * This call needs to be run as user.
1507 * smbd_smb2_request_check_tcon()
1508 * calls change_to_user() on success.
1510 status = smbd_smb2_request_check_tcon(req);
1511 if (!NT_STATUS_IS_OK(status)) {
1512 return_value = smbd_smb2_request_error(req, status);
1513 break;
1517 START_PROFILE(smb2_read);
1518 return_value = smbd_smb2_request_process_read(req);
1519 END_PROFILE(smb2_read);
1521 break;
1523 case SMB2_OP_WRITE:
1524 if (!NT_STATUS_IS_OK(session_status)) {
1525 return_value = smbd_smb2_request_error(req, session_status);
1526 break;
1529 * This call needs to be run as user.
1531 * smbd_smb2_request_check_tcon()
1532 * calls change_to_user() on success.
1534 status = smbd_smb2_request_check_tcon(req);
1535 if (!NT_STATUS_IS_OK(status)) {
1536 return_value = smbd_smb2_request_error(req, status);
1537 break;
1541 START_PROFILE(smb2_write);
1542 return_value = smbd_smb2_request_process_write(req);
1543 END_PROFILE(smb2_write);
1545 break;
1547 case SMB2_OP_LOCK:
1548 if (!NT_STATUS_IS_OK(session_status)) {
1549 /* Too ugly to live ? JRA. */
1550 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1551 session_status = NT_STATUS_FILE_CLOSED;
1553 return_value = smbd_smb2_request_error(req, session_status);
1554 break;
1557 * This call needs to be run as user.
1559 * smbd_smb2_request_check_tcon()
1560 * calls change_to_user() on success.
1562 status = smbd_smb2_request_check_tcon(req);
1563 if (!NT_STATUS_IS_OK(status)) {
1564 /* Too ugly to live ? JRA. */
1565 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1566 status = NT_STATUS_FILE_CLOSED;
1568 return_value = smbd_smb2_request_error(req, status);
1569 break;
1573 START_PROFILE(smb2_lock);
1574 return_value = smbd_smb2_request_process_lock(req);
1575 END_PROFILE(smb2_lock);
1577 break;
1579 case SMB2_OP_IOCTL:
1580 if (!NT_STATUS_IS_OK(session_status)) {
1581 return_value = smbd_smb2_request_error(req, session_status);
1582 break;
1585 * This call needs to be run as user.
1587 * smbd_smb2_request_check_tcon()
1588 * calls change_to_user() on success.
1590 status = smbd_smb2_request_check_tcon(req);
1591 if (!NT_STATUS_IS_OK(status)) {
1592 return_value = smbd_smb2_request_error(req, status);
1593 break;
1597 START_PROFILE(smb2_ioctl);
1598 return_value = smbd_smb2_request_process_ioctl(req);
1599 END_PROFILE(smb2_ioctl);
1601 break;
1603 case SMB2_OP_CANCEL:
1605 * This call needs to be run as root
1607 * That is what we also do in the SMB1 case.
1609 change_to_root_user();
1612 START_PROFILE(smb2_cancel);
1613 return_value = smbd_smb2_request_process_cancel(req);
1614 END_PROFILE(smb2_cancel);
1616 break;
1618 case SMB2_OP_KEEPALIVE:
1619 /* This call needs to be run as root */
1620 change_to_root_user();
1623 START_PROFILE(smb2_keepalive);
1624 return_value = smbd_smb2_request_process_keepalive(req);
1625 END_PROFILE(smb2_keepalive);
1627 break;
1629 case SMB2_OP_FIND:
1630 if (!NT_STATUS_IS_OK(session_status)) {
1631 return_value = smbd_smb2_request_error(req, session_status);
1632 break;
1635 * This call needs to be run as user.
1637 * smbd_smb2_request_check_tcon()
1638 * calls change_to_user() on success.
1640 status = smbd_smb2_request_check_tcon(req);
1641 if (!NT_STATUS_IS_OK(status)) {
1642 return_value = smbd_smb2_request_error(req, status);
1643 break;
1647 START_PROFILE(smb2_find);
1648 return_value = smbd_smb2_request_process_find(req);
1649 END_PROFILE(smb2_find);
1651 break;
1653 case SMB2_OP_NOTIFY:
1654 if (!NT_STATUS_IS_OK(session_status)) {
1655 return_value = smbd_smb2_request_error(req, session_status);
1656 break;
1659 * This call needs to be run as user.
1661 * smbd_smb2_request_check_tcon()
1662 * calls change_to_user() on success.
1664 status = smbd_smb2_request_check_tcon(req);
1665 if (!NT_STATUS_IS_OK(status)) {
1666 return_value = smbd_smb2_request_error(req, status);
1667 break;
1671 START_PROFILE(smb2_notify);
1672 return_value = smbd_smb2_request_process_notify(req);
1673 END_PROFILE(smb2_notify);
1675 break;
1677 case SMB2_OP_GETINFO:
1678 if (!NT_STATUS_IS_OK(session_status)) {
1679 return_value = smbd_smb2_request_error(req, session_status);
1680 break;
1683 * This call needs to be run as user.
1685 * smbd_smb2_request_check_tcon()
1686 * calls change_to_user() on success.
1688 status = smbd_smb2_request_check_tcon(req);
1689 if (!NT_STATUS_IS_OK(status)) {
1690 return_value = smbd_smb2_request_error(req, status);
1691 break;
1695 START_PROFILE(smb2_getinfo);
1696 return_value = smbd_smb2_request_process_getinfo(req);
1697 END_PROFILE(smb2_getinfo);
1699 break;
1701 case SMB2_OP_SETINFO:
1702 if (!NT_STATUS_IS_OK(session_status)) {
1703 return_value = smbd_smb2_request_error(req, session_status);
1704 break;
1707 * This call needs to be run as user.
1709 * smbd_smb2_request_check_tcon()
1710 * calls change_to_user() on success.
1712 status = smbd_smb2_request_check_tcon(req);
1713 if (!NT_STATUS_IS_OK(status)) {
1714 return_value = smbd_smb2_request_error(req, status);
1715 break;
1719 START_PROFILE(smb2_setinfo);
1720 return_value = smbd_smb2_request_process_setinfo(req);
1721 END_PROFILE(smb2_setinfo);
1723 break;
1725 case SMB2_OP_BREAK:
1726 if (!NT_STATUS_IS_OK(session_status)) {
1727 return_value = smbd_smb2_request_error(req, session_status);
1728 break;
1731 * This call needs to be run as user.
1733 * smbd_smb2_request_check_tcon()
1734 * calls change_to_user() on success.
1736 status = smbd_smb2_request_check_tcon(req);
1737 if (!NT_STATUS_IS_OK(status)) {
1738 return_value = smbd_smb2_request_error(req, status);
1739 break;
1743 START_PROFILE(smb2_break);
1744 return_value = smbd_smb2_request_process_break(req);
1745 END_PROFILE(smb2_break);
1747 break;
1749 default:
1750 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1751 break;
1753 return return_value;
1756 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1758 struct tevent_req *subreq;
1759 int i = req->current_idx;
1761 req->subreq = NULL;
1763 req->current_idx += 3;
1765 if (req->current_idx < req->out.vector_count) {
1767 * We must process the remaining compound
1768 * SMB2 requests before any new incoming SMB2
1769 * requests. This is because incoming SMB2
1770 * requests may include a cancel for a
1771 * compound request we haven't processed
1772 * yet.
1774 struct tevent_immediate *im = tevent_create_immediate(req);
1775 if (!im) {
1776 return NT_STATUS_NO_MEMORY;
1778 tevent_schedule_immediate(im,
1779 req->sconn->smb2.event_ctx,
1780 smbd_smb2_request_dispatch_immediate,
1781 req);
1782 return NT_STATUS_OK;
1785 if (req->compound_related) {
1786 req->sconn->smb2.compound_related_in_progress = false;
1789 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1791 /* Set credit for these operations (zero credits if this
1792 is a final reply for an async operation). */
1793 smb2_calculate_credits(req, req);
1795 if (req->do_signing) {
1796 NTSTATUS status;
1797 status = smb2_signing_sign_pdu(req->session->session_key,
1798 &req->out.vector[i], 3);
1799 if (!NT_STATUS_IS_OK(status)) {
1800 return status;
1804 if (DEBUGLEVEL >= 10) {
1805 dbgtext("smbd_smb2_request_reply: sending...\n");
1806 print_req_vectors(req);
1809 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1810 if (req->out.vector_count == 4 &&
1811 req->out.vector[3].iov_base == NULL &&
1812 req->out.vector[3].iov_len != 0) {
1813 /* Dynamic part is NULL. Chop it off,
1814 We're going to send it via sendfile. */
1815 req->out.vector_count -= 1;
1818 subreq = tstream_writev_queue_send(req,
1819 req->sconn->smb2.event_ctx,
1820 req->sconn->smb2.stream,
1821 req->sconn->smb2.send_queue,
1822 req->out.vector,
1823 req->out.vector_count);
1824 if (subreq == NULL) {
1825 return NT_STATUS_NO_MEMORY;
1827 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1829 * We're done with this request -
1830 * move it off the "being processed" queue.
1832 DLIST_REMOVE(req->sconn->smb2.requests, req);
1834 return NT_STATUS_OK;
1837 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
1839 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1840 struct tevent_immediate *im,
1841 void *private_data)
1843 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1844 struct smbd_smb2_request);
1845 struct smbd_server_connection *sconn = req->sconn;
1846 NTSTATUS status;
1848 TALLOC_FREE(im);
1850 if (DEBUGLEVEL >= 10) {
1851 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1852 req->current_idx, req->in.vector_count));
1853 print_req_vectors(req);
1856 status = smbd_smb2_request_dispatch(req);
1857 if (!NT_STATUS_IS_OK(status)) {
1858 smbd_server_connection_terminate(sconn, nt_errstr(status));
1859 return;
1862 status = smbd_smb2_request_next_incoming(sconn);
1863 if (!NT_STATUS_IS_OK(status)) {
1864 smbd_server_connection_terminate(sconn, nt_errstr(status));
1865 return;
1869 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1871 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1872 struct smbd_smb2_request);
1873 struct smbd_server_connection *sconn = req->sconn;
1874 int ret;
1875 int sys_errno;
1876 NTSTATUS status;
1878 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1879 TALLOC_FREE(subreq);
1880 TALLOC_FREE(req);
1881 if (ret == -1) {
1882 status = map_nt_error_from_unix(sys_errno);
1883 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1884 nt_errstr(status)));
1885 smbd_server_connection_terminate(sconn, nt_errstr(status));
1886 return;
1889 status = smbd_smb2_request_next_incoming(sconn);
1890 if (!NT_STATUS_IS_OK(status)) {
1891 smbd_server_connection_terminate(sconn, nt_errstr(status));
1892 return;
1896 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1897 NTSTATUS status,
1898 DATA_BLOB body, DATA_BLOB *dyn,
1899 const char *location)
1901 uint8_t *outhdr;
1902 int i = req->current_idx;
1903 uint32_t next_command_ofs;
1905 DEBUG(10,("smbd_smb2_request_done_ex: "
1906 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1907 i, nt_errstr(status), (unsigned int)body.length,
1908 dyn ? "yes": "no",
1909 (unsigned int)(dyn ? dyn->length : 0),
1910 location));
1912 if (body.length < 2) {
1913 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1916 if ((body.length % 2) != 0) {
1917 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1920 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1922 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1923 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1925 req->out.vector[i+1].iov_base = (void *)body.data;
1926 req->out.vector[i+1].iov_len = body.length;
1928 if (dyn) {
1929 req->out.vector[i+2].iov_base = (void *)dyn->data;
1930 req->out.vector[i+2].iov_len = dyn->length;
1931 } else {
1932 req->out.vector[i+2].iov_base = NULL;
1933 req->out.vector[i+2].iov_len = 0;
1936 /* see if we need to recalculate the offset to the next response */
1937 if (next_command_ofs > 0) {
1938 next_command_ofs = SMB2_HDR_BODY;
1939 next_command_ofs += req->out.vector[i+1].iov_len;
1940 next_command_ofs += req->out.vector[i+2].iov_len;
1943 if ((next_command_ofs % 8) != 0) {
1944 size_t pad_size = 8 - (next_command_ofs % 8);
1945 if (req->out.vector[i+2].iov_len == 0) {
1947 * if the dyn buffer is empty
1948 * we can use it to add padding
1950 uint8_t *pad;
1952 pad = talloc_zero_array(req->out.vector,
1953 uint8_t, pad_size);
1954 if (pad == NULL) {
1955 return smbd_smb2_request_error(req,
1956 NT_STATUS_NO_MEMORY);
1959 req->out.vector[i+2].iov_base = (void *)pad;
1960 req->out.vector[i+2].iov_len = pad_size;
1961 } else {
1963 * For now we copy the dynamic buffer
1964 * and add the padding to the new buffer
1966 size_t old_size;
1967 uint8_t *old_dyn;
1968 size_t new_size;
1969 uint8_t *new_dyn;
1971 old_size = req->out.vector[i+2].iov_len;
1972 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
1974 new_size = old_size + pad_size;
1975 new_dyn = talloc_zero_array(req->out.vector,
1976 uint8_t, new_size);
1977 if (new_dyn == NULL) {
1978 return smbd_smb2_request_error(req,
1979 NT_STATUS_NO_MEMORY);
1982 memcpy(new_dyn, old_dyn, old_size);
1983 memset(new_dyn + old_size, 0, pad_size);
1985 req->out.vector[i+2].iov_base = (void *)new_dyn;
1986 req->out.vector[i+2].iov_len = new_size;
1988 next_command_ofs += pad_size;
1991 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1993 return smbd_smb2_request_reply(req);
1996 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
1997 NTSTATUS status,
1998 DATA_BLOB *info,
1999 const char *location)
2001 DATA_BLOB body;
2002 int i = req->current_idx;
2003 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
2005 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2006 i, nt_errstr(status), info ? " +info" : "",
2007 location));
2009 body.data = outhdr + SMB2_HDR_BODY;
2010 body.length = 8;
2011 SSVAL(body.data, 0, 9);
2013 if (info) {
2014 SIVAL(body.data, 0x04, info->length);
2015 } else {
2016 /* Allocated size of req->out.vector[i].iov_base
2017 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2018 * 1 byte without having to do an alloc.
2020 info = talloc_zero_array(req->out.vector,
2021 DATA_BLOB,
2023 if (!info) {
2024 return NT_STATUS_NO_MEMORY;
2026 info->data = ((uint8_t *)outhdr) +
2027 OUTVEC_ALLOC_SIZE - 1;
2028 info->length = 1;
2029 SCVAL(info->data, 0, 0);
2033 * if a request fails, all other remaining
2034 * compounded requests should fail too
2036 req->next_status = NT_STATUS_INVALID_PARAMETER;
2038 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2042 struct smbd_smb2_send_oplock_break_state {
2043 struct smbd_server_connection *sconn;
2044 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2045 struct iovec vector;
2048 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2050 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2051 uint64_t file_id_persistent,
2052 uint64_t file_id_volatile,
2053 uint8_t oplock_level)
2055 struct smbd_smb2_send_oplock_break_state *state;
2056 struct tevent_req *subreq;
2057 uint8_t *hdr;
2058 uint8_t *body;
2060 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2061 if (state == NULL) {
2062 return NT_STATUS_NO_MEMORY;
2064 state->sconn = sconn;
2066 state->vector.iov_base = (void *)state->buf;
2067 state->vector.iov_len = sizeof(state->buf);
2069 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2070 hdr = state->buf + 4;
2071 body = hdr + SMB2_HDR_BODY;
2073 SIVAL(hdr, 0, SMB2_MAGIC);
2074 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2075 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2076 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2077 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2078 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2079 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2080 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2081 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2082 SIVAL(hdr, SMB2_HDR_PID, 0);
2083 SIVAL(hdr, SMB2_HDR_TID, 0);
2084 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2085 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2087 SSVAL(body, 0x00, 0x18);
2089 SCVAL(body, 0x02, oplock_level);
2090 SCVAL(body, 0x03, 0); /* reserved */
2091 SIVAL(body, 0x04, 0); /* reserved */
2092 SBVAL(body, 0x08, file_id_persistent);
2093 SBVAL(body, 0x10, file_id_volatile);
2095 subreq = tstream_writev_queue_send(state,
2096 sconn->smb2.event_ctx,
2097 sconn->smb2.stream,
2098 sconn->smb2.send_queue,
2099 &state->vector, 1);
2100 if (subreq == NULL) {
2101 return NT_STATUS_NO_MEMORY;
2103 tevent_req_set_callback(subreq,
2104 smbd_smb2_oplock_break_writev_done,
2105 state);
2107 return NT_STATUS_OK;
2110 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2112 struct smbd_smb2_send_oplock_break_state *state =
2113 tevent_req_callback_data(subreq,
2114 struct smbd_smb2_send_oplock_break_state);
2115 struct smbd_server_connection *sconn = state->sconn;
2116 int ret;
2117 int sys_errno;
2119 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2120 TALLOC_FREE(subreq);
2121 if (ret == -1) {
2122 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2123 smbd_server_connection_terminate(sconn, nt_errstr(status));
2124 return;
2127 TALLOC_FREE(state);
2130 struct smbd_smb2_request_read_state {
2131 size_t missing;
2132 bool asked_for_header;
2133 struct smbd_smb2_request *smb2_req;
2136 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2137 void *private_data,
2138 TALLOC_CTX *mem_ctx,
2139 struct iovec **_vector,
2140 size_t *_count);
2141 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2143 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2144 struct tevent_context *ev,
2145 struct smbd_server_connection *sconn)
2147 struct tevent_req *req;
2148 struct smbd_smb2_request_read_state *state;
2149 struct tevent_req *subreq;
2151 req = tevent_req_create(mem_ctx, &state,
2152 struct smbd_smb2_request_read_state);
2153 if (req == NULL) {
2154 return NULL;
2156 state->missing = 0;
2157 state->asked_for_header = false;
2159 state->smb2_req = smbd_smb2_request_allocate(state);
2160 if (tevent_req_nomem(state->smb2_req, req)) {
2161 return tevent_req_post(req, ev);
2163 state->smb2_req->sconn = sconn;
2165 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2166 sconn->smb2.recv_queue,
2167 smbd_smb2_request_next_vector,
2168 state);
2169 if (tevent_req_nomem(subreq, req)) {
2170 return tevent_req_post(req, ev);
2172 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2174 return req;
2177 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2178 void *private_data,
2179 TALLOC_CTX *mem_ctx,
2180 struct iovec **_vector,
2181 size_t *_count)
2183 struct smbd_smb2_request_read_state *state =
2184 talloc_get_type_abort(private_data,
2185 struct smbd_smb2_request_read_state);
2186 struct smbd_smb2_request *req = state->smb2_req;
2187 struct iovec *vector;
2188 int idx = req->in.vector_count;
2189 size_t len = 0;
2190 uint8_t *buf = NULL;
2192 if (req->in.vector_count == 0) {
2194 * first we need to get the NBT header
2196 req->in.vector = talloc_array(req, struct iovec,
2197 req->in.vector_count + 1);
2198 if (req->in.vector == NULL) {
2199 return -1;
2201 req->in.vector_count += 1;
2203 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2204 req->in.vector[idx].iov_len = 4;
2206 vector = talloc_array(mem_ctx, struct iovec, 1);
2207 if (vector == NULL) {
2208 return -1;
2211 vector[0] = req->in.vector[idx];
2213 *_vector = vector;
2214 *_count = 1;
2215 return 0;
2218 if (req->in.vector_count == 1) {
2220 * Now we analyze the NBT header
2222 state->missing = smb2_len(req->in.vector[0].iov_base);
2224 if (state->missing == 0) {
2225 /* if there're no remaining bytes, we're done */
2226 *_vector = NULL;
2227 *_count = 0;
2228 return 0;
2231 req->in.vector = talloc_realloc(req, req->in.vector,
2232 struct iovec,
2233 req->in.vector_count + 1);
2234 if (req->in.vector == NULL) {
2235 return -1;
2237 req->in.vector_count += 1;
2239 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2241 * it's a special NBT message,
2242 * so get all remaining bytes
2244 len = state->missing;
2245 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2247 * it's an invalid message, just read what we can get
2248 * and let the caller handle the error
2250 len = state->missing;
2251 } else {
2253 * We assume it's a SMB2 request,
2254 * and we first get the header and the
2255 * first 2 bytes (the struct size) of the body
2257 len = SMB2_HDR_BODY + 2;
2259 state->asked_for_header = true;
2262 state->missing -= len;
2264 buf = talloc_array(req->in.vector, uint8_t, len);
2265 if (buf == NULL) {
2266 return -1;
2269 req->in.vector[idx].iov_base = (void *)buf;
2270 req->in.vector[idx].iov_len = len;
2272 vector = talloc_array(mem_ctx, struct iovec, 1);
2273 if (vector == NULL) {
2274 return -1;
2277 vector[0] = req->in.vector[idx];
2279 *_vector = vector;
2280 *_count = 1;
2281 return 0;
2284 if (state->missing == 0) {
2285 /* if there're no remaining bytes, we're done */
2286 *_vector = NULL;
2287 *_count = 0;
2288 return 0;
2291 if (state->asked_for_header) {
2292 const uint8_t *hdr;
2293 size_t full_size;
2294 size_t next_command_ofs;
2295 size_t body_size;
2296 uint8_t *body;
2297 size_t dyn_size;
2298 uint8_t *dyn;
2299 bool invalid = false;
2301 state->asked_for_header = false;
2304 * We got the SMB2 header and the first 2 bytes
2305 * of the body. We fix the size to just the header
2306 * and manually copy the 2 first bytes to the body section
2308 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2309 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2311 /* allocate vectors for body and dynamic areas */
2312 req->in.vector = talloc_realloc(req, req->in.vector,
2313 struct iovec,
2314 req->in.vector_count + 2);
2315 if (req->in.vector == NULL) {
2316 return -1;
2318 req->in.vector_count += 2;
2320 full_size = state->missing + SMB2_HDR_BODY + 2;
2321 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2322 body_size = SVAL(hdr, SMB2_HDR_BODY);
2324 if (next_command_ofs != 0) {
2325 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2327 * this is invalid, just return a zero
2328 * body and let the caller deal with the error
2330 invalid = true;
2331 } else if (next_command_ofs > full_size) {
2333 * this is invalid, just return a zero
2334 * body and let the caller deal with the error
2336 invalid = true;
2337 } else {
2338 full_size = next_command_ofs;
2342 if (!invalid) {
2343 if (body_size < 2) {
2345 * this is invalid, just return a zero
2346 * body and let the caller deal with the error
2348 invalid = true;
2351 if ((body_size % 2) != 0) {
2352 body_size -= 1;
2355 if (body_size > (full_size - SMB2_HDR_BODY)) {
2357 * this is invalid, just return a zero
2358 * body and let the caller deal with the error
2360 invalid = true;
2364 if (invalid) {
2365 /* the caller should check this */
2366 body_size = 2;
2369 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2371 state->missing -= (body_size - 2) + dyn_size;
2373 body = talloc_array(req->in.vector, uint8_t, body_size);
2374 if (body == NULL) {
2375 return -1;
2378 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2379 if (dyn == NULL) {
2380 return -1;
2383 req->in.vector[idx].iov_base = (void *)body;
2384 req->in.vector[idx].iov_len = body_size;
2385 req->in.vector[idx+1].iov_base = (void *)dyn;
2386 req->in.vector[idx+1].iov_len = dyn_size;
2388 vector = talloc_array(mem_ctx, struct iovec, 2);
2389 if (vector == NULL) {
2390 return -1;
2394 * the first 2 bytes of the body were already fetched
2395 * together with the header
2397 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2398 vector[0].iov_base = body + 2;
2399 vector[0].iov_len = body_size - 2;
2401 vector[1] = req->in.vector[idx+1];
2403 *_vector = vector;
2404 *_count = 2;
2405 return 0;
2409 * when we endup here, we're looking for a new SMB2 request
2410 * next. And we ask for its header and the first 2 bytes of
2411 * the body (like we did for the first SMB2 request).
2414 req->in.vector = talloc_realloc(req, req->in.vector,
2415 struct iovec,
2416 req->in.vector_count + 1);
2417 if (req->in.vector == NULL) {
2418 return -1;
2420 req->in.vector_count += 1;
2423 * We assume it's a SMB2 request,
2424 * and we first get the header and the
2425 * first 2 bytes (the struct size) of the body
2427 len = SMB2_HDR_BODY + 2;
2429 if (len > state->missing) {
2430 /* let the caller handle the error */
2431 len = state->missing;
2434 state->missing -= len;
2435 state->asked_for_header = true;
2437 buf = talloc_array(req->in.vector, uint8_t, len);
2438 if (buf == NULL) {
2439 return -1;
2442 req->in.vector[idx].iov_base = (void *)buf;
2443 req->in.vector[idx].iov_len = len;
2445 vector = talloc_array(mem_ctx, struct iovec, 1);
2446 if (vector == NULL) {
2447 return -1;
2450 vector[0] = req->in.vector[idx];
2452 *_vector = vector;
2453 *_count = 1;
2454 return 0;
2457 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2459 struct tevent_req *req =
2460 tevent_req_callback_data(subreq,
2461 struct tevent_req);
2462 int ret;
2463 int sys_errno;
2464 NTSTATUS status;
2466 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2467 if (ret == -1) {
2468 status = map_nt_error_from_unix(sys_errno);
2469 tevent_req_nterror(req, status);
2470 return;
2473 tevent_req_done(req);
2476 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2477 TALLOC_CTX *mem_ctx,
2478 struct smbd_smb2_request **_smb2_req)
2480 struct smbd_smb2_request_read_state *state =
2481 tevent_req_data(req,
2482 struct smbd_smb2_request_read_state);
2483 NTSTATUS status;
2485 if (tevent_req_is_nterror(req, &status)) {
2486 tevent_req_received(req);
2487 return status;
2490 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2491 *_smb2_req = state->smb2_req;
2492 tevent_req_received(req);
2493 return NT_STATUS_OK;
2496 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2498 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2500 size_t max_send_queue_len;
2501 size_t cur_send_queue_len;
2502 struct tevent_req *subreq;
2504 if (sconn->smb2.compound_related_in_progress) {
2506 * Can't read another until the related
2507 * compound is done.
2509 return NT_STATUS_OK;
2512 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2514 * if there is already a smbd_smb2_request_read
2515 * pending, we are done.
2517 return NT_STATUS_OK;
2520 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2521 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2523 if (cur_send_queue_len > max_send_queue_len) {
2525 * if we have a lot of requests to send,
2526 * we wait until they are on the wire until we
2527 * ask for the next request.
2529 return NT_STATUS_OK;
2532 /* ask for the next request */
2533 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2534 if (subreq == NULL) {
2535 return NT_STATUS_NO_MEMORY;
2537 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2539 return NT_STATUS_OK;
2542 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2543 const uint8_t *inbuf, size_t size)
2545 NTSTATUS status;
2546 struct smbd_smb2_request *req = NULL;
2548 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2549 (unsigned int)size));
2551 status = smbd_initialize_smb2(sconn);
2552 if (!NT_STATUS_IS_OK(status)) {
2553 smbd_server_connection_terminate(sconn, nt_errstr(status));
2554 return;
2557 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2558 if (!NT_STATUS_IS_OK(status)) {
2559 smbd_server_connection_terminate(sconn, nt_errstr(status));
2560 return;
2563 status = smbd_smb2_request_validate(req);
2564 if (!NT_STATUS_IS_OK(status)) {
2565 smbd_server_connection_terminate(sconn, nt_errstr(status));
2566 return;
2569 status = smbd_smb2_request_setup_out(req);
2570 if (!NT_STATUS_IS_OK(status)) {
2571 smbd_server_connection_terminate(sconn, nt_errstr(status));
2572 return;
2575 status = smbd_smb2_request_dispatch(req);
2576 if (!NT_STATUS_IS_OK(status)) {
2577 smbd_server_connection_terminate(sconn, nt_errstr(status));
2578 return;
2581 status = smbd_smb2_request_next_incoming(sconn);
2582 if (!NT_STATUS_IS_OK(status)) {
2583 smbd_server_connection_terminate(sconn, nt_errstr(status));
2584 return;
2587 sconn->num_requests++;
2590 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2592 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2593 struct smbd_server_connection);
2594 NTSTATUS status;
2595 struct smbd_smb2_request *req = NULL;
2597 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2598 TALLOC_FREE(subreq);
2599 if (!NT_STATUS_IS_OK(status)) {
2600 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2601 nt_errstr(status)));
2602 smbd_server_connection_terminate(sconn, nt_errstr(status));
2603 return;
2606 if (req->in.nbt_hdr[0] != 0x00) {
2607 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2608 req->in.nbt_hdr[0]));
2609 TALLOC_FREE(req);
2610 goto next;
2613 req->current_idx = 1;
2615 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2616 req->current_idx, req->in.vector_count));
2618 status = smbd_smb2_request_validate(req);
2619 if (!NT_STATUS_IS_OK(status)) {
2620 smbd_server_connection_terminate(sconn, nt_errstr(status));
2621 return;
2624 status = smbd_smb2_request_setup_out(req);
2625 if (!NT_STATUS_IS_OK(status)) {
2626 smbd_server_connection_terminate(sconn, nt_errstr(status));
2627 return;
2630 status = smbd_smb2_request_dispatch(req);
2631 if (!NT_STATUS_IS_OK(status)) {
2632 smbd_server_connection_terminate(sconn, nt_errstr(status));
2633 return;
2636 next:
2637 status = smbd_smb2_request_next_incoming(sconn);
2638 if (!NT_STATUS_IS_OK(status)) {
2639 smbd_server_connection_terminate(sconn, nt_errstr(status));
2640 return;
2643 sconn->num_requests++;
2645 /* The timeout_processing function isn't run nearly
2646 often enough to implement 'max log size' without
2647 overrunning the size of the file by many megabytes.
2648 This is especially true if we are running at debug
2649 level 10. Checking every 50 SMB2s is a nice
2650 tradeoff of performance vs log file size overrun. */
2652 if ((sconn->num_requests % 50) == 0 &&
2653 need_to_check_log_size()) {
2654 change_to_root_user();
2655 check_log_size();