s4-drs: mark WERR_DS_DRA_BUSY as a non error in DsReplicaUpdateRefs
[Samba/gebeck_regimport.git] / source3 / smbd / smb2_server.c
blob851e2fd7ef4a6cce56ef248205bde9735d101b30
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"
29 #include "../lib/util/bitmap.h"
30 #include "../librpc/gen_ndr/krb5pac.h"
31 #include "auth.h"
33 #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9)
35 static const char *smb2_names[] = {
36 "SMB2_NEGPROT",
37 "SMB2_SESSSETUP",
38 "SMB2_LOGOFF",
39 "SMB2_TCON",
40 "SMB2_TDIS",
41 "SMB2_CREATE",
42 "SMB2_CLOSE",
43 "SMB2_FLUSH",
44 "SMB2_READ",
45 "SMB2_WRITE",
46 "SMB2_LOCK",
47 "SMB2_IOCTL",
48 "SMB2_CANCEL",
49 "SMB2_KEEPALIVE",
50 "SMB2_FIND",
51 "SMB2_NOTIFY",
52 "SMB2_GETINFO",
53 "SMB2_SETINFO",
54 "SMB2_BREAK"
57 const char *smb2_opcode_name(uint16_t opcode)
59 if (opcode > 0x12) {
60 return "Bad SMB2 opcode";
62 return smb2_names[opcode];
65 static void print_req_vectors(struct smbd_smb2_request *req)
67 int i;
69 for (i = 0; i < req->in.vector_count; i++) {
70 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
71 (unsigned int)i,
72 (unsigned int)req->in.vector[i].iov_len);
74 for (i = 0; i < req->out.vector_count; i++) {
75 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
76 (unsigned int)i,
77 (unsigned int)req->out.vector[i].iov_len);
81 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
83 if (size < (4 + SMB2_HDR_BODY)) {
84 return false;
87 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
88 return false;
91 return true;
94 static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
96 NTSTATUS status;
97 int ret;
99 TALLOC_FREE(sconn->smb1.fde);
101 sconn->smb2.event_ctx = server_event_context();
103 sconn->smb2.recv_queue = tevent_queue_create(sconn, "smb2 recv queue");
104 if (sconn->smb2.recv_queue == NULL) {
105 return NT_STATUS_NO_MEMORY;
108 sconn->smb2.send_queue = tevent_queue_create(sconn, "smb2 send queue");
109 if (sconn->smb2.send_queue == NULL) {
110 return NT_STATUS_NO_MEMORY;
113 sconn->smb2.sessions.idtree = idr_init(sconn);
114 if (sconn->smb2.sessions.idtree == NULL) {
115 return NT_STATUS_NO_MEMORY;
117 sconn->smb2.sessions.limit = 0x0000FFFE;
118 sconn->smb2.sessions.list = NULL;
119 sconn->smb2.seqnum_low = 0;
120 sconn->smb2.credits_granted = 0;
121 sconn->smb2.max_credits = lp_smb2_max_credits();
122 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
123 DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR*sconn->smb2.max_credits);
124 if (sconn->smb2.credits_bitmap == NULL) {
125 return NT_STATUS_NO_MEMORY;
128 ret = tstream_bsd_existing_socket(sconn, sconn->sock,
129 &sconn->smb2.stream);
130 if (ret == -1) {
131 status = map_nt_error_from_unix(errno);
132 return status;
135 /* Ensure child is set to non-blocking mode */
136 set_blocking(sconn->sock, false);
137 return NT_STATUS_OK;
140 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
141 #define _smb2_setlen(_buf,len) do { \
142 uint8_t *buf = (uint8_t *)_buf; \
143 buf[0] = 0; \
144 buf[1] = ((len)&0xFF0000)>>16; \
145 buf[2] = ((len)&0xFF00)>>8; \
146 buf[3] = (len)&0xFF; \
147 } while (0)
149 static void smb2_setup_nbt_length(struct iovec *vector, int count)
151 size_t len = 0;
152 int i;
154 for (i=1; i < count; i++) {
155 len += vector[i].iov_len;
158 _smb2_setlen(vector[0].iov_base, len);
161 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request **req)
163 if (*req) {
164 (*req)->parent = NULL;
165 (*req)->mem_pool = NULL;
168 return 0;
171 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
173 if (req->parent) {
174 *req->parent = NULL;
175 talloc_free(req->mem_pool);
178 return 0;
181 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
183 TALLOC_CTX *mem_pool;
184 struct smbd_smb2_request **parent;
185 struct smbd_smb2_request *req;
187 #if 0
188 /* Enable this to find subtle valgrind errors. */
189 mem_pool = talloc_init("smbd_smb2_request_allocate");
190 #else
191 mem_pool = talloc_pool(mem_ctx, 8192);
192 #endif
193 if (mem_pool == NULL) {
194 return NULL;
197 parent = talloc(mem_pool, struct smbd_smb2_request *);
198 if (parent == NULL) {
199 talloc_free(mem_pool);
200 return NULL;
203 req = talloc_zero(parent, struct smbd_smb2_request);
204 if (req == NULL) {
205 talloc_free(mem_pool);
206 return NULL;
208 *parent = req;
209 req->mem_pool = mem_pool;
210 req->parent = parent;
212 req->last_session_id = UINT64_MAX;
213 req->last_tid = UINT32_MAX;
215 talloc_set_destructor(parent, smbd_smb2_request_parent_destructor);
216 talloc_set_destructor(req, smbd_smb2_request_destructor);
218 return req;
221 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
222 const uint8_t *inbuf, size_t size,
223 struct smbd_smb2_request **_req)
225 struct smbd_smb2_request *req;
226 uint32_t protocol_version;
227 const uint8_t *inhdr = NULL;
228 off_t ofs = 0;
229 uint16_t cmd;
230 uint32_t next_command_ofs;
232 if (size < (4 + SMB2_HDR_BODY + 2)) {
233 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
234 return NT_STATUS_INVALID_PARAMETER;
237 inhdr = inbuf + 4;
239 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
240 if (protocol_version != SMB2_MAGIC) {
241 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
242 protocol_version));
243 return NT_STATUS_INVALID_PARAMETER;
246 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
247 if (cmd != SMB2_OP_NEGPROT) {
248 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
249 cmd));
250 return NT_STATUS_INVALID_PARAMETER;
253 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
254 if (next_command_ofs != 0) {
255 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
256 next_command_ofs));
257 return NT_STATUS_INVALID_PARAMETER;
260 req = smbd_smb2_request_allocate(sconn);
261 if (req == NULL) {
262 return NT_STATUS_NO_MEMORY;
264 req->sconn = sconn;
266 talloc_steal(req, inbuf);
268 req->in.vector = talloc_array(req, struct iovec, 4);
269 if (req->in.vector == NULL) {
270 TALLOC_FREE(req);
271 return NT_STATUS_NO_MEMORY;
273 req->in.vector_count = 4;
275 memcpy(req->in.nbt_hdr, inbuf, 4);
277 ofs = 0;
278 req->in.vector[0].iov_base = discard_const_p(void, req->in.nbt_hdr);
279 req->in.vector[0].iov_len = 4;
280 ofs += req->in.vector[0].iov_len;
282 req->in.vector[1].iov_base = discard_const_p(void, (inbuf + ofs));
283 req->in.vector[1].iov_len = SMB2_HDR_BODY;
284 ofs += req->in.vector[1].iov_len;
286 req->in.vector[2].iov_base = discard_const_p(void, (inbuf + ofs));
287 req->in.vector[2].iov_len = SVAL(inbuf, ofs) & 0xFFFE;
288 ofs += req->in.vector[2].iov_len;
290 if (ofs > size) {
291 return NT_STATUS_INVALID_PARAMETER;
294 req->in.vector[3].iov_base = discard_const_p(void, (inbuf + ofs));
295 req->in.vector[3].iov_len = size - ofs;
296 ofs += req->in.vector[3].iov_len;
298 req->current_idx = 1;
300 *_req = req;
301 return NT_STATUS_OK;
304 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
305 const uint8_t *inhdr)
307 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
308 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
309 uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
310 unsigned int bitmap_offset;
312 if (opcode == SMB2_OP_CANCEL) {
313 /* SMB2_CANCEL requests by definition resend messageids. */
314 return true;
317 if (message_id < sconn->smb2.seqnum_low ||
318 message_id > (sconn->smb2.seqnum_low +
319 (sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR))) {
320 DEBUG(0,("smb2_validate_message_id: bad message_id "
321 "%llu (low = %llu, max = %lu)\n",
322 (unsigned long long)message_id,
323 (unsigned long long)sconn->smb2.seqnum_low,
324 (unsigned long)sconn->smb2.max_credits ));
325 return false;
328 if (sconn->smb2.credits_granted == 0) {
329 DEBUG(0,("smb2_validate_message_id: client used more "
330 "credits than granted message_id (%llu)\n",
331 (unsigned long long)message_id));
332 return false;
335 /* client just used a credit. */
336 sconn->smb2.credits_granted -= 1;
338 /* Mark the message_id as seen in the bitmap. */
339 bitmap_offset = (unsigned int)(message_id %
340 (uint64_t)(sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR));
341 if (bitmap_query(credits_bm, bitmap_offset)) {
342 DEBUG(0,("smb2_validate_message_id: duplicate message_id "
343 "%llu (bm offset %u)\n",
344 (unsigned long long)message_id,
345 bitmap_offset));
346 return false;
348 bitmap_set(credits_bm, bitmap_offset);
350 if (message_id == sconn->smb2.seqnum_low + 1) {
351 /* Move the window forward by all the message_id's
352 already seen. */
353 while (bitmap_query(credits_bm, bitmap_offset)) {
354 DEBUG(10,("smb2_validate_message_id: clearing "
355 "id %llu (position %u) from bitmap\n",
356 (unsigned long long)(sconn->smb2.seqnum_low + 1),
357 bitmap_offset ));
358 bitmap_clear(credits_bm, bitmap_offset);
359 sconn->smb2.seqnum_low += 1;
360 bitmap_offset = (bitmap_offset + 1) %
361 (sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR);
365 return true;
368 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
370 int count;
371 int idx;
373 count = req->in.vector_count;
375 if (count < 4) {
376 /* It's not a SMB2 request */
377 return NT_STATUS_INVALID_PARAMETER;
380 for (idx=1; idx < count; idx += 3) {
381 const uint8_t *inhdr = NULL;
382 uint32_t flags;
384 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
385 return NT_STATUS_INVALID_PARAMETER;
388 if (req->in.vector[idx+1].iov_len < 2) {
389 return NT_STATUS_INVALID_PARAMETER;
392 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
394 /* Check the SMB2 header */
395 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
396 return NT_STATUS_INVALID_PARAMETER;
399 if (!smb2_validate_message_id(req->sconn, inhdr)) {
400 return NT_STATUS_INVALID_PARAMETER;
403 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
404 if (idx == 1) {
406 * the 1st request should never have the
407 * SMB2_HDR_FLAG_CHAINED flag set
409 if (flags & SMB2_HDR_FLAG_CHAINED) {
410 req->next_status = NT_STATUS_INVALID_PARAMETER;
411 return NT_STATUS_OK;
413 } else if (idx == 4) {
415 * the 2nd request triggers related vs. unrelated
416 * compounded requests
418 if (flags & SMB2_HDR_FLAG_CHAINED) {
419 req->compound_related = true;
421 } else if (idx > 4) {
422 #if 0
424 * It seems the this tests are wrong
425 * see the SMB2-COMPOUND test
429 * all other requests should match the 2nd one
431 if (flags & SMB2_HDR_FLAG_CHAINED) {
432 if (!req->compound_related) {
433 req->next_status =
434 NT_STATUS_INVALID_PARAMETER;
435 return NT_STATUS_OK;
437 } else {
438 if (req->compound_related) {
439 req->next_status =
440 NT_STATUS_INVALID_PARAMETER;
441 return NT_STATUS_OK;
444 #endif
448 return NT_STATUS_OK;
451 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
452 const struct iovec *in_vector,
453 struct iovec *out_vector)
455 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
456 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
457 uint16_t credits_requested;
458 uint32_t out_flags;
459 uint16_t credits_granted = 0;
461 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
462 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
464 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
466 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
468 * In case we already send an async interim
469 * response, we should not grant
470 * credits on the final response.
472 credits_requested = 0;
475 if (credits_requested) {
476 uint16_t modified_credits_requested;
477 uint32_t multiplier;
480 * Split up max_credits into 1/16ths, and then scale
481 * the requested credits by how many 16ths have been
482 * currently granted. Less than 1/16th == grant all
483 * requested (100%), scale down as more have been
484 * granted. Never ask for less than 1 as the client
485 * asked for at least 1. JRA.
488 multiplier = 16 - (((sconn->smb2.credits_granted * 16) / sconn->smb2.max_credits) % 16);
490 modified_credits_requested = (multiplier * credits_requested) / 16;
491 if (modified_credits_requested == 0) {
492 modified_credits_requested = 1;
495 /* Remember what we gave out. */
496 credits_granted = MIN(modified_credits_requested,
497 (sconn->smb2.max_credits - sconn->smb2.credits_granted));
500 if (credits_granted == 0 && sconn->smb2.credits_granted == 0) {
501 /* First negprot packet, or ensure the client credits can
502 never drop to zero. */
503 credits_granted = 1;
506 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
507 sconn->smb2.credits_granted += credits_granted;
509 DEBUG(10,("smb2_set_operation_credit: requested %u, "
510 "granted %u, total granted %u\n",
511 (unsigned int)credits_requested,
512 (unsigned int)credits_granted,
513 (unsigned int)sconn->smb2.credits_granted ));
516 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
517 struct smbd_smb2_request *outreq)
519 int count, idx;
520 uint16_t total_credits = 0;
522 count = outreq->out.vector_count;
524 for (idx=1; idx < count; idx += 3) {
525 uint8_t *outhdr = (uint8_t *)outreq->out.vector[idx].iov_base;
526 smb2_set_operation_credit(outreq->sconn,
527 &inreq->in.vector[idx],
528 &outreq->out.vector[idx]);
529 /* To match Windows, count up what we
530 just granted. */
531 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
532 /* Set to zero in all but the last reply. */
533 if (idx + 3 < count) {
534 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
535 } else {
536 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
541 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
543 struct iovec *vector;
544 int count;
545 int idx;
547 count = req->in.vector_count;
548 vector = talloc_zero_array(req, struct iovec, count);
549 if (vector == NULL) {
550 return NT_STATUS_NO_MEMORY;
553 vector[0].iov_base = req->out.nbt_hdr;
554 vector[0].iov_len = 4;
555 SIVAL(req->out.nbt_hdr, 0, 0);
557 for (idx=1; idx < count; idx += 3) {
558 const uint8_t *inhdr = NULL;
559 uint32_t in_flags;
560 uint8_t *outhdr = NULL;
561 uint8_t *outbody = NULL;
562 uint32_t next_command_ofs = 0;
563 struct iovec *current = &vector[idx];
565 if ((idx + 3) < count) {
566 /* we have a next command -
567 * setup for the error case. */
568 next_command_ofs = SMB2_HDR_BODY + 9;
571 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
572 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
574 outhdr = talloc_zero_array(vector, uint8_t,
575 OUTVEC_ALLOC_SIZE);
576 if (outhdr == NULL) {
577 return NT_STATUS_NO_MEMORY;
580 outbody = outhdr + SMB2_HDR_BODY;
582 current[0].iov_base = (void *)outhdr;
583 current[0].iov_len = SMB2_HDR_BODY;
585 current[1].iov_base = (void *)outbody;
586 current[1].iov_len = 8;
588 current[2].iov_base = NULL;
589 current[2].iov_len = 0;
591 /* setup the SMB2 header */
592 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
593 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
594 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
595 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
596 SIVAL(outhdr, SMB2_HDR_STATUS,
597 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
598 SSVAL(outhdr, SMB2_HDR_OPCODE,
599 SVAL(inhdr, SMB2_HDR_OPCODE));
600 SIVAL(outhdr, SMB2_HDR_FLAGS,
601 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
602 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
603 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
604 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
605 SIVAL(outhdr, SMB2_HDR_PID,
606 IVAL(inhdr, SMB2_HDR_PID));
607 SIVAL(outhdr, SMB2_HDR_TID,
608 IVAL(inhdr, SMB2_HDR_TID));
609 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
610 BVAL(inhdr, SMB2_HDR_SESSION_ID));
611 memcpy(outhdr + SMB2_HDR_SIGNATURE,
612 inhdr + SMB2_HDR_SIGNATURE, 16);
614 /* setup error body header */
615 SSVAL(outbody, 0x00, 0x08 + 1);
616 SSVAL(outbody, 0x02, 0);
617 SIVAL(outbody, 0x04, 0);
620 req->out.vector = vector;
621 req->out.vector_count = count;
623 /* setup the length of the NBT packet */
624 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
626 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
628 return NT_STATUS_OK;
631 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
632 const char *reason,
633 const char *location)
635 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
636 reason, location));
637 exit_server_cleanly(reason);
640 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
641 struct iovec *outvec,
642 const struct iovec *srcvec)
644 /* vec[0] is always boilerplate and must
645 * be allocated with size OUTVEC_ALLOC_SIZE. */
647 outvec[0].iov_base = talloc_memdup(ctx,
648 srcvec[0].iov_base,
649 OUTVEC_ALLOC_SIZE);
650 if (!outvec[0].iov_base) {
651 return false;
653 outvec[0].iov_len = SMB2_HDR_BODY;
656 * If this is a "standard" vec[1] of length 8,
657 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
658 * then duplicate this. Else use talloc_memdup().
661 if (srcvec[1].iov_len == 8 &&
662 srcvec[1].iov_base ==
663 ((uint8_t *)srcvec[0].iov_base) +
664 SMB2_HDR_BODY) {
665 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
666 SMB2_HDR_BODY;
667 outvec[1].iov_len = 8;
668 } else {
669 outvec[1].iov_base = talloc_memdup(ctx,
670 srcvec[1].iov_base,
671 srcvec[1].iov_len);
672 if (!outvec[1].iov_base) {
673 return false;
675 outvec[1].iov_len = srcvec[1].iov_len;
679 * If this is a "standard" vec[2] of length 1,
680 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
681 * then duplicate this. Else use talloc_memdup().
684 if (srcvec[2].iov_base &&
685 srcvec[2].iov_len) {
686 if (srcvec[2].iov_base ==
687 ((uint8_t *)srcvec[0].iov_base) +
688 (OUTVEC_ALLOC_SIZE - 1) &&
689 srcvec[2].iov_len == 1) {
690 /* Common SMB2 error packet case. */
691 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
692 (OUTVEC_ALLOC_SIZE - 1);
693 } else {
694 outvec[2].iov_base = talloc_memdup(ctx,
695 srcvec[2].iov_base,
696 srcvec[2].iov_len);
697 if (!outvec[2].iov_base) {
698 return false;
701 outvec[2].iov_len = srcvec[2].iov_len;
702 } else {
703 outvec[2].iov_base = NULL;
704 outvec[2].iov_len = 0;
706 return true;
709 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
711 struct smbd_smb2_request *newreq = NULL;
712 struct iovec *outvec = NULL;
713 int count = req->out.vector_count;
714 int i;
716 newreq = smbd_smb2_request_allocate(req->sconn);
717 if (!newreq) {
718 return NULL;
721 newreq->sconn = req->sconn;
722 newreq->session = req->session;
723 newreq->do_signing = req->do_signing;
724 newreq->current_idx = req->current_idx;
726 outvec = talloc_zero_array(newreq, struct iovec, count);
727 if (!outvec) {
728 TALLOC_FREE(newreq);
729 return NULL;
731 newreq->out.vector = outvec;
732 newreq->out.vector_count = count;
734 /* Setup the outvec's identically to req. */
735 outvec[0].iov_base = newreq->out.nbt_hdr;
736 outvec[0].iov_len = 4;
737 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
739 /* Setup the vectors identically to the ones in req. */
740 for (i = 1; i < count; i += 3) {
741 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
742 break;
746 if (i < count) {
747 /* Alloc failed. */
748 TALLOC_FREE(newreq);
749 return NULL;
752 smb2_setup_nbt_length(newreq->out.vector,
753 newreq->out.vector_count);
755 return newreq;
758 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
760 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
762 int i = 0;
763 uint8_t *outhdr = NULL;
764 struct smbd_smb2_request *nreq = NULL;
766 /* Create a new smb2 request we'll use
767 for the interim return. */
768 nreq = dup_smb2_req(req);
769 if (!nreq) {
770 return NT_STATUS_NO_MEMORY;
773 /* Lose the last 3 out vectors. They're the
774 ones we'll be using for the async reply. */
775 nreq->out.vector_count -= 3;
777 smb2_setup_nbt_length(nreq->out.vector,
778 nreq->out.vector_count);
780 /* Step back to the previous reply. */
781 i = nreq->current_idx - 3;
782 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
783 /* And end the chain. */
784 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
786 /* Calculate outgoing credits */
787 smb2_calculate_credits(req, nreq);
789 /* Re-sign if needed. */
790 if (nreq->do_signing) {
791 NTSTATUS status;
792 status = smb2_signing_sign_pdu(nreq->session->session_key,
793 &nreq->out.vector[i], 3);
794 if (!NT_STATUS_IS_OK(status)) {
795 return status;
798 if (DEBUGLEVEL >= 10) {
799 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
800 (unsigned int)nreq->current_idx );
801 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
802 (unsigned int)nreq->out.vector_count );
803 print_req_vectors(nreq);
805 nreq->subreq = tstream_writev_queue_send(nreq,
806 nreq->sconn->smb2.event_ctx,
807 nreq->sconn->smb2.stream,
808 nreq->sconn->smb2.send_queue,
809 nreq->out.vector,
810 nreq->out.vector_count);
812 if (nreq->subreq == NULL) {
813 return NT_STATUS_NO_MEMORY;
816 tevent_req_set_callback(nreq->subreq,
817 smbd_smb2_request_writev_done,
818 nreq);
820 return NT_STATUS_OK;
823 struct smbd_smb2_request_pending_state {
824 struct smbd_server_connection *sconn;
825 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
826 struct iovec vector[3];
829 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
831 struct smbd_smb2_request_pending_state *state =
832 tevent_req_callback_data(subreq,
833 struct smbd_smb2_request_pending_state);
834 struct smbd_server_connection *sconn = state->sconn;
835 int ret;
836 int sys_errno;
838 ret = tstream_writev_queue_recv(subreq, &sys_errno);
839 TALLOC_FREE(subreq);
840 if (ret == -1) {
841 NTSTATUS status = map_nt_error_from_unix(sys_errno);
842 smbd_server_connection_terminate(sconn, nt_errstr(status));
843 return;
846 TALLOC_FREE(state);
849 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
850 struct tevent_timer *te,
851 struct timeval current_time,
852 void *private_data);
854 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
855 struct tevent_req *subreq,
856 uint32_t defer_time)
858 NTSTATUS status;
859 int i = req->current_idx;
860 struct timeval defer_endtime;
861 uint8_t *outhdr = NULL;
862 uint32_t flags;
864 if (!tevent_req_is_in_progress(subreq)) {
865 return NT_STATUS_OK;
868 req->subreq = subreq;
869 subreq = NULL;
871 if (req->async_te) {
872 /* We're already async. */
873 return NT_STATUS_OK;
876 outhdr = (uint8_t *)req->out.vector[i].iov_base;
877 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
878 if (flags & SMB2_HDR_FLAG_ASYNC) {
879 /* We're already async. */
880 return NT_STATUS_OK;
883 if (req->in.vector_count > i + 3) {
885 * We're trying to go async in a compound
886 * request chain. This is not allowed.
887 * Cancel the outstanding request.
889 tevent_req_cancel(req->subreq);
890 return smbd_smb2_request_error(req,
891 NT_STATUS_INSUFFICIENT_RESOURCES);
894 if (DEBUGLEVEL >= 10) {
895 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
896 (unsigned int)req->current_idx );
897 print_req_vectors(req);
900 if (req->out.vector_count > 4) {
901 struct iovec *outvec = NULL;
903 /* This is a compound reply. We
904 * must do an interim response
905 * followed by the async response
906 * to match W2K8R2.
908 status = smb2_send_async_interim_response(req);
909 if (!NT_STATUS_IS_OK(status)) {
910 return status;
914 * We're splitting off the last SMB2
915 * request in a compound set, and the
916 * smb2_send_async_interim_response()
917 * call above just sent all the replies
918 * for the previous SMB2 requests in
919 * this compound set. So we're no longer
920 * in the "compound_related_in_progress"
921 * state, and this is no longer a compound
922 * request.
924 req->compound_related = false;
925 req->sconn->smb2.compound_related_in_progress = false;
927 /* Re-arrange the in.vectors. */
928 req->in.vector[1] = req->in.vector[i];
929 req->in.vector[2] = req->in.vector[i+1];
930 req->in.vector[3] = req->in.vector[i+2];
931 req->in.vector_count = 4;
933 /* Reset the new in size. */
934 smb2_setup_nbt_length(req->in.vector, 4);
936 /* Now recreate the out.vectors. */
937 outvec = talloc_zero_array(req, struct iovec, 4);
938 if (!outvec) {
939 return NT_STATUS_NO_MEMORY;
942 /* 0 is always boilerplate and must
943 * be of size 4 for the length field. */
945 outvec[0].iov_base = req->out.nbt_hdr;
946 outvec[0].iov_len = 4;
947 SIVAL(req->out.nbt_hdr, 0, 0);
949 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
950 return NT_STATUS_NO_MEMORY;
953 TALLOC_FREE(req->out.vector);
955 req->out.vector = outvec;
957 req->current_idx = 1;
958 req->out.vector_count = 4;
960 outhdr = (uint8_t *)req->out.vector[1].iov_base;
961 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
962 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
965 defer_endtime = timeval_current_ofs_usec(defer_time);
966 req->async_te = tevent_add_timer(req->sconn->smb2.event_ctx,
967 req, defer_endtime,
968 smbd_smb2_request_pending_timer,
969 req);
970 if (req->async_te == NULL) {
971 return NT_STATUS_NO_MEMORY;
974 return NT_STATUS_OK;
977 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
978 struct tevent_timer *te,
979 struct timeval current_time,
980 void *private_data)
982 struct smbd_smb2_request *req =
983 talloc_get_type_abort(private_data,
984 struct smbd_smb2_request);
985 struct smbd_smb2_request_pending_state *state = NULL;
986 int i = req->current_idx;
987 uint8_t *outhdr = NULL;
988 const uint8_t *inhdr = NULL;
989 uint8_t *hdr = NULL;
990 uint8_t *body = NULL;
991 uint32_t flags = 0;
992 uint64_t message_id = 0;
993 uint64_t async_id = 0;
994 struct tevent_req *subreq = NULL;
996 TALLOC_FREE(req->async_te);
998 /* Ensure our final reply matches the interim one. */
999 inhdr = (const uint8_t *)req->in.vector[1].iov_base;
1000 outhdr = (uint8_t *)req->out.vector[1].iov_base;
1001 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1002 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1004 async_id = message_id; /* keep it simple for now... */
1006 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1007 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1009 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1010 "going async\n",
1011 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1012 (unsigned long long)async_id ));
1015 * What we send is identical to a smbd_smb2_request_error
1016 * packet with an error status of STATUS_PENDING. Make use
1017 * of this fact sometime when refactoring. JRA.
1020 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1021 if (state == NULL) {
1022 smbd_server_connection_terminate(req->sconn,
1023 nt_errstr(NT_STATUS_NO_MEMORY));
1024 return;
1026 state->sconn = req->sconn;
1028 state->vector[0].iov_base = (void *)state->buf;
1029 state->vector[0].iov_len = 4;
1031 state->vector[1].iov_base = state->buf + 4;
1032 state->vector[1].iov_len = SMB2_HDR_BODY;
1034 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
1035 state->vector[2].iov_len = 9;
1037 smb2_setup_nbt_length(state->vector, 3);
1039 hdr = (uint8_t *)state->vector[1].iov_base;
1040 body = (uint8_t *)state->vector[2].iov_base;
1042 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1043 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1044 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1045 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1046 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1048 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1049 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1050 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1051 SBVAL(hdr, SMB2_HDR_PID, async_id);
1052 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1053 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1054 memcpy(hdr+SMB2_HDR_SIGNATURE,
1055 outhdr+SMB2_HDR_SIGNATURE, 16);
1057 SSVAL(body, 0x00, 0x08 + 1);
1059 SCVAL(body, 0x02, 0);
1060 SCVAL(body, 0x03, 0);
1061 SIVAL(body, 0x04, 0);
1062 /* Match W2K8R2... */
1063 SCVAL(body, 0x08, 0x21);
1065 /* Ensure we correctly go through crediting. Grant
1066 the credits now, and zero credits on the final
1067 response. */
1068 smb2_set_operation_credit(req->sconn,
1069 &req->in.vector[i],
1070 &state->vector[1]);
1072 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1074 if (req->do_signing) {
1075 NTSTATUS status;
1077 status = smb2_signing_sign_pdu(req->session->session_key,
1078 &state->vector[1], 2);
1079 if (!NT_STATUS_IS_OK(status)) {
1080 smbd_server_connection_terminate(req->sconn,
1081 nt_errstr(status));
1082 return;
1086 subreq = tstream_writev_queue_send(state,
1087 state->sconn->smb2.event_ctx,
1088 state->sconn->smb2.stream,
1089 state->sconn->smb2.send_queue,
1090 state->vector,
1092 if (subreq == NULL) {
1093 smbd_server_connection_terminate(state->sconn,
1094 nt_errstr(NT_STATUS_NO_MEMORY));
1095 return;
1097 tevent_req_set_callback(subreq,
1098 smbd_smb2_request_pending_writev_done,
1099 state);
1102 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1104 struct smbd_server_connection *sconn = req->sconn;
1105 struct smbd_smb2_request *cur;
1106 const uint8_t *inhdr;
1107 int i = req->current_idx;
1108 uint32_t flags;
1109 uint64_t search_message_id;
1110 uint64_t search_async_id;
1111 uint64_t found_id;
1113 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1115 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1116 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1117 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1120 * we don't need the request anymore
1121 * cancel requests never have a response
1123 DLIST_REMOVE(req->sconn->smb2.requests, req);
1124 TALLOC_FREE(req);
1126 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1127 const uint8_t *outhdr;
1128 uint64_t message_id;
1129 uint64_t async_id;
1131 i = cur->current_idx;
1133 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1135 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1136 async_id = BVAL(outhdr, SMB2_HDR_PID);
1138 if (flags & SMB2_HDR_FLAG_ASYNC) {
1139 if (search_async_id == async_id) {
1140 found_id = async_id;
1141 break;
1143 } else {
1144 if (search_message_id == message_id) {
1145 found_id = message_id;
1146 break;
1151 if (cur && cur->subreq) {
1152 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1153 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1154 "cancel opcode[%s] mid %llu\n",
1155 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1156 (unsigned long long)found_id ));
1157 tevent_req_cancel(cur->subreq);
1160 return NT_STATUS_OK;
1163 /*************************************************************
1164 Ensure an incoming tid is a valid one for us to access.
1165 Change to the associated uid credentials and chdir to the
1166 valid tid directory.
1167 *************************************************************/
1169 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1171 const uint8_t *inhdr;
1172 int i = req->current_idx;
1173 uint32_t in_flags;
1174 uint32_t in_tid;
1175 void *p;
1176 struct smbd_smb2_tcon *tcon;
1178 req->tcon = NULL;
1180 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1182 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1183 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1185 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1186 in_tid = req->last_tid;
1189 /* lookup an existing session */
1190 p = idr_find(req->session->tcons.idtree, in_tid);
1191 if (p == NULL) {
1192 return NT_STATUS_NETWORK_NAME_DELETED;
1194 tcon = talloc_get_type_abort(p, struct smbd_smb2_tcon);
1196 if (!change_to_user(tcon->compat_conn,req->session->vuid)) {
1197 return NT_STATUS_ACCESS_DENIED;
1200 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1201 if (!set_current_service(tcon->compat_conn, 0, true)) {
1202 return NT_STATUS_ACCESS_DENIED;
1205 req->tcon = tcon;
1206 req->last_tid = in_tid;
1208 return NT_STATUS_OK;
1211 /*************************************************************
1212 Ensure an incoming session_id is a valid one for us to access.
1213 *************************************************************/
1215 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1217 const uint8_t *inhdr;
1218 int i = req->current_idx;
1219 uint32_t in_flags;
1220 uint64_t in_session_id;
1221 void *p;
1222 struct smbd_smb2_session *session;
1224 req->session = NULL;
1225 req->tcon = NULL;
1227 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1229 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1230 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1232 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1233 in_session_id = req->last_session_id;
1236 /* lookup an existing session */
1237 p = idr_find(req->sconn->smb2.sessions.idtree, in_session_id);
1238 if (p == NULL) {
1239 return NT_STATUS_USER_SESSION_DELETED;
1241 session = talloc_get_type_abort(p, struct smbd_smb2_session);
1243 if (!NT_STATUS_IS_OK(session->status)) {
1244 return NT_STATUS_ACCESS_DENIED;
1247 set_current_user_info(session->session_info->unix_info->sanitized_username,
1248 session->session_info->unix_info->unix_name,
1249 session->session_info->info->domain_name);
1251 req->session = session;
1252 req->last_session_id = in_session_id;
1254 return NT_STATUS_OK;
1257 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1258 size_t expected_body_size)
1260 const uint8_t *inhdr;
1261 uint16_t opcode;
1262 const uint8_t *inbody;
1263 int i = req->current_idx;
1264 size_t body_size;
1265 size_t min_dyn_size = expected_body_size & 0x00000001;
1268 * The following should be checked already.
1270 if ((i+2) > req->in.vector_count) {
1271 return NT_STATUS_INTERNAL_ERROR;
1273 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1274 return NT_STATUS_INTERNAL_ERROR;
1276 if (req->in.vector[i+1].iov_len < 2) {
1277 return NT_STATUS_INTERNAL_ERROR;
1280 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1281 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1283 switch (opcode) {
1284 case SMB2_OP_IOCTL:
1285 case SMB2_OP_GETINFO:
1286 min_dyn_size = 0;
1287 break;
1291 * Now check the expected body size,
1292 * where the last byte might be in the
1293 * dynnamic section..
1295 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1296 return NT_STATUS_INVALID_PARAMETER;
1298 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1299 return NT_STATUS_INVALID_PARAMETER;
1302 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1304 body_size = SVAL(inbody, 0x00);
1305 if (body_size != expected_body_size) {
1306 return NT_STATUS_INVALID_PARAMETER;
1309 return NT_STATUS_OK;
1312 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1314 const uint8_t *inhdr;
1315 int i = req->current_idx;
1316 uint16_t opcode;
1317 uint32_t flags;
1318 uint64_t mid;
1319 NTSTATUS status;
1320 NTSTATUS session_status;
1321 uint32_t allowed_flags;
1322 NTSTATUS return_value;
1324 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1326 /* TODO: verify more things */
1328 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1329 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1330 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1331 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1332 smb2_opcode_name(opcode),
1333 (unsigned long long)mid));
1335 if (get_Protocol() >= PROTOCOL_SMB2_02) {
1337 * once the protocol is negotiated
1338 * SMB2_OP_NEGPROT is not allowed anymore
1340 if (opcode == SMB2_OP_NEGPROT) {
1341 /* drop the connection */
1342 return NT_STATUS_INVALID_PARAMETER;
1344 } else {
1346 * if the protocol is not negotiated yet
1347 * only SMB2_OP_NEGPROT is allowed.
1349 if (opcode != SMB2_OP_NEGPROT) {
1350 /* drop the connection */
1351 return NT_STATUS_INVALID_PARAMETER;
1355 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1356 SMB2_HDR_FLAG_SIGNED |
1357 SMB2_HDR_FLAG_DFS;
1358 if (opcode == SMB2_OP_CANCEL) {
1359 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1361 if ((flags & ~allowed_flags) != 0) {
1362 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1366 * Check if the client provided a valid session id,
1367 * if so smbd_smb2_request_check_session() calls
1368 * set_current_user_info().
1370 * As some command don't require a valid session id
1371 * we defer the check of the session_status
1373 session_status = smbd_smb2_request_check_session(req);
1375 req->do_signing = false;
1376 if (flags & SMB2_HDR_FLAG_SIGNED) {
1377 if (!NT_STATUS_IS_OK(session_status)) {
1378 return smbd_smb2_request_error(req, session_status);
1381 req->do_signing = true;
1382 status = smb2_signing_check_pdu(req->session->session_key,
1383 &req->in.vector[i], 3);
1384 if (!NT_STATUS_IS_OK(status)) {
1385 return smbd_smb2_request_error(req, status);
1387 } else if (opcode == SMB2_OP_CANCEL) {
1388 /* Cancel requests are allowed to skip the signing */
1389 } else if (req->session && req->session->do_signing) {
1390 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1393 if (flags & SMB2_HDR_FLAG_CHAINED) {
1395 * This check is mostly for giving the correct error code
1396 * for compounded requests.
1398 * TODO: we may need to move this after the session
1399 * and tcon checks.
1401 if (!NT_STATUS_IS_OK(req->next_status)) {
1402 return smbd_smb2_request_error(req, req->next_status);
1404 } else {
1405 req->compat_chain_fsp = NULL;
1408 if (req->compound_related) {
1409 req->sconn->smb2.compound_related_in_progress = true;
1412 switch (opcode) {
1413 case SMB2_OP_NEGPROT:
1414 /* This call needs to be run as root */
1415 change_to_root_user();
1418 START_PROFILE(smb2_negprot);
1419 return_value = smbd_smb2_request_process_negprot(req);
1420 END_PROFILE(smb2_negprot);
1422 break;
1424 case SMB2_OP_SESSSETUP:
1425 /* This call needs to be run as root */
1426 change_to_root_user();
1429 START_PROFILE(smb2_sesssetup);
1430 return_value = smbd_smb2_request_process_sesssetup(req);
1431 END_PROFILE(smb2_sesssetup);
1433 break;
1435 case SMB2_OP_LOGOFF:
1436 if (!NT_STATUS_IS_OK(session_status)) {
1437 return_value = smbd_smb2_request_error(req, session_status);
1438 break;
1441 /* This call needs to be run as root */
1442 change_to_root_user();
1445 START_PROFILE(smb2_logoff);
1446 return_value = smbd_smb2_request_process_logoff(req);
1447 END_PROFILE(smb2_logoff);
1449 break;
1451 case SMB2_OP_TCON:
1452 if (!NT_STATUS_IS_OK(session_status)) {
1453 return_value = smbd_smb2_request_error(req, session_status);
1454 break;
1458 * This call needs to be run as root.
1460 * smbd_smb2_request_process_tcon()
1461 * calls make_connection_snum(), which will call
1462 * change_to_user(), when needed.
1464 change_to_root_user();
1467 START_PROFILE(smb2_tcon);
1468 return_value = smbd_smb2_request_process_tcon(req);
1469 END_PROFILE(smb2_tcon);
1471 break;
1473 case SMB2_OP_TDIS:
1474 if (!NT_STATUS_IS_OK(session_status)) {
1475 return_value = smbd_smb2_request_error(req, session_status);
1476 break;
1479 * This call needs to be run as user.
1481 * smbd_smb2_request_check_tcon()
1482 * calls change_to_user() on success.
1484 status = smbd_smb2_request_check_tcon(req);
1485 if (!NT_STATUS_IS_OK(status)) {
1486 return_value = smbd_smb2_request_error(req, status);
1487 break;
1489 /* This call needs to be run as root */
1490 change_to_root_user();
1494 START_PROFILE(smb2_tdis);
1495 return_value = smbd_smb2_request_process_tdis(req);
1496 END_PROFILE(smb2_tdis);
1498 break;
1500 case SMB2_OP_CREATE:
1501 if (!NT_STATUS_IS_OK(session_status)) {
1502 return_value = smbd_smb2_request_error(req, session_status);
1503 break;
1506 * This call needs to be run as user.
1508 * smbd_smb2_request_check_tcon()
1509 * calls change_to_user() on success.
1511 status = smbd_smb2_request_check_tcon(req);
1512 if (!NT_STATUS_IS_OK(status)) {
1513 return_value = smbd_smb2_request_error(req, status);
1514 break;
1518 START_PROFILE(smb2_create);
1519 return_value = smbd_smb2_request_process_create(req);
1520 END_PROFILE(smb2_create);
1522 break;
1524 case SMB2_OP_CLOSE:
1525 if (!NT_STATUS_IS_OK(session_status)) {
1526 return_value = smbd_smb2_request_error(req, session_status);
1527 break;
1530 * This call needs to be run as user.
1532 * smbd_smb2_request_check_tcon()
1533 * calls change_to_user() on success.
1535 status = smbd_smb2_request_check_tcon(req);
1536 if (!NT_STATUS_IS_OK(status)) {
1537 return_value = smbd_smb2_request_error(req, status);
1538 break;
1542 START_PROFILE(smb2_close);
1543 return_value = smbd_smb2_request_process_close(req);
1544 END_PROFILE(smb2_close);
1546 break;
1548 case SMB2_OP_FLUSH:
1549 if (!NT_STATUS_IS_OK(session_status)) {
1550 return_value = smbd_smb2_request_error(req, session_status);
1551 break;
1554 * This call needs to be run as user.
1556 * smbd_smb2_request_check_tcon()
1557 * calls change_to_user() on success.
1559 status = smbd_smb2_request_check_tcon(req);
1560 if (!NT_STATUS_IS_OK(status)) {
1561 return_value = smbd_smb2_request_error(req, status);
1562 break;
1566 START_PROFILE(smb2_flush);
1567 return_value = smbd_smb2_request_process_flush(req);
1568 END_PROFILE(smb2_flush);
1570 break;
1572 case SMB2_OP_READ:
1573 if (!NT_STATUS_IS_OK(session_status)) {
1574 return_value = smbd_smb2_request_error(req, session_status);
1575 break;
1578 * This call needs to be run as user.
1580 * smbd_smb2_request_check_tcon()
1581 * calls change_to_user() on success.
1583 status = smbd_smb2_request_check_tcon(req);
1584 if (!NT_STATUS_IS_OK(status)) {
1585 return_value = smbd_smb2_request_error(req, status);
1586 break;
1590 START_PROFILE(smb2_read);
1591 return_value = smbd_smb2_request_process_read(req);
1592 END_PROFILE(smb2_read);
1594 break;
1596 case SMB2_OP_WRITE:
1597 if (!NT_STATUS_IS_OK(session_status)) {
1598 return_value = smbd_smb2_request_error(req, session_status);
1599 break;
1602 * This call needs to be run as user.
1604 * smbd_smb2_request_check_tcon()
1605 * calls change_to_user() on success.
1607 status = smbd_smb2_request_check_tcon(req);
1608 if (!NT_STATUS_IS_OK(status)) {
1609 return_value = smbd_smb2_request_error(req, status);
1610 break;
1614 START_PROFILE(smb2_write);
1615 return_value = smbd_smb2_request_process_write(req);
1616 END_PROFILE(smb2_write);
1618 break;
1620 case SMB2_OP_LOCK:
1621 if (!NT_STATUS_IS_OK(session_status)) {
1622 /* Too ugly to live ? JRA. */
1623 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1624 session_status = NT_STATUS_FILE_CLOSED;
1626 return_value = smbd_smb2_request_error(req, session_status);
1627 break;
1630 * This call needs to be run as user.
1632 * smbd_smb2_request_check_tcon()
1633 * calls change_to_user() on success.
1635 status = smbd_smb2_request_check_tcon(req);
1636 if (!NT_STATUS_IS_OK(status)) {
1637 /* Too ugly to live ? JRA. */
1638 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1639 status = NT_STATUS_FILE_CLOSED;
1641 return_value = smbd_smb2_request_error(req, status);
1642 break;
1646 START_PROFILE(smb2_lock);
1647 return_value = smbd_smb2_request_process_lock(req);
1648 END_PROFILE(smb2_lock);
1650 break;
1652 case SMB2_OP_IOCTL:
1653 if (!NT_STATUS_IS_OK(session_status)) {
1654 return_value = smbd_smb2_request_error(req, session_status);
1655 break;
1658 * This call needs to be run as user.
1660 * smbd_smb2_request_check_tcon()
1661 * calls change_to_user() on success.
1663 status = smbd_smb2_request_check_tcon(req);
1664 if (!NT_STATUS_IS_OK(status)) {
1665 return_value = smbd_smb2_request_error(req, status);
1666 break;
1670 START_PROFILE(smb2_ioctl);
1671 return_value = smbd_smb2_request_process_ioctl(req);
1672 END_PROFILE(smb2_ioctl);
1674 break;
1676 case SMB2_OP_CANCEL:
1678 * This call needs to be run as root
1680 * That is what we also do in the SMB1 case.
1682 change_to_root_user();
1685 START_PROFILE(smb2_cancel);
1686 return_value = smbd_smb2_request_process_cancel(req);
1687 END_PROFILE(smb2_cancel);
1689 break;
1691 case SMB2_OP_KEEPALIVE:
1692 /* This call needs to be run as root */
1693 change_to_root_user();
1696 START_PROFILE(smb2_keepalive);
1697 return_value = smbd_smb2_request_process_keepalive(req);
1698 END_PROFILE(smb2_keepalive);
1700 break;
1702 case SMB2_OP_FIND:
1703 if (!NT_STATUS_IS_OK(session_status)) {
1704 return_value = smbd_smb2_request_error(req, session_status);
1705 break;
1708 * This call needs to be run as user.
1710 * smbd_smb2_request_check_tcon()
1711 * calls change_to_user() on success.
1713 status = smbd_smb2_request_check_tcon(req);
1714 if (!NT_STATUS_IS_OK(status)) {
1715 return_value = smbd_smb2_request_error(req, status);
1716 break;
1720 START_PROFILE(smb2_find);
1721 return_value = smbd_smb2_request_process_find(req);
1722 END_PROFILE(smb2_find);
1724 break;
1726 case SMB2_OP_NOTIFY:
1727 if (!NT_STATUS_IS_OK(session_status)) {
1728 return_value = smbd_smb2_request_error(req, session_status);
1729 break;
1732 * This call needs to be run as user.
1734 * smbd_smb2_request_check_tcon()
1735 * calls change_to_user() on success.
1737 status = smbd_smb2_request_check_tcon(req);
1738 if (!NT_STATUS_IS_OK(status)) {
1739 return_value = smbd_smb2_request_error(req, status);
1740 break;
1744 START_PROFILE(smb2_notify);
1745 return_value = smbd_smb2_request_process_notify(req);
1746 END_PROFILE(smb2_notify);
1748 break;
1750 case SMB2_OP_GETINFO:
1751 if (!NT_STATUS_IS_OK(session_status)) {
1752 return_value = smbd_smb2_request_error(req, session_status);
1753 break;
1756 * This call needs to be run as user.
1758 * smbd_smb2_request_check_tcon()
1759 * calls change_to_user() on success.
1761 status = smbd_smb2_request_check_tcon(req);
1762 if (!NT_STATUS_IS_OK(status)) {
1763 return_value = smbd_smb2_request_error(req, status);
1764 break;
1768 START_PROFILE(smb2_getinfo);
1769 return_value = smbd_smb2_request_process_getinfo(req);
1770 END_PROFILE(smb2_getinfo);
1772 break;
1774 case SMB2_OP_SETINFO:
1775 if (!NT_STATUS_IS_OK(session_status)) {
1776 return_value = smbd_smb2_request_error(req, session_status);
1777 break;
1780 * This call needs to be run as user.
1782 * smbd_smb2_request_check_tcon()
1783 * calls change_to_user() on success.
1785 status = smbd_smb2_request_check_tcon(req);
1786 if (!NT_STATUS_IS_OK(status)) {
1787 return_value = smbd_smb2_request_error(req, status);
1788 break;
1792 START_PROFILE(smb2_setinfo);
1793 return_value = smbd_smb2_request_process_setinfo(req);
1794 END_PROFILE(smb2_setinfo);
1796 break;
1798 case SMB2_OP_BREAK:
1799 if (!NT_STATUS_IS_OK(session_status)) {
1800 return_value = smbd_smb2_request_error(req, session_status);
1801 break;
1804 * This call needs to be run as user.
1806 * smbd_smb2_request_check_tcon()
1807 * calls change_to_user() on success.
1809 status = smbd_smb2_request_check_tcon(req);
1810 if (!NT_STATUS_IS_OK(status)) {
1811 return_value = smbd_smb2_request_error(req, status);
1812 break;
1816 START_PROFILE(smb2_break);
1817 return_value = smbd_smb2_request_process_break(req);
1818 END_PROFILE(smb2_break);
1820 break;
1822 default:
1823 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1824 break;
1826 return return_value;
1829 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1831 struct tevent_req *subreq;
1832 int i = req->current_idx;
1834 req->subreq = NULL;
1835 TALLOC_FREE(req->async_te);
1837 req->current_idx += 3;
1839 if (req->current_idx < req->out.vector_count) {
1841 * We must process the remaining compound
1842 * SMB2 requests before any new incoming SMB2
1843 * requests. This is because incoming SMB2
1844 * requests may include a cancel for a
1845 * compound request we haven't processed
1846 * yet.
1848 struct tevent_immediate *im = tevent_create_immediate(req);
1849 if (!im) {
1850 return NT_STATUS_NO_MEMORY;
1852 tevent_schedule_immediate(im,
1853 req->sconn->smb2.event_ctx,
1854 smbd_smb2_request_dispatch_immediate,
1855 req);
1856 return NT_STATUS_OK;
1859 if (req->compound_related) {
1860 req->sconn->smb2.compound_related_in_progress = false;
1863 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1865 /* Set credit for these operations (zero credits if this
1866 is a final reply for an async operation). */
1867 smb2_calculate_credits(req, req);
1869 if (req->do_signing) {
1870 NTSTATUS status;
1871 status = smb2_signing_sign_pdu(req->session->session_key,
1872 &req->out.vector[i], 3);
1873 if (!NT_STATUS_IS_OK(status)) {
1874 return status;
1878 if (DEBUGLEVEL >= 10) {
1879 dbgtext("smbd_smb2_request_reply: sending...\n");
1880 print_req_vectors(req);
1883 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1884 if (req->out.vector_count == 4 &&
1885 req->out.vector[3].iov_base == NULL &&
1886 req->out.vector[3].iov_len != 0) {
1887 /* Dynamic part is NULL. Chop it off,
1888 We're going to send it via sendfile. */
1889 req->out.vector_count -= 1;
1892 subreq = tstream_writev_queue_send(req,
1893 req->sconn->smb2.event_ctx,
1894 req->sconn->smb2.stream,
1895 req->sconn->smb2.send_queue,
1896 req->out.vector,
1897 req->out.vector_count);
1898 if (subreq == NULL) {
1899 return NT_STATUS_NO_MEMORY;
1901 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1903 * We're done with this request -
1904 * move it off the "being processed" queue.
1906 DLIST_REMOVE(req->sconn->smb2.requests, req);
1908 return NT_STATUS_OK;
1911 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
1913 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1914 struct tevent_immediate *im,
1915 void *private_data)
1917 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1918 struct smbd_smb2_request);
1919 struct smbd_server_connection *sconn = req->sconn;
1920 NTSTATUS status;
1922 TALLOC_FREE(im);
1924 if (DEBUGLEVEL >= 10) {
1925 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1926 req->current_idx, req->in.vector_count));
1927 print_req_vectors(req);
1930 status = smbd_smb2_request_dispatch(req);
1931 if (!NT_STATUS_IS_OK(status)) {
1932 smbd_server_connection_terminate(sconn, nt_errstr(status));
1933 return;
1936 status = smbd_smb2_request_next_incoming(sconn);
1937 if (!NT_STATUS_IS_OK(status)) {
1938 smbd_server_connection_terminate(sconn, nt_errstr(status));
1939 return;
1943 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1945 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1946 struct smbd_smb2_request);
1947 struct smbd_server_connection *sconn = req->sconn;
1948 int ret;
1949 int sys_errno;
1950 NTSTATUS status;
1952 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1953 TALLOC_FREE(subreq);
1954 TALLOC_FREE(req);
1955 if (ret == -1) {
1956 status = map_nt_error_from_unix(sys_errno);
1957 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1958 nt_errstr(status)));
1959 smbd_server_connection_terminate(sconn, nt_errstr(status));
1960 return;
1963 status = smbd_smb2_request_next_incoming(sconn);
1964 if (!NT_STATUS_IS_OK(status)) {
1965 smbd_server_connection_terminate(sconn, nt_errstr(status));
1966 return;
1970 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1971 NTSTATUS status,
1972 DATA_BLOB body, DATA_BLOB *dyn,
1973 const char *location)
1975 uint8_t *outhdr;
1976 int i = req->current_idx;
1977 uint32_t next_command_ofs;
1979 DEBUG(10,("smbd_smb2_request_done_ex: "
1980 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1981 i, nt_errstr(status), (unsigned int)body.length,
1982 dyn ? "yes": "no",
1983 (unsigned int)(dyn ? dyn->length : 0),
1984 location));
1986 if (body.length < 2) {
1987 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1990 if ((body.length % 2) != 0) {
1991 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1994 outhdr = (uint8_t *)req->out.vector[i].iov_base;
1996 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1997 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1999 req->out.vector[i+1].iov_base = (void *)body.data;
2000 req->out.vector[i+1].iov_len = body.length;
2002 if (dyn) {
2003 req->out.vector[i+2].iov_base = (void *)dyn->data;
2004 req->out.vector[i+2].iov_len = dyn->length;
2005 } else {
2006 req->out.vector[i+2].iov_base = NULL;
2007 req->out.vector[i+2].iov_len = 0;
2010 /* see if we need to recalculate the offset to the next response */
2011 if (next_command_ofs > 0) {
2012 next_command_ofs = SMB2_HDR_BODY;
2013 next_command_ofs += req->out.vector[i+1].iov_len;
2014 next_command_ofs += req->out.vector[i+2].iov_len;
2017 if ((next_command_ofs % 8) != 0) {
2018 size_t pad_size = 8 - (next_command_ofs % 8);
2019 if (req->out.vector[i+2].iov_len == 0) {
2021 * if the dyn buffer is empty
2022 * we can use it to add padding
2024 uint8_t *pad;
2026 pad = talloc_zero_array(req->out.vector,
2027 uint8_t, pad_size);
2028 if (pad == NULL) {
2029 return smbd_smb2_request_error(req,
2030 NT_STATUS_NO_MEMORY);
2033 req->out.vector[i+2].iov_base = (void *)pad;
2034 req->out.vector[i+2].iov_len = pad_size;
2035 } else {
2037 * For now we copy the dynamic buffer
2038 * and add the padding to the new buffer
2040 size_t old_size;
2041 uint8_t *old_dyn;
2042 size_t new_size;
2043 uint8_t *new_dyn;
2045 old_size = req->out.vector[i+2].iov_len;
2046 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2048 new_size = old_size + pad_size;
2049 new_dyn = talloc_zero_array(req->out.vector,
2050 uint8_t, new_size);
2051 if (new_dyn == NULL) {
2052 return smbd_smb2_request_error(req,
2053 NT_STATUS_NO_MEMORY);
2056 memcpy(new_dyn, old_dyn, old_size);
2057 memset(new_dyn + old_size, 0, pad_size);
2059 req->out.vector[i+2].iov_base = (void *)new_dyn;
2060 req->out.vector[i+2].iov_len = new_size;
2062 next_command_ofs += pad_size;
2065 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2067 return smbd_smb2_request_reply(req);
2070 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2071 NTSTATUS status,
2072 DATA_BLOB *info,
2073 const char *location)
2075 DATA_BLOB body;
2076 int i = req->current_idx;
2077 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
2079 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2080 i, nt_errstr(status), info ? " +info" : "",
2081 location));
2083 body.data = outhdr + SMB2_HDR_BODY;
2084 body.length = 8;
2085 SSVAL(body.data, 0, 9);
2087 if (info) {
2088 SIVAL(body.data, 0x04, info->length);
2089 } else {
2090 /* Allocated size of req->out.vector[i].iov_base
2091 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2092 * 1 byte without having to do an alloc.
2094 info = talloc_zero_array(req->out.vector,
2095 DATA_BLOB,
2097 if (!info) {
2098 return NT_STATUS_NO_MEMORY;
2100 info->data = ((uint8_t *)outhdr) +
2101 OUTVEC_ALLOC_SIZE - 1;
2102 info->length = 1;
2103 SCVAL(info->data, 0, 0);
2107 * if a request fails, all other remaining
2108 * compounded requests should fail too
2110 req->next_status = NT_STATUS_INVALID_PARAMETER;
2112 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2116 struct smbd_smb2_send_oplock_break_state {
2117 struct smbd_server_connection *sconn;
2118 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2119 struct iovec vector;
2122 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2124 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2125 uint64_t file_id_persistent,
2126 uint64_t file_id_volatile,
2127 uint8_t oplock_level)
2129 struct smbd_smb2_send_oplock_break_state *state;
2130 struct tevent_req *subreq;
2131 uint8_t *hdr;
2132 uint8_t *body;
2134 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2135 if (state == NULL) {
2136 return NT_STATUS_NO_MEMORY;
2138 state->sconn = sconn;
2140 state->vector.iov_base = (void *)state->buf;
2141 state->vector.iov_len = sizeof(state->buf);
2143 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2144 hdr = state->buf + 4;
2145 body = hdr + SMB2_HDR_BODY;
2147 SIVAL(hdr, 0, SMB2_MAGIC);
2148 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2149 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2150 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2151 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2152 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2153 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2154 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2155 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2156 SIVAL(hdr, SMB2_HDR_PID, 0);
2157 SIVAL(hdr, SMB2_HDR_TID, 0);
2158 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2159 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2161 SSVAL(body, 0x00, 0x18);
2163 SCVAL(body, 0x02, oplock_level);
2164 SCVAL(body, 0x03, 0); /* reserved */
2165 SIVAL(body, 0x04, 0); /* reserved */
2166 SBVAL(body, 0x08, file_id_persistent);
2167 SBVAL(body, 0x10, file_id_volatile);
2169 subreq = tstream_writev_queue_send(state,
2170 sconn->smb2.event_ctx,
2171 sconn->smb2.stream,
2172 sconn->smb2.send_queue,
2173 &state->vector, 1);
2174 if (subreq == NULL) {
2175 return NT_STATUS_NO_MEMORY;
2177 tevent_req_set_callback(subreq,
2178 smbd_smb2_oplock_break_writev_done,
2179 state);
2181 return NT_STATUS_OK;
2184 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2186 struct smbd_smb2_send_oplock_break_state *state =
2187 tevent_req_callback_data(subreq,
2188 struct smbd_smb2_send_oplock_break_state);
2189 struct smbd_server_connection *sconn = state->sconn;
2190 int ret;
2191 int sys_errno;
2193 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2194 TALLOC_FREE(subreq);
2195 if (ret == -1) {
2196 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2197 smbd_server_connection_terminate(sconn, nt_errstr(status));
2198 return;
2201 TALLOC_FREE(state);
2204 struct smbd_smb2_request_read_state {
2205 size_t missing;
2206 bool asked_for_header;
2207 struct smbd_smb2_request *smb2_req;
2210 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2211 void *private_data,
2212 TALLOC_CTX *mem_ctx,
2213 struct iovec **_vector,
2214 size_t *_count);
2215 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2217 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2218 struct tevent_context *ev,
2219 struct smbd_server_connection *sconn)
2221 struct tevent_req *req;
2222 struct smbd_smb2_request_read_state *state;
2223 struct tevent_req *subreq;
2225 req = tevent_req_create(mem_ctx, &state,
2226 struct smbd_smb2_request_read_state);
2227 if (req == NULL) {
2228 return NULL;
2230 state->missing = 0;
2231 state->asked_for_header = false;
2233 state->smb2_req = smbd_smb2_request_allocate(state);
2234 if (tevent_req_nomem(state->smb2_req, req)) {
2235 return tevent_req_post(req, ev);
2237 state->smb2_req->sconn = sconn;
2239 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2240 sconn->smb2.recv_queue,
2241 smbd_smb2_request_next_vector,
2242 state);
2243 if (tevent_req_nomem(subreq, req)) {
2244 return tevent_req_post(req, ev);
2246 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2248 return req;
2251 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2252 void *private_data,
2253 TALLOC_CTX *mem_ctx,
2254 struct iovec **_vector,
2255 size_t *_count)
2257 struct smbd_smb2_request_read_state *state =
2258 talloc_get_type_abort(private_data,
2259 struct smbd_smb2_request_read_state);
2260 struct smbd_smb2_request *req = state->smb2_req;
2261 struct iovec *vector;
2262 int idx = req->in.vector_count;
2263 size_t len = 0;
2264 uint8_t *buf = NULL;
2266 if (req->in.vector_count == 0) {
2268 * first we need to get the NBT header
2270 req->in.vector = talloc_array(req, struct iovec,
2271 req->in.vector_count + 1);
2272 if (req->in.vector == NULL) {
2273 return -1;
2275 req->in.vector_count += 1;
2277 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2278 req->in.vector[idx].iov_len = 4;
2280 vector = talloc_array(mem_ctx, struct iovec, 1);
2281 if (vector == NULL) {
2282 return -1;
2285 vector[0] = req->in.vector[idx];
2287 *_vector = vector;
2288 *_count = 1;
2289 return 0;
2292 if (req->in.vector_count == 1) {
2294 * Now we analyze the NBT header
2296 state->missing = smb2_len(req->in.vector[0].iov_base);
2298 if (state->missing == 0) {
2299 /* if there're no remaining bytes, we're done */
2300 *_vector = NULL;
2301 *_count = 0;
2302 return 0;
2305 req->in.vector = talloc_realloc(req, req->in.vector,
2306 struct iovec,
2307 req->in.vector_count + 1);
2308 if (req->in.vector == NULL) {
2309 return -1;
2311 req->in.vector_count += 1;
2313 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2315 * it's a special NBT message,
2316 * so get all remaining bytes
2318 len = state->missing;
2319 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2321 * it's an invalid message, just read what we can get
2322 * and let the caller handle the error
2324 len = state->missing;
2325 } else {
2327 * We assume it's a SMB2 request,
2328 * and we first get the header and the
2329 * first 2 bytes (the struct size) of the body
2331 len = SMB2_HDR_BODY + 2;
2333 state->asked_for_header = true;
2336 state->missing -= len;
2338 buf = talloc_array(req->in.vector, uint8_t, len);
2339 if (buf == NULL) {
2340 return -1;
2343 req->in.vector[idx].iov_base = (void *)buf;
2344 req->in.vector[idx].iov_len = len;
2346 vector = talloc_array(mem_ctx, struct iovec, 1);
2347 if (vector == NULL) {
2348 return -1;
2351 vector[0] = req->in.vector[idx];
2353 *_vector = vector;
2354 *_count = 1;
2355 return 0;
2358 if (state->missing == 0) {
2359 /* if there're no remaining bytes, we're done */
2360 *_vector = NULL;
2361 *_count = 0;
2362 return 0;
2365 if (state->asked_for_header) {
2366 const uint8_t *hdr;
2367 size_t full_size;
2368 size_t next_command_ofs;
2369 size_t body_size;
2370 uint8_t *body;
2371 size_t dyn_size;
2372 uint8_t *dyn;
2373 bool invalid = false;
2375 state->asked_for_header = false;
2378 * We got the SMB2 header and the first 2 bytes
2379 * of the body. We fix the size to just the header
2380 * and manually copy the 2 first bytes to the body section
2382 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2383 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2385 /* allocate vectors for body and dynamic areas */
2386 req->in.vector = talloc_realloc(req, req->in.vector,
2387 struct iovec,
2388 req->in.vector_count + 2);
2389 if (req->in.vector == NULL) {
2390 return -1;
2392 req->in.vector_count += 2;
2394 full_size = state->missing + SMB2_HDR_BODY + 2;
2395 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2396 body_size = SVAL(hdr, SMB2_HDR_BODY);
2398 if (next_command_ofs != 0) {
2399 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2401 * this is invalid, just return a zero
2402 * body and let the caller deal with the error
2404 invalid = true;
2405 } else if (next_command_ofs > full_size) {
2407 * this is invalid, just return a zero
2408 * body and let the caller deal with the error
2410 invalid = true;
2411 } else {
2412 full_size = next_command_ofs;
2416 if (!invalid) {
2417 if (body_size < 2) {
2419 * this is invalid, just return a zero
2420 * body and let the caller deal with the error
2422 invalid = true;
2426 * Mask out the lowest bit, the "dynamic" part
2427 * of body_size.
2429 body_size &= ~1;
2431 if (body_size > (full_size - SMB2_HDR_BODY)) {
2433 * this is invalid, just return a zero
2434 * body and let the caller deal with the error
2436 invalid = true;
2440 if (invalid) {
2441 /* the caller should check this */
2442 body_size = 2;
2445 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2447 state->missing -= (body_size - 2) + dyn_size;
2449 body = talloc_array(req->in.vector, uint8_t, body_size);
2450 if (body == NULL) {
2451 return -1;
2454 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2455 if (dyn == NULL) {
2456 return -1;
2459 req->in.vector[idx].iov_base = (void *)body;
2460 req->in.vector[idx].iov_len = body_size;
2461 req->in.vector[idx+1].iov_base = (void *)dyn;
2462 req->in.vector[idx+1].iov_len = dyn_size;
2464 vector = talloc_array(mem_ctx, struct iovec, 2);
2465 if (vector == NULL) {
2466 return -1;
2470 * the first 2 bytes of the body were already fetched
2471 * together with the header
2473 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2474 vector[0].iov_base = body + 2;
2475 vector[0].iov_len = body_size - 2;
2477 vector[1] = req->in.vector[idx+1];
2479 *_vector = vector;
2480 *_count = 2;
2481 return 0;
2485 * when we endup here, we're looking for a new SMB2 request
2486 * next. And we ask for its header and the first 2 bytes of
2487 * the body (like we did for the first SMB2 request).
2490 req->in.vector = talloc_realloc(req, req->in.vector,
2491 struct iovec,
2492 req->in.vector_count + 1);
2493 if (req->in.vector == NULL) {
2494 return -1;
2496 req->in.vector_count += 1;
2499 * We assume it's a SMB2 request,
2500 * and we first get the header and the
2501 * first 2 bytes (the struct size) of the body
2503 len = SMB2_HDR_BODY + 2;
2505 if (len > state->missing) {
2506 /* let the caller handle the error */
2507 len = state->missing;
2510 state->missing -= len;
2511 state->asked_for_header = true;
2513 buf = talloc_array(req->in.vector, uint8_t, len);
2514 if (buf == NULL) {
2515 return -1;
2518 req->in.vector[idx].iov_base = (void *)buf;
2519 req->in.vector[idx].iov_len = len;
2521 vector = talloc_array(mem_ctx, struct iovec, 1);
2522 if (vector == NULL) {
2523 return -1;
2526 vector[0] = req->in.vector[idx];
2528 *_vector = vector;
2529 *_count = 1;
2530 return 0;
2533 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2535 struct tevent_req *req =
2536 tevent_req_callback_data(subreq,
2537 struct tevent_req);
2538 int ret;
2539 int sys_errno;
2540 NTSTATUS status;
2542 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2543 if (ret == -1) {
2544 status = map_nt_error_from_unix(sys_errno);
2545 tevent_req_nterror(req, status);
2546 return;
2549 tevent_req_done(req);
2552 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2553 TALLOC_CTX *mem_ctx,
2554 struct smbd_smb2_request **_smb2_req)
2556 struct smbd_smb2_request_read_state *state =
2557 tevent_req_data(req,
2558 struct smbd_smb2_request_read_state);
2559 NTSTATUS status;
2561 if (tevent_req_is_nterror(req, &status)) {
2562 tevent_req_received(req);
2563 return status;
2566 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2567 *_smb2_req = state->smb2_req;
2568 tevent_req_received(req);
2569 return NT_STATUS_OK;
2572 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2574 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2576 size_t max_send_queue_len;
2577 size_t cur_send_queue_len;
2578 struct tevent_req *subreq;
2580 if (sconn->smb2.compound_related_in_progress) {
2582 * Can't read another until the related
2583 * compound is done.
2585 return NT_STATUS_OK;
2588 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2590 * if there is already a smbd_smb2_request_read
2591 * pending, we are done.
2593 return NT_STATUS_OK;
2596 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2597 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2599 if (cur_send_queue_len > max_send_queue_len) {
2601 * if we have a lot of requests to send,
2602 * we wait until they are on the wire until we
2603 * ask for the next request.
2605 return NT_STATUS_OK;
2608 /* ask for the next request */
2609 subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2610 if (subreq == NULL) {
2611 return NT_STATUS_NO_MEMORY;
2613 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2615 return NT_STATUS_OK;
2618 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2619 const uint8_t *inbuf, size_t size)
2621 NTSTATUS status;
2622 struct smbd_smb2_request *req = NULL;
2624 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2625 (unsigned int)size));
2627 status = smbd_initialize_smb2(sconn);
2628 if (!NT_STATUS_IS_OK(status)) {
2629 smbd_server_connection_terminate(sconn, nt_errstr(status));
2630 return;
2633 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2634 if (!NT_STATUS_IS_OK(status)) {
2635 smbd_server_connection_terminate(sconn, nt_errstr(status));
2636 return;
2639 status = smbd_smb2_request_setup_out(req);
2640 if (!NT_STATUS_IS_OK(status)) {
2641 smbd_server_connection_terminate(sconn, nt_errstr(status));
2642 return;
2645 status = smbd_smb2_request_dispatch(req);
2646 if (!NT_STATUS_IS_OK(status)) {
2647 smbd_server_connection_terminate(sconn, nt_errstr(status));
2648 return;
2651 status = smbd_smb2_request_next_incoming(sconn);
2652 if (!NT_STATUS_IS_OK(status)) {
2653 smbd_server_connection_terminate(sconn, nt_errstr(status));
2654 return;
2657 sconn->num_requests++;
2660 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2662 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2663 struct smbd_server_connection);
2664 NTSTATUS status;
2665 struct smbd_smb2_request *req = NULL;
2667 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2668 TALLOC_FREE(subreq);
2669 if (!NT_STATUS_IS_OK(status)) {
2670 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2671 nt_errstr(status)));
2672 smbd_server_connection_terminate(sconn, nt_errstr(status));
2673 return;
2676 if (req->in.nbt_hdr[0] != 0x00) {
2677 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2678 req->in.nbt_hdr[0]));
2679 TALLOC_FREE(req);
2680 goto next;
2683 req->current_idx = 1;
2685 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2686 req->current_idx, req->in.vector_count));
2688 status = smbd_smb2_request_validate(req);
2689 if (!NT_STATUS_IS_OK(status)) {
2690 smbd_server_connection_terminate(sconn, nt_errstr(status));
2691 return;
2694 status = smbd_smb2_request_setup_out(req);
2695 if (!NT_STATUS_IS_OK(status)) {
2696 smbd_server_connection_terminate(sconn, nt_errstr(status));
2697 return;
2700 status = smbd_smb2_request_dispatch(req);
2701 if (!NT_STATUS_IS_OK(status)) {
2702 smbd_server_connection_terminate(sconn, nt_errstr(status));
2703 return;
2706 next:
2707 status = smbd_smb2_request_next_incoming(sconn);
2708 if (!NT_STATUS_IS_OK(status)) {
2709 smbd_server_connection_terminate(sconn, nt_errstr(status));
2710 return;
2713 sconn->num_requests++;
2715 /* The timeout_processing function isn't run nearly
2716 often enough to implement 'max log size' without
2717 overrunning the size of the file by many megabytes.
2718 This is especially true if we are running at debug
2719 level 10. Checking every 50 SMB2s is a nice
2720 tradeoff of performance vs log file size overrun. */
2722 if ((sconn->num_requests % 50) == 0 &&
2723 need_to_check_log_size()) {
2724 change_to_root_user();
2725 check_log_size();