s3:smbd: make use of smbXsrv_tcon and smbXsrv_session for smb2
[Samba/gebeck_regimport.git] / source3 / smbd / smb2_server.c
bloba3d7c2c506967d155ef54ea0a0b9b3d096a555e3
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.recv_queue = tevent_queue_create(sconn, "smb2 recv queue");
102 if (sconn->smb2.recv_queue == NULL) {
103 return NT_STATUS_NO_MEMORY;
106 sconn->smb2.send_queue = tevent_queue_create(sconn, "smb2 send queue");
107 if (sconn->smb2.send_queue == NULL) {
108 return NT_STATUS_NO_MEMORY;
111 sconn->smb2.seqnum_low = 0;
112 sconn->smb2.credits_granted = 0;
113 sconn->smb2.max_credits = lp_smb2_max_credits();
114 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
115 DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR*sconn->smb2.max_credits);
116 if (sconn->smb2.credits_bitmap == NULL) {
117 return NT_STATUS_NO_MEMORY;
120 ret = tstream_bsd_existing_socket(sconn, sconn->sock,
121 &sconn->smb2.stream);
122 if (ret == -1) {
123 status = map_nt_error_from_unix(errno);
124 return status;
127 /* Ensure child is set to non-blocking mode */
128 set_blocking(sconn->sock, false);
129 return NT_STATUS_OK;
132 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
133 #define _smb2_setlen(_buf,len) do { \
134 uint8_t *buf = (uint8_t *)_buf; \
135 buf[0] = 0; \
136 buf[1] = ((len)&0xFF0000)>>16; \
137 buf[2] = ((len)&0xFF00)>>8; \
138 buf[3] = (len)&0xFF; \
139 } while (0)
141 static void smb2_setup_nbt_length(struct iovec *vector, int count)
143 size_t len = 0;
144 int i;
146 for (i=1; i < count; i++) {
147 len += vector[i].iov_len;
150 _smb2_setlen(vector[0].iov_base, len);
153 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request **req)
155 if (*req) {
156 (*req)->parent = NULL;
157 (*req)->mem_pool = NULL;
160 return 0;
163 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
165 if (req->parent) {
166 *req->parent = NULL;
167 talloc_free(req->mem_pool);
170 return 0;
173 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
175 TALLOC_CTX *mem_pool;
176 struct smbd_smb2_request **parent;
177 struct smbd_smb2_request *req;
179 #if 0
180 /* Enable this to find subtle valgrind errors. */
181 mem_pool = talloc_init("smbd_smb2_request_allocate");
182 #else
183 mem_pool = talloc_pool(mem_ctx, 8192);
184 #endif
185 if (mem_pool == NULL) {
186 return NULL;
189 parent = talloc(mem_pool, struct smbd_smb2_request *);
190 if (parent == NULL) {
191 talloc_free(mem_pool);
192 return NULL;
195 req = talloc_zero(parent, struct smbd_smb2_request);
196 if (req == NULL) {
197 talloc_free(mem_pool);
198 return NULL;
200 *parent = req;
201 req->mem_pool = mem_pool;
202 req->parent = parent;
204 req->last_session_id = UINT64_MAX;
205 req->last_tid = UINT32_MAX;
207 talloc_set_destructor(parent, smbd_smb2_request_parent_destructor);
208 talloc_set_destructor(req, smbd_smb2_request_destructor);
210 return req;
213 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
214 const uint8_t *inbuf, size_t size,
215 struct smbd_smb2_request **_req)
217 struct smbd_smb2_request *req;
218 uint32_t protocol_version;
219 const uint8_t *inhdr = NULL;
220 off_t ofs = 0;
221 uint16_t cmd;
222 uint32_t next_command_ofs;
224 if (size < (4 + SMB2_HDR_BODY + 2)) {
225 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
226 return NT_STATUS_INVALID_PARAMETER;
229 inhdr = inbuf + 4;
231 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
232 if (protocol_version != SMB2_MAGIC) {
233 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
234 protocol_version));
235 return NT_STATUS_INVALID_PARAMETER;
238 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
239 if (cmd != SMB2_OP_NEGPROT) {
240 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
241 cmd));
242 return NT_STATUS_INVALID_PARAMETER;
245 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
246 if (next_command_ofs != 0) {
247 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
248 next_command_ofs));
249 return NT_STATUS_INVALID_PARAMETER;
252 req = smbd_smb2_request_allocate(sconn);
253 if (req == NULL) {
254 return NT_STATUS_NO_MEMORY;
256 req->sconn = sconn;
258 talloc_steal(req, inbuf);
260 req->in.vector = talloc_array(req, struct iovec, 4);
261 if (req->in.vector == NULL) {
262 TALLOC_FREE(req);
263 return NT_STATUS_NO_MEMORY;
265 req->in.vector_count = 4;
267 memcpy(req->in.nbt_hdr, inbuf, 4);
269 ofs = 0;
270 req->in.vector[0].iov_base = discard_const_p(void, req->in.nbt_hdr);
271 req->in.vector[0].iov_len = 4;
272 ofs += req->in.vector[0].iov_len;
274 req->in.vector[1].iov_base = discard_const_p(void, (inbuf + ofs));
275 req->in.vector[1].iov_len = SMB2_HDR_BODY;
276 ofs += req->in.vector[1].iov_len;
278 req->in.vector[2].iov_base = discard_const_p(void, (inbuf + ofs));
279 req->in.vector[2].iov_len = SVAL(inbuf, ofs) & 0xFFFE;
280 ofs += req->in.vector[2].iov_len;
282 if (ofs > size) {
283 return NT_STATUS_INVALID_PARAMETER;
286 req->in.vector[3].iov_base = discard_const_p(void, (inbuf + ofs));
287 req->in.vector[3].iov_len = size - ofs;
288 ofs += req->in.vector[3].iov_len;
290 req->current_idx = 1;
292 *_req = req;
293 return NT_STATUS_OK;
296 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
297 const uint8_t *inhdr)
299 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
300 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
301 uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
302 unsigned int bitmap_offset;
303 uint16_t credit_charge = 1;
304 uint64_t i;
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 if (sconn->smb2.credits_granted == 0) {
323 DEBUG(0,("smb2_validate_message_id: client used more "
324 "credits than granted, message_id (%llu)\n",
325 (unsigned long long)message_id));
326 return false;
329 if (sconn->smb2.supports_multicredit) {
330 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
331 credit_charge = MAX(credit_charge, 1);
334 DEBUG(11, ("smb2_validate_message_id: mid %llu, credits_granted %llu, "
335 "charge %llu, max_credits %llu, seqnum_low: %llu\n",
336 (unsigned long long) message_id,
337 (unsigned long long) sconn->smb2.credits_granted,
338 (unsigned long long) credit_charge,
339 (unsigned long long) sconn->smb2.max_credits,
340 (unsigned long long) sconn->smb2.seqnum_low));
342 /* substract used credits */
343 sconn->smb2.credits_granted -= credit_charge;
346 * now check the message ids
348 * for multi-credit requests we need to check all current mid plus
349 * the implicit mids caused by the credit charge
350 * e.g. current mid = 15, charge 5 => mark 15-19 as used
353 for (i = message_id; i <= (message_id+credit_charge-1); i++) {
355 DEBUG(11, ("Iterating mid %llu\n", (unsigned long long) i));
357 /* Mark the message_ids as seen in the bitmap. */
358 bitmap_offset = (unsigned int)(i %
359 (uint64_t)(sconn->smb2.max_credits *
360 DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR));
361 if (bitmap_query(credits_bm, bitmap_offset)) {
362 DEBUG(0,("smb2_validate_message_id: duplicate "
363 "message_id %llu (bm offset %u)\n",
364 (unsigned long long)i, bitmap_offset));
365 return false;
367 bitmap_set(credits_bm, bitmap_offset);
369 if (i == sconn->smb2.seqnum_low + 1) {
370 /* Move the window forward by all the message_id's
371 already seen. */
372 while (bitmap_query(credits_bm, bitmap_offset)) {
373 DEBUG(10,("smb2_validate_message_id: clearing "
374 "id %llu (position %u) from bitmap\n",
375 (unsigned long long)(sconn->smb2.seqnum_low + 1),
376 bitmap_offset));
377 bitmap_clear(credits_bm, bitmap_offset);
378 sconn->smb2.seqnum_low += 1;
379 bitmap_offset = (bitmap_offset + 1) %
380 (sconn->smb2.max_credits *
381 DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR);
386 return true;
389 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
391 int count;
392 int idx;
394 count = req->in.vector_count;
396 if (count < 4) {
397 /* It's not a SMB2 request */
398 return NT_STATUS_INVALID_PARAMETER;
401 for (idx=1; idx < count; idx += 3) {
402 const uint8_t *inhdr = NULL;
403 uint32_t flags;
405 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
406 return NT_STATUS_INVALID_PARAMETER;
409 if (req->in.vector[idx+1].iov_len < 2) {
410 return NT_STATUS_INVALID_PARAMETER;
413 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
415 /* Check the SMB2 header */
416 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
417 return NT_STATUS_INVALID_PARAMETER;
420 if (!smb2_validate_message_id(req->sconn, inhdr)) {
421 return NT_STATUS_INVALID_PARAMETER;
424 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
425 if (idx == 1) {
427 * the 1st request should never have the
428 * SMB2_HDR_FLAG_CHAINED flag set
430 if (flags & SMB2_HDR_FLAG_CHAINED) {
431 req->next_status = NT_STATUS_INVALID_PARAMETER;
432 return NT_STATUS_OK;
434 } else if (idx == 4) {
436 * the 2nd request triggers related vs. unrelated
437 * compounded requests
439 if (flags & SMB2_HDR_FLAG_CHAINED) {
440 req->compound_related = true;
442 } else if (idx > 4) {
443 #if 0
445 * It seems the this tests are wrong
446 * see the SMB2-COMPOUND test
450 * all other requests should match the 2nd one
452 if (flags & SMB2_HDR_FLAG_CHAINED) {
453 if (!req->compound_related) {
454 req->next_status =
455 NT_STATUS_INVALID_PARAMETER;
456 return NT_STATUS_OK;
458 } else {
459 if (req->compound_related) {
460 req->next_status =
461 NT_STATUS_INVALID_PARAMETER;
462 return NT_STATUS_OK;
465 #endif
469 return NT_STATUS_OK;
472 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
473 const struct iovec *in_vector,
474 struct iovec *out_vector)
476 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
477 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
478 uint16_t credits_requested;
479 uint32_t out_flags;
480 uint16_t credits_granted = 0;
482 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
483 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
485 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
487 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
489 * In case we already send an async interim
490 * response, we should not grant
491 * credits on the final response.
493 credits_requested = 0;
496 if (credits_requested) {
497 uint16_t modified_credits_requested;
498 uint32_t multiplier;
501 * Split up max_credits into 1/16ths, and then scale
502 * the requested credits by how many 16ths have been
503 * currently granted. Less than 1/16th == grant all
504 * requested (100%), scale down as more have been
505 * granted. Never ask for less than 1 as the client
506 * asked for at least 1. JRA.
509 multiplier = 16 - (((sconn->smb2.credits_granted * 16) / sconn->smb2.max_credits) % 16);
511 modified_credits_requested = (multiplier * credits_requested) / 16;
512 if (modified_credits_requested == 0) {
513 modified_credits_requested = 1;
516 /* Remember what we gave out. */
517 credits_granted = MIN(modified_credits_requested,
518 (sconn->smb2.max_credits - sconn->smb2.credits_granted));
521 if (credits_granted == 0 && sconn->smb2.credits_granted == 0) {
522 /* First negprot packet, or ensure the client credits can
523 never drop to zero. */
524 credits_granted = 1;
527 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
528 sconn->smb2.credits_granted += credits_granted;
530 DEBUG(10,("smb2_set_operation_credit: requested %u, "
531 "granted %u, total granted %u\n",
532 (unsigned int)credits_requested,
533 (unsigned int)credits_granted,
534 (unsigned int)sconn->smb2.credits_granted ));
537 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
538 struct smbd_smb2_request *outreq)
540 int count, idx;
541 uint16_t total_credits = 0;
543 count = outreq->out.vector_count;
545 for (idx=1; idx < count; idx += 3) {
546 uint8_t *outhdr = (uint8_t *)outreq->out.vector[idx].iov_base;
547 smb2_set_operation_credit(outreq->sconn,
548 &inreq->in.vector[idx],
549 &outreq->out.vector[idx]);
550 /* To match Windows, count up what we
551 just granted. */
552 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
553 /* Set to zero in all but the last reply. */
554 if (idx + 3 < count) {
555 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
556 } else {
557 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
562 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
564 struct iovec *vector;
565 int count;
566 int idx;
568 req->request_time = timeval_current();
570 count = req->in.vector_count;
571 vector = talloc_zero_array(req, struct iovec, count);
572 if (vector == NULL) {
573 return NT_STATUS_NO_MEMORY;
576 vector[0].iov_base = req->out.nbt_hdr;
577 vector[0].iov_len = 4;
578 SIVAL(req->out.nbt_hdr, 0, 0);
580 for (idx=1; idx < count; idx += 3) {
581 const uint8_t *inhdr = NULL;
582 uint8_t *outhdr = NULL;
583 uint8_t *outbody = NULL;
584 uint32_t next_command_ofs = 0;
585 struct iovec *current = &vector[idx];
587 if ((idx + 3) < count) {
588 /* we have a next command -
589 * setup for the error case. */
590 next_command_ofs = SMB2_HDR_BODY + 9;
593 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
595 outhdr = talloc_zero_array(vector, uint8_t,
596 OUTVEC_ALLOC_SIZE);
597 if (outhdr == NULL) {
598 return NT_STATUS_NO_MEMORY;
601 outbody = outhdr + SMB2_HDR_BODY;
603 current[0].iov_base = (void *)outhdr;
604 current[0].iov_len = SMB2_HDR_BODY;
606 current[1].iov_base = (void *)outbody;
607 current[1].iov_len = 8;
609 current[2].iov_base = NULL;
610 current[2].iov_len = 0;
612 /* setup the SMB2 header */
613 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
614 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
615 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
616 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
617 SIVAL(outhdr, SMB2_HDR_STATUS,
618 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
619 SSVAL(outhdr, SMB2_HDR_OPCODE,
620 SVAL(inhdr, SMB2_HDR_OPCODE));
621 SIVAL(outhdr, SMB2_HDR_FLAGS,
622 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
623 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
624 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
625 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
626 SIVAL(outhdr, SMB2_HDR_PID,
627 IVAL(inhdr, SMB2_HDR_PID));
628 SIVAL(outhdr, SMB2_HDR_TID,
629 IVAL(inhdr, SMB2_HDR_TID));
630 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
631 BVAL(inhdr, SMB2_HDR_SESSION_ID));
632 memcpy(outhdr + SMB2_HDR_SIGNATURE,
633 inhdr + SMB2_HDR_SIGNATURE, 16);
635 /* setup error body header */
636 SSVAL(outbody, 0x00, 0x08 + 1);
637 SSVAL(outbody, 0x02, 0);
638 SIVAL(outbody, 0x04, 0);
641 req->out.vector = vector;
642 req->out.vector_count = count;
644 /* setup the length of the NBT packet */
645 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
647 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
649 return NT_STATUS_OK;
652 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
653 const char *reason,
654 const char *location)
656 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
657 reason, location));
658 exit_server_cleanly(reason);
661 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
662 struct iovec *outvec,
663 const struct iovec *srcvec)
665 /* vec[0] is always boilerplate and must
666 * be allocated with size OUTVEC_ALLOC_SIZE. */
668 outvec[0].iov_base = talloc_memdup(ctx,
669 srcvec[0].iov_base,
670 OUTVEC_ALLOC_SIZE);
671 if (!outvec[0].iov_base) {
672 return false;
674 outvec[0].iov_len = SMB2_HDR_BODY;
677 * If this is a "standard" vec[1] of length 8,
678 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
679 * then duplicate this. Else use talloc_memdup().
682 if (srcvec[1].iov_len == 8 &&
683 srcvec[1].iov_base ==
684 ((uint8_t *)srcvec[0].iov_base) +
685 SMB2_HDR_BODY) {
686 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
687 SMB2_HDR_BODY;
688 outvec[1].iov_len = 8;
689 } else {
690 outvec[1].iov_base = talloc_memdup(ctx,
691 srcvec[1].iov_base,
692 srcvec[1].iov_len);
693 if (!outvec[1].iov_base) {
694 return false;
696 outvec[1].iov_len = srcvec[1].iov_len;
700 * If this is a "standard" vec[2] of length 1,
701 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
702 * then duplicate this. Else use talloc_memdup().
705 if (srcvec[2].iov_base &&
706 srcvec[2].iov_len) {
707 if (srcvec[2].iov_base ==
708 ((uint8_t *)srcvec[0].iov_base) +
709 (OUTVEC_ALLOC_SIZE - 1) &&
710 srcvec[2].iov_len == 1) {
711 /* Common SMB2 error packet case. */
712 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
713 (OUTVEC_ALLOC_SIZE - 1);
714 } else {
715 outvec[2].iov_base = talloc_memdup(ctx,
716 srcvec[2].iov_base,
717 srcvec[2].iov_len);
718 if (!outvec[2].iov_base) {
719 return false;
722 outvec[2].iov_len = srcvec[2].iov_len;
723 } else {
724 outvec[2].iov_base = NULL;
725 outvec[2].iov_len = 0;
727 return true;
730 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
732 struct smbd_smb2_request *newreq = NULL;
733 struct iovec *outvec = NULL;
734 int count = req->out.vector_count;
735 int i;
737 newreq = smbd_smb2_request_allocate(req->sconn);
738 if (!newreq) {
739 return NULL;
742 newreq->sconn = req->sconn;
743 newreq->session = req->session;
744 newreq->do_signing = req->do_signing;
745 newreq->current_idx = req->current_idx;
747 outvec = talloc_zero_array(newreq, struct iovec, count);
748 if (!outvec) {
749 TALLOC_FREE(newreq);
750 return NULL;
752 newreq->out.vector = outvec;
753 newreq->out.vector_count = count;
755 /* Setup the outvec's identically to req. */
756 outvec[0].iov_base = newreq->out.nbt_hdr;
757 outvec[0].iov_len = 4;
758 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
760 /* Setup the vectors identically to the ones in req. */
761 for (i = 1; i < count; i += 3) {
762 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
763 break;
767 if (i < count) {
768 /* Alloc failed. */
769 TALLOC_FREE(newreq);
770 return NULL;
773 smb2_setup_nbt_length(newreq->out.vector,
774 newreq->out.vector_count);
776 return newreq;
779 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
781 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
783 int i = 0;
784 uint8_t *outhdr = NULL;
785 struct smbd_smb2_request *nreq = NULL;
787 /* Create a new smb2 request we'll use
788 for the interim return. */
789 nreq = dup_smb2_req(req);
790 if (!nreq) {
791 return NT_STATUS_NO_MEMORY;
794 /* Lose the last 3 out vectors. They're the
795 ones we'll be using for the async reply. */
796 nreq->out.vector_count -= 3;
798 smb2_setup_nbt_length(nreq->out.vector,
799 nreq->out.vector_count);
801 /* Step back to the previous reply. */
802 i = nreq->current_idx - 3;
803 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
804 /* And end the chain. */
805 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
807 /* Calculate outgoing credits */
808 smb2_calculate_credits(req, nreq);
810 /* Re-sign if needed. */
811 if (nreq->do_signing) {
812 NTSTATUS status;
813 struct smbXsrv_session *x = nreq->session;
814 struct smbXsrv_connection *conn = x->connection;
815 DATA_BLOB signing_key = x->global->channels[0].signing_key;
817 status = smb2_signing_sign_pdu(signing_key,
818 conn->protocol,
819 &nreq->out.vector[i], 3);
820 if (!NT_STATUS_IS_OK(status)) {
821 return status;
824 if (DEBUGLEVEL >= 10) {
825 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
826 (unsigned int)nreq->current_idx );
827 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
828 (unsigned int)nreq->out.vector_count );
829 print_req_vectors(nreq);
831 nreq->subreq = tstream_writev_queue_send(nreq,
832 nreq->sconn->ev_ctx,
833 nreq->sconn->smb2.stream,
834 nreq->sconn->smb2.send_queue,
835 nreq->out.vector,
836 nreq->out.vector_count);
838 if (nreq->subreq == NULL) {
839 return NT_STATUS_NO_MEMORY;
842 tevent_req_set_callback(nreq->subreq,
843 smbd_smb2_request_writev_done,
844 nreq);
846 return NT_STATUS_OK;
849 struct smbd_smb2_request_pending_state {
850 struct smbd_server_connection *sconn;
851 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
852 struct iovec vector[3];
855 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
857 struct smbd_smb2_request_pending_state *state =
858 tevent_req_callback_data(subreq,
859 struct smbd_smb2_request_pending_state);
860 struct smbd_server_connection *sconn = state->sconn;
861 int ret;
862 int sys_errno;
864 ret = tstream_writev_queue_recv(subreq, &sys_errno);
865 TALLOC_FREE(subreq);
866 if (ret == -1) {
867 NTSTATUS status = map_nt_error_from_unix(sys_errno);
868 smbd_server_connection_terminate(sconn, nt_errstr(status));
869 return;
872 TALLOC_FREE(state);
875 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
876 struct tevent_timer *te,
877 struct timeval current_time,
878 void *private_data);
880 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
881 struct tevent_req *subreq,
882 uint32_t defer_time)
884 NTSTATUS status;
885 int i = req->current_idx;
886 struct timeval defer_endtime;
887 uint8_t *outhdr = NULL;
888 uint32_t flags;
890 if (!tevent_req_is_in_progress(subreq)) {
891 return NT_STATUS_OK;
894 req->subreq = subreq;
895 subreq = NULL;
897 if (req->async_te) {
898 /* We're already async. */
899 return NT_STATUS_OK;
902 outhdr = (uint8_t *)req->out.vector[i].iov_base;
903 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
904 if (flags & SMB2_HDR_FLAG_ASYNC) {
905 /* We're already async. */
906 return NT_STATUS_OK;
909 if (req->in.vector_count > i + 3) {
911 * We're trying to go async in a compound
912 * request chain. This is not allowed.
913 * Cancel the outstanding request.
915 tevent_req_cancel(req->subreq);
916 return smbd_smb2_request_error(req,
917 NT_STATUS_INSUFFICIENT_RESOURCES);
920 if (DEBUGLEVEL >= 10) {
921 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
922 (unsigned int)req->current_idx );
923 print_req_vectors(req);
926 if (req->out.vector_count > 4) {
927 struct iovec *outvec = NULL;
929 /* This is a compound reply. We
930 * must do an interim response
931 * followed by the async response
932 * to match W2K8R2.
934 status = smb2_send_async_interim_response(req);
935 if (!NT_STATUS_IS_OK(status)) {
936 return status;
940 * We're splitting off the last SMB2
941 * request in a compound set, and the
942 * smb2_send_async_interim_response()
943 * call above just sent all the replies
944 * for the previous SMB2 requests in
945 * this compound set. So we're no longer
946 * in the "compound_related_in_progress"
947 * state, and this is no longer a compound
948 * request.
950 req->compound_related = false;
951 req->sconn->smb2.compound_related_in_progress = false;
953 /* Re-arrange the in.vectors. */
954 req->in.vector[1] = req->in.vector[i];
955 req->in.vector[2] = req->in.vector[i+1];
956 req->in.vector[3] = req->in.vector[i+2];
957 req->in.vector_count = 4;
959 /* Reset the new in size. */
960 smb2_setup_nbt_length(req->in.vector, 4);
962 /* Now recreate the out.vectors. */
963 outvec = talloc_zero_array(req, struct iovec, 4);
964 if (!outvec) {
965 return NT_STATUS_NO_MEMORY;
968 /* 0 is always boilerplate and must
969 * be of size 4 for the length field. */
971 outvec[0].iov_base = req->out.nbt_hdr;
972 outvec[0].iov_len = 4;
973 SIVAL(req->out.nbt_hdr, 0, 0);
975 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
976 return NT_STATUS_NO_MEMORY;
979 TALLOC_FREE(req->out.vector);
981 req->out.vector = outvec;
983 req->current_idx = 1;
984 req->out.vector_count = 4;
986 outhdr = (uint8_t *)req->out.vector[1].iov_base;
987 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
988 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
991 defer_endtime = timeval_current_ofs_usec(defer_time);
992 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
993 req, defer_endtime,
994 smbd_smb2_request_pending_timer,
995 req);
996 if (req->async_te == NULL) {
997 return NT_STATUS_NO_MEMORY;
1000 return NT_STATUS_OK;
1003 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1004 struct tevent_timer *te,
1005 struct timeval current_time,
1006 void *private_data)
1008 struct smbd_smb2_request *req =
1009 talloc_get_type_abort(private_data,
1010 struct smbd_smb2_request);
1011 struct smbd_smb2_request_pending_state *state = NULL;
1012 int i = req->current_idx;
1013 uint8_t *outhdr = NULL;
1014 const uint8_t *inhdr = NULL;
1015 uint8_t *hdr = NULL;
1016 uint8_t *body = NULL;
1017 uint32_t flags = 0;
1018 uint64_t message_id = 0;
1019 uint64_t async_id = 0;
1020 struct tevent_req *subreq = NULL;
1022 TALLOC_FREE(req->async_te);
1024 /* Ensure our final reply matches the interim one. */
1025 inhdr = (const uint8_t *)req->in.vector[1].iov_base;
1026 outhdr = (uint8_t *)req->out.vector[1].iov_base;
1027 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1028 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1030 async_id = message_id; /* keep it simple for now... */
1032 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1033 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1035 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1036 "going async\n",
1037 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1038 (unsigned long long)async_id ));
1041 * What we send is identical to a smbd_smb2_request_error
1042 * packet with an error status of STATUS_PENDING. Make use
1043 * of this fact sometime when refactoring. JRA.
1046 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1047 if (state == NULL) {
1048 smbd_server_connection_terminate(req->sconn,
1049 nt_errstr(NT_STATUS_NO_MEMORY));
1050 return;
1052 state->sconn = req->sconn;
1054 state->vector[0].iov_base = (void *)state->buf;
1055 state->vector[0].iov_len = 4;
1057 state->vector[1].iov_base = state->buf + 4;
1058 state->vector[1].iov_len = SMB2_HDR_BODY;
1060 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
1061 state->vector[2].iov_len = 9;
1063 smb2_setup_nbt_length(state->vector, 3);
1065 hdr = (uint8_t *)state->vector[1].iov_base;
1066 body = (uint8_t *)state->vector[2].iov_base;
1068 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1069 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1070 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1071 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1072 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1074 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1075 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1076 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1077 SBVAL(hdr, SMB2_HDR_PID, async_id);
1078 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1079 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1080 memcpy(hdr+SMB2_HDR_SIGNATURE,
1081 outhdr+SMB2_HDR_SIGNATURE, 16);
1083 SSVAL(body, 0x00, 0x08 + 1);
1085 SCVAL(body, 0x02, 0);
1086 SCVAL(body, 0x03, 0);
1087 SIVAL(body, 0x04, 0);
1088 /* Match W2K8R2... */
1089 SCVAL(body, 0x08, 0x21);
1091 /* Ensure we correctly go through crediting. Grant
1092 the credits now, and zero credits on the final
1093 response. */
1094 smb2_set_operation_credit(req->sconn,
1095 &req->in.vector[i],
1096 &state->vector[1]);
1098 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1100 if (req->do_signing) {
1101 NTSTATUS status;
1102 struct smbXsrv_session *x = req->session;
1103 struct smbXsrv_connection *conn = x->connection;
1104 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1106 status = smb2_signing_sign_pdu(signing_key,
1107 conn->protocol,
1108 &state->vector[1], 2);
1109 if (!NT_STATUS_IS_OK(status)) {
1110 smbd_server_connection_terminate(req->sconn,
1111 nt_errstr(status));
1112 return;
1116 subreq = tstream_writev_queue_send(state,
1117 state->sconn->ev_ctx,
1118 state->sconn->smb2.stream,
1119 state->sconn->smb2.send_queue,
1120 state->vector,
1122 if (subreq == NULL) {
1123 smbd_server_connection_terminate(state->sconn,
1124 nt_errstr(NT_STATUS_NO_MEMORY));
1125 return;
1127 tevent_req_set_callback(subreq,
1128 smbd_smb2_request_pending_writev_done,
1129 state);
1132 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1134 struct smbd_server_connection *sconn = req->sconn;
1135 struct smbd_smb2_request *cur;
1136 const uint8_t *inhdr;
1137 int i = req->current_idx;
1138 uint32_t flags;
1139 uint64_t search_message_id;
1140 uint64_t search_async_id;
1141 uint64_t found_id;
1143 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1145 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1146 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1147 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1150 * we don't need the request anymore
1151 * cancel requests never have a response
1153 DLIST_REMOVE(req->sconn->smb2.requests, req);
1154 TALLOC_FREE(req);
1156 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1157 const uint8_t *outhdr;
1158 uint64_t message_id;
1159 uint64_t async_id;
1161 i = cur->current_idx;
1163 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1165 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1166 async_id = BVAL(outhdr, SMB2_HDR_PID);
1168 if (flags & SMB2_HDR_FLAG_ASYNC) {
1169 if (search_async_id == async_id) {
1170 found_id = async_id;
1171 break;
1173 } else {
1174 if (search_message_id == message_id) {
1175 found_id = message_id;
1176 break;
1181 if (cur && cur->subreq) {
1182 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1183 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1184 "cancel opcode[%s] mid %llu\n",
1185 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1186 (unsigned long long)found_id ));
1187 tevent_req_cancel(cur->subreq);
1190 return NT_STATUS_OK;
1193 /*************************************************************
1194 Ensure an incoming tid is a valid one for us to access.
1195 Change to the associated uid credentials and chdir to the
1196 valid tid directory.
1197 *************************************************************/
1199 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1201 const uint8_t *inhdr;
1202 int i = req->current_idx;
1203 uint32_t in_flags;
1204 uint32_t in_tid;
1205 struct smbXsrv_tcon0 *tcon;
1206 NTSTATUS status;
1207 NTTIME now = timeval_to_nttime(&req->request_time);
1209 req->tcon = NULL;
1211 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1213 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1214 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1216 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1217 in_tid = req->last_tid;
1220 status = smb2srv_tcon_lookup(req->session,
1221 in_tid, now, &tcon);
1222 if (!NT_STATUS_IS_OK(status)) {
1223 return status;
1226 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1227 return NT_STATUS_ACCESS_DENIED;
1230 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1231 if (!set_current_service(tcon->compat, 0, true)) {
1232 return NT_STATUS_ACCESS_DENIED;
1235 req->tcon = tcon;
1236 req->last_tid = in_tid;
1238 return NT_STATUS_OK;
1241 /*************************************************************
1242 Ensure an incoming session_id is a valid one for us to access.
1243 *************************************************************/
1245 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1247 const uint8_t *inhdr;
1248 int i = req->current_idx;
1249 uint32_t in_flags;
1250 uint64_t in_session_id;
1251 struct smbXsrv_session *session;
1252 struct auth_session_info *session_info;
1253 NTSTATUS status;
1254 NTTIME now = timeval_to_nttime(&req->request_time);
1256 req->session = NULL;
1257 req->tcon = NULL;
1259 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1261 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1262 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1264 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1265 in_session_id = req->last_session_id;
1268 /* lookup an existing session */
1269 status = smb2srv_session_lookup(req->sconn->conn,
1270 in_session_id, now,
1271 &session);
1272 if (!NT_STATUS_IS_OK(status)) {
1273 return status;
1276 session_info = session->global->auth_session_info;
1277 if (session_info == NULL) {
1278 return NT_STATUS_INVALID_HANDLE;
1281 set_current_user_info(session_info->unix_info->sanitized_username,
1282 session_info->unix_info->unix_name,
1283 session_info->info->domain_name);
1285 req->session = session;
1286 req->last_session_id = in_session_id;
1288 return NT_STATUS_OK;
1291 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1292 uint32_t data_length)
1294 uint16_t needed_charge;
1295 uint16_t credit_charge;
1296 const uint8_t *inhdr;
1297 int i = req->current_idx;
1299 if (!req->sconn->smb2.supports_multicredit) {
1300 if (data_length > 65536) {
1301 return NT_STATUS_INVALID_PARAMETER;
1303 return NT_STATUS_OK;
1306 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1307 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1309 /* requests larger than 64 KB need credit charge */
1310 if (credit_charge == 0 && data_length > 65536) {
1311 DEBUG(2, ("Request larger than 64KB w/o creditcharge\n"));
1312 return NT_STATUS_INVALID_PARAMETER;
1315 needed_charge = (data_length - 1)/ 65536 + 1;
1317 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1318 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1319 credit_charge, needed_charge));
1321 if (needed_charge > credit_charge) {
1322 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1323 credit_charge, needed_charge));
1324 return NT_STATUS_INVALID_PARAMETER;
1327 return NT_STATUS_OK;
1330 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1331 size_t expected_body_size)
1333 const uint8_t *inhdr;
1334 uint16_t opcode;
1335 const uint8_t *inbody;
1336 int i = req->current_idx;
1337 size_t body_size;
1338 size_t min_dyn_size = expected_body_size & 0x00000001;
1341 * The following should be checked already.
1343 if ((i+2) > req->in.vector_count) {
1344 return NT_STATUS_INTERNAL_ERROR;
1346 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1347 return NT_STATUS_INTERNAL_ERROR;
1349 if (req->in.vector[i+1].iov_len < 2) {
1350 return NT_STATUS_INTERNAL_ERROR;
1353 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1354 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1356 switch (opcode) {
1357 case SMB2_OP_IOCTL:
1358 case SMB2_OP_GETINFO:
1359 min_dyn_size = 0;
1360 break;
1364 * Now check the expected body size,
1365 * where the last byte might be in the
1366 * dynamic section..
1368 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1369 return NT_STATUS_INVALID_PARAMETER;
1371 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1372 return NT_STATUS_INVALID_PARAMETER;
1375 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1377 body_size = SVAL(inbody, 0x00);
1378 if (body_size != expected_body_size) {
1379 return NT_STATUS_INVALID_PARAMETER;
1382 return NT_STATUS_OK;
1385 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1387 const uint8_t *inhdr;
1388 int i = req->current_idx;
1389 uint16_t opcode;
1390 uint32_t flags;
1391 uint64_t mid;
1392 NTSTATUS status;
1393 NTSTATUS session_status;
1394 uint32_t allowed_flags;
1395 NTSTATUS return_value;
1396 struct smbXsrv_session *x = NULL;
1398 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1400 /* TODO: verify more things */
1402 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1403 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1404 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1405 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1406 smb2_opcode_name(opcode),
1407 (unsigned long long)mid));
1409 if (get_Protocol() >= PROTOCOL_SMB2_02) {
1411 * once the protocol is negotiated
1412 * SMB2_OP_NEGPROT is not allowed anymore
1414 if (opcode == SMB2_OP_NEGPROT) {
1415 /* drop the connection */
1416 return NT_STATUS_INVALID_PARAMETER;
1418 } else {
1420 * if the protocol is not negotiated yet
1421 * only SMB2_OP_NEGPROT is allowed.
1423 if (opcode != SMB2_OP_NEGPROT) {
1424 /* drop the connection */
1425 return NT_STATUS_INVALID_PARAMETER;
1429 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1430 SMB2_HDR_FLAG_SIGNED |
1431 SMB2_HDR_FLAG_DFS;
1432 if (opcode == SMB2_OP_CANCEL) {
1433 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1435 if ((flags & ~allowed_flags) != 0) {
1436 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1440 * Check if the client provided a valid session id,
1441 * if so smbd_smb2_request_check_session() calls
1442 * set_current_user_info().
1444 * As some command don't require a valid session id
1445 * we defer the check of the session_status
1447 session_status = smbd_smb2_request_check_session(req);
1448 x = req->session;
1450 req->do_signing = false;
1451 if (flags & SMB2_HDR_FLAG_SIGNED) {
1452 struct smbXsrv_connection *conn = x->connection;
1453 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1455 if (!NT_STATUS_IS_OK(session_status)) {
1456 return smbd_smb2_request_error(req, session_status);
1459 req->do_signing = true;
1460 status = smb2_signing_check_pdu(signing_key,
1461 conn->protocol,
1462 &req->in.vector[i], 3);
1463 if (!NT_STATUS_IS_OK(status)) {
1464 return smbd_smb2_request_error(req, status);
1466 } else if (opcode == SMB2_OP_CANCEL) {
1467 /* Cancel requests are allowed to skip the signing */
1468 } else if (x && x->global->signing_required) {
1469 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1472 if (flags & SMB2_HDR_FLAG_CHAINED) {
1474 * This check is mostly for giving the correct error code
1475 * for compounded requests.
1477 * TODO: we may need to move this after the session
1478 * and tcon checks.
1480 if (!NT_STATUS_IS_OK(req->next_status)) {
1481 return smbd_smb2_request_error(req, req->next_status);
1483 } else {
1484 req->compat_chain_fsp = NULL;
1487 if (req->compound_related) {
1488 req->sconn->smb2.compound_related_in_progress = true;
1491 switch (opcode) {
1492 case SMB2_OP_NEGPROT:
1493 /* This call needs to be run as root */
1494 change_to_root_user();
1497 START_PROFILE(smb2_negprot);
1498 return_value = smbd_smb2_request_process_negprot(req);
1499 END_PROFILE(smb2_negprot);
1501 break;
1503 case SMB2_OP_SESSSETUP:
1504 /* This call needs to be run as root */
1505 change_to_root_user();
1508 START_PROFILE(smb2_sesssetup);
1509 return_value = smbd_smb2_request_process_sesssetup(req);
1510 END_PROFILE(smb2_sesssetup);
1512 break;
1514 case SMB2_OP_LOGOFF:
1515 if (!NT_STATUS_IS_OK(session_status)) {
1516 return_value = smbd_smb2_request_error(req, session_status);
1517 break;
1520 /* This call needs to be run as root */
1521 change_to_root_user();
1524 START_PROFILE(smb2_logoff);
1525 return_value = smbd_smb2_request_process_logoff(req);
1526 END_PROFILE(smb2_logoff);
1528 break;
1530 case SMB2_OP_TCON:
1531 if (!NT_STATUS_IS_OK(session_status)) {
1532 return_value = smbd_smb2_request_error(req, session_status);
1533 break;
1537 * This call needs to be run as root.
1539 * smbd_smb2_request_process_tcon()
1540 * calls make_connection_snum(), which will call
1541 * change_to_user(), when needed.
1543 change_to_root_user();
1546 START_PROFILE(smb2_tcon);
1547 return_value = smbd_smb2_request_process_tcon(req);
1548 END_PROFILE(smb2_tcon);
1550 break;
1552 case SMB2_OP_TDIS:
1553 if (!NT_STATUS_IS_OK(session_status)) {
1554 return_value = smbd_smb2_request_error(req, session_status);
1555 break;
1558 * This call needs to be run as user.
1560 * smbd_smb2_request_check_tcon()
1561 * calls change_to_user() on success.
1563 status = smbd_smb2_request_check_tcon(req);
1564 if (!NT_STATUS_IS_OK(status)) {
1565 return_value = smbd_smb2_request_error(req, status);
1566 break;
1568 /* This call needs to be run as root */
1569 change_to_root_user();
1573 START_PROFILE(smb2_tdis);
1574 return_value = smbd_smb2_request_process_tdis(req);
1575 END_PROFILE(smb2_tdis);
1577 break;
1579 case SMB2_OP_CREATE:
1580 if (!NT_STATUS_IS_OK(session_status)) {
1581 return_value = smbd_smb2_request_error(req, session_status);
1582 break;
1585 * This call needs to be run as user.
1587 * smbd_smb2_request_check_tcon()
1588 * calls change_to_user() on success.
1590 status = smbd_smb2_request_check_tcon(req);
1591 if (!NT_STATUS_IS_OK(status)) {
1592 return_value = smbd_smb2_request_error(req, status);
1593 break;
1597 START_PROFILE(smb2_create);
1598 return_value = smbd_smb2_request_process_create(req);
1599 END_PROFILE(smb2_create);
1601 break;
1603 case SMB2_OP_CLOSE:
1604 if (!NT_STATUS_IS_OK(session_status)) {
1605 return_value = smbd_smb2_request_error(req, session_status);
1606 break;
1609 * This call needs to be run as user.
1611 * smbd_smb2_request_check_tcon()
1612 * calls change_to_user() on success.
1614 status = smbd_smb2_request_check_tcon(req);
1615 if (!NT_STATUS_IS_OK(status)) {
1616 return_value = smbd_smb2_request_error(req, status);
1617 break;
1621 START_PROFILE(smb2_close);
1622 return_value = smbd_smb2_request_process_close(req);
1623 END_PROFILE(smb2_close);
1625 break;
1627 case SMB2_OP_FLUSH:
1628 if (!NT_STATUS_IS_OK(session_status)) {
1629 return_value = smbd_smb2_request_error(req, session_status);
1630 break;
1633 * This call needs to be run as user.
1635 * smbd_smb2_request_check_tcon()
1636 * calls change_to_user() on success.
1638 status = smbd_smb2_request_check_tcon(req);
1639 if (!NT_STATUS_IS_OK(status)) {
1640 return_value = smbd_smb2_request_error(req, status);
1641 break;
1645 START_PROFILE(smb2_flush);
1646 return_value = smbd_smb2_request_process_flush(req);
1647 END_PROFILE(smb2_flush);
1649 break;
1651 case SMB2_OP_READ:
1652 if (!NT_STATUS_IS_OK(session_status)) {
1653 return_value = smbd_smb2_request_error(req, session_status);
1654 break;
1657 * This call needs to be run as user.
1659 * smbd_smb2_request_check_tcon()
1660 * calls change_to_user() on success.
1662 status = smbd_smb2_request_check_tcon(req);
1663 if (!NT_STATUS_IS_OK(status)) {
1664 return_value = smbd_smb2_request_error(req, status);
1665 break;
1669 START_PROFILE(smb2_read);
1670 return_value = smbd_smb2_request_process_read(req);
1671 END_PROFILE(smb2_read);
1673 break;
1675 case SMB2_OP_WRITE:
1676 if (!NT_STATUS_IS_OK(session_status)) {
1677 return_value = smbd_smb2_request_error(req, session_status);
1678 break;
1681 * This call needs to be run as user.
1683 * smbd_smb2_request_check_tcon()
1684 * calls change_to_user() on success.
1686 status = smbd_smb2_request_check_tcon(req);
1687 if (!NT_STATUS_IS_OK(status)) {
1688 return_value = smbd_smb2_request_error(req, status);
1689 break;
1693 START_PROFILE(smb2_write);
1694 return_value = smbd_smb2_request_process_write(req);
1695 END_PROFILE(smb2_write);
1697 break;
1699 case SMB2_OP_LOCK:
1700 if (!NT_STATUS_IS_OK(session_status)) {
1701 /* Too ugly to live ? JRA. */
1702 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1703 session_status = NT_STATUS_FILE_CLOSED;
1705 return_value = smbd_smb2_request_error(req, session_status);
1706 break;
1709 * This call needs to be run as user.
1711 * smbd_smb2_request_check_tcon()
1712 * calls change_to_user() on success.
1714 status = smbd_smb2_request_check_tcon(req);
1715 if (!NT_STATUS_IS_OK(status)) {
1716 /* Too ugly to live ? JRA. */
1717 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1718 status = NT_STATUS_FILE_CLOSED;
1720 return_value = smbd_smb2_request_error(req, status);
1721 break;
1725 START_PROFILE(smb2_lock);
1726 return_value = smbd_smb2_request_process_lock(req);
1727 END_PROFILE(smb2_lock);
1729 break;
1731 case SMB2_OP_IOCTL:
1732 if (!NT_STATUS_IS_OK(session_status)) {
1733 return_value = smbd_smb2_request_error(req, session_status);
1734 break;
1737 * This call needs to be run as user.
1739 * smbd_smb2_request_check_tcon()
1740 * calls change_to_user() on success.
1742 status = smbd_smb2_request_check_tcon(req);
1743 if (!NT_STATUS_IS_OK(status)) {
1744 return_value = smbd_smb2_request_error(req, status);
1745 break;
1749 START_PROFILE(smb2_ioctl);
1750 return_value = smbd_smb2_request_process_ioctl(req);
1751 END_PROFILE(smb2_ioctl);
1753 break;
1755 case SMB2_OP_CANCEL:
1757 * This call needs to be run as root
1759 * That is what we also do in the SMB1 case.
1761 change_to_root_user();
1764 START_PROFILE(smb2_cancel);
1765 return_value = smbd_smb2_request_process_cancel(req);
1766 END_PROFILE(smb2_cancel);
1768 break;
1770 case SMB2_OP_KEEPALIVE:
1771 /* This call needs to be run as root */
1772 change_to_root_user();
1775 START_PROFILE(smb2_keepalive);
1776 return_value = smbd_smb2_request_process_keepalive(req);
1777 END_PROFILE(smb2_keepalive);
1779 break;
1781 case SMB2_OP_FIND:
1782 if (!NT_STATUS_IS_OK(session_status)) {
1783 return_value = smbd_smb2_request_error(req, session_status);
1784 break;
1787 * This call needs to be run as user.
1789 * smbd_smb2_request_check_tcon()
1790 * calls change_to_user() on success.
1792 status = smbd_smb2_request_check_tcon(req);
1793 if (!NT_STATUS_IS_OK(status)) {
1794 return_value = smbd_smb2_request_error(req, status);
1795 break;
1799 START_PROFILE(smb2_find);
1800 return_value = smbd_smb2_request_process_find(req);
1801 END_PROFILE(smb2_find);
1803 break;
1805 case SMB2_OP_NOTIFY:
1806 if (!NT_STATUS_IS_OK(session_status)) {
1807 return_value = smbd_smb2_request_error(req, session_status);
1808 break;
1811 * This call needs to be run as user.
1813 * smbd_smb2_request_check_tcon()
1814 * calls change_to_user() on success.
1816 status = smbd_smb2_request_check_tcon(req);
1817 if (!NT_STATUS_IS_OK(status)) {
1818 return_value = smbd_smb2_request_error(req, status);
1819 break;
1823 START_PROFILE(smb2_notify);
1824 return_value = smbd_smb2_request_process_notify(req);
1825 END_PROFILE(smb2_notify);
1827 break;
1829 case SMB2_OP_GETINFO:
1830 if (!NT_STATUS_IS_OK(session_status)) {
1831 return_value = smbd_smb2_request_error(req, session_status);
1832 break;
1835 * This call needs to be run as user.
1837 * smbd_smb2_request_check_tcon()
1838 * calls change_to_user() on success.
1840 status = smbd_smb2_request_check_tcon(req);
1841 if (!NT_STATUS_IS_OK(status)) {
1842 return_value = smbd_smb2_request_error(req, status);
1843 break;
1847 START_PROFILE(smb2_getinfo);
1848 return_value = smbd_smb2_request_process_getinfo(req);
1849 END_PROFILE(smb2_getinfo);
1851 break;
1853 case SMB2_OP_SETINFO:
1854 if (!NT_STATUS_IS_OK(session_status)) {
1855 return_value = smbd_smb2_request_error(req, session_status);
1856 break;
1859 * This call needs to be run as user.
1861 * smbd_smb2_request_check_tcon()
1862 * calls change_to_user() on success.
1864 status = smbd_smb2_request_check_tcon(req);
1865 if (!NT_STATUS_IS_OK(status)) {
1866 return_value = smbd_smb2_request_error(req, status);
1867 break;
1871 START_PROFILE(smb2_setinfo);
1872 return_value = smbd_smb2_request_process_setinfo(req);
1873 END_PROFILE(smb2_setinfo);
1875 break;
1877 case SMB2_OP_BREAK:
1878 if (!NT_STATUS_IS_OK(session_status)) {
1879 return_value = smbd_smb2_request_error(req, session_status);
1880 break;
1883 * This call needs to be run as user.
1885 * smbd_smb2_request_check_tcon()
1886 * calls change_to_user() on success.
1888 status = smbd_smb2_request_check_tcon(req);
1889 if (!NT_STATUS_IS_OK(status)) {
1890 return_value = smbd_smb2_request_error(req, status);
1891 break;
1895 START_PROFILE(smb2_break);
1896 return_value = smbd_smb2_request_process_break(req);
1897 END_PROFILE(smb2_break);
1899 break;
1901 default:
1902 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1903 break;
1905 return return_value;
1908 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1910 struct tevent_req *subreq;
1911 int i = req->current_idx;
1913 req->subreq = NULL;
1914 TALLOC_FREE(req->async_te);
1916 req->current_idx += 3;
1918 if (req->current_idx < req->out.vector_count) {
1920 * We must process the remaining compound
1921 * SMB2 requests before any new incoming SMB2
1922 * requests. This is because incoming SMB2
1923 * requests may include a cancel for a
1924 * compound request we haven't processed
1925 * yet.
1927 struct tevent_immediate *im = tevent_create_immediate(req);
1928 if (!im) {
1929 return NT_STATUS_NO_MEMORY;
1931 tevent_schedule_immediate(im,
1932 req->sconn->ev_ctx,
1933 smbd_smb2_request_dispatch_immediate,
1934 req);
1935 return NT_STATUS_OK;
1938 if (req->compound_related) {
1939 req->sconn->smb2.compound_related_in_progress = false;
1942 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1944 /* Set credit for these operations (zero credits if this
1945 is a final reply for an async operation). */
1946 smb2_calculate_credits(req, req);
1948 if (req->do_signing) {
1949 NTSTATUS status;
1950 struct smbXsrv_session *x = req->session;
1951 struct smbXsrv_connection *conn = x->connection;
1952 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1954 status = smb2_signing_sign_pdu(signing_key,
1955 conn->protocol,
1956 &req->out.vector[i], 3);
1957 if (!NT_STATUS_IS_OK(status)) {
1958 return status;
1962 if (DEBUGLEVEL >= 10) {
1963 dbgtext("smbd_smb2_request_reply: sending...\n");
1964 print_req_vectors(req);
1967 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1968 if (req->out.vector_count == 4 &&
1969 req->out.vector[3].iov_base == NULL &&
1970 req->out.vector[3].iov_len != 0) {
1971 /* Dynamic part is NULL. Chop it off,
1972 We're going to send it via sendfile. */
1973 req->out.vector_count -= 1;
1976 subreq = tstream_writev_queue_send(req,
1977 req->sconn->ev_ctx,
1978 req->sconn->smb2.stream,
1979 req->sconn->smb2.send_queue,
1980 req->out.vector,
1981 req->out.vector_count);
1982 if (subreq == NULL) {
1983 return NT_STATUS_NO_MEMORY;
1985 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1987 * We're done with this request -
1988 * move it off the "being processed" queue.
1990 DLIST_REMOVE(req->sconn->smb2.requests, req);
1992 return NT_STATUS_OK;
1995 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
1997 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1998 struct tevent_immediate *im,
1999 void *private_data)
2001 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2002 struct smbd_smb2_request);
2003 struct smbd_server_connection *sconn = req->sconn;
2004 NTSTATUS status;
2006 TALLOC_FREE(im);
2008 if (DEBUGLEVEL >= 10) {
2009 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2010 req->current_idx, req->in.vector_count));
2011 print_req_vectors(req);
2014 status = smbd_smb2_request_dispatch(req);
2015 if (!NT_STATUS_IS_OK(status)) {
2016 smbd_server_connection_terminate(sconn, nt_errstr(status));
2017 return;
2020 status = smbd_smb2_request_next_incoming(sconn);
2021 if (!NT_STATUS_IS_OK(status)) {
2022 smbd_server_connection_terminate(sconn, nt_errstr(status));
2023 return;
2027 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
2029 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
2030 struct smbd_smb2_request);
2031 struct smbd_server_connection *sconn = req->sconn;
2032 int ret;
2033 int sys_errno;
2034 NTSTATUS status;
2036 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2037 TALLOC_FREE(subreq);
2038 TALLOC_FREE(req);
2039 if (ret == -1) {
2040 status = map_nt_error_from_unix(sys_errno);
2041 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2042 nt_errstr(status)));
2043 smbd_server_connection_terminate(sconn, nt_errstr(status));
2044 return;
2047 status = smbd_smb2_request_next_incoming(sconn);
2048 if (!NT_STATUS_IS_OK(status)) {
2049 smbd_server_connection_terminate(sconn, nt_errstr(status));
2050 return;
2054 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2055 NTSTATUS status,
2056 DATA_BLOB body, DATA_BLOB *dyn,
2057 const char *location)
2059 uint8_t *outhdr;
2060 int i = req->current_idx;
2061 uint32_t next_command_ofs;
2063 DEBUG(10,("smbd_smb2_request_done_ex: "
2064 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2065 i, nt_errstr(status), (unsigned int)body.length,
2066 dyn ? "yes": "no",
2067 (unsigned int)(dyn ? dyn->length : 0),
2068 location));
2070 if (body.length < 2) {
2071 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2074 if ((body.length % 2) != 0) {
2075 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2078 outhdr = (uint8_t *)req->out.vector[i].iov_base;
2080 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2081 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2083 req->out.vector[i+1].iov_base = (void *)body.data;
2084 req->out.vector[i+1].iov_len = body.length;
2086 if (dyn) {
2087 req->out.vector[i+2].iov_base = (void *)dyn->data;
2088 req->out.vector[i+2].iov_len = dyn->length;
2089 } else {
2090 req->out.vector[i+2].iov_base = NULL;
2091 req->out.vector[i+2].iov_len = 0;
2094 /* see if we need to recalculate the offset to the next response */
2095 if (next_command_ofs > 0) {
2096 next_command_ofs = SMB2_HDR_BODY;
2097 next_command_ofs += req->out.vector[i+1].iov_len;
2098 next_command_ofs += req->out.vector[i+2].iov_len;
2101 if ((next_command_ofs % 8) != 0) {
2102 size_t pad_size = 8 - (next_command_ofs % 8);
2103 if (req->out.vector[i+2].iov_len == 0) {
2105 * if the dyn buffer is empty
2106 * we can use it to add padding
2108 uint8_t *pad;
2110 pad = talloc_zero_array(req->out.vector,
2111 uint8_t, pad_size);
2112 if (pad == NULL) {
2113 return smbd_smb2_request_error(req,
2114 NT_STATUS_NO_MEMORY);
2117 req->out.vector[i+2].iov_base = (void *)pad;
2118 req->out.vector[i+2].iov_len = pad_size;
2119 } else {
2121 * For now we copy the dynamic buffer
2122 * and add the padding to the new buffer
2124 size_t old_size;
2125 uint8_t *old_dyn;
2126 size_t new_size;
2127 uint8_t *new_dyn;
2129 old_size = req->out.vector[i+2].iov_len;
2130 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2132 new_size = old_size + pad_size;
2133 new_dyn = talloc_zero_array(req->out.vector,
2134 uint8_t, new_size);
2135 if (new_dyn == NULL) {
2136 return smbd_smb2_request_error(req,
2137 NT_STATUS_NO_MEMORY);
2140 memcpy(new_dyn, old_dyn, old_size);
2141 memset(new_dyn + old_size, 0, pad_size);
2143 req->out.vector[i+2].iov_base = (void *)new_dyn;
2144 req->out.vector[i+2].iov_len = new_size;
2146 next_command_ofs += pad_size;
2149 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2151 return smbd_smb2_request_reply(req);
2154 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2155 NTSTATUS status,
2156 DATA_BLOB *info,
2157 const char *location)
2159 DATA_BLOB body;
2160 int i = req->current_idx;
2161 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
2163 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2164 i, nt_errstr(status), info ? " +info" : "",
2165 location));
2167 body.data = outhdr + SMB2_HDR_BODY;
2168 body.length = 8;
2169 SSVAL(body.data, 0, 9);
2171 if (info) {
2172 SIVAL(body.data, 0x04, info->length);
2173 } else {
2174 /* Allocated size of req->out.vector[i].iov_base
2175 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2176 * 1 byte without having to do an alloc.
2178 info = talloc_zero_array(req->out.vector,
2179 DATA_BLOB,
2181 if (!info) {
2182 return NT_STATUS_NO_MEMORY;
2184 info->data = ((uint8_t *)outhdr) +
2185 OUTVEC_ALLOC_SIZE - 1;
2186 info->length = 1;
2187 SCVAL(info->data, 0, 0);
2191 * if a request fails, all other remaining
2192 * compounded requests should fail too
2194 req->next_status = NT_STATUS_INVALID_PARAMETER;
2196 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2200 struct smbd_smb2_send_oplock_break_state {
2201 struct smbd_server_connection *sconn;
2202 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2203 struct iovec vector;
2206 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2208 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2209 uint64_t file_id_persistent,
2210 uint64_t file_id_volatile,
2211 uint8_t oplock_level)
2213 struct smbd_smb2_send_oplock_break_state *state;
2214 struct tevent_req *subreq;
2215 uint8_t *hdr;
2216 uint8_t *body;
2218 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2219 if (state == NULL) {
2220 return NT_STATUS_NO_MEMORY;
2222 state->sconn = sconn;
2224 state->vector.iov_base = (void *)state->buf;
2225 state->vector.iov_len = sizeof(state->buf);
2227 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2228 hdr = state->buf + 4;
2229 body = hdr + SMB2_HDR_BODY;
2231 SIVAL(hdr, 0, SMB2_MAGIC);
2232 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2233 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2234 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2235 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2236 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2237 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2238 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2239 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2240 SIVAL(hdr, SMB2_HDR_PID, 0);
2241 SIVAL(hdr, SMB2_HDR_TID, 0);
2242 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2243 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2245 SSVAL(body, 0x00, 0x18);
2247 SCVAL(body, 0x02, oplock_level);
2248 SCVAL(body, 0x03, 0); /* reserved */
2249 SIVAL(body, 0x04, 0); /* reserved */
2250 SBVAL(body, 0x08, file_id_persistent);
2251 SBVAL(body, 0x10, file_id_volatile);
2253 subreq = tstream_writev_queue_send(state,
2254 sconn->ev_ctx,
2255 sconn->smb2.stream,
2256 sconn->smb2.send_queue,
2257 &state->vector, 1);
2258 if (subreq == NULL) {
2259 return NT_STATUS_NO_MEMORY;
2261 tevent_req_set_callback(subreq,
2262 smbd_smb2_oplock_break_writev_done,
2263 state);
2265 return NT_STATUS_OK;
2268 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2270 struct smbd_smb2_send_oplock_break_state *state =
2271 tevent_req_callback_data(subreq,
2272 struct smbd_smb2_send_oplock_break_state);
2273 struct smbd_server_connection *sconn = state->sconn;
2274 int ret;
2275 int sys_errno;
2277 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2278 TALLOC_FREE(subreq);
2279 if (ret == -1) {
2280 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2281 smbd_server_connection_terminate(sconn, nt_errstr(status));
2282 return;
2285 TALLOC_FREE(state);
2288 struct smbd_smb2_request_read_state {
2289 size_t missing;
2290 bool asked_for_header;
2291 struct smbd_smb2_request *smb2_req;
2294 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2295 void *private_data,
2296 TALLOC_CTX *mem_ctx,
2297 struct iovec **_vector,
2298 size_t *_count);
2299 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2301 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2302 struct tevent_context *ev,
2303 struct smbd_server_connection *sconn)
2305 struct tevent_req *req;
2306 struct smbd_smb2_request_read_state *state;
2307 struct tevent_req *subreq;
2309 req = tevent_req_create(mem_ctx, &state,
2310 struct smbd_smb2_request_read_state);
2311 if (req == NULL) {
2312 return NULL;
2314 state->missing = 0;
2315 state->asked_for_header = false;
2317 state->smb2_req = smbd_smb2_request_allocate(state);
2318 if (tevent_req_nomem(state->smb2_req, req)) {
2319 return tevent_req_post(req, ev);
2321 state->smb2_req->sconn = sconn;
2323 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2324 sconn->smb2.recv_queue,
2325 smbd_smb2_request_next_vector,
2326 state);
2327 if (tevent_req_nomem(subreq, req)) {
2328 return tevent_req_post(req, ev);
2330 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2332 return req;
2335 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2336 void *private_data,
2337 TALLOC_CTX *mem_ctx,
2338 struct iovec **_vector,
2339 size_t *_count)
2341 struct smbd_smb2_request_read_state *state =
2342 talloc_get_type_abort(private_data,
2343 struct smbd_smb2_request_read_state);
2344 struct smbd_smb2_request *req = state->smb2_req;
2345 struct iovec *vector;
2346 int idx = req->in.vector_count;
2347 size_t len = 0;
2348 uint8_t *buf = NULL;
2350 if (req->in.vector_count == 0) {
2352 * first we need to get the NBT header
2354 req->in.vector = talloc_array(req, struct iovec,
2355 req->in.vector_count + 1);
2356 if (req->in.vector == NULL) {
2357 return -1;
2359 req->in.vector_count += 1;
2361 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2362 req->in.vector[idx].iov_len = 4;
2364 vector = talloc_array(mem_ctx, struct iovec, 1);
2365 if (vector == NULL) {
2366 return -1;
2369 vector[0] = req->in.vector[idx];
2371 *_vector = vector;
2372 *_count = 1;
2373 return 0;
2376 if (req->in.vector_count == 1) {
2378 * Now we analyze the NBT header
2380 state->missing = smb2_len(req->in.vector[0].iov_base);
2382 if (state->missing == 0) {
2383 /* if there're no remaining bytes, we're done */
2384 *_vector = NULL;
2385 *_count = 0;
2386 return 0;
2389 req->in.vector = talloc_realloc(req, req->in.vector,
2390 struct iovec,
2391 req->in.vector_count + 1);
2392 if (req->in.vector == NULL) {
2393 return -1;
2395 req->in.vector_count += 1;
2397 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2399 * it's a special NBT message,
2400 * so get all remaining bytes
2402 len = state->missing;
2403 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2405 * it's an invalid message, just read what we can get
2406 * and let the caller handle the error
2408 len = state->missing;
2409 } else {
2411 * We assume it's a SMB2 request,
2412 * and we first get the header and the
2413 * first 2 bytes (the struct size) of the body
2415 len = SMB2_HDR_BODY + 2;
2417 state->asked_for_header = true;
2420 state->missing -= len;
2422 buf = talloc_array(req->in.vector, uint8_t, len);
2423 if (buf == NULL) {
2424 return -1;
2427 req->in.vector[idx].iov_base = (void *)buf;
2428 req->in.vector[idx].iov_len = len;
2430 vector = talloc_array(mem_ctx, struct iovec, 1);
2431 if (vector == NULL) {
2432 return -1;
2435 vector[0] = req->in.vector[idx];
2437 *_vector = vector;
2438 *_count = 1;
2439 return 0;
2442 if (state->missing == 0) {
2443 /* if there're no remaining bytes, we're done */
2444 *_vector = NULL;
2445 *_count = 0;
2446 return 0;
2449 if (state->asked_for_header) {
2450 const uint8_t *hdr;
2451 size_t full_size;
2452 size_t next_command_ofs;
2453 size_t body_size;
2454 uint8_t *body;
2455 size_t dyn_size;
2456 uint8_t *dyn;
2457 bool invalid = false;
2459 state->asked_for_header = false;
2462 * We got the SMB2 header and the first 2 bytes
2463 * of the body. We fix the size to just the header
2464 * and manually copy the 2 first bytes to the body section
2466 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2467 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2469 /* allocate vectors for body and dynamic areas */
2470 req->in.vector = talloc_realloc(req, req->in.vector,
2471 struct iovec,
2472 req->in.vector_count + 2);
2473 if (req->in.vector == NULL) {
2474 return -1;
2476 req->in.vector_count += 2;
2478 full_size = state->missing + SMB2_HDR_BODY + 2;
2479 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2480 body_size = SVAL(hdr, SMB2_HDR_BODY);
2482 if (next_command_ofs != 0) {
2483 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2485 * this is invalid, just return a zero
2486 * body and let the caller deal with the error
2488 invalid = true;
2489 } else if (next_command_ofs > full_size) {
2491 * this is invalid, just return a zero
2492 * body and let the caller deal with the error
2494 invalid = true;
2495 } else {
2496 full_size = next_command_ofs;
2500 if (!invalid) {
2501 if (body_size < 2) {
2503 * this is invalid, just return a zero
2504 * body and let the caller deal with the error
2506 invalid = true;
2510 * Mask out the lowest bit, the "dynamic" part
2511 * of body_size.
2513 body_size &= ~1;
2515 if (body_size > (full_size - SMB2_HDR_BODY)) {
2517 * this is invalid, just return a zero
2518 * body and let the caller deal with the error
2520 invalid = true;
2524 if (invalid) {
2525 /* the caller should check this */
2526 body_size = 2;
2529 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2531 state->missing -= (body_size - 2) + dyn_size;
2533 body = talloc_array(req->in.vector, uint8_t, body_size);
2534 if (body == NULL) {
2535 return -1;
2538 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2539 if (dyn == NULL) {
2540 return -1;
2543 req->in.vector[idx].iov_base = (void *)body;
2544 req->in.vector[idx].iov_len = body_size;
2545 req->in.vector[idx+1].iov_base = (void *)dyn;
2546 req->in.vector[idx+1].iov_len = dyn_size;
2548 vector = talloc_array(mem_ctx, struct iovec, 2);
2549 if (vector == NULL) {
2550 return -1;
2554 * the first 2 bytes of the body were already fetched
2555 * together with the header
2557 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2558 vector[0].iov_base = body + 2;
2559 vector[0].iov_len = body_size - 2;
2561 vector[1] = req->in.vector[idx+1];
2563 *_vector = vector;
2564 *_count = 2;
2565 return 0;
2569 * when we endup here, we're looking for a new SMB2 request
2570 * next. And we ask for its header and the first 2 bytes of
2571 * the body (like we did for the first SMB2 request).
2574 req->in.vector = talloc_realloc(req, req->in.vector,
2575 struct iovec,
2576 req->in.vector_count + 1);
2577 if (req->in.vector == NULL) {
2578 return -1;
2580 req->in.vector_count += 1;
2583 * We assume it's a SMB2 request,
2584 * and we first get the header and the
2585 * first 2 bytes (the struct size) of the body
2587 len = SMB2_HDR_BODY + 2;
2589 if (len > state->missing) {
2590 /* let the caller handle the error */
2591 len = state->missing;
2594 state->missing -= len;
2595 state->asked_for_header = true;
2597 buf = talloc_array(req->in.vector, uint8_t, len);
2598 if (buf == NULL) {
2599 return -1;
2602 req->in.vector[idx].iov_base = (void *)buf;
2603 req->in.vector[idx].iov_len = len;
2605 vector = talloc_array(mem_ctx, struct iovec, 1);
2606 if (vector == NULL) {
2607 return -1;
2610 vector[0] = req->in.vector[idx];
2612 *_vector = vector;
2613 *_count = 1;
2614 return 0;
2617 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2619 struct tevent_req *req =
2620 tevent_req_callback_data(subreq,
2621 struct tevent_req);
2622 int ret;
2623 int sys_errno;
2624 NTSTATUS status;
2626 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2627 if (ret == -1) {
2628 status = map_nt_error_from_unix(sys_errno);
2629 tevent_req_nterror(req, status);
2630 return;
2633 tevent_req_done(req);
2636 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2637 TALLOC_CTX *mem_ctx,
2638 struct smbd_smb2_request **_smb2_req)
2640 struct smbd_smb2_request_read_state *state =
2641 tevent_req_data(req,
2642 struct smbd_smb2_request_read_state);
2643 NTSTATUS status;
2645 if (tevent_req_is_nterror(req, &status)) {
2646 tevent_req_received(req);
2647 return status;
2650 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2651 *_smb2_req = state->smb2_req;
2652 tevent_req_received(req);
2653 return NT_STATUS_OK;
2656 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2658 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2660 size_t max_send_queue_len;
2661 size_t cur_send_queue_len;
2662 struct tevent_req *subreq;
2664 if (sconn->smb2.compound_related_in_progress) {
2666 * Can't read another until the related
2667 * compound is done.
2669 return NT_STATUS_OK;
2672 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2674 * if there is already a smbd_smb2_request_read
2675 * pending, we are done.
2677 return NT_STATUS_OK;
2680 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2681 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2683 if (cur_send_queue_len > max_send_queue_len) {
2685 * if we have a lot of requests to send,
2686 * we wait until they are on the wire until we
2687 * ask for the next request.
2689 return NT_STATUS_OK;
2692 /* ask for the next request */
2693 subreq = smbd_smb2_request_read_send(sconn, sconn->ev_ctx, sconn);
2694 if (subreq == NULL) {
2695 return NT_STATUS_NO_MEMORY;
2697 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2699 return NT_STATUS_OK;
2702 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2703 const uint8_t *inbuf, size_t size)
2705 NTSTATUS status;
2706 struct smbd_smb2_request *req = NULL;
2708 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2709 (unsigned int)size));
2711 status = smbd_initialize_smb2(sconn);
2712 if (!NT_STATUS_IS_OK(status)) {
2713 smbd_server_connection_terminate(sconn, nt_errstr(status));
2714 return;
2717 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2718 if (!NT_STATUS_IS_OK(status)) {
2719 smbd_server_connection_terminate(sconn, nt_errstr(status));
2720 return;
2723 status = smbd_smb2_request_setup_out(req);
2724 if (!NT_STATUS_IS_OK(status)) {
2725 smbd_server_connection_terminate(sconn, nt_errstr(status));
2726 return;
2729 status = smbd_smb2_request_dispatch(req);
2730 if (!NT_STATUS_IS_OK(status)) {
2731 smbd_server_connection_terminate(sconn, nt_errstr(status));
2732 return;
2735 status = smbd_smb2_request_next_incoming(sconn);
2736 if (!NT_STATUS_IS_OK(status)) {
2737 smbd_server_connection_terminate(sconn, nt_errstr(status));
2738 return;
2741 sconn->num_requests++;
2744 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2746 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2747 struct smbd_server_connection);
2748 NTSTATUS status;
2749 struct smbd_smb2_request *req = NULL;
2751 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2752 TALLOC_FREE(subreq);
2753 if (!NT_STATUS_IS_OK(status)) {
2754 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2755 nt_errstr(status)));
2756 smbd_server_connection_terminate(sconn, nt_errstr(status));
2757 return;
2760 if (req->in.nbt_hdr[0] != 0x00) {
2761 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2762 req->in.nbt_hdr[0]));
2763 TALLOC_FREE(req);
2764 goto next;
2767 req->current_idx = 1;
2769 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2770 req->current_idx, req->in.vector_count));
2772 status = smbd_smb2_request_validate(req);
2773 if (!NT_STATUS_IS_OK(status)) {
2774 smbd_server_connection_terminate(sconn, nt_errstr(status));
2775 return;
2778 status = smbd_smb2_request_setup_out(req);
2779 if (!NT_STATUS_IS_OK(status)) {
2780 smbd_server_connection_terminate(sconn, nt_errstr(status));
2781 return;
2784 status = smbd_smb2_request_dispatch(req);
2785 if (!NT_STATUS_IS_OK(status)) {
2786 smbd_server_connection_terminate(sconn, nt_errstr(status));
2787 return;
2790 next:
2791 status = smbd_smb2_request_next_incoming(sconn);
2792 if (!NT_STATUS_IS_OK(status)) {
2793 smbd_server_connection_terminate(sconn, nt_errstr(status));
2794 return;
2797 sconn->num_requests++;
2799 /* The timeout_processing function isn't run nearly
2800 often enough to implement 'max log size' without
2801 overrunning the size of the file by many megabytes.
2802 This is especially true if we are running at debug
2803 level 10. Checking every 50 SMB2s is a nice
2804 tradeoff of performance vs log file size overrun. */
2806 if ((sconn->num_requests % 50) == 0 &&
2807 need_to_check_log_size()) {
2808 change_to_root_user();
2809 check_log_size();