libcli/smb: fix padding in smb2_create_blob*
[Samba/gebeck_regimport.git] / source3 / smbd / smb2_server.c
blobbe7997febfb919b9bacfd3705f4d10765bbafa2f
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 status = smb2srv_tcon_lookup(req->session,
1695 in_tid, now, &tcon);
1696 if (!NT_STATUS_IS_OK(status)) {
1697 return status;
1700 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1701 return NT_STATUS_ACCESS_DENIED;
1704 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1705 if (!set_current_service(tcon->compat, 0, true)) {
1706 return NT_STATUS_ACCESS_DENIED;
1709 req->tcon = tcon;
1710 req->last_tid = in_tid;
1712 return NT_STATUS_OK;
1715 /*************************************************************
1716 Ensure an incoming session_id is a valid one for us to access.
1717 *************************************************************/
1719 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1721 const uint8_t *inhdr;
1722 uint32_t in_flags;
1723 uint16_t in_opcode;
1724 uint64_t in_session_id;
1725 struct smbXsrv_session *session = NULL;
1726 struct auth_session_info *session_info;
1727 NTSTATUS status;
1728 NTTIME now = timeval_to_nttime(&req->request_time);
1730 req->session = NULL;
1731 req->tcon = NULL;
1733 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1735 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1736 in_opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1737 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1739 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1740 in_session_id = req->last_session_id;
1743 /* lookup an existing session */
1744 status = smb2srv_session_lookup(req->sconn->conn,
1745 in_session_id, now,
1746 &session);
1747 if (session) {
1748 req->session = session;
1749 req->last_session_id = in_session_id;
1751 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1752 switch (in_opcode) {
1753 case SMB2_OP_SESSSETUP:
1754 status = NT_STATUS_OK;
1755 break;
1756 default:
1757 break;
1760 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1761 switch (in_opcode) {
1762 case SMB2_OP_TCON:
1763 case SMB2_OP_CREATE:
1764 case SMB2_OP_GETINFO:
1765 case SMB2_OP_SETINFO:
1766 return NT_STATUS_INVALID_HANDLE;
1767 default:
1769 * Notice the check for
1770 * (session_info == NULL)
1771 * below.
1773 status = NT_STATUS_OK;
1774 break;
1777 if (!NT_STATUS_IS_OK(status)) {
1778 return status;
1781 session_info = session->global->auth_session_info;
1782 if (session_info == NULL) {
1783 return NT_STATUS_INVALID_HANDLE;
1786 set_current_user_info(session_info->unix_info->sanitized_username,
1787 session_info->unix_info->unix_name,
1788 session_info->info->domain_name);
1790 return NT_STATUS_OK;
1793 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1794 uint32_t data_length)
1796 uint16_t needed_charge;
1797 uint16_t credit_charge = 1;
1798 const uint8_t *inhdr;
1800 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1802 if (req->sconn->smb2.supports_multicredit) {
1803 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1804 credit_charge = MAX(credit_charge, 1);
1807 needed_charge = (data_length - 1)/ 65536 + 1;
1809 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1810 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1811 credit_charge, needed_charge));
1813 if (needed_charge > credit_charge) {
1814 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1815 credit_charge, needed_charge));
1816 return NT_STATUS_INVALID_PARAMETER;
1819 return NT_STATUS_OK;
1822 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1823 size_t expected_body_size)
1825 struct iovec *inhdr_v;
1826 const uint8_t *inhdr;
1827 uint16_t opcode;
1828 const uint8_t *inbody;
1829 size_t body_size;
1830 size_t min_dyn_size = expected_body_size & 0x00000001;
1831 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1834 * The following should be checked already.
1836 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1837 return NT_STATUS_INTERNAL_ERROR;
1839 if (req->current_idx > max_idx) {
1840 return NT_STATUS_INTERNAL_ERROR;
1843 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1844 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1845 return NT_STATUS_INTERNAL_ERROR;
1847 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1848 return NT_STATUS_INTERNAL_ERROR;
1851 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1852 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1854 switch (opcode) {
1855 case SMB2_OP_IOCTL:
1856 case SMB2_OP_GETINFO:
1857 min_dyn_size = 0;
1858 break;
1862 * Now check the expected body size,
1863 * where the last byte might be in the
1864 * dynamic section..
1866 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1867 return NT_STATUS_INVALID_PARAMETER;
1869 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1870 return NT_STATUS_INVALID_PARAMETER;
1873 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1875 body_size = SVAL(inbody, 0x00);
1876 if (body_size != expected_body_size) {
1877 return NT_STATUS_INVALID_PARAMETER;
1880 return NT_STATUS_OK;
1883 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1885 struct smbXsrv_connection *conn = req->sconn->conn;
1886 const struct smbd_smb2_dispatch_table *call = NULL;
1887 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1888 const uint8_t *inhdr;
1889 uint16_t opcode;
1890 uint32_t flags;
1891 uint64_t mid;
1892 NTSTATUS status;
1893 NTSTATUS session_status;
1894 uint32_t allowed_flags;
1895 NTSTATUS return_value;
1896 struct smbXsrv_session *x = NULL;
1897 bool signing_required = false;
1898 bool encryption_required = false;
1900 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1902 /* TODO: verify more things */
1904 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1905 opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1906 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1907 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1908 smb2_opcode_name(opcode),
1909 (unsigned long long)mid));
1911 if (conn->protocol >= PROTOCOL_SMB2_02) {
1913 * once the protocol is negotiated
1914 * SMB2_OP_NEGPROT is not allowed anymore
1916 if (opcode == SMB2_OP_NEGPROT) {
1917 /* drop the connection */
1918 return NT_STATUS_INVALID_PARAMETER;
1920 } else {
1922 * if the protocol is not negotiated yet
1923 * only SMB2_OP_NEGPROT is allowed.
1925 if (opcode != SMB2_OP_NEGPROT) {
1926 /* drop the connection */
1927 return NT_STATUS_INVALID_PARAMETER;
1932 * Check if the client provided a valid session id,
1933 * if so smbd_smb2_request_check_session() calls
1934 * set_current_user_info().
1936 * As some command don't require a valid session id
1937 * we defer the check of the session_status
1939 session_status = smbd_smb2_request_check_session(req);
1940 x = req->session;
1941 if (x != NULL) {
1942 signing_required = x->global->signing_required;
1943 encryption_required = x->global->encryption_required;
1945 if (opcode == SMB2_OP_SESSSETUP &&
1946 x->global->channels[0].signing_key.length) {
1947 signing_required = true;
1951 req->do_signing = false;
1952 req->do_encryption = false;
1953 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
1954 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
1955 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
1957 if (x != NULL && x->global->session_wire_id != tf_session_id) {
1958 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1959 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1960 (unsigned long long)x->global->session_wire_id,
1961 (unsigned long long)tf_session_id));
1963 * TODO: windows allows this...
1964 * should we drop the connection?
1966 * For now we just return ACCESS_DENIED
1967 * (Windows clients never trigger this)
1968 * and wait for an update of [MS-SMB2].
1970 return smbd_smb2_request_error(req,
1971 NT_STATUS_ACCESS_DENIED);
1974 req->do_encryption = true;
1977 if (encryption_required && !req->do_encryption) {
1978 return smbd_smb2_request_error(req,
1979 NT_STATUS_ACCESS_DENIED);
1982 call = smbd_smb2_call(opcode);
1983 if (call == NULL) {
1984 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1987 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1988 SMB2_HDR_FLAG_SIGNED |
1989 SMB2_HDR_FLAG_DFS;
1990 if (opcode == SMB2_OP_CANCEL) {
1991 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1993 if ((flags & ~allowed_flags) != 0) {
1994 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1997 if (req->do_encryption) {
1998 signing_required = false;
1999 } else if (flags & SMB2_HDR_FLAG_SIGNED) {
2000 DATA_BLOB signing_key;
2002 if (x == NULL) {
2003 return smbd_smb2_request_error(
2004 req, NT_STATUS_ACCESS_DENIED);
2007 signing_key = x->global->channels[0].signing_key;
2010 * If we have a signing key, we should
2011 * sign the response
2013 if (signing_key.length > 0) {
2014 req->do_signing = true;
2017 status = smb2_signing_check_pdu(signing_key,
2018 conn->protocol,
2019 SMBD_SMB2_IN_HDR_IOV(req),
2020 SMBD_SMB2_NUM_IOV_PER_REQ);
2021 if (!NT_STATUS_IS_OK(status)) {
2022 return smbd_smb2_request_error(req, status);
2026 * Now that we know the request was correctly signed
2027 * we have to sign the response too.
2029 req->do_signing = true;
2031 if (!NT_STATUS_IS_OK(session_status)) {
2032 return smbd_smb2_request_error(req, session_status);
2034 } else if (opcode == SMB2_OP_CANCEL) {
2035 /* Cancel requests are allowed to skip the signing */
2036 } else if (signing_required) {
2038 * If signing is required we try to sign
2039 * a possible error response
2041 req->do_signing = true;
2042 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2045 if (flags & SMB2_HDR_FLAG_CHAINED) {
2047 * This check is mostly for giving the correct error code
2048 * for compounded requests.
2050 * TODO: we may need to move this after the session
2051 * and tcon checks.
2053 if (!NT_STATUS_IS_OK(req->next_status)) {
2054 return smbd_smb2_request_error(req, req->next_status);
2056 } else {
2057 req->compat_chain_fsp = NULL;
2060 if (req->compound_related) {
2061 req->sconn->smb2.compound_related_in_progress = true;
2064 if (call->need_session) {
2065 if (!NT_STATUS_IS_OK(session_status)) {
2066 return smbd_smb2_request_error(req, session_status);
2070 if (call->need_tcon) {
2071 SMB_ASSERT(call->need_session);
2074 * This call needs to be run as user.
2076 * smbd_smb2_request_check_tcon()
2077 * calls change_to_user() on success.
2079 status = smbd_smb2_request_check_tcon(req);
2080 if (!NT_STATUS_IS_OK(status)) {
2081 return smbd_smb2_request_error(req, status);
2083 if (req->tcon->global->encryption_required) {
2084 encryption_required = true;
2086 if (encryption_required && !req->do_encryption) {
2087 return smbd_smb2_request_error(req,
2088 NT_STATUS_ACCESS_DENIED);
2092 if (call->fileid_ofs != 0) {
2093 size_t needed = call->fileid_ofs + 16;
2094 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2095 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2096 uint64_t file_id_persistent;
2097 uint64_t file_id_volatile;
2098 struct files_struct *fsp;
2100 SMB_ASSERT(call->need_tcon);
2102 if (needed > body_size) {
2103 return smbd_smb2_request_error(req,
2104 NT_STATUS_INVALID_PARAMETER);
2107 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2108 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2110 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2111 if (fsp == NULL) {
2112 if (!call->allow_invalid_fileid) {
2113 return smbd_smb2_request_error(req,
2114 NT_STATUS_FILE_CLOSED);
2117 if (file_id_persistent != UINT64_MAX) {
2118 return smbd_smb2_request_error(req,
2119 NT_STATUS_FILE_CLOSED);
2121 if (file_id_volatile != UINT64_MAX) {
2122 return smbd_smb2_request_error(req,
2123 NT_STATUS_FILE_CLOSED);
2128 if (call->as_root) {
2129 SMB_ASSERT(call->fileid_ofs == 0);
2130 /* This call needs to be run as root */
2131 change_to_root_user();
2132 } else {
2133 SMB_ASSERT(call->need_tcon);
2136 switch (opcode) {
2137 case SMB2_OP_NEGPROT:
2139 START_PROFILE(smb2_negprot);
2140 return_value = smbd_smb2_request_process_negprot(req);
2141 END_PROFILE(smb2_negprot);
2143 break;
2145 case SMB2_OP_SESSSETUP:
2147 START_PROFILE(smb2_sesssetup);
2148 return_value = smbd_smb2_request_process_sesssetup(req);
2149 END_PROFILE(smb2_sesssetup);
2151 break;
2153 case SMB2_OP_LOGOFF:
2155 START_PROFILE(smb2_logoff);
2156 return_value = smbd_smb2_request_process_logoff(req);
2157 END_PROFILE(smb2_logoff);
2159 break;
2161 case SMB2_OP_TCON:
2163 START_PROFILE(smb2_tcon);
2164 return_value = smbd_smb2_request_process_tcon(req);
2165 END_PROFILE(smb2_tcon);
2167 break;
2169 case SMB2_OP_TDIS:
2171 START_PROFILE(smb2_tdis);
2172 return_value = smbd_smb2_request_process_tdis(req);
2173 END_PROFILE(smb2_tdis);
2175 break;
2177 case SMB2_OP_CREATE:
2179 START_PROFILE(smb2_create);
2180 return_value = smbd_smb2_request_process_create(req);
2181 END_PROFILE(smb2_create);
2183 break;
2185 case SMB2_OP_CLOSE:
2187 START_PROFILE(smb2_close);
2188 return_value = smbd_smb2_request_process_close(req);
2189 END_PROFILE(smb2_close);
2191 break;
2193 case SMB2_OP_FLUSH:
2195 START_PROFILE(smb2_flush);
2196 return_value = smbd_smb2_request_process_flush(req);
2197 END_PROFILE(smb2_flush);
2199 break;
2201 case SMB2_OP_READ:
2203 START_PROFILE(smb2_read);
2204 return_value = smbd_smb2_request_process_read(req);
2205 END_PROFILE(smb2_read);
2207 break;
2209 case SMB2_OP_WRITE:
2211 START_PROFILE(smb2_write);
2212 return_value = smbd_smb2_request_process_write(req);
2213 END_PROFILE(smb2_write);
2215 break;
2217 case SMB2_OP_LOCK:
2219 START_PROFILE(smb2_lock);
2220 return_value = smbd_smb2_request_process_lock(req);
2221 END_PROFILE(smb2_lock);
2223 break;
2225 case SMB2_OP_IOCTL:
2227 START_PROFILE(smb2_ioctl);
2228 return_value = smbd_smb2_request_process_ioctl(req);
2229 END_PROFILE(smb2_ioctl);
2231 break;
2233 case SMB2_OP_CANCEL:
2235 START_PROFILE(smb2_cancel);
2236 return_value = smbd_smb2_request_process_cancel(req);
2237 END_PROFILE(smb2_cancel);
2239 break;
2241 case SMB2_OP_KEEPALIVE:
2243 START_PROFILE(smb2_keepalive);
2244 return_value = smbd_smb2_request_process_keepalive(req);
2245 END_PROFILE(smb2_keepalive);
2247 break;
2249 case SMB2_OP_FIND:
2251 START_PROFILE(smb2_find);
2252 return_value = smbd_smb2_request_process_find(req);
2253 END_PROFILE(smb2_find);
2255 break;
2257 case SMB2_OP_NOTIFY:
2259 START_PROFILE(smb2_notify);
2260 return_value = smbd_smb2_request_process_notify(req);
2261 END_PROFILE(smb2_notify);
2263 break;
2265 case SMB2_OP_GETINFO:
2267 START_PROFILE(smb2_getinfo);
2268 return_value = smbd_smb2_request_process_getinfo(req);
2269 END_PROFILE(smb2_getinfo);
2271 break;
2273 case SMB2_OP_SETINFO:
2275 START_PROFILE(smb2_setinfo);
2276 return_value = smbd_smb2_request_process_setinfo(req);
2277 END_PROFILE(smb2_setinfo);
2279 break;
2281 case SMB2_OP_BREAK:
2283 START_PROFILE(smb2_break);
2284 return_value = smbd_smb2_request_process_break(req);
2285 END_PROFILE(smb2_break);
2287 break;
2289 default:
2290 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2291 break;
2293 return return_value;
2296 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2298 struct smbXsrv_connection *conn = req->sconn->conn;
2299 struct tevent_req *subreq;
2300 int first_idx = 1;
2301 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2302 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2303 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2305 req->subreq = NULL;
2306 TALLOC_FREE(req->async_te);
2308 if (req->do_encryption &&
2309 (firsttf->iov_len == 0) &&
2310 (req->first_key.length == 0) &&
2311 (req->session != NULL) &&
2312 (req->session->global->encryption_key.length != 0))
2314 DATA_BLOB encryption_key = req->session->global->encryption_key;
2315 uint8_t *tf;
2316 uint64_t session_id = req->session->global->session_wire_id;
2317 struct smbXsrv_session *x = req->session;
2318 uint64_t nonce_high;
2319 uint64_t nonce_low;
2321 nonce_high = x->nonce_high;
2322 nonce_low = x->nonce_low;
2324 x->nonce_low += 1;
2325 if (x->nonce_low == 0) {
2326 x->nonce_low += 1;
2327 x->nonce_high += 1;
2331 * We need to place the SMB2_TRANSFORM header before the
2332 * first SMB2 header
2336 * we need to remember the encryption key
2337 * and defer the signing/encryption until
2338 * we are sure that we do not change
2339 * the header again.
2341 req->first_key = data_blob_dup_talloc(req, encryption_key);
2342 if (req->first_key.data == NULL) {
2343 return NT_STATUS_NO_MEMORY;
2346 tf = talloc_zero_array(req->out.vector, uint8_t,
2347 SMB2_TF_HDR_SIZE);
2348 if (tf == NULL) {
2349 return NT_STATUS_NO_MEMORY;
2352 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2353 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2354 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2355 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2357 firsttf->iov_base = (void *)tf;
2358 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2361 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2362 (req->last_key.length > 0) &&
2363 (firsttf->iov_len == 0))
2365 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2366 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2367 NTSTATUS status;
2370 * As we are sure the header of the last request in the
2371 * compound chain will not change, we can to sign here
2372 * with the last signing key we remembered.
2374 status = smb2_signing_sign_pdu(req->last_key,
2375 conn->protocol,
2376 lasthdr,
2377 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2378 if (!NT_STATUS_IS_OK(status)) {
2379 return status;
2382 data_blob_clear_free(&req->last_key);
2384 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2386 if (req->current_idx < req->out.vector_count) {
2388 * We must process the remaining compound
2389 * SMB2 requests before any new incoming SMB2
2390 * requests. This is because incoming SMB2
2391 * requests may include a cancel for a
2392 * compound request we haven't processed
2393 * yet.
2395 struct tevent_immediate *im = tevent_create_immediate(req);
2396 if (!im) {
2397 return NT_STATUS_NO_MEMORY;
2400 if (req->do_signing && firsttf->iov_len == 0) {
2401 struct smbXsrv_session *x = req->session;
2402 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2405 * we need to remember the signing key
2406 * and defer the signing until
2407 * we are sure that we do not change
2408 * the header again.
2410 req->last_key = data_blob_dup_talloc(req, signing_key);
2411 if (req->last_key.data == NULL) {
2412 return NT_STATUS_NO_MEMORY;
2416 tevent_schedule_immediate(im,
2417 req->sconn->ev_ctx,
2418 smbd_smb2_request_dispatch_immediate,
2419 req);
2420 return NT_STATUS_OK;
2423 if (req->compound_related) {
2424 req->sconn->smb2.compound_related_in_progress = false;
2427 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2429 /* Set credit for these operations (zero credits if this
2430 is a final reply for an async operation). */
2431 smb2_calculate_credits(req, req);
2434 * now check if we need to sign the current response
2436 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2437 NTSTATUS status;
2439 status = smb2_signing_encrypt_pdu(req->first_key,
2440 conn->protocol,
2441 firsttf,
2442 req->out.vector_count - first_idx);
2443 if (!NT_STATUS_IS_OK(status)) {
2444 return status;
2446 } else if (req->do_signing) {
2447 NTSTATUS status;
2448 struct smbXsrv_session *x = req->session;
2449 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2451 status = smb2_signing_sign_pdu(signing_key,
2452 conn->protocol,
2453 outhdr,
2454 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2455 if (!NT_STATUS_IS_OK(status)) {
2456 return status;
2459 data_blob_clear_free(&req->first_key);
2461 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2462 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2463 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2464 /* Dynamic part is NULL. Chop it off,
2465 We're going to send it via sendfile. */
2466 req->out.vector_count -= 1;
2469 subreq = tstream_writev_queue_send(req,
2470 req->sconn->ev_ctx,
2471 req->sconn->smb2.stream,
2472 req->sconn->smb2.send_queue,
2473 req->out.vector,
2474 req->out.vector_count);
2475 if (subreq == NULL) {
2476 return NT_STATUS_NO_MEMORY;
2478 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
2480 * We're done with this request -
2481 * move it off the "being processed" queue.
2483 DLIST_REMOVE(req->sconn->smb2.requests, req);
2485 return NT_STATUS_OK;
2488 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2490 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2491 struct tevent_immediate *im,
2492 void *private_data)
2494 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2495 struct smbd_smb2_request);
2496 struct smbd_server_connection *sconn = req->sconn;
2497 NTSTATUS status;
2499 TALLOC_FREE(im);
2501 if (DEBUGLEVEL >= 10) {
2502 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2503 req->current_idx, req->in.vector_count));
2504 print_req_vectors(req);
2507 status = smbd_smb2_request_dispatch(req);
2508 if (!NT_STATUS_IS_OK(status)) {
2509 smbd_server_connection_terminate(sconn, nt_errstr(status));
2510 return;
2513 status = smbd_smb2_request_next_incoming(sconn);
2514 if (!NT_STATUS_IS_OK(status)) {
2515 smbd_server_connection_terminate(sconn, nt_errstr(status));
2516 return;
2520 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
2522 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
2523 struct smbd_smb2_request);
2524 struct smbd_server_connection *sconn = req->sconn;
2525 int ret;
2526 int sys_errno;
2527 NTSTATUS status;
2529 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2530 TALLOC_FREE(subreq);
2531 TALLOC_FREE(req);
2532 if (ret == -1) {
2533 status = map_nt_error_from_unix(sys_errno);
2534 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2535 nt_errstr(status)));
2536 smbd_server_connection_terminate(sconn, nt_errstr(status));
2537 return;
2540 status = smbd_smb2_request_next_incoming(sconn);
2541 if (!NT_STATUS_IS_OK(status)) {
2542 smbd_server_connection_terminate(sconn, nt_errstr(status));
2543 return;
2547 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2548 NTSTATUS status,
2549 DATA_BLOB body, DATA_BLOB *dyn,
2550 const char *location)
2552 uint8_t *outhdr;
2553 struct iovec *outbody_v;
2554 struct iovec *outdyn_v;
2555 uint32_t next_command_ofs;
2557 DEBUG(10,("smbd_smb2_request_done_ex: "
2558 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2559 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2560 dyn ? "yes": "no",
2561 (unsigned int)(dyn ? dyn->length : 0),
2562 location));
2564 if (body.length < 2) {
2565 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2568 if ((body.length % 2) != 0) {
2569 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2572 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2573 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2574 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2576 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2577 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2579 outbody_v->iov_base = (void *)body.data;
2580 outbody_v->iov_len = body.length;
2582 if (dyn) {
2583 outdyn_v->iov_base = (void *)dyn->data;
2584 outdyn_v->iov_len = dyn->length;
2585 } else {
2586 outdyn_v->iov_base = NULL;
2587 outdyn_v->iov_len = 0;
2590 /* see if we need to recalculate the offset to the next response */
2591 if (next_command_ofs > 0) {
2592 next_command_ofs = SMB2_HDR_BODY;
2593 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2594 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2597 if ((next_command_ofs % 8) != 0) {
2598 size_t pad_size = 8 - (next_command_ofs % 8);
2599 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2601 * if the dyn buffer is empty
2602 * we can use it to add padding
2604 uint8_t *pad;
2606 pad = talloc_zero_array(req->out.vector,
2607 uint8_t, pad_size);
2608 if (pad == NULL) {
2609 return smbd_smb2_request_error(req,
2610 NT_STATUS_NO_MEMORY);
2613 outdyn_v->iov_base = (void *)pad;
2614 outdyn_v->iov_len = pad_size;
2615 } else {
2617 * For now we copy the dynamic buffer
2618 * and add the padding to the new buffer
2620 size_t old_size;
2621 uint8_t *old_dyn;
2622 size_t new_size;
2623 uint8_t *new_dyn;
2625 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2626 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2628 new_size = old_size + pad_size;
2629 new_dyn = talloc_zero_array(req->out.vector,
2630 uint8_t, new_size);
2631 if (new_dyn == NULL) {
2632 return smbd_smb2_request_error(req,
2633 NT_STATUS_NO_MEMORY);
2636 memcpy(new_dyn, old_dyn, old_size);
2637 memset(new_dyn + old_size, 0, pad_size);
2639 outdyn_v->iov_base = (void *)new_dyn;
2640 outdyn_v->iov_len = new_size;
2642 next_command_ofs += pad_size;
2645 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2647 return smbd_smb2_request_reply(req);
2650 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2651 NTSTATUS status,
2652 DATA_BLOB *info,
2653 const char *location)
2655 DATA_BLOB body;
2656 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2658 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2659 req->current_idx, nt_errstr(status), info ? " +info" : "",
2660 location));
2662 body.data = outhdr + SMB2_HDR_BODY;
2663 body.length = 8;
2664 SSVAL(body.data, 0, 9);
2666 if (info) {
2667 SIVAL(body.data, 0x04, info->length);
2668 } else {
2669 /* Allocated size of req->out.vector[i].iov_base
2670 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2671 * 1 byte without having to do an alloc.
2673 info = talloc_zero_array(req->out.vector,
2674 DATA_BLOB,
2676 if (!info) {
2677 return NT_STATUS_NO_MEMORY;
2679 info->data = ((uint8_t *)outhdr) +
2680 OUTVEC_ALLOC_SIZE - 1;
2681 info->length = 1;
2682 SCVAL(info->data, 0, 0);
2686 * if a request fails, all other remaining
2687 * compounded requests should fail too
2689 req->next_status = NT_STATUS_INVALID_PARAMETER;
2691 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2695 struct smbd_smb2_send_oplock_break_state {
2696 struct smbd_server_connection *sconn;
2697 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x18];
2698 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2701 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2703 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2704 struct smbXsrv_session *session,
2705 struct smbXsrv_tcon *tcon,
2706 struct smbXsrv_open *op,
2707 uint8_t oplock_level)
2709 struct smbd_smb2_send_oplock_break_state *state;
2710 struct smbXsrv_connection *conn = sconn->conn;
2711 struct tevent_req *subreq;
2712 uint8_t *tf;
2713 size_t tf_len;
2714 uint8_t *hdr;
2715 uint8_t *body;
2716 size_t body_len;
2717 uint8_t *dyn;
2718 size_t dyn_len;
2719 bool do_encryption = session->global->encryption_required;
2720 uint64_t nonce_high = 0;
2721 uint64_t nonce_low = 0;
2723 if (tcon->global->encryption_required) {
2724 do_encryption = true;
2727 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2728 if (state == NULL) {
2729 return NT_STATUS_NO_MEMORY;
2731 state->sconn = sconn;
2733 tf = state->buf + NBT_HDR_SIZE;
2734 tf_len = SMB2_TF_HDR_SIZE;
2735 hdr = tf + tf_len;
2736 body = hdr + SMB2_HDR_BODY;
2737 body_len = 0x18;
2738 dyn = body + body_len;
2739 dyn_len = 0;
2741 if (do_encryption) {
2742 nonce_high = session->nonce_high;
2743 nonce_low = session->nonce_low;
2745 session->nonce_low += 1;
2746 if (session->nonce_low == 0) {
2747 session->nonce_low += 1;
2748 session->nonce_high += 1;
2752 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2753 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2754 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2755 SBVAL(tf, SMB2_TF_SESSION_ID, session->global->session_wire_id);
2757 SIVAL(hdr, 0, SMB2_MAGIC);
2758 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2759 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2760 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2761 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2762 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2763 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2764 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2765 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2766 SIVAL(hdr, SMB2_HDR_PID, 0);
2767 SIVAL(hdr, SMB2_HDR_TID, 0);
2768 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2769 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2771 SSVAL(body, 0x00, body_len);
2773 SCVAL(body, 0x02, oplock_level);
2774 SCVAL(body, 0x03, 0); /* reserved */
2775 SIVAL(body, 0x04, 0); /* reserved */
2776 SBVAL(body, 0x08, op->global->open_persistent_id);
2777 SBVAL(body, 0x10, op->global->open_volatile_id);
2779 state->vector[0].iov_base = (void *)state->buf;
2780 state->vector[0].iov_len = NBT_HDR_SIZE;
2782 if (do_encryption) {
2783 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
2784 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
2785 } else {
2786 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
2787 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
2790 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
2791 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
2793 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
2794 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = body_len;
2796 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
2797 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_len;
2799 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2801 if (do_encryption) {
2802 NTSTATUS status;
2803 DATA_BLOB encryption_key = session->global->encryption_key;
2805 status = smb2_signing_encrypt_pdu(encryption_key,
2806 conn->protocol,
2807 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2808 SMBD_SMB2_NUM_IOV_PER_REQ);
2809 if (!NT_STATUS_IS_OK(status)) {
2810 return status;
2814 subreq = tstream_writev_queue_send(state,
2815 sconn->ev_ctx,
2816 sconn->smb2.stream,
2817 sconn->smb2.send_queue,
2818 state->vector,
2819 ARRAY_SIZE(state->vector));
2820 if (subreq == NULL) {
2821 return NT_STATUS_NO_MEMORY;
2823 tevent_req_set_callback(subreq,
2824 smbd_smb2_oplock_break_writev_done,
2825 state);
2827 return NT_STATUS_OK;
2830 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2832 struct smbd_smb2_send_oplock_break_state *state =
2833 tevent_req_callback_data(subreq,
2834 struct smbd_smb2_send_oplock_break_state);
2835 struct smbd_server_connection *sconn = state->sconn;
2836 int ret;
2837 int sys_errno;
2839 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2840 TALLOC_FREE(subreq);
2841 if (ret == -1) {
2842 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2843 smbd_server_connection_terminate(sconn, nt_errstr(status));
2844 return;
2847 TALLOC_FREE(state);
2850 struct smbd_smb2_request_read_state {
2851 struct tevent_context *ev;
2852 struct smbd_server_connection *sconn;
2853 struct smbd_smb2_request *smb2_req;
2854 struct {
2855 uint8_t nbt[NBT_HDR_SIZE];
2856 bool done;
2857 } hdr;
2858 size_t pktlen;
2859 uint8_t *pktbuf;
2862 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2863 void *private_data,
2864 TALLOC_CTX *mem_ctx,
2865 struct iovec **_vector,
2866 size_t *_count);
2867 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2869 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2870 struct tevent_context *ev,
2871 struct smbd_server_connection *sconn)
2873 struct tevent_req *req;
2874 struct smbd_smb2_request_read_state *state;
2875 struct tevent_req *subreq;
2877 req = tevent_req_create(mem_ctx, &state,
2878 struct smbd_smb2_request_read_state);
2879 if (req == NULL) {
2880 return NULL;
2882 state->ev = ev;
2883 state->sconn = sconn;
2885 state->smb2_req = smbd_smb2_request_allocate(state);
2886 if (tevent_req_nomem(state->smb2_req, req)) {
2887 return tevent_req_post(req, ev);
2889 state->smb2_req->sconn = sconn;
2891 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
2892 state->ev,
2893 state->sconn->smb2.stream,
2894 state->sconn->smb2.recv_queue,
2895 smbd_smb2_request_next_vector,
2896 state);
2897 if (tevent_req_nomem(subreq, req)) {
2898 return tevent_req_post(req, ev);
2900 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2902 return req;
2905 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2906 void *private_data,
2907 TALLOC_CTX *mem_ctx,
2908 struct iovec **_vector,
2909 size_t *_count)
2911 struct smbd_smb2_request_read_state *state =
2912 talloc_get_type_abort(private_data,
2913 struct smbd_smb2_request_read_state);
2914 struct iovec *vector;
2916 if (state->pktlen > 0) {
2917 /* if there're no remaining bytes, we're done */
2918 *_vector = NULL;
2919 *_count = 0;
2920 return 0;
2923 if (!state->hdr.done) {
2925 * first we need to get the NBT header
2927 vector = talloc_array(mem_ctx, struct iovec, 1);
2928 if (vector == NULL) {
2929 return -1;
2932 vector[0].iov_base = (void *)state->hdr.nbt;
2933 vector[0].iov_len = NBT_HDR_SIZE;
2935 *_vector = vector;
2936 *_count = 1;
2938 state->hdr.done = true;
2939 return 0;
2943 * Now we analyze the NBT header
2945 state->pktlen = smb2_len(state->hdr.nbt);
2947 if (state->pktlen == 0) {
2948 /* if there're no remaining bytes, we're done */
2949 *_vector = NULL;
2950 *_count = 0;
2951 return 0;
2954 state->pktbuf = talloc_array(state->smb2_req, uint8_t, state->pktlen);
2955 if (state->pktbuf == NULL) {
2956 return -1;
2959 vector = talloc_array(mem_ctx, struct iovec, 1);
2960 if (vector == NULL) {
2961 return -1;
2964 vector[0].iov_base = (void *)state->pktbuf;
2965 vector[0].iov_len = state->pktlen;
2967 *_vector = vector;
2968 *_count = 1;
2969 return 0;
2972 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2974 struct tevent_req *req =
2975 tevent_req_callback_data(subreq,
2976 struct tevent_req);
2977 struct smbd_smb2_request_read_state *state =
2978 tevent_req_data(req,
2979 struct smbd_smb2_request_read_state);
2980 int ret;
2981 int sys_errno;
2982 NTSTATUS status;
2983 NTTIME now;
2985 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2986 TALLOC_FREE(subreq);
2987 if (ret == -1) {
2988 status = map_nt_error_from_unix(sys_errno);
2989 tevent_req_nterror(req, status);
2990 return;
2993 if (state->hdr.nbt[0] != 0x00) {
2994 DEBUG(1,("smbd_smb2_request_read_done: ignore NBT[0x%02X] msg\n",
2995 state->hdr.nbt[0]));
2997 ZERO_STRUCT(state->hdr);
2998 TALLOC_FREE(state->pktbuf);
2999 state->pktlen = 0;
3001 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
3002 state->ev,
3003 state->sconn->smb2.stream,
3004 state->sconn->smb2.recv_queue,
3005 smbd_smb2_request_next_vector,
3006 state);
3007 if (tevent_req_nomem(subreq, req)) {
3008 return;
3010 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
3011 return;
3014 state->smb2_req->request_time = timeval_current();
3015 now = timeval_to_nttime(&state->smb2_req->request_time);
3017 status = smbd_smb2_inbuf_parse_compound(state->smb2_req->sconn->conn,
3018 now,
3019 state->pktbuf,
3020 state->pktlen,
3021 state->smb2_req,
3022 &state->smb2_req->in.vector,
3023 &state->smb2_req->in.vector_count);
3024 if (tevent_req_nterror(req, status)) {
3025 return;
3028 state->smb2_req->current_idx = 1;
3030 tevent_req_done(req);
3033 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
3034 TALLOC_CTX *mem_ctx,
3035 struct smbd_smb2_request **_smb2_req)
3037 struct smbd_smb2_request_read_state *state =
3038 tevent_req_data(req,
3039 struct smbd_smb2_request_read_state);
3040 NTSTATUS status;
3042 if (tevent_req_is_nterror(req, &status)) {
3043 tevent_req_received(req);
3044 return status;
3047 *_smb2_req = talloc_move(mem_ctx, &state->smb2_req);
3048 tevent_req_received(req);
3049 return NT_STATUS_OK;
3052 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
3054 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
3056 size_t max_send_queue_len;
3057 size_t cur_send_queue_len;
3058 struct tevent_req *subreq;
3060 if (sconn->smb2.compound_related_in_progress) {
3062 * Can't read another until the related
3063 * compound is done.
3065 return NT_STATUS_OK;
3068 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
3070 * if there is already a smbd_smb2_request_read
3071 * pending, we are done.
3073 return NT_STATUS_OK;
3076 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
3077 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
3079 if (cur_send_queue_len > max_send_queue_len) {
3081 * if we have a lot of requests to send,
3082 * we wait until they are on the wire until we
3083 * ask for the next request.
3085 return NT_STATUS_OK;
3088 /* ask for the next request */
3089 subreq = smbd_smb2_request_read_send(sconn, sconn->ev_ctx, sconn);
3090 if (subreq == NULL) {
3091 return NT_STATUS_NO_MEMORY;
3093 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
3095 return NT_STATUS_OK;
3098 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
3099 uint8_t *inbuf, size_t size)
3101 NTSTATUS status;
3102 struct smbd_smb2_request *req = NULL;
3104 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3105 (unsigned int)size));
3107 status = smbd_initialize_smb2(sconn);
3108 if (!NT_STATUS_IS_OK(status)) {
3109 smbd_server_connection_terminate(sconn, nt_errstr(status));
3110 return;
3113 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
3114 if (!NT_STATUS_IS_OK(status)) {
3115 smbd_server_connection_terminate(sconn, nt_errstr(status));
3116 return;
3119 status = smbd_smb2_request_validate(req);
3120 if (!NT_STATUS_IS_OK(status)) {
3121 smbd_server_connection_terminate(sconn, nt_errstr(status));
3122 return;
3125 status = smbd_smb2_request_setup_out(req);
3126 if (!NT_STATUS_IS_OK(status)) {
3127 smbd_server_connection_terminate(sconn, nt_errstr(status));
3128 return;
3131 status = smbd_smb2_request_dispatch(req);
3132 if (!NT_STATUS_IS_OK(status)) {
3133 smbd_server_connection_terminate(sconn, nt_errstr(status));
3134 return;
3137 status = smbd_smb2_request_next_incoming(sconn);
3138 if (!NT_STATUS_IS_OK(status)) {
3139 smbd_server_connection_terminate(sconn, nt_errstr(status));
3140 return;
3143 sconn->num_requests++;
3146 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
3148 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
3149 struct smbd_server_connection);
3150 NTSTATUS status;
3151 struct smbd_smb2_request *req = NULL;
3153 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
3154 TALLOC_FREE(subreq);
3155 if (!NT_STATUS_IS_OK(status)) {
3156 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
3157 nt_errstr(status)));
3158 smbd_server_connection_terminate(sconn, nt_errstr(status));
3159 return;
3162 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
3163 req->current_idx, req->in.vector_count));
3165 status = smbd_smb2_request_validate(req);
3166 if (!NT_STATUS_IS_OK(status)) {
3167 smbd_server_connection_terminate(sconn, nt_errstr(status));
3168 return;
3171 status = smbd_smb2_request_setup_out(req);
3172 if (!NT_STATUS_IS_OK(status)) {
3173 smbd_server_connection_terminate(sconn, nt_errstr(status));
3174 return;
3177 status = smbd_smb2_request_dispatch(req);
3178 if (!NT_STATUS_IS_OK(status)) {
3179 smbd_server_connection_terminate(sconn, nt_errstr(status));
3180 return;
3183 status = smbd_smb2_request_next_incoming(sconn);
3184 if (!NT_STATUS_IS_OK(status)) {
3185 smbd_server_connection_terminate(sconn, nt_errstr(status));
3186 return;
3189 sconn->num_requests++;
3191 /* The timeout_processing function isn't run nearly
3192 often enough to implement 'max log size' without
3193 overrunning the size of the file by many megabytes.
3194 This is especially true if we are running at debug
3195 level 10. Checking every 50 SMB2s is a nice
3196 tradeoff of performance vs log file size overrun. */
3198 if ((sconn->num_requests % 50) == 0 &&
3199 need_to_check_log_size()) {
3200 change_to_root_user();
3201 check_log_size();