s3:smb2_server: add some comments about change_to_user() and change_to_root_user()
[Samba.git] / source3 / smbd / smb2_server.c
blobc5c7a8e4384128324ed8e87c139f23e560488f50
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 talloc_set_destructor(parent, smbd_smb2_request_parent_destructor);
210 talloc_set_destructor(req, smbd_smb2_request_destructor);
212 return req;
215 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
216 const uint8_t *inbuf, size_t size,
217 struct smbd_smb2_request **_req)
219 struct smbd_smb2_request *req;
220 uint32_t protocol_version;
221 const uint8_t *inhdr = NULL;
222 off_t ofs = 0;
223 uint16_t cmd;
224 uint32_t next_command_ofs;
226 if (size < (4 + SMB2_HDR_BODY + 2)) {
227 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
228 return NT_STATUS_INVALID_PARAMETER;
231 inhdr = inbuf + 4;
233 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
234 if (protocol_version != SMB2_MAGIC) {
235 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
236 protocol_version));
237 return NT_STATUS_INVALID_PARAMETER;
240 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
241 if (cmd != SMB2_OP_NEGPROT) {
242 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
243 cmd));
244 return NT_STATUS_INVALID_PARAMETER;
247 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
248 if (next_command_ofs != 0) {
249 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
250 next_command_ofs));
251 return NT_STATUS_INVALID_PARAMETER;
254 req = smbd_smb2_request_allocate(sconn);
255 if (req == NULL) {
256 return NT_STATUS_NO_MEMORY;
258 req->sconn = sconn;
260 talloc_steal(req, inbuf);
262 req->in.vector = talloc_array(req, struct iovec, 4);
263 if (req->in.vector == NULL) {
264 TALLOC_FREE(req);
265 return NT_STATUS_NO_MEMORY;
267 req->in.vector_count = 4;
269 memcpy(req->in.nbt_hdr, inbuf, 4);
271 ofs = 0;
272 req->in.vector[0].iov_base = (void *)req->in.nbt_hdr;
273 req->in.vector[0].iov_len = 4;
274 ofs += req->in.vector[0].iov_len;
276 req->in.vector[1].iov_base = (void *)(inbuf + ofs);
277 req->in.vector[1].iov_len = SMB2_HDR_BODY;
278 ofs += req->in.vector[1].iov_len;
280 req->in.vector[2].iov_base = (void *)(inbuf + ofs);
281 req->in.vector[2].iov_len = SVAL(inbuf, ofs) & 0xFFFE;
282 ofs += req->in.vector[2].iov_len;
284 if (ofs > size) {
285 return NT_STATUS_INVALID_PARAMETER;
288 req->in.vector[3].iov_base = (void *)(inbuf + ofs);
289 req->in.vector[3].iov_len = size - ofs;
290 ofs += req->in.vector[3].iov_len;
292 req->current_idx = 1;
294 *_req = req;
295 return NT_STATUS_OK;
298 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
299 const uint8_t *inhdr)
301 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
302 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
303 uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
304 unsigned int bitmap_offset;
306 if (opcode == SMB2_OP_CANCEL) {
307 /* SMB2_CANCEL requests by definition resend messageids. */
308 return true;
311 if (message_id < sconn->smb2.seqnum_low ||
312 message_id > (sconn->smb2.seqnum_low +
313 (sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR))) {
314 DEBUG(0,("smb2_validate_message_id: bad message_id "
315 "%llu (low = %llu, max = %lu)\n",
316 (unsigned long long)message_id,
317 (unsigned long long)sconn->smb2.seqnum_low,
318 (unsigned long)sconn->smb2.max_credits ));
319 return false;
322 /* client just used a credit. */
323 SMB_ASSERT(sconn->smb2.credits_granted > 0);
324 sconn->smb2.credits_granted -= 1;
326 /* Mark the message_id as seen in the bitmap. */
327 bitmap_offset = (unsigned int)(message_id %
328 (uint64_t)(sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR));
329 if (bitmap_query(credits_bm, bitmap_offset)) {
330 DEBUG(0,("smb2_validate_message_id: duplicate message_id "
331 "%llu (bm offset %u)\n",
332 (unsigned long long)message_id,
333 bitmap_offset));
334 return false;
336 bitmap_set(credits_bm, bitmap_offset);
338 if (message_id == sconn->smb2.seqnum_low + 1) {
339 /* Move the window forward by all the message_id's
340 already seen. */
341 while (bitmap_query(credits_bm, bitmap_offset)) {
342 DEBUG(10,("smb2_validate_message_id: clearing "
343 "id %llu (position %u) from bitmap\n",
344 (unsigned long long)(sconn->smb2.seqnum_low + 1),
345 bitmap_offset ));
346 bitmap_clear(credits_bm, bitmap_offset);
347 sconn->smb2.seqnum_low += 1;
348 bitmap_offset = (bitmap_offset + 1) %
349 (sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR);
353 return true;
356 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
358 int count;
359 int idx;
360 bool compound_related = false;
362 count = req->in.vector_count;
364 if (count < 4) {
365 /* It's not a SMB2 request */
366 return NT_STATUS_INVALID_PARAMETER;
369 for (idx=1; idx < count; idx += 3) {
370 const uint8_t *inhdr = NULL;
371 uint32_t flags;
373 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
374 return NT_STATUS_INVALID_PARAMETER;
377 if (req->in.vector[idx+1].iov_len < 2) {
378 return NT_STATUS_INVALID_PARAMETER;
381 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
383 /* Check the SMB2 header */
384 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
385 return NT_STATUS_INVALID_PARAMETER;
388 if (!smb2_validate_message_id(req->sconn, inhdr)) {
389 return NT_STATUS_INVALID_PARAMETER;
392 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
393 if (idx == 1) {
395 * the 1st request should never have the
396 * SMB2_HDR_FLAG_CHAINED flag set
398 if (flags & SMB2_HDR_FLAG_CHAINED) {
399 req->next_status = NT_STATUS_INVALID_PARAMETER;
400 return NT_STATUS_OK;
402 } else if (idx == 4) {
404 * the 2nd request triggers related vs. unrelated
405 * compounded requests
407 if (flags & SMB2_HDR_FLAG_CHAINED) {
408 compound_related = true;
410 } else if (idx > 4) {
411 #if 0
413 * It seems the this tests are wrong
414 * see the SMB2-COMPOUND test
418 * all other requests should match the 2nd one
420 if (flags & SMB2_HDR_FLAG_CHAINED) {
421 if (!compound_related) {
422 req->next_status =
423 NT_STATUS_INVALID_PARAMETER;
424 return NT_STATUS_OK;
426 } else {
427 if (compound_related) {
428 req->next_status =
429 NT_STATUS_INVALID_PARAMETER;
430 return NT_STATUS_OK;
433 #endif
437 return NT_STATUS_OK;
440 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
441 const struct iovec *in_vector,
442 struct iovec *out_vector)
444 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
445 uint16_t credits_requested = 0;
446 uint16_t credits_granted = 0;
448 if (in_vector != NULL) {
449 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
450 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
453 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
455 /* Remember what we gave out. */
456 credits_granted = MIN(credits_requested, (sconn->smb2.max_credits -
457 sconn->smb2.credits_granted));
459 if (credits_granted == 0 && sconn->smb2.credits_granted == 0) {
460 /* First negprot packet, or ensure the client credits can
461 never drop to zero. */
462 credits_granted = 1;
465 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
466 sconn->smb2.credits_granted += credits_granted;
468 DEBUG(10,("smb2_set_operation_credit: requested %u, "
469 "granted %u, total granted %u\n",
470 (unsigned int)credits_requested,
471 (unsigned int)credits_granted,
472 (unsigned int)sconn->smb2.credits_granted ));
475 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
476 struct smbd_smb2_request *outreq)
478 int count, idx;
480 count = outreq->out.vector_count;
482 for (idx=1; idx < count; idx += 3) {
483 smb2_set_operation_credit(outreq->sconn,
484 &inreq->in.vector[idx],
485 &outreq->out.vector[idx]);
489 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
491 struct iovec *vector;
492 int count;
493 int idx;
495 count = req->in.vector_count;
496 vector = talloc_zero_array(req, struct iovec, count);
497 if (vector == NULL) {
498 return NT_STATUS_NO_MEMORY;
501 vector[0].iov_base = req->out.nbt_hdr;
502 vector[0].iov_len = 4;
503 SIVAL(req->out.nbt_hdr, 0, 0);
505 for (idx=1; idx < count; idx += 3) {
506 const uint8_t *inhdr = NULL;
507 uint32_t in_flags;
508 uint8_t *outhdr = NULL;
509 uint8_t *outbody = NULL;
510 uint32_t next_command_ofs = 0;
511 struct iovec *current = &vector[idx];
513 if ((idx + 3) < count) {
514 /* we have a next command -
515 * setup for the error case. */
516 next_command_ofs = SMB2_HDR_BODY + 9;
519 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
520 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
522 outhdr = talloc_zero_array(vector, uint8_t,
523 OUTVEC_ALLOC_SIZE);
524 if (outhdr == NULL) {
525 return NT_STATUS_NO_MEMORY;
528 outbody = outhdr + SMB2_HDR_BODY;
530 current[0].iov_base = (void *)outhdr;
531 current[0].iov_len = SMB2_HDR_BODY;
533 current[1].iov_base = (void *)outbody;
534 current[1].iov_len = 8;
536 current[2].iov_base = NULL;
537 current[2].iov_len = 0;
539 /* setup the SMB2 header */
540 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
541 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
542 SSVAL(outhdr, SMB2_HDR_EPOCH, 0);
543 SIVAL(outhdr, SMB2_HDR_STATUS,
544 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
545 SSVAL(outhdr, SMB2_HDR_OPCODE,
546 SVAL(inhdr, SMB2_HDR_OPCODE));
547 SIVAL(outhdr, SMB2_HDR_FLAGS,
548 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
549 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
550 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
551 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
552 SIVAL(outhdr, SMB2_HDR_PID,
553 IVAL(inhdr, SMB2_HDR_PID));
554 SIVAL(outhdr, SMB2_HDR_TID,
555 IVAL(inhdr, SMB2_HDR_TID));
556 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
557 BVAL(inhdr, SMB2_HDR_SESSION_ID));
558 memset(outhdr + SMB2_HDR_SIGNATURE, 0, 16);
560 /* setup error body header */
561 SSVAL(outbody, 0x00, 0x08 + 1);
562 SSVAL(outbody, 0x02, 0);
563 SIVAL(outbody, 0x04, 0);
566 req->out.vector = vector;
567 req->out.vector_count = count;
569 /* setup the length of the NBT packet */
570 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
572 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
574 return NT_STATUS_OK;
577 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
578 const char *reason,
579 const char *location)
581 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
582 reason, location));
583 exit_server_cleanly(reason);
586 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
587 struct iovec *outvec,
588 const struct iovec *srcvec)
590 /* vec[0] is always boilerplate and must
591 * be allocated with size OUTVEC_ALLOC_SIZE. */
593 outvec[0].iov_base = talloc_memdup(ctx,
594 srcvec[0].iov_base,
595 OUTVEC_ALLOC_SIZE);
596 if (!outvec[0].iov_base) {
597 return false;
599 outvec[0].iov_len = SMB2_HDR_BODY;
602 * If this is a "standard" vec[1] of length 8,
603 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
604 * then duplicate this. Else use talloc_memdup().
607 if (srcvec[1].iov_len == 8 &&
608 srcvec[1].iov_base ==
609 ((uint8_t *)srcvec[0].iov_base) +
610 SMB2_HDR_BODY) {
611 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
612 SMB2_HDR_BODY;
613 outvec[1].iov_len = 8;
614 } else {
615 outvec[1].iov_base = talloc_memdup(ctx,
616 srcvec[1].iov_base,
617 srcvec[1].iov_len);
618 if (!outvec[1].iov_base) {
619 return false;
621 outvec[1].iov_len = srcvec[1].iov_len;
625 * If this is a "standard" vec[2] of length 1,
626 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
627 * then duplicate this. Else use talloc_memdup().
630 if (srcvec[2].iov_base &&
631 srcvec[2].iov_len) {
632 if (srcvec[2].iov_base ==
633 ((uint8_t *)srcvec[0].iov_base) +
634 (OUTVEC_ALLOC_SIZE - 1) &&
635 srcvec[2].iov_len == 1) {
636 /* Common SMB2 error packet case. */
637 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
638 (OUTVEC_ALLOC_SIZE - 1);
639 } else {
640 outvec[2].iov_base = talloc_memdup(ctx,
641 srcvec[2].iov_base,
642 srcvec[2].iov_len);
643 if (!outvec[2].iov_base) {
644 return false;
647 outvec[2].iov_len = srcvec[2].iov_len;
648 } else {
649 outvec[2].iov_base = NULL;
650 outvec[2].iov_len = 0;
652 return true;
655 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
657 struct smbd_smb2_request *newreq = NULL;
658 struct iovec *outvec = NULL;
659 int count = req->out.vector_count;
660 int i;
662 newreq = smbd_smb2_request_allocate(req->sconn);
663 if (!newreq) {
664 return NULL;
667 newreq->sconn = req->sconn;
668 newreq->session = req->session;
669 newreq->do_signing = req->do_signing;
670 newreq->current_idx = req->current_idx;
671 newreq->async = false;
672 newreq->cancelled = false;
673 /* Note we are leaving:
674 ->tcon
675 ->smb1req
676 ->compat_chain_fsp
677 uninitialized as NULL here as
678 they're not used in the interim
679 response code. JRA. */
681 outvec = talloc_zero_array(newreq, struct iovec, count);
682 if (!outvec) {
683 TALLOC_FREE(newreq);
684 return NULL;
686 newreq->out.vector = outvec;
687 newreq->out.vector_count = count;
689 /* Setup the outvec's identically to req. */
690 outvec[0].iov_base = newreq->out.nbt_hdr;
691 outvec[0].iov_len = 4;
692 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
694 /* Setup the vectors identically to the ones in req. */
695 for (i = 1; i < count; i += 3) {
696 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
697 break;
701 if (i < count) {
702 /* Alloc failed. */
703 TALLOC_FREE(newreq);
704 return NULL;
707 smb2_setup_nbt_length(newreq->out.vector,
708 newreq->out.vector_count);
710 return newreq;
713 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
715 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
717 int i = 0;
718 uint8_t *outhdr = NULL;
719 struct smbd_smb2_request *nreq = NULL;
721 /* Create a new smb2 request we'll use
722 for the interim return. */
723 nreq = dup_smb2_req(req);
724 if (!nreq) {
725 return NT_STATUS_NO_MEMORY;
728 /* Lose the last 3 out vectors. They're the
729 ones we'll be using for the async reply. */
730 nreq->out.vector_count -= 3;
732 smb2_setup_nbt_length(nreq->out.vector,
733 nreq->out.vector_count);
735 /* Step back to the previous reply. */
736 i = nreq->current_idx - 3;
737 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
738 /* And end the chain. */
739 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
741 /* Calculate outgoing credits */
742 smb2_calculate_credits(req, nreq);
744 /* Re-sign if needed. */
745 if (nreq->do_signing) {
746 NTSTATUS status;
747 status = smb2_signing_sign_pdu(nreq->session->session_key,
748 &nreq->out.vector[i], 3);
749 if (!NT_STATUS_IS_OK(status)) {
750 return status;
753 if (DEBUGLEVEL >= 10) {
754 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
755 (unsigned int)nreq->current_idx );
756 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
757 (unsigned int)nreq->out.vector_count );
758 print_req_vectors(nreq);
760 nreq->subreq = tstream_writev_queue_send(nreq,
761 nreq->sconn->smb2.event_ctx,
762 nreq->sconn->smb2.stream,
763 nreq->sconn->smb2.send_queue,
764 nreq->out.vector,
765 nreq->out.vector_count);
767 if (nreq->subreq == NULL) {
768 return NT_STATUS_NO_MEMORY;
771 tevent_req_set_callback(nreq->subreq,
772 smbd_smb2_request_writev_done,
773 nreq);
775 return NT_STATUS_OK;
778 struct smbd_smb2_request_pending_state {
779 struct smbd_server_connection *sconn;
780 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
781 struct iovec vector[3];
784 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
786 struct smbd_smb2_request_pending_state *state =
787 tevent_req_callback_data(subreq,
788 struct smbd_smb2_request_pending_state);
789 struct smbd_server_connection *sconn = state->sconn;
790 int ret;
791 int sys_errno;
793 ret = tstream_writev_queue_recv(subreq, &sys_errno);
794 TALLOC_FREE(subreq);
795 if (ret == -1) {
796 NTSTATUS status = map_nt_error_from_unix(sys_errno);
797 smbd_server_connection_terminate(sconn, nt_errstr(status));
798 return;
801 TALLOC_FREE(state);
804 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
805 struct tevent_req *subreq)
807 NTSTATUS status;
808 struct smbd_smb2_request_pending_state *state = NULL;
809 int i = req->current_idx;
810 uint8_t *reqhdr = NULL;
811 uint8_t *hdr = NULL;
812 uint8_t *body = NULL;
813 uint32_t flags = 0;
814 uint64_t message_id = 0;
815 uint64_t async_id = 0;
816 struct iovec *outvec = NULL;
818 if (!tevent_req_is_in_progress(subreq)) {
819 return NT_STATUS_OK;
822 req->subreq = subreq;
823 subreq = NULL;
825 if (req->async) {
826 /* We're already async. */
827 return NT_STATUS_OK;
830 if (req->in.vector_count > i + 3) {
832 * We're trying to go async in a compound
833 * request chain. This is not allowed.
834 * Cancel the outstanding request.
836 tevent_req_cancel(req->subreq);
837 return smbd_smb2_request_error(req,
838 NT_STATUS_INSUFFICIENT_RESOURCES);
841 if (DEBUGLEVEL >= 10) {
842 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
843 (unsigned int)req->current_idx );
844 print_req_vectors(req);
847 if (req->out.vector_count > 4) {
848 /* This is a compound reply. We
849 * must do an interim response
850 * followed by the async response
851 * to match W2K8R2.
853 status = smb2_send_async_interim_response(req);
854 if (!NT_STATUS_IS_OK(status)) {
855 return status;
859 /* Don't return an intermediate packet on a pipe read/write. */
860 if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
861 return NT_STATUS_OK;
864 reqhdr = (uint8_t *)req->out.vector[i].iov_base;
865 flags = (IVAL(reqhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
866 message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
867 async_id = message_id; /* keep it simple for now... */
870 * What we send is identical to a smbd_smb2_request_error
871 * packet with an error status of STATUS_PENDING. Make use
872 * of this fact sometime when refactoring. JRA.
875 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
876 if (state == NULL) {
877 return NT_STATUS_NO_MEMORY;
879 state->sconn = req->sconn;
881 state->vector[0].iov_base = (void *)state->buf;
882 state->vector[0].iov_len = 4;
884 state->vector[1].iov_base = state->buf + 4;
885 state->vector[1].iov_len = SMB2_HDR_BODY;
887 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
888 state->vector[2].iov_len = 9;
890 smb2_setup_nbt_length(state->vector, 3);
892 hdr = (uint8_t *)state->vector[1].iov_base;
893 body = (uint8_t *)state->vector[2].iov_base;
895 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
896 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
897 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
898 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
899 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(reqhdr, SMB2_HDR_OPCODE));
901 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
902 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
903 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
904 SBVAL(hdr, SMB2_HDR_PID, async_id);
905 SBVAL(hdr, SMB2_HDR_SESSION_ID,
906 BVAL(reqhdr, SMB2_HDR_SESSION_ID));
907 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
909 SSVAL(body, 0x00, 0x08 + 1);
911 SCVAL(body, 0x02, 0);
912 SCVAL(body, 0x03, 0);
913 SIVAL(body, 0x04, 0);
914 /* Match W2K8R2... */
915 SCVAL(body, 0x08, 0x21);
917 /* Ensure we correctly go through crediting. Grant
918 the credits now, and zero credits on the final
919 response. */
920 smb2_set_operation_credit(req->sconn,
921 &req->in.vector[i],
922 &state->vector[1]);
924 if (req->do_signing) {
925 status = smb2_signing_sign_pdu(req->session->session_key,
926 &state->vector[1], 2);
927 if (!NT_STATUS_IS_OK(status)) {
928 return status;
932 subreq = tstream_writev_queue_send(state,
933 req->sconn->smb2.event_ctx,
934 req->sconn->smb2.stream,
935 req->sconn->smb2.send_queue,
936 state->vector,
939 if (subreq == NULL) {
940 return NT_STATUS_NO_MEMORY;
943 tevent_req_set_callback(subreq,
944 smbd_smb2_request_pending_writev_done,
945 state);
947 /* Note we're going async with this request. */
948 req->async = true;
951 * Now manipulate req so that the outstanding async request
952 * is the only one left in the struct smbd_smb2_request.
955 if (req->current_idx == 1) {
956 /* There was only one. */
957 goto out;
960 /* Re-arrange the in.vectors. */
961 req->in.vector[1] = req->in.vector[i];
962 req->in.vector[2] = req->in.vector[i+1];
963 req->in.vector[3] = req->in.vector[i+2];
964 req->in.vector_count = 4;
965 /* Reset the new in size. */
966 smb2_setup_nbt_length(req->in.vector, 4);
968 /* Now recreate the out.vectors. */
969 outvec = talloc_zero_array(req, struct iovec, 4);
970 if (!outvec) {
971 return NT_STATUS_NO_MEMORY;
974 /* 0 is always boilerplate and must
975 * be of size 4 for the length field. */
977 outvec[0].iov_base = req->out.nbt_hdr;
978 outvec[0].iov_len = 4;
979 SIVAL(req->out.nbt_hdr, 0, 0);
981 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
982 return NT_STATUS_NO_MEMORY;
985 TALLOC_FREE(req->out.vector);
987 req->out.vector = outvec;
989 req->current_idx = 1;
990 req->out.vector_count = 4;
992 out:
994 smb2_setup_nbt_length(req->out.vector,
995 req->out.vector_count);
997 /* Ensure our final reply matches the interim one. */
998 reqhdr = (uint8_t *)req->out.vector[1].iov_base;
999 SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1000 SBVAL(reqhdr, SMB2_HDR_PID, async_id);
1003 const uint8_t *inhdr =
1004 (const uint8_t *)req->in.vector[1].iov_base;
1005 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1006 "going async\n",
1007 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1008 (unsigned long long)async_id ));
1010 return NT_STATUS_OK;
1013 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1015 struct smbd_server_connection *sconn = req->sconn;
1016 struct smbd_smb2_request *cur;
1017 const uint8_t *inhdr;
1018 int i = req->current_idx;
1019 uint32_t flags;
1020 uint64_t search_message_id;
1021 uint64_t search_async_id;
1022 uint64_t found_id;
1024 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1026 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1027 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1028 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1031 * we don't need the request anymore
1032 * cancel requests never have a response
1034 DLIST_REMOVE(req->sconn->smb2.requests, req);
1035 TALLOC_FREE(req);
1037 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1038 const uint8_t *outhdr;
1039 uint64_t message_id;
1040 uint64_t async_id;
1042 i = cur->current_idx;
1044 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1046 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1047 async_id = BVAL(outhdr, SMB2_HDR_PID);
1049 if (flags & SMB2_HDR_FLAG_ASYNC) {
1050 if (search_async_id == async_id) {
1051 found_id = async_id;
1052 break;
1054 } else {
1055 if (search_message_id == message_id) {
1056 found_id = message_id;
1057 break;
1062 if (cur && cur->subreq) {
1063 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1064 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1065 "cancel opcode[%s] mid %llu\n",
1066 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1067 (unsigned long long)found_id ));
1068 tevent_req_cancel(cur->subreq);
1071 return NT_STATUS_OK;
1074 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1076 const uint8_t *inhdr;
1077 int i = req->current_idx;
1078 uint16_t opcode;
1079 uint32_t flags;
1080 uint64_t mid;
1081 NTSTATUS status;
1082 NTSTATUS session_status;
1083 uint32_t allowed_flags;
1084 NTSTATUS return_value;
1086 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1088 /* TODO: verify more things */
1090 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1091 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1092 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1093 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1094 smb2_opcode_name(opcode),
1095 (unsigned long long)mid));
1097 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1098 SMB2_HDR_FLAG_SIGNED |
1099 SMB2_HDR_FLAG_DFS;
1100 if (opcode == SMB2_OP_CANCEL) {
1101 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1103 if ((flags & ~allowed_flags) != 0) {
1104 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1108 * Check if the client provided a valid session id,
1109 * if so smbd_smb2_request_check_session() calls
1110 * set_current_user_info().
1112 * As some command don't require a valid session id
1113 * we defer the check of the session_status
1115 session_status = smbd_smb2_request_check_session(req);
1117 req->do_signing = false;
1118 if (flags & SMB2_HDR_FLAG_SIGNED) {
1119 if (!NT_STATUS_IS_OK(session_status)) {
1120 return smbd_smb2_request_error(req, session_status);
1123 req->do_signing = true;
1124 status = smb2_signing_check_pdu(req->session->session_key,
1125 &req->in.vector[i], 3);
1126 if (!NT_STATUS_IS_OK(status)) {
1127 return smbd_smb2_request_error(req, status);
1129 } else if (req->session && req->session->do_signing) {
1130 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1133 if (flags & SMB2_HDR_FLAG_CHAINED) {
1135 * This check is mostly for giving the correct error code
1136 * for compounded requests.
1138 * TODO: we may need to move this after the session
1139 * and tcon checks.
1141 if (!NT_STATUS_IS_OK(req->next_status)) {
1142 return smbd_smb2_request_error(req, req->next_status);
1144 } else {
1145 req->compat_chain_fsp = NULL;
1148 switch (opcode) {
1149 case SMB2_OP_NEGPROT:
1150 /* This call needs to be run as root */
1151 change_to_root_user();
1154 START_PROFILE(smb2_negprot);
1155 return_value = smbd_smb2_request_process_negprot(req);
1156 END_PROFILE(smb2_negprot);
1158 break;
1160 case SMB2_OP_SESSSETUP:
1161 /* This call needs to be run as root */
1162 change_to_root_user();
1165 START_PROFILE(smb2_sesssetup);
1166 return_value = smbd_smb2_request_process_sesssetup(req);
1167 END_PROFILE(smb2_sesssetup);
1169 break;
1171 case SMB2_OP_LOGOFF:
1172 if (!NT_STATUS_IS_OK(session_status)) {
1173 return_value = smbd_smb2_request_error(req, session_status);
1174 break;
1177 /* This call needs to be run as root */
1178 change_to_root_user();
1181 START_PROFILE(smb2_logoff);
1182 return_value = smbd_smb2_request_process_logoff(req);
1183 END_PROFILE(smb2_logoff);
1185 break;
1187 case SMB2_OP_TCON:
1188 if (!NT_STATUS_IS_OK(session_status)) {
1189 return_value = smbd_smb2_request_error(req, session_status);
1190 break;
1194 * This call needs to be run as root.
1196 * smbd_smb2_request_process_tcon()
1197 * calls make_connection_snum(), which will call
1198 * change_to_user(), when needed.
1200 change_to_root_user();
1203 START_PROFILE(smb2_tcon);
1204 return_value = smbd_smb2_request_process_tcon(req);
1205 END_PROFILE(smb2_tcon);
1207 break;
1209 case SMB2_OP_TDIS:
1210 if (!NT_STATUS_IS_OK(session_status)) {
1211 return_value = smbd_smb2_request_error(req, session_status);
1212 break;
1215 * This call needs to be run as user.
1217 * smbd_smb2_request_check_tcon()
1218 * calls change_to_user() on success.
1220 status = smbd_smb2_request_check_tcon(req);
1221 if (!NT_STATUS_IS_OK(status)) {
1222 return_value = smbd_smb2_request_error(req, status);
1223 break;
1225 /* This call needs to be run as root */
1226 change_to_root_user();
1230 START_PROFILE(smb2_tdis);
1231 return_value = smbd_smb2_request_process_tdis(req);
1232 END_PROFILE(smb2_tdis);
1234 break;
1236 case SMB2_OP_CREATE:
1237 if (!NT_STATUS_IS_OK(session_status)) {
1238 return_value = smbd_smb2_request_error(req, session_status);
1239 break;
1242 * This call needs to be run as user.
1244 * smbd_smb2_request_check_tcon()
1245 * calls change_to_user() on success.
1247 status = smbd_smb2_request_check_tcon(req);
1248 if (!NT_STATUS_IS_OK(status)) {
1249 return_value = smbd_smb2_request_error(req, status);
1250 break;
1254 START_PROFILE(smb2_create);
1255 return_value = smbd_smb2_request_process_create(req);
1256 END_PROFILE(smb2_create);
1258 break;
1260 case SMB2_OP_CLOSE:
1261 if (!NT_STATUS_IS_OK(session_status)) {
1262 return_value = smbd_smb2_request_error(req, session_status);
1263 break;
1266 * This call needs to be run as user.
1268 * smbd_smb2_request_check_tcon()
1269 * calls change_to_user() on success.
1271 status = smbd_smb2_request_check_tcon(req);
1272 if (!NT_STATUS_IS_OK(status)) {
1273 return_value = smbd_smb2_request_error(req, status);
1274 break;
1278 START_PROFILE(smb2_close);
1279 return_value = smbd_smb2_request_process_close(req);
1280 END_PROFILE(smb2_close);
1282 break;
1284 case SMB2_OP_FLUSH:
1285 if (!NT_STATUS_IS_OK(session_status)) {
1286 return_value = smbd_smb2_request_error(req, session_status);
1287 break;
1290 * This call needs to be run as user.
1292 * smbd_smb2_request_check_tcon()
1293 * calls change_to_user() on success.
1295 status = smbd_smb2_request_check_tcon(req);
1296 if (!NT_STATUS_IS_OK(status)) {
1297 return_value = smbd_smb2_request_error(req, status);
1298 break;
1302 START_PROFILE(smb2_flush);
1303 return_value = smbd_smb2_request_process_flush(req);
1304 END_PROFILE(smb2_flush);
1306 break;
1308 case SMB2_OP_READ:
1309 if (!NT_STATUS_IS_OK(session_status)) {
1310 return_value = smbd_smb2_request_error(req, session_status);
1311 break;
1314 * This call needs to be run as user.
1316 * smbd_smb2_request_check_tcon()
1317 * calls change_to_user() on success.
1319 status = smbd_smb2_request_check_tcon(req);
1320 if (!NT_STATUS_IS_OK(status)) {
1321 return_value = smbd_smb2_request_error(req, status);
1322 break;
1326 START_PROFILE(smb2_read);
1327 return_value = smbd_smb2_request_process_read(req);
1328 END_PROFILE(smb2_read);
1330 break;
1332 case SMB2_OP_WRITE:
1333 if (!NT_STATUS_IS_OK(session_status)) {
1334 return_value = smbd_smb2_request_error(req, session_status);
1335 break;
1338 * This call needs to be run as user.
1340 * smbd_smb2_request_check_tcon()
1341 * calls change_to_user() on success.
1343 status = smbd_smb2_request_check_tcon(req);
1344 if (!NT_STATUS_IS_OK(status)) {
1345 return_value = smbd_smb2_request_error(req, status);
1346 break;
1350 START_PROFILE(smb2_write);
1351 return_value = smbd_smb2_request_process_write(req);
1352 END_PROFILE(smb2_write);
1354 break;
1356 case SMB2_OP_LOCK:
1357 if (!NT_STATUS_IS_OK(session_status)) {
1358 /* Too ugly to live ? JRA. */
1359 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1360 session_status = NT_STATUS_FILE_CLOSED;
1362 return_value = smbd_smb2_request_error(req, session_status);
1363 break;
1366 * This call needs to be run as user.
1368 * smbd_smb2_request_check_tcon()
1369 * calls change_to_user() on success.
1371 status = smbd_smb2_request_check_tcon(req);
1372 if (!NT_STATUS_IS_OK(status)) {
1373 /* Too ugly to live ? JRA. */
1374 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1375 status = NT_STATUS_FILE_CLOSED;
1377 return_value = smbd_smb2_request_error(req, status);
1378 break;
1382 START_PROFILE(smb2_lock);
1383 return_value = smbd_smb2_request_process_lock(req);
1384 END_PROFILE(smb2_lock);
1386 break;
1388 case SMB2_OP_IOCTL:
1389 if (!NT_STATUS_IS_OK(session_status)) {
1390 return_value = smbd_smb2_request_error(req, session_status);
1391 break;
1394 * This call needs to be run as user.
1396 * smbd_smb2_request_check_tcon()
1397 * calls change_to_user() on success.
1399 status = smbd_smb2_request_check_tcon(req);
1400 if (!NT_STATUS_IS_OK(status)) {
1401 return_value = smbd_smb2_request_error(req, status);
1402 break;
1406 START_PROFILE(smb2_ioctl);
1407 return_value = smbd_smb2_request_process_ioctl(req);
1408 END_PROFILE(smb2_ioctl);
1410 break;
1412 case SMB2_OP_CANCEL:
1414 * This call needs to be run as root
1416 * That is what we also do in the SMB1 case.
1418 change_to_root_user();
1421 START_PROFILE(smb2_cancel);
1422 return_value = smbd_smb2_request_process_cancel(req);
1423 END_PROFILE(smb2_cancel);
1425 break;
1427 case SMB2_OP_KEEPALIVE:
1428 /* This call needs to be run as root */
1429 change_to_root_user();
1432 START_PROFILE(smb2_keepalive);
1433 return_value = smbd_smb2_request_process_keepalive(req);
1434 END_PROFILE(smb2_keepalive);
1436 break;
1438 case SMB2_OP_FIND:
1439 if (!NT_STATUS_IS_OK(session_status)) {
1440 return_value = smbd_smb2_request_error(req, session_status);
1441 break;
1444 * This call needs to be run as user.
1446 * smbd_smb2_request_check_tcon()
1447 * calls change_to_user() on success.
1449 status = smbd_smb2_request_check_tcon(req);
1450 if (!NT_STATUS_IS_OK(status)) {
1451 return_value = smbd_smb2_request_error(req, status);
1452 break;
1456 START_PROFILE(smb2_find);
1457 return_value = smbd_smb2_request_process_find(req);
1458 END_PROFILE(smb2_find);
1460 break;
1462 case SMB2_OP_NOTIFY:
1463 if (!NT_STATUS_IS_OK(session_status)) {
1464 return_value = smbd_smb2_request_error(req, session_status);
1465 break;
1468 * This call needs to be run as user.
1470 * smbd_smb2_request_check_tcon()
1471 * calls change_to_user() on success.
1473 status = smbd_smb2_request_check_tcon(req);
1474 if (!NT_STATUS_IS_OK(status)) {
1475 return_value = smbd_smb2_request_error(req, status);
1476 break;
1480 START_PROFILE(smb2_notify);
1481 return_value = smbd_smb2_request_process_notify(req);
1482 END_PROFILE(smb2_notify);
1484 break;
1486 case SMB2_OP_GETINFO:
1487 if (!NT_STATUS_IS_OK(session_status)) {
1488 return_value = smbd_smb2_request_error(req, session_status);
1489 break;
1492 * This call needs to be run as user.
1494 * smbd_smb2_request_check_tcon()
1495 * calls change_to_user() on success.
1497 status = smbd_smb2_request_check_tcon(req);
1498 if (!NT_STATUS_IS_OK(status)) {
1499 return_value = smbd_smb2_request_error(req, status);
1500 break;
1504 START_PROFILE(smb2_getinfo);
1505 return_value = smbd_smb2_request_process_getinfo(req);
1506 END_PROFILE(smb2_getinfo);
1508 break;
1510 case SMB2_OP_SETINFO:
1511 if (!NT_STATUS_IS_OK(session_status)) {
1512 return_value = smbd_smb2_request_error(req, session_status);
1513 break;
1516 * This call needs to be run as user.
1518 * smbd_smb2_request_check_tcon()
1519 * calls change_to_user() on success.
1521 status = smbd_smb2_request_check_tcon(req);
1522 if (!NT_STATUS_IS_OK(status)) {
1523 return_value = smbd_smb2_request_error(req, status);
1524 break;
1528 START_PROFILE(smb2_setinfo);
1529 return_value = smbd_smb2_request_process_setinfo(req);
1530 END_PROFILE(smb2_setinfo);
1532 break;
1534 case SMB2_OP_BREAK:
1535 if (!NT_STATUS_IS_OK(session_status)) {
1536 return_value = smbd_smb2_request_error(req, session_status);
1537 break;
1540 * This call needs to be run as user.
1542 * smbd_smb2_request_check_tcon()
1543 * calls change_to_user() on success.
1545 status = smbd_smb2_request_check_tcon(req);
1546 if (!NT_STATUS_IS_OK(status)) {
1547 return_value = smbd_smb2_request_error(req, status);
1548 break;
1552 START_PROFILE(smb2_break);
1553 return_value = smbd_smb2_request_process_break(req);
1554 END_PROFILE(smb2_break);
1556 break;
1558 default:
1559 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1560 break;
1562 return return_value;
1565 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1567 struct tevent_req *subreq;
1568 int i = req->current_idx;
1570 req->subreq = NULL;
1572 req->current_idx += 3;
1574 if (req->current_idx < req->out.vector_count) {
1576 * We must process the remaining compound
1577 * SMB2 requests before any new incoming SMB2
1578 * requests. This is because incoming SMB2
1579 * requests may include a cancel for a
1580 * compound request we haven't processed
1581 * yet.
1583 struct tevent_immediate *im = tevent_create_immediate(req);
1584 if (!im) {
1585 return NT_STATUS_NO_MEMORY;
1587 tevent_schedule_immediate(im,
1588 req->sconn->smb2.event_ctx,
1589 smbd_smb2_request_dispatch_immediate,
1590 req);
1591 return NT_STATUS_OK;
1594 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1596 /* Set credit for this operation (zero credits if this
1597 is a final reply for an async operation). */
1598 smb2_set_operation_credit(req->sconn,
1599 req->async ? NULL : &req->in.vector[i],
1600 &req->out.vector[i]);
1602 if (req->do_signing) {
1603 NTSTATUS status;
1604 status = smb2_signing_sign_pdu(req->session->session_key,
1605 &req->out.vector[i], 3);
1606 if (!NT_STATUS_IS_OK(status)) {
1607 return status;
1611 if (DEBUGLEVEL >= 10) {
1612 dbgtext("smbd_smb2_request_reply: sending...\n");
1613 print_req_vectors(req);
1616 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1617 if (req->out.vector_count == 4 &&
1618 req->out.vector[3].iov_base == NULL &&
1619 req->out.vector[3].iov_len != 0) {
1620 /* Dynamic part is NULL. Chop it off,
1621 We're going to send it via sendfile. */
1622 req->out.vector_count -= 1;
1625 subreq = tstream_writev_queue_send(req,
1626 req->sconn->smb2.event_ctx,
1627 req->sconn->smb2.stream,
1628 req->sconn->smb2.send_queue,
1629 req->out.vector,
1630 req->out.vector_count);
1631 if (subreq == NULL) {
1632 return NT_STATUS_NO_MEMORY;
1634 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1636 * We're done with this request -
1637 * move it off the "being processed" queue.
1639 DLIST_REMOVE(req->sconn->smb2.requests, req);
1641 return NT_STATUS_OK;
1644 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1645 struct tevent_immediate *im,
1646 void *private_data)
1648 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1649 struct smbd_smb2_request);
1650 struct smbd_server_connection *sconn = req->sconn;
1651 NTSTATUS status;
1653 TALLOC_FREE(im);
1655 if (DEBUGLEVEL >= 10) {
1656 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1657 req->current_idx, req->in.vector_count));
1658 print_req_vectors(req);
1661 status = smbd_smb2_request_dispatch(req);
1662 if (!NT_STATUS_IS_OK(status)) {
1663 smbd_server_connection_terminate(sconn, nt_errstr(status));
1664 return;
1668 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1670 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1671 struct smbd_smb2_request);
1672 struct smbd_server_connection *sconn = req->sconn;
1673 int ret;
1674 int sys_errno;
1676 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1677 TALLOC_FREE(subreq);
1678 TALLOC_FREE(req);
1679 if (ret == -1) {
1680 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1681 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1682 nt_errstr(status)));
1683 smbd_server_connection_terminate(sconn, nt_errstr(status));
1684 return;
1688 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1689 NTSTATUS status,
1690 DATA_BLOB body, DATA_BLOB *dyn,
1691 const char *location)
1693 uint8_t *outhdr;
1694 int i = req->current_idx;
1695 uint32_t next_command_ofs;
1697 DEBUG(10,("smbd_smb2_request_done_ex: "
1698 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1699 i, nt_errstr(status), (unsigned int)body.length,
1700 dyn ? "yes": "no",
1701 (unsigned int)(dyn ? dyn->length : 0),
1702 location));
1704 if (body.length < 2) {
1705 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1708 if ((body.length % 2) != 0) {
1709 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1712 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1714 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1715 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1717 req->out.vector[i+1].iov_base = (void *)body.data;
1718 req->out.vector[i+1].iov_len = body.length;
1720 if (dyn) {
1721 req->out.vector[i+2].iov_base = (void *)dyn->data;
1722 req->out.vector[i+2].iov_len = dyn->length;
1723 } else {
1724 req->out.vector[i+2].iov_base = NULL;
1725 req->out.vector[i+2].iov_len = 0;
1728 /* see if we need to recalculate the offset to the next response */
1729 if (next_command_ofs > 0) {
1730 next_command_ofs = SMB2_HDR_BODY;
1731 next_command_ofs += req->out.vector[i+1].iov_len;
1732 next_command_ofs += req->out.vector[i+2].iov_len;
1735 if ((next_command_ofs % 8) != 0) {
1736 size_t pad_size = 8 - (next_command_ofs % 8);
1737 if (req->out.vector[i+2].iov_len == 0) {
1739 * if the dyn buffer is empty
1740 * we can use it to add padding
1742 uint8_t *pad;
1744 pad = talloc_zero_array(req->out.vector,
1745 uint8_t, pad_size);
1746 if (pad == NULL) {
1747 return smbd_smb2_request_error(req,
1748 NT_STATUS_NO_MEMORY);
1751 req->out.vector[i+2].iov_base = (void *)pad;
1752 req->out.vector[i+2].iov_len = pad_size;
1753 } else {
1755 * For now we copy the dynamic buffer
1756 * and add the padding to the new buffer
1758 size_t old_size;
1759 uint8_t *old_dyn;
1760 size_t new_size;
1761 uint8_t *new_dyn;
1763 old_size = req->out.vector[i+2].iov_len;
1764 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
1766 new_size = old_size + pad_size;
1767 new_dyn = talloc_zero_array(req->out.vector,
1768 uint8_t, new_size);
1769 if (new_dyn == NULL) {
1770 return smbd_smb2_request_error(req,
1771 NT_STATUS_NO_MEMORY);
1774 memcpy(new_dyn, old_dyn, old_size);
1775 memset(new_dyn + old_size, 0, pad_size);
1777 req->out.vector[i+2].iov_base = (void *)new_dyn;
1778 req->out.vector[i+2].iov_len = new_size;
1780 next_command_ofs += pad_size;
1783 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1785 return smbd_smb2_request_reply(req);
1788 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
1789 NTSTATUS status,
1790 DATA_BLOB *info,
1791 const char *location)
1793 DATA_BLOB body;
1794 int i = req->current_idx;
1795 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
1797 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1798 i, nt_errstr(status), info ? " +info" : "",
1799 location));
1801 body.data = outhdr + SMB2_HDR_BODY;
1802 body.length = 8;
1803 SSVAL(body.data, 0, 9);
1805 if (info) {
1806 SIVAL(body.data, 0x04, info->length);
1807 } else {
1808 /* Allocated size of req->out.vector[i].iov_base
1809 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
1810 * 1 byte without having to do an alloc.
1812 info = talloc_zero_array(req->out.vector,
1813 DATA_BLOB,
1815 if (!info) {
1816 return NT_STATUS_NO_MEMORY;
1818 info->data = ((uint8_t *)outhdr) +
1819 OUTVEC_ALLOC_SIZE - 1;
1820 info->length = 1;
1821 SCVAL(info->data, 0, 0);
1825 * if a request fails, all other remaining
1826 * compounded requests should fail too
1828 req->next_status = NT_STATUS_INVALID_PARAMETER;
1830 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
1834 struct smbd_smb2_send_oplock_break_state {
1835 struct smbd_server_connection *sconn;
1836 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
1837 struct iovec vector;
1840 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
1842 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
1843 uint64_t file_id_persistent,
1844 uint64_t file_id_volatile,
1845 uint8_t oplock_level)
1847 struct smbd_smb2_send_oplock_break_state *state;
1848 struct tevent_req *subreq;
1849 uint8_t *hdr;
1850 uint8_t *body;
1852 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
1853 if (state == NULL) {
1854 return NT_STATUS_NO_MEMORY;
1856 state->sconn = sconn;
1858 state->vector.iov_base = (void *)state->buf;
1859 state->vector.iov_len = sizeof(state->buf);
1861 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
1862 hdr = state->buf + 4;
1863 body = hdr + SMB2_HDR_BODY;
1865 SIVAL(hdr, 0, SMB2_MAGIC);
1866 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1867 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1868 SIVAL(hdr, SMB2_HDR_STATUS, 0);
1869 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
1870 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
1871 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
1872 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1873 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
1874 SIVAL(hdr, SMB2_HDR_PID, 0);
1875 SIVAL(hdr, SMB2_HDR_TID, 0);
1876 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
1877 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
1879 SSVAL(body, 0x00, 0x18);
1881 SCVAL(body, 0x02, oplock_level);
1882 SCVAL(body, 0x03, 0); /* reserved */
1883 SIVAL(body, 0x04, 0); /* reserved */
1884 SBVAL(body, 0x08, file_id_persistent);
1885 SBVAL(body, 0x10, file_id_volatile);
1887 subreq = tstream_writev_queue_send(state,
1888 sconn->smb2.event_ctx,
1889 sconn->smb2.stream,
1890 sconn->smb2.send_queue,
1891 &state->vector, 1);
1892 if (subreq == NULL) {
1893 return NT_STATUS_NO_MEMORY;
1895 tevent_req_set_callback(subreq,
1896 smbd_smb2_oplock_break_writev_done,
1897 state);
1899 return NT_STATUS_OK;
1902 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
1904 struct smbd_smb2_send_oplock_break_state *state =
1905 tevent_req_callback_data(subreq,
1906 struct smbd_smb2_send_oplock_break_state);
1907 struct smbd_server_connection *sconn = state->sconn;
1908 int ret;
1909 int sys_errno;
1911 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1912 TALLOC_FREE(subreq);
1913 if (ret == -1) {
1914 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1915 smbd_server_connection_terminate(sconn, nt_errstr(status));
1916 return;
1919 TALLOC_FREE(state);
1922 struct smbd_smb2_request_read_state {
1923 size_t missing;
1924 bool asked_for_header;
1925 struct smbd_smb2_request *smb2_req;
1928 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1929 void *private_data,
1930 TALLOC_CTX *mem_ctx,
1931 struct iovec **_vector,
1932 size_t *_count);
1933 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
1935 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
1936 struct tevent_context *ev,
1937 struct smbd_server_connection *sconn)
1939 struct tevent_req *req;
1940 struct smbd_smb2_request_read_state *state;
1941 struct tevent_req *subreq;
1943 req = tevent_req_create(mem_ctx, &state,
1944 struct smbd_smb2_request_read_state);
1945 if (req == NULL) {
1946 return NULL;
1948 state->missing = 0;
1949 state->asked_for_header = false;
1951 state->smb2_req = smbd_smb2_request_allocate(state);
1952 if (tevent_req_nomem(state->smb2_req, req)) {
1953 return tevent_req_post(req, ev);
1955 state->smb2_req->sconn = sconn;
1957 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
1958 sconn->smb2.recv_queue,
1959 smbd_smb2_request_next_vector,
1960 state);
1961 if (tevent_req_nomem(subreq, req)) {
1962 return tevent_req_post(req, ev);
1964 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
1966 return req;
1969 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1970 void *private_data,
1971 TALLOC_CTX *mem_ctx,
1972 struct iovec **_vector,
1973 size_t *_count)
1975 struct smbd_smb2_request_read_state *state =
1976 talloc_get_type_abort(private_data,
1977 struct smbd_smb2_request_read_state);
1978 struct smbd_smb2_request *req = state->smb2_req;
1979 struct iovec *vector;
1980 int idx = req->in.vector_count;
1981 size_t len = 0;
1982 uint8_t *buf = NULL;
1984 if (req->in.vector_count == 0) {
1986 * first we need to get the NBT header
1988 req->in.vector = talloc_array(req, struct iovec,
1989 req->in.vector_count + 1);
1990 if (req->in.vector == NULL) {
1991 return -1;
1993 req->in.vector_count += 1;
1995 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
1996 req->in.vector[idx].iov_len = 4;
1998 vector = talloc_array(mem_ctx, struct iovec, 1);
1999 if (vector == NULL) {
2000 return -1;
2003 vector[0] = req->in.vector[idx];
2005 *_vector = vector;
2006 *_count = 1;
2007 return 0;
2010 if (req->in.vector_count == 1) {
2012 * Now we analyze the NBT header
2014 state->missing = smb2_len(req->in.vector[0].iov_base);
2016 if (state->missing == 0) {
2017 /* if there're no remaining bytes, we're done */
2018 *_vector = NULL;
2019 *_count = 0;
2020 return 0;
2023 req->in.vector = talloc_realloc(req, req->in.vector,
2024 struct iovec,
2025 req->in.vector_count + 1);
2026 if (req->in.vector == NULL) {
2027 return -1;
2029 req->in.vector_count += 1;
2031 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2033 * it's a special NBT message,
2034 * so get all remaining bytes
2036 len = state->missing;
2037 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2039 * it's an invalid message, just read what we can get
2040 * and let the caller handle the error
2042 len = state->missing;
2043 } else {
2045 * We assume it's a SMB2 request,
2046 * and we first get the header and the
2047 * first 2 bytes (the struct size) of the body
2049 len = SMB2_HDR_BODY + 2;
2051 state->asked_for_header = true;
2054 state->missing -= len;
2056 buf = talloc_array(req->in.vector, uint8_t, len);
2057 if (buf == NULL) {
2058 return -1;
2061 req->in.vector[idx].iov_base = (void *)buf;
2062 req->in.vector[idx].iov_len = len;
2064 vector = talloc_array(mem_ctx, struct iovec, 1);
2065 if (vector == NULL) {
2066 return -1;
2069 vector[0] = req->in.vector[idx];
2071 *_vector = vector;
2072 *_count = 1;
2073 return 0;
2076 if (state->missing == 0) {
2077 /* if there're no remaining bytes, we're done */
2078 *_vector = NULL;
2079 *_count = 0;
2080 return 0;
2083 if (state->asked_for_header) {
2084 const uint8_t *hdr;
2085 size_t full_size;
2086 size_t next_command_ofs;
2087 size_t body_size;
2088 uint8_t *body;
2089 size_t dyn_size;
2090 uint8_t *dyn;
2091 bool invalid = false;
2093 state->asked_for_header = false;
2096 * We got the SMB2 header and the first 2 bytes
2097 * of the body. We fix the size to just the header
2098 * and manually copy the 2 first bytes to the body section
2100 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2101 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2103 /* allocate vectors for body and dynamic areas */
2104 req->in.vector = talloc_realloc(req, req->in.vector,
2105 struct iovec,
2106 req->in.vector_count + 2);
2107 if (req->in.vector == NULL) {
2108 return -1;
2110 req->in.vector_count += 2;
2112 full_size = state->missing + SMB2_HDR_BODY + 2;
2113 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2114 body_size = SVAL(hdr, SMB2_HDR_BODY);
2116 if (next_command_ofs != 0) {
2117 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2119 * this is invalid, just return a zero
2120 * body and let the caller deal with the error
2122 invalid = true;
2123 } else if (next_command_ofs > full_size) {
2125 * this is invalid, just return a zero
2126 * body and let the caller deal with the error
2128 invalid = true;
2129 } else {
2130 full_size = next_command_ofs;
2134 if (!invalid) {
2135 if (body_size < 2) {
2137 * this is invalid, just return a zero
2138 * body and let the caller deal with the error
2140 invalid = true;
2143 if ((body_size % 2) != 0) {
2144 body_size -= 1;
2147 if (body_size > (full_size - SMB2_HDR_BODY)) {
2149 * this is invalid, just return a zero
2150 * body and let the caller deal with the error
2152 invalid = true;
2156 if (invalid) {
2157 /* the caller should check this */
2158 body_size = 2;
2161 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2163 state->missing -= (body_size - 2) + dyn_size;
2165 body = talloc_array(req->in.vector, uint8_t, body_size);
2166 if (body == NULL) {
2167 return -1;
2170 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2171 if (dyn == NULL) {
2172 return -1;
2175 req->in.vector[idx].iov_base = (void *)body;
2176 req->in.vector[idx].iov_len = body_size;
2177 req->in.vector[idx+1].iov_base = (void *)dyn;
2178 req->in.vector[idx+1].iov_len = dyn_size;
2180 vector = talloc_array(mem_ctx, struct iovec, 2);
2181 if (vector == NULL) {
2182 return -1;
2186 * the first 2 bytes of the body were already fetched
2187 * together with the header
2189 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2190 vector[0].iov_base = body + 2;
2191 vector[0].iov_len = body_size - 2;
2193 vector[1] = req->in.vector[idx+1];
2195 *_vector = vector;
2196 *_count = 2;
2197 return 0;
2201 * when we endup here, we're looking for a new SMB2 request
2202 * next. And we ask for its header and the first 2 bytes of
2203 * the body (like we did for the first SMB2 request).
2206 req->in.vector = talloc_realloc(req, req->in.vector,
2207 struct iovec,
2208 req->in.vector_count + 1);
2209 if (req->in.vector == NULL) {
2210 return -1;
2212 req->in.vector_count += 1;
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 if (len > state->missing) {
2222 /* let the caller handle the error */
2223 len = state->missing;
2226 state->missing -= len;
2227 state->asked_for_header = true;
2229 buf = talloc_array(req->in.vector, uint8_t, len);
2230 if (buf == NULL) {
2231 return -1;
2234 req->in.vector[idx].iov_base = (void *)buf;
2235 req->in.vector[idx].iov_len = len;
2237 vector = talloc_array(mem_ctx, struct iovec, 1);
2238 if (vector == NULL) {
2239 return -1;
2242 vector[0] = req->in.vector[idx];
2244 *_vector = vector;
2245 *_count = 1;
2246 return 0;
2249 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2251 struct tevent_req *req =
2252 tevent_req_callback_data(subreq,
2253 struct tevent_req);
2254 int ret;
2255 int sys_errno;
2256 NTSTATUS status;
2258 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2259 if (ret == -1) {
2260 status = map_nt_error_from_unix(sys_errno);
2261 tevent_req_nterror(req, status);
2262 return;
2265 tevent_req_done(req);
2268 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2269 TALLOC_CTX *mem_ctx,
2270 struct smbd_smb2_request **_smb2_req)
2272 struct smbd_smb2_request_read_state *state =
2273 tevent_req_data(req,
2274 struct smbd_smb2_request_read_state);
2275 NTSTATUS status;
2277 if (tevent_req_is_nterror(req, &status)) {
2278 tevent_req_received(req);
2279 return status;
2282 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2283 *_smb2_req = state->smb2_req;
2284 tevent_req_received(req);
2285 return NT_STATUS_OK;
2288 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2290 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2291 const uint8_t *inbuf, size_t size)
2293 NTSTATUS status;
2294 struct smbd_smb2_request *req = NULL;
2295 struct tevent_req *subreq;
2297 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2298 (unsigned int)size));
2300 status = smbd_initialize_smb2(sconn);
2301 if (!NT_STATUS_IS_OK(status)) {
2302 smbd_server_connection_terminate(sconn, nt_errstr(status));
2303 return;
2306 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2307 if (!NT_STATUS_IS_OK(status)) {
2308 smbd_server_connection_terminate(sconn, nt_errstr(status));
2309 return;
2312 status = smbd_smb2_request_setup_out(req);
2313 if (!NT_STATUS_IS_OK(status)) {
2314 smbd_server_connection_terminate(sconn, nt_errstr(status));
2315 return;
2318 status = smbd_smb2_request_dispatch(req);
2319 if (!NT_STATUS_IS_OK(status)) {
2320 smbd_server_connection_terminate(sconn, nt_errstr(status));
2321 return;
2324 /* ask for the next request */
2325 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2326 if (subreq == NULL) {
2327 smbd_server_connection_terminate(sconn, "no memory for reading");
2328 return;
2330 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2332 sconn->num_requests++;
2335 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2337 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2338 struct smbd_server_connection);
2339 NTSTATUS status;
2340 struct smbd_smb2_request *req = NULL;
2342 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2343 TALLOC_FREE(subreq);
2344 if (!NT_STATUS_IS_OK(status)) {
2345 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2346 nt_errstr(status)));
2347 smbd_server_connection_terminate(sconn, nt_errstr(status));
2348 return;
2351 if (req->in.nbt_hdr[0] != 0x00) {
2352 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2353 req->in.nbt_hdr[0]));
2354 TALLOC_FREE(req);
2355 goto next;
2358 req->current_idx = 1;
2360 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2361 req->current_idx, req->in.vector_count));
2363 status = smbd_smb2_request_validate(req);
2364 if (!NT_STATUS_IS_OK(status)) {
2365 smbd_server_connection_terminate(sconn, nt_errstr(status));
2366 return;
2369 status = smbd_smb2_request_setup_out(req);
2370 if (!NT_STATUS_IS_OK(status)) {
2371 smbd_server_connection_terminate(sconn, nt_errstr(status));
2372 return;
2375 status = smbd_smb2_request_dispatch(req);
2376 if (!NT_STATUS_IS_OK(status)) {
2377 smbd_server_connection_terminate(sconn, nt_errstr(status));
2378 return;
2381 next:
2382 /* ask for the next request (this constructs the main loop) */
2383 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2384 if (subreq == NULL) {
2385 smbd_server_connection_terminate(sconn, "no memory for reading");
2386 return;
2388 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2390 sconn->num_requests++;
2392 /* The timeout_processing function isn't run nearly
2393 often enough to implement 'max log size' without
2394 overrunning the size of the file by many megabytes.
2395 This is especially true if we are running at debug
2396 level 10. Checking every 50 SMB2s is a nice
2397 tradeoff of performance vs log file size overrun. */
2399 if ((sconn->num_requests % 50) == 0 &&
2400 need_to_check_log_size()) {
2401 change_to_root_user();
2402 check_log_size();