s3:smb2_server: split out a smb2_validate_sequence_number() function
[Samba/gebeck_regimport.git] / source3 / smbd / smb2_server.c
blobc4d7d926d1d90d4bacc9a0285b666cec6b750159
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 = 1;
113 sconn->smb2.max_credits = lp_smb2_max_credits();
114 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
115 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_sequence_number(struct smbd_server_connection *sconn,
297 uint64_t message_id, uint64_t seq_id)
299 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
300 unsigned int offset;
302 if (seq_id < sconn->smb2.seqnum_low) {
303 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
304 "%llu (sequence id %llu) (low = %llu, max = %lu)\n",
305 (unsigned long long)message_id,
306 (unsigned long long)seq_id,
307 (unsigned long long)sconn->smb2.seqnum_low,
308 (unsigned long)sconn->smb2.max_credits));
309 return false;
312 if (seq_id > (sconn->smb2.seqnum_low + sconn->smb2.max_credits)) {
313 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
314 "%llu (sequence id %llu) (low = %llu, max = %lu)\n",
315 (unsigned long long)message_id,
316 (unsigned long long)seq_id,
317 (unsigned long long)sconn->smb2.seqnum_low,
318 (unsigned long)sconn->smb2.max_credits));
319 return false;
322 offset = seq_id % sconn->smb2.max_credits;
324 if (bitmap_query(credits_bm, offset)) {
325 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
326 "%llu (sequence id %llu) (low = %llu, max = %lu) "
327 "(bm offset %u)\n",
328 (unsigned long long)message_id,
329 (unsigned long long)seq_id,
330 (unsigned long long)sconn->smb2.seqnum_low,
331 (unsigned long)sconn->smb2.max_credits,
332 offset));
333 return false;
336 /* Mark the message_ids as seen in the bitmap. */
337 bitmap_set(credits_bm, offset);
339 if (seq_id != sconn->smb2.seqnum_low) {
340 return true;
344 * Move the window forward by all the message_id's
345 * already seen.
347 while (bitmap_query(credits_bm, offset)) {
348 DEBUG(10,("smb2_validate_sequence_number: clearing "
349 "id %llu (position %u) from bitmap\n",
350 (unsigned long long)(sconn->smb2.seqnum_low),
351 offset));
352 bitmap_clear(credits_bm, offset);
354 sconn->smb2.seqnum_low += 1;
355 offset = sconn->smb2.seqnum_low % sconn->smb2.max_credits;
358 return true;
361 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
362 const uint8_t *inhdr)
364 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
365 uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
366 uint16_t credit_charge = 1;
367 uint64_t i;
369 if (opcode == SMB2_OP_CANCEL) {
370 /* SMB2_CANCEL requests by definition resend messageids. */
371 return true;
374 if (sconn->smb2.credits_granted == 0) {
375 DEBUG(0,("smb2_validate_message_id: client used more "
376 "credits than granted, message_id (%llu)\n",
377 (unsigned long long)message_id));
378 return false;
381 if (sconn->smb2.supports_multicredit) {
382 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
383 credit_charge = MAX(credit_charge, 1);
386 DEBUG(11, ("smb2_validate_message_id: mid %llu, credits_granted %llu, "
387 "charge %llu, max_credits %llu, seqnum_low: %llu\n",
388 (unsigned long long) message_id,
389 (unsigned long long) sconn->smb2.credits_granted,
390 (unsigned long long) credit_charge,
391 (unsigned long long) sconn->smb2.max_credits,
392 (unsigned long long) sconn->smb2.seqnum_low));
395 * now check the message ids
397 * for multi-credit requests we need to check all current mid plus
398 * the implicit mids caused by the credit charge
399 * e.g. current mid = 15, charge 5 => mark 15-19 as used
402 for (i = 0; i <= (credit_charge-1); i++) {
403 uint64_t id = message_id + i;
404 bool ok;
406 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
407 (unsigned long long)message_id,
408 credit_charge,
409 (unsigned long long)id));
411 ok = smb2_validate_sequence_number(sconn, message_id, id);
412 if (!ok) {
413 return false;
417 /* substract used credits */
418 sconn->smb2.credits_granted -= credit_charge;
420 return true;
423 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
425 int count;
426 int idx;
428 count = req->in.vector_count;
430 if (count < 4) {
431 /* It's not a SMB2 request */
432 return NT_STATUS_INVALID_PARAMETER;
435 for (idx=1; idx < count; idx += 3) {
436 const uint8_t *inhdr = NULL;
437 uint32_t flags;
439 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
440 return NT_STATUS_INVALID_PARAMETER;
443 if (req->in.vector[idx+1].iov_len < 2) {
444 return NT_STATUS_INVALID_PARAMETER;
447 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
449 /* Check the SMB2 header */
450 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
451 return NT_STATUS_INVALID_PARAMETER;
454 if (!smb2_validate_message_id(req->sconn, inhdr)) {
455 return NT_STATUS_INVALID_PARAMETER;
458 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
459 if (idx == 1) {
461 * the 1st request should never have the
462 * SMB2_HDR_FLAG_CHAINED flag set
464 if (flags & SMB2_HDR_FLAG_CHAINED) {
465 req->next_status = NT_STATUS_INVALID_PARAMETER;
466 return NT_STATUS_OK;
468 } else if (idx == 4) {
470 * the 2nd request triggers related vs. unrelated
471 * compounded requests
473 if (flags & SMB2_HDR_FLAG_CHAINED) {
474 req->compound_related = true;
476 } else if (idx > 4) {
477 #if 0
479 * It seems the this tests are wrong
480 * see the SMB2-COMPOUND test
484 * all other requests should match the 2nd one
486 if (flags & SMB2_HDR_FLAG_CHAINED) {
487 if (!req->compound_related) {
488 req->next_status =
489 NT_STATUS_INVALID_PARAMETER;
490 return NT_STATUS_OK;
492 } else {
493 if (req->compound_related) {
494 req->next_status =
495 NT_STATUS_INVALID_PARAMETER;
496 return NT_STATUS_OK;
499 #endif
503 return NT_STATUS_OK;
506 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
507 const struct iovec *in_vector,
508 struct iovec *out_vector)
510 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
511 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
512 uint16_t credits_requested;
513 uint32_t out_flags;
514 uint16_t credits_granted = 0;
516 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
517 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
519 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
521 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
523 * In case we already send an async interim
524 * response, we should not grant
525 * credits on the final response.
527 credits_requested = 0;
530 if (credits_requested) {
531 uint16_t modified_credits_requested;
532 uint32_t multiplier;
535 * Split up max_credits into 1/16ths, and then scale
536 * the requested credits by how many 16ths have been
537 * currently granted. Less than 1/16th == grant all
538 * requested (100%), scale down as more have been
539 * granted. Never ask for less than 1 as the client
540 * asked for at least 1. JRA.
543 multiplier = 16 - (((sconn->smb2.credits_granted * 16) / sconn->smb2.max_credits) % 16);
545 modified_credits_requested = (multiplier * credits_requested) / 16;
546 if (modified_credits_requested == 0) {
547 modified_credits_requested = 1;
550 /* Remember what we gave out. */
551 credits_granted = MIN(modified_credits_requested,
552 (sconn->smb2.max_credits - sconn->smb2.credits_granted));
555 if (credits_granted == 0 && sconn->smb2.credits_granted == 0) {
556 /* First negprot packet, or ensure the client credits can
557 never drop to zero. */
558 credits_granted = 1;
561 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
562 sconn->smb2.credits_granted += credits_granted;
564 DEBUG(10,("smb2_set_operation_credit: requested %u, "
565 "granted %u, total granted %u\n",
566 (unsigned int)credits_requested,
567 (unsigned int)credits_granted,
568 (unsigned int)sconn->smb2.credits_granted ));
571 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
572 struct smbd_smb2_request *outreq)
574 int count, idx;
575 uint16_t total_credits = 0;
577 count = outreq->out.vector_count;
579 for (idx=1; idx < count; idx += 3) {
580 uint8_t *outhdr = (uint8_t *)outreq->out.vector[idx].iov_base;
581 smb2_set_operation_credit(outreq->sconn,
582 &inreq->in.vector[idx],
583 &outreq->out.vector[idx]);
584 /* To match Windows, count up what we
585 just granted. */
586 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
587 /* Set to zero in all but the last reply. */
588 if (idx + 3 < count) {
589 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
590 } else {
591 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
596 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
598 struct iovec *vector;
599 int count;
600 int idx;
602 req->request_time = timeval_current();
604 count = req->in.vector_count;
605 vector = talloc_zero_array(req, struct iovec, count);
606 if (vector == NULL) {
607 return NT_STATUS_NO_MEMORY;
610 vector[0].iov_base = req->out.nbt_hdr;
611 vector[0].iov_len = 4;
612 SIVAL(req->out.nbt_hdr, 0, 0);
614 for (idx=1; idx < count; idx += 3) {
615 const uint8_t *inhdr = NULL;
616 uint8_t *outhdr = NULL;
617 uint8_t *outbody = NULL;
618 uint32_t next_command_ofs = 0;
619 struct iovec *current = &vector[idx];
621 if ((idx + 3) < count) {
622 /* we have a next command -
623 * setup for the error case. */
624 next_command_ofs = SMB2_HDR_BODY + 9;
627 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
629 outhdr = talloc_zero_array(vector, uint8_t,
630 OUTVEC_ALLOC_SIZE);
631 if (outhdr == NULL) {
632 return NT_STATUS_NO_MEMORY;
635 outbody = outhdr + SMB2_HDR_BODY;
637 current[0].iov_base = (void *)outhdr;
638 current[0].iov_len = SMB2_HDR_BODY;
640 current[1].iov_base = (void *)outbody;
641 current[1].iov_len = 8;
643 current[2].iov_base = NULL;
644 current[2].iov_len = 0;
646 /* setup the SMB2 header */
647 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
648 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
649 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
650 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
651 SIVAL(outhdr, SMB2_HDR_STATUS,
652 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
653 SSVAL(outhdr, SMB2_HDR_OPCODE,
654 SVAL(inhdr, SMB2_HDR_OPCODE));
655 SIVAL(outhdr, SMB2_HDR_FLAGS,
656 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
657 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
658 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
659 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
660 SIVAL(outhdr, SMB2_HDR_PID,
661 IVAL(inhdr, SMB2_HDR_PID));
662 SIVAL(outhdr, SMB2_HDR_TID,
663 IVAL(inhdr, SMB2_HDR_TID));
664 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
665 BVAL(inhdr, SMB2_HDR_SESSION_ID));
666 memcpy(outhdr + SMB2_HDR_SIGNATURE,
667 inhdr + SMB2_HDR_SIGNATURE, 16);
669 /* setup error body header */
670 SSVAL(outbody, 0x00, 0x08 + 1);
671 SSVAL(outbody, 0x02, 0);
672 SIVAL(outbody, 0x04, 0);
675 req->out.vector = vector;
676 req->out.vector_count = count;
678 /* setup the length of the NBT packet */
679 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
681 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
683 return NT_STATUS_OK;
686 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
687 const char *reason,
688 const char *location)
690 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
691 reason, location));
692 exit_server_cleanly(reason);
695 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
696 struct iovec *outvec,
697 const struct iovec *srcvec)
699 /* vec[0] is always boilerplate and must
700 * be allocated with size OUTVEC_ALLOC_SIZE. */
702 outvec[0].iov_base = talloc_memdup(ctx,
703 srcvec[0].iov_base,
704 OUTVEC_ALLOC_SIZE);
705 if (!outvec[0].iov_base) {
706 return false;
708 outvec[0].iov_len = SMB2_HDR_BODY;
711 * If this is a "standard" vec[1] of length 8,
712 * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
713 * then duplicate this. Else use talloc_memdup().
716 if (srcvec[1].iov_len == 8 &&
717 srcvec[1].iov_base ==
718 ((uint8_t *)srcvec[0].iov_base) +
719 SMB2_HDR_BODY) {
720 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
721 SMB2_HDR_BODY;
722 outvec[1].iov_len = 8;
723 } else {
724 outvec[1].iov_base = talloc_memdup(ctx,
725 srcvec[1].iov_base,
726 srcvec[1].iov_len);
727 if (!outvec[1].iov_base) {
728 return false;
730 outvec[1].iov_len = srcvec[1].iov_len;
734 * If this is a "standard" vec[2] of length 1,
735 * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
736 * then duplicate this. Else use talloc_memdup().
739 if (srcvec[2].iov_base &&
740 srcvec[2].iov_len) {
741 if (srcvec[2].iov_base ==
742 ((uint8_t *)srcvec[0].iov_base) +
743 (OUTVEC_ALLOC_SIZE - 1) &&
744 srcvec[2].iov_len == 1) {
745 /* Common SMB2 error packet case. */
746 outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
747 (OUTVEC_ALLOC_SIZE - 1);
748 } else {
749 outvec[2].iov_base = talloc_memdup(ctx,
750 srcvec[2].iov_base,
751 srcvec[2].iov_len);
752 if (!outvec[2].iov_base) {
753 return false;
756 outvec[2].iov_len = srcvec[2].iov_len;
757 } else {
758 outvec[2].iov_base = NULL;
759 outvec[2].iov_len = 0;
761 return true;
764 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
766 struct smbd_smb2_request *newreq = NULL;
767 struct iovec *outvec = NULL;
768 int count = req->out.vector_count;
769 int i;
771 newreq = smbd_smb2_request_allocate(req->sconn);
772 if (!newreq) {
773 return NULL;
776 newreq->sconn = req->sconn;
777 newreq->session = req->session;
778 newreq->do_signing = req->do_signing;
779 newreq->current_idx = req->current_idx;
781 outvec = talloc_zero_array(newreq, struct iovec, count);
782 if (!outvec) {
783 TALLOC_FREE(newreq);
784 return NULL;
786 newreq->out.vector = outvec;
787 newreq->out.vector_count = count;
789 /* Setup the outvec's identically to req. */
790 outvec[0].iov_base = newreq->out.nbt_hdr;
791 outvec[0].iov_len = 4;
792 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
794 /* Setup the vectors identically to the ones in req. */
795 for (i = 1; i < count; i += 3) {
796 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
797 break;
801 if (i < count) {
802 /* Alloc failed. */
803 TALLOC_FREE(newreq);
804 return NULL;
807 smb2_setup_nbt_length(newreq->out.vector,
808 newreq->out.vector_count);
810 return newreq;
813 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
815 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
817 int i = 0;
818 uint8_t *outhdr = NULL;
819 struct smbd_smb2_request *nreq = NULL;
821 /* Create a new smb2 request we'll use
822 for the interim return. */
823 nreq = dup_smb2_req(req);
824 if (!nreq) {
825 return NT_STATUS_NO_MEMORY;
828 /* Lose the last 3 out vectors. They're the
829 ones we'll be using for the async reply. */
830 nreq->out.vector_count -= 3;
832 smb2_setup_nbt_length(nreq->out.vector,
833 nreq->out.vector_count);
835 /* Step back to the previous reply. */
836 i = nreq->current_idx - 3;
837 outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
838 /* And end the chain. */
839 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
841 /* Calculate outgoing credits */
842 smb2_calculate_credits(req, nreq);
844 /* Re-sign if needed. */
845 if (nreq->do_signing) {
846 NTSTATUS status;
847 struct smbXsrv_session *x = nreq->session;
848 struct smbXsrv_connection *conn = x->connection;
849 DATA_BLOB signing_key = x->global->channels[0].signing_key;
851 status = smb2_signing_sign_pdu(signing_key,
852 conn->protocol,
853 &nreq->out.vector[i], 3);
854 if (!NT_STATUS_IS_OK(status)) {
855 return status;
858 if (DEBUGLEVEL >= 10) {
859 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
860 (unsigned int)nreq->current_idx );
861 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
862 (unsigned int)nreq->out.vector_count );
863 print_req_vectors(nreq);
865 nreq->subreq = tstream_writev_queue_send(nreq,
866 nreq->sconn->ev_ctx,
867 nreq->sconn->smb2.stream,
868 nreq->sconn->smb2.send_queue,
869 nreq->out.vector,
870 nreq->out.vector_count);
872 if (nreq->subreq == NULL) {
873 return NT_STATUS_NO_MEMORY;
876 tevent_req_set_callback(nreq->subreq,
877 smbd_smb2_request_writev_done,
878 nreq);
880 return NT_STATUS_OK;
883 struct smbd_smb2_request_pending_state {
884 struct smbd_server_connection *sconn;
885 uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
886 struct iovec vector[3];
889 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
891 struct smbd_smb2_request_pending_state *state =
892 tevent_req_callback_data(subreq,
893 struct smbd_smb2_request_pending_state);
894 struct smbd_server_connection *sconn = state->sconn;
895 int ret;
896 int sys_errno;
898 ret = tstream_writev_queue_recv(subreq, &sys_errno);
899 TALLOC_FREE(subreq);
900 if (ret == -1) {
901 NTSTATUS status = map_nt_error_from_unix(sys_errno);
902 smbd_server_connection_terminate(sconn, nt_errstr(status));
903 return;
906 TALLOC_FREE(state);
909 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
910 struct tevent_timer *te,
911 struct timeval current_time,
912 void *private_data);
914 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
915 struct tevent_req *subreq,
916 uint32_t defer_time)
918 NTSTATUS status;
919 int i = req->current_idx;
920 struct timeval defer_endtime;
921 uint8_t *outhdr = NULL;
922 uint32_t flags;
924 if (!tevent_req_is_in_progress(subreq)) {
925 return NT_STATUS_OK;
928 req->subreq = subreq;
929 subreq = NULL;
931 if (req->async_te) {
932 /* We're already async. */
933 return NT_STATUS_OK;
936 outhdr = (uint8_t *)req->out.vector[i].iov_base;
937 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
938 if (flags & SMB2_HDR_FLAG_ASYNC) {
939 /* We're already async. */
940 return NT_STATUS_OK;
943 if (req->in.vector_count > i + 3) {
945 * We're trying to go async in a compound
946 * request chain. This is not allowed.
947 * Cancel the outstanding request.
949 tevent_req_cancel(req->subreq);
950 return smbd_smb2_request_error(req,
951 NT_STATUS_INSUFFICIENT_RESOURCES);
954 if (DEBUGLEVEL >= 10) {
955 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
956 (unsigned int)req->current_idx );
957 print_req_vectors(req);
960 if (req->out.vector_count > 4) {
961 struct iovec *outvec = NULL;
963 /* This is a compound reply. We
964 * must do an interim response
965 * followed by the async response
966 * to match W2K8R2.
968 status = smb2_send_async_interim_response(req);
969 if (!NT_STATUS_IS_OK(status)) {
970 return status;
974 * We're splitting off the last SMB2
975 * request in a compound set, and the
976 * smb2_send_async_interim_response()
977 * call above just sent all the replies
978 * for the previous SMB2 requests in
979 * this compound set. So we're no longer
980 * in the "compound_related_in_progress"
981 * state, and this is no longer a compound
982 * request.
984 req->compound_related = false;
985 req->sconn->smb2.compound_related_in_progress = false;
987 /* Re-arrange the in.vectors. */
988 req->in.vector[1] = req->in.vector[i];
989 req->in.vector[2] = req->in.vector[i+1];
990 req->in.vector[3] = req->in.vector[i+2];
991 req->in.vector_count = 4;
993 /* Reset the new in size. */
994 smb2_setup_nbt_length(req->in.vector, 4);
996 /* Now recreate the out.vectors. */
997 outvec = talloc_zero_array(req, struct iovec, 4);
998 if (!outvec) {
999 return NT_STATUS_NO_MEMORY;
1002 /* 0 is always boilerplate and must
1003 * be of size 4 for the length field. */
1005 outvec[0].iov_base = req->out.nbt_hdr;
1006 outvec[0].iov_len = 4;
1007 SIVAL(req->out.nbt_hdr, 0, 0);
1009 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
1010 return NT_STATUS_NO_MEMORY;
1013 TALLOC_FREE(req->out.vector);
1015 req->out.vector = outvec;
1017 req->current_idx = 1;
1018 req->out.vector_count = 4;
1020 outhdr = (uint8_t *)req->out.vector[1].iov_base;
1021 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1022 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1025 defer_endtime = timeval_current_ofs_usec(defer_time);
1026 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1027 req, defer_endtime,
1028 smbd_smb2_request_pending_timer,
1029 req);
1030 if (req->async_te == NULL) {
1031 return NT_STATUS_NO_MEMORY;
1034 return NT_STATUS_OK;
1037 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1038 struct tevent_timer *te,
1039 struct timeval current_time,
1040 void *private_data)
1042 struct smbd_smb2_request *req =
1043 talloc_get_type_abort(private_data,
1044 struct smbd_smb2_request);
1045 struct smbd_smb2_request_pending_state *state = NULL;
1046 int i = req->current_idx;
1047 uint8_t *outhdr = NULL;
1048 const uint8_t *inhdr = NULL;
1049 uint8_t *hdr = NULL;
1050 uint8_t *body = NULL;
1051 uint32_t flags = 0;
1052 uint64_t message_id = 0;
1053 uint64_t async_id = 0;
1054 struct tevent_req *subreq = NULL;
1056 TALLOC_FREE(req->async_te);
1058 /* Ensure our final reply matches the interim one. */
1059 inhdr = (const uint8_t *)req->in.vector[1].iov_base;
1060 outhdr = (uint8_t *)req->out.vector[1].iov_base;
1061 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1062 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1064 async_id = message_id; /* keep it simple for now... */
1066 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1067 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1069 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1070 "going async\n",
1071 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1072 (unsigned long long)async_id ));
1075 * What we send is identical to a smbd_smb2_request_error
1076 * packet with an error status of STATUS_PENDING. Make use
1077 * of this fact sometime when refactoring. JRA.
1080 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1081 if (state == NULL) {
1082 smbd_server_connection_terminate(req->sconn,
1083 nt_errstr(NT_STATUS_NO_MEMORY));
1084 return;
1086 state->sconn = req->sconn;
1088 state->vector[0].iov_base = (void *)state->buf;
1089 state->vector[0].iov_len = 4;
1091 state->vector[1].iov_base = state->buf + 4;
1092 state->vector[1].iov_len = SMB2_HDR_BODY;
1094 state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
1095 state->vector[2].iov_len = 9;
1097 smb2_setup_nbt_length(state->vector, 3);
1099 hdr = (uint8_t *)state->vector[1].iov_base;
1100 body = (uint8_t *)state->vector[2].iov_base;
1102 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1103 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1104 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1105 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1106 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1108 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1109 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1110 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1111 SBVAL(hdr, SMB2_HDR_PID, async_id);
1112 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1113 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1114 memcpy(hdr+SMB2_HDR_SIGNATURE,
1115 outhdr+SMB2_HDR_SIGNATURE, 16);
1117 SSVAL(body, 0x00, 0x08 + 1);
1119 SCVAL(body, 0x02, 0);
1120 SCVAL(body, 0x03, 0);
1121 SIVAL(body, 0x04, 0);
1122 /* Match W2K8R2... */
1123 SCVAL(body, 0x08, 0x21);
1125 /* Ensure we correctly go through crediting. Grant
1126 the credits now, and zero credits on the final
1127 response. */
1128 smb2_set_operation_credit(req->sconn,
1129 &req->in.vector[i],
1130 &state->vector[1]);
1132 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1134 if (req->do_signing) {
1135 NTSTATUS status;
1136 struct smbXsrv_session *x = req->session;
1137 struct smbXsrv_connection *conn = x->connection;
1138 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1140 status = smb2_signing_sign_pdu(signing_key,
1141 conn->protocol,
1142 &state->vector[1], 2);
1143 if (!NT_STATUS_IS_OK(status)) {
1144 smbd_server_connection_terminate(req->sconn,
1145 nt_errstr(status));
1146 return;
1150 subreq = tstream_writev_queue_send(state,
1151 state->sconn->ev_ctx,
1152 state->sconn->smb2.stream,
1153 state->sconn->smb2.send_queue,
1154 state->vector,
1156 if (subreq == NULL) {
1157 smbd_server_connection_terminate(state->sconn,
1158 nt_errstr(NT_STATUS_NO_MEMORY));
1159 return;
1161 tevent_req_set_callback(subreq,
1162 smbd_smb2_request_pending_writev_done,
1163 state);
1166 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1168 struct smbd_server_connection *sconn = req->sconn;
1169 struct smbd_smb2_request *cur;
1170 const uint8_t *inhdr;
1171 int i = req->current_idx;
1172 uint32_t flags;
1173 uint64_t search_message_id;
1174 uint64_t search_async_id;
1175 uint64_t found_id;
1177 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1179 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1180 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1181 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1184 * we don't need the request anymore
1185 * cancel requests never have a response
1187 DLIST_REMOVE(req->sconn->smb2.requests, req);
1188 TALLOC_FREE(req);
1190 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1191 const uint8_t *outhdr;
1192 uint64_t message_id;
1193 uint64_t async_id;
1195 i = cur->current_idx;
1197 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1199 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1200 async_id = BVAL(outhdr, SMB2_HDR_PID);
1202 if (flags & SMB2_HDR_FLAG_ASYNC) {
1203 if (search_async_id == async_id) {
1204 found_id = async_id;
1205 break;
1207 } else {
1208 if (search_message_id == message_id) {
1209 found_id = message_id;
1210 break;
1215 if (cur && cur->subreq) {
1216 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1217 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1218 "cancel opcode[%s] mid %llu\n",
1219 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1220 (unsigned long long)found_id ));
1221 tevent_req_cancel(cur->subreq);
1224 return NT_STATUS_OK;
1227 /*************************************************************
1228 Ensure an incoming tid is a valid one for us to access.
1229 Change to the associated uid credentials and chdir to the
1230 valid tid directory.
1231 *************************************************************/
1233 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1235 const uint8_t *inhdr;
1236 int i = req->current_idx;
1237 uint32_t in_flags;
1238 uint32_t in_tid;
1239 struct smbXsrv_tcon0 *tcon;
1240 NTSTATUS status;
1241 NTTIME now = timeval_to_nttime(&req->request_time);
1243 req->tcon = NULL;
1245 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1247 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1248 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1250 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1251 in_tid = req->last_tid;
1254 status = smb2srv_tcon_lookup(req->session,
1255 in_tid, now, &tcon);
1256 if (!NT_STATUS_IS_OK(status)) {
1257 return status;
1260 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1261 return NT_STATUS_ACCESS_DENIED;
1264 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1265 if (!set_current_service(tcon->compat, 0, true)) {
1266 return NT_STATUS_ACCESS_DENIED;
1269 req->tcon = tcon;
1270 req->last_tid = in_tid;
1272 return NT_STATUS_OK;
1275 /*************************************************************
1276 Ensure an incoming session_id is a valid one for us to access.
1277 *************************************************************/
1279 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1281 const uint8_t *inhdr;
1282 int i = req->current_idx;
1283 uint32_t in_flags;
1284 uint16_t in_opcode;
1285 uint64_t in_session_id;
1286 struct smbXsrv_session *session = NULL;
1287 struct auth_session_info *session_info;
1288 NTSTATUS status;
1289 NTTIME now = timeval_to_nttime(&req->request_time);
1291 req->session = NULL;
1292 req->tcon = NULL;
1294 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1296 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1297 in_opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1298 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1300 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1301 in_session_id = req->last_session_id;
1304 /* lookup an existing session */
1305 status = smb2srv_session_lookup(req->sconn->conn,
1306 in_session_id, now,
1307 &session);
1308 if (session) {
1309 req->session = session;
1310 req->last_session_id = in_session_id;
1312 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1313 switch (in_opcode) {
1314 case SMB2_OP_SESSSETUP:
1315 status = NT_STATUS_OK;
1316 break;
1317 default:
1318 break;
1321 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1322 switch (in_opcode) {
1323 case SMB2_OP_TCON:
1324 case SMB2_OP_CREATE:
1325 case SMB2_OP_GETINFO:
1326 case SMB2_OP_SETINFO:
1327 return NT_STATUS_INVALID_HANDLE;
1328 default:
1330 * Notice the check for
1331 * (session_info == NULL)
1332 * below.
1334 status = NT_STATUS_OK;
1335 break;
1338 if (!NT_STATUS_IS_OK(status)) {
1339 return status;
1342 session_info = session->global->auth_session_info;
1343 if (session_info == NULL) {
1344 return NT_STATUS_INVALID_HANDLE;
1347 set_current_user_info(session_info->unix_info->sanitized_username,
1348 session_info->unix_info->unix_name,
1349 session_info->info->domain_name);
1351 return NT_STATUS_OK;
1354 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1355 uint32_t data_length)
1357 uint16_t needed_charge;
1358 uint16_t credit_charge;
1359 const uint8_t *inhdr;
1360 int i = req->current_idx;
1362 if (!req->sconn->smb2.supports_multicredit) {
1363 if (data_length > 65536) {
1364 return NT_STATUS_INVALID_PARAMETER;
1366 return NT_STATUS_OK;
1369 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1370 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1372 /* requests larger than 64 KB need credit charge */
1373 if (credit_charge == 0 && data_length > 65536) {
1374 DEBUG(2, ("Request larger than 64KB w/o creditcharge\n"));
1375 return NT_STATUS_INVALID_PARAMETER;
1378 needed_charge = (data_length - 1)/ 65536 + 1;
1380 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1381 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1382 credit_charge, needed_charge));
1384 if (needed_charge > credit_charge) {
1385 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1386 credit_charge, needed_charge));
1387 return NT_STATUS_INVALID_PARAMETER;
1390 return NT_STATUS_OK;
1393 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1394 size_t expected_body_size)
1396 const uint8_t *inhdr;
1397 uint16_t opcode;
1398 const uint8_t *inbody;
1399 int i = req->current_idx;
1400 size_t body_size;
1401 size_t min_dyn_size = expected_body_size & 0x00000001;
1404 * The following should be checked already.
1406 if ((i+2) > req->in.vector_count) {
1407 return NT_STATUS_INTERNAL_ERROR;
1409 if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1410 return NT_STATUS_INTERNAL_ERROR;
1412 if (req->in.vector[i+1].iov_len < 2) {
1413 return NT_STATUS_INTERNAL_ERROR;
1416 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1417 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1419 switch (opcode) {
1420 case SMB2_OP_IOCTL:
1421 case SMB2_OP_GETINFO:
1422 min_dyn_size = 0;
1423 break;
1427 * Now check the expected body size,
1428 * where the last byte might be in the
1429 * dynamic section..
1431 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1432 return NT_STATUS_INVALID_PARAMETER;
1434 if (req->in.vector[i+2].iov_len < min_dyn_size) {
1435 return NT_STATUS_INVALID_PARAMETER;
1438 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1440 body_size = SVAL(inbody, 0x00);
1441 if (body_size != expected_body_size) {
1442 return NT_STATUS_INVALID_PARAMETER;
1445 return NT_STATUS_OK;
1448 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1450 const uint8_t *inhdr;
1451 int i = req->current_idx;
1452 uint16_t opcode;
1453 uint32_t flags;
1454 uint64_t mid;
1455 NTSTATUS status;
1456 NTSTATUS session_status;
1457 uint32_t allowed_flags;
1458 NTSTATUS return_value;
1459 struct smbXsrv_session *x = NULL;
1460 bool signing_required = false;
1462 inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1464 /* TODO: verify more things */
1466 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1467 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1468 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1469 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1470 smb2_opcode_name(opcode),
1471 (unsigned long long)mid));
1473 if (get_Protocol() >= PROTOCOL_SMB2_02) {
1475 * once the protocol is negotiated
1476 * SMB2_OP_NEGPROT is not allowed anymore
1478 if (opcode == SMB2_OP_NEGPROT) {
1479 /* drop the connection */
1480 return NT_STATUS_INVALID_PARAMETER;
1482 } else {
1484 * if the protocol is not negotiated yet
1485 * only SMB2_OP_NEGPROT is allowed.
1487 if (opcode != SMB2_OP_NEGPROT) {
1488 /* drop the connection */
1489 return NT_STATUS_INVALID_PARAMETER;
1493 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1494 SMB2_HDR_FLAG_SIGNED |
1495 SMB2_HDR_FLAG_DFS;
1496 if (opcode == SMB2_OP_CANCEL) {
1497 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1499 if ((flags & ~allowed_flags) != 0) {
1500 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1504 * Check if the client provided a valid session id,
1505 * if so smbd_smb2_request_check_session() calls
1506 * set_current_user_info().
1508 * As some command don't require a valid session id
1509 * we defer the check of the session_status
1511 session_status = smbd_smb2_request_check_session(req);
1512 x = req->session;
1514 if (x != NULL) {
1515 signing_required = x->global->signing_required;
1517 if (opcode == SMB2_OP_SESSSETUP &&
1518 x->global->channels[0].signing_key.length) {
1519 signing_required = true;
1523 req->do_signing = false;
1524 if (flags & SMB2_HDR_FLAG_SIGNED) {
1525 struct smbXsrv_connection *conn = x->connection;
1526 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1528 if (!NT_STATUS_IS_OK(session_status)) {
1529 return smbd_smb2_request_error(req, session_status);
1532 req->do_signing = true;
1533 status = smb2_signing_check_pdu(signing_key,
1534 conn->protocol,
1535 &req->in.vector[i], 3);
1536 if (!NT_STATUS_IS_OK(status)) {
1537 return smbd_smb2_request_error(req, status);
1539 } else if (opcode == SMB2_OP_CANCEL) {
1540 /* Cancel requests are allowed to skip the signing */
1541 } else if (signing_required) {
1542 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1545 if (flags & SMB2_HDR_FLAG_CHAINED) {
1547 * This check is mostly for giving the correct error code
1548 * for compounded requests.
1550 * TODO: we may need to move this after the session
1551 * and tcon checks.
1553 if (!NT_STATUS_IS_OK(req->next_status)) {
1554 return smbd_smb2_request_error(req, req->next_status);
1556 } else {
1557 req->compat_chain_fsp = NULL;
1560 if (req->compound_related) {
1561 req->sconn->smb2.compound_related_in_progress = true;
1564 switch (opcode) {
1565 case SMB2_OP_NEGPROT:
1566 /* This call needs to be run as root */
1567 change_to_root_user();
1570 START_PROFILE(smb2_negprot);
1571 return_value = smbd_smb2_request_process_negprot(req);
1572 END_PROFILE(smb2_negprot);
1574 break;
1576 case SMB2_OP_SESSSETUP:
1577 /* This call needs to be run as root */
1578 change_to_root_user();
1581 START_PROFILE(smb2_sesssetup);
1582 return_value = smbd_smb2_request_process_sesssetup(req);
1583 END_PROFILE(smb2_sesssetup);
1585 break;
1587 case SMB2_OP_LOGOFF:
1588 if (!NT_STATUS_IS_OK(session_status)) {
1589 return_value = smbd_smb2_request_error(req, session_status);
1590 break;
1593 /* This call needs to be run as root */
1594 change_to_root_user();
1597 START_PROFILE(smb2_logoff);
1598 return_value = smbd_smb2_request_process_logoff(req);
1599 END_PROFILE(smb2_logoff);
1601 break;
1603 case SMB2_OP_TCON:
1604 if (!NT_STATUS_IS_OK(session_status)) {
1605 return_value = smbd_smb2_request_error(req, session_status);
1606 break;
1610 * This call needs to be run as root.
1612 * smbd_smb2_request_process_tcon()
1613 * calls make_connection_snum(), which will call
1614 * change_to_user(), when needed.
1616 change_to_root_user();
1619 START_PROFILE(smb2_tcon);
1620 return_value = smbd_smb2_request_process_tcon(req);
1621 END_PROFILE(smb2_tcon);
1623 break;
1625 case SMB2_OP_TDIS:
1626 if (!NT_STATUS_IS_OK(session_status)) {
1627 return_value = smbd_smb2_request_error(req, session_status);
1628 break;
1631 * This call needs to be run as user.
1633 * smbd_smb2_request_check_tcon()
1634 * calls change_to_user() on success.
1636 status = smbd_smb2_request_check_tcon(req);
1637 if (!NT_STATUS_IS_OK(status)) {
1638 return_value = smbd_smb2_request_error(req, status);
1639 break;
1641 /* This call needs to be run as root */
1642 change_to_root_user();
1646 START_PROFILE(smb2_tdis);
1647 return_value = smbd_smb2_request_process_tdis(req);
1648 END_PROFILE(smb2_tdis);
1650 break;
1652 case SMB2_OP_CREATE:
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_create);
1671 return_value = smbd_smb2_request_process_create(req);
1672 END_PROFILE(smb2_create);
1674 break;
1676 case SMB2_OP_CLOSE:
1677 if (!NT_STATUS_IS_OK(session_status)) {
1678 return_value = smbd_smb2_request_error(req, session_status);
1679 break;
1682 * This call needs to be run as user.
1684 * smbd_smb2_request_check_tcon()
1685 * calls change_to_user() on success.
1687 status = smbd_smb2_request_check_tcon(req);
1688 if (!NT_STATUS_IS_OK(status)) {
1689 return_value = smbd_smb2_request_error(req, status);
1690 break;
1694 START_PROFILE(smb2_close);
1695 return_value = smbd_smb2_request_process_close(req);
1696 END_PROFILE(smb2_close);
1698 break;
1700 case SMB2_OP_FLUSH:
1701 if (!NT_STATUS_IS_OK(session_status)) {
1702 return_value = smbd_smb2_request_error(req, session_status);
1703 break;
1706 * This call needs to be run as user.
1708 * smbd_smb2_request_check_tcon()
1709 * calls change_to_user() on success.
1711 status = smbd_smb2_request_check_tcon(req);
1712 if (!NT_STATUS_IS_OK(status)) {
1713 return_value = smbd_smb2_request_error(req, status);
1714 break;
1718 START_PROFILE(smb2_flush);
1719 return_value = smbd_smb2_request_process_flush(req);
1720 END_PROFILE(smb2_flush);
1722 break;
1724 case SMB2_OP_READ:
1725 if (!NT_STATUS_IS_OK(session_status)) {
1726 return_value = smbd_smb2_request_error(req, session_status);
1727 break;
1730 * This call needs to be run as user.
1732 * smbd_smb2_request_check_tcon()
1733 * calls change_to_user() on success.
1735 status = smbd_smb2_request_check_tcon(req);
1736 if (!NT_STATUS_IS_OK(status)) {
1737 return_value = smbd_smb2_request_error(req, status);
1738 break;
1742 START_PROFILE(smb2_read);
1743 return_value = smbd_smb2_request_process_read(req);
1744 END_PROFILE(smb2_read);
1746 break;
1748 case SMB2_OP_WRITE:
1749 if (!NT_STATUS_IS_OK(session_status)) {
1750 return_value = smbd_smb2_request_error(req, session_status);
1751 break;
1754 * This call needs to be run as user.
1756 * smbd_smb2_request_check_tcon()
1757 * calls change_to_user() on success.
1759 status = smbd_smb2_request_check_tcon(req);
1760 if (!NT_STATUS_IS_OK(status)) {
1761 return_value = smbd_smb2_request_error(req, status);
1762 break;
1766 START_PROFILE(smb2_write);
1767 return_value = smbd_smb2_request_process_write(req);
1768 END_PROFILE(smb2_write);
1770 break;
1772 case SMB2_OP_LOCK:
1773 if (!NT_STATUS_IS_OK(session_status)) {
1774 /* Too ugly to live ? JRA. */
1775 if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1776 session_status = NT_STATUS_FILE_CLOSED;
1778 return_value = smbd_smb2_request_error(req, session_status);
1779 break;
1782 * This call needs to be run as user.
1784 * smbd_smb2_request_check_tcon()
1785 * calls change_to_user() on success.
1787 status = smbd_smb2_request_check_tcon(req);
1788 if (!NT_STATUS_IS_OK(status)) {
1789 /* Too ugly to live ? JRA. */
1790 if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1791 status = NT_STATUS_FILE_CLOSED;
1793 return_value = smbd_smb2_request_error(req, status);
1794 break;
1798 START_PROFILE(smb2_lock);
1799 return_value = smbd_smb2_request_process_lock(req);
1800 END_PROFILE(smb2_lock);
1802 break;
1804 case SMB2_OP_IOCTL:
1805 if (!NT_STATUS_IS_OK(session_status)) {
1806 return_value = smbd_smb2_request_error(req, session_status);
1807 break;
1810 * This call needs to be run as user.
1812 * smbd_smb2_request_check_tcon()
1813 * calls change_to_user() on success.
1815 status = smbd_smb2_request_check_tcon(req);
1816 if (!NT_STATUS_IS_OK(status)) {
1817 return_value = smbd_smb2_request_error(req, status);
1818 break;
1822 START_PROFILE(smb2_ioctl);
1823 return_value = smbd_smb2_request_process_ioctl(req);
1824 END_PROFILE(smb2_ioctl);
1826 break;
1828 case SMB2_OP_CANCEL:
1830 * This call needs to be run as root
1832 * That is what we also do in the SMB1 case.
1834 change_to_root_user();
1837 START_PROFILE(smb2_cancel);
1838 return_value = smbd_smb2_request_process_cancel(req);
1839 END_PROFILE(smb2_cancel);
1841 break;
1843 case SMB2_OP_KEEPALIVE:
1844 /* This call needs to be run as root */
1845 change_to_root_user();
1848 START_PROFILE(smb2_keepalive);
1849 return_value = smbd_smb2_request_process_keepalive(req);
1850 END_PROFILE(smb2_keepalive);
1852 break;
1854 case SMB2_OP_FIND:
1855 if (!NT_STATUS_IS_OK(session_status)) {
1856 return_value = smbd_smb2_request_error(req, session_status);
1857 break;
1860 * This call needs to be run as user.
1862 * smbd_smb2_request_check_tcon()
1863 * calls change_to_user() on success.
1865 status = smbd_smb2_request_check_tcon(req);
1866 if (!NT_STATUS_IS_OK(status)) {
1867 return_value = smbd_smb2_request_error(req, status);
1868 break;
1872 START_PROFILE(smb2_find);
1873 return_value = smbd_smb2_request_process_find(req);
1874 END_PROFILE(smb2_find);
1876 break;
1878 case SMB2_OP_NOTIFY:
1879 if (!NT_STATUS_IS_OK(session_status)) {
1880 return_value = smbd_smb2_request_error(req, session_status);
1881 break;
1884 * This call needs to be run as user.
1886 * smbd_smb2_request_check_tcon()
1887 * calls change_to_user() on success.
1889 status = smbd_smb2_request_check_tcon(req);
1890 if (!NT_STATUS_IS_OK(status)) {
1891 return_value = smbd_smb2_request_error(req, status);
1892 break;
1896 START_PROFILE(smb2_notify);
1897 return_value = smbd_smb2_request_process_notify(req);
1898 END_PROFILE(smb2_notify);
1900 break;
1902 case SMB2_OP_GETINFO:
1903 if (!NT_STATUS_IS_OK(session_status)) {
1904 return_value = smbd_smb2_request_error(req, session_status);
1905 break;
1908 * This call needs to be run as user.
1910 * smbd_smb2_request_check_tcon()
1911 * calls change_to_user() on success.
1913 status = smbd_smb2_request_check_tcon(req);
1914 if (!NT_STATUS_IS_OK(status)) {
1915 return_value = smbd_smb2_request_error(req, status);
1916 break;
1920 START_PROFILE(smb2_getinfo);
1921 return_value = smbd_smb2_request_process_getinfo(req);
1922 END_PROFILE(smb2_getinfo);
1924 break;
1926 case SMB2_OP_SETINFO:
1927 if (!NT_STATUS_IS_OK(session_status)) {
1928 return_value = smbd_smb2_request_error(req, session_status);
1929 break;
1932 * This call needs to be run as user.
1934 * smbd_smb2_request_check_tcon()
1935 * calls change_to_user() on success.
1937 status = smbd_smb2_request_check_tcon(req);
1938 if (!NT_STATUS_IS_OK(status)) {
1939 return_value = smbd_smb2_request_error(req, status);
1940 break;
1944 START_PROFILE(smb2_setinfo);
1945 return_value = smbd_smb2_request_process_setinfo(req);
1946 END_PROFILE(smb2_setinfo);
1948 break;
1950 case SMB2_OP_BREAK:
1951 if (!NT_STATUS_IS_OK(session_status)) {
1952 return_value = smbd_smb2_request_error(req, session_status);
1953 break;
1956 * This call needs to be run as user.
1958 * smbd_smb2_request_check_tcon()
1959 * calls change_to_user() on success.
1961 status = smbd_smb2_request_check_tcon(req);
1962 if (!NT_STATUS_IS_OK(status)) {
1963 return_value = smbd_smb2_request_error(req, status);
1964 break;
1968 START_PROFILE(smb2_break);
1969 return_value = smbd_smb2_request_process_break(req);
1970 END_PROFILE(smb2_break);
1972 break;
1974 default:
1975 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1976 break;
1978 return return_value;
1981 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1983 struct tevent_req *subreq;
1984 int i = req->current_idx;
1986 req->subreq = NULL;
1987 TALLOC_FREE(req->async_te);
1989 req->current_idx += 3;
1991 if (req->current_idx < req->out.vector_count) {
1993 * We must process the remaining compound
1994 * SMB2 requests before any new incoming SMB2
1995 * requests. This is because incoming SMB2
1996 * requests may include a cancel for a
1997 * compound request we haven't processed
1998 * yet.
2000 struct tevent_immediate *im = tevent_create_immediate(req);
2001 if (!im) {
2002 return NT_STATUS_NO_MEMORY;
2004 tevent_schedule_immediate(im,
2005 req->sconn->ev_ctx,
2006 smbd_smb2_request_dispatch_immediate,
2007 req);
2008 return NT_STATUS_OK;
2011 if (req->compound_related) {
2012 req->sconn->smb2.compound_related_in_progress = false;
2015 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2017 /* Set credit for these operations (zero credits if this
2018 is a final reply for an async operation). */
2019 smb2_calculate_credits(req, req);
2021 if (req->do_signing) {
2022 NTSTATUS status;
2023 struct smbXsrv_session *x = req->session;
2024 struct smbXsrv_connection *conn = x->connection;
2025 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2027 status = smb2_signing_sign_pdu(signing_key,
2028 conn->protocol,
2029 &req->out.vector[i], 3);
2030 if (!NT_STATUS_IS_OK(status)) {
2031 return status;
2035 if (DEBUGLEVEL >= 10) {
2036 dbgtext("smbd_smb2_request_reply: sending...\n");
2037 print_req_vectors(req);
2040 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2041 if (req->out.vector_count == 4 &&
2042 req->out.vector[3].iov_base == NULL &&
2043 req->out.vector[3].iov_len != 0) {
2044 /* Dynamic part is NULL. Chop it off,
2045 We're going to send it via sendfile. */
2046 req->out.vector_count -= 1;
2049 subreq = tstream_writev_queue_send(req,
2050 req->sconn->ev_ctx,
2051 req->sconn->smb2.stream,
2052 req->sconn->smb2.send_queue,
2053 req->out.vector,
2054 req->out.vector_count);
2055 if (subreq == NULL) {
2056 return NT_STATUS_NO_MEMORY;
2058 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
2060 * We're done with this request -
2061 * move it off the "being processed" queue.
2063 DLIST_REMOVE(req->sconn->smb2.requests, req);
2065 return NT_STATUS_OK;
2068 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2070 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2071 struct tevent_immediate *im,
2072 void *private_data)
2074 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2075 struct smbd_smb2_request);
2076 struct smbd_server_connection *sconn = req->sconn;
2077 NTSTATUS status;
2079 TALLOC_FREE(im);
2081 if (DEBUGLEVEL >= 10) {
2082 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2083 req->current_idx, req->in.vector_count));
2084 print_req_vectors(req);
2087 status = smbd_smb2_request_dispatch(req);
2088 if (!NT_STATUS_IS_OK(status)) {
2089 smbd_server_connection_terminate(sconn, nt_errstr(status));
2090 return;
2093 status = smbd_smb2_request_next_incoming(sconn);
2094 if (!NT_STATUS_IS_OK(status)) {
2095 smbd_server_connection_terminate(sconn, nt_errstr(status));
2096 return;
2100 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
2102 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
2103 struct smbd_smb2_request);
2104 struct smbd_server_connection *sconn = req->sconn;
2105 int ret;
2106 int sys_errno;
2107 NTSTATUS status;
2109 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2110 TALLOC_FREE(subreq);
2111 TALLOC_FREE(req);
2112 if (ret == -1) {
2113 status = map_nt_error_from_unix(sys_errno);
2114 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2115 nt_errstr(status)));
2116 smbd_server_connection_terminate(sconn, nt_errstr(status));
2117 return;
2120 status = smbd_smb2_request_next_incoming(sconn);
2121 if (!NT_STATUS_IS_OK(status)) {
2122 smbd_server_connection_terminate(sconn, nt_errstr(status));
2123 return;
2127 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2128 NTSTATUS status,
2129 DATA_BLOB body, DATA_BLOB *dyn,
2130 const char *location)
2132 uint8_t *outhdr;
2133 int i = req->current_idx;
2134 uint32_t next_command_ofs;
2136 DEBUG(10,("smbd_smb2_request_done_ex: "
2137 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2138 i, nt_errstr(status), (unsigned int)body.length,
2139 dyn ? "yes": "no",
2140 (unsigned int)(dyn ? dyn->length : 0),
2141 location));
2143 if (body.length < 2) {
2144 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2147 if ((body.length % 2) != 0) {
2148 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2151 outhdr = (uint8_t *)req->out.vector[i].iov_base;
2153 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2154 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2156 req->out.vector[i+1].iov_base = (void *)body.data;
2157 req->out.vector[i+1].iov_len = body.length;
2159 if (dyn) {
2160 req->out.vector[i+2].iov_base = (void *)dyn->data;
2161 req->out.vector[i+2].iov_len = dyn->length;
2162 } else {
2163 req->out.vector[i+2].iov_base = NULL;
2164 req->out.vector[i+2].iov_len = 0;
2167 /* see if we need to recalculate the offset to the next response */
2168 if (next_command_ofs > 0) {
2169 next_command_ofs = SMB2_HDR_BODY;
2170 next_command_ofs += req->out.vector[i+1].iov_len;
2171 next_command_ofs += req->out.vector[i+2].iov_len;
2174 if ((next_command_ofs % 8) != 0) {
2175 size_t pad_size = 8 - (next_command_ofs % 8);
2176 if (req->out.vector[i+2].iov_len == 0) {
2178 * if the dyn buffer is empty
2179 * we can use it to add padding
2181 uint8_t *pad;
2183 pad = talloc_zero_array(req->out.vector,
2184 uint8_t, pad_size);
2185 if (pad == NULL) {
2186 return smbd_smb2_request_error(req,
2187 NT_STATUS_NO_MEMORY);
2190 req->out.vector[i+2].iov_base = (void *)pad;
2191 req->out.vector[i+2].iov_len = pad_size;
2192 } else {
2194 * For now we copy the dynamic buffer
2195 * and add the padding to the new buffer
2197 size_t old_size;
2198 uint8_t *old_dyn;
2199 size_t new_size;
2200 uint8_t *new_dyn;
2202 old_size = req->out.vector[i+2].iov_len;
2203 old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2205 new_size = old_size + pad_size;
2206 new_dyn = talloc_zero_array(req->out.vector,
2207 uint8_t, new_size);
2208 if (new_dyn == NULL) {
2209 return smbd_smb2_request_error(req,
2210 NT_STATUS_NO_MEMORY);
2213 memcpy(new_dyn, old_dyn, old_size);
2214 memset(new_dyn + old_size, 0, pad_size);
2216 req->out.vector[i+2].iov_base = (void *)new_dyn;
2217 req->out.vector[i+2].iov_len = new_size;
2219 next_command_ofs += pad_size;
2222 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2224 return smbd_smb2_request_reply(req);
2227 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2228 NTSTATUS status,
2229 DATA_BLOB *info,
2230 const char *location)
2232 DATA_BLOB body;
2233 int i = req->current_idx;
2234 uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
2236 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2237 i, nt_errstr(status), info ? " +info" : "",
2238 location));
2240 body.data = outhdr + SMB2_HDR_BODY;
2241 body.length = 8;
2242 SSVAL(body.data, 0, 9);
2244 if (info) {
2245 SIVAL(body.data, 0x04, info->length);
2246 } else {
2247 /* Allocated size of req->out.vector[i].iov_base
2248 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2249 * 1 byte without having to do an alloc.
2251 info = talloc_zero_array(req->out.vector,
2252 DATA_BLOB,
2254 if (!info) {
2255 return NT_STATUS_NO_MEMORY;
2257 info->data = ((uint8_t *)outhdr) +
2258 OUTVEC_ALLOC_SIZE - 1;
2259 info->length = 1;
2260 SCVAL(info->data, 0, 0);
2264 * if a request fails, all other remaining
2265 * compounded requests should fail too
2267 req->next_status = NT_STATUS_INVALID_PARAMETER;
2269 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2273 struct smbd_smb2_send_oplock_break_state {
2274 struct smbd_server_connection *sconn;
2275 uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2276 struct iovec vector;
2279 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2281 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2282 uint64_t file_id_persistent,
2283 uint64_t file_id_volatile,
2284 uint8_t oplock_level)
2286 struct smbd_smb2_send_oplock_break_state *state;
2287 struct tevent_req *subreq;
2288 uint8_t *hdr;
2289 uint8_t *body;
2291 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2292 if (state == NULL) {
2293 return NT_STATUS_NO_MEMORY;
2295 state->sconn = sconn;
2297 state->vector.iov_base = (void *)state->buf;
2298 state->vector.iov_len = sizeof(state->buf);
2300 _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2301 hdr = state->buf + 4;
2302 body = hdr + SMB2_HDR_BODY;
2304 SIVAL(hdr, 0, SMB2_MAGIC);
2305 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2306 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2307 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2308 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2309 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2310 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2311 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2312 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2313 SIVAL(hdr, SMB2_HDR_PID, 0);
2314 SIVAL(hdr, SMB2_HDR_TID, 0);
2315 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2316 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2318 SSVAL(body, 0x00, 0x18);
2320 SCVAL(body, 0x02, oplock_level);
2321 SCVAL(body, 0x03, 0); /* reserved */
2322 SIVAL(body, 0x04, 0); /* reserved */
2323 SBVAL(body, 0x08, file_id_persistent);
2324 SBVAL(body, 0x10, file_id_volatile);
2326 subreq = tstream_writev_queue_send(state,
2327 sconn->ev_ctx,
2328 sconn->smb2.stream,
2329 sconn->smb2.send_queue,
2330 &state->vector, 1);
2331 if (subreq == NULL) {
2332 return NT_STATUS_NO_MEMORY;
2334 tevent_req_set_callback(subreq,
2335 smbd_smb2_oplock_break_writev_done,
2336 state);
2338 return NT_STATUS_OK;
2341 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2343 struct smbd_smb2_send_oplock_break_state *state =
2344 tevent_req_callback_data(subreq,
2345 struct smbd_smb2_send_oplock_break_state);
2346 struct smbd_server_connection *sconn = state->sconn;
2347 int ret;
2348 int sys_errno;
2350 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2351 TALLOC_FREE(subreq);
2352 if (ret == -1) {
2353 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2354 smbd_server_connection_terminate(sconn, nt_errstr(status));
2355 return;
2358 TALLOC_FREE(state);
2361 struct smbd_smb2_request_read_state {
2362 size_t missing;
2363 bool asked_for_header;
2364 struct smbd_smb2_request *smb2_req;
2367 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2368 void *private_data,
2369 TALLOC_CTX *mem_ctx,
2370 struct iovec **_vector,
2371 size_t *_count);
2372 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2374 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2375 struct tevent_context *ev,
2376 struct smbd_server_connection *sconn)
2378 struct tevent_req *req;
2379 struct smbd_smb2_request_read_state *state;
2380 struct tevent_req *subreq;
2382 req = tevent_req_create(mem_ctx, &state,
2383 struct smbd_smb2_request_read_state);
2384 if (req == NULL) {
2385 return NULL;
2387 state->missing = 0;
2388 state->asked_for_header = false;
2390 state->smb2_req = smbd_smb2_request_allocate(state);
2391 if (tevent_req_nomem(state->smb2_req, req)) {
2392 return tevent_req_post(req, ev);
2394 state->smb2_req->sconn = sconn;
2396 subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2397 sconn->smb2.recv_queue,
2398 smbd_smb2_request_next_vector,
2399 state);
2400 if (tevent_req_nomem(subreq, req)) {
2401 return tevent_req_post(req, ev);
2403 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2405 return req;
2408 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2409 void *private_data,
2410 TALLOC_CTX *mem_ctx,
2411 struct iovec **_vector,
2412 size_t *_count)
2414 struct smbd_smb2_request_read_state *state =
2415 talloc_get_type_abort(private_data,
2416 struct smbd_smb2_request_read_state);
2417 struct smbd_smb2_request *req = state->smb2_req;
2418 struct iovec *vector;
2419 int idx = req->in.vector_count;
2420 size_t len = 0;
2421 uint8_t *buf = NULL;
2423 if (req->in.vector_count == 0) {
2425 * first we need to get the NBT header
2427 req->in.vector = talloc_array(req, struct iovec,
2428 req->in.vector_count + 1);
2429 if (req->in.vector == NULL) {
2430 return -1;
2432 req->in.vector_count += 1;
2434 req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
2435 req->in.vector[idx].iov_len = 4;
2437 vector = talloc_array(mem_ctx, struct iovec, 1);
2438 if (vector == NULL) {
2439 return -1;
2442 vector[0] = req->in.vector[idx];
2444 *_vector = vector;
2445 *_count = 1;
2446 return 0;
2449 if (req->in.vector_count == 1) {
2451 * Now we analyze the NBT header
2453 state->missing = smb2_len(req->in.vector[0].iov_base);
2455 if (state->missing == 0) {
2456 /* if there're no remaining bytes, we're done */
2457 *_vector = NULL;
2458 *_count = 0;
2459 return 0;
2462 req->in.vector = talloc_realloc(req, req->in.vector,
2463 struct iovec,
2464 req->in.vector_count + 1);
2465 if (req->in.vector == NULL) {
2466 return -1;
2468 req->in.vector_count += 1;
2470 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2472 * it's a special NBT message,
2473 * so get all remaining bytes
2475 len = state->missing;
2476 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2478 * it's an invalid message, just read what we can get
2479 * and let the caller handle the error
2481 len = state->missing;
2482 } else {
2484 * We assume it's a SMB2 request,
2485 * and we first get the header and the
2486 * first 2 bytes (the struct size) of the body
2488 len = SMB2_HDR_BODY + 2;
2490 state->asked_for_header = true;
2493 state->missing -= len;
2495 buf = talloc_array(req->in.vector, uint8_t, len);
2496 if (buf == NULL) {
2497 return -1;
2500 req->in.vector[idx].iov_base = (void *)buf;
2501 req->in.vector[idx].iov_len = len;
2503 vector = talloc_array(mem_ctx, struct iovec, 1);
2504 if (vector == NULL) {
2505 return -1;
2508 vector[0] = req->in.vector[idx];
2510 *_vector = vector;
2511 *_count = 1;
2512 return 0;
2515 if (state->missing == 0) {
2516 /* if there're no remaining bytes, we're done */
2517 *_vector = NULL;
2518 *_count = 0;
2519 return 0;
2522 if (state->asked_for_header) {
2523 const uint8_t *hdr;
2524 size_t full_size;
2525 size_t next_command_ofs;
2526 size_t body_size;
2527 uint8_t *body;
2528 size_t dyn_size;
2529 uint8_t *dyn;
2530 bool invalid = false;
2532 state->asked_for_header = false;
2535 * We got the SMB2 header and the first 2 bytes
2536 * of the body. We fix the size to just the header
2537 * and manually copy the 2 first bytes to the body section
2539 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2540 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2542 /* allocate vectors for body and dynamic areas */
2543 req->in.vector = talloc_realloc(req, req->in.vector,
2544 struct iovec,
2545 req->in.vector_count + 2);
2546 if (req->in.vector == NULL) {
2547 return -1;
2549 req->in.vector_count += 2;
2551 full_size = state->missing + SMB2_HDR_BODY + 2;
2552 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2553 body_size = SVAL(hdr, SMB2_HDR_BODY);
2555 if (next_command_ofs != 0) {
2556 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2558 * this is invalid, just return a zero
2559 * body and let the caller deal with the error
2561 invalid = true;
2562 } else if (next_command_ofs > full_size) {
2564 * this is invalid, just return a zero
2565 * body and let the caller deal with the error
2567 invalid = true;
2568 } else {
2569 full_size = next_command_ofs;
2573 if (!invalid) {
2574 if (body_size < 2) {
2576 * this is invalid, just return a zero
2577 * body and let the caller deal with the error
2579 invalid = true;
2583 * Mask out the lowest bit, the "dynamic" part
2584 * of body_size.
2586 body_size &= ~1;
2588 if (body_size > (full_size - SMB2_HDR_BODY)) {
2590 * this is invalid, just return a zero
2591 * body and let the caller deal with the error
2593 invalid = true;
2597 if (invalid) {
2598 /* the caller should check this */
2599 body_size = 2;
2602 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2604 state->missing -= (body_size - 2) + dyn_size;
2606 body = talloc_array(req->in.vector, uint8_t, body_size);
2607 if (body == NULL) {
2608 return -1;
2611 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2612 if (dyn == NULL) {
2613 return -1;
2616 req->in.vector[idx].iov_base = (void *)body;
2617 req->in.vector[idx].iov_len = body_size;
2618 req->in.vector[idx+1].iov_base = (void *)dyn;
2619 req->in.vector[idx+1].iov_len = dyn_size;
2621 vector = talloc_array(mem_ctx, struct iovec, 2);
2622 if (vector == NULL) {
2623 return -1;
2627 * the first 2 bytes of the body were already fetched
2628 * together with the header
2630 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2631 vector[0].iov_base = body + 2;
2632 vector[0].iov_len = body_size - 2;
2634 vector[1] = req->in.vector[idx+1];
2636 *_vector = vector;
2637 *_count = 2;
2638 return 0;
2642 * when we endup here, we're looking for a new SMB2 request
2643 * next. And we ask for its header and the first 2 bytes of
2644 * the body (like we did for the first SMB2 request).
2647 req->in.vector = talloc_realloc(req, req->in.vector,
2648 struct iovec,
2649 req->in.vector_count + 1);
2650 if (req->in.vector == NULL) {
2651 return -1;
2653 req->in.vector_count += 1;
2656 * We assume it's a SMB2 request,
2657 * and we first get the header and the
2658 * first 2 bytes (the struct size) of the body
2660 len = SMB2_HDR_BODY + 2;
2662 if (len > state->missing) {
2663 /* let the caller handle the error */
2664 len = state->missing;
2667 state->missing -= len;
2668 state->asked_for_header = true;
2670 buf = talloc_array(req->in.vector, uint8_t, len);
2671 if (buf == NULL) {
2672 return -1;
2675 req->in.vector[idx].iov_base = (void *)buf;
2676 req->in.vector[idx].iov_len = len;
2678 vector = talloc_array(mem_ctx, struct iovec, 1);
2679 if (vector == NULL) {
2680 return -1;
2683 vector[0] = req->in.vector[idx];
2685 *_vector = vector;
2686 *_count = 1;
2687 return 0;
2690 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2692 struct tevent_req *req =
2693 tevent_req_callback_data(subreq,
2694 struct tevent_req);
2695 int ret;
2696 int sys_errno;
2697 NTSTATUS status;
2699 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2700 if (ret == -1) {
2701 status = map_nt_error_from_unix(sys_errno);
2702 tevent_req_nterror(req, status);
2703 return;
2706 tevent_req_done(req);
2709 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2710 TALLOC_CTX *mem_ctx,
2711 struct smbd_smb2_request **_smb2_req)
2713 struct smbd_smb2_request_read_state *state =
2714 tevent_req_data(req,
2715 struct smbd_smb2_request_read_state);
2716 NTSTATUS status;
2718 if (tevent_req_is_nterror(req, &status)) {
2719 tevent_req_received(req);
2720 return status;
2723 talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2724 *_smb2_req = state->smb2_req;
2725 tevent_req_received(req);
2726 return NT_STATUS_OK;
2729 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2731 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2733 size_t max_send_queue_len;
2734 size_t cur_send_queue_len;
2735 struct tevent_req *subreq;
2737 if (sconn->smb2.compound_related_in_progress) {
2739 * Can't read another until the related
2740 * compound is done.
2742 return NT_STATUS_OK;
2745 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2747 * if there is already a smbd_smb2_request_read
2748 * pending, we are done.
2750 return NT_STATUS_OK;
2753 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2754 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2756 if (cur_send_queue_len > max_send_queue_len) {
2758 * if we have a lot of requests to send,
2759 * we wait until they are on the wire until we
2760 * ask for the next request.
2762 return NT_STATUS_OK;
2765 /* ask for the next request */
2766 subreq = smbd_smb2_request_read_send(sconn, sconn->ev_ctx, sconn);
2767 if (subreq == NULL) {
2768 return NT_STATUS_NO_MEMORY;
2770 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2772 return NT_STATUS_OK;
2775 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2776 const uint8_t *inbuf, size_t size)
2778 NTSTATUS status;
2779 struct smbd_smb2_request *req = NULL;
2781 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2782 (unsigned int)size));
2784 status = smbd_initialize_smb2(sconn);
2785 if (!NT_STATUS_IS_OK(status)) {
2786 smbd_server_connection_terminate(sconn, nt_errstr(status));
2787 return;
2790 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2791 if (!NT_STATUS_IS_OK(status)) {
2792 smbd_server_connection_terminate(sconn, nt_errstr(status));
2793 return;
2796 status = smbd_smb2_request_validate(req);
2797 if (!NT_STATUS_IS_OK(status)) {
2798 smbd_server_connection_terminate(sconn, nt_errstr(status));
2799 return;
2802 status = smbd_smb2_request_setup_out(req);
2803 if (!NT_STATUS_IS_OK(status)) {
2804 smbd_server_connection_terminate(sconn, nt_errstr(status));
2805 return;
2808 status = smbd_smb2_request_dispatch(req);
2809 if (!NT_STATUS_IS_OK(status)) {
2810 smbd_server_connection_terminate(sconn, nt_errstr(status));
2811 return;
2814 status = smbd_smb2_request_next_incoming(sconn);
2815 if (!NT_STATUS_IS_OK(status)) {
2816 smbd_server_connection_terminate(sconn, nt_errstr(status));
2817 return;
2820 sconn->num_requests++;
2823 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2825 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2826 struct smbd_server_connection);
2827 NTSTATUS status;
2828 struct smbd_smb2_request *req = NULL;
2830 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2831 TALLOC_FREE(subreq);
2832 if (!NT_STATUS_IS_OK(status)) {
2833 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2834 nt_errstr(status)));
2835 smbd_server_connection_terminate(sconn, nt_errstr(status));
2836 return;
2839 if (req->in.nbt_hdr[0] != 0x00) {
2840 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2841 req->in.nbt_hdr[0]));
2842 TALLOC_FREE(req);
2843 goto next;
2846 req->current_idx = 1;
2848 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2849 req->current_idx, req->in.vector_count));
2851 status = smbd_smb2_request_validate(req);
2852 if (!NT_STATUS_IS_OK(status)) {
2853 smbd_server_connection_terminate(sconn, nt_errstr(status));
2854 return;
2857 status = smbd_smb2_request_setup_out(req);
2858 if (!NT_STATUS_IS_OK(status)) {
2859 smbd_server_connection_terminate(sconn, nt_errstr(status));
2860 return;
2863 status = smbd_smb2_request_dispatch(req);
2864 if (!NT_STATUS_IS_OK(status)) {
2865 smbd_server_connection_terminate(sconn, nt_errstr(status));
2866 return;
2869 next:
2870 status = smbd_smb2_request_next_incoming(sconn);
2871 if (!NT_STATUS_IS_OK(status)) {
2872 smbd_server_connection_terminate(sconn, nt_errstr(status));
2873 return;
2876 sconn->num_requests++;
2878 /* The timeout_processing function isn't run nearly
2879 often enough to implement 'max log size' without
2880 overrunning the size of the file by many megabytes.
2881 This is especially true if we are running at debug
2882 level 10. Checking every 50 SMB2s is a nice
2883 tradeoff of performance vs log file size overrun. */
2885 if ((sconn->num_requests % 50) == 0 &&
2886 need_to_check_log_size()) {
2887 change_to_root_user();
2888 check_log_size();