s3: Fix uninitialized memory read in talloc_free()
[Samba.git] / source3 / smbd / smb2_server.c
blob8a5d81f87b227a9dc8e09f59bc1233e39d2eb6fe
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 = 0;
118 sconn->smb2.max_credits = lp_smb2_max_credits();
119 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
120 DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR*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_message_id(struct smbd_server_connection *sconn,
302 const uint8_t *inhdr)
304 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
305 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
306 uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
307 unsigned int bitmap_offset;
309 if (opcode == SMB2_OP_CANCEL) {
310 /* SMB2_CANCEL requests by definition resend messageids. */
311 return true;
314 if (message_id < sconn->smb2.seqnum_low ||
315 message_id > (sconn->smb2.seqnum_low +
316 (sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR))) {
317 DEBUG(0,("smb2_validate_message_id: bad message_id "
318 "%llu (low = %llu, max = %lu)\n",
319 (unsigned long long)message_id,
320 (unsigned long long)sconn->smb2.seqnum_low,
321 (unsigned long)sconn->smb2.max_credits ));
322 return false;
325 if (sconn->smb2.credits_granted == 0) {
326 DEBUG(0,("smb2_validate_message_id: client used more "
327 "credits than granted message_id (%llu)\n",
328 (unsigned long long)message_id));
329 return false;
332 /* client just used a credit. */
333 sconn->smb2.credits_granted -= 1;
335 /* Mark the message_id as seen in the bitmap. */
336 bitmap_offset = (unsigned int)(message_id %
337 (uint64_t)(sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR));
338 if (bitmap_query(credits_bm, bitmap_offset)) {
339 DEBUG(0,("smb2_validate_message_id: duplicate message_id "
340 "%llu (bm offset %u)\n",
341 (unsigned long long)message_id,
342 bitmap_offset));
343 return false;
345 bitmap_set(credits_bm, bitmap_offset);
347 if (message_id == sconn->smb2.seqnum_low + 1) {
348 /* Move the window forward by all the message_id's
349 already seen. */
350 while (bitmap_query(credits_bm, bitmap_offset)) {
351 DEBUG(10,("smb2_validate_message_id: clearing "
352 "id %llu (position %u) from bitmap\n",
353 (unsigned long long)(sconn->smb2.seqnum_low + 1),
354 bitmap_offset ));
355 bitmap_clear(credits_bm, bitmap_offset);
356 sconn->smb2.seqnum_low += 1;
357 bitmap_offset = (bitmap_offset + 1) %
358 (sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR);
362 return true;
365 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
367 int count;
368 int idx;
370 count = req->in.vector_count;
372 if (count < 4) {
373 /* It's not a SMB2 request */
374 return NT_STATUS_INVALID_PARAMETER;
377 for (idx=1; idx < count; idx += 3) {
378 const uint8_t *inhdr = NULL;
379 uint32_t flags;
381 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
382 return NT_STATUS_INVALID_PARAMETER;
385 if (req->in.vector[idx+1].iov_len < 2) {
386 return NT_STATUS_INVALID_PARAMETER;
389 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
391 /* Check the SMB2 header */
392 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
393 return NT_STATUS_INVALID_PARAMETER;
396 if (!smb2_validate_message_id(req->sconn, inhdr)) {
397 return NT_STATUS_INVALID_PARAMETER;
400 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
401 if (idx == 1) {
403 * the 1st request should never have the
404 * SMB2_HDR_FLAG_CHAINED flag set
406 if (flags & SMB2_HDR_FLAG_CHAINED) {
407 req->next_status = NT_STATUS_INVALID_PARAMETER;
408 return NT_STATUS_OK;
410 } else if (idx == 4) {
412 * the 2nd request triggers related vs. unrelated
413 * compounded requests
415 if (flags & SMB2_HDR_FLAG_CHAINED) {
416 req->compound_related = true;
418 } else if (idx > 4) {
419 #if 0
421 * It seems the this tests are wrong
422 * see the SMB2-COMPOUND test
426 * all other requests should match the 2nd one
428 if (flags & SMB2_HDR_FLAG_CHAINED) {
429 if (!req->compound_related) {
430 req->next_status =
431 NT_STATUS_INVALID_PARAMETER;
432 return NT_STATUS_OK;
434 } else {
435 if (req->compound_related) {
436 req->next_status =
437 NT_STATUS_INVALID_PARAMETER;
438 return NT_STATUS_OK;
441 #endif
445 return NT_STATUS_OK;
448 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
449 const struct iovec *in_vector,
450 struct iovec *out_vector)
452 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
453 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
454 uint16_t credits_requested;
455 uint32_t out_flags;
456 uint16_t credits_granted = 0;
458 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
459 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
461 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
463 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
465 * In case we already send an async interim
466 * response, we should not grant
467 * credits on the final response.
469 credits_requested = 0;
472 if (credits_requested) {
473 uint16_t modified_credits_requested;
474 uint32_t multiplier;
477 * Split up max_credits into 1/16ths, and then scale
478 * the requested credits by how many 16ths have been
479 * currently granted. Less than 1/16th == grant all
480 * requested (100%), scale down as more have been
481 * granted. Never ask for less than 1 as the client
482 * asked for at least 1. JRA.
485 multiplier = 16 - (((sconn->smb2.credits_granted * 16) / sconn->smb2.max_credits) % 16);
487 modified_credits_requested = (multiplier * credits_requested) / 16;
488 if (modified_credits_requested == 0) {
489 modified_credits_requested = 1;
492 /* Remember what we gave out. */
493 credits_granted = MIN(modified_credits_requested,
494 (sconn->smb2.max_credits - sconn->smb2.credits_granted));
497 if (credits_granted == 0 && sconn->smb2.credits_granted == 0) {
498 /* First negprot packet, or ensure the client credits can
499 never drop to zero. */
500 credits_granted = 1;
503 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
504 sconn->smb2.credits_granted += credits_granted;
506 DEBUG(10,("smb2_set_operation_credit: requested %u, "
507 "granted %u, total granted %u\n",
508 (unsigned int)credits_requested,
509 (unsigned int)credits_granted,
510 (unsigned int)sconn->smb2.credits_granted ));
513 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
514 struct smbd_smb2_request *outreq)
516 int count, idx;
517 uint16_t total_credits = 0;
519 count = outreq->out.vector_count;
521 for (idx=1; idx < count; idx += 3) {
522 uint8_t *outhdr = (uint8_t *)outreq->out.vector[idx].iov_base;
523 smb2_set_operation_credit(outreq->sconn,
524 &inreq->in.vector[idx],
525 &outreq->out.vector[idx]);
526 /* To match Windows, count up what we
527 just granted. */
528 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
529 /* Set to zero in all but the last reply. */
530 if (idx + 3 < count) {
531 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
532 } else {
533 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
538 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
540 struct iovec *vector;
541 int count;
542 int idx;
544 count = req->in.vector_count;
545 vector = talloc_zero_array(req, struct iovec, count);
546 if (vector == NULL) {
547 return NT_STATUS_NO_MEMORY;
550 vector[0].iov_base = req->out.nbt_hdr;
551 vector[0].iov_len = 4;
552 SIVAL(req->out.nbt_hdr, 0, 0);
554 for (idx=1; idx < count; idx += 3) {
555 const uint8_t *inhdr = NULL;
556 uint32_t in_flags;
557 uint8_t *outhdr = NULL;
558 uint8_t *outbody = NULL;
559 uint32_t next_command_ofs = 0;
560 struct iovec *current = &vector[idx];
562 if ((idx + 3) < count) {
563 /* we have a next command -
564 * setup for the error case. */
565 next_command_ofs = SMB2_HDR_BODY + 9;
568 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
569 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
571 outhdr = talloc_zero_array(vector, uint8_t,
572 OUTVEC_ALLOC_SIZE);
573 if (outhdr == NULL) {
574 return NT_STATUS_NO_MEMORY;
577 outbody = outhdr + SMB2_HDR_BODY;
579 current[0].iov_base = (void *)outhdr;
580 current[0].iov_len = SMB2_HDR_BODY;
582 current[1].iov_base = (void *)outbody;
583 current[1].iov_len = 8;
585 current[2].iov_base = NULL;
586 current[2].iov_len = 0;
588 /* setup the SMB2 header */
589 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
590 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
591 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
592 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
593 SIVAL(outhdr, SMB2_HDR_STATUS,
594 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
595 SSVAL(outhdr, SMB2_HDR_OPCODE,
596 SVAL(inhdr, SMB2_HDR_OPCODE));
597 SIVAL(outhdr, SMB2_HDR_FLAGS,
598 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
599 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
600 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
601 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
602 SIVAL(outhdr, SMB2_HDR_PID,
603 IVAL(inhdr, SMB2_HDR_PID));
604 SIVAL(outhdr, SMB2_HDR_TID,
605 IVAL(inhdr, SMB2_HDR_TID));
606 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
607 BVAL(inhdr, SMB2_HDR_SESSION_ID));
608 memcpy(outhdr + SMB2_HDR_SIGNATURE,
609 inhdr + SMB2_HDR_SIGNATURE, 16);
611 /* setup error body header */
612 SSVAL(outbody, 0x00, 0x08 + 1);
613 SSVAL(outbody, 0x02, 0);
614 SIVAL(outbody, 0x04, 0);
617 req->out.vector = vector;
618 req->out.vector_count = count;
620 /* setup the length of the NBT packet */
621 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
623 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
625 return NT_STATUS_OK;
628 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
629 const char *reason,
630 const char *location)
632 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
633 reason, location));
634 exit_server_cleanly(reason);
637 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
638 struct iovec *outvec,
639 const struct iovec *srcvec)
641 /* vec[0] is always boilerplate and must
642 * be allocated with size OUTVEC_ALLOC_SIZE. */
644 outvec[0].iov_base = talloc_memdup(ctx,
645 srcvec[0].iov_base,
646 OUTVEC_ALLOC_SIZE);
647 if (!outvec[0].iov_base) {
648 return false;
650 outvec[0].iov_len = SMB2_HDR_BODY;
653 * If this is a "standard" vec[1] of length 8,
654 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
655 * then duplicate this. Else use talloc_memdup().
658 if (srcvec[1].iov_len == 8 &&
659 srcvec[1].iov_base ==
660 ((uint8_t *)srcvec[0].iov_base) +
661 SMB2_HDR_BODY) {
662 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
663 SMB2_HDR_BODY;
664 outvec[1].iov_len = 8;
665 } else {
666 outvec[1].iov_base = talloc_memdup(ctx,
667 srcvec[1].iov_base,
668 srcvec[1].iov_len);
669 if (!outvec[1].iov_base) {
670 return false;
672 outvec[1].iov_len = srcvec[1].iov_len;
676 * If this is a "standard" vec[2] of length 1,
677 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
678 * then duplicate this. Else use talloc_memdup().
681 if (srcvec[2].iov_base &&
682 srcvec[2].iov_len) {
683 if (srcvec[2].iov_base ==
684 ((uint8_t *)srcvec[0].iov_base) +
685 (OUTVEC_ALLOC_SIZE - 1) &&
686 srcvec[2].iov_len == 1) {
687 /* Common SMB2 error packet case. */
688 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
689 (OUTVEC_ALLOC_SIZE - 1);
690 } else {
691 outvec[2].iov_base = talloc_memdup(ctx,
692 srcvec[2].iov_base,
693 srcvec[2].iov_len);
694 if (!outvec[2].iov_base) {
695 return false;
698 outvec[2].iov_len = srcvec[2].iov_len;
699 } else {
700 outvec[2].iov_base = NULL;
701 outvec[2].iov_len = 0;
703 return true;
706 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
708 struct smbd_smb2_request *newreq = NULL;
709 struct iovec *outvec = NULL;
710 int count = req->out.vector_count;
711 int i;
713 newreq = smbd_smb2_request_allocate(req->sconn);
714 if (!newreq) {
715 return NULL;
718 newreq->sconn = req->sconn;
719 newreq->session = req->session;
720 newreq->do_signing = req->do_signing;
721 newreq->current_idx = req->current_idx;
722 newreq->async = false;
723 newreq->cancelled = false;
724 /* Note we are leaving:
725 ->tcon
726 ->smb1req
727 ->compat_chain_fsp
728 uninitialized as NULL here as
729 they're not used in the interim
730 response code. JRA. */
732 outvec = talloc_zero_array(newreq, struct iovec, count);
733 if (!outvec) {
734 TALLOC_FREE(newreq);
735 return NULL;
737 newreq->out.vector = outvec;
738 newreq->out.vector_count = count;
740 /* Setup the outvec's identically to req. */
741 outvec[0].iov_base = newreq->out.nbt_hdr;
742 outvec[0].iov_len = 4;
743 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
745 /* Setup the vectors identically to the ones in req. */
746 for (i = 1; i < count; i += 3) {
747 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
748 break;
752 if (i < count) {
753 /* Alloc failed. */
754 TALLOC_FREE(newreq);
755 return NULL;
758 smb2_setup_nbt_length(newreq->out.vector,
759 newreq->out.vector_count);
761 return newreq;
764 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
766 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
768 int i = 0;
769 uint8_t *outhdr = NULL;
770 struct smbd_smb2_request *nreq = NULL;
772 /* Create a new smb2 request we'll use
773 for the interim return. */
774 nreq = dup_smb2_req(req);
775 if (!nreq) {
776 return NT_STATUS_NO_MEMORY;
779 /* Lose the last 3 out vectors. They're the
780 ones we'll be using for the async reply. */
781 nreq->out.vector_count -= 3;
783 smb2_setup_nbt_length(nreq->out.vector,
784 nreq->out.vector_count);
786 /* Step back to the previous reply. */
787 i = nreq->current_idx - 3;
788 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
789 /* And end the chain. */
790 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
792 /* Calculate outgoing credits */
793 smb2_calculate_credits(req, nreq);
795 /* Re-sign if needed. */
796 if (nreq->do_signing) {
797 NTSTATUS status;
798 status = smb2_signing_sign_pdu(nreq->session->session_key,
799 &nreq->out.vector[i], 3);
800 if (!NT_STATUS_IS_OK(status)) {
801 return status;
804 if (DEBUGLEVEL >= 10) {
805 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
806 (unsigned int)nreq->current_idx );
807 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
808 (unsigned int)nreq->out.vector_count );
809 print_req_vectors(nreq);
811 nreq->subreq = tstream_writev_queue_send(nreq,
812 nreq->sconn->smb2.event_ctx,
813 nreq->sconn->smb2.stream,
814 nreq->sconn->smb2.send_queue,
815 nreq->out.vector,
816 nreq->out.vector_count);
818 if (nreq->subreq == NULL) {
819 return NT_STATUS_NO_MEMORY;
822 tevent_req_set_callback(nreq->subreq,
823 smbd_smb2_request_writev_done,
824 nreq);
826 return NT_STATUS_OK;
829 struct smbd_smb2_request_pending_state {
830 struct smbd_server_connection *sconn;
831 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
832 struct iovec vector[3];
835 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
837 struct smbd_smb2_request_pending_state *state =
838 tevent_req_callback_data(subreq,
839 struct smbd_smb2_request_pending_state);
840 struct smbd_server_connection *sconn = state->sconn;
841 int ret;
842 int sys_errno;
844 ret = tstream_writev_queue_recv(subreq, &sys_errno);
845 TALLOC_FREE(subreq);
846 if (ret == -1) {
847 NTSTATUS status = map_nt_error_from_unix(sys_errno);
848 smbd_server_connection_terminate(sconn, nt_errstr(status));
849 return;
852 TALLOC_FREE(state);
855 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
856 struct tevent_req *subreq)
858 NTSTATUS status;
859 struct smbd_smb2_request_pending_state *state = NULL;
860 int i = req->current_idx;
861 uint8_t *reqhdr = NULL;
862 uint8_t *hdr = NULL;
863 uint8_t *body = NULL;
864 uint32_t flags = 0;
865 uint64_t message_id = 0;
866 uint64_t async_id = 0;
867 struct iovec *outvec = NULL;
869 if (!tevent_req_is_in_progress(subreq)) {
870 return NT_STATUS_OK;
873 req->subreq = subreq;
874 subreq = NULL;
876 if (req->async) {
877 /* We're already async. */
878 return NT_STATUS_OK;
881 if (req->in.vector_count > i + 3) {
883 * We're trying to go async in a compound
884 * request chain. This is not allowed.
885 * Cancel the outstanding request.
887 tevent_req_cancel(req->subreq);
888 return smbd_smb2_request_error(req,
889 NT_STATUS_INSUFFICIENT_RESOURCES);
892 if (DEBUGLEVEL >= 10) {
893 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
894 (unsigned int)req->current_idx );
895 print_req_vectors(req);
898 if (req->out.vector_count > 4) {
899 /* This is a compound reply. We
900 * must do an interim response
901 * followed by the async response
902 * to match W2K8R2.
904 status = smb2_send_async_interim_response(req);
905 if (!NT_STATUS_IS_OK(status)) {
906 return status;
910 * We're splitting off the last SMB2
911 * request in a compound set, and the
912 * smb2_send_async_interim_response()
913 * call above just sent all the replies
914 * for the previous SMB2 requests in
915 * this compound set. So we're no longer
916 * in the "compound_related_in_progress"
917 * state, and this is no longer a compound
918 * request.
920 req->compound_related = false;
921 req->sconn->smb2.compound_related_in_progress = false;
924 /* Don't return an intermediate packet on a pipe read/write. */
925 if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
926 goto ipc_out;
929 reqhdr = (uint8_t *)req->out.vector[i].iov_base;
930 flags = (IVAL(reqhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
931 message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
932 async_id = message_id; /* keep it simple for now... */
935 * What we send is identical to a smbd_smb2_request_error
936 * packet with an error status of STATUS_PENDING. Make use
937 * of this fact sometime when refactoring. JRA.
940 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
941 if (state == NULL) {
942 return NT_STATUS_NO_MEMORY;
944 state->sconn = req->sconn;
946 state->vector[0].iov_base = (void *)state->buf;
947 state->vector[0].iov_len = 4;
949 state->vector[1].iov_base = state->buf + 4;
950 state->vector[1].iov_len = SMB2_HDR_BODY;
952 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
953 state->vector[2].iov_len = 9;
955 smb2_setup_nbt_length(state->vector, 3);
957 hdr = (uint8_t *)state->vector[1].iov_base;
958 body = (uint8_t *)state->vector[2].iov_base;
960 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
961 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
962 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
963 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
964 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(reqhdr, SMB2_HDR_OPCODE));
966 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
967 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
968 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
969 SBVAL(hdr, SMB2_HDR_PID, async_id);
970 SBVAL(hdr, SMB2_HDR_SESSION_ID,
971 BVAL(reqhdr, SMB2_HDR_SESSION_ID));
972 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
974 SSVAL(body, 0x00, 0x08 + 1);
976 SCVAL(body, 0x02, 0);
977 SCVAL(body, 0x03, 0);
978 SIVAL(body, 0x04, 0);
979 /* Match W2K8R2... */
980 SCVAL(body, 0x08, 0x21);
982 /* Ensure we correctly go through crediting. Grant
983 the credits now, and zero credits on the final
984 response. */
985 smb2_set_operation_credit(req->sconn,
986 &req->in.vector[i],
987 &state->vector[1]);
989 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
991 if (req->do_signing) {
992 status = smb2_signing_sign_pdu(req->session->session_key,
993 &state->vector[1], 2);
994 if (!NT_STATUS_IS_OK(status)) {
995 return status;
999 subreq = tstream_writev_queue_send(state,
1000 req->sconn->smb2.event_ctx,
1001 req->sconn->smb2.stream,
1002 req->sconn->smb2.send_queue,
1003 state->vector,
1006 if (subreq == NULL) {
1007 return NT_STATUS_NO_MEMORY;
1010 tevent_req_set_callback(subreq,
1011 smbd_smb2_request_pending_writev_done,
1012 state);
1014 /* Note we're going async with this request. */
1015 req->async = true;
1017 ipc_out:
1020 * Now manipulate req so that the outstanding async request
1021 * is the only one left in the struct smbd_smb2_request.
1024 if (req->current_idx == 1) {
1025 /* There was only one. */
1026 goto out;
1029 /* Re-arrange the in.vectors. */
1030 req->in.vector[1] = req->in.vector[i];
1031 req->in.vector[2] = req->in.vector[i+1];
1032 req->in.vector[3] = req->in.vector[i+2];
1033 req->in.vector_count = 4;
1034 /* Reset the new in size. */
1035 smb2_setup_nbt_length(req->in.vector, 4);
1037 /* Now recreate the out.vectors. */
1038 outvec = talloc_zero_array(req, struct iovec, 4);
1039 if (!outvec) {
1040 return NT_STATUS_NO_MEMORY;
1043 /* 0 is always boilerplate and must
1044 * be of size 4 for the length field. */
1046 outvec[0].iov_base = req->out.nbt_hdr;
1047 outvec[0].iov_len = 4;
1048 SIVAL(req->out.nbt_hdr, 0, 0);
1050 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
1051 return NT_STATUS_NO_MEMORY;
1054 TALLOC_FREE(req->out.vector);
1056 req->out.vector = outvec;
1058 req->current_idx = 1;
1059 req->out.vector_count = 4;
1061 out:
1063 smb2_setup_nbt_length(req->out.vector,
1064 req->out.vector_count);
1066 if (req->async) {
1067 /* Ensure our final reply matches the interim one. */
1068 reqhdr = (uint8_t *)req->out.vector[1].iov_base;
1069 SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1070 SBVAL(reqhdr, SMB2_HDR_PID, async_id);
1073 const uint8_t *inhdr =
1074 (const uint8_t *)req->in.vector[1].iov_base;
1075 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1076 "going async\n",
1077 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1078 (unsigned long long)async_id ));
1082 return NT_STATUS_OK;
1085 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1087 struct smbd_server_connection *sconn = req->sconn;
1088 struct smbd_smb2_request *cur;
1089 const uint8_t *inhdr;
1090 int i = req->current_idx;
1091 uint32_t flags;
1092 uint64_t search_message_id;
1093 uint64_t search_async_id;
1094 uint64_t found_id;
1096 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1098 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1099 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1100 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1103 * we don't need the request anymore
1104 * cancel requests never have a response
1106 DLIST_REMOVE(req->sconn->smb2.requests, req);
1107 TALLOC_FREE(req);
1109 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1110 const uint8_t *outhdr;
1111 uint64_t message_id;
1112 uint64_t async_id;
1114 i = cur->current_idx;
1116 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1118 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1119 async_id = BVAL(outhdr, SMB2_HDR_PID);
1121 if (flags & SMB2_HDR_FLAG_ASYNC) {
1122 if (search_async_id == async_id) {
1123 found_id = async_id;
1124 break;
1126 } else {
1127 if (search_message_id == message_id) {
1128 found_id = message_id;
1129 break;
1134 if (cur && cur->subreq) {
1135 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1136 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1137 "cancel opcode[%s] mid %llu\n",
1138 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1139 (unsigned long long)found_id ));
1140 tevent_req_cancel(cur->subreq);
1143 return NT_STATUS_OK;
1146 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1147 size_t expected_body_size)
1149 const uint8_t *inhdr;
1150 uint16_t opcode;
1151 const uint8_t *inbody;
1152 int i = req->current_idx;
1153 size_t body_size;
1154 size_t min_dyn_size = expected_body_size & 0x00000001;
1157 * The following should be checked already.
1159 if ((i+2) > req->in.vector_count) {
1160 return NT_STATUS_INTERNAL_ERROR;
1162 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1163 return NT_STATUS_INTERNAL_ERROR;
1165 if (req->in.vector[i+1].iov_len < 2) {
1166 return NT_STATUS_INTERNAL_ERROR;
1169 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1170 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1172 switch (opcode) {
1173 case SMB2_OP_IOCTL:
1174 case SMB2_OP_GETINFO:
1175 min_dyn_size = 0;
1176 break;
1180 * Now check the expected body size,
1181 * where the last byte might be in the
1182 * dynnamic section..
1184 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1185 return NT_STATUS_INVALID_PARAMETER;
1187 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1188 return NT_STATUS_INVALID_PARAMETER;
1191 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1193 body_size = SVAL(inbody, 0x00);
1194 if (body_size != expected_body_size) {
1195 return NT_STATUS_INVALID_PARAMETER;
1198 return NT_STATUS_OK;
1201 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1203 const uint8_t *inhdr;
1204 int i = req->current_idx;
1205 uint16_t opcode;
1206 uint32_t flags;
1207 uint64_t mid;
1208 NTSTATUS status;
1209 NTSTATUS session_status;
1210 uint32_t allowed_flags;
1211 NTSTATUS return_value;
1213 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1215 /* TODO: verify more things */
1217 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1218 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1219 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1220 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1221 smb2_opcode_name(opcode),
1222 (unsigned long long)mid));
1224 if (get_Protocol() >= PROTOCOL_SMB2) {
1226 * once the protocol is negotiated
1227 * SMB2_OP_NEGPROT is not allowed anymore
1229 if (opcode == SMB2_OP_NEGPROT) {
1230 /* drop the connection */
1231 return NT_STATUS_INVALID_PARAMETER;
1233 } else {
1235 * if the protocol is not negotiated yet
1236 * only SMB2_OP_NEGPROT is allowed.
1238 if (opcode != SMB2_OP_NEGPROT) {
1239 /* drop the connection */
1240 return NT_STATUS_INVALID_PARAMETER;
1244 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1245 SMB2_HDR_FLAG_SIGNED |
1246 SMB2_HDR_FLAG_DFS;
1247 if (opcode == SMB2_OP_CANCEL) {
1248 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1250 if ((flags & ~allowed_flags) != 0) {
1251 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1255 * Check if the client provided a valid session id,
1256 * if so smbd_smb2_request_check_session() calls
1257 * set_current_user_info().
1259 * As some command don't require a valid session id
1260 * we defer the check of the session_status
1262 session_status = smbd_smb2_request_check_session(req);
1264 req->do_signing = false;
1265 if (flags & SMB2_HDR_FLAG_SIGNED) {
1266 if (!NT_STATUS_IS_OK(session_status)) {
1267 return smbd_smb2_request_error(req, session_status);
1270 req->do_signing = true;
1271 status = smb2_signing_check_pdu(req->session->session_key,
1272 &req->in.vector[i], 3);
1273 if (!NT_STATUS_IS_OK(status)) {
1274 return smbd_smb2_request_error(req, status);
1276 } else if (opcode == SMB2_OP_CANCEL) {
1277 /* Cancel requests are allowed to skip the signing */
1278 } else if (req->session && req->session->do_signing) {
1279 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1282 if (flags & SMB2_HDR_FLAG_CHAINED) {
1284 * This check is mostly for giving the correct error code
1285 * for compounded requests.
1287 * TODO: we may need to move this after the session
1288 * and tcon checks.
1290 if (!NT_STATUS_IS_OK(req->next_status)) {
1291 return smbd_smb2_request_error(req, req->next_status);
1293 } else {
1294 req->compat_chain_fsp = NULL;
1297 if (req->compound_related) {
1298 req->sconn->smb2.compound_related_in_progress = true;
1301 switch (opcode) {
1302 case SMB2_OP_NEGPROT:
1303 /* This call needs to be run as root */
1304 change_to_root_user();
1307 START_PROFILE(smb2_negprot);
1308 return_value = smbd_smb2_request_process_negprot(req);
1309 END_PROFILE(smb2_negprot);
1311 break;
1313 case SMB2_OP_SESSSETUP:
1314 /* This call needs to be run as root */
1315 change_to_root_user();
1318 START_PROFILE(smb2_sesssetup);
1319 return_value = smbd_smb2_request_process_sesssetup(req);
1320 END_PROFILE(smb2_sesssetup);
1322 break;
1324 case SMB2_OP_LOGOFF:
1325 if (!NT_STATUS_IS_OK(session_status)) {
1326 return_value = smbd_smb2_request_error(req, session_status);
1327 break;
1330 /* This call needs to be run as root */
1331 change_to_root_user();
1334 START_PROFILE(smb2_logoff);
1335 return_value = smbd_smb2_request_process_logoff(req);
1336 END_PROFILE(smb2_logoff);
1338 break;
1340 case SMB2_OP_TCON:
1341 if (!NT_STATUS_IS_OK(session_status)) {
1342 return_value = smbd_smb2_request_error(req, session_status);
1343 break;
1347 * This call needs to be run as root.
1349 * smbd_smb2_request_process_tcon()
1350 * calls make_connection_snum(), which will call
1351 * change_to_user(), when needed.
1353 change_to_root_user();
1356 START_PROFILE(smb2_tcon);
1357 return_value = smbd_smb2_request_process_tcon(req);
1358 END_PROFILE(smb2_tcon);
1360 break;
1362 case SMB2_OP_TDIS:
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 user.
1370 * smbd_smb2_request_check_tcon()
1371 * calls change_to_user() on success.
1373 status = smbd_smb2_request_check_tcon(req);
1374 if (!NT_STATUS_IS_OK(status)) {
1375 return_value = smbd_smb2_request_error(req, status);
1376 break;
1378 /* This call needs to be run as root */
1379 change_to_root_user();
1383 START_PROFILE(smb2_tdis);
1384 return_value = smbd_smb2_request_process_tdis(req);
1385 END_PROFILE(smb2_tdis);
1387 break;
1389 case SMB2_OP_CREATE:
1390 if (!NT_STATUS_IS_OK(session_status)) {
1391 return_value = smbd_smb2_request_error(req, session_status);
1392 break;
1395 * This call needs to be run as user.
1397 * smbd_smb2_request_check_tcon()
1398 * calls change_to_user() on success.
1400 status = smbd_smb2_request_check_tcon(req);
1401 if (!NT_STATUS_IS_OK(status)) {
1402 return_value = smbd_smb2_request_error(req, status);
1403 break;
1407 START_PROFILE(smb2_create);
1408 return_value = smbd_smb2_request_process_create(req);
1409 END_PROFILE(smb2_create);
1411 break;
1413 case SMB2_OP_CLOSE:
1414 if (!NT_STATUS_IS_OK(session_status)) {
1415 return_value = smbd_smb2_request_error(req, session_status);
1416 break;
1419 * This call needs to be run as user.
1421 * smbd_smb2_request_check_tcon()
1422 * calls change_to_user() on success.
1424 status = smbd_smb2_request_check_tcon(req);
1425 if (!NT_STATUS_IS_OK(status)) {
1426 return_value = smbd_smb2_request_error(req, status);
1427 break;
1431 START_PROFILE(smb2_close);
1432 return_value = smbd_smb2_request_process_close(req);
1433 END_PROFILE(smb2_close);
1435 break;
1437 case SMB2_OP_FLUSH:
1438 if (!NT_STATUS_IS_OK(session_status)) {
1439 return_value = smbd_smb2_request_error(req, session_status);
1440 break;
1443 * This call needs to be run as user.
1445 * smbd_smb2_request_check_tcon()
1446 * calls change_to_user() on success.
1448 status = smbd_smb2_request_check_tcon(req);
1449 if (!NT_STATUS_IS_OK(status)) {
1450 return_value = smbd_smb2_request_error(req, status);
1451 break;
1455 START_PROFILE(smb2_flush);
1456 return_value = smbd_smb2_request_process_flush(req);
1457 END_PROFILE(smb2_flush);
1459 break;
1461 case SMB2_OP_READ:
1462 if (!NT_STATUS_IS_OK(session_status)) {
1463 return_value = smbd_smb2_request_error(req, session_status);
1464 break;
1467 * This call needs to be run as user.
1469 * smbd_smb2_request_check_tcon()
1470 * calls change_to_user() on success.
1472 status = smbd_smb2_request_check_tcon(req);
1473 if (!NT_STATUS_IS_OK(status)) {
1474 return_value = smbd_smb2_request_error(req, status);
1475 break;
1479 START_PROFILE(smb2_read);
1480 return_value = smbd_smb2_request_process_read(req);
1481 END_PROFILE(smb2_read);
1483 break;
1485 case SMB2_OP_WRITE:
1486 if (!NT_STATUS_IS_OK(session_status)) {
1487 return_value = smbd_smb2_request_error(req, session_status);
1488 break;
1491 * This call needs to be run as user.
1493 * smbd_smb2_request_check_tcon()
1494 * calls change_to_user() on success.
1496 status = smbd_smb2_request_check_tcon(req);
1497 if (!NT_STATUS_IS_OK(status)) {
1498 return_value = smbd_smb2_request_error(req, status);
1499 break;
1503 START_PROFILE(smb2_write);
1504 return_value = smbd_smb2_request_process_write(req);
1505 END_PROFILE(smb2_write);
1507 break;
1509 case SMB2_OP_LOCK:
1510 if (!NT_STATUS_IS_OK(session_status)) {
1511 /* Too ugly to live ? JRA. */
1512 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1513 session_status = NT_STATUS_FILE_CLOSED;
1515 return_value = smbd_smb2_request_error(req, session_status);
1516 break;
1519 * This call needs to be run as user.
1521 * smbd_smb2_request_check_tcon()
1522 * calls change_to_user() on success.
1524 status = smbd_smb2_request_check_tcon(req);
1525 if (!NT_STATUS_IS_OK(status)) {
1526 /* Too ugly to live ? JRA. */
1527 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1528 status = NT_STATUS_FILE_CLOSED;
1530 return_value = smbd_smb2_request_error(req, status);
1531 break;
1535 START_PROFILE(smb2_lock);
1536 return_value = smbd_smb2_request_process_lock(req);
1537 END_PROFILE(smb2_lock);
1539 break;
1541 case SMB2_OP_IOCTL:
1542 if (!NT_STATUS_IS_OK(session_status)) {
1543 return_value = smbd_smb2_request_error(req, session_status);
1544 break;
1547 * This call needs to be run as user.
1549 * smbd_smb2_request_check_tcon()
1550 * calls change_to_user() on success.
1552 status = smbd_smb2_request_check_tcon(req);
1553 if (!NT_STATUS_IS_OK(status)) {
1554 return_value = smbd_smb2_request_error(req, status);
1555 break;
1559 START_PROFILE(smb2_ioctl);
1560 return_value = smbd_smb2_request_process_ioctl(req);
1561 END_PROFILE(smb2_ioctl);
1563 break;
1565 case SMB2_OP_CANCEL:
1567 * This call needs to be run as root
1569 * That is what we also do in the SMB1 case.
1571 change_to_root_user();
1574 START_PROFILE(smb2_cancel);
1575 return_value = smbd_smb2_request_process_cancel(req);
1576 END_PROFILE(smb2_cancel);
1578 break;
1580 case SMB2_OP_KEEPALIVE:
1581 /* This call needs to be run as root */
1582 change_to_root_user();
1585 START_PROFILE(smb2_keepalive);
1586 return_value = smbd_smb2_request_process_keepalive(req);
1587 END_PROFILE(smb2_keepalive);
1589 break;
1591 case SMB2_OP_FIND:
1592 if (!NT_STATUS_IS_OK(session_status)) {
1593 return_value = smbd_smb2_request_error(req, session_status);
1594 break;
1597 * This call needs to be run as user.
1599 * smbd_smb2_request_check_tcon()
1600 * calls change_to_user() on success.
1602 status = smbd_smb2_request_check_tcon(req);
1603 if (!NT_STATUS_IS_OK(status)) {
1604 return_value = smbd_smb2_request_error(req, status);
1605 break;
1609 START_PROFILE(smb2_find);
1610 return_value = smbd_smb2_request_process_find(req);
1611 END_PROFILE(smb2_find);
1613 break;
1615 case SMB2_OP_NOTIFY:
1616 if (!NT_STATUS_IS_OK(session_status)) {
1617 return_value = smbd_smb2_request_error(req, session_status);
1618 break;
1621 * This call needs to be run as user.
1623 * smbd_smb2_request_check_tcon()
1624 * calls change_to_user() on success.
1626 status = smbd_smb2_request_check_tcon(req);
1627 if (!NT_STATUS_IS_OK(status)) {
1628 return_value = smbd_smb2_request_error(req, status);
1629 break;
1633 START_PROFILE(smb2_notify);
1634 return_value = smbd_smb2_request_process_notify(req);
1635 END_PROFILE(smb2_notify);
1637 break;
1639 case SMB2_OP_GETINFO:
1640 if (!NT_STATUS_IS_OK(session_status)) {
1641 return_value = smbd_smb2_request_error(req, session_status);
1642 break;
1645 * This call needs to be run as user.
1647 * smbd_smb2_request_check_tcon()
1648 * calls change_to_user() on success.
1650 status = smbd_smb2_request_check_tcon(req);
1651 if (!NT_STATUS_IS_OK(status)) {
1652 return_value = smbd_smb2_request_error(req, status);
1653 break;
1657 START_PROFILE(smb2_getinfo);
1658 return_value = smbd_smb2_request_process_getinfo(req);
1659 END_PROFILE(smb2_getinfo);
1661 break;
1663 case SMB2_OP_SETINFO:
1664 if (!NT_STATUS_IS_OK(session_status)) {
1665 return_value = smbd_smb2_request_error(req, session_status);
1666 break;
1669 * This call needs to be run as user.
1671 * smbd_smb2_request_check_tcon()
1672 * calls change_to_user() on success.
1674 status = smbd_smb2_request_check_tcon(req);
1675 if (!NT_STATUS_IS_OK(status)) {
1676 return_value = smbd_smb2_request_error(req, status);
1677 break;
1681 START_PROFILE(smb2_setinfo);
1682 return_value = smbd_smb2_request_process_setinfo(req);
1683 END_PROFILE(smb2_setinfo);
1685 break;
1687 case SMB2_OP_BREAK:
1688 if (!NT_STATUS_IS_OK(session_status)) {
1689 return_value = smbd_smb2_request_error(req, session_status);
1690 break;
1693 * This call needs to be run as user.
1695 * smbd_smb2_request_check_tcon()
1696 * calls change_to_user() on success.
1698 status = smbd_smb2_request_check_tcon(req);
1699 if (!NT_STATUS_IS_OK(status)) {
1700 return_value = smbd_smb2_request_error(req, status);
1701 break;
1705 START_PROFILE(smb2_break);
1706 return_value = smbd_smb2_request_process_break(req);
1707 END_PROFILE(smb2_break);
1709 break;
1711 default:
1712 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1713 break;
1715 return return_value;
1718 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1720 struct tevent_req *subreq;
1721 int i = req->current_idx;
1723 req->subreq = NULL;
1725 req->current_idx += 3;
1727 if (req->current_idx < req->out.vector_count) {
1729 * We must process the remaining compound
1730 * SMB2 requests before any new incoming SMB2
1731 * requests. This is because incoming SMB2
1732 * requests may include a cancel for a
1733 * compound request we haven't processed
1734 * yet.
1736 struct tevent_immediate *im = tevent_create_immediate(req);
1737 if (!im) {
1738 return NT_STATUS_NO_MEMORY;
1740 tevent_schedule_immediate(im,
1741 req->sconn->smb2.event_ctx,
1742 smbd_smb2_request_dispatch_immediate,
1743 req);
1744 return NT_STATUS_OK;
1747 if (req->compound_related) {
1748 req->sconn->smb2.compound_related_in_progress = false;
1751 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1753 /* Set credit for these operations (zero credits if this
1754 is a final reply for an async operation). */
1755 smb2_calculate_credits(req, req);
1757 if (req->do_signing) {
1758 NTSTATUS status;
1759 status = smb2_signing_sign_pdu(req->session->session_key,
1760 &req->out.vector[i], 3);
1761 if (!NT_STATUS_IS_OK(status)) {
1762 return status;
1766 if (DEBUGLEVEL >= 10) {
1767 dbgtext("smbd_smb2_request_reply: sending...\n");
1768 print_req_vectors(req);
1771 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1772 if (req->out.vector_count == 4 &&
1773 req->out.vector[3].iov_base == NULL &&
1774 req->out.vector[3].iov_len != 0) {
1775 /* Dynamic part is NULL. Chop it off,
1776 We're going to send it via sendfile. */
1777 req->out.vector_count -= 1;
1780 subreq = tstream_writev_queue_send(req,
1781 req->sconn->smb2.event_ctx,
1782 req->sconn->smb2.stream,
1783 req->sconn->smb2.send_queue,
1784 req->out.vector,
1785 req->out.vector_count);
1786 if (subreq == NULL) {
1787 return NT_STATUS_NO_MEMORY;
1789 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1791 * We're done with this request -
1792 * move it off the "being processed" queue.
1794 DLIST_REMOVE(req->sconn->smb2.requests, req);
1796 return NT_STATUS_OK;
1799 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
1801 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1802 struct tevent_immediate *im,
1803 void *private_data)
1805 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1806 struct smbd_smb2_request);
1807 struct smbd_server_connection *sconn = req->sconn;
1808 NTSTATUS status;
1810 TALLOC_FREE(im);
1812 if (DEBUGLEVEL >= 10) {
1813 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1814 req->current_idx, req->in.vector_count));
1815 print_req_vectors(req);
1818 status = smbd_smb2_request_dispatch(req);
1819 if (!NT_STATUS_IS_OK(status)) {
1820 smbd_server_connection_terminate(sconn, nt_errstr(status));
1821 return;
1824 status = smbd_smb2_request_next_incoming(sconn);
1825 if (!NT_STATUS_IS_OK(status)) {
1826 smbd_server_connection_terminate(sconn, nt_errstr(status));
1827 return;
1831 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1833 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1834 struct smbd_smb2_request);
1835 struct smbd_server_connection *sconn = req->sconn;
1836 int ret;
1837 int sys_errno;
1838 NTSTATUS status;
1840 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1841 TALLOC_FREE(subreq);
1842 TALLOC_FREE(req);
1843 if (ret == -1) {
1844 status = map_nt_error_from_unix(sys_errno);
1845 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1846 nt_errstr(status)));
1847 smbd_server_connection_terminate(sconn, nt_errstr(status));
1848 return;
1851 status = smbd_smb2_request_next_incoming(sconn);
1852 if (!NT_STATUS_IS_OK(status)) {
1853 smbd_server_connection_terminate(sconn, nt_errstr(status));
1854 return;
1858 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1859 NTSTATUS status,
1860 DATA_BLOB body, DATA_BLOB *dyn,
1861 const char *location)
1863 uint8_t *outhdr;
1864 int i = req->current_idx;
1865 uint32_t next_command_ofs;
1867 DEBUG(10,("smbd_smb2_request_done_ex: "
1868 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1869 i, nt_errstr(status), (unsigned int)body.length,
1870 dyn ? "yes": "no",
1871 (unsigned int)(dyn ? dyn->length : 0),
1872 location));
1874 if (body.length < 2) {
1875 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1878 if ((body.length % 2) != 0) {
1879 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1882 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1884 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1885 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1887 req->out.vector[i+1].iov_base = (void *)body.data;
1888 req->out.vector[i+1].iov_len = body.length;
1890 if (dyn) {
1891 req->out.vector[i+2].iov_base = (void *)dyn->data;
1892 req->out.vector[i+2].iov_len = dyn->length;
1893 } else {
1894 req->out.vector[i+2].iov_base = NULL;
1895 req->out.vector[i+2].iov_len = 0;
1898 /* see if we need to recalculate the offset to the next response */
1899 if (next_command_ofs > 0) {
1900 next_command_ofs = SMB2_HDR_BODY;
1901 next_command_ofs += req->out.vector[i+1].iov_len;
1902 next_command_ofs += req->out.vector[i+2].iov_len;
1905 if ((next_command_ofs % 8) != 0) {
1906 size_t pad_size = 8 - (next_command_ofs % 8);
1907 if (req->out.vector[i+2].iov_len == 0) {
1909 * if the dyn buffer is empty
1910 * we can use it to add padding
1912 uint8_t *pad;
1914 pad = talloc_zero_array(req->out.vector,
1915 uint8_t, pad_size);
1916 if (pad == NULL) {
1917 return smbd_smb2_request_error(req,
1918 NT_STATUS_NO_MEMORY);
1921 req->out.vector[i+2].iov_base = (void *)pad;
1922 req->out.vector[i+2].iov_len = pad_size;
1923 } else {
1925 * For now we copy the dynamic buffer
1926 * and add the padding to the new buffer
1928 size_t old_size;
1929 uint8_t *old_dyn;
1930 size_t new_size;
1931 uint8_t *new_dyn;
1933 old_size = req->out.vector[i+2].iov_len;
1934 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
1936 new_size = old_size + pad_size;
1937 new_dyn = talloc_zero_array(req->out.vector,
1938 uint8_t, new_size);
1939 if (new_dyn == NULL) {
1940 return smbd_smb2_request_error(req,
1941 NT_STATUS_NO_MEMORY);
1944 memcpy(new_dyn, old_dyn, old_size);
1945 memset(new_dyn + old_size, 0, pad_size);
1947 req->out.vector[i+2].iov_base = (void *)new_dyn;
1948 req->out.vector[i+2].iov_len = new_size;
1950 next_command_ofs += pad_size;
1953 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1955 return smbd_smb2_request_reply(req);
1958 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
1959 NTSTATUS status,
1960 DATA_BLOB *info,
1961 const char *location)
1963 DATA_BLOB body;
1964 int i = req->current_idx;
1965 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
1967 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1968 i, nt_errstr(status), info ? " +info" : "",
1969 location));
1971 body.data = outhdr + SMB2_HDR_BODY;
1972 body.length = 8;
1973 SSVAL(body.data, 0, 9);
1975 if (info) {
1976 SIVAL(body.data, 0x04, info->length);
1977 } else {
1978 /* Allocated size of req->out.vector[i].iov_base
1979 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
1980 * 1 byte without having to do an alloc.
1982 info = talloc_zero_array(req->out.vector,
1983 DATA_BLOB,
1985 if (!info) {
1986 return NT_STATUS_NO_MEMORY;
1988 info->data = ((uint8_t *)outhdr) +
1989 OUTVEC_ALLOC_SIZE - 1;
1990 info->length = 1;
1991 SCVAL(info->data, 0, 0);
1995 * if a request fails, all other remaining
1996 * compounded requests should fail too
1998 req->next_status = NT_STATUS_INVALID_PARAMETER;
2000 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2004 struct smbd_smb2_send_oplock_break_state {
2005 struct smbd_server_connection *sconn;
2006 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2007 struct iovec vector;
2010 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2012 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2013 uint64_t file_id_persistent,
2014 uint64_t file_id_volatile,
2015 uint8_t oplock_level)
2017 struct smbd_smb2_send_oplock_break_state *state;
2018 struct tevent_req *subreq;
2019 uint8_t *hdr;
2020 uint8_t *body;
2022 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2023 if (state == NULL) {
2024 return NT_STATUS_NO_MEMORY;
2026 state->sconn = sconn;
2028 state->vector.iov_base = (void *)state->buf;
2029 state->vector.iov_len = sizeof(state->buf);
2031 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2032 hdr = state->buf + 4;
2033 body = hdr + SMB2_HDR_BODY;
2035 SIVAL(hdr, 0, SMB2_MAGIC);
2036 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2037 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2038 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2039 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2040 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2041 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2042 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2043 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2044 SIVAL(hdr, SMB2_HDR_PID, 0);
2045 SIVAL(hdr, SMB2_HDR_TID, 0);
2046 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2047 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2049 SSVAL(body, 0x00, 0x18);
2051 SCVAL(body, 0x02, oplock_level);
2052 SCVAL(body, 0x03, 0); /* reserved */
2053 SIVAL(body, 0x04, 0); /* reserved */
2054 SBVAL(body, 0x08, file_id_persistent);
2055 SBVAL(body, 0x10, file_id_volatile);
2057 subreq = tstream_writev_queue_send(state,
2058 sconn->smb2.event_ctx,
2059 sconn->smb2.stream,
2060 sconn->smb2.send_queue,
2061 &state->vector, 1);
2062 if (subreq == NULL) {
2063 return NT_STATUS_NO_MEMORY;
2065 tevent_req_set_callback(subreq,
2066 smbd_smb2_oplock_break_writev_done,
2067 state);
2069 return NT_STATUS_OK;
2072 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2074 struct smbd_smb2_send_oplock_break_state *state =
2075 tevent_req_callback_data(subreq,
2076 struct smbd_smb2_send_oplock_break_state);
2077 struct smbd_server_connection *sconn = state->sconn;
2078 int ret;
2079 int sys_errno;
2081 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2082 TALLOC_FREE(subreq);
2083 if (ret == -1) {
2084 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2085 smbd_server_connection_terminate(sconn, nt_errstr(status));
2086 return;
2089 TALLOC_FREE(state);
2092 struct smbd_smb2_request_read_state {
2093 size_t missing;
2094 bool asked_for_header;
2095 struct smbd_smb2_request *smb2_req;
2098 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2099 void *private_data,
2100 TALLOC_CTX *mem_ctx,
2101 struct iovec **_vector,
2102 size_t *_count);
2103 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2105 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2106 struct tevent_context *ev,
2107 struct smbd_server_connection *sconn)
2109 struct tevent_req *req;
2110 struct smbd_smb2_request_read_state *state;
2111 struct tevent_req *subreq;
2113 req = tevent_req_create(mem_ctx, &state,
2114 struct smbd_smb2_request_read_state);
2115 if (req == NULL) {
2116 return NULL;
2118 state->missing = 0;
2119 state->asked_for_header = false;
2121 state->smb2_req = smbd_smb2_request_allocate(state);
2122 if (tevent_req_nomem(state->smb2_req, req)) {
2123 return tevent_req_post(req, ev);
2125 state->smb2_req->sconn = sconn;
2127 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2128 sconn->smb2.recv_queue,
2129 smbd_smb2_request_next_vector,
2130 state);
2131 if (tevent_req_nomem(subreq, req)) {
2132 return tevent_req_post(req, ev);
2134 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2136 return req;
2139 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2140 void *private_data,
2141 TALLOC_CTX *mem_ctx,
2142 struct iovec **_vector,
2143 size_t *_count)
2145 struct smbd_smb2_request_read_state *state =
2146 talloc_get_type_abort(private_data,
2147 struct smbd_smb2_request_read_state);
2148 struct smbd_smb2_request *req = state->smb2_req;
2149 struct iovec *vector;
2150 int idx = req->in.vector_count;
2151 size_t len = 0;
2152 uint8_t *buf = NULL;
2154 if (req->in.vector_count == 0) {
2156 * first we need to get the NBT header
2158 req->in.vector = talloc_array(req, struct iovec,
2159 req->in.vector_count + 1);
2160 if (req->in.vector == NULL) {
2161 return -1;
2163 req->in.vector_count += 1;
2165 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2166 req->in.vector[idx].iov_len = 4;
2168 vector = talloc_array(mem_ctx, struct iovec, 1);
2169 if (vector == NULL) {
2170 return -1;
2173 vector[0] = req->in.vector[idx];
2175 *_vector = vector;
2176 *_count = 1;
2177 return 0;
2180 if (req->in.vector_count == 1) {
2182 * Now we analyze the NBT header
2184 state->missing = smb2_len(req->in.vector[0].iov_base);
2186 if (state->missing == 0) {
2187 /* if there're no remaining bytes, we're done */
2188 *_vector = NULL;
2189 *_count = 0;
2190 return 0;
2193 req->in.vector = talloc_realloc(req, req->in.vector,
2194 struct iovec,
2195 req->in.vector_count + 1);
2196 if (req->in.vector == NULL) {
2197 return -1;
2199 req->in.vector_count += 1;
2201 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2203 * it's a special NBT message,
2204 * so get all remaining bytes
2206 len = state->missing;
2207 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2209 * it's an invalid message, just read what we can get
2210 * and let the caller handle the error
2212 len = state->missing;
2213 } else {
2215 * We assume it's a SMB2 request,
2216 * and we first get the header and the
2217 * first 2 bytes (the struct size) of the body
2219 len = SMB2_HDR_BODY + 2;
2221 state->asked_for_header = true;
2224 state->missing -= len;
2226 buf = talloc_array(req->in.vector, uint8_t, len);
2227 if (buf == NULL) {
2228 return -1;
2231 req->in.vector[idx].iov_base = (void *)buf;
2232 req->in.vector[idx].iov_len = len;
2234 vector = talloc_array(mem_ctx, struct iovec, 1);
2235 if (vector == NULL) {
2236 return -1;
2239 vector[0] = req->in.vector[idx];
2241 *_vector = vector;
2242 *_count = 1;
2243 return 0;
2246 if (state->missing == 0) {
2247 /* if there're no remaining bytes, we're done */
2248 *_vector = NULL;
2249 *_count = 0;
2250 return 0;
2253 if (state->asked_for_header) {
2254 const uint8_t *hdr;
2255 size_t full_size;
2256 size_t next_command_ofs;
2257 size_t body_size;
2258 uint8_t *body;
2259 size_t dyn_size;
2260 uint8_t *dyn;
2261 bool invalid = false;
2263 state->asked_for_header = false;
2266 * We got the SMB2 header and the first 2 bytes
2267 * of the body. We fix the size to just the header
2268 * and manually copy the 2 first bytes to the body section
2270 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2271 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2273 /* allocate vectors for body and dynamic areas */
2274 req->in.vector = talloc_realloc(req, req->in.vector,
2275 struct iovec,
2276 req->in.vector_count + 2);
2277 if (req->in.vector == NULL) {
2278 return -1;
2280 req->in.vector_count += 2;
2282 full_size = state->missing + SMB2_HDR_BODY + 2;
2283 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2284 body_size = SVAL(hdr, SMB2_HDR_BODY);
2286 if (next_command_ofs != 0) {
2287 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2289 * this is invalid, just return a zero
2290 * body and let the caller deal with the error
2292 invalid = true;
2293 } else if (next_command_ofs > full_size) {
2295 * this is invalid, just return a zero
2296 * body and let the caller deal with the error
2298 invalid = true;
2299 } else {
2300 full_size = next_command_ofs;
2304 if (!invalid) {
2305 if (body_size < 2) {
2307 * this is invalid, just return a zero
2308 * body and let the caller deal with the error
2310 invalid = true;
2313 if ((body_size % 2) != 0) {
2314 body_size -= 1;
2317 if (body_size > (full_size - SMB2_HDR_BODY)) {
2319 * this is invalid, just return a zero
2320 * body and let the caller deal with the error
2322 invalid = true;
2326 if (invalid) {
2327 /* the caller should check this */
2328 body_size = 2;
2331 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2333 state->missing -= (body_size - 2) + dyn_size;
2335 body = talloc_array(req->in.vector, uint8_t, body_size);
2336 if (body == NULL) {
2337 return -1;
2340 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2341 if (dyn == NULL) {
2342 return -1;
2345 req->in.vector[idx].iov_base = (void *)body;
2346 req->in.vector[idx].iov_len = body_size;
2347 req->in.vector[idx+1].iov_base = (void *)dyn;
2348 req->in.vector[idx+1].iov_len = dyn_size;
2350 vector = talloc_array(mem_ctx, struct iovec, 2);
2351 if (vector == NULL) {
2352 return -1;
2356 * the first 2 bytes of the body were already fetched
2357 * together with the header
2359 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2360 vector[0].iov_base = body + 2;
2361 vector[0].iov_len = body_size - 2;
2363 vector[1] = req->in.vector[idx+1];
2365 *_vector = vector;
2366 *_count = 2;
2367 return 0;
2371 * when we endup here, we're looking for a new SMB2 request
2372 * next. And we ask for its header and the first 2 bytes of
2373 * the body (like we did for the first SMB2 request).
2376 req->in.vector = talloc_realloc(req, req->in.vector,
2377 struct iovec,
2378 req->in.vector_count + 1);
2379 if (req->in.vector == NULL) {
2380 return -1;
2382 req->in.vector_count += 1;
2385 * We assume it's a SMB2 request,
2386 * and we first get the header and the
2387 * first 2 bytes (the struct size) of the body
2389 len = SMB2_HDR_BODY + 2;
2391 if (len > state->missing) {
2392 /* let the caller handle the error */
2393 len = state->missing;
2396 state->missing -= len;
2397 state->asked_for_header = true;
2399 buf = talloc_array(req->in.vector, uint8_t, len);
2400 if (buf == NULL) {
2401 return -1;
2404 req->in.vector[idx].iov_base = (void *)buf;
2405 req->in.vector[idx].iov_len = len;
2407 vector = talloc_array(mem_ctx, struct iovec, 1);
2408 if (vector == NULL) {
2409 return -1;
2412 vector[0] = req->in.vector[idx];
2414 *_vector = vector;
2415 *_count = 1;
2416 return 0;
2419 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2421 struct tevent_req *req =
2422 tevent_req_callback_data(subreq,
2423 struct tevent_req);
2424 int ret;
2425 int sys_errno;
2426 NTSTATUS status;
2428 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2429 if (ret == -1) {
2430 status = map_nt_error_from_unix(sys_errno);
2431 tevent_req_nterror(req, status);
2432 return;
2435 tevent_req_done(req);
2438 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2439 TALLOC_CTX *mem_ctx,
2440 struct smbd_smb2_request **_smb2_req)
2442 struct smbd_smb2_request_read_state *state =
2443 tevent_req_data(req,
2444 struct smbd_smb2_request_read_state);
2445 NTSTATUS status;
2447 if (tevent_req_is_nterror(req, &status)) {
2448 tevent_req_received(req);
2449 return status;
2452 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2453 *_smb2_req = state->smb2_req;
2454 tevent_req_received(req);
2455 return NT_STATUS_OK;
2458 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2460 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2462 size_t max_send_queue_len;
2463 size_t cur_send_queue_len;
2464 struct tevent_req *subreq;
2466 if (sconn->smb2.compound_related_in_progress) {
2468 * Can't read another until the related
2469 * compound is done.
2471 return NT_STATUS_OK;
2474 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2476 * if there is already a smbd_smb2_request_read
2477 * pending, we are done.
2479 return NT_STATUS_OK;
2482 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2483 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2485 if (cur_send_queue_len > max_send_queue_len) {
2487 * if we have a lot of requests to send,
2488 * we wait until they are on the wire until we
2489 * ask for the next request.
2491 return NT_STATUS_OK;
2494 /* ask for the next request */
2495 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2496 if (subreq == NULL) {
2497 return NT_STATUS_NO_MEMORY;
2499 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2501 return NT_STATUS_OK;
2504 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2505 const uint8_t *inbuf, size_t size)
2507 NTSTATUS status;
2508 struct smbd_smb2_request *req = NULL;
2510 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2511 (unsigned int)size));
2513 status = smbd_initialize_smb2(sconn);
2514 if (!NT_STATUS_IS_OK(status)) {
2515 smbd_server_connection_terminate(sconn, nt_errstr(status));
2516 return;
2519 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2520 if (!NT_STATUS_IS_OK(status)) {
2521 smbd_server_connection_terminate(sconn, nt_errstr(status));
2522 return;
2525 status = smbd_smb2_request_setup_out(req);
2526 if (!NT_STATUS_IS_OK(status)) {
2527 smbd_server_connection_terminate(sconn, nt_errstr(status));
2528 return;
2531 status = smbd_smb2_request_dispatch(req);
2532 if (!NT_STATUS_IS_OK(status)) {
2533 smbd_server_connection_terminate(sconn, nt_errstr(status));
2534 return;
2537 status = smbd_smb2_request_next_incoming(sconn);
2538 if (!NT_STATUS_IS_OK(status)) {
2539 smbd_server_connection_terminate(sconn, nt_errstr(status));
2540 return;
2543 sconn->num_requests++;
2546 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2548 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2549 struct smbd_server_connection);
2550 NTSTATUS status;
2551 struct smbd_smb2_request *req = NULL;
2553 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2554 TALLOC_FREE(subreq);
2555 if (!NT_STATUS_IS_OK(status)) {
2556 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2557 nt_errstr(status)));
2558 smbd_server_connection_terminate(sconn, nt_errstr(status));
2559 return;
2562 if (req->in.nbt_hdr[0] != 0x00) {
2563 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2564 req->in.nbt_hdr[0]));
2565 TALLOC_FREE(req);
2566 goto next;
2569 req->current_idx = 1;
2571 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2572 req->current_idx, req->in.vector_count));
2574 status = smbd_smb2_request_validate(req);
2575 if (!NT_STATUS_IS_OK(status)) {
2576 smbd_server_connection_terminate(sconn, nt_errstr(status));
2577 return;
2580 status = smbd_smb2_request_setup_out(req);
2581 if (!NT_STATUS_IS_OK(status)) {
2582 smbd_server_connection_terminate(sconn, nt_errstr(status));
2583 return;
2586 status = smbd_smb2_request_dispatch(req);
2587 if (!NT_STATUS_IS_OK(status)) {
2588 smbd_server_connection_terminate(sconn, nt_errstr(status));
2589 return;
2592 next:
2593 status = smbd_smb2_request_next_incoming(sconn);
2594 if (!NT_STATUS_IS_OK(status)) {
2595 smbd_server_connection_terminate(sconn, nt_errstr(status));
2596 return;
2599 sconn->num_requests++;
2601 /* The timeout_processing function isn't run nearly
2602 often enough to implement 'max log size' without
2603 overrunning the size of the file by many megabytes.
2604 This is especially true if we are running at debug
2605 level 10. Checking every 50 SMB2s is a nice
2606 tradeoff of performance vs log file size overrun. */
2608 if ((sconn->num_requests % 50) == 0 &&
2609 need_to_check_log_size()) {
2610 change_to_root_user();
2611 check_log_size();