s3:smb2_server: do the req->next_status check before the signing checks
[Samba.git] / source3 / smbd / smb2_server.c
blobbf7f437bebde1efcc604b7b6ebc99a3853ffd249
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 struct smbd_smb2_dispatch_table {
36 uint16_t opcode;
37 const char *name;
38 bool need_session;
39 bool need_tcon;
40 bool as_root;
41 uint16_t fileid_ofs;
42 bool allow_invalid_fileid;
43 } smbd_smb2_table[] = {
44 #define _OP(o) .opcode = o, .name = #o
46 _OP(SMB2_OP_NEGPROT),
47 .as_root = true,
48 },{
49 _OP(SMB2_OP_SESSSETUP),
50 .as_root = true,
51 },{
52 _OP(SMB2_OP_LOGOFF),
53 .need_session = true,
54 .as_root = true,
55 },{
56 _OP(SMB2_OP_TCON),
57 .need_session = true,
59 * This call needs to be run as root.
61 * smbd_smb2_request_process_tcon()
62 * calls make_connection_snum(), which will call
63 * change_to_user(), when needed.
65 .as_root = true,
66 },{
67 _OP(SMB2_OP_TDIS),
68 .need_session = true,
69 .need_tcon = true,
70 .as_root = true,
71 },{
72 _OP(SMB2_OP_CREATE),
73 .need_session = true,
74 .need_tcon = true,
75 },{
76 _OP(SMB2_OP_CLOSE),
77 .need_session = true,
78 .need_tcon = true,
79 .fileid_ofs = 0x08,
80 },{
81 _OP(SMB2_OP_FLUSH),
82 .need_session = true,
83 .need_tcon = true,
84 .fileid_ofs = 0x08,
85 },{
86 _OP(SMB2_OP_READ),
87 .need_session = true,
88 .need_tcon = true,
89 .fileid_ofs = 0x10,
90 },{
91 _OP(SMB2_OP_WRITE),
92 .need_session = true,
93 .need_tcon = true,
94 .fileid_ofs = 0x10,
95 },{
96 _OP(SMB2_OP_LOCK),
97 .need_session = true,
98 .need_tcon = true,
99 .fileid_ofs = 0x08,
101 _OP(SMB2_OP_IOCTL),
102 .need_session = true,
103 .need_tcon = true,
104 .fileid_ofs = 0x08,
105 .allow_invalid_fileid = true,
107 _OP(SMB2_OP_CANCEL),
108 .as_root = true,
110 _OP(SMB2_OP_KEEPALIVE),
111 .as_root = true,
113 _OP(SMB2_OP_FIND),
114 .need_session = true,
115 .need_tcon = true,
116 .fileid_ofs = 0x08,
118 _OP(SMB2_OP_NOTIFY),
119 .need_session = true,
120 .need_tcon = true,
121 .fileid_ofs = 0x08,
123 _OP(SMB2_OP_GETINFO),
124 .need_session = true,
125 .need_tcon = true,
126 .fileid_ofs = 0x18,
128 _OP(SMB2_OP_SETINFO),
129 .need_session = true,
130 .need_tcon = true,
131 .fileid_ofs = 0x10,
133 _OP(SMB2_OP_BREAK),
134 .need_session = true,
135 .need_tcon = true,
137 * we do not set
138 * .fileid_ofs here
139 * as LEASE breaks does not
140 * have a file id
145 const char *smb2_opcode_name(uint16_t opcode)
147 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
148 return "Bad SMB2 opcode";
150 return smbd_smb2_table[opcode].name;
153 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
155 const struct smbd_smb2_dispatch_table *ret = NULL;
157 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
158 return NULL;
161 ret = &smbd_smb2_table[opcode];
163 SMB_ASSERT(ret->opcode == opcode);
165 return ret;
168 static void print_req_vectors(const struct smbd_smb2_request *req)
170 int i;
172 for (i = 0; i < req->in.vector_count; i++) {
173 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
174 (unsigned int)i,
175 (unsigned int)req->in.vector[i].iov_len);
177 for (i = 0; i < req->out.vector_count; i++) {
178 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
179 (unsigned int)i,
180 (unsigned int)req->out.vector[i].iov_len);
184 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
186 if (size < (4 + SMB2_HDR_BODY)) {
187 return false;
190 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
191 return false;
194 return true;
197 static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
199 NTSTATUS status;
200 int ret;
202 TALLOC_FREE(sconn->smb1.fde);
204 sconn->smb2.recv_queue = tevent_queue_create(sconn, "smb2 recv queue");
205 if (sconn->smb2.recv_queue == NULL) {
206 return NT_STATUS_NO_MEMORY;
209 sconn->smb2.send_queue = tevent_queue_create(sconn, "smb2 send queue");
210 if (sconn->smb2.send_queue == NULL) {
211 return NT_STATUS_NO_MEMORY;
214 sconn->smb2.seqnum_low = 0;
215 sconn->smb2.seqnum_range = 1;
216 sconn->smb2.credits_granted = 1;
217 sconn->smb2.max_credits = lp_smb2_max_credits();
218 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
219 sconn->smb2.max_credits);
220 if (sconn->smb2.credits_bitmap == NULL) {
221 return NT_STATUS_NO_MEMORY;
224 ret = tstream_bsd_existing_socket(sconn, sconn->sock,
225 &sconn->smb2.stream);
226 if (ret == -1) {
227 status = map_nt_error_from_unix(errno);
228 return status;
231 /* Ensure child is set to non-blocking mode */
232 set_blocking(sconn->sock, false);
233 return NT_STATUS_OK;
236 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
237 #define _smb2_setlen(_buf,len) do { \
238 uint8_t *buf = (uint8_t *)_buf; \
239 buf[0] = 0; \
240 buf[1] = ((len)&0xFF0000)>>16; \
241 buf[2] = ((len)&0xFF00)>>8; \
242 buf[3] = (len)&0xFF; \
243 } while (0)
245 static void smb2_setup_nbt_length(struct iovec *vector, int count)
247 size_t len = 0;
248 int i;
250 for (i=1; i < count; i++) {
251 len += vector[i].iov_len;
254 _smb2_setlen(vector[0].iov_base, len);
257 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
259 data_blob_clear_free(&req->first_key);
260 data_blob_clear_free(&req->last_key);
261 return 0;
264 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
266 TALLOC_CTX *mem_pool;
267 struct smbd_smb2_request *req;
269 #if 0
270 /* Enable this to find subtle valgrind errors. */
271 mem_pool = talloc_init("smbd_smb2_request_allocate");
272 #else
273 mem_pool = talloc_pool(mem_ctx, 8192);
274 #endif
275 if (mem_pool == NULL) {
276 return NULL;
279 req = talloc_zero(mem_pool, struct smbd_smb2_request);
280 if (req == NULL) {
281 talloc_free(mem_pool);
282 return NULL;
284 talloc_reparent(mem_pool, mem_ctx, req);
285 TALLOC_FREE(mem_pool);
287 req->last_session_id = UINT64_MAX;
288 req->last_tid = UINT32_MAX;
290 talloc_set_destructor(req, smbd_smb2_request_destructor);
292 return req;
295 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn,
296 NTTIME now,
297 uint8_t *buf,
298 size_t buflen,
299 TALLOC_CTX *mem_ctx,
300 struct iovec **piov,
301 int *pnum_iov)
303 struct iovec *iov;
304 int num_iov = 1;
305 size_t taken = 0;
306 uint8_t *first_hdr = buf;
307 size_t verified_buflen = 0;
308 uint8_t *tf = NULL;
309 size_t tf_len = 0;
312 * Note: index '0' is reserved for the transport protocol
314 iov = talloc_zero_array(mem_ctx, struct iovec, num_iov);
315 if (iov == NULL) {
316 return NT_STATUS_NO_MEMORY;
319 while (taken < buflen) {
320 size_t len = buflen - taken;
321 uint8_t *hdr = first_hdr + taken;
322 struct iovec *cur;
323 size_t full_size;
324 size_t next_command_ofs;
325 uint16_t body_size;
326 uint8_t *body = NULL;
327 uint32_t dyn_size;
328 uint8_t *dyn = NULL;
329 struct iovec *iov_tmp;
331 if (verified_buflen > taken) {
332 len = verified_buflen - taken;
333 } else {
334 tf = NULL;
335 tf_len = 0;
338 if (len < 4) {
339 DEBUG(10, ("%d bytes left, expected at least %d\n",
340 (int)len, 4));
341 goto inval;
343 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
344 struct smbXsrv_session *s = NULL;
345 uint64_t uid;
346 struct iovec tf_iov[2];
347 NTSTATUS status;
348 size_t enc_len;
350 if (conn->protocol < PROTOCOL_SMB2_24) {
351 DEBUG(10, ("Got SMB2_TRANSFORM header, "
352 "but dialect[0x%04X] is used\n",
353 conn->smb2.server.dialect));
354 goto inval;
357 if (!(conn->smb2.server.capabilities & SMB2_CAP_ENCRYPTION)) {
358 DEBUG(10, ("Got SMB2_TRANSFORM header, "
359 "but not negotiated "
360 "client[0x%08X] server[0x%08X]\n",
361 conn->smb2.client.capabilities,
362 conn->smb2.server.capabilities));
363 goto inval;
366 if (len < SMB2_TF_HDR_SIZE) {
367 DEBUG(1, ("%d bytes left, expected at least %d\n",
368 (int)len, SMB2_TF_HDR_SIZE));
369 goto inval;
371 tf = hdr;
372 tf_len = SMB2_TF_HDR_SIZE;
373 taken += tf_len;
375 hdr = first_hdr + taken;
376 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
377 uid = BVAL(tf, SMB2_TF_SESSION_ID);
379 if (len < SMB2_TF_HDR_SIZE + enc_len) {
380 DEBUG(1, ("%d bytes left, expected at least %d\n",
381 (int)len,
382 (int)(SMB2_TF_HDR_SIZE + enc_len)));
383 goto inval;
386 status = smb2srv_session_lookup(conn, uid, now, &s);
387 if (s == NULL) {
388 DEBUG(1, ("invalid session[%llu] in "
389 "SMB2_TRANSFORM header\n",
390 (unsigned long long)uid));
391 TALLOC_FREE(iov);
392 return NT_STATUS_USER_SESSION_DELETED;
395 tf_iov[0].iov_base = (void *)tf;
396 tf_iov[0].iov_len = tf_len;
397 tf_iov[1].iov_base = (void *)hdr;
398 tf_iov[1].iov_len = enc_len;
400 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
401 conn->protocol,
402 tf_iov, 2);
403 if (!NT_STATUS_IS_OK(status)) {
404 TALLOC_FREE(iov);
405 return status;
408 verified_buflen = taken + enc_len;
409 len = enc_len;
413 * We need the header plus the body length field
416 if (len < SMB2_HDR_BODY + 2) {
417 DEBUG(10, ("%d bytes left, expected at least %d\n",
418 (int)len, SMB2_HDR_BODY));
419 goto inval;
421 if (IVAL(hdr, 0) != SMB2_MAGIC) {
422 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
423 IVAL(hdr, 0)));
424 goto inval;
426 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
427 DEBUG(10, ("Got HDR len %d, expected %d\n",
428 SVAL(hdr, 4), SMB2_HDR_BODY));
429 goto inval;
432 full_size = len;
433 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
434 body_size = SVAL(hdr, SMB2_HDR_BODY);
436 if (next_command_ofs != 0) {
437 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
438 goto inval;
440 if (next_command_ofs > full_size) {
441 goto inval;
443 full_size = next_command_ofs;
445 if (body_size < 2) {
446 goto inval;
448 body_size &= 0xfffe;
450 if (body_size > (full_size - SMB2_HDR_BODY)) {
452 * let the caller handle the error
454 body_size = full_size - SMB2_HDR_BODY;
456 body = hdr + SMB2_HDR_BODY;
457 dyn = body + body_size;
458 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
460 iov_tmp = talloc_realloc(mem_ctx, iov, struct iovec,
461 num_iov + SMBD_SMB2_NUM_IOV_PER_REQ);
462 if (iov_tmp == NULL) {
463 TALLOC_FREE(iov);
464 return NT_STATUS_NO_MEMORY;
466 iov = iov_tmp;
467 cur = &iov[num_iov];
468 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
470 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
471 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
472 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
473 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
474 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
475 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
476 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
477 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
479 taken += full_size;
482 *piov = iov;
483 *pnum_iov = num_iov;
484 return NT_STATUS_OK;
486 inval:
487 TALLOC_FREE(iov);
488 return NT_STATUS_INVALID_PARAMETER;
491 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
492 uint8_t *inbuf, size_t size,
493 struct smbd_smb2_request **_req)
495 struct smbd_smb2_request *req;
496 uint32_t protocol_version;
497 const uint8_t *inhdr = NULL;
498 uint16_t cmd;
499 uint32_t next_command_ofs;
500 NTSTATUS status;
501 NTTIME now;
503 if (size < (4 + SMB2_HDR_BODY + 2)) {
504 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
505 return NT_STATUS_INVALID_PARAMETER;
508 inhdr = inbuf + 4;
510 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
511 if (protocol_version != SMB2_MAGIC) {
512 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
513 protocol_version));
514 return NT_STATUS_INVALID_PARAMETER;
517 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
518 if (cmd != SMB2_OP_NEGPROT) {
519 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
520 cmd));
521 return NT_STATUS_INVALID_PARAMETER;
524 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
525 if (next_command_ofs != 0) {
526 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
527 next_command_ofs));
528 return NT_STATUS_INVALID_PARAMETER;
531 req = smbd_smb2_request_allocate(sconn);
532 if (req == NULL) {
533 return NT_STATUS_NO_MEMORY;
535 req->sconn = sconn;
537 talloc_steal(req, inbuf);
539 req->request_time = timeval_current();
540 now = timeval_to_nttime(&req->request_time);
542 status = smbd_smb2_inbuf_parse_compound(sconn->conn,
543 now,
544 inbuf + NBT_HDR_SIZE,
545 size - NBT_HDR_SIZE,
546 req, &req->in.vector,
547 &req->in.vector_count);
548 if (!NT_STATUS_IS_OK(status)) {
549 TALLOC_FREE(req);
550 return status;
553 req->current_idx = 1;
555 *_req = req;
556 return NT_STATUS_OK;
559 static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
560 uint64_t message_id, uint64_t seq_id)
562 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
563 unsigned int offset;
565 if (seq_id < sconn->smb2.seqnum_low) {
566 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
567 "%llu (sequence id %llu) "
568 "(granted = %u, low = %llu, range = %u)\n",
569 (unsigned long long)message_id,
570 (unsigned long long)seq_id,
571 (unsigned int)sconn->smb2.credits_granted,
572 (unsigned long long)sconn->smb2.seqnum_low,
573 (unsigned int)sconn->smb2.seqnum_range));
574 return false;
577 if (seq_id >= sconn->smb2.seqnum_low + sconn->smb2.seqnum_range) {
578 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
579 "%llu (sequence id %llu) "
580 "(granted = %u, low = %llu, range = %u)\n",
581 (unsigned long long)message_id,
582 (unsigned long long)seq_id,
583 (unsigned int)sconn->smb2.credits_granted,
584 (unsigned long long)sconn->smb2.seqnum_low,
585 (unsigned int)sconn->smb2.seqnum_range));
586 return false;
589 offset = seq_id % sconn->smb2.max_credits;
591 if (bitmap_query(credits_bm, offset)) {
592 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
593 "%llu (sequence id %llu) "
594 "(granted = %u, low = %llu, range = %u) "
595 "(bm offset %u)\n",
596 (unsigned long long)message_id,
597 (unsigned long long)seq_id,
598 (unsigned int)sconn->smb2.credits_granted,
599 (unsigned long long)sconn->smb2.seqnum_low,
600 (unsigned int)sconn->smb2.seqnum_range,
601 offset));
602 return false;
605 /* Mark the message_ids as seen in the bitmap. */
606 bitmap_set(credits_bm, offset);
608 if (seq_id != sconn->smb2.seqnum_low) {
609 return true;
613 * Move the window forward by all the message_id's
614 * already seen.
616 while (bitmap_query(credits_bm, offset)) {
617 DEBUG(10,("smb2_validate_sequence_number: clearing "
618 "id %llu (position %u) from bitmap\n",
619 (unsigned long long)(sconn->smb2.seqnum_low),
620 offset));
621 bitmap_clear(credits_bm, offset);
623 sconn->smb2.seqnum_low += 1;
624 sconn->smb2.seqnum_range -= 1;
625 offset = sconn->smb2.seqnum_low % sconn->smb2.max_credits;
628 return true;
631 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
632 const uint8_t *inhdr)
634 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
635 uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
636 uint16_t credit_charge = 1;
637 uint64_t i;
639 if (opcode == SMB2_OP_CANCEL) {
640 /* SMB2_CANCEL requests by definition resend messageids. */
641 return true;
644 if (sconn->smb2.supports_multicredit) {
645 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
646 credit_charge = MAX(credit_charge, 1);
649 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
650 "credits_granted %llu, "
651 "seqnum low/range: %llu/%llu\n",
652 (unsigned long long) message_id,
653 (unsigned long long) credit_charge,
654 (unsigned long long) sconn->smb2.credits_granted,
655 (unsigned long long) sconn->smb2.seqnum_low,
656 (unsigned long long) sconn->smb2.seqnum_range));
658 if (sconn->smb2.credits_granted < credit_charge) {
659 DEBUG(0, ("smb2_validate_message_id: client used more "
660 "credits than granted, mid %llu, charge %llu, "
661 "credits_granted %llu, "
662 "seqnum low/range: %llu/%llu\n",
663 (unsigned long long) message_id,
664 (unsigned long long) credit_charge,
665 (unsigned long long) sconn->smb2.credits_granted,
666 (unsigned long long) sconn->smb2.seqnum_low,
667 (unsigned long long) sconn->smb2.seqnum_range));
668 return false;
672 * now check the message ids
674 * for multi-credit requests we need to check all current mid plus
675 * the implicit mids caused by the credit charge
676 * e.g. current mid = 15, charge 5 => mark 15-19 as used
679 for (i = 0; i <= (credit_charge-1); i++) {
680 uint64_t id = message_id + i;
681 bool ok;
683 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
684 (unsigned long long)message_id,
685 credit_charge,
686 (unsigned long long)id));
688 ok = smb2_validate_sequence_number(sconn, message_id, id);
689 if (!ok) {
690 return false;
694 /* substract used credits */
695 sconn->smb2.credits_granted -= credit_charge;
697 return true;
700 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
702 int count;
703 int idx;
705 count = req->in.vector_count;
707 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
708 /* It's not a SMB2 request */
709 return NT_STATUS_INVALID_PARAMETER;
712 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
713 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
714 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
715 const uint8_t *inhdr = NULL;
716 uint32_t flags;
718 if (hdr->iov_len != SMB2_HDR_BODY) {
719 return NT_STATUS_INVALID_PARAMETER;
722 if (body->iov_len < 2) {
723 return NT_STATUS_INVALID_PARAMETER;
726 inhdr = (const uint8_t *)hdr->iov_base;
728 /* Check the SMB2 header */
729 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
730 return NT_STATUS_INVALID_PARAMETER;
733 if (!smb2_validate_message_id(req->sconn, inhdr)) {
734 return NT_STATUS_INVALID_PARAMETER;
737 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
738 if (idx < SMBD_SMB2_NUM_IOV_PER_REQ) {
740 * the 1st request should never have the
741 * SMB2_HDR_FLAG_CHAINED flag set
743 if (flags & SMB2_HDR_FLAG_CHAINED) {
744 req->next_status = NT_STATUS_INVALID_PARAMETER;
745 return NT_STATUS_OK;
747 } else if (idx < 2*SMBD_SMB2_NUM_IOV_PER_REQ) {
749 * the 2nd request triggers related vs. unrelated
750 * compounded requests
752 if (flags & SMB2_HDR_FLAG_CHAINED) {
753 req->compound_related = true;
755 } else {
756 #if 0
758 * It seems the this tests are wrong
759 * see the SMB2-COMPOUND test
763 * all other requests should match the 2nd one
765 if (flags & SMB2_HDR_FLAG_CHAINED) {
766 if (!req->compound_related) {
767 req->next_status =
768 NT_STATUS_INVALID_PARAMETER;
769 return NT_STATUS_OK;
771 } else {
772 if (req->compound_related) {
773 req->next_status =
774 NT_STATUS_INVALID_PARAMETER;
775 return NT_STATUS_OK;
778 #endif
782 return NT_STATUS_OK;
785 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
786 const struct iovec *in_vector,
787 struct iovec *out_vector)
789 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
790 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
791 uint16_t credit_charge = 1;
792 uint16_t credits_requested;
793 uint32_t out_flags;
794 uint16_t cmd;
795 NTSTATUS out_status;
796 uint16_t credits_granted = 0;
797 uint64_t credits_possible;
798 uint16_t current_max_credits;
801 * first we grant only 1/16th of the max range.
803 * Windows also starts with the 1/16th and then grants
804 * more later. I was only able to trigger higher
805 * values, when using a verify high credit charge.
807 * TODO: scale up depending one load, free memory
808 * or other stuff.
809 * Maybe also on the relationship between number
810 * of requests and the used sequence number.
811 * Which means we would grant more credits
812 * for client which use multi credit requests.
814 current_max_credits = sconn->smb2.max_credits / 16;
815 current_max_credits = MAX(current_max_credits, 1);
817 if (sconn->smb2.supports_multicredit) {
818 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
819 credit_charge = MAX(credit_charge, 1);
822 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
823 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
824 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
825 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
827 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
828 SMB_ASSERT(sconn->smb2.max_credits >= credit_charge);
830 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
832 * In case we already send an async interim
833 * response, we should not grant
834 * credits on the final response.
836 credits_granted = 0;
837 } else if (credits_requested > 0) {
838 uint16_t additional_max = 0;
839 uint16_t additional_credits = credits_requested - 1;
841 switch (cmd) {
842 case SMB2_OP_NEGPROT:
843 break;
844 case SMB2_OP_SESSSETUP:
846 * Windows 2012 RC1 starts to grant
847 * additional credits
848 * with a successful session setup
850 if (NT_STATUS_IS_OK(out_status)) {
851 additional_max = 32;
853 break;
854 default:
856 * We match windows and only grant additional credits
857 * in chunks of 32.
859 additional_max = 32;
860 break;
863 additional_credits = MIN(additional_credits, additional_max);
865 credits_granted = credit_charge + additional_credits;
866 } else if (sconn->smb2.credits_granted == 0) {
868 * Make sure the client has always at least one credit
870 credits_granted = 1;
874 * sequence numbers should not wrap
876 * 1. calculate the possible credits until
877 * the sequence numbers start to wrap on 64-bit.
879 * 2. UINT64_MAX is used for Break Notifications.
881 * 2. truncate the possible credits to the maximum
882 * credits we want to grant to the client in total.
884 * 3. remove the range we'll already granted to the client
885 * this makes sure the client consumes the lowest sequence
886 * number, before we can grant additional credits.
888 credits_possible = UINT64_MAX - sconn->smb2.seqnum_low;
889 if (credits_possible > 0) {
890 /* remove UINT64_MAX */
891 credits_possible -= 1;
893 credits_possible = MIN(credits_possible, current_max_credits);
894 credits_possible -= sconn->smb2.seqnum_range;
896 credits_granted = MIN(credits_granted, credits_possible);
898 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
899 sconn->smb2.credits_granted += credits_granted;
900 sconn->smb2.seqnum_range += credits_granted;
902 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
903 "granted %u, current possible/max %u/%u, "
904 "total granted/max/low/range %u/%u/%llu/%u\n",
905 (unsigned int)credits_requested,
906 (unsigned int)credit_charge,
907 (unsigned int)credits_granted,
908 (unsigned int)credits_possible,
909 (unsigned int)current_max_credits,
910 (unsigned int)sconn->smb2.credits_granted,
911 (unsigned int)sconn->smb2.max_credits,
912 (unsigned long long)sconn->smb2.seqnum_low,
913 (unsigned int)sconn->smb2.seqnum_range));
916 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
917 struct smbd_smb2_request *outreq)
919 int count, idx;
920 uint16_t total_credits = 0;
922 count = outreq->out.vector_count;
924 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
925 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
926 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
927 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
929 smb2_set_operation_credit(outreq->sconn, inhdr_v, outhdr_v);
931 /* To match Windows, count up what we
932 just granted. */
933 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
934 /* Set to zero in all but the last reply. */
935 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
936 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
937 } else {
938 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
943 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
945 struct iovec *vector;
946 int count;
947 int idx;
949 count = req->in.vector_count;
950 vector = talloc_zero_array(req, struct iovec, count);
951 if (vector == NULL) {
952 return NT_STATUS_NO_MEMORY;
955 vector[0].iov_base = req->out.nbt_hdr;
956 vector[0].iov_len = 4;
957 SIVAL(req->out.nbt_hdr, 0, 0);
959 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
960 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
961 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
962 uint8_t *outhdr = NULL;
963 uint8_t *outbody = NULL;
964 uint32_t next_command_ofs = 0;
965 struct iovec *current = &vector[idx];
967 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
968 /* we have a next command -
969 * setup for the error case. */
970 next_command_ofs = SMB2_HDR_BODY + 9;
973 outhdr = talloc_zero_array(vector, uint8_t,
974 OUTVEC_ALLOC_SIZE);
975 if (outhdr == NULL) {
976 return NT_STATUS_NO_MEMORY;
979 outbody = outhdr + SMB2_HDR_BODY;
982 * SMBD_SMB2_TF_IOV_OFS might be used later
984 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
985 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
987 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
988 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
990 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
991 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
993 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
994 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
996 /* setup the SMB2 header */
997 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
998 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
999 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1000 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1001 SIVAL(outhdr, SMB2_HDR_STATUS,
1002 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1003 SSVAL(outhdr, SMB2_HDR_OPCODE,
1004 SVAL(inhdr, SMB2_HDR_OPCODE));
1005 SIVAL(outhdr, SMB2_HDR_FLAGS,
1006 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1007 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1008 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1009 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1010 SIVAL(outhdr, SMB2_HDR_PID,
1011 IVAL(inhdr, SMB2_HDR_PID));
1012 SIVAL(outhdr, SMB2_HDR_TID,
1013 IVAL(inhdr, SMB2_HDR_TID));
1014 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1015 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1016 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1017 inhdr + SMB2_HDR_SIGNATURE, 16);
1019 /* setup error body header */
1020 SSVAL(outbody, 0x00, 0x08 + 1);
1021 SSVAL(outbody, 0x02, 0);
1022 SIVAL(outbody, 0x04, 0);
1025 req->out.vector = vector;
1026 req->out.vector_count = count;
1028 /* setup the length of the NBT packet */
1029 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1031 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
1033 return NT_STATUS_OK;
1036 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
1037 const char *reason,
1038 const char *location)
1040 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1041 reason, location));
1042 exit_server_cleanly(reason);
1045 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1046 struct iovec *outvec,
1047 const struct iovec *srcvec)
1049 const uint8_t *srctf;
1050 size_t srctf_len;
1051 const uint8_t *srchdr;
1052 size_t srchdr_len;
1053 const uint8_t *srcbody;
1054 size_t srcbody_len;
1055 const uint8_t *expected_srcbody;
1056 const uint8_t *srcdyn;
1057 size_t srcdyn_len;
1058 const uint8_t *expected_srcdyn;
1059 uint8_t *dsttf;
1060 uint8_t *dsthdr;
1061 uint8_t *dstbody;
1062 uint8_t *dstdyn;
1064 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1065 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1066 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1067 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1068 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1069 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1070 expected_srcbody = srchdr + SMB2_HDR_BODY;
1071 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1072 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1073 expected_srcdyn = srcbody + 8;
1075 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1076 return false;
1079 if (srchdr_len != SMB2_HDR_BODY) {
1080 return false;
1083 if (srctf_len == SMB2_TF_HDR_SIZE) {
1084 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1085 if (dsttf == NULL) {
1086 return false;
1088 } else {
1089 dsttf = NULL;
1091 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1092 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1094 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1095 * be allocated with size OUTVEC_ALLOC_SIZE. */
1097 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1098 if (dsthdr == NULL) {
1099 return false;
1101 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1102 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1105 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1106 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1107 * then duplicate this. Else use talloc_memdup().
1110 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1111 dstbody = dsthdr + SMB2_HDR_BODY;
1112 } else {
1113 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1114 if (dstbody == NULL) {
1115 return false;
1118 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1119 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1122 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1123 * pointing to
1124 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1125 * then duplicate this. Else use talloc_memdup().
1128 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1129 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1130 } else if (srcdyn == NULL) {
1131 dstdyn = NULL;
1132 } else {
1133 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1134 if (dstdyn == NULL) {
1135 return false;
1138 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1139 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1141 return true;
1144 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1146 struct smbd_smb2_request *newreq = NULL;
1147 struct iovec *outvec = NULL;
1148 int count = req->out.vector_count;
1149 int i;
1151 newreq = smbd_smb2_request_allocate(req->sconn);
1152 if (!newreq) {
1153 return NULL;
1156 newreq->sconn = req->sconn;
1157 newreq->session = req->session;
1158 newreq->do_encryption = req->do_encryption;
1159 newreq->do_signing = req->do_signing;
1160 newreq->current_idx = req->current_idx;
1162 outvec = talloc_zero_array(newreq, struct iovec, count);
1163 if (!outvec) {
1164 TALLOC_FREE(newreq);
1165 return NULL;
1167 newreq->out.vector = outvec;
1168 newreq->out.vector_count = count;
1170 /* Setup the outvec's identically to req. */
1171 outvec[0].iov_base = newreq->out.nbt_hdr;
1172 outvec[0].iov_len = 4;
1173 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1175 /* Setup the vectors identically to the ones in req. */
1176 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1177 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1178 break;
1182 if (i < count) {
1183 /* Alloc failed. */
1184 TALLOC_FREE(newreq);
1185 return NULL;
1188 smb2_setup_nbt_length(newreq->out.vector,
1189 newreq->out.vector_count);
1191 return newreq;
1194 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
1196 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1198 struct smbXsrv_connection *conn = req->sconn->conn;
1199 int first_idx = 1;
1200 struct iovec *firsttf = NULL;
1201 struct iovec *outhdr_v = NULL;
1202 uint8_t *outhdr = NULL;
1203 struct smbd_smb2_request *nreq = NULL;
1204 NTSTATUS status;
1206 /* Create a new smb2 request we'll use
1207 for the interim return. */
1208 nreq = dup_smb2_req(req);
1209 if (!nreq) {
1210 return NT_STATUS_NO_MEMORY;
1213 /* Lose the last X out vectors. They're the
1214 ones we'll be using for the async reply. */
1215 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1217 smb2_setup_nbt_length(nreq->out.vector,
1218 nreq->out.vector_count);
1220 /* Step back to the previous reply. */
1221 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1222 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1223 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1224 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1225 /* And end the chain. */
1226 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1228 /* Calculate outgoing credits */
1229 smb2_calculate_credits(req, nreq);
1231 if (DEBUGLEVEL >= 10) {
1232 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1233 (unsigned int)nreq->current_idx );
1234 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1235 (unsigned int)nreq->out.vector_count );
1236 print_req_vectors(nreq);
1240 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1241 * we need to sign/encrypt here with the last/first key we remembered
1243 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1244 status = smb2_signing_encrypt_pdu(req->first_key,
1245 conn->protocol,
1246 firsttf,
1247 nreq->out.vector_count - first_idx);
1248 if (!NT_STATUS_IS_OK(status)) {
1249 return status;
1251 } else if (req->last_key.length > 0) {
1252 status = smb2_signing_sign_pdu(req->last_key,
1253 conn->protocol,
1254 outhdr_v,
1255 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1256 if (!NT_STATUS_IS_OK(status)) {
1257 return status;
1261 nreq->subreq = tstream_writev_queue_send(nreq,
1262 nreq->sconn->ev_ctx,
1263 nreq->sconn->smb2.stream,
1264 nreq->sconn->smb2.send_queue,
1265 nreq->out.vector,
1266 nreq->out.vector_count);
1268 if (nreq->subreq == NULL) {
1269 return NT_STATUS_NO_MEMORY;
1272 tevent_req_set_callback(nreq->subreq,
1273 smbd_smb2_request_writev_done,
1274 nreq);
1276 return NT_STATUS_OK;
1279 struct smbd_smb2_request_pending_state {
1280 struct smbd_server_connection *sconn;
1281 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1282 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1285 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
1287 struct smbd_smb2_request_pending_state *state =
1288 tevent_req_callback_data(subreq,
1289 struct smbd_smb2_request_pending_state);
1290 struct smbd_server_connection *sconn = state->sconn;
1291 int ret;
1292 int sys_errno;
1294 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1295 TALLOC_FREE(subreq);
1296 if (ret == -1) {
1297 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1298 smbd_server_connection_terminate(sconn, nt_errstr(status));
1299 return;
1302 TALLOC_FREE(state);
1305 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1306 struct tevent_timer *te,
1307 struct timeval current_time,
1308 void *private_data);
1310 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1311 struct tevent_req *subreq,
1312 uint32_t defer_time)
1314 NTSTATUS status;
1315 int idx = req->current_idx;
1316 struct timeval defer_endtime;
1317 uint8_t *outhdr = NULL;
1318 uint32_t flags;
1320 if (!tevent_req_is_in_progress(subreq)) {
1321 return NT_STATUS_OK;
1324 req->subreq = subreq;
1325 subreq = NULL;
1327 if (req->async_te) {
1328 /* We're already async. */
1329 return NT_STATUS_OK;
1332 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1333 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1334 if (flags & SMB2_HDR_FLAG_ASYNC) {
1335 /* We're already async. */
1336 return NT_STATUS_OK;
1339 if (req->in.vector_count > idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1341 * We're trying to go async in a compound
1342 * request chain. This is not allowed.
1343 * Cancel the outstanding request.
1345 tevent_req_cancel(req->subreq);
1346 return smbd_smb2_request_error(req,
1347 NT_STATUS_INSUFFICIENT_RESOURCES);
1350 if (DEBUGLEVEL >= 10) {
1351 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1352 (unsigned int)req->current_idx );
1353 print_req_vectors(req);
1356 if (req->out.vector_count >= (2*SMBD_SMB2_NUM_IOV_PER_REQ)) {
1358 * This is a compound reply. We
1359 * must do an interim response
1360 * followed by the async response
1361 * to match W2K8R2.
1363 status = smb2_send_async_interim_response(req);
1364 if (!NT_STATUS_IS_OK(status)) {
1365 return status;
1367 data_blob_clear_free(&req->first_key);
1370 * We're splitting off the last SMB2
1371 * request in a compound set, and the
1372 * smb2_send_async_interim_response()
1373 * call above just sent all the replies
1374 * for the previous SMB2 requests in
1375 * this compound set. So we're no longer
1376 * in the "compound_related_in_progress"
1377 * state, and this is no longer a compound
1378 * request.
1380 req->compound_related = false;
1381 req->sconn->smb2.compound_related_in_progress = false;
1383 req->current_idx = 1;
1385 /* Re-arrange the in.vectors. */
1386 memmove(&req->in.vector[req->current_idx],
1387 &req->in.vector[idx],
1388 sizeof(req->in.vector[0])*SMBD_SMB2_NUM_IOV_PER_REQ);
1389 req->in.vector_count = req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ;
1391 /* Re-arrange the out.vectors. */
1392 memmove(&req->out.vector[req->current_idx],
1393 &req->out.vector[idx],
1394 sizeof(req->out.vector[0])*SMBD_SMB2_NUM_IOV_PER_REQ);
1395 req->out.vector_count = req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ;
1397 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1398 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1399 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1401 data_blob_clear_free(&req->last_key);
1403 defer_endtime = timeval_current_ofs_usec(defer_time);
1404 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1405 req, defer_endtime,
1406 smbd_smb2_request_pending_timer,
1407 req);
1408 if (req->async_te == NULL) {
1409 return NT_STATUS_NO_MEMORY;
1412 return NT_STATUS_OK;
1415 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1416 struct tevent_timer *te,
1417 struct timeval current_time,
1418 void *private_data)
1420 struct smbd_smb2_request *req =
1421 talloc_get_type_abort(private_data,
1422 struct smbd_smb2_request);
1423 struct smbd_smb2_request_pending_state *state = NULL;
1424 uint8_t *outhdr = NULL;
1425 const uint8_t *inhdr = NULL;
1426 uint8_t *tf = NULL;
1427 size_t tf_len = 0;
1428 uint8_t *hdr = NULL;
1429 uint8_t *body = NULL;
1430 uint8_t *dyn = NULL;
1431 uint32_t flags = 0;
1432 uint64_t session_id = 0;
1433 uint64_t message_id = 0;
1434 uint64_t nonce_high = 0;
1435 uint64_t nonce_low = 0;
1436 uint64_t async_id = 0;
1437 struct tevent_req *subreq = NULL;
1439 TALLOC_FREE(req->async_te);
1441 /* Ensure our final reply matches the interim one. */
1442 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1443 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1444 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1445 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1446 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1448 async_id = message_id; /* keep it simple for now... */
1450 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1451 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1453 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1454 "going async\n",
1455 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1456 (unsigned long long)async_id ));
1459 * What we send is identical to a smbd_smb2_request_error
1460 * packet with an error status of STATUS_PENDING. Make use
1461 * of this fact sometime when refactoring. JRA.
1464 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1465 if (state == NULL) {
1466 smbd_server_connection_terminate(req->sconn,
1467 nt_errstr(NT_STATUS_NO_MEMORY));
1468 return;
1470 state->sconn = req->sconn;
1472 tf = state->buf + NBT_HDR_SIZE;
1473 tf_len = SMB2_TF_HDR_SIZE;
1475 hdr = tf + SMB2_TF_HDR_SIZE;
1476 body = hdr + SMB2_HDR_BODY;
1477 dyn = body + 8;
1479 if (req->do_encryption) {
1480 struct smbXsrv_session *x = req->session;
1482 nonce_high = x->nonce_high;
1483 nonce_low = x->nonce_low;
1485 x->nonce_low += 1;
1486 if (x->nonce_low == 0) {
1487 x->nonce_low += 1;
1488 x->nonce_high += 1;
1492 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1493 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1494 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1495 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1497 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1498 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1499 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1500 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1501 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1503 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1504 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1505 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1506 SBVAL(hdr, SMB2_HDR_PID, async_id);
1507 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1508 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1509 memcpy(hdr+SMB2_HDR_SIGNATURE,
1510 outhdr+SMB2_HDR_SIGNATURE, 16);
1512 SSVAL(body, 0x00, 0x08 + 1);
1514 SCVAL(body, 0x02, 0);
1515 SCVAL(body, 0x03, 0);
1516 SIVAL(body, 0x04, 0);
1517 /* Match W2K8R2... */
1518 SCVAL(dyn, 0x00, 0x21);
1520 state->vector[0].iov_base = (void *)state->buf;
1521 state->vector[0].iov_len = NBT_HDR_SIZE;
1523 if (req->do_encryption) {
1524 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1525 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1526 } else {
1527 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1528 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1531 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1532 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1534 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1535 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1537 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1538 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1540 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1542 /* Ensure we correctly go through crediting. Grant
1543 the credits now, and zero credits on the final
1544 response. */
1545 smb2_set_operation_credit(req->sconn,
1546 SMBD_SMB2_IN_HDR_IOV(req),
1547 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1549 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1551 if (DEBUGLVL(10)) {
1552 int i;
1554 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1555 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1556 (unsigned int)i,
1557 (unsigned int)ARRAY_SIZE(state->vector),
1558 (unsigned int)state->vector[i].iov_len);
1562 if (req->do_encryption) {
1563 NTSTATUS status;
1564 struct smbXsrv_session *x = req->session;
1565 struct smbXsrv_connection *conn = x->connection;
1566 DATA_BLOB encryption_key = x->global->encryption_key;
1568 status = smb2_signing_encrypt_pdu(encryption_key,
1569 conn->protocol,
1570 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1571 SMBD_SMB2_NUM_IOV_PER_REQ);
1572 if (!NT_STATUS_IS_OK(status)) {
1573 smbd_server_connection_terminate(req->sconn,
1574 nt_errstr(status));
1575 return;
1577 } else if (req->do_signing) {
1578 NTSTATUS status;
1579 struct smbXsrv_session *x = req->session;
1580 struct smbXsrv_connection *conn = x->connection;
1581 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1583 status = smb2_signing_sign_pdu(signing_key,
1584 conn->protocol,
1585 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1586 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1587 if (!NT_STATUS_IS_OK(status)) {
1588 smbd_server_connection_terminate(req->sconn,
1589 nt_errstr(status));
1590 return;
1594 subreq = tstream_writev_queue_send(state,
1595 state->sconn->ev_ctx,
1596 state->sconn->smb2.stream,
1597 state->sconn->smb2.send_queue,
1598 state->vector,
1599 ARRAY_SIZE(state->vector));
1600 if (subreq == NULL) {
1601 smbd_server_connection_terminate(state->sconn,
1602 nt_errstr(NT_STATUS_NO_MEMORY));
1603 return;
1605 tevent_req_set_callback(subreq,
1606 smbd_smb2_request_pending_writev_done,
1607 state);
1610 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1612 struct smbd_server_connection *sconn = req->sconn;
1613 struct smbd_smb2_request *cur;
1614 const uint8_t *inhdr;
1615 uint32_t flags;
1616 uint64_t search_message_id;
1617 uint64_t search_async_id;
1618 uint64_t found_id;
1620 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1622 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1623 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1624 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1627 * we don't need the request anymore
1628 * cancel requests never have a response
1630 DLIST_REMOVE(req->sconn->smb2.requests, req);
1631 TALLOC_FREE(req);
1633 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1634 const uint8_t *outhdr;
1635 uint64_t message_id;
1636 uint64_t async_id;
1638 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1640 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1641 async_id = BVAL(outhdr, SMB2_HDR_PID);
1643 if (flags & SMB2_HDR_FLAG_ASYNC) {
1644 if (search_async_id == async_id) {
1645 found_id = async_id;
1646 break;
1648 } else {
1649 if (search_message_id == message_id) {
1650 found_id = message_id;
1651 break;
1656 if (cur && cur->subreq) {
1657 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1658 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1659 "cancel opcode[%s] mid %llu\n",
1660 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1661 (unsigned long long)found_id ));
1662 tevent_req_cancel(cur->subreq);
1665 return NT_STATUS_OK;
1668 /*************************************************************
1669 Ensure an incoming tid is a valid one for us to access.
1670 Change to the associated uid credentials and chdir to the
1671 valid tid directory.
1672 *************************************************************/
1674 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1676 const uint8_t *inhdr;
1677 uint32_t in_flags;
1678 uint32_t in_tid;
1679 struct smbXsrv_tcon *tcon;
1680 NTSTATUS status;
1681 NTTIME now = timeval_to_nttime(&req->request_time);
1683 req->tcon = NULL;
1685 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1687 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1688 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1690 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1691 in_tid = req->last_tid;
1694 req->last_tid = 0;
1696 status = smb2srv_tcon_lookup(req->session,
1697 in_tid, now, &tcon);
1698 if (!NT_STATUS_IS_OK(status)) {
1699 return status;
1702 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1703 return NT_STATUS_ACCESS_DENIED;
1706 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1707 if (!set_current_service(tcon->compat, 0, true)) {
1708 return NT_STATUS_ACCESS_DENIED;
1711 req->tcon = tcon;
1712 req->last_tid = in_tid;
1714 return NT_STATUS_OK;
1717 /*************************************************************
1718 Ensure an incoming session_id is a valid one for us to access.
1719 *************************************************************/
1721 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1723 const uint8_t *inhdr;
1724 uint32_t in_flags;
1725 uint16_t in_opcode;
1726 uint64_t in_session_id;
1727 struct smbXsrv_session *session = NULL;
1728 struct auth_session_info *session_info;
1729 NTSTATUS status;
1730 NTTIME now = timeval_to_nttime(&req->request_time);
1732 req->session = NULL;
1733 req->tcon = NULL;
1735 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1737 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1738 in_opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1739 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1741 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1742 in_session_id = req->last_session_id;
1745 req->last_session_id = 0;
1747 /* lookup an existing session */
1748 status = smb2srv_session_lookup(req->sconn->conn,
1749 in_session_id, now,
1750 &session);
1751 if (session) {
1752 req->session = session;
1753 req->last_session_id = in_session_id;
1755 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1756 switch (in_opcode) {
1757 case SMB2_OP_SESSSETUP:
1758 status = NT_STATUS_OK;
1759 break;
1760 default:
1761 break;
1764 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1765 switch (in_opcode) {
1766 case SMB2_OP_TCON:
1767 case SMB2_OP_CREATE:
1768 case SMB2_OP_GETINFO:
1769 case SMB2_OP_SETINFO:
1770 return NT_STATUS_INVALID_HANDLE;
1771 default:
1773 * Notice the check for
1774 * (session_info == NULL)
1775 * below.
1777 status = NT_STATUS_OK;
1778 break;
1781 if (!NT_STATUS_IS_OK(status)) {
1782 return status;
1785 session_info = session->global->auth_session_info;
1786 if (session_info == NULL) {
1787 return NT_STATUS_INVALID_HANDLE;
1790 set_current_user_info(session_info->unix_info->sanitized_username,
1791 session_info->unix_info->unix_name,
1792 session_info->info->domain_name);
1794 return NT_STATUS_OK;
1797 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1798 uint32_t data_length)
1800 uint16_t needed_charge;
1801 uint16_t credit_charge = 1;
1802 const uint8_t *inhdr;
1804 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1806 if (req->sconn->smb2.supports_multicredit) {
1807 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1808 credit_charge = MAX(credit_charge, 1);
1811 needed_charge = (data_length - 1)/ 65536 + 1;
1813 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1814 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1815 credit_charge, needed_charge));
1817 if (needed_charge > credit_charge) {
1818 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1819 credit_charge, needed_charge));
1820 return NT_STATUS_INVALID_PARAMETER;
1823 return NT_STATUS_OK;
1826 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1827 size_t expected_body_size)
1829 struct iovec *inhdr_v;
1830 const uint8_t *inhdr;
1831 uint16_t opcode;
1832 const uint8_t *inbody;
1833 size_t body_size;
1834 size_t min_dyn_size = expected_body_size & 0x00000001;
1835 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1838 * The following should be checked already.
1840 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1841 return NT_STATUS_INTERNAL_ERROR;
1843 if (req->current_idx > max_idx) {
1844 return NT_STATUS_INTERNAL_ERROR;
1847 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1848 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1849 return NT_STATUS_INTERNAL_ERROR;
1851 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1852 return NT_STATUS_INTERNAL_ERROR;
1855 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1856 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1858 switch (opcode) {
1859 case SMB2_OP_IOCTL:
1860 case SMB2_OP_GETINFO:
1861 min_dyn_size = 0;
1862 break;
1866 * Now check the expected body size,
1867 * where the last byte might be in the
1868 * dynamic section..
1870 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1871 return NT_STATUS_INVALID_PARAMETER;
1873 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1874 return NT_STATUS_INVALID_PARAMETER;
1877 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1879 body_size = SVAL(inbody, 0x00);
1880 if (body_size != expected_body_size) {
1881 return NT_STATUS_INVALID_PARAMETER;
1884 return NT_STATUS_OK;
1887 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1889 struct smbXsrv_connection *conn = req->sconn->conn;
1890 const struct smbd_smb2_dispatch_table *call = NULL;
1891 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1892 const uint8_t *inhdr;
1893 uint16_t opcode;
1894 uint32_t flags;
1895 uint64_t mid;
1896 NTSTATUS status;
1897 NTSTATUS session_status;
1898 uint32_t allowed_flags;
1899 NTSTATUS return_value;
1900 struct smbXsrv_session *x = NULL;
1901 bool signing_required = false;
1902 bool encryption_required = false;
1904 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1906 /* TODO: verify more things */
1908 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1909 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1910 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1911 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1912 smb2_opcode_name(opcode),
1913 (unsigned long long)mid));
1915 if (conn->protocol >= PROTOCOL_SMB2_02) {
1917 * once the protocol is negotiated
1918 * SMB2_OP_NEGPROT is not allowed anymore
1920 if (opcode == SMB2_OP_NEGPROT) {
1921 /* drop the connection */
1922 return NT_STATUS_INVALID_PARAMETER;
1924 } else {
1926 * if the protocol is not negotiated yet
1927 * only SMB2_OP_NEGPROT is allowed.
1929 if (opcode != SMB2_OP_NEGPROT) {
1930 /* drop the connection */
1931 return NT_STATUS_INVALID_PARAMETER;
1936 * Check if the client provided a valid session id,
1937 * if so smbd_smb2_request_check_session() calls
1938 * set_current_user_info().
1940 * As some command don't require a valid session id
1941 * we defer the check of the session_status
1943 session_status = smbd_smb2_request_check_session(req);
1944 x = req->session;
1945 if (x != NULL) {
1946 signing_required = x->global->signing_required;
1947 encryption_required = x->global->encryption_required;
1949 if (opcode == SMB2_OP_SESSSETUP &&
1950 x->global->channels[0].signing_key.length) {
1951 signing_required = true;
1955 req->do_signing = false;
1956 req->do_encryption = false;
1957 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
1958 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
1959 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
1961 if (x != NULL && x->global->session_wire_id != tf_session_id) {
1962 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1963 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1964 (unsigned long long)x->global->session_wire_id,
1965 (unsigned long long)tf_session_id));
1967 * TODO: windows allows this...
1968 * should we drop the connection?
1970 * For now we just return ACCESS_DENIED
1971 * (Windows clients never trigger this)
1972 * and wait for an update of [MS-SMB2].
1974 return smbd_smb2_request_error(req,
1975 NT_STATUS_ACCESS_DENIED);
1978 req->do_encryption = true;
1981 if (encryption_required && !req->do_encryption) {
1982 return smbd_smb2_request_error(req,
1983 NT_STATUS_ACCESS_DENIED);
1986 call = smbd_smb2_call(opcode);
1987 if (call == NULL) {
1988 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1991 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1992 SMB2_HDR_FLAG_SIGNED |
1993 SMB2_HDR_FLAG_DFS;
1994 if (opcode == SMB2_OP_CANCEL) {
1995 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1997 if ((flags & ~allowed_flags) != 0) {
1998 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2001 if (flags & SMB2_HDR_FLAG_CHAINED) {
2003 * This check is mostly for giving the correct error code
2004 * for compounded requests.
2006 * TODO: we may need to move this after the session
2007 * and tcon checks.
2009 if (!NT_STATUS_IS_OK(req->next_status)) {
2010 return smbd_smb2_request_error(req, req->next_status);
2012 } else {
2013 req->compat_chain_fsp = NULL;
2016 if (req->do_encryption) {
2017 signing_required = false;
2018 } else if (flags & SMB2_HDR_FLAG_SIGNED) {
2019 DATA_BLOB signing_key;
2021 if (x == NULL) {
2022 return smbd_smb2_request_error(
2023 req, NT_STATUS_ACCESS_DENIED);
2026 signing_key = x->global->channels[0].signing_key;
2029 * If we have a signing key, we should
2030 * sign the response
2032 if (signing_key.length > 0) {
2033 req->do_signing = true;
2036 status = smb2_signing_check_pdu(signing_key,
2037 conn->protocol,
2038 SMBD_SMB2_IN_HDR_IOV(req),
2039 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2040 if (!NT_STATUS_IS_OK(status)) {
2041 return smbd_smb2_request_error(req, status);
2045 * Now that we know the request was correctly signed
2046 * we have to sign the response too.
2048 req->do_signing = true;
2050 if (!NT_STATUS_IS_OK(session_status)) {
2051 return smbd_smb2_request_error(req, session_status);
2053 } else if (opcode == SMB2_OP_CANCEL) {
2054 /* Cancel requests are allowed to skip the signing */
2055 } else if (signing_required) {
2057 * If signing is required we try to sign
2058 * a possible error response
2060 req->do_signing = true;
2061 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2064 if (req->compound_related) {
2065 req->sconn->smb2.compound_related_in_progress = true;
2068 if (call->need_session) {
2069 if (!NT_STATUS_IS_OK(session_status)) {
2070 return smbd_smb2_request_error(req, session_status);
2074 if (call->need_tcon) {
2075 SMB_ASSERT(call->need_session);
2078 * This call needs to be run as user.
2080 * smbd_smb2_request_check_tcon()
2081 * calls change_to_user() on success.
2083 status = smbd_smb2_request_check_tcon(req);
2084 if (!NT_STATUS_IS_OK(status)) {
2085 return smbd_smb2_request_error(req, status);
2087 if (req->tcon->global->encryption_required) {
2088 encryption_required = true;
2090 if (encryption_required && !req->do_encryption) {
2091 return smbd_smb2_request_error(req,
2092 NT_STATUS_ACCESS_DENIED);
2096 if (call->fileid_ofs != 0) {
2097 size_t needed = call->fileid_ofs + 16;
2098 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2099 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2100 uint64_t file_id_persistent;
2101 uint64_t file_id_volatile;
2102 struct files_struct *fsp;
2104 SMB_ASSERT(call->need_tcon);
2106 if (needed > body_size) {
2107 return smbd_smb2_request_error(req,
2108 NT_STATUS_INVALID_PARAMETER);
2111 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2112 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2114 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2115 if (fsp == NULL) {
2116 if (!call->allow_invalid_fileid) {
2117 return smbd_smb2_request_error(req,
2118 NT_STATUS_FILE_CLOSED);
2121 if (file_id_persistent != UINT64_MAX) {
2122 return smbd_smb2_request_error(req,
2123 NT_STATUS_FILE_CLOSED);
2125 if (file_id_volatile != UINT64_MAX) {
2126 return smbd_smb2_request_error(req,
2127 NT_STATUS_FILE_CLOSED);
2132 if (call->as_root) {
2133 SMB_ASSERT(call->fileid_ofs == 0);
2134 /* This call needs to be run as root */
2135 change_to_root_user();
2136 } else {
2137 SMB_ASSERT(call->need_tcon);
2140 switch (opcode) {
2141 case SMB2_OP_NEGPROT:
2143 START_PROFILE(smb2_negprot);
2144 return_value = smbd_smb2_request_process_negprot(req);
2145 END_PROFILE(smb2_negprot);
2147 break;
2149 case SMB2_OP_SESSSETUP:
2151 START_PROFILE(smb2_sesssetup);
2152 return_value = smbd_smb2_request_process_sesssetup(req);
2153 END_PROFILE(smb2_sesssetup);
2155 break;
2157 case SMB2_OP_LOGOFF:
2159 START_PROFILE(smb2_logoff);
2160 return_value = smbd_smb2_request_process_logoff(req);
2161 END_PROFILE(smb2_logoff);
2163 break;
2165 case SMB2_OP_TCON:
2167 START_PROFILE(smb2_tcon);
2168 return_value = smbd_smb2_request_process_tcon(req);
2169 END_PROFILE(smb2_tcon);
2171 break;
2173 case SMB2_OP_TDIS:
2175 START_PROFILE(smb2_tdis);
2176 return_value = smbd_smb2_request_process_tdis(req);
2177 END_PROFILE(smb2_tdis);
2179 break;
2181 case SMB2_OP_CREATE:
2183 START_PROFILE(smb2_create);
2184 return_value = smbd_smb2_request_process_create(req);
2185 END_PROFILE(smb2_create);
2187 break;
2189 case SMB2_OP_CLOSE:
2191 START_PROFILE(smb2_close);
2192 return_value = smbd_smb2_request_process_close(req);
2193 END_PROFILE(smb2_close);
2195 break;
2197 case SMB2_OP_FLUSH:
2199 START_PROFILE(smb2_flush);
2200 return_value = smbd_smb2_request_process_flush(req);
2201 END_PROFILE(smb2_flush);
2203 break;
2205 case SMB2_OP_READ:
2207 START_PROFILE(smb2_read);
2208 return_value = smbd_smb2_request_process_read(req);
2209 END_PROFILE(smb2_read);
2211 break;
2213 case SMB2_OP_WRITE:
2215 START_PROFILE(smb2_write);
2216 return_value = smbd_smb2_request_process_write(req);
2217 END_PROFILE(smb2_write);
2219 break;
2221 case SMB2_OP_LOCK:
2223 START_PROFILE(smb2_lock);
2224 return_value = smbd_smb2_request_process_lock(req);
2225 END_PROFILE(smb2_lock);
2227 break;
2229 case SMB2_OP_IOCTL:
2231 START_PROFILE(smb2_ioctl);
2232 return_value = smbd_smb2_request_process_ioctl(req);
2233 END_PROFILE(smb2_ioctl);
2235 break;
2237 case SMB2_OP_CANCEL:
2239 START_PROFILE(smb2_cancel);
2240 return_value = smbd_smb2_request_process_cancel(req);
2241 END_PROFILE(smb2_cancel);
2243 break;
2245 case SMB2_OP_KEEPALIVE:
2247 START_PROFILE(smb2_keepalive);
2248 return_value = smbd_smb2_request_process_keepalive(req);
2249 END_PROFILE(smb2_keepalive);
2251 break;
2253 case SMB2_OP_FIND:
2255 START_PROFILE(smb2_find);
2256 return_value = smbd_smb2_request_process_find(req);
2257 END_PROFILE(smb2_find);
2259 break;
2261 case SMB2_OP_NOTIFY:
2263 START_PROFILE(smb2_notify);
2264 return_value = smbd_smb2_request_process_notify(req);
2265 END_PROFILE(smb2_notify);
2267 break;
2269 case SMB2_OP_GETINFO:
2271 START_PROFILE(smb2_getinfo);
2272 return_value = smbd_smb2_request_process_getinfo(req);
2273 END_PROFILE(smb2_getinfo);
2275 break;
2277 case SMB2_OP_SETINFO:
2279 START_PROFILE(smb2_setinfo);
2280 return_value = smbd_smb2_request_process_setinfo(req);
2281 END_PROFILE(smb2_setinfo);
2283 break;
2285 case SMB2_OP_BREAK:
2287 START_PROFILE(smb2_break);
2288 return_value = smbd_smb2_request_process_break(req);
2289 END_PROFILE(smb2_break);
2291 break;
2293 default:
2294 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2295 break;
2297 return return_value;
2300 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2302 struct smbXsrv_connection *conn = req->sconn->conn;
2303 struct tevent_req *subreq;
2304 int first_idx = 1;
2305 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2306 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2307 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2309 req->subreq = NULL;
2310 TALLOC_FREE(req->async_te);
2312 if (req->do_encryption &&
2313 (firsttf->iov_len == 0) &&
2314 (req->first_key.length == 0) &&
2315 (req->session != NULL) &&
2316 (req->session->global->encryption_key.length != 0))
2318 DATA_BLOB encryption_key = req->session->global->encryption_key;
2319 uint8_t *tf;
2320 uint64_t session_id = req->session->global->session_wire_id;
2321 struct smbXsrv_session *x = req->session;
2322 uint64_t nonce_high;
2323 uint64_t nonce_low;
2325 nonce_high = x->nonce_high;
2326 nonce_low = x->nonce_low;
2328 x->nonce_low += 1;
2329 if (x->nonce_low == 0) {
2330 x->nonce_low += 1;
2331 x->nonce_high += 1;
2335 * We need to place the SMB2_TRANSFORM header before the
2336 * first SMB2 header
2340 * we need to remember the encryption key
2341 * and defer the signing/encryption until
2342 * we are sure that we do not change
2343 * the header again.
2345 req->first_key = data_blob_dup_talloc(req, encryption_key);
2346 if (req->first_key.data == NULL) {
2347 return NT_STATUS_NO_MEMORY;
2350 tf = talloc_zero_array(req->out.vector, uint8_t,
2351 SMB2_TF_HDR_SIZE);
2352 if (tf == NULL) {
2353 return NT_STATUS_NO_MEMORY;
2356 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2357 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2358 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2359 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2361 firsttf->iov_base = (void *)tf;
2362 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2365 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2366 (req->last_key.length > 0) &&
2367 (firsttf->iov_len == 0))
2369 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2370 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2371 NTSTATUS status;
2374 * As we are sure the header of the last request in the
2375 * compound chain will not change, we can to sign here
2376 * with the last signing key we remembered.
2378 status = smb2_signing_sign_pdu(req->last_key,
2379 conn->protocol,
2380 lasthdr,
2381 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2382 if (!NT_STATUS_IS_OK(status)) {
2383 return status;
2386 data_blob_clear_free(&req->last_key);
2388 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2390 if (req->current_idx < req->out.vector_count) {
2392 * We must process the remaining compound
2393 * SMB2 requests before any new incoming SMB2
2394 * requests. This is because incoming SMB2
2395 * requests may include a cancel for a
2396 * compound request we haven't processed
2397 * yet.
2399 struct tevent_immediate *im = tevent_create_immediate(req);
2400 if (!im) {
2401 return NT_STATUS_NO_MEMORY;
2404 if (req->do_signing && firsttf->iov_len == 0) {
2405 struct smbXsrv_session *x = req->session;
2406 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2409 * we need to remember the signing key
2410 * and defer the signing until
2411 * we are sure that we do not change
2412 * the header again.
2414 req->last_key = data_blob_dup_talloc(req, signing_key);
2415 if (req->last_key.data == NULL) {
2416 return NT_STATUS_NO_MEMORY;
2420 tevent_schedule_immediate(im,
2421 req->sconn->ev_ctx,
2422 smbd_smb2_request_dispatch_immediate,
2423 req);
2424 return NT_STATUS_OK;
2427 if (req->compound_related) {
2428 req->sconn->smb2.compound_related_in_progress = false;
2431 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2433 /* Set credit for these operations (zero credits if this
2434 is a final reply for an async operation). */
2435 smb2_calculate_credits(req, req);
2438 * now check if we need to sign the current response
2440 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2441 NTSTATUS status;
2443 status = smb2_signing_encrypt_pdu(req->first_key,
2444 conn->protocol,
2445 firsttf,
2446 req->out.vector_count - first_idx);
2447 if (!NT_STATUS_IS_OK(status)) {
2448 return status;
2450 } else if (req->do_signing) {
2451 NTSTATUS status;
2452 struct smbXsrv_session *x = req->session;
2453 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2455 status = smb2_signing_sign_pdu(signing_key,
2456 conn->protocol,
2457 outhdr,
2458 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2459 if (!NT_STATUS_IS_OK(status)) {
2460 return status;
2463 data_blob_clear_free(&req->first_key);
2465 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2466 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2467 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2468 /* Dynamic part is NULL. Chop it off,
2469 We're going to send it via sendfile. */
2470 req->out.vector_count -= 1;
2473 subreq = tstream_writev_queue_send(req,
2474 req->sconn->ev_ctx,
2475 req->sconn->smb2.stream,
2476 req->sconn->smb2.send_queue,
2477 req->out.vector,
2478 req->out.vector_count);
2479 if (subreq == NULL) {
2480 return NT_STATUS_NO_MEMORY;
2482 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
2484 * We're done with this request -
2485 * move it off the "being processed" queue.
2487 DLIST_REMOVE(req->sconn->smb2.requests, req);
2489 return NT_STATUS_OK;
2492 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2494 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2495 struct tevent_immediate *im,
2496 void *private_data)
2498 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2499 struct smbd_smb2_request);
2500 struct smbd_server_connection *sconn = req->sconn;
2501 NTSTATUS status;
2503 TALLOC_FREE(im);
2505 if (DEBUGLEVEL >= 10) {
2506 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2507 req->current_idx, req->in.vector_count));
2508 print_req_vectors(req);
2511 status = smbd_smb2_request_dispatch(req);
2512 if (!NT_STATUS_IS_OK(status)) {
2513 smbd_server_connection_terminate(sconn, nt_errstr(status));
2514 return;
2517 status = smbd_smb2_request_next_incoming(sconn);
2518 if (!NT_STATUS_IS_OK(status)) {
2519 smbd_server_connection_terminate(sconn, nt_errstr(status));
2520 return;
2524 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
2526 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
2527 struct smbd_smb2_request);
2528 struct smbd_server_connection *sconn = req->sconn;
2529 int ret;
2530 int sys_errno;
2531 NTSTATUS status;
2533 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2534 TALLOC_FREE(subreq);
2535 TALLOC_FREE(req);
2536 if (ret == -1) {
2537 status = map_nt_error_from_unix(sys_errno);
2538 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2539 nt_errstr(status)));
2540 smbd_server_connection_terminate(sconn, nt_errstr(status));
2541 return;
2544 status = smbd_smb2_request_next_incoming(sconn);
2545 if (!NT_STATUS_IS_OK(status)) {
2546 smbd_server_connection_terminate(sconn, nt_errstr(status));
2547 return;
2551 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2552 NTSTATUS status,
2553 DATA_BLOB body, DATA_BLOB *dyn,
2554 const char *location)
2556 uint8_t *outhdr;
2557 struct iovec *outbody_v;
2558 struct iovec *outdyn_v;
2559 uint32_t next_command_ofs;
2561 DEBUG(10,("smbd_smb2_request_done_ex: "
2562 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2563 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2564 dyn ? "yes": "no",
2565 (unsigned int)(dyn ? dyn->length : 0),
2566 location));
2568 if (body.length < 2) {
2569 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2572 if ((body.length % 2) != 0) {
2573 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2576 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2577 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2578 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2580 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2581 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2583 outbody_v->iov_base = (void *)body.data;
2584 outbody_v->iov_len = body.length;
2586 if (dyn) {
2587 outdyn_v->iov_base = (void *)dyn->data;
2588 outdyn_v->iov_len = dyn->length;
2589 } else {
2590 outdyn_v->iov_base = NULL;
2591 outdyn_v->iov_len = 0;
2594 /* see if we need to recalculate the offset to the next response */
2595 if (next_command_ofs > 0) {
2596 next_command_ofs = SMB2_HDR_BODY;
2597 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2598 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2601 if ((next_command_ofs % 8) != 0) {
2602 size_t pad_size = 8 - (next_command_ofs % 8);
2603 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2605 * if the dyn buffer is empty
2606 * we can use it to add padding
2608 uint8_t *pad;
2610 pad = talloc_zero_array(req->out.vector,
2611 uint8_t, pad_size);
2612 if (pad == NULL) {
2613 return smbd_smb2_request_error(req,
2614 NT_STATUS_NO_MEMORY);
2617 outdyn_v->iov_base = (void *)pad;
2618 outdyn_v->iov_len = pad_size;
2619 } else {
2621 * For now we copy the dynamic buffer
2622 * and add the padding to the new buffer
2624 size_t old_size;
2625 uint8_t *old_dyn;
2626 size_t new_size;
2627 uint8_t *new_dyn;
2629 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2630 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2632 new_size = old_size + pad_size;
2633 new_dyn = talloc_zero_array(req->out.vector,
2634 uint8_t, new_size);
2635 if (new_dyn == NULL) {
2636 return smbd_smb2_request_error(req,
2637 NT_STATUS_NO_MEMORY);
2640 memcpy(new_dyn, old_dyn, old_size);
2641 memset(new_dyn + old_size, 0, pad_size);
2643 outdyn_v->iov_base = (void *)new_dyn;
2644 outdyn_v->iov_len = new_size;
2646 next_command_ofs += pad_size;
2649 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2651 return smbd_smb2_request_reply(req);
2654 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2655 NTSTATUS status,
2656 DATA_BLOB *info,
2657 const char *location)
2659 DATA_BLOB body;
2660 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2662 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2663 req->current_idx, nt_errstr(status), info ? " +info" : "",
2664 location));
2666 body.data = outhdr + SMB2_HDR_BODY;
2667 body.length = 8;
2668 SSVAL(body.data, 0, 9);
2670 if (info) {
2671 SIVAL(body.data, 0x04, info->length);
2672 } else {
2673 /* Allocated size of req->out.vector[i].iov_base
2674 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2675 * 1 byte without having to do an alloc.
2677 info = talloc_zero_array(req->out.vector,
2678 DATA_BLOB,
2680 if (!info) {
2681 return NT_STATUS_NO_MEMORY;
2683 info->data = ((uint8_t *)outhdr) +
2684 OUTVEC_ALLOC_SIZE - 1;
2685 info->length = 1;
2686 SCVAL(info->data, 0, 0);
2690 * Note: Even if there is an error, continue to process the request.
2691 * per MS-SMB2.
2694 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2698 struct smbd_smb2_send_oplock_break_state {
2699 struct smbd_server_connection *sconn;
2700 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x18];
2701 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2704 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2706 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2707 struct smbXsrv_session *session,
2708 struct smbXsrv_tcon *tcon,
2709 struct smbXsrv_open *op,
2710 uint8_t oplock_level)
2712 struct smbd_smb2_send_oplock_break_state *state;
2713 struct smbXsrv_connection *conn = sconn->conn;
2714 struct tevent_req *subreq;
2715 uint8_t *tf;
2716 size_t tf_len;
2717 uint8_t *hdr;
2718 uint8_t *body;
2719 size_t body_len;
2720 uint8_t *dyn;
2721 size_t dyn_len;
2722 bool do_encryption = session->global->encryption_required;
2723 uint64_t nonce_high = 0;
2724 uint64_t nonce_low = 0;
2726 if (tcon->global->encryption_required) {
2727 do_encryption = true;
2730 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2731 if (state == NULL) {
2732 return NT_STATUS_NO_MEMORY;
2734 state->sconn = sconn;
2736 tf = state->buf + NBT_HDR_SIZE;
2737 tf_len = SMB2_TF_HDR_SIZE;
2738 hdr = tf + tf_len;
2739 body = hdr + SMB2_HDR_BODY;
2740 body_len = 0x18;
2741 dyn = body + body_len;
2742 dyn_len = 0;
2744 if (do_encryption) {
2745 nonce_high = session->nonce_high;
2746 nonce_low = session->nonce_low;
2748 session->nonce_low += 1;
2749 if (session->nonce_low == 0) {
2750 session->nonce_low += 1;
2751 session->nonce_high += 1;
2755 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2756 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2757 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2758 SBVAL(tf, SMB2_TF_SESSION_ID, session->global->session_wire_id);
2760 SIVAL(hdr, 0, SMB2_MAGIC);
2761 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2762 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2763 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2764 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2765 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2766 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2767 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2768 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2769 SIVAL(hdr, SMB2_HDR_PID, 0);
2770 SIVAL(hdr, SMB2_HDR_TID, 0);
2771 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2772 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2774 SSVAL(body, 0x00, body_len);
2776 SCVAL(body, 0x02, oplock_level);
2777 SCVAL(body, 0x03, 0); /* reserved */
2778 SIVAL(body, 0x04, 0); /* reserved */
2779 SBVAL(body, 0x08, op->global->open_persistent_id);
2780 SBVAL(body, 0x10, op->global->open_volatile_id);
2782 state->vector[0].iov_base = (void *)state->buf;
2783 state->vector[0].iov_len = NBT_HDR_SIZE;
2785 if (do_encryption) {
2786 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
2787 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
2788 } else {
2789 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
2790 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
2793 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
2794 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
2796 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
2797 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = body_len;
2799 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
2800 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_len;
2802 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2804 if (do_encryption) {
2805 NTSTATUS status;
2806 DATA_BLOB encryption_key = session->global->encryption_key;
2808 status = smb2_signing_encrypt_pdu(encryption_key,
2809 conn->protocol,
2810 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2811 SMBD_SMB2_NUM_IOV_PER_REQ);
2812 if (!NT_STATUS_IS_OK(status)) {
2813 return status;
2817 subreq = tstream_writev_queue_send(state,
2818 sconn->ev_ctx,
2819 sconn->smb2.stream,
2820 sconn->smb2.send_queue,
2821 state->vector,
2822 ARRAY_SIZE(state->vector));
2823 if (subreq == NULL) {
2824 return NT_STATUS_NO_MEMORY;
2826 tevent_req_set_callback(subreq,
2827 smbd_smb2_oplock_break_writev_done,
2828 state);
2830 return NT_STATUS_OK;
2833 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2835 struct smbd_smb2_send_oplock_break_state *state =
2836 tevent_req_callback_data(subreq,
2837 struct smbd_smb2_send_oplock_break_state);
2838 struct smbd_server_connection *sconn = state->sconn;
2839 int ret;
2840 int sys_errno;
2842 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2843 TALLOC_FREE(subreq);
2844 if (ret == -1) {
2845 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2846 smbd_server_connection_terminate(sconn, nt_errstr(status));
2847 return;
2850 TALLOC_FREE(state);
2853 struct smbd_smb2_request_read_state {
2854 struct tevent_context *ev;
2855 struct smbd_server_connection *sconn;
2856 struct smbd_smb2_request *smb2_req;
2857 struct {
2858 uint8_t nbt[NBT_HDR_SIZE];
2859 bool done;
2860 } hdr;
2861 size_t pktlen;
2862 uint8_t *pktbuf;
2865 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2866 void *private_data,
2867 TALLOC_CTX *mem_ctx,
2868 struct iovec **_vector,
2869 size_t *_count);
2870 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2872 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2873 struct tevent_context *ev,
2874 struct smbd_server_connection *sconn)
2876 struct tevent_req *req;
2877 struct smbd_smb2_request_read_state *state;
2878 struct tevent_req *subreq;
2880 req = tevent_req_create(mem_ctx, &state,
2881 struct smbd_smb2_request_read_state);
2882 if (req == NULL) {
2883 return NULL;
2885 state->ev = ev;
2886 state->sconn = sconn;
2888 state->smb2_req = smbd_smb2_request_allocate(state);
2889 if (tevent_req_nomem(state->smb2_req, req)) {
2890 return tevent_req_post(req, ev);
2892 state->smb2_req->sconn = sconn;
2894 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
2895 state->ev,
2896 state->sconn->smb2.stream,
2897 state->sconn->smb2.recv_queue,
2898 smbd_smb2_request_next_vector,
2899 state);
2900 if (tevent_req_nomem(subreq, req)) {
2901 return tevent_req_post(req, ev);
2903 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2905 return req;
2908 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2909 void *private_data,
2910 TALLOC_CTX *mem_ctx,
2911 struct iovec **_vector,
2912 size_t *_count)
2914 struct smbd_smb2_request_read_state *state =
2915 talloc_get_type_abort(private_data,
2916 struct smbd_smb2_request_read_state);
2917 struct iovec *vector;
2919 if (state->pktlen > 0) {
2920 /* if there're no remaining bytes, we're done */
2921 *_vector = NULL;
2922 *_count = 0;
2923 return 0;
2926 if (!state->hdr.done) {
2928 * first we need to get the NBT header
2930 vector = talloc_array(mem_ctx, struct iovec, 1);
2931 if (vector == NULL) {
2932 return -1;
2935 vector[0].iov_base = (void *)state->hdr.nbt;
2936 vector[0].iov_len = NBT_HDR_SIZE;
2938 *_vector = vector;
2939 *_count = 1;
2941 state->hdr.done = true;
2942 return 0;
2946 * Now we analyze the NBT header
2948 state->pktlen = smb2_len(state->hdr.nbt);
2950 if (state->pktlen == 0) {
2951 /* if there're no remaining bytes, we're done */
2952 *_vector = NULL;
2953 *_count = 0;
2954 return 0;
2957 state->pktbuf = talloc_array(state->smb2_req, uint8_t, state->pktlen);
2958 if (state->pktbuf == NULL) {
2959 return -1;
2962 vector = talloc_array(mem_ctx, struct iovec, 1);
2963 if (vector == NULL) {
2964 return -1;
2967 vector[0].iov_base = (void *)state->pktbuf;
2968 vector[0].iov_len = state->pktlen;
2970 *_vector = vector;
2971 *_count = 1;
2972 return 0;
2975 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2977 struct tevent_req *req =
2978 tevent_req_callback_data(subreq,
2979 struct tevent_req);
2980 struct smbd_smb2_request_read_state *state =
2981 tevent_req_data(req,
2982 struct smbd_smb2_request_read_state);
2983 int ret;
2984 int sys_errno;
2985 NTSTATUS status;
2986 NTTIME now;
2988 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2989 TALLOC_FREE(subreq);
2990 if (ret == -1) {
2991 status = map_nt_error_from_unix(sys_errno);
2992 tevent_req_nterror(req, status);
2993 return;
2996 if (state->hdr.nbt[0] != 0x00) {
2997 DEBUG(1,("smbd_smb2_request_read_done: ignore NBT[0x%02X] msg\n",
2998 state->hdr.nbt[0]));
3000 ZERO_STRUCT(state->hdr);
3001 TALLOC_FREE(state->pktbuf);
3002 state->pktlen = 0;
3004 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
3005 state->ev,
3006 state->sconn->smb2.stream,
3007 state->sconn->smb2.recv_queue,
3008 smbd_smb2_request_next_vector,
3009 state);
3010 if (tevent_req_nomem(subreq, req)) {
3011 return;
3013 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
3014 return;
3017 state->smb2_req->request_time = timeval_current();
3018 now = timeval_to_nttime(&state->smb2_req->request_time);
3020 status = smbd_smb2_inbuf_parse_compound(state->smb2_req->sconn->conn,
3021 now,
3022 state->pktbuf,
3023 state->pktlen,
3024 state->smb2_req,
3025 &state->smb2_req->in.vector,
3026 &state->smb2_req->in.vector_count);
3027 if (tevent_req_nterror(req, status)) {
3028 return;
3031 state->smb2_req->current_idx = 1;
3033 tevent_req_done(req);
3036 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
3037 TALLOC_CTX *mem_ctx,
3038 struct smbd_smb2_request **_smb2_req)
3040 struct smbd_smb2_request_read_state *state =
3041 tevent_req_data(req,
3042 struct smbd_smb2_request_read_state);
3043 NTSTATUS status;
3045 if (tevent_req_is_nterror(req, &status)) {
3046 tevent_req_received(req);
3047 return status;
3050 *_smb2_req = talloc_move(mem_ctx, &state->smb2_req);
3051 tevent_req_received(req);
3052 return NT_STATUS_OK;
3055 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
3057 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
3059 size_t max_send_queue_len;
3060 size_t cur_send_queue_len;
3061 struct tevent_req *subreq;
3063 if (sconn->smb2.compound_related_in_progress) {
3065 * Can't read another until the related
3066 * compound is done.
3068 return NT_STATUS_OK;
3071 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
3073 * if there is already a smbd_smb2_request_read
3074 * pending, we are done.
3076 return NT_STATUS_OK;
3079 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
3080 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
3082 if (cur_send_queue_len > max_send_queue_len) {
3084 * if we have a lot of requests to send,
3085 * we wait until they are on the wire until we
3086 * ask for the next request.
3088 return NT_STATUS_OK;
3091 /* ask for the next request */
3092 subreq = smbd_smb2_request_read_send(sconn, sconn->ev_ctx, sconn);
3093 if (subreq == NULL) {
3094 return NT_STATUS_NO_MEMORY;
3096 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
3098 return NT_STATUS_OK;
3101 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
3102 uint8_t *inbuf, size_t size)
3104 NTSTATUS status;
3105 struct smbd_smb2_request *req = NULL;
3107 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3108 (unsigned int)size));
3110 status = smbd_initialize_smb2(sconn);
3111 if (!NT_STATUS_IS_OK(status)) {
3112 smbd_server_connection_terminate(sconn, nt_errstr(status));
3113 return;
3116 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
3117 if (!NT_STATUS_IS_OK(status)) {
3118 smbd_server_connection_terminate(sconn, nt_errstr(status));
3119 return;
3122 status = smbd_smb2_request_validate(req);
3123 if (!NT_STATUS_IS_OK(status)) {
3124 smbd_server_connection_terminate(sconn, nt_errstr(status));
3125 return;
3128 status = smbd_smb2_request_setup_out(req);
3129 if (!NT_STATUS_IS_OK(status)) {
3130 smbd_server_connection_terminate(sconn, nt_errstr(status));
3131 return;
3134 status = smbd_smb2_request_dispatch(req);
3135 if (!NT_STATUS_IS_OK(status)) {
3136 smbd_server_connection_terminate(sconn, nt_errstr(status));
3137 return;
3140 status = smbd_smb2_request_next_incoming(sconn);
3141 if (!NT_STATUS_IS_OK(status)) {
3142 smbd_server_connection_terminate(sconn, nt_errstr(status));
3143 return;
3146 sconn->num_requests++;
3149 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
3151 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
3152 struct smbd_server_connection);
3153 NTSTATUS status;
3154 struct smbd_smb2_request *req = NULL;
3156 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
3157 TALLOC_FREE(subreq);
3158 if (!NT_STATUS_IS_OK(status)) {
3159 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
3160 nt_errstr(status)));
3161 smbd_server_connection_terminate(sconn, nt_errstr(status));
3162 return;
3165 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
3166 req->current_idx, req->in.vector_count));
3168 status = smbd_smb2_request_validate(req);
3169 if (!NT_STATUS_IS_OK(status)) {
3170 smbd_server_connection_terminate(sconn, nt_errstr(status));
3171 return;
3174 status = smbd_smb2_request_setup_out(req);
3175 if (!NT_STATUS_IS_OK(status)) {
3176 smbd_server_connection_terminate(sconn, nt_errstr(status));
3177 return;
3180 status = smbd_smb2_request_dispatch(req);
3181 if (!NT_STATUS_IS_OK(status)) {
3182 smbd_server_connection_terminate(sconn, nt_errstr(status));
3183 return;
3186 status = smbd_smb2_request_next_incoming(sconn);
3187 if (!NT_STATUS_IS_OK(status)) {
3188 smbd_server_connection_terminate(sconn, nt_errstr(status));
3189 return;
3192 sconn->num_requests++;
3194 /* The timeout_processing function isn't run nearly
3195 often enough to implement 'max log size' without
3196 overrunning the size of the file by many megabytes.
3197 This is especially true if we are running at debug
3198 level 10. Checking every 50 SMB2s is a nice
3199 tradeoff of performance vs log file size overrun. */
3201 if ((sconn->num_requests % 50) == 0 &&
3202 need_to_check_log_size()) {
3203 change_to_root_user();
3204 check_log_size();