s3:smb2_server: don't assume that req->out.vector is always a valid talloc pointer
[Samba.git] / source3 / smbd / smb2_server.c
blobceee35d05a235f14c9e3995ce01a657b5645f32a
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 static void smbd_smb2_connection_handler(struct tevent_context *ev,
34 struct tevent_fd *fde,
35 uint16_t flags,
36 void *private_data);
37 static NTSTATUS smbd_smb2_io_handler(struct smbd_server_connection *sconn,
38 uint16_t fde_flags);
40 static const struct smbd_smb2_dispatch_table {
41 uint16_t opcode;
42 const char *name;
43 bool need_session;
44 bool need_tcon;
45 bool as_root;
46 uint16_t fileid_ofs;
47 bool allow_invalid_fileid;
48 } smbd_smb2_table[] = {
49 #define _OP(o) .opcode = o, .name = #o
51 _OP(SMB2_OP_NEGPROT),
52 .as_root = true,
53 },{
54 _OP(SMB2_OP_SESSSETUP),
55 .as_root = true,
56 },{
57 _OP(SMB2_OP_LOGOFF),
58 .need_session = true,
59 .as_root = true,
60 },{
61 _OP(SMB2_OP_TCON),
62 .need_session = true,
64 * This call needs to be run as root.
66 * smbd_smb2_request_process_tcon()
67 * calls make_connection_snum(), which will call
68 * change_to_user(), when needed.
70 .as_root = true,
71 },{
72 _OP(SMB2_OP_TDIS),
73 .need_session = true,
74 .need_tcon = true,
75 .as_root = true,
76 },{
77 _OP(SMB2_OP_CREATE),
78 .need_session = true,
79 .need_tcon = true,
80 },{
81 _OP(SMB2_OP_CLOSE),
82 .need_session = true,
83 .need_tcon = true,
84 .fileid_ofs = 0x08,
85 },{
86 _OP(SMB2_OP_FLUSH),
87 .need_session = true,
88 .need_tcon = true,
89 .fileid_ofs = 0x08,
90 },{
91 _OP(SMB2_OP_READ),
92 .need_session = true,
93 .need_tcon = true,
94 .fileid_ofs = 0x10,
95 },{
96 _OP(SMB2_OP_WRITE),
97 .need_session = true,
98 .need_tcon = true,
99 .fileid_ofs = 0x10,
101 _OP(SMB2_OP_LOCK),
102 .need_session = true,
103 .need_tcon = true,
104 .fileid_ofs = 0x08,
106 _OP(SMB2_OP_IOCTL),
107 .need_session = true,
108 .need_tcon = true,
109 .fileid_ofs = 0x08,
110 .allow_invalid_fileid = true,
112 _OP(SMB2_OP_CANCEL),
113 .as_root = true,
115 _OP(SMB2_OP_KEEPALIVE),
116 .as_root = true,
118 _OP(SMB2_OP_FIND),
119 .need_session = true,
120 .need_tcon = true,
121 .fileid_ofs = 0x08,
123 _OP(SMB2_OP_NOTIFY),
124 .need_session = true,
125 .need_tcon = true,
126 .fileid_ofs = 0x08,
128 _OP(SMB2_OP_GETINFO),
129 .need_session = true,
130 .need_tcon = true,
131 .fileid_ofs = 0x18,
133 _OP(SMB2_OP_SETINFO),
134 .need_session = true,
135 .need_tcon = true,
136 .fileid_ofs = 0x10,
138 _OP(SMB2_OP_BREAK),
139 .need_session = true,
140 .need_tcon = true,
142 * we do not set
143 * .fileid_ofs here
144 * as LEASE breaks does not
145 * have a file id
150 const char *smb2_opcode_name(uint16_t opcode)
152 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
153 return "Bad SMB2 opcode";
155 return smbd_smb2_table[opcode].name;
158 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
160 const struct smbd_smb2_dispatch_table *ret = NULL;
162 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
163 return NULL;
166 ret = &smbd_smb2_table[opcode];
168 SMB_ASSERT(ret->opcode == opcode);
170 return ret;
173 static void print_req_vectors(const struct smbd_smb2_request *req)
175 int i;
177 for (i = 0; i < req->in.vector_count; i++) {
178 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
179 (unsigned int)i,
180 (unsigned int)req->in.vector[i].iov_len);
182 for (i = 0; i < req->out.vector_count; i++) {
183 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
184 (unsigned int)i,
185 (unsigned int)req->out.vector[i].iov_len);
189 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
191 if (size < (4 + SMB2_HDR_BODY)) {
192 return false;
195 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
196 return false;
199 return true;
202 static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
204 TALLOC_FREE(sconn->smb1.fde);
206 sconn->smb2.send_queue = NULL;
208 sconn->smb2.seqnum_low = 0;
209 sconn->smb2.seqnum_range = 1;
210 sconn->smb2.credits_granted = 1;
211 sconn->smb2.max_credits = lp_smb2_max_credits();
212 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
213 sconn->smb2.max_credits);
214 if (sconn->smb2.credits_bitmap == NULL) {
215 return NT_STATUS_NO_MEMORY;
218 sconn->smb2.fde = tevent_add_fd(sconn->ev_ctx,
219 sconn,
220 sconn->sock,
221 TEVENT_FD_READ,
222 smbd_smb2_connection_handler,
223 sconn);
224 if (sconn->smb2.fde == NULL) {
225 return NT_STATUS_NO_MEMORY;
228 /* Ensure child is set to non-blocking mode */
229 set_blocking(sconn->sock, false);
230 return NT_STATUS_OK;
233 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
234 #define _smb2_setlen(_buf,len) do { \
235 uint8_t *buf = (uint8_t *)_buf; \
236 buf[0] = 0; \
237 buf[1] = ((len)&0xFF0000)>>16; \
238 buf[2] = ((len)&0xFF00)>>8; \
239 buf[3] = (len)&0xFF; \
240 } while (0)
242 static void smb2_setup_nbt_length(struct iovec *vector, int count)
244 size_t len = 0;
245 int i;
247 for (i=1; i < count; i++) {
248 len += vector[i].iov_len;
251 _smb2_setlen(vector[0].iov_base, len);
254 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
256 if (req->first_key.length > 0) {
257 data_blob_clear_free(&req->first_key);
259 if (req->last_key.length > 0) {
260 data_blob_clear_free(&req->last_key);
262 return 0;
265 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
267 TALLOC_CTX *mem_pool;
268 struct smbd_smb2_request *req;
270 #if 0
271 /* Enable this to find subtle valgrind errors. */
272 mem_pool = talloc_init("smbd_smb2_request_allocate");
273 #else
274 mem_pool = talloc_tos();
275 #endif
276 if (mem_pool == NULL) {
277 return NULL;
280 req = talloc_zero(mem_pool, struct smbd_smb2_request);
281 if (req == NULL) {
282 talloc_free(mem_pool);
283 return NULL;
285 talloc_reparent(mem_pool, mem_ctx, req);
286 #if 0
287 TALLOC_FREE(mem_pool);
288 #endif
290 req->last_session_id = UINT64_MAX;
291 req->last_tid = UINT32_MAX;
293 talloc_set_destructor(req, smbd_smb2_request_destructor);
295 return req;
298 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn,
299 NTTIME now,
300 uint8_t *buf,
301 size_t buflen,
302 struct smbd_smb2_request *req,
303 struct iovec **piov,
304 int *pnum_iov)
306 TALLOC_CTX *mem_ctx = req;
307 struct iovec *iov;
308 int num_iov = 1;
309 size_t taken = 0;
310 uint8_t *first_hdr = buf;
311 size_t verified_buflen = 0;
312 uint8_t *tf = NULL;
313 size_t tf_len = 0;
316 * Note: index '0' is reserved for the transport protocol
318 iov = req->in._vector;
320 while (taken < buflen) {
321 size_t len = buflen - taken;
322 uint8_t *hdr = first_hdr + taken;
323 struct iovec *cur;
324 size_t full_size;
325 size_t next_command_ofs;
326 uint16_t body_size;
327 uint8_t *body = NULL;
328 uint32_t dyn_size;
329 uint8_t *dyn = NULL;
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 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
461 struct iovec *iov_tmp = NULL;
462 struct iovec *iov_alloc = NULL;
464 if (iov != req->in._vector) {
465 iov_alloc = iov;
468 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
469 struct iovec,
470 num_iov +
471 SMBD_SMB2_NUM_IOV_PER_REQ);
472 if (iov_tmp == NULL) {
473 TALLOC_FREE(iov_alloc);
474 return NT_STATUS_NO_MEMORY;
477 if (iov_alloc == NULL) {
478 memcpy(iov_tmp,
479 req->in._vector,
480 sizeof(req->in._vector));
483 iov = iov_tmp;
485 cur = &iov[num_iov];
486 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
488 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
489 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
490 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
491 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
492 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
493 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
494 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
495 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
497 taken += full_size;
500 *piov = iov;
501 *pnum_iov = num_iov;
502 return NT_STATUS_OK;
504 inval:
505 if (iov != req->in._vector) {
506 TALLOC_FREE(iov);
508 return NT_STATUS_INVALID_PARAMETER;
511 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
512 uint8_t *inbuf, size_t size,
513 struct smbd_smb2_request **_req)
515 struct smbd_smb2_request *req;
516 uint32_t protocol_version;
517 const uint8_t *inhdr = NULL;
518 uint16_t cmd;
519 uint32_t next_command_ofs;
520 NTSTATUS status;
521 NTTIME now;
523 if (size < (4 + SMB2_HDR_BODY + 2)) {
524 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
525 return NT_STATUS_INVALID_PARAMETER;
528 inhdr = inbuf + 4;
530 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
531 if (protocol_version != SMB2_MAGIC) {
532 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
533 protocol_version));
534 return NT_STATUS_INVALID_PARAMETER;
537 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
538 if (cmd != SMB2_OP_NEGPROT) {
539 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
540 cmd));
541 return NT_STATUS_INVALID_PARAMETER;
544 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
545 if (next_command_ofs != 0) {
546 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
547 next_command_ofs));
548 return NT_STATUS_INVALID_PARAMETER;
551 req = smbd_smb2_request_allocate(sconn);
552 if (req == NULL) {
553 return NT_STATUS_NO_MEMORY;
555 req->sconn = sconn;
557 talloc_steal(req, inbuf);
559 req->request_time = timeval_current();
560 now = timeval_to_nttime(&req->request_time);
562 status = smbd_smb2_inbuf_parse_compound(sconn->conn,
563 now,
564 inbuf + NBT_HDR_SIZE,
565 size - NBT_HDR_SIZE,
566 req, &req->in.vector,
567 &req->in.vector_count);
568 if (!NT_STATUS_IS_OK(status)) {
569 TALLOC_FREE(req);
570 return status;
573 req->current_idx = 1;
575 *_req = req;
576 return NT_STATUS_OK;
579 static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
580 uint64_t message_id, uint64_t seq_id)
582 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
583 unsigned int offset;
585 if (seq_id < sconn->smb2.seqnum_low) {
586 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
587 "%llu (sequence id %llu) "
588 "(granted = %u, low = %llu, range = %u)\n",
589 (unsigned long long)message_id,
590 (unsigned long long)seq_id,
591 (unsigned int)sconn->smb2.credits_granted,
592 (unsigned long long)sconn->smb2.seqnum_low,
593 (unsigned int)sconn->smb2.seqnum_range));
594 return false;
597 if (seq_id >= sconn->smb2.seqnum_low + sconn->smb2.seqnum_range) {
598 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
599 "%llu (sequence id %llu) "
600 "(granted = %u, low = %llu, range = %u)\n",
601 (unsigned long long)message_id,
602 (unsigned long long)seq_id,
603 (unsigned int)sconn->smb2.credits_granted,
604 (unsigned long long)sconn->smb2.seqnum_low,
605 (unsigned int)sconn->smb2.seqnum_range));
606 return false;
609 offset = seq_id % sconn->smb2.max_credits;
611 if (bitmap_query(credits_bm, offset)) {
612 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
613 "%llu (sequence id %llu) "
614 "(granted = %u, low = %llu, range = %u) "
615 "(bm offset %u)\n",
616 (unsigned long long)message_id,
617 (unsigned long long)seq_id,
618 (unsigned int)sconn->smb2.credits_granted,
619 (unsigned long long)sconn->smb2.seqnum_low,
620 (unsigned int)sconn->smb2.seqnum_range,
621 offset));
622 return false;
625 /* Mark the message_ids as seen in the bitmap. */
626 bitmap_set(credits_bm, offset);
628 if (seq_id != sconn->smb2.seqnum_low) {
629 return true;
633 * Move the window forward by all the message_id's
634 * already seen.
636 while (bitmap_query(credits_bm, offset)) {
637 DEBUG(10,("smb2_validate_sequence_number: clearing "
638 "id %llu (position %u) from bitmap\n",
639 (unsigned long long)(sconn->smb2.seqnum_low),
640 offset));
641 bitmap_clear(credits_bm, offset);
643 sconn->smb2.seqnum_low += 1;
644 sconn->smb2.seqnum_range -= 1;
645 offset = sconn->smb2.seqnum_low % sconn->smb2.max_credits;
648 return true;
651 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
652 const uint8_t *inhdr)
654 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
655 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
656 uint16_t credit_charge = 1;
657 uint64_t i;
659 if (opcode == SMB2_OP_CANCEL) {
660 /* SMB2_CANCEL requests by definition resend messageids. */
661 return true;
664 if (sconn->smb2.supports_multicredit) {
665 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
666 credit_charge = MAX(credit_charge, 1);
669 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
670 "credits_granted %llu, "
671 "seqnum low/range: %llu/%llu\n",
672 (unsigned long long) message_id,
673 (unsigned long long) credit_charge,
674 (unsigned long long) sconn->smb2.credits_granted,
675 (unsigned long long) sconn->smb2.seqnum_low,
676 (unsigned long long) sconn->smb2.seqnum_range));
678 if (sconn->smb2.credits_granted < credit_charge) {
679 DEBUG(0, ("smb2_validate_message_id: client used more "
680 "credits than granted, mid %llu, charge %llu, "
681 "credits_granted %llu, "
682 "seqnum low/range: %llu/%llu\n",
683 (unsigned long long) message_id,
684 (unsigned long long) credit_charge,
685 (unsigned long long) sconn->smb2.credits_granted,
686 (unsigned long long) sconn->smb2.seqnum_low,
687 (unsigned long long) sconn->smb2.seqnum_range));
688 return false;
692 * now check the message ids
694 * for multi-credit requests we need to check all current mid plus
695 * the implicit mids caused by the credit charge
696 * e.g. current mid = 15, charge 5 => mark 15-19 as used
699 for (i = 0; i <= (credit_charge-1); i++) {
700 uint64_t id = message_id + i;
701 bool ok;
703 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
704 (unsigned long long)message_id,
705 credit_charge,
706 (unsigned long long)id));
708 ok = smb2_validate_sequence_number(sconn, message_id, id);
709 if (!ok) {
710 return false;
714 /* substract used credits */
715 sconn->smb2.credits_granted -= credit_charge;
717 return true;
720 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
722 int count;
723 int idx;
725 count = req->in.vector_count;
727 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
728 /* It's not a SMB2 request */
729 return NT_STATUS_INVALID_PARAMETER;
732 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
733 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
734 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
735 const uint8_t *inhdr = NULL;
737 if (hdr->iov_len != SMB2_HDR_BODY) {
738 return NT_STATUS_INVALID_PARAMETER;
741 if (body->iov_len < 2) {
742 return NT_STATUS_INVALID_PARAMETER;
745 inhdr = (const uint8_t *)hdr->iov_base;
747 /* Check the SMB2 header */
748 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
749 return NT_STATUS_INVALID_PARAMETER;
752 if (!smb2_validate_message_id(req->sconn, inhdr)) {
753 return NT_STATUS_INVALID_PARAMETER;
757 return NT_STATUS_OK;
760 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
761 const struct iovec *in_vector,
762 struct iovec *out_vector)
764 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
765 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
766 uint16_t credit_charge = 1;
767 uint16_t credits_requested;
768 uint32_t out_flags;
769 uint16_t cmd;
770 NTSTATUS out_status;
771 uint16_t credits_granted = 0;
772 uint64_t credits_possible;
773 uint16_t current_max_credits;
776 * first we grant only 1/16th of the max range.
778 * Windows also starts with the 1/16th and then grants
779 * more later. I was only able to trigger higher
780 * values, when using a very high credit charge.
782 * TODO: scale up depending on load, free memory
783 * or other stuff.
784 * Maybe also on the relationship between number
785 * of requests and the used sequence number.
786 * Which means we would grant more credits
787 * for client which use multi credit requests.
789 current_max_credits = sconn->smb2.max_credits / 16;
790 current_max_credits = MAX(current_max_credits, 1);
792 if (sconn->smb2.supports_multicredit) {
793 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
794 credit_charge = MAX(credit_charge, 1);
797 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
798 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
799 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
800 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
802 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
804 if (sconn->smb2.max_credits < credit_charge) {
805 smbd_server_connection_terminate(sconn,
806 "client error: credit charge > max credits\n");
807 return;
810 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
812 * In case we already send an async interim
813 * response, we should not grant
814 * credits on the final response.
816 credits_granted = 0;
817 } else if (credits_requested > 0) {
818 uint16_t additional_max = 0;
819 uint16_t additional_credits = credits_requested - 1;
821 switch (cmd) {
822 case SMB2_OP_NEGPROT:
823 break;
824 case SMB2_OP_SESSSETUP:
826 * Windows 2012 RC1 starts to grant
827 * additional credits
828 * with a successful session setup
830 if (NT_STATUS_IS_OK(out_status)) {
831 additional_max = 32;
833 break;
834 default:
836 * We match windows and only grant additional credits
837 * in chunks of 32.
839 additional_max = 32;
840 break;
843 additional_credits = MIN(additional_credits, additional_max);
845 credits_granted = credit_charge + additional_credits;
846 } else if (sconn->smb2.credits_granted == 0) {
848 * Make sure the client has always at least one credit
850 credits_granted = 1;
854 * sequence numbers should not wrap
856 * 1. calculate the possible credits until
857 * the sequence numbers start to wrap on 64-bit.
859 * 2. UINT64_MAX is used for Break Notifications.
861 * 2. truncate the possible credits to the maximum
862 * credits we want to grant to the client in total.
864 * 3. remove the range we'll already granted to the client
865 * this makes sure the client consumes the lowest sequence
866 * number, before we can grant additional credits.
868 credits_possible = UINT64_MAX - sconn->smb2.seqnum_low;
869 if (credits_possible > 0) {
870 /* remove UINT64_MAX */
871 credits_possible -= 1;
873 credits_possible = MIN(credits_possible, current_max_credits);
874 credits_possible -= sconn->smb2.seqnum_range;
876 credits_granted = MIN(credits_granted, credits_possible);
878 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
879 sconn->smb2.credits_granted += credits_granted;
880 sconn->smb2.seqnum_range += credits_granted;
882 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
883 "granted %u, current possible/max %u/%u, "
884 "total granted/max/low/range %u/%u/%llu/%u\n",
885 (unsigned int)credits_requested,
886 (unsigned int)credit_charge,
887 (unsigned int)credits_granted,
888 (unsigned int)credits_possible,
889 (unsigned int)current_max_credits,
890 (unsigned int)sconn->smb2.credits_granted,
891 (unsigned int)sconn->smb2.max_credits,
892 (unsigned long long)sconn->smb2.seqnum_low,
893 (unsigned int)sconn->smb2.seqnum_range));
896 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
897 struct smbd_smb2_request *outreq)
899 int count, idx;
900 uint16_t total_credits = 0;
902 count = outreq->out.vector_count;
904 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
905 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
906 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
907 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
909 smb2_set_operation_credit(outreq->sconn, inhdr_v, outhdr_v);
911 /* To match Windows, count up what we
912 just granted. */
913 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
914 /* Set to zero in all but the last reply. */
915 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
916 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
917 } else {
918 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
923 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
925 if (req->current_idx <= 1) {
926 if (size <= sizeof(req->out._body)) {
927 return data_blob_const(req->out._body, size);
931 return data_blob_talloc(req, NULL, size);
934 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
936 struct iovec *vector;
937 int count;
938 int idx;
940 count = req->in.vector_count;
941 vector = talloc_zero_array(req, struct iovec, count);
942 if (vector == NULL) {
943 return NT_STATUS_NO_MEMORY;
946 vector[0].iov_base = req->out.nbt_hdr;
947 vector[0].iov_len = 4;
948 SIVAL(req->out.nbt_hdr, 0, 0);
950 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
951 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
952 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
953 uint8_t *outhdr = NULL;
954 uint8_t *outbody = NULL;
955 uint32_t next_command_ofs = 0;
956 struct iovec *current = &vector[idx];
958 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
959 /* we have a next command -
960 * setup for the error case. */
961 next_command_ofs = SMB2_HDR_BODY + 9;
964 if (idx == 1) {
965 outhdr = req->out._hdr;
966 } else {
967 outhdr = talloc_zero_array(vector, uint8_t,
968 OUTVEC_ALLOC_SIZE);
969 if (outhdr == NULL) {
970 return NT_STATUS_NO_MEMORY;
974 outbody = outhdr + SMB2_HDR_BODY;
977 * SMBD_SMB2_TF_IOV_OFS might be used later
979 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
980 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
982 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
983 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
985 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
986 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
988 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
989 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
991 /* setup the SMB2 header */
992 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
993 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
994 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
995 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
996 SIVAL(outhdr, SMB2_HDR_STATUS,
997 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
998 SSVAL(outhdr, SMB2_HDR_OPCODE,
999 SVAL(inhdr, SMB2_HDR_OPCODE));
1000 SIVAL(outhdr, SMB2_HDR_FLAGS,
1001 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1002 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1003 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1004 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1005 SIVAL(outhdr, SMB2_HDR_PID,
1006 IVAL(inhdr, SMB2_HDR_PID));
1007 SIVAL(outhdr, SMB2_HDR_TID,
1008 IVAL(inhdr, SMB2_HDR_TID));
1009 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1010 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1011 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1012 inhdr + SMB2_HDR_SIGNATURE, 16);
1014 /* setup error body header */
1015 SSVAL(outbody, 0x00, 0x08 + 1);
1016 SSVAL(outbody, 0x02, 0);
1017 SIVAL(outbody, 0x04, 0);
1020 req->out.vector = vector;
1021 req->out.vector_count = count;
1023 /* setup the length of the NBT packet */
1024 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1026 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
1028 return NT_STATUS_OK;
1031 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
1032 const char *reason,
1033 const char *location)
1035 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1036 reason, location));
1037 exit_server_cleanly(reason);
1040 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1041 struct iovec *outvec,
1042 const struct iovec *srcvec)
1044 const uint8_t *srctf;
1045 size_t srctf_len;
1046 const uint8_t *srchdr;
1047 size_t srchdr_len;
1048 const uint8_t *srcbody;
1049 size_t srcbody_len;
1050 const uint8_t *expected_srcbody;
1051 const uint8_t *srcdyn;
1052 size_t srcdyn_len;
1053 const uint8_t *expected_srcdyn;
1054 uint8_t *dsttf;
1055 uint8_t *dsthdr;
1056 uint8_t *dstbody;
1057 uint8_t *dstdyn;
1059 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1060 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1061 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1062 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1063 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1064 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1065 expected_srcbody = srchdr + SMB2_HDR_BODY;
1066 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1067 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1068 expected_srcdyn = srcbody + 8;
1070 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1071 return false;
1074 if (srchdr_len != SMB2_HDR_BODY) {
1075 return false;
1078 if (srctf_len == SMB2_TF_HDR_SIZE) {
1079 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1080 if (dsttf == NULL) {
1081 return false;
1083 } else {
1084 dsttf = NULL;
1086 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1087 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1089 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1090 * be allocated with size OUTVEC_ALLOC_SIZE. */
1092 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1093 if (dsthdr == NULL) {
1094 return false;
1096 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1097 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1100 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1101 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1102 * then duplicate this. Else use talloc_memdup().
1105 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1106 dstbody = dsthdr + SMB2_HDR_BODY;
1107 } else {
1108 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1109 if (dstbody == NULL) {
1110 return false;
1113 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1114 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1117 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1118 * pointing to
1119 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1120 * then duplicate this. Else use talloc_memdup().
1123 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1124 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1125 } else if (srcdyn == NULL) {
1126 dstdyn = NULL;
1127 } else {
1128 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1129 if (dstdyn == NULL) {
1130 return false;
1133 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1134 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1136 return true;
1139 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1141 struct smbd_smb2_request *newreq = NULL;
1142 struct iovec *outvec = NULL;
1143 int count = req->out.vector_count;
1144 int i;
1146 newreq = smbd_smb2_request_allocate(req->sconn);
1147 if (!newreq) {
1148 return NULL;
1151 newreq->sconn = req->sconn;
1152 newreq->session = req->session;
1153 newreq->do_encryption = req->do_encryption;
1154 newreq->do_signing = req->do_signing;
1155 newreq->current_idx = req->current_idx;
1157 outvec = talloc_zero_array(newreq, struct iovec, count);
1158 if (!outvec) {
1159 TALLOC_FREE(newreq);
1160 return NULL;
1162 newreq->out.vector = outvec;
1163 newreq->out.vector_count = count;
1165 /* Setup the outvec's identically to req. */
1166 outvec[0].iov_base = newreq->out.nbt_hdr;
1167 outvec[0].iov_len = 4;
1168 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1170 /* Setup the vectors identically to the ones in req. */
1171 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1172 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1173 break;
1177 if (i < count) {
1178 /* Alloc failed. */
1179 TALLOC_FREE(newreq);
1180 return NULL;
1183 smb2_setup_nbt_length(newreq->out.vector,
1184 newreq->out.vector_count);
1186 return newreq;
1189 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1191 struct smbd_server_connection *sconn = req->sconn;
1192 struct smbXsrv_connection *conn = req->sconn->conn;
1193 int first_idx = 1;
1194 struct iovec *firsttf = NULL;
1195 struct iovec *outhdr_v = NULL;
1196 uint8_t *outhdr = NULL;
1197 struct smbd_smb2_request *nreq = NULL;
1198 NTSTATUS status;
1200 /* Create a new smb2 request we'll use
1201 for the interim return. */
1202 nreq = dup_smb2_req(req);
1203 if (!nreq) {
1204 return NT_STATUS_NO_MEMORY;
1207 /* Lose the last X out vectors. They're the
1208 ones we'll be using for the async reply. */
1209 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1211 smb2_setup_nbt_length(nreq->out.vector,
1212 nreq->out.vector_count);
1214 /* Step back to the previous reply. */
1215 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1216 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1217 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1218 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1219 /* And end the chain. */
1220 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1222 /* Calculate outgoing credits */
1223 smb2_calculate_credits(req, nreq);
1225 if (DEBUGLEVEL >= 10) {
1226 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1227 (unsigned int)nreq->current_idx );
1228 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1229 (unsigned int)nreq->out.vector_count );
1230 print_req_vectors(nreq);
1234 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1235 * we need to sign/encrypt here with the last/first key we remembered
1237 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1238 status = smb2_signing_encrypt_pdu(req->first_key,
1239 conn->protocol,
1240 firsttf,
1241 nreq->out.vector_count - first_idx);
1242 if (!NT_STATUS_IS_OK(status)) {
1243 return status;
1245 } else if (req->last_key.length > 0) {
1246 status = smb2_signing_sign_pdu(req->last_key,
1247 conn->protocol,
1248 outhdr_v,
1249 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1250 if (!NT_STATUS_IS_OK(status)) {
1251 return status;
1255 nreq->queue_entry.mem_ctx = nreq;
1256 nreq->queue_entry.vector = nreq->out.vector;
1257 nreq->queue_entry.count = nreq->out.vector_count;
1258 DLIST_ADD_END(nreq->sconn->smb2.send_queue, &nreq->queue_entry, NULL);
1259 nreq->sconn->smb2.send_queue_len++;
1261 status = smbd_smb2_io_handler(sconn, TEVENT_FD_WRITE);
1262 if (!NT_STATUS_IS_OK(status)) {
1263 return status;
1266 return NT_STATUS_OK;
1269 struct smbd_smb2_request_pending_state {
1270 struct smbd_server_connection *sconn;
1271 struct smbd_smb2_send_queue queue_entry;
1272 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1273 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1276 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1277 struct tevent_timer *te,
1278 struct timeval current_time,
1279 void *private_data);
1281 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1282 struct tevent_req *subreq,
1283 uint32_t defer_time)
1285 NTSTATUS status;
1286 struct timeval defer_endtime;
1287 uint8_t *outhdr = NULL;
1288 uint32_t flags;
1290 if (!tevent_req_is_in_progress(subreq)) {
1292 * This is a performance optimization,
1293 * it avoids one tevent_loop iteration,
1294 * which means we avoid one
1295 * talloc_stackframe_pool/talloc_free pair.
1297 tevent_req_notify_callback(subreq);
1298 return NT_STATUS_OK;
1301 req->subreq = subreq;
1302 subreq = NULL;
1304 if (req->async_te) {
1305 /* We're already async. */
1306 return NT_STATUS_OK;
1309 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1310 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1311 if (flags & SMB2_HDR_FLAG_ASYNC) {
1312 /* We're already async. */
1313 return NT_STATUS_OK;
1316 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1318 * We're trying to go async in a compound
1319 * request chain.
1320 * This is only allowed for opens that
1321 * cause an oplock break, otherwise it
1322 * is not allowed. See [MS-SMB2].pdf
1323 * note <194> on Section 3.3.5.2.7.
1325 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1327 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1329 * Cancel the outstanding request.
1331 bool ok = tevent_req_cancel(req->subreq);
1332 if (ok) {
1333 return NT_STATUS_OK;
1335 TALLOC_FREE(req->subreq);
1336 return smbd_smb2_request_error(req,
1337 NT_STATUS_INTERNAL_ERROR);
1341 if (DEBUGLEVEL >= 10) {
1342 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1343 (unsigned int)req->current_idx );
1344 print_req_vectors(req);
1347 if (req->current_idx > 1) {
1349 * We're going async in a compound
1350 * chain after the first request has
1351 * already been processed. Send an
1352 * interim response containing the
1353 * set of replies already generated.
1355 int idx = req->current_idx;
1357 status = smb2_send_async_interim_response(req);
1358 if (!NT_STATUS_IS_OK(status)) {
1359 return status;
1361 if (req->first_key.length > 0) {
1362 data_blob_clear_free(&req->first_key);
1365 req->current_idx = 1;
1368 * Re-arrange the in.vectors to remove what
1369 * we just sent.
1371 memmove(&req->in.vector[1],
1372 &req->in.vector[idx],
1373 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1374 req->in.vector_count = 1 + (req->in.vector_count - idx);
1376 /* Re-arrange the out.vectors to match. */
1377 memmove(&req->out.vector[1],
1378 &req->out.vector[idx],
1379 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1380 req->out.vector_count = 1 + (req->out.vector_count - idx);
1382 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1384 * We only have one remaining request as
1385 * we've processed everything else.
1386 * This is no longer a compound request.
1388 req->compound_related = false;
1389 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1390 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1391 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1394 if (req->last_key.length > 0) {
1395 data_blob_clear_free(&req->last_key);
1398 defer_endtime = timeval_current_ofs_usec(defer_time);
1399 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1400 req, defer_endtime,
1401 smbd_smb2_request_pending_timer,
1402 req);
1403 if (req->async_te == NULL) {
1404 return NT_STATUS_NO_MEMORY;
1407 return NT_STATUS_OK;
1410 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1411 struct tevent_timer *te,
1412 struct timeval current_time,
1413 void *private_data)
1415 struct smbd_smb2_request *req =
1416 talloc_get_type_abort(private_data,
1417 struct smbd_smb2_request);
1418 struct smbd_server_connection *sconn = req->sconn;
1419 struct smbd_smb2_request_pending_state *state = NULL;
1420 uint8_t *outhdr = NULL;
1421 const uint8_t *inhdr = NULL;
1422 uint8_t *tf = NULL;
1423 size_t tf_len = 0;
1424 uint8_t *hdr = NULL;
1425 uint8_t *body = NULL;
1426 uint8_t *dyn = NULL;
1427 uint32_t flags = 0;
1428 uint64_t session_id = 0;
1429 uint64_t message_id = 0;
1430 uint64_t nonce_high = 0;
1431 uint64_t nonce_low = 0;
1432 uint64_t async_id = 0;
1433 NTSTATUS status;
1435 TALLOC_FREE(req->async_te);
1437 /* Ensure our final reply matches the interim one. */
1438 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1439 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1440 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1441 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1442 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1444 async_id = message_id; /* keep it simple for now... */
1446 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1447 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1449 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1450 "going async\n",
1451 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1452 (unsigned long long)async_id ));
1455 * What we send is identical to a smbd_smb2_request_error
1456 * packet with an error status of STATUS_PENDING. Make use
1457 * of this fact sometime when refactoring. JRA.
1460 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1461 if (state == NULL) {
1462 smbd_server_connection_terminate(req->sconn,
1463 nt_errstr(NT_STATUS_NO_MEMORY));
1464 return;
1466 state->sconn = req->sconn;
1468 tf = state->buf + NBT_HDR_SIZE;
1469 tf_len = SMB2_TF_HDR_SIZE;
1471 hdr = tf + SMB2_TF_HDR_SIZE;
1472 body = hdr + SMB2_HDR_BODY;
1473 dyn = body + 8;
1475 if (req->do_encryption) {
1476 struct smbXsrv_session *x = req->session;
1478 nonce_high = x->nonce_high;
1479 nonce_low = x->nonce_low;
1481 x->nonce_low += 1;
1482 if (x->nonce_low == 0) {
1483 x->nonce_low += 1;
1484 x->nonce_high += 1;
1488 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1489 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1490 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1491 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1493 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1494 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1495 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1496 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1497 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1499 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1500 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1501 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1502 SBVAL(hdr, SMB2_HDR_PID, async_id);
1503 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1504 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1505 memcpy(hdr+SMB2_HDR_SIGNATURE,
1506 outhdr+SMB2_HDR_SIGNATURE, 16);
1508 SSVAL(body, 0x00, 0x08 + 1);
1510 SCVAL(body, 0x02, 0);
1511 SCVAL(body, 0x03, 0);
1512 SIVAL(body, 0x04, 0);
1513 /* Match W2K8R2... */
1514 SCVAL(dyn, 0x00, 0x21);
1516 state->vector[0].iov_base = (void *)state->buf;
1517 state->vector[0].iov_len = NBT_HDR_SIZE;
1519 if (req->do_encryption) {
1520 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1521 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1522 } else {
1523 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1524 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1527 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1528 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1530 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1531 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1533 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1534 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1536 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1538 /* Ensure we correctly go through crediting. Grant
1539 the credits now, and zero credits on the final
1540 response. */
1541 smb2_set_operation_credit(req->sconn,
1542 SMBD_SMB2_IN_HDR_IOV(req),
1543 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1545 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1547 if (DEBUGLVL(10)) {
1548 int i;
1550 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1551 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1552 (unsigned int)i,
1553 (unsigned int)ARRAY_SIZE(state->vector),
1554 (unsigned int)state->vector[i].iov_len);
1558 if (req->do_encryption) {
1559 struct smbXsrv_session *x = req->session;
1560 struct smbXsrv_connection *conn = x->connection;
1561 DATA_BLOB encryption_key = x->global->encryption_key;
1563 status = smb2_signing_encrypt_pdu(encryption_key,
1564 conn->protocol,
1565 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1566 SMBD_SMB2_NUM_IOV_PER_REQ);
1567 if (!NT_STATUS_IS_OK(status)) {
1568 smbd_server_connection_terminate(req->sconn,
1569 nt_errstr(status));
1570 return;
1572 } else if (req->do_signing) {
1573 struct smbXsrv_session *x = req->session;
1574 struct smbXsrv_connection *conn = x->connection;
1575 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1577 status = smb2_signing_sign_pdu(signing_key,
1578 conn->protocol,
1579 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1580 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1581 if (!NT_STATUS_IS_OK(status)) {
1582 smbd_server_connection_terminate(req->sconn,
1583 nt_errstr(status));
1584 return;
1588 state->queue_entry.mem_ctx = state;
1589 state->queue_entry.vector = state->vector;
1590 state->queue_entry.count = ARRAY_SIZE(state->vector);
1591 DLIST_ADD_END(sconn->smb2.send_queue, &state->queue_entry, NULL);
1592 sconn->smb2.send_queue_len++;
1594 status = smbd_smb2_io_handler(sconn, TEVENT_FD_WRITE);
1595 if (!NT_STATUS_IS_OK(status)) {
1596 smbd_server_connection_terminate(sconn,
1597 nt_errstr(status));
1598 return;
1602 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1604 struct smbd_server_connection *sconn = req->sconn;
1605 struct smbd_smb2_request *cur;
1606 const uint8_t *inhdr;
1607 uint32_t flags;
1608 uint64_t search_message_id;
1609 uint64_t search_async_id;
1610 uint64_t found_id;
1612 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1614 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1615 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1616 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1619 * we don't need the request anymore
1620 * cancel requests never have a response
1622 DLIST_REMOVE(req->sconn->smb2.requests, req);
1623 TALLOC_FREE(req);
1625 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1626 const uint8_t *outhdr;
1627 uint64_t message_id;
1628 uint64_t async_id;
1630 if (cur->compound_related) {
1632 * Never cancel anything in a compound request.
1633 * Way too hard to deal with the result.
1635 continue;
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(SVAL(inhdr, SMB2_HDR_OPCODE)),
1661 (unsigned long long)found_id ));
1662 tevent_req_cancel(cur->subreq);
1665 return NT_STATUS_OK;
1668 /*************************************************************
1669 Ensure an incoming tid is a valid one for us to access.
1670 Change to the associated uid credentials and chdir to the
1671 valid tid directory.
1672 *************************************************************/
1674 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1676 const uint8_t *inhdr;
1677 uint32_t in_flags;
1678 uint32_t in_tid;
1679 struct smbXsrv_tcon *tcon;
1680 NTSTATUS status;
1681 NTTIME now = timeval_to_nttime(&req->request_time);
1683 req->tcon = NULL;
1685 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1687 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1688 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1690 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1691 in_tid = req->last_tid;
1694 req->last_tid = 0;
1696 status = smb2srv_tcon_lookup(req->session,
1697 in_tid, now, &tcon);
1698 if (!NT_STATUS_IS_OK(status)) {
1699 return status;
1702 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1703 return NT_STATUS_ACCESS_DENIED;
1706 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1707 if (!set_current_service(tcon->compat, 0, true)) {
1708 return NT_STATUS_ACCESS_DENIED;
1711 req->tcon = tcon;
1712 req->last_tid = in_tid;
1714 return NT_STATUS_OK;
1717 /*************************************************************
1718 Ensure an incoming session_id is a valid one for us to access.
1719 *************************************************************/
1721 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1723 const uint8_t *inhdr;
1724 uint32_t in_flags;
1725 uint16_t in_opcode;
1726 uint64_t in_session_id;
1727 struct smbXsrv_session *session = NULL;
1728 struct auth_session_info *session_info;
1729 NTSTATUS status;
1730 NTTIME now = timeval_to_nttime(&req->request_time);
1732 req->session = NULL;
1733 req->tcon = NULL;
1735 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1737 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1738 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1739 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1741 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1742 in_session_id = req->last_session_id;
1745 req->last_session_id = 0;
1747 /* lookup an existing session */
1748 status = smb2srv_session_lookup(req->sconn->conn,
1749 in_session_id, now,
1750 &session);
1751 if (session) {
1752 req->session = session;
1753 req->last_session_id = in_session_id;
1755 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1756 switch (in_opcode) {
1757 case SMB2_OP_SESSSETUP:
1758 status = NT_STATUS_OK;
1759 break;
1760 default:
1761 break;
1764 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1765 switch (in_opcode) {
1766 case SMB2_OP_TCON:
1767 case SMB2_OP_CREATE:
1768 case SMB2_OP_GETINFO:
1769 case SMB2_OP_SETINFO:
1770 return NT_STATUS_INVALID_HANDLE;
1771 default:
1773 * Notice the check for
1774 * (session_info == NULL)
1775 * below.
1777 status = NT_STATUS_OK;
1778 break;
1781 if (!NT_STATUS_IS_OK(status)) {
1782 return status;
1785 session_info = session->global->auth_session_info;
1786 if (session_info == NULL) {
1787 return NT_STATUS_INVALID_HANDLE;
1790 if (in_session_id != req->sconn->conn->last_session_id) {
1791 req->sconn->conn->last_session_id = in_session_id;
1792 set_current_user_info(session_info->unix_info->sanitized_username,
1793 session_info->unix_info->unix_name,
1794 session_info->info->domain_name);
1797 return NT_STATUS_OK;
1800 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1801 uint32_t data_length)
1803 uint16_t needed_charge;
1804 uint16_t credit_charge = 1;
1805 const uint8_t *inhdr;
1807 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1809 if (req->sconn->smb2.supports_multicredit) {
1810 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1811 credit_charge = MAX(credit_charge, 1);
1814 needed_charge = (data_length - 1)/ 65536 + 1;
1816 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1817 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1818 credit_charge, needed_charge));
1820 if (needed_charge > credit_charge) {
1821 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1822 credit_charge, needed_charge));
1823 return NT_STATUS_INVALID_PARAMETER;
1826 return NT_STATUS_OK;
1829 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1830 size_t expected_body_size)
1832 struct iovec *inhdr_v;
1833 const uint8_t *inhdr;
1834 uint16_t opcode;
1835 const uint8_t *inbody;
1836 size_t body_size;
1837 size_t min_dyn_size = expected_body_size & 0x00000001;
1838 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1841 * The following should be checked already.
1843 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1844 return NT_STATUS_INTERNAL_ERROR;
1846 if (req->current_idx > max_idx) {
1847 return NT_STATUS_INTERNAL_ERROR;
1850 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1851 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1852 return NT_STATUS_INTERNAL_ERROR;
1854 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1855 return NT_STATUS_INTERNAL_ERROR;
1858 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1859 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1861 switch (opcode) {
1862 case SMB2_OP_IOCTL:
1863 case SMB2_OP_GETINFO:
1864 min_dyn_size = 0;
1865 break;
1869 * Now check the expected body size,
1870 * where the last byte might be in the
1871 * dynamic section..
1873 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1874 return NT_STATUS_INVALID_PARAMETER;
1876 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1877 return NT_STATUS_INVALID_PARAMETER;
1880 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1882 body_size = SVAL(inbody, 0x00);
1883 if (body_size != expected_body_size) {
1884 return NT_STATUS_INVALID_PARAMETER;
1887 return NT_STATUS_OK;
1890 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1892 struct smbXsrv_connection *conn = req->sconn->conn;
1893 const struct smbd_smb2_dispatch_table *call = NULL;
1894 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1895 const uint8_t *inhdr;
1896 uint16_t opcode;
1897 uint32_t flags;
1898 uint64_t mid;
1899 NTSTATUS status;
1900 NTSTATUS session_status;
1901 uint32_t allowed_flags;
1902 NTSTATUS return_value;
1903 struct smbXsrv_session *x = NULL;
1904 bool signing_required = false;
1905 bool encryption_required = false;
1907 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1909 /* TODO: verify more things */
1911 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1912 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1913 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1914 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1915 smb2_opcode_name(opcode),
1916 (unsigned long long)mid));
1918 if (conn->protocol >= PROTOCOL_SMB2_02) {
1920 * once the protocol is negotiated
1921 * SMB2_OP_NEGPROT is not allowed anymore
1923 if (opcode == SMB2_OP_NEGPROT) {
1924 /* drop the connection */
1925 return NT_STATUS_INVALID_PARAMETER;
1927 } else {
1929 * if the protocol is not negotiated yet
1930 * only SMB2_OP_NEGPROT is allowed.
1932 if (opcode != SMB2_OP_NEGPROT) {
1933 /* drop the connection */
1934 return NT_STATUS_INVALID_PARAMETER;
1939 * Check if the client provided a valid session id,
1940 * if so smbd_smb2_request_check_session() calls
1941 * set_current_user_info().
1943 * As some command don't require a valid session id
1944 * we defer the check of the session_status
1946 session_status = smbd_smb2_request_check_session(req);
1947 x = req->session;
1948 if (x != NULL) {
1949 signing_required = x->global->signing_required;
1950 encryption_required = x->global->encryption_required;
1952 if (opcode == SMB2_OP_SESSSETUP &&
1953 x->global->channels[0].signing_key.length) {
1954 signing_required = true;
1958 req->do_signing = false;
1959 req->do_encryption = false;
1960 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
1961 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
1962 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
1964 if (x != NULL && x->global->session_wire_id != tf_session_id) {
1965 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1966 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1967 (unsigned long long)x->global->session_wire_id,
1968 (unsigned long long)tf_session_id));
1970 * TODO: windows allows this...
1971 * should we drop the connection?
1973 * For now we just return ACCESS_DENIED
1974 * (Windows clients never trigger this)
1975 * and wait for an update of [MS-SMB2].
1977 return smbd_smb2_request_error(req,
1978 NT_STATUS_ACCESS_DENIED);
1981 req->do_encryption = true;
1984 if (encryption_required && !req->do_encryption) {
1985 return smbd_smb2_request_error(req,
1986 NT_STATUS_ACCESS_DENIED);
1989 call = smbd_smb2_call(opcode);
1990 if (call == NULL) {
1991 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1994 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1995 SMB2_HDR_FLAG_SIGNED |
1996 SMB2_HDR_FLAG_DFS;
1997 if (opcode == SMB2_OP_CANCEL) {
1998 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2000 if ((flags & ~allowed_flags) != 0) {
2001 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2004 if (flags & SMB2_HDR_FLAG_CHAINED) {
2006 * This check is mostly for giving the correct error code
2007 * for compounded requests.
2009 if (!NT_STATUS_IS_OK(session_status)) {
2010 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2012 } else {
2013 req->compat_chain_fsp = NULL;
2016 if (req->do_encryption) {
2017 signing_required = false;
2018 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2019 DATA_BLOB signing_key;
2021 if (x == NULL) {
2022 return smbd_smb2_request_error(
2023 req, NT_STATUS_USER_SESSION_DELETED);
2026 signing_key = x->global->channels[0].signing_key;
2029 * If we have a signing key, we should
2030 * sign the response
2032 if (signing_key.length > 0) {
2033 req->do_signing = true;
2036 status = smb2_signing_check_pdu(signing_key,
2037 conn->protocol,
2038 SMBD_SMB2_IN_HDR_IOV(req),
2039 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2040 if (!NT_STATUS_IS_OK(status)) {
2041 return smbd_smb2_request_error(req, status);
2045 * Now that we know the request was correctly signed
2046 * we have to sign the response too.
2048 req->do_signing = true;
2050 if (!NT_STATUS_IS_OK(session_status)) {
2051 return smbd_smb2_request_error(req, session_status);
2053 } else if (opcode == SMB2_OP_CANCEL) {
2054 /* Cancel requests are allowed to skip the signing */
2055 } else if (signing_required) {
2057 * If signing is required we try to sign
2058 * a possible error response
2060 req->do_signing = true;
2061 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2064 if (flags & SMB2_HDR_FLAG_CHAINED) {
2065 req->compound_related = true;
2068 if (call->need_session) {
2069 if (!NT_STATUS_IS_OK(session_status)) {
2070 return smbd_smb2_request_error(req, session_status);
2074 if (call->need_tcon) {
2075 SMB_ASSERT(call->need_session);
2078 * This call needs to be run as user.
2080 * smbd_smb2_request_check_tcon()
2081 * calls change_to_user() on success.
2083 status = smbd_smb2_request_check_tcon(req);
2084 if (!NT_STATUS_IS_OK(status)) {
2085 return smbd_smb2_request_error(req, status);
2087 if (req->tcon->global->encryption_required) {
2088 encryption_required = true;
2090 if (encryption_required && !req->do_encryption) {
2091 return smbd_smb2_request_error(req,
2092 NT_STATUS_ACCESS_DENIED);
2096 if (call->fileid_ofs != 0) {
2097 size_t needed = call->fileid_ofs + 16;
2098 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2099 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2100 uint64_t file_id_persistent;
2101 uint64_t file_id_volatile;
2102 struct files_struct *fsp;
2104 SMB_ASSERT(call->need_tcon);
2106 if (needed > body_size) {
2107 return smbd_smb2_request_error(req,
2108 NT_STATUS_INVALID_PARAMETER);
2111 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2112 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2114 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2115 if (fsp == NULL) {
2116 if (!call->allow_invalid_fileid) {
2117 return smbd_smb2_request_error(req,
2118 NT_STATUS_FILE_CLOSED);
2121 if (file_id_persistent != UINT64_MAX) {
2122 return smbd_smb2_request_error(req,
2123 NT_STATUS_FILE_CLOSED);
2125 if (file_id_volatile != UINT64_MAX) {
2126 return smbd_smb2_request_error(req,
2127 NT_STATUS_FILE_CLOSED);
2132 if (call->as_root) {
2133 SMB_ASSERT(call->fileid_ofs == 0);
2134 /* This call needs to be run as root */
2135 change_to_root_user();
2136 } else {
2137 SMB_ASSERT(call->need_tcon);
2140 switch (opcode) {
2141 case SMB2_OP_NEGPROT:
2143 START_PROFILE(smb2_negprot);
2144 return_value = smbd_smb2_request_process_negprot(req);
2145 END_PROFILE(smb2_negprot);
2147 break;
2149 case SMB2_OP_SESSSETUP:
2151 START_PROFILE(smb2_sesssetup);
2152 return_value = smbd_smb2_request_process_sesssetup(req);
2153 END_PROFILE(smb2_sesssetup);
2155 break;
2157 case SMB2_OP_LOGOFF:
2159 START_PROFILE(smb2_logoff);
2160 return_value = smbd_smb2_request_process_logoff(req);
2161 END_PROFILE(smb2_logoff);
2163 break;
2165 case SMB2_OP_TCON:
2167 START_PROFILE(smb2_tcon);
2168 return_value = smbd_smb2_request_process_tcon(req);
2169 END_PROFILE(smb2_tcon);
2171 break;
2173 case SMB2_OP_TDIS:
2175 START_PROFILE(smb2_tdis);
2176 return_value = smbd_smb2_request_process_tdis(req);
2177 END_PROFILE(smb2_tdis);
2179 break;
2181 case SMB2_OP_CREATE:
2183 START_PROFILE(smb2_create);
2184 return_value = smbd_smb2_request_process_create(req);
2185 END_PROFILE(smb2_create);
2187 break;
2189 case SMB2_OP_CLOSE:
2191 START_PROFILE(smb2_close);
2192 return_value = smbd_smb2_request_process_close(req);
2193 END_PROFILE(smb2_close);
2195 break;
2197 case SMB2_OP_FLUSH:
2199 START_PROFILE(smb2_flush);
2200 return_value = smbd_smb2_request_process_flush(req);
2201 END_PROFILE(smb2_flush);
2203 break;
2205 case SMB2_OP_READ:
2207 START_PROFILE(smb2_read);
2208 return_value = smbd_smb2_request_process_read(req);
2209 END_PROFILE(smb2_read);
2211 break;
2213 case SMB2_OP_WRITE:
2215 START_PROFILE(smb2_write);
2216 return_value = smbd_smb2_request_process_write(req);
2217 END_PROFILE(smb2_write);
2219 break;
2221 case SMB2_OP_LOCK:
2223 START_PROFILE(smb2_lock);
2224 return_value = smbd_smb2_request_process_lock(req);
2225 END_PROFILE(smb2_lock);
2227 break;
2229 case SMB2_OP_IOCTL:
2231 START_PROFILE(smb2_ioctl);
2232 return_value = smbd_smb2_request_process_ioctl(req);
2233 END_PROFILE(smb2_ioctl);
2235 break;
2237 case SMB2_OP_CANCEL:
2239 START_PROFILE(smb2_cancel);
2240 return_value = smbd_smb2_request_process_cancel(req);
2241 END_PROFILE(smb2_cancel);
2243 break;
2245 case SMB2_OP_KEEPALIVE:
2247 START_PROFILE(smb2_keepalive);
2248 return_value = smbd_smb2_request_process_keepalive(req);
2249 END_PROFILE(smb2_keepalive);
2251 break;
2253 case SMB2_OP_FIND:
2255 START_PROFILE(smb2_find);
2256 return_value = smbd_smb2_request_process_find(req);
2257 END_PROFILE(smb2_find);
2259 break;
2261 case SMB2_OP_NOTIFY:
2263 START_PROFILE(smb2_notify);
2264 return_value = smbd_smb2_request_process_notify(req);
2265 END_PROFILE(smb2_notify);
2267 break;
2269 case SMB2_OP_GETINFO:
2271 START_PROFILE(smb2_getinfo);
2272 return_value = smbd_smb2_request_process_getinfo(req);
2273 END_PROFILE(smb2_getinfo);
2275 break;
2277 case SMB2_OP_SETINFO:
2279 START_PROFILE(smb2_setinfo);
2280 return_value = smbd_smb2_request_process_setinfo(req);
2281 END_PROFILE(smb2_setinfo);
2283 break;
2285 case SMB2_OP_BREAK:
2287 START_PROFILE(smb2_break);
2288 return_value = smbd_smb2_request_process_break(req);
2289 END_PROFILE(smb2_break);
2291 break;
2293 default:
2294 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2295 break;
2297 return return_value;
2300 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2302 struct smbd_server_connection *sconn = req->sconn;
2303 struct smbXsrv_connection *conn = req->sconn->conn;
2304 int first_idx = 1;
2305 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2306 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2307 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2308 NTSTATUS status;
2310 req->subreq = NULL;
2311 TALLOC_FREE(req->async_te);
2313 if (req->do_encryption &&
2314 (firsttf->iov_len == 0) &&
2315 (req->first_key.length == 0) &&
2316 (req->session != NULL) &&
2317 (req->session->global->encryption_key.length != 0))
2319 DATA_BLOB encryption_key = req->session->global->encryption_key;
2320 uint8_t *tf;
2321 uint64_t session_id = req->session->global->session_wire_id;
2322 struct smbXsrv_session *x = req->session;
2323 uint64_t nonce_high;
2324 uint64_t nonce_low;
2326 nonce_high = x->nonce_high;
2327 nonce_low = x->nonce_low;
2329 x->nonce_low += 1;
2330 if (x->nonce_low == 0) {
2331 x->nonce_low += 1;
2332 x->nonce_high += 1;
2336 * We need to place the SMB2_TRANSFORM header before the
2337 * first SMB2 header
2341 * we need to remember the encryption key
2342 * and defer the signing/encryption until
2343 * we are sure that we do not change
2344 * the header again.
2346 req->first_key = data_blob_dup_talloc(req, encryption_key);
2347 if (req->first_key.data == NULL) {
2348 return NT_STATUS_NO_MEMORY;
2351 tf = talloc_zero_array(req, uint8_t,
2352 SMB2_TF_HDR_SIZE);
2353 if (tf == NULL) {
2354 return NT_STATUS_NO_MEMORY;
2357 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2358 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2359 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2360 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2362 firsttf->iov_base = (void *)tf;
2363 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2366 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2367 (req->last_key.length > 0) &&
2368 (firsttf->iov_len == 0))
2370 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2371 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2374 * As we are sure the header of the last request in the
2375 * compound chain will not change, we can to sign here
2376 * with the last signing key we remembered.
2378 status = smb2_signing_sign_pdu(req->last_key,
2379 conn->protocol,
2380 lasthdr,
2381 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2382 if (!NT_STATUS_IS_OK(status)) {
2383 return status;
2386 if (req->last_key.length > 0) {
2387 data_blob_clear_free(&req->last_key);
2390 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2392 if (req->current_idx < req->out.vector_count) {
2394 * We must process the remaining compound
2395 * SMB2 requests before any new incoming SMB2
2396 * requests. This is because incoming SMB2
2397 * requests may include a cancel for a
2398 * compound request we haven't processed
2399 * yet.
2401 struct tevent_immediate *im = tevent_create_immediate(req);
2402 if (!im) {
2403 return NT_STATUS_NO_MEMORY;
2406 if (req->do_signing && firsttf->iov_len == 0) {
2407 struct smbXsrv_session *x = req->session;
2408 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2411 * we need to remember the signing key
2412 * and defer the signing until
2413 * we are sure that we do not change
2414 * the header again.
2416 req->last_key = data_blob_dup_talloc(req, signing_key);
2417 if (req->last_key.data == NULL) {
2418 return NT_STATUS_NO_MEMORY;
2422 tevent_schedule_immediate(im,
2423 req->sconn->ev_ctx,
2424 smbd_smb2_request_dispatch_immediate,
2425 req);
2426 return NT_STATUS_OK;
2429 if (req->compound_related) {
2430 req->compound_related = false;
2433 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2435 /* Set credit for these operations (zero credits if this
2436 is a final reply for an async operation). */
2437 smb2_calculate_credits(req, req);
2440 * now check if we need to sign the current response
2442 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2443 status = smb2_signing_encrypt_pdu(req->first_key,
2444 conn->protocol,
2445 firsttf,
2446 req->out.vector_count - first_idx);
2447 if (!NT_STATUS_IS_OK(status)) {
2448 return status;
2450 } else if (req->do_signing) {
2451 struct smbXsrv_session *x = req->session;
2452 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2454 status = smb2_signing_sign_pdu(signing_key,
2455 conn->protocol,
2456 outhdr,
2457 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2458 if (!NT_STATUS_IS_OK(status)) {
2459 return status;
2462 if (req->first_key.length > 0) {
2463 data_blob_clear_free(&req->first_key);
2466 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2467 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2468 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2469 /* Dynamic part is NULL. Chop it off,
2470 We're going to send it via sendfile. */
2471 req->out.vector_count -= 1;
2475 * We're done with this request -
2476 * move it off the "being processed" queue.
2478 DLIST_REMOVE(req->sconn->smb2.requests, req);
2480 req->queue_entry.mem_ctx = req;
2481 req->queue_entry.vector = req->out.vector;
2482 req->queue_entry.count = req->out.vector_count;
2483 DLIST_ADD_END(req->sconn->smb2.send_queue, &req->queue_entry, NULL);
2484 req->sconn->smb2.send_queue_len++;
2486 status = smbd_smb2_io_handler(sconn, TEVENT_FD_WRITE);
2487 if (!NT_STATUS_IS_OK(status)) {
2488 return status;
2491 return NT_STATUS_OK;
2494 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2496 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2497 struct tevent_immediate *im,
2498 void *private_data)
2500 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2501 struct smbd_smb2_request);
2502 struct smbd_server_connection *sconn = req->sconn;
2503 NTSTATUS status;
2505 TALLOC_FREE(im);
2507 if (DEBUGLEVEL >= 10) {
2508 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2509 req->current_idx, req->in.vector_count));
2510 print_req_vectors(req);
2513 status = smbd_smb2_request_dispatch(req);
2514 if (!NT_STATUS_IS_OK(status)) {
2515 smbd_server_connection_terminate(sconn, nt_errstr(status));
2516 return;
2519 status = smbd_smb2_request_next_incoming(sconn);
2520 if (!NT_STATUS_IS_OK(status)) {
2521 smbd_server_connection_terminate(sconn, nt_errstr(status));
2522 return;
2526 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2527 NTSTATUS status,
2528 DATA_BLOB body, DATA_BLOB *dyn,
2529 const char *location)
2531 uint8_t *outhdr;
2532 struct iovec *outbody_v;
2533 struct iovec *outdyn_v;
2534 uint32_t next_command_ofs;
2536 DEBUG(10,("smbd_smb2_request_done_ex: "
2537 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2538 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2539 dyn ? "yes": "no",
2540 (unsigned int)(dyn ? dyn->length : 0),
2541 location));
2543 if (body.length < 2) {
2544 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2547 if ((body.length % 2) != 0) {
2548 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2551 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2552 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2553 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2555 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2556 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2558 outbody_v->iov_base = (void *)body.data;
2559 outbody_v->iov_len = body.length;
2561 if (dyn) {
2562 outdyn_v->iov_base = (void *)dyn->data;
2563 outdyn_v->iov_len = dyn->length;
2564 } else {
2565 outdyn_v->iov_base = NULL;
2566 outdyn_v->iov_len = 0;
2569 /* see if we need to recalculate the offset to the next response */
2570 if (next_command_ofs > 0) {
2571 next_command_ofs = SMB2_HDR_BODY;
2572 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2573 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2576 if ((next_command_ofs % 8) != 0) {
2577 size_t pad_size = 8 - (next_command_ofs % 8);
2578 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2580 * if the dyn buffer is empty
2581 * we can use it to add padding
2583 uint8_t *pad;
2585 pad = talloc_zero_array(req,
2586 uint8_t, pad_size);
2587 if (pad == NULL) {
2588 return smbd_smb2_request_error(req,
2589 NT_STATUS_NO_MEMORY);
2592 outdyn_v->iov_base = (void *)pad;
2593 outdyn_v->iov_len = pad_size;
2594 } else {
2596 * For now we copy the dynamic buffer
2597 * and add the padding to the new buffer
2599 size_t old_size;
2600 uint8_t *old_dyn;
2601 size_t new_size;
2602 uint8_t *new_dyn;
2604 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2605 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2607 new_size = old_size + pad_size;
2608 new_dyn = talloc_zero_array(req,
2609 uint8_t, new_size);
2610 if (new_dyn == NULL) {
2611 return smbd_smb2_request_error(req,
2612 NT_STATUS_NO_MEMORY);
2615 memcpy(new_dyn, old_dyn, old_size);
2616 memset(new_dyn + old_size, 0, pad_size);
2618 outdyn_v->iov_base = (void *)new_dyn;
2619 outdyn_v->iov_len = new_size;
2621 next_command_ofs += pad_size;
2624 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2626 return smbd_smb2_request_reply(req);
2629 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2630 NTSTATUS status,
2631 DATA_BLOB *info,
2632 const char *location)
2634 DATA_BLOB body;
2635 DATA_BLOB _dyn;
2636 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2637 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2639 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2640 req->current_idx, nt_errstr(status), info ? " +info" : "",
2641 location));
2643 if (unread_bytes) {
2644 /* Recvfile error. Drain incoming socket. */
2645 size_t ret;
2647 errno = 0;
2648 ret = drain_socket(req->sconn->sock, unread_bytes);
2649 if (ret != unread_bytes) {
2650 NTSTATUS error;
2652 if (errno == 0) {
2653 error = NT_STATUS_IO_DEVICE_ERROR;
2654 } else {
2655 error = map_nt_error_from_unix_common(errno);
2658 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2659 "ret[%u] errno[%d] => %s\n",
2660 (unsigned)unread_bytes,
2661 (unsigned)ret, errno, nt_errstr(error)));
2662 return error;
2666 body.data = outhdr + SMB2_HDR_BODY;
2667 body.length = 8;
2668 SSVAL(body.data, 0, 9);
2670 if (info) {
2671 SIVAL(body.data, 0x04, info->length);
2672 } else {
2673 /* Allocated size of req->out.vector[i].iov_base
2674 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2675 * 1 byte without having to do an alloc.
2677 info = &_dyn;
2678 info->data = ((uint8_t *)outhdr) +
2679 OUTVEC_ALLOC_SIZE - 1;
2680 info->length = 1;
2681 SCVAL(info->data, 0, 0);
2685 * Note: Even if there is an error, continue to process the request.
2686 * per MS-SMB2.
2689 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2693 struct smbd_smb2_send_oplock_break_state {
2694 struct smbd_server_connection *sconn;
2695 struct smbd_smb2_send_queue queue_entry;
2696 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x18];
2697 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2700 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2701 struct smbXsrv_session *session,
2702 struct smbXsrv_tcon *tcon,
2703 struct smbXsrv_open *op,
2704 uint8_t oplock_level)
2706 struct smbd_smb2_send_oplock_break_state *state;
2707 struct smbXsrv_connection *conn = sconn->conn;
2708 uint8_t *tf;
2709 size_t tf_len;
2710 uint8_t *hdr;
2711 uint8_t *body;
2712 size_t body_len;
2713 uint8_t *dyn;
2714 size_t dyn_len;
2715 bool do_encryption = session->global->encryption_required;
2716 uint64_t nonce_high = 0;
2717 uint64_t nonce_low = 0;
2718 NTSTATUS status;
2720 if (tcon->global->encryption_required) {
2721 do_encryption = true;
2724 state = talloc_zero(sconn, struct smbd_smb2_send_oplock_break_state);
2725 if (state == NULL) {
2726 return NT_STATUS_NO_MEMORY;
2728 state->sconn = sconn;
2730 tf = state->buf + NBT_HDR_SIZE;
2731 tf_len = SMB2_TF_HDR_SIZE;
2732 hdr = tf + tf_len;
2733 body = hdr + SMB2_HDR_BODY;
2734 body_len = 0x18;
2735 dyn = body + body_len;
2736 dyn_len = 0;
2738 if (do_encryption) {
2739 nonce_high = session->nonce_high;
2740 nonce_low = session->nonce_low;
2742 session->nonce_low += 1;
2743 if (session->nonce_low == 0) {
2744 session->nonce_low += 1;
2745 session->nonce_high += 1;
2749 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2750 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2751 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2752 SBVAL(tf, SMB2_TF_SESSION_ID, session->global->session_wire_id);
2754 SIVAL(hdr, 0, SMB2_MAGIC);
2755 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2756 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2757 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2758 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2759 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2760 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2761 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2762 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2763 SIVAL(hdr, SMB2_HDR_PID, 0);
2764 SIVAL(hdr, SMB2_HDR_TID, 0);
2765 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2766 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2768 SSVAL(body, 0x00, body_len);
2770 SCVAL(body, 0x02, oplock_level);
2771 SCVAL(body, 0x03, 0); /* reserved */
2772 SIVAL(body, 0x04, 0); /* reserved */
2773 SBVAL(body, 0x08, op->global->open_persistent_id);
2774 SBVAL(body, 0x10, op->global->open_volatile_id);
2776 state->vector[0].iov_base = (void *)state->buf;
2777 state->vector[0].iov_len = NBT_HDR_SIZE;
2779 if (do_encryption) {
2780 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
2781 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
2782 } else {
2783 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
2784 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
2787 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
2788 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
2790 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
2791 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = body_len;
2793 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
2794 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_len;
2796 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2798 if (do_encryption) {
2799 DATA_BLOB encryption_key = session->global->encryption_key;
2801 status = smb2_signing_encrypt_pdu(encryption_key,
2802 conn->protocol,
2803 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2804 SMBD_SMB2_NUM_IOV_PER_REQ);
2805 if (!NT_STATUS_IS_OK(status)) {
2806 return status;
2810 state->queue_entry.mem_ctx = state;
2811 state->queue_entry.vector = state->vector;
2812 state->queue_entry.count = ARRAY_SIZE(state->vector);
2813 DLIST_ADD_END(state->sconn->smb2.send_queue, &state->queue_entry, NULL);
2814 state->sconn->smb2.send_queue_len++;
2816 status = smbd_smb2_io_handler(sconn, TEVENT_FD_WRITE);
2817 if (!NT_STATUS_IS_OK(status)) {
2818 return status;
2821 return NT_STATUS_OK;
2824 static size_t get_min_receive_file_size(struct smbd_smb2_request *smb2_req)
2826 if (smb2_req->do_signing) {
2827 return 0;
2829 if (smb2_req->do_encryption) {
2830 return 0;
2832 return (size_t)lp_min_receive_file_size();
2835 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2837 uint32_t flags;
2839 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
2840 /* Transform header. Cannot recvfile. */
2841 return false;
2843 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
2844 /* Not SMB2. Normal error path will cope. */
2845 return false;
2847 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
2848 /* Not SMB2. Normal error path will cope. */
2849 return false;
2851 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
2852 /* Needs to be a WRITE. */
2853 return false;
2855 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
2856 /* Chained. Cannot recvfile. */
2857 return false;
2859 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
2860 if (flags & SMB2_HDR_FLAG_CHAINED) {
2861 /* Chained. Cannot recvfile. */
2862 return false;
2864 if (flags & SMB2_HDR_FLAG_SIGNED) {
2865 /* Signed. Cannot recvfile. */
2866 return false;
2869 DEBUG(10,("Doing recvfile write len = %u\n",
2870 (unsigned int)(state->pktlen -
2871 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN)));
2873 return true;
2876 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2878 struct smbd_smb2_request_read_state *state = &sconn->smb2.request_read_state;
2879 size_t max_send_queue_len;
2880 size_t cur_send_queue_len;
2882 if (!NT_STATUS_IS_OK(sconn->status)) {
2884 * we're not supposed to do any io
2886 return NT_STATUS_OK;
2889 if (state->req != NULL) {
2891 * if there is already a tstream_readv_pdu
2892 * pending, we are done.
2894 return NT_STATUS_OK;
2897 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2898 cur_send_queue_len = sconn->smb2.send_queue_len;
2900 if (cur_send_queue_len > max_send_queue_len) {
2902 * if we have a lot of requests to send,
2903 * we wait until they are on the wire until we
2904 * ask for the next request.
2906 return NT_STATUS_OK;
2909 /* ask for the next request */
2910 ZERO_STRUCTP(state);
2911 state->req = smbd_smb2_request_allocate(sconn);
2912 if (state->req == NULL) {
2913 return NT_STATUS_NO_MEMORY;
2915 state->req->sconn = sconn;
2916 state->min_recv_size = get_min_receive_file_size(state->req);
2918 TEVENT_FD_READABLE(sconn->smb2.fde);
2920 return NT_STATUS_OK;
2923 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2924 uint8_t *inbuf, size_t size)
2926 NTSTATUS status;
2927 struct smbd_smb2_request *req = NULL;
2929 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2930 (unsigned int)size));
2932 status = smbd_initialize_smb2(sconn);
2933 if (!NT_STATUS_IS_OK(status)) {
2934 smbd_server_connection_terminate(sconn, nt_errstr(status));
2935 return;
2938 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2939 if (!NT_STATUS_IS_OK(status)) {
2940 smbd_server_connection_terminate(sconn, nt_errstr(status));
2941 return;
2944 status = smbd_smb2_request_validate(req);
2945 if (!NT_STATUS_IS_OK(status)) {
2946 smbd_server_connection_terminate(sconn, nt_errstr(status));
2947 return;
2950 status = smbd_smb2_request_setup_out(req);
2951 if (!NT_STATUS_IS_OK(status)) {
2952 smbd_server_connection_terminate(sconn, nt_errstr(status));
2953 return;
2956 status = smbd_smb2_request_dispatch(req);
2957 if (!NT_STATUS_IS_OK(status)) {
2958 smbd_server_connection_terminate(sconn, nt_errstr(status));
2959 return;
2962 status = smbd_smb2_request_next_incoming(sconn);
2963 if (!NT_STATUS_IS_OK(status)) {
2964 smbd_server_connection_terminate(sconn, nt_errstr(status));
2965 return;
2968 sconn->num_requests++;
2971 static int socket_error_from_errno(int ret,
2972 int sys_errno,
2973 bool *retry)
2975 *retry = false;
2977 if (ret >= 0) {
2978 return 0;
2981 if (ret != -1) {
2982 return EIO;
2985 if (sys_errno == 0) {
2986 return EIO;
2989 if (sys_errno == EINTR) {
2990 *retry = true;
2991 return sys_errno;
2994 if (sys_errno == EINPROGRESS) {
2995 *retry = true;
2996 return sys_errno;
2999 if (sys_errno == EAGAIN) {
3000 *retry = true;
3001 return sys_errno;
3004 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3005 if (sys_errno == ENOMEM) {
3006 *retry = true;
3007 return sys_errno;
3010 #ifdef EWOULDBLOCK
3011 #if EWOULDBLOCK != EAGAIN
3012 if (sys_errno == EWOULDBLOCK) {
3013 *retry = true;
3014 return sys_errno;
3016 #endif
3017 #endif
3019 return sys_errno;
3022 static NTSTATUS smbd_smb2_flush_send_queue(struct smbd_server_connection *sconn)
3024 int ret;
3025 int err;
3026 bool retry;
3028 if (sconn->smb2.send_queue == NULL) {
3029 TEVENT_FD_NOT_WRITEABLE(sconn->smb2.fde);
3030 return NT_STATUS_OK;
3033 while (sconn->smb2.send_queue != NULL) {
3034 struct smbd_smb2_send_queue *e = sconn->smb2.send_queue;
3036 if (e->sendfile_header != NULL) {
3037 size_t size = 0;
3038 size_t i = 0;
3039 uint8_t *buf;
3041 for (i=0; i < e->count; i++) {
3042 size += e->vector[i].iov_len;
3045 if (size <= e->sendfile_header->length) {
3046 buf = e->sendfile_header->data;
3047 } else {
3048 buf = talloc_array(e->mem_ctx, uint8_t, size);
3049 if (buf == NULL) {
3050 return NT_STATUS_NO_MEMORY;
3054 size = 0;
3055 for (i=0; i < e->count; i++) {
3056 memcpy(buf+size,
3057 e->vector[i].iov_base,
3058 e->vector[i].iov_len);
3059 size += e->vector[i].iov_len;
3062 e->sendfile_header->data = buf;
3063 e->sendfile_header->length = size;
3064 e->count = 0;
3066 sconn->smb2.send_queue_len--;
3067 DLIST_REMOVE(sconn->smb2.send_queue, e);
3069 * This triggers the sendfile path via
3070 * the destructor.
3072 talloc_free(e->mem_ctx);
3073 continue;
3076 ret = writev(sconn->sock, e->vector, e->count);
3077 if (ret == 0) {
3078 /* propagate end of file */
3079 return NT_STATUS_INTERNAL_ERROR;
3081 err = socket_error_from_errno(ret, errno, &retry);
3082 if (retry) {
3083 /* retry later */
3084 TEVENT_FD_WRITEABLE(sconn->smb2.fde);
3085 return NT_STATUS_OK;
3087 if (err != 0) {
3088 return map_nt_error_from_unix_common(err);
3090 while (ret > 0) {
3091 if (ret < e->vector[0].iov_len) {
3092 uint8_t *base;
3093 base = (uint8_t *)e->vector[0].iov_base;
3094 base += ret;
3095 e->vector[0].iov_base = (void *)base;
3096 e->vector[0].iov_len -= ret;
3097 break;
3099 ret -= e->vector[0].iov_len;
3100 e->vector += 1;
3101 e->count -= 1;
3105 * there're maybe some empty vectors at the end
3106 * which we need to skip, otherwise we would get
3107 * ret == 0 from the readv() call and return EPIPE
3109 while (e->count > 0) {
3110 if (e->vector[0].iov_len > 0) {
3111 break;
3113 e->vector += 1;
3114 e->count -= 1;
3117 if (e->count > 0) {
3118 /* we have more to write */
3119 TEVENT_FD_WRITEABLE(sconn->smb2.fde);
3120 return NT_STATUS_OK;
3123 sconn->smb2.send_queue_len--;
3124 DLIST_REMOVE(sconn->smb2.send_queue, e);
3125 talloc_free(e->mem_ctx);
3128 return NT_STATUS_OK;
3131 static NTSTATUS smbd_smb2_io_handler(struct smbd_server_connection *sconn,
3132 uint16_t fde_flags)
3134 struct smbd_smb2_request_read_state *state = &sconn->smb2.request_read_state;
3135 struct smbd_smb2_request *req = NULL;
3136 size_t min_recvfile_size = UINT32_MAX;
3137 int ret;
3138 int err;
3139 bool retry;
3140 NTSTATUS status;
3141 NTTIME now;
3143 if (!NT_STATUS_IS_OK(sconn->status)) {
3145 * we're not supposed to do any io
3147 TEVENT_FD_NOT_READABLE(sconn->smb2.fde);
3148 TEVENT_FD_NOT_WRITEABLE(sconn->smb2.fde);
3149 return NT_STATUS_OK;
3152 if (fde_flags & TEVENT_FD_WRITE) {
3153 status = smbd_smb2_flush_send_queue(sconn);
3154 if (!NT_STATUS_IS_OK(status)) {
3155 return status;
3159 if (!(fde_flags & TEVENT_FD_READ)) {
3160 return NT_STATUS_OK;
3163 if (state->req == NULL) {
3164 TEVENT_FD_NOT_READABLE(sconn->smb2.fde);
3165 return NT_STATUS_OK;
3168 again:
3169 if (!state->hdr.done) {
3170 state->hdr.done = true;
3172 state->vector.iov_base = (void *)state->hdr.nbt;
3173 state->vector.iov_len = NBT_HDR_SIZE;
3176 ret = readv(sconn->sock, &state->vector, 1);
3177 if (ret == 0) {
3178 /* propagate end of file */
3179 return NT_STATUS_END_OF_FILE;
3181 err = socket_error_from_errno(ret, errno, &retry);
3182 if (retry) {
3183 /* retry later */
3184 TEVENT_FD_READABLE(sconn->smb2.fde);
3185 return NT_STATUS_OK;
3187 if (err != 0) {
3188 return map_nt_error_from_unix_common(err);
3191 if (ret < state->vector.iov_len) {
3192 uint8_t *base;
3193 base = (uint8_t *)state->vector.iov_base;
3194 base += ret;
3195 state->vector.iov_base = (void *)base;
3196 state->vector.iov_len -= ret;
3197 /* we have more to read */
3198 TEVENT_FD_READABLE(sconn->smb2.fde);
3199 return NT_STATUS_OK;
3202 if (state->pktlen > 0) {
3203 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3205 * Not a possible receivefile write.
3206 * Read the rest of the data.
3208 state->doing_receivefile = false;
3209 state->vector.iov_base = (void *)(state->pktbuf +
3210 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN);
3211 state->vector.iov_len = (state->pktlen -
3212 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN);
3213 goto again;
3217 * Either this is a receivefile write so we've
3218 * done a short read, or if not we have all the data.
3220 goto got_full;
3224 * Now we analyze the NBT header
3226 state->pktlen = smb2_len(state->hdr.nbt);
3227 if (state->pktlen == 0) {
3228 goto got_full;
3231 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3232 if (state->pktbuf == NULL) {
3233 return NT_STATUS_NO_MEMORY;
3236 state->vector.iov_base = (void *)state->pktbuf;
3238 if (state->min_recv_size != 0) {
3239 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3240 min_recvfile_size += state->min_recv_size;
3243 if (state->pktlen > min_recvfile_size) {
3245 * Might be a receivefile write. Read the SMB2 HEADER +
3246 * SMB2_WRITE header first. Set 'doing_receivefile'
3247 * as we're *attempting* receivefile write. If this
3248 * turns out not to be a SMB2_WRITE request or otherwise
3249 * not suitable then we'll just read the rest of the data
3250 * the next time this function is called.
3252 state->vector.iov_len = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3253 state->doing_receivefile = true;
3254 } else {
3255 state->vector.iov_len = state->pktlen;
3258 goto again;
3260 got_full:
3262 if (state->hdr.nbt[0] != 0x00) {
3263 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3264 state->hdr.nbt[0]));
3266 req = state->req;
3267 ZERO_STRUCTP(state);
3268 state->req = req;
3269 state->min_recv_size = get_min_receive_file_size(state->req);
3270 req = NULL;
3271 goto again;
3274 req = state->req;
3275 state->req = NULL;
3277 req->request_time = timeval_current();
3278 now = timeval_to_nttime(&req->request_time);
3280 status = smbd_smb2_inbuf_parse_compound(req->sconn->conn,
3281 now,
3282 state->pktbuf,
3283 state->pktlen,
3284 req,
3285 &req->in.vector,
3286 &req->in.vector_count);
3287 if (!NT_STATUS_IS_OK(status)) {
3288 return status;
3291 if (state->doing_receivefile) {
3292 req->smb1req = talloc_zero(req, struct smb_request);
3293 if (req->smb1req == NULL) {
3294 return NT_STATUS_NO_MEMORY;
3296 req->smb1req->unread_bytes =
3297 state->pktlen - SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3300 ZERO_STRUCTP(state);
3302 req->current_idx = 1;
3304 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3305 req->current_idx, req->in.vector_count));
3307 status = smbd_smb2_request_validate(req);
3308 if (!NT_STATUS_IS_OK(status)) {
3309 return status;
3312 status = smbd_smb2_request_setup_out(req);
3313 if (!NT_STATUS_IS_OK(status)) {
3314 return status;
3317 status = smbd_smb2_request_dispatch(req);
3318 if (!NT_STATUS_IS_OK(status)) {
3319 return status;
3322 sconn->num_requests++;
3324 /* The timeout_processing function isn't run nearly
3325 often enough to implement 'max log size' without
3326 overrunning the size of the file by many megabytes.
3327 This is especially true if we are running at debug
3328 level 10. Checking every 50 SMB2s is a nice
3329 tradeoff of performance vs log file size overrun. */
3331 if ((sconn->num_requests % 50) == 0 &&
3332 need_to_check_log_size()) {
3333 change_to_root_user();
3334 check_log_size();
3337 status = smbd_smb2_request_next_incoming(sconn);
3338 if (!NT_STATUS_IS_OK(status)) {
3339 return status;
3342 return NT_STATUS_OK;
3345 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3346 struct tevent_fd *fde,
3347 uint16_t flags,
3348 void *private_data)
3350 struct smbd_server_connection *sconn =
3351 talloc_get_type_abort(private_data,
3352 struct smbd_server_connection);
3353 NTSTATUS status;
3355 status = smbd_smb2_io_handler(sconn, flags);
3356 if (!NT_STATUS_IS_OK(status)) {
3357 smbd_server_connection_terminate(sconn, nt_errstr(status));
3358 return;