Add extra fields into struct smbd_smb2_request_read_state to support receivefile.
[Samba/id10ts.git] / source3 / smbd / smb2_server.c
blobe1671a7473e4b7cabc8b65fd67122ff7fa45a2c6
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 = SVAL(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;
717 if (hdr->iov_len != SMB2_HDR_BODY) {
718 return NT_STATUS_INVALID_PARAMETER;
721 if (body->iov_len < 2) {
722 return NT_STATUS_INVALID_PARAMETER;
725 inhdr = (const uint8_t *)hdr->iov_base;
727 /* Check the SMB2 header */
728 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
729 return NT_STATUS_INVALID_PARAMETER;
732 if (!smb2_validate_message_id(req->sconn, inhdr)) {
733 return NT_STATUS_INVALID_PARAMETER;
737 return NT_STATUS_OK;
740 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
741 const struct iovec *in_vector,
742 struct iovec *out_vector)
744 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
745 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
746 uint16_t credit_charge = 1;
747 uint16_t credits_requested;
748 uint32_t out_flags;
749 uint16_t cmd;
750 NTSTATUS out_status;
751 uint16_t credits_granted = 0;
752 uint64_t credits_possible;
753 uint16_t current_max_credits;
756 * first we grant only 1/16th of the max range.
758 * Windows also starts with the 1/16th and then grants
759 * more later. I was only able to trigger higher
760 * values, when using a very high credit charge.
762 * TODO: scale up depending on load, free memory
763 * or other stuff.
764 * Maybe also on the relationship between number
765 * of requests and the used sequence number.
766 * Which means we would grant more credits
767 * for client which use multi credit requests.
769 current_max_credits = sconn->smb2.max_credits / 16;
770 current_max_credits = MAX(current_max_credits, 1);
772 if (sconn->smb2.supports_multicredit) {
773 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
774 credit_charge = MAX(credit_charge, 1);
777 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
778 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
779 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
780 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
782 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
784 if (sconn->smb2.max_credits < credit_charge) {
785 smbd_server_connection_terminate(sconn,
786 "client error: credit charge > max credits\n");
787 return;
790 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
792 * In case we already send an async interim
793 * response, we should not grant
794 * credits on the final response.
796 credits_granted = 0;
797 } else if (credits_requested > 0) {
798 uint16_t additional_max = 0;
799 uint16_t additional_credits = credits_requested - 1;
801 switch (cmd) {
802 case SMB2_OP_NEGPROT:
803 break;
804 case SMB2_OP_SESSSETUP:
806 * Windows 2012 RC1 starts to grant
807 * additional credits
808 * with a successful session setup
810 if (NT_STATUS_IS_OK(out_status)) {
811 additional_max = 32;
813 break;
814 default:
816 * We match windows and only grant additional credits
817 * in chunks of 32.
819 additional_max = 32;
820 break;
823 additional_credits = MIN(additional_credits, additional_max);
825 credits_granted = credit_charge + additional_credits;
826 } else if (sconn->smb2.credits_granted == 0) {
828 * Make sure the client has always at least one credit
830 credits_granted = 1;
834 * sequence numbers should not wrap
836 * 1. calculate the possible credits until
837 * the sequence numbers start to wrap on 64-bit.
839 * 2. UINT64_MAX is used for Break Notifications.
841 * 2. truncate the possible credits to the maximum
842 * credits we want to grant to the client in total.
844 * 3. remove the range we'll already granted to the client
845 * this makes sure the client consumes the lowest sequence
846 * number, before we can grant additional credits.
848 credits_possible = UINT64_MAX - sconn->smb2.seqnum_low;
849 if (credits_possible > 0) {
850 /* remove UINT64_MAX */
851 credits_possible -= 1;
853 credits_possible = MIN(credits_possible, current_max_credits);
854 credits_possible -= sconn->smb2.seqnum_range;
856 credits_granted = MIN(credits_granted, credits_possible);
858 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
859 sconn->smb2.credits_granted += credits_granted;
860 sconn->smb2.seqnum_range += credits_granted;
862 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
863 "granted %u, current possible/max %u/%u, "
864 "total granted/max/low/range %u/%u/%llu/%u\n",
865 (unsigned int)credits_requested,
866 (unsigned int)credit_charge,
867 (unsigned int)credits_granted,
868 (unsigned int)credits_possible,
869 (unsigned int)current_max_credits,
870 (unsigned int)sconn->smb2.credits_granted,
871 (unsigned int)sconn->smb2.max_credits,
872 (unsigned long long)sconn->smb2.seqnum_low,
873 (unsigned int)sconn->smb2.seqnum_range));
876 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
877 struct smbd_smb2_request *outreq)
879 int count, idx;
880 uint16_t total_credits = 0;
882 count = outreq->out.vector_count;
884 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
885 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
886 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
887 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
889 smb2_set_operation_credit(outreq->sconn, inhdr_v, outhdr_v);
891 /* To match Windows, count up what we
892 just granted. */
893 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
894 /* Set to zero in all but the last reply. */
895 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
896 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
897 } else {
898 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
903 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
905 struct iovec *vector;
906 int count;
907 int idx;
909 count = req->in.vector_count;
910 vector = talloc_zero_array(req, struct iovec, count);
911 if (vector == NULL) {
912 return NT_STATUS_NO_MEMORY;
915 vector[0].iov_base = req->out.nbt_hdr;
916 vector[0].iov_len = 4;
917 SIVAL(req->out.nbt_hdr, 0, 0);
919 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
920 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
921 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
922 uint8_t *outhdr = NULL;
923 uint8_t *outbody = NULL;
924 uint32_t next_command_ofs = 0;
925 struct iovec *current = &vector[idx];
927 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
928 /* we have a next command -
929 * setup for the error case. */
930 next_command_ofs = SMB2_HDR_BODY + 9;
933 outhdr = talloc_zero_array(vector, uint8_t,
934 OUTVEC_ALLOC_SIZE);
935 if (outhdr == NULL) {
936 return NT_STATUS_NO_MEMORY;
939 outbody = outhdr + SMB2_HDR_BODY;
942 * SMBD_SMB2_TF_IOV_OFS might be used later
944 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
945 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
947 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
948 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
950 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
951 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
953 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
954 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
956 /* setup the SMB2 header */
957 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
958 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
959 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
960 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
961 SIVAL(outhdr, SMB2_HDR_STATUS,
962 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
963 SSVAL(outhdr, SMB2_HDR_OPCODE,
964 SVAL(inhdr, SMB2_HDR_OPCODE));
965 SIVAL(outhdr, SMB2_HDR_FLAGS,
966 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
967 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
968 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
969 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
970 SIVAL(outhdr, SMB2_HDR_PID,
971 IVAL(inhdr, SMB2_HDR_PID));
972 SIVAL(outhdr, SMB2_HDR_TID,
973 IVAL(inhdr, SMB2_HDR_TID));
974 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
975 BVAL(inhdr, SMB2_HDR_SESSION_ID));
976 memcpy(outhdr + SMB2_HDR_SIGNATURE,
977 inhdr + SMB2_HDR_SIGNATURE, 16);
979 /* setup error body header */
980 SSVAL(outbody, 0x00, 0x08 + 1);
981 SSVAL(outbody, 0x02, 0);
982 SIVAL(outbody, 0x04, 0);
985 req->out.vector = vector;
986 req->out.vector_count = count;
988 /* setup the length of the NBT packet */
989 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
991 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
993 return NT_STATUS_OK;
996 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
997 const char *reason,
998 const char *location)
1000 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1001 reason, location));
1002 exit_server_cleanly(reason);
1005 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1006 struct iovec *outvec,
1007 const struct iovec *srcvec)
1009 const uint8_t *srctf;
1010 size_t srctf_len;
1011 const uint8_t *srchdr;
1012 size_t srchdr_len;
1013 const uint8_t *srcbody;
1014 size_t srcbody_len;
1015 const uint8_t *expected_srcbody;
1016 const uint8_t *srcdyn;
1017 size_t srcdyn_len;
1018 const uint8_t *expected_srcdyn;
1019 uint8_t *dsttf;
1020 uint8_t *dsthdr;
1021 uint8_t *dstbody;
1022 uint8_t *dstdyn;
1024 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1025 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1026 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1027 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1028 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1029 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1030 expected_srcbody = srchdr + SMB2_HDR_BODY;
1031 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1032 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1033 expected_srcdyn = srcbody + 8;
1035 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1036 return false;
1039 if (srchdr_len != SMB2_HDR_BODY) {
1040 return false;
1043 if (srctf_len == SMB2_TF_HDR_SIZE) {
1044 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1045 if (dsttf == NULL) {
1046 return false;
1048 } else {
1049 dsttf = NULL;
1051 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1052 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1054 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1055 * be allocated with size OUTVEC_ALLOC_SIZE. */
1057 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1058 if (dsthdr == NULL) {
1059 return false;
1061 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1062 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1065 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1066 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1067 * then duplicate this. Else use talloc_memdup().
1070 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1071 dstbody = dsthdr + SMB2_HDR_BODY;
1072 } else {
1073 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1074 if (dstbody == NULL) {
1075 return false;
1078 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1079 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1082 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1083 * pointing to
1084 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1085 * then duplicate this. Else use talloc_memdup().
1088 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1089 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1090 } else if (srcdyn == NULL) {
1091 dstdyn = NULL;
1092 } else {
1093 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1094 if (dstdyn == NULL) {
1095 return false;
1098 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1099 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1101 return true;
1104 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1106 struct smbd_smb2_request *newreq = NULL;
1107 struct iovec *outvec = NULL;
1108 int count = req->out.vector_count;
1109 int i;
1111 newreq = smbd_smb2_request_allocate(req->sconn);
1112 if (!newreq) {
1113 return NULL;
1116 newreq->sconn = req->sconn;
1117 newreq->session = req->session;
1118 newreq->do_encryption = req->do_encryption;
1119 newreq->do_signing = req->do_signing;
1120 newreq->current_idx = req->current_idx;
1122 outvec = talloc_zero_array(newreq, struct iovec, count);
1123 if (!outvec) {
1124 TALLOC_FREE(newreq);
1125 return NULL;
1127 newreq->out.vector = outvec;
1128 newreq->out.vector_count = count;
1130 /* Setup the outvec's identically to req. */
1131 outvec[0].iov_base = newreq->out.nbt_hdr;
1132 outvec[0].iov_len = 4;
1133 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1135 /* Setup the vectors identically to the ones in req. */
1136 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1137 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1138 break;
1142 if (i < count) {
1143 /* Alloc failed. */
1144 TALLOC_FREE(newreq);
1145 return NULL;
1148 smb2_setup_nbt_length(newreq->out.vector,
1149 newreq->out.vector_count);
1151 return newreq;
1154 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
1156 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1158 struct smbXsrv_connection *conn = req->sconn->conn;
1159 int first_idx = 1;
1160 struct iovec *firsttf = NULL;
1161 struct iovec *outhdr_v = NULL;
1162 uint8_t *outhdr = NULL;
1163 struct smbd_smb2_request *nreq = NULL;
1164 NTSTATUS status;
1166 /* Create a new smb2 request we'll use
1167 for the interim return. */
1168 nreq = dup_smb2_req(req);
1169 if (!nreq) {
1170 return NT_STATUS_NO_MEMORY;
1173 /* Lose the last X out vectors. They're the
1174 ones we'll be using for the async reply. */
1175 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1177 smb2_setup_nbt_length(nreq->out.vector,
1178 nreq->out.vector_count);
1180 /* Step back to the previous reply. */
1181 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1182 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1183 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1184 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1185 /* And end the chain. */
1186 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1188 /* Calculate outgoing credits */
1189 smb2_calculate_credits(req, nreq);
1191 if (DEBUGLEVEL >= 10) {
1192 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1193 (unsigned int)nreq->current_idx );
1194 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1195 (unsigned int)nreq->out.vector_count );
1196 print_req_vectors(nreq);
1200 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1201 * we need to sign/encrypt here with the last/first key we remembered
1203 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1204 status = smb2_signing_encrypt_pdu(req->first_key,
1205 conn->protocol,
1206 firsttf,
1207 nreq->out.vector_count - first_idx);
1208 if (!NT_STATUS_IS_OK(status)) {
1209 return status;
1211 } else if (req->last_key.length > 0) {
1212 status = smb2_signing_sign_pdu(req->last_key,
1213 conn->protocol,
1214 outhdr_v,
1215 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1216 if (!NT_STATUS_IS_OK(status)) {
1217 return status;
1221 nreq->subreq = tstream_writev_queue_send(nreq,
1222 nreq->sconn->ev_ctx,
1223 nreq->sconn->smb2.stream,
1224 nreq->sconn->smb2.send_queue,
1225 nreq->out.vector,
1226 nreq->out.vector_count);
1228 if (nreq->subreq == NULL) {
1229 return NT_STATUS_NO_MEMORY;
1232 tevent_req_set_callback(nreq->subreq,
1233 smbd_smb2_request_writev_done,
1234 nreq);
1236 return NT_STATUS_OK;
1239 struct smbd_smb2_request_pending_state {
1240 struct smbd_server_connection *sconn;
1241 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1242 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1245 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
1247 struct smbd_smb2_request_pending_state *state =
1248 tevent_req_callback_data(subreq,
1249 struct smbd_smb2_request_pending_state);
1250 struct smbd_server_connection *sconn = state->sconn;
1251 int ret;
1252 int sys_errno;
1254 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1255 TALLOC_FREE(subreq);
1256 if (ret == -1) {
1257 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1258 smbd_server_connection_terminate(sconn, nt_errstr(status));
1259 return;
1262 TALLOC_FREE(state);
1265 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1266 struct tevent_timer *te,
1267 struct timeval current_time,
1268 void *private_data);
1270 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1271 struct tevent_req *subreq,
1272 uint32_t defer_time)
1274 NTSTATUS status;
1275 int idx = req->current_idx;
1276 struct timeval defer_endtime;
1277 uint8_t *outhdr = NULL;
1278 uint32_t flags;
1280 if (!tevent_req_is_in_progress(subreq)) {
1281 return NT_STATUS_OK;
1284 req->subreq = subreq;
1285 subreq = NULL;
1287 if (req->async_te) {
1288 /* We're already async. */
1289 return NT_STATUS_OK;
1292 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1293 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1294 if (flags & SMB2_HDR_FLAG_ASYNC) {
1295 /* We're already async. */
1296 return NT_STATUS_OK;
1299 if (req->in.vector_count > idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1301 * We're trying to go async in a compound
1302 * request chain. This is not allowed.
1303 * Cancel the outstanding request.
1305 bool ok = tevent_req_cancel(req->subreq);
1306 if (ok) {
1307 return NT_STATUS_OK;
1309 TALLOC_FREE(req->subreq);
1310 return smbd_smb2_request_error(req,
1311 NT_STATUS_INTERNAL_ERROR);
1314 if (DEBUGLEVEL >= 10) {
1315 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1316 (unsigned int)req->current_idx );
1317 print_req_vectors(req);
1320 if (req->out.vector_count >= (2*SMBD_SMB2_NUM_IOV_PER_REQ)) {
1322 * This is a compound reply. We
1323 * must do an interim response
1324 * followed by the async response
1325 * to match W2K8R2.
1327 status = smb2_send_async_interim_response(req);
1328 if (!NT_STATUS_IS_OK(status)) {
1329 return status;
1331 data_blob_clear_free(&req->first_key);
1334 * We're splitting off the last SMB2
1335 * request in a compound set, and the
1336 * smb2_send_async_interim_response()
1337 * call above just sent all the replies
1338 * for the previous SMB2 requests in
1339 * this compound set. So we're no longer
1340 * in the "compound_related_in_progress"
1341 * state, and this is no longer a compound
1342 * request.
1344 req->compound_related = false;
1345 req->sconn->smb2.compound_related_in_progress = false;
1347 req->current_idx = 1;
1349 /* Re-arrange the in.vectors. */
1350 memmove(&req->in.vector[req->current_idx],
1351 &req->in.vector[idx],
1352 sizeof(req->in.vector[0])*SMBD_SMB2_NUM_IOV_PER_REQ);
1353 req->in.vector_count = req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ;
1355 /* Re-arrange the out.vectors. */
1356 memmove(&req->out.vector[req->current_idx],
1357 &req->out.vector[idx],
1358 sizeof(req->out.vector[0])*SMBD_SMB2_NUM_IOV_PER_REQ);
1359 req->out.vector_count = req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ;
1361 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1362 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1363 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1365 data_blob_clear_free(&req->last_key);
1367 defer_endtime = timeval_current_ofs_usec(defer_time);
1368 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1369 req, defer_endtime,
1370 smbd_smb2_request_pending_timer,
1371 req);
1372 if (req->async_te == NULL) {
1373 return NT_STATUS_NO_MEMORY;
1376 return NT_STATUS_OK;
1379 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1380 struct tevent_timer *te,
1381 struct timeval current_time,
1382 void *private_data)
1384 struct smbd_smb2_request *req =
1385 talloc_get_type_abort(private_data,
1386 struct smbd_smb2_request);
1387 struct smbd_smb2_request_pending_state *state = NULL;
1388 uint8_t *outhdr = NULL;
1389 const uint8_t *inhdr = NULL;
1390 uint8_t *tf = NULL;
1391 size_t tf_len = 0;
1392 uint8_t *hdr = NULL;
1393 uint8_t *body = NULL;
1394 uint8_t *dyn = NULL;
1395 uint32_t flags = 0;
1396 uint64_t session_id = 0;
1397 uint64_t message_id = 0;
1398 uint64_t nonce_high = 0;
1399 uint64_t nonce_low = 0;
1400 uint64_t async_id = 0;
1401 struct tevent_req *subreq = NULL;
1403 TALLOC_FREE(req->async_te);
1405 /* Ensure our final reply matches the interim one. */
1406 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1407 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1408 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1409 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1410 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1412 async_id = message_id; /* keep it simple for now... */
1414 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1415 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1417 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1418 "going async\n",
1419 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1420 (unsigned long long)async_id ));
1423 * What we send is identical to a smbd_smb2_request_error
1424 * packet with an error status of STATUS_PENDING. Make use
1425 * of this fact sometime when refactoring. JRA.
1428 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1429 if (state == NULL) {
1430 smbd_server_connection_terminate(req->sconn,
1431 nt_errstr(NT_STATUS_NO_MEMORY));
1432 return;
1434 state->sconn = req->sconn;
1436 tf = state->buf + NBT_HDR_SIZE;
1437 tf_len = SMB2_TF_HDR_SIZE;
1439 hdr = tf + SMB2_TF_HDR_SIZE;
1440 body = hdr + SMB2_HDR_BODY;
1441 dyn = body + 8;
1443 if (req->do_encryption) {
1444 struct smbXsrv_session *x = req->session;
1446 nonce_high = x->nonce_high;
1447 nonce_low = x->nonce_low;
1449 x->nonce_low += 1;
1450 if (x->nonce_low == 0) {
1451 x->nonce_low += 1;
1452 x->nonce_high += 1;
1456 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1457 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1458 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1459 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1461 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1462 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1463 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1464 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1465 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1467 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1468 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1469 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1470 SBVAL(hdr, SMB2_HDR_PID, async_id);
1471 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1472 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1473 memcpy(hdr+SMB2_HDR_SIGNATURE,
1474 outhdr+SMB2_HDR_SIGNATURE, 16);
1476 SSVAL(body, 0x00, 0x08 + 1);
1478 SCVAL(body, 0x02, 0);
1479 SCVAL(body, 0x03, 0);
1480 SIVAL(body, 0x04, 0);
1481 /* Match W2K8R2... */
1482 SCVAL(dyn, 0x00, 0x21);
1484 state->vector[0].iov_base = (void *)state->buf;
1485 state->vector[0].iov_len = NBT_HDR_SIZE;
1487 if (req->do_encryption) {
1488 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1489 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1490 } else {
1491 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1492 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1495 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1496 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1498 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1499 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1501 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1502 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1504 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1506 /* Ensure we correctly go through crediting. Grant
1507 the credits now, and zero credits on the final
1508 response. */
1509 smb2_set_operation_credit(req->sconn,
1510 SMBD_SMB2_IN_HDR_IOV(req),
1511 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1513 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1515 if (DEBUGLVL(10)) {
1516 int i;
1518 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1519 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1520 (unsigned int)i,
1521 (unsigned int)ARRAY_SIZE(state->vector),
1522 (unsigned int)state->vector[i].iov_len);
1526 if (req->do_encryption) {
1527 NTSTATUS status;
1528 struct smbXsrv_session *x = req->session;
1529 struct smbXsrv_connection *conn = x->connection;
1530 DATA_BLOB encryption_key = x->global->encryption_key;
1532 status = smb2_signing_encrypt_pdu(encryption_key,
1533 conn->protocol,
1534 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1535 SMBD_SMB2_NUM_IOV_PER_REQ);
1536 if (!NT_STATUS_IS_OK(status)) {
1537 smbd_server_connection_terminate(req->sconn,
1538 nt_errstr(status));
1539 return;
1541 } else if (req->do_signing) {
1542 NTSTATUS status;
1543 struct smbXsrv_session *x = req->session;
1544 struct smbXsrv_connection *conn = x->connection;
1545 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1547 status = smb2_signing_sign_pdu(signing_key,
1548 conn->protocol,
1549 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1550 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1551 if (!NT_STATUS_IS_OK(status)) {
1552 smbd_server_connection_terminate(req->sconn,
1553 nt_errstr(status));
1554 return;
1558 subreq = tstream_writev_queue_send(state,
1559 state->sconn->ev_ctx,
1560 state->sconn->smb2.stream,
1561 state->sconn->smb2.send_queue,
1562 state->vector,
1563 ARRAY_SIZE(state->vector));
1564 if (subreq == NULL) {
1565 smbd_server_connection_terminate(state->sconn,
1566 nt_errstr(NT_STATUS_NO_MEMORY));
1567 return;
1569 tevent_req_set_callback(subreq,
1570 smbd_smb2_request_pending_writev_done,
1571 state);
1574 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1576 struct smbd_server_connection *sconn = req->sconn;
1577 struct smbd_smb2_request *cur;
1578 const uint8_t *inhdr;
1579 uint32_t flags;
1580 uint64_t search_message_id;
1581 uint64_t search_async_id;
1582 uint64_t found_id;
1584 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1586 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1587 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1588 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1591 * we don't need the request anymore
1592 * cancel requests never have a response
1594 DLIST_REMOVE(req->sconn->smb2.requests, req);
1595 TALLOC_FREE(req);
1597 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1598 const uint8_t *outhdr;
1599 uint64_t message_id;
1600 uint64_t async_id;
1602 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1604 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1605 async_id = BVAL(outhdr, SMB2_HDR_PID);
1607 if (flags & SMB2_HDR_FLAG_ASYNC) {
1608 if (search_async_id == async_id) {
1609 found_id = async_id;
1610 break;
1612 } else {
1613 if (search_message_id == message_id) {
1614 found_id = message_id;
1615 break;
1620 if (cur && cur->subreq) {
1621 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1622 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1623 "cancel opcode[%s] mid %llu\n",
1624 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1625 (unsigned long long)found_id ));
1626 tevent_req_cancel(cur->subreq);
1629 return NT_STATUS_OK;
1632 /*************************************************************
1633 Ensure an incoming tid is a valid one for us to access.
1634 Change to the associated uid credentials and chdir to the
1635 valid tid directory.
1636 *************************************************************/
1638 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1640 const uint8_t *inhdr;
1641 uint32_t in_flags;
1642 uint32_t in_tid;
1643 struct smbXsrv_tcon *tcon;
1644 NTSTATUS status;
1645 NTTIME now = timeval_to_nttime(&req->request_time);
1647 req->tcon = NULL;
1649 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1651 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1652 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1654 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1655 in_tid = req->last_tid;
1658 req->last_tid = 0;
1660 status = smb2srv_tcon_lookup(req->session,
1661 in_tid, now, &tcon);
1662 if (!NT_STATUS_IS_OK(status)) {
1663 return status;
1666 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1667 return NT_STATUS_ACCESS_DENIED;
1670 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1671 if (!set_current_service(tcon->compat, 0, true)) {
1672 return NT_STATUS_ACCESS_DENIED;
1675 req->tcon = tcon;
1676 req->last_tid = in_tid;
1678 return NT_STATUS_OK;
1681 /*************************************************************
1682 Ensure an incoming session_id is a valid one for us to access.
1683 *************************************************************/
1685 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1687 const uint8_t *inhdr;
1688 uint32_t in_flags;
1689 uint16_t in_opcode;
1690 uint64_t in_session_id;
1691 struct smbXsrv_session *session = NULL;
1692 struct auth_session_info *session_info;
1693 NTSTATUS status;
1694 NTTIME now = timeval_to_nttime(&req->request_time);
1696 req->session = NULL;
1697 req->tcon = NULL;
1699 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1701 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1702 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1703 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1705 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1706 in_session_id = req->last_session_id;
1709 req->last_session_id = 0;
1711 /* lookup an existing session */
1712 status = smb2srv_session_lookup(req->sconn->conn,
1713 in_session_id, now,
1714 &session);
1715 if (session) {
1716 req->session = session;
1717 req->last_session_id = in_session_id;
1719 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1720 switch (in_opcode) {
1721 case SMB2_OP_SESSSETUP:
1722 status = NT_STATUS_OK;
1723 break;
1724 default:
1725 break;
1728 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1729 switch (in_opcode) {
1730 case SMB2_OP_TCON:
1731 case SMB2_OP_CREATE:
1732 case SMB2_OP_GETINFO:
1733 case SMB2_OP_SETINFO:
1734 return NT_STATUS_INVALID_HANDLE;
1735 default:
1737 * Notice the check for
1738 * (session_info == NULL)
1739 * below.
1741 status = NT_STATUS_OK;
1742 break;
1745 if (!NT_STATUS_IS_OK(status)) {
1746 return status;
1749 session_info = session->global->auth_session_info;
1750 if (session_info == NULL) {
1751 return NT_STATUS_INVALID_HANDLE;
1754 set_current_user_info(session_info->unix_info->sanitized_username,
1755 session_info->unix_info->unix_name,
1756 session_info->info->domain_name);
1758 return NT_STATUS_OK;
1761 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1762 uint32_t data_length)
1764 uint16_t needed_charge;
1765 uint16_t credit_charge = 1;
1766 const uint8_t *inhdr;
1768 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1770 if (req->sconn->smb2.supports_multicredit) {
1771 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1772 credit_charge = MAX(credit_charge, 1);
1775 needed_charge = (data_length - 1)/ 65536 + 1;
1777 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1778 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1779 credit_charge, needed_charge));
1781 if (needed_charge > credit_charge) {
1782 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1783 credit_charge, needed_charge));
1784 return NT_STATUS_INVALID_PARAMETER;
1787 return NT_STATUS_OK;
1790 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1791 size_t expected_body_size)
1793 struct iovec *inhdr_v;
1794 const uint8_t *inhdr;
1795 uint16_t opcode;
1796 const uint8_t *inbody;
1797 size_t body_size;
1798 size_t min_dyn_size = expected_body_size & 0x00000001;
1799 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1802 * The following should be checked already.
1804 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1805 return NT_STATUS_INTERNAL_ERROR;
1807 if (req->current_idx > max_idx) {
1808 return NT_STATUS_INTERNAL_ERROR;
1811 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1812 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1813 return NT_STATUS_INTERNAL_ERROR;
1815 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1816 return NT_STATUS_INTERNAL_ERROR;
1819 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1820 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1822 switch (opcode) {
1823 case SMB2_OP_IOCTL:
1824 case SMB2_OP_GETINFO:
1825 min_dyn_size = 0;
1826 break;
1830 * Now check the expected body size,
1831 * where the last byte might be in the
1832 * dynamic section..
1834 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1835 return NT_STATUS_INVALID_PARAMETER;
1837 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1838 return NT_STATUS_INVALID_PARAMETER;
1841 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1843 body_size = SVAL(inbody, 0x00);
1844 if (body_size != expected_body_size) {
1845 return NT_STATUS_INVALID_PARAMETER;
1848 return NT_STATUS_OK;
1851 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1853 struct smbXsrv_connection *conn = req->sconn->conn;
1854 const struct smbd_smb2_dispatch_table *call = NULL;
1855 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1856 const uint8_t *inhdr;
1857 uint16_t opcode;
1858 uint32_t flags;
1859 uint64_t mid;
1860 NTSTATUS status;
1861 NTSTATUS session_status;
1862 uint32_t allowed_flags;
1863 NTSTATUS return_value;
1864 struct smbXsrv_session *x = NULL;
1865 bool signing_required = false;
1866 bool encryption_required = false;
1868 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1870 /* TODO: verify more things */
1872 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1873 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1874 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1875 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1876 smb2_opcode_name(opcode),
1877 (unsigned long long)mid));
1879 if (conn->protocol >= PROTOCOL_SMB2_02) {
1881 * once the protocol is negotiated
1882 * SMB2_OP_NEGPROT is not allowed anymore
1884 if (opcode == SMB2_OP_NEGPROT) {
1885 /* drop the connection */
1886 return NT_STATUS_INVALID_PARAMETER;
1888 } else {
1890 * if the protocol is not negotiated yet
1891 * only SMB2_OP_NEGPROT is allowed.
1893 if (opcode != SMB2_OP_NEGPROT) {
1894 /* drop the connection */
1895 return NT_STATUS_INVALID_PARAMETER;
1900 * Check if the client provided a valid session id,
1901 * if so smbd_smb2_request_check_session() calls
1902 * set_current_user_info().
1904 * As some command don't require a valid session id
1905 * we defer the check of the session_status
1907 session_status = smbd_smb2_request_check_session(req);
1908 x = req->session;
1909 if (x != NULL) {
1910 signing_required = x->global->signing_required;
1911 encryption_required = x->global->encryption_required;
1913 if (opcode == SMB2_OP_SESSSETUP &&
1914 x->global->channels[0].signing_key.length) {
1915 signing_required = true;
1919 req->do_signing = false;
1920 req->do_encryption = false;
1921 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
1922 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
1923 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
1925 if (x != NULL && x->global->session_wire_id != tf_session_id) {
1926 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1927 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1928 (unsigned long long)x->global->session_wire_id,
1929 (unsigned long long)tf_session_id));
1931 * TODO: windows allows this...
1932 * should we drop the connection?
1934 * For now we just return ACCESS_DENIED
1935 * (Windows clients never trigger this)
1936 * and wait for an update of [MS-SMB2].
1938 return smbd_smb2_request_error(req,
1939 NT_STATUS_ACCESS_DENIED);
1942 req->do_encryption = true;
1945 if (encryption_required && !req->do_encryption) {
1946 return smbd_smb2_request_error(req,
1947 NT_STATUS_ACCESS_DENIED);
1950 call = smbd_smb2_call(opcode);
1951 if (call == NULL) {
1952 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1955 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1956 SMB2_HDR_FLAG_SIGNED |
1957 SMB2_HDR_FLAG_DFS;
1958 if (opcode == SMB2_OP_CANCEL) {
1959 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1961 if ((flags & ~allowed_flags) != 0) {
1962 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1965 if (flags & SMB2_HDR_FLAG_CHAINED) {
1967 * This check is mostly for giving the correct error code
1968 * for compounded requests.
1970 if (!NT_STATUS_IS_OK(session_status)) {
1971 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1973 } else {
1974 req->compat_chain_fsp = NULL;
1977 if (req->do_encryption) {
1978 signing_required = false;
1979 } else if (flags & SMB2_HDR_FLAG_SIGNED) {
1980 DATA_BLOB signing_key;
1982 if (x == NULL) {
1983 return smbd_smb2_request_error(
1984 req, NT_STATUS_ACCESS_DENIED);
1987 signing_key = x->global->channels[0].signing_key;
1990 * If we have a signing key, we should
1991 * sign the response
1993 if (signing_key.length > 0) {
1994 req->do_signing = true;
1997 status = smb2_signing_check_pdu(signing_key,
1998 conn->protocol,
1999 SMBD_SMB2_IN_HDR_IOV(req),
2000 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2001 if (!NT_STATUS_IS_OK(status)) {
2002 return smbd_smb2_request_error(req, status);
2006 * Now that we know the request was correctly signed
2007 * we have to sign the response too.
2009 req->do_signing = true;
2011 if (!NT_STATUS_IS_OK(session_status)) {
2012 return smbd_smb2_request_error(req, session_status);
2014 } else if (opcode == SMB2_OP_CANCEL) {
2015 /* Cancel requests are allowed to skip the signing */
2016 } else if (signing_required) {
2018 * If signing is required we try to sign
2019 * a possible error response
2021 req->do_signing = true;
2022 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2025 if (flags & SMB2_HDR_FLAG_CHAINED) {
2026 req->compound_related = true;
2027 req->sconn->smb2.compound_related_in_progress = true;
2030 if (call->need_session) {
2031 if (!NT_STATUS_IS_OK(session_status)) {
2032 return smbd_smb2_request_error(req, session_status);
2036 if (call->need_tcon) {
2037 SMB_ASSERT(call->need_session);
2040 * This call needs to be run as user.
2042 * smbd_smb2_request_check_tcon()
2043 * calls change_to_user() on success.
2045 status = smbd_smb2_request_check_tcon(req);
2046 if (!NT_STATUS_IS_OK(status)) {
2047 return smbd_smb2_request_error(req, status);
2049 if (req->tcon->global->encryption_required) {
2050 encryption_required = true;
2052 if (encryption_required && !req->do_encryption) {
2053 return smbd_smb2_request_error(req,
2054 NT_STATUS_ACCESS_DENIED);
2058 if (call->fileid_ofs != 0) {
2059 size_t needed = call->fileid_ofs + 16;
2060 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2061 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2062 uint64_t file_id_persistent;
2063 uint64_t file_id_volatile;
2064 struct files_struct *fsp;
2066 SMB_ASSERT(call->need_tcon);
2068 if (needed > body_size) {
2069 return smbd_smb2_request_error(req,
2070 NT_STATUS_INVALID_PARAMETER);
2073 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2074 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2076 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2077 if (fsp == NULL) {
2078 if (!call->allow_invalid_fileid) {
2079 return smbd_smb2_request_error(req,
2080 NT_STATUS_FILE_CLOSED);
2083 if (file_id_persistent != UINT64_MAX) {
2084 return smbd_smb2_request_error(req,
2085 NT_STATUS_FILE_CLOSED);
2087 if (file_id_volatile != UINT64_MAX) {
2088 return smbd_smb2_request_error(req,
2089 NT_STATUS_FILE_CLOSED);
2094 if (call->as_root) {
2095 SMB_ASSERT(call->fileid_ofs == 0);
2096 /* This call needs to be run as root */
2097 change_to_root_user();
2098 } else {
2099 SMB_ASSERT(call->need_tcon);
2102 switch (opcode) {
2103 case SMB2_OP_NEGPROT:
2105 START_PROFILE(smb2_negprot);
2106 return_value = smbd_smb2_request_process_negprot(req);
2107 END_PROFILE(smb2_negprot);
2109 break;
2111 case SMB2_OP_SESSSETUP:
2113 START_PROFILE(smb2_sesssetup);
2114 return_value = smbd_smb2_request_process_sesssetup(req);
2115 END_PROFILE(smb2_sesssetup);
2117 break;
2119 case SMB2_OP_LOGOFF:
2121 START_PROFILE(smb2_logoff);
2122 return_value = smbd_smb2_request_process_logoff(req);
2123 END_PROFILE(smb2_logoff);
2125 break;
2127 case SMB2_OP_TCON:
2129 START_PROFILE(smb2_tcon);
2130 return_value = smbd_smb2_request_process_tcon(req);
2131 END_PROFILE(smb2_tcon);
2133 break;
2135 case SMB2_OP_TDIS:
2137 START_PROFILE(smb2_tdis);
2138 return_value = smbd_smb2_request_process_tdis(req);
2139 END_PROFILE(smb2_tdis);
2141 break;
2143 case SMB2_OP_CREATE:
2145 START_PROFILE(smb2_create);
2146 return_value = smbd_smb2_request_process_create(req);
2147 END_PROFILE(smb2_create);
2149 break;
2151 case SMB2_OP_CLOSE:
2153 START_PROFILE(smb2_close);
2154 return_value = smbd_smb2_request_process_close(req);
2155 END_PROFILE(smb2_close);
2157 break;
2159 case SMB2_OP_FLUSH:
2161 START_PROFILE(smb2_flush);
2162 return_value = smbd_smb2_request_process_flush(req);
2163 END_PROFILE(smb2_flush);
2165 break;
2167 case SMB2_OP_READ:
2169 START_PROFILE(smb2_read);
2170 return_value = smbd_smb2_request_process_read(req);
2171 END_PROFILE(smb2_read);
2173 break;
2175 case SMB2_OP_WRITE:
2177 START_PROFILE(smb2_write);
2178 return_value = smbd_smb2_request_process_write(req);
2179 END_PROFILE(smb2_write);
2181 break;
2183 case SMB2_OP_LOCK:
2185 START_PROFILE(smb2_lock);
2186 return_value = smbd_smb2_request_process_lock(req);
2187 END_PROFILE(smb2_lock);
2189 break;
2191 case SMB2_OP_IOCTL:
2193 START_PROFILE(smb2_ioctl);
2194 return_value = smbd_smb2_request_process_ioctl(req);
2195 END_PROFILE(smb2_ioctl);
2197 break;
2199 case SMB2_OP_CANCEL:
2201 START_PROFILE(smb2_cancel);
2202 return_value = smbd_smb2_request_process_cancel(req);
2203 END_PROFILE(smb2_cancel);
2205 break;
2207 case SMB2_OP_KEEPALIVE:
2209 START_PROFILE(smb2_keepalive);
2210 return_value = smbd_smb2_request_process_keepalive(req);
2211 END_PROFILE(smb2_keepalive);
2213 break;
2215 case SMB2_OP_FIND:
2217 START_PROFILE(smb2_find);
2218 return_value = smbd_smb2_request_process_find(req);
2219 END_PROFILE(smb2_find);
2221 break;
2223 case SMB2_OP_NOTIFY:
2225 START_PROFILE(smb2_notify);
2226 return_value = smbd_smb2_request_process_notify(req);
2227 END_PROFILE(smb2_notify);
2229 break;
2231 case SMB2_OP_GETINFO:
2233 START_PROFILE(smb2_getinfo);
2234 return_value = smbd_smb2_request_process_getinfo(req);
2235 END_PROFILE(smb2_getinfo);
2237 break;
2239 case SMB2_OP_SETINFO:
2241 START_PROFILE(smb2_setinfo);
2242 return_value = smbd_smb2_request_process_setinfo(req);
2243 END_PROFILE(smb2_setinfo);
2245 break;
2247 case SMB2_OP_BREAK:
2249 START_PROFILE(smb2_break);
2250 return_value = smbd_smb2_request_process_break(req);
2251 END_PROFILE(smb2_break);
2253 break;
2255 default:
2256 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2257 break;
2259 return return_value;
2262 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2264 struct smbXsrv_connection *conn = req->sconn->conn;
2265 struct tevent_req *subreq;
2266 int first_idx = 1;
2267 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2268 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2269 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2271 req->subreq = NULL;
2272 TALLOC_FREE(req->async_te);
2274 if (req->do_encryption &&
2275 (firsttf->iov_len == 0) &&
2276 (req->first_key.length == 0) &&
2277 (req->session != NULL) &&
2278 (req->session->global->encryption_key.length != 0))
2280 DATA_BLOB encryption_key = req->session->global->encryption_key;
2281 uint8_t *tf;
2282 uint64_t session_id = req->session->global->session_wire_id;
2283 struct smbXsrv_session *x = req->session;
2284 uint64_t nonce_high;
2285 uint64_t nonce_low;
2287 nonce_high = x->nonce_high;
2288 nonce_low = x->nonce_low;
2290 x->nonce_low += 1;
2291 if (x->nonce_low == 0) {
2292 x->nonce_low += 1;
2293 x->nonce_high += 1;
2297 * We need to place the SMB2_TRANSFORM header before the
2298 * first SMB2 header
2302 * we need to remember the encryption key
2303 * and defer the signing/encryption until
2304 * we are sure that we do not change
2305 * the header again.
2307 req->first_key = data_blob_dup_talloc(req, encryption_key);
2308 if (req->first_key.data == NULL) {
2309 return NT_STATUS_NO_MEMORY;
2312 tf = talloc_zero_array(req->out.vector, uint8_t,
2313 SMB2_TF_HDR_SIZE);
2314 if (tf == NULL) {
2315 return NT_STATUS_NO_MEMORY;
2318 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2319 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2320 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2321 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2323 firsttf->iov_base = (void *)tf;
2324 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2327 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2328 (req->last_key.length > 0) &&
2329 (firsttf->iov_len == 0))
2331 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2332 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2333 NTSTATUS status;
2336 * As we are sure the header of the last request in the
2337 * compound chain will not change, we can to sign here
2338 * with the last signing key we remembered.
2340 status = smb2_signing_sign_pdu(req->last_key,
2341 conn->protocol,
2342 lasthdr,
2343 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2344 if (!NT_STATUS_IS_OK(status)) {
2345 return status;
2348 data_blob_clear_free(&req->last_key);
2350 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2352 if (req->current_idx < req->out.vector_count) {
2354 * We must process the remaining compound
2355 * SMB2 requests before any new incoming SMB2
2356 * requests. This is because incoming SMB2
2357 * requests may include a cancel for a
2358 * compound request we haven't processed
2359 * yet.
2361 struct tevent_immediate *im = tevent_create_immediate(req);
2362 if (!im) {
2363 return NT_STATUS_NO_MEMORY;
2366 if (req->do_signing && firsttf->iov_len == 0) {
2367 struct smbXsrv_session *x = req->session;
2368 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2371 * we need to remember the signing key
2372 * and defer the signing until
2373 * we are sure that we do not change
2374 * the header again.
2376 req->last_key = data_blob_dup_talloc(req, signing_key);
2377 if (req->last_key.data == NULL) {
2378 return NT_STATUS_NO_MEMORY;
2382 tevent_schedule_immediate(im,
2383 req->sconn->ev_ctx,
2384 smbd_smb2_request_dispatch_immediate,
2385 req);
2386 return NT_STATUS_OK;
2389 if (req->compound_related) {
2390 req->compound_related = false;
2391 req->sconn->smb2.compound_related_in_progress = false;
2394 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2396 /* Set credit for these operations (zero credits if this
2397 is a final reply for an async operation). */
2398 smb2_calculate_credits(req, req);
2401 * now check if we need to sign the current response
2403 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2404 NTSTATUS status;
2406 status = smb2_signing_encrypt_pdu(req->first_key,
2407 conn->protocol,
2408 firsttf,
2409 req->out.vector_count - first_idx);
2410 if (!NT_STATUS_IS_OK(status)) {
2411 return status;
2413 } else if (req->do_signing) {
2414 NTSTATUS status;
2415 struct smbXsrv_session *x = req->session;
2416 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2418 status = smb2_signing_sign_pdu(signing_key,
2419 conn->protocol,
2420 outhdr,
2421 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2422 if (!NT_STATUS_IS_OK(status)) {
2423 return status;
2426 data_blob_clear_free(&req->first_key);
2428 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2429 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2430 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2431 /* Dynamic part is NULL. Chop it off,
2432 We're going to send it via sendfile. */
2433 req->out.vector_count -= 1;
2436 subreq = tstream_writev_queue_send(req,
2437 req->sconn->ev_ctx,
2438 req->sconn->smb2.stream,
2439 req->sconn->smb2.send_queue,
2440 req->out.vector,
2441 req->out.vector_count);
2442 if (subreq == NULL) {
2443 return NT_STATUS_NO_MEMORY;
2445 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
2447 * We're done with this request -
2448 * move it off the "being processed" queue.
2450 DLIST_REMOVE(req->sconn->smb2.requests, req);
2452 return NT_STATUS_OK;
2455 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2457 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2458 struct tevent_immediate *im,
2459 void *private_data)
2461 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2462 struct smbd_smb2_request);
2463 struct smbd_server_connection *sconn = req->sconn;
2464 NTSTATUS status;
2466 TALLOC_FREE(im);
2468 if (DEBUGLEVEL >= 10) {
2469 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2470 req->current_idx, req->in.vector_count));
2471 print_req_vectors(req);
2474 status = smbd_smb2_request_dispatch(req);
2475 if (!NT_STATUS_IS_OK(status)) {
2476 smbd_server_connection_terminate(sconn, nt_errstr(status));
2477 return;
2480 status = smbd_smb2_request_next_incoming(sconn);
2481 if (!NT_STATUS_IS_OK(status)) {
2482 smbd_server_connection_terminate(sconn, nt_errstr(status));
2483 return;
2487 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
2489 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
2490 struct smbd_smb2_request);
2491 struct smbd_server_connection *sconn = req->sconn;
2492 int ret;
2493 int sys_errno;
2494 NTSTATUS status;
2496 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2497 TALLOC_FREE(subreq);
2498 TALLOC_FREE(req);
2499 if (ret == -1) {
2500 status = map_nt_error_from_unix(sys_errno);
2501 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2502 nt_errstr(status)));
2503 smbd_server_connection_terminate(sconn, nt_errstr(status));
2504 return;
2507 status = smbd_smb2_request_next_incoming(sconn);
2508 if (!NT_STATUS_IS_OK(status)) {
2509 smbd_server_connection_terminate(sconn, nt_errstr(status));
2510 return;
2514 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2515 NTSTATUS status,
2516 DATA_BLOB body, DATA_BLOB *dyn,
2517 const char *location)
2519 uint8_t *outhdr;
2520 struct iovec *outbody_v;
2521 struct iovec *outdyn_v;
2522 uint32_t next_command_ofs;
2524 DEBUG(10,("smbd_smb2_request_done_ex: "
2525 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2526 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2527 dyn ? "yes": "no",
2528 (unsigned int)(dyn ? dyn->length : 0),
2529 location));
2531 if (body.length < 2) {
2532 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2535 if ((body.length % 2) != 0) {
2536 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2539 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2540 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2541 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2543 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2544 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2546 outbody_v->iov_base = (void *)body.data;
2547 outbody_v->iov_len = body.length;
2549 if (dyn) {
2550 outdyn_v->iov_base = (void *)dyn->data;
2551 outdyn_v->iov_len = dyn->length;
2552 } else {
2553 outdyn_v->iov_base = NULL;
2554 outdyn_v->iov_len = 0;
2557 /* see if we need to recalculate the offset to the next response */
2558 if (next_command_ofs > 0) {
2559 next_command_ofs = SMB2_HDR_BODY;
2560 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2561 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2564 if ((next_command_ofs % 8) != 0) {
2565 size_t pad_size = 8 - (next_command_ofs % 8);
2566 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2568 * if the dyn buffer is empty
2569 * we can use it to add padding
2571 uint8_t *pad;
2573 pad = talloc_zero_array(req->out.vector,
2574 uint8_t, pad_size);
2575 if (pad == NULL) {
2576 return smbd_smb2_request_error(req,
2577 NT_STATUS_NO_MEMORY);
2580 outdyn_v->iov_base = (void *)pad;
2581 outdyn_v->iov_len = pad_size;
2582 } else {
2584 * For now we copy the dynamic buffer
2585 * and add the padding to the new buffer
2587 size_t old_size;
2588 uint8_t *old_dyn;
2589 size_t new_size;
2590 uint8_t *new_dyn;
2592 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2593 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2595 new_size = old_size + pad_size;
2596 new_dyn = talloc_zero_array(req->out.vector,
2597 uint8_t, new_size);
2598 if (new_dyn == NULL) {
2599 return smbd_smb2_request_error(req,
2600 NT_STATUS_NO_MEMORY);
2603 memcpy(new_dyn, old_dyn, old_size);
2604 memset(new_dyn + old_size, 0, pad_size);
2606 outdyn_v->iov_base = (void *)new_dyn;
2607 outdyn_v->iov_len = new_size;
2609 next_command_ofs += pad_size;
2612 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2614 return smbd_smb2_request_reply(req);
2617 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2618 NTSTATUS status,
2619 DATA_BLOB *info,
2620 const char *location)
2622 DATA_BLOB body;
2623 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2624 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2626 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2627 req->current_idx, nt_errstr(status), info ? " +info" : "",
2628 location));
2630 if (unread_bytes) {
2631 /* Recvfile error. Drain incoming socket. */
2632 size_t ret = drain_socket(req->sconn->sock, unread_bytes);
2633 if (ret != unread_bytes) {
2634 smbd_server_connection_terminate(req->sconn,
2635 "Failed to drain SMB2 socket\n");
2639 body.data = outhdr + SMB2_HDR_BODY;
2640 body.length = 8;
2641 SSVAL(body.data, 0, 9);
2643 if (info) {
2644 SIVAL(body.data, 0x04, info->length);
2645 } else {
2646 /* Allocated size of req->out.vector[i].iov_base
2647 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2648 * 1 byte without having to do an alloc.
2650 info = talloc_zero_array(req->out.vector,
2651 DATA_BLOB,
2653 if (!info) {
2654 return NT_STATUS_NO_MEMORY;
2656 info->data = ((uint8_t *)outhdr) +
2657 OUTVEC_ALLOC_SIZE - 1;
2658 info->length = 1;
2659 SCVAL(info->data, 0, 0);
2663 * Note: Even if there is an error, continue to process the request.
2664 * per MS-SMB2.
2667 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2671 struct smbd_smb2_send_oplock_break_state {
2672 struct smbd_server_connection *sconn;
2673 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x18];
2674 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2677 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2679 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2680 struct smbXsrv_session *session,
2681 struct smbXsrv_tcon *tcon,
2682 struct smbXsrv_open *op,
2683 uint8_t oplock_level)
2685 struct smbd_smb2_send_oplock_break_state *state;
2686 struct smbXsrv_connection *conn = sconn->conn;
2687 struct tevent_req *subreq;
2688 uint8_t *tf;
2689 size_t tf_len;
2690 uint8_t *hdr;
2691 uint8_t *body;
2692 size_t body_len;
2693 uint8_t *dyn;
2694 size_t dyn_len;
2695 bool do_encryption = session->global->encryption_required;
2696 uint64_t nonce_high = 0;
2697 uint64_t nonce_low = 0;
2699 if (tcon->global->encryption_required) {
2700 do_encryption = true;
2703 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2704 if (state == NULL) {
2705 return NT_STATUS_NO_MEMORY;
2707 state->sconn = sconn;
2709 tf = state->buf + NBT_HDR_SIZE;
2710 tf_len = SMB2_TF_HDR_SIZE;
2711 hdr = tf + tf_len;
2712 body = hdr + SMB2_HDR_BODY;
2713 body_len = 0x18;
2714 dyn = body + body_len;
2715 dyn_len = 0;
2717 if (do_encryption) {
2718 nonce_high = session->nonce_high;
2719 nonce_low = session->nonce_low;
2721 session->nonce_low += 1;
2722 if (session->nonce_low == 0) {
2723 session->nonce_low += 1;
2724 session->nonce_high += 1;
2728 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2729 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2730 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2731 SBVAL(tf, SMB2_TF_SESSION_ID, session->global->session_wire_id);
2733 SIVAL(hdr, 0, SMB2_MAGIC);
2734 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2735 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2736 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2737 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2738 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2739 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2740 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2741 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2742 SIVAL(hdr, SMB2_HDR_PID, 0);
2743 SIVAL(hdr, SMB2_HDR_TID, 0);
2744 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2745 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2747 SSVAL(body, 0x00, body_len);
2749 SCVAL(body, 0x02, oplock_level);
2750 SCVAL(body, 0x03, 0); /* reserved */
2751 SIVAL(body, 0x04, 0); /* reserved */
2752 SBVAL(body, 0x08, op->global->open_persistent_id);
2753 SBVAL(body, 0x10, op->global->open_volatile_id);
2755 state->vector[0].iov_base = (void *)state->buf;
2756 state->vector[0].iov_len = NBT_HDR_SIZE;
2758 if (do_encryption) {
2759 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
2760 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
2761 } else {
2762 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
2763 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
2766 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
2767 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
2769 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
2770 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = body_len;
2772 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
2773 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_len;
2775 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2777 if (do_encryption) {
2778 NTSTATUS status;
2779 DATA_BLOB encryption_key = session->global->encryption_key;
2781 status = smb2_signing_encrypt_pdu(encryption_key,
2782 conn->protocol,
2783 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2784 SMBD_SMB2_NUM_IOV_PER_REQ);
2785 if (!NT_STATUS_IS_OK(status)) {
2786 return status;
2790 subreq = tstream_writev_queue_send(state,
2791 sconn->ev_ctx,
2792 sconn->smb2.stream,
2793 sconn->smb2.send_queue,
2794 state->vector,
2795 ARRAY_SIZE(state->vector));
2796 if (subreq == NULL) {
2797 return NT_STATUS_NO_MEMORY;
2799 tevent_req_set_callback(subreq,
2800 smbd_smb2_oplock_break_writev_done,
2801 state);
2803 return NT_STATUS_OK;
2806 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2808 struct smbd_smb2_send_oplock_break_state *state =
2809 tevent_req_callback_data(subreq,
2810 struct smbd_smb2_send_oplock_break_state);
2811 struct smbd_server_connection *sconn = state->sconn;
2812 int ret;
2813 int sys_errno;
2815 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2816 TALLOC_FREE(subreq);
2817 if (ret == -1) {
2818 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2819 smbd_server_connection_terminate(sconn, nt_errstr(status));
2820 return;
2823 TALLOC_FREE(state);
2826 struct smbd_smb2_request_read_state {
2827 struct tevent_context *ev;
2828 struct smbd_server_connection *sconn;
2829 struct smbd_smb2_request *smb2_req;
2830 struct {
2831 uint8_t nbt[NBT_HDR_SIZE];
2832 bool done;
2833 } hdr;
2834 bool doing_receivefile;
2835 size_t min_recv_size;
2836 size_t pktlen;
2837 uint8_t *pktbuf;
2840 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2841 void *private_data,
2842 TALLOC_CTX *mem_ctx,
2843 struct iovec **_vector,
2844 size_t *_count);
2845 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2847 static size_t get_min_receive_file_size(struct smbd_smb2_request *smb2_req)
2849 if (smb2_req->do_signing) {
2850 return 0;
2852 if (smb2_req->do_encryption) {
2853 return 0;
2855 return (size_t)lp_min_receive_file_size();
2858 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2859 struct tevent_context *ev,
2860 struct smbd_server_connection *sconn)
2862 struct tevent_req *req;
2863 struct smbd_smb2_request_read_state *state;
2864 struct tevent_req *subreq;
2866 req = tevent_req_create(mem_ctx, &state,
2867 struct smbd_smb2_request_read_state);
2868 if (req == NULL) {
2869 return NULL;
2871 state->ev = ev;
2872 state->sconn = sconn;
2874 state->smb2_req = smbd_smb2_request_allocate(state);
2875 if (tevent_req_nomem(state->smb2_req, req)) {
2876 return tevent_req_post(req, ev);
2878 state->smb2_req->sconn = sconn;
2879 state->min_recv_size = get_min_receive_file_size(state->smb2_req);
2881 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
2882 state->ev,
2883 state->sconn->smb2.stream,
2884 state->sconn->smb2.recv_queue,
2885 smbd_smb2_request_next_vector,
2886 state);
2887 if (tevent_req_nomem(subreq, req)) {
2888 return tevent_req_post(req, ev);
2890 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2892 return req;
2895 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2896 void *private_data,
2897 TALLOC_CTX *mem_ctx,
2898 struct iovec **_vector,
2899 size_t *_count)
2901 struct smbd_smb2_request_read_state *state =
2902 talloc_get_type_abort(private_data,
2903 struct smbd_smb2_request_read_state);
2904 struct iovec *vector;
2906 if (state->pktlen > 0) {
2907 /* if there're no remaining bytes, we're done */
2908 *_vector = NULL;
2909 *_count = 0;
2910 return 0;
2913 if (!state->hdr.done) {
2915 * first we need to get the NBT header
2917 vector = talloc_array(mem_ctx, struct iovec, 1);
2918 if (vector == NULL) {
2919 return -1;
2922 vector[0].iov_base = (void *)state->hdr.nbt;
2923 vector[0].iov_len = NBT_HDR_SIZE;
2925 *_vector = vector;
2926 *_count = 1;
2928 state->hdr.done = true;
2929 return 0;
2933 * Now we analyze the NBT header
2935 state->pktlen = smb2_len(state->hdr.nbt);
2937 if (state->pktlen == 0) {
2938 /* if there're no remaining bytes, we're done */
2939 *_vector = NULL;
2940 *_count = 0;
2941 return 0;
2944 state->pktbuf = talloc_array(state->smb2_req, uint8_t, state->pktlen);
2945 if (state->pktbuf == NULL) {
2946 return -1;
2949 vector = talloc_array(mem_ctx, struct iovec, 1);
2950 if (vector == NULL) {
2951 return -1;
2954 vector[0].iov_base = (void *)state->pktbuf;
2955 vector[0].iov_len = state->pktlen;
2957 *_vector = vector;
2958 *_count = 1;
2959 return 0;
2962 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2964 struct tevent_req *req =
2965 tevent_req_callback_data(subreq,
2966 struct tevent_req);
2967 struct smbd_smb2_request_read_state *state =
2968 tevent_req_data(req,
2969 struct smbd_smb2_request_read_state);
2970 int ret;
2971 int sys_errno;
2972 NTSTATUS status;
2973 NTTIME now;
2975 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2976 TALLOC_FREE(subreq);
2977 if (ret == -1) {
2978 status = map_nt_error_from_unix(sys_errno);
2979 tevent_req_nterror(req, status);
2980 return;
2983 if (state->hdr.nbt[0] != 0x00) {
2984 DEBUG(1,("smbd_smb2_request_read_done: ignore NBT[0x%02X] msg\n",
2985 state->hdr.nbt[0]));
2987 ZERO_STRUCT(state->hdr);
2988 TALLOC_FREE(state->pktbuf);
2989 state->pktlen = 0;
2991 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
2992 state->ev,
2993 state->sconn->smb2.stream,
2994 state->sconn->smb2.recv_queue,
2995 smbd_smb2_request_next_vector,
2996 state);
2997 if (tevent_req_nomem(subreq, req)) {
2998 return;
3000 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
3001 return;
3004 state->smb2_req->request_time = timeval_current();
3005 now = timeval_to_nttime(&state->smb2_req->request_time);
3007 status = smbd_smb2_inbuf_parse_compound(state->smb2_req->sconn->conn,
3008 now,
3009 state->pktbuf,
3010 state->pktlen,
3011 state->smb2_req,
3012 &state->smb2_req->in.vector,
3013 &state->smb2_req->in.vector_count);
3014 if (tevent_req_nterror(req, status)) {
3015 return;
3018 state->smb2_req->current_idx = 1;
3020 tevent_req_done(req);
3023 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
3024 TALLOC_CTX *mem_ctx,
3025 struct smbd_smb2_request **_smb2_req)
3027 struct smbd_smb2_request_read_state *state =
3028 tevent_req_data(req,
3029 struct smbd_smb2_request_read_state);
3030 NTSTATUS status;
3032 if (tevent_req_is_nterror(req, &status)) {
3033 tevent_req_received(req);
3034 return status;
3037 *_smb2_req = talloc_move(mem_ctx, &state->smb2_req);
3038 tevent_req_received(req);
3039 return NT_STATUS_OK;
3042 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
3044 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
3046 size_t max_send_queue_len;
3047 size_t cur_send_queue_len;
3048 struct tevent_req *subreq;
3050 if (sconn->smb2.compound_related_in_progress) {
3052 * Can't read another until the related
3053 * compound is done.
3055 return NT_STATUS_OK;
3058 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
3060 * if there is already a smbd_smb2_request_read
3061 * pending, we are done.
3063 return NT_STATUS_OK;
3066 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
3067 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
3069 if (cur_send_queue_len > max_send_queue_len) {
3071 * if we have a lot of requests to send,
3072 * we wait until they are on the wire until we
3073 * ask for the next request.
3075 return NT_STATUS_OK;
3078 /* ask for the next request */
3079 subreq = smbd_smb2_request_read_send(sconn, sconn->ev_ctx, sconn);
3080 if (subreq == NULL) {
3081 return NT_STATUS_NO_MEMORY;
3083 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
3085 return NT_STATUS_OK;
3088 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
3089 uint8_t *inbuf, size_t size)
3091 NTSTATUS status;
3092 struct smbd_smb2_request *req = NULL;
3094 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3095 (unsigned int)size));
3097 status = smbd_initialize_smb2(sconn);
3098 if (!NT_STATUS_IS_OK(status)) {
3099 smbd_server_connection_terminate(sconn, nt_errstr(status));
3100 return;
3103 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
3104 if (!NT_STATUS_IS_OK(status)) {
3105 smbd_server_connection_terminate(sconn, nt_errstr(status));
3106 return;
3109 status = smbd_smb2_request_validate(req);
3110 if (!NT_STATUS_IS_OK(status)) {
3111 smbd_server_connection_terminate(sconn, nt_errstr(status));
3112 return;
3115 status = smbd_smb2_request_setup_out(req);
3116 if (!NT_STATUS_IS_OK(status)) {
3117 smbd_server_connection_terminate(sconn, nt_errstr(status));
3118 return;
3121 status = smbd_smb2_request_dispatch(req);
3122 if (!NT_STATUS_IS_OK(status)) {
3123 smbd_server_connection_terminate(sconn, nt_errstr(status));
3124 return;
3127 status = smbd_smb2_request_next_incoming(sconn);
3128 if (!NT_STATUS_IS_OK(status)) {
3129 smbd_server_connection_terminate(sconn, nt_errstr(status));
3130 return;
3133 sconn->num_requests++;
3136 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
3138 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
3139 struct smbd_server_connection);
3140 NTSTATUS status;
3141 struct smbd_smb2_request *req = NULL;
3143 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
3144 TALLOC_FREE(subreq);
3145 if (!NT_STATUS_IS_OK(status)) {
3146 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
3147 nt_errstr(status)));
3148 smbd_server_connection_terminate(sconn, nt_errstr(status));
3149 return;
3152 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
3153 req->current_idx, req->in.vector_count));
3155 status = smbd_smb2_request_validate(req);
3156 if (!NT_STATUS_IS_OK(status)) {
3157 smbd_server_connection_terminate(sconn, nt_errstr(status));
3158 return;
3161 status = smbd_smb2_request_setup_out(req);
3162 if (!NT_STATUS_IS_OK(status)) {
3163 smbd_server_connection_terminate(sconn, nt_errstr(status));
3164 return;
3167 status = smbd_smb2_request_dispatch(req);
3168 if (!NT_STATUS_IS_OK(status)) {
3169 smbd_server_connection_terminate(sconn, nt_errstr(status));
3170 return;
3173 status = smbd_smb2_request_next_incoming(sconn);
3174 if (!NT_STATUS_IS_OK(status)) {
3175 smbd_server_connection_terminate(sconn, nt_errstr(status));
3176 return;
3179 sconn->num_requests++;
3181 /* The timeout_processing function isn't run nearly
3182 often enough to implement 'max log size' without
3183 overrunning the size of the file by many megabytes.
3184 This is especially true if we are running at debug
3185 level 10. Checking every 50 SMB2s is a nice
3186 tradeoff of performance vs log file size overrun. */
3188 if ((sconn->num_requests % 50) == 0 &&
3189 need_to_check_log_size()) {
3190 change_to_root_user();
3191 check_log_size();