s3:smb2_server: correctly maintain request counters for compound requests
[Samba.git] / source3 / smbd / smb2_server.c
blob177e5ffc2f2fba98354ea40b997261184c22ba89
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 "lib/util/iov_buf.h"
32 #include "auth.h"
33 #include "lib/crypto/sha512.h"
35 #undef DBGC_CLASS
36 #define DBGC_CLASS DBGC_SMB2
38 static void smbd_smb2_connection_handler(struct tevent_context *ev,
39 struct tevent_fd *fde,
40 uint16_t flags,
41 void *private_data);
42 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn);
44 static const struct smbd_smb2_dispatch_table {
45 uint16_t opcode;
46 const char *name;
47 bool need_session;
48 bool need_tcon;
49 bool as_root;
50 uint16_t fileid_ofs;
51 bool allow_invalid_fileid;
52 bool modify;
53 } smbd_smb2_table[] = {
54 #define _OP(o) .opcode = o, .name = #o
56 _OP(SMB2_OP_NEGPROT),
57 .as_root = true,
58 },{
59 _OP(SMB2_OP_SESSSETUP),
60 .as_root = true,
61 },{
62 _OP(SMB2_OP_LOGOFF),
63 .need_session = true,
64 .as_root = true,
65 },{
66 _OP(SMB2_OP_TCON),
67 .need_session = true,
69 * This call needs to be run as root.
71 * smbd_smb2_request_process_tcon()
72 * calls make_connection_snum(), which will call
73 * change_to_user(), when needed.
75 .as_root = true,
76 },{
77 _OP(SMB2_OP_TDIS),
78 .need_session = true,
79 .need_tcon = true,
80 .as_root = true,
81 },{
82 _OP(SMB2_OP_CREATE),
83 .need_session = true,
84 .need_tcon = true,
85 },{
86 _OP(SMB2_OP_CLOSE),
87 .need_session = true,
88 .need_tcon = true,
89 .fileid_ofs = 0x08,
90 },{
91 _OP(SMB2_OP_FLUSH),
92 .need_session = true,
93 .need_tcon = true,
94 .fileid_ofs = 0x08,
95 },{
96 _OP(SMB2_OP_READ),
97 .need_session = true,
98 .need_tcon = true,
99 .fileid_ofs = 0x10,
101 _OP(SMB2_OP_WRITE),
102 .need_session = true,
103 .need_tcon = true,
104 .fileid_ofs = 0x10,
105 .modify = true,
107 _OP(SMB2_OP_LOCK),
108 .need_session = true,
109 .need_tcon = true,
110 .fileid_ofs = 0x08,
112 _OP(SMB2_OP_IOCTL),
113 .need_session = true,
114 .need_tcon = true,
115 .fileid_ofs = 0x08,
116 .allow_invalid_fileid = true,
117 .modify = true,
119 _OP(SMB2_OP_CANCEL),
120 .as_root = true,
122 _OP(SMB2_OP_KEEPALIVE),
123 .as_root = true,
125 _OP(SMB2_OP_QUERY_DIRECTORY),
126 .need_session = true,
127 .need_tcon = true,
128 .fileid_ofs = 0x08,
130 _OP(SMB2_OP_NOTIFY),
131 .need_session = true,
132 .need_tcon = true,
133 .fileid_ofs = 0x08,
135 _OP(SMB2_OP_GETINFO),
136 .need_session = true,
137 .need_tcon = true,
138 .fileid_ofs = 0x18,
140 _OP(SMB2_OP_SETINFO),
141 .need_session = true,
142 .need_tcon = true,
143 .fileid_ofs = 0x10,
144 .modify = true,
146 _OP(SMB2_OP_BREAK),
147 .need_session = true,
148 .need_tcon = true,
150 * we do not set
151 * .fileid_ofs here
152 * as LEASE breaks does not
153 * have a file id
158 const char *smb2_opcode_name(uint16_t opcode)
160 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
161 return "Bad SMB2 opcode";
163 return smbd_smb2_table[opcode].name;
166 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
168 const struct smbd_smb2_dispatch_table *ret = NULL;
170 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
171 return NULL;
174 ret = &smbd_smb2_table[opcode];
176 SMB_ASSERT(ret->opcode == opcode);
178 return ret;
181 static void print_req_vectors(const struct smbd_smb2_request *req)
183 int i;
185 for (i = 0; i < req->in.vector_count; i++) {
186 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
187 (unsigned int)i,
188 (unsigned int)req->in.vector[i].iov_len);
190 for (i = 0; i < req->out.vector_count; i++) {
191 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
192 (unsigned int)i,
193 (unsigned int)req->out.vector[i].iov_len);
197 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
199 if (size < (4 + SMB2_HDR_BODY)) {
200 return false;
203 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
204 return false;
207 return true;
210 bool smbd_smb2_is_compound(const struct smbd_smb2_request *req)
212 return req->in.vector_count >= (2*SMBD_SMB2_NUM_IOV_PER_REQ);
215 static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn,
216 uint64_t expected_seq_low)
218 TALLOC_FREE(xconn->transport.fde);
220 xconn->smb2.credits.seq_low = expected_seq_low;
221 xconn->smb2.credits.seq_range = 1;
222 xconn->smb2.credits.granted = 1;
223 xconn->smb2.credits.max = lp_smb2_max_credits();
224 xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
225 xconn->smb2.credits.max);
226 if (xconn->smb2.credits.bitmap == NULL) {
227 return NT_STATUS_NO_MEMORY;
230 xconn->transport.fde = tevent_add_fd(xconn->ev_ctx,
231 xconn,
232 xconn->transport.sock,
233 TEVENT_FD_READ,
234 smbd_smb2_connection_handler,
235 xconn);
236 if (xconn->transport.fde == NULL) {
237 return NT_STATUS_NO_MEMORY;
240 /* Ensure child is set to non-blocking mode */
241 set_blocking(xconn->transport.sock, false);
242 return NT_STATUS_OK;
245 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
246 #define _smb2_setlen(_buf,len) do { \
247 uint8_t *buf = (uint8_t *)_buf; \
248 buf[0] = 0; \
249 buf[1] = ((len)&0xFF0000)>>16; \
250 buf[2] = ((len)&0xFF00)>>8; \
251 buf[3] = (len)&0xFF; \
252 } while (0)
254 static bool smb2_setup_nbt_length(struct iovec *vector, int count)
256 ssize_t len;
258 if (count == 0) {
259 return false;
262 len = iov_buflen(vector+1, count-1);
264 if ((len == -1) || (len > 0xFFFFFF)) {
265 return false;
268 _smb2_setlen(vector[0].iov_base, len);
269 return true;
272 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
274 if (req->first_key.length > 0) {
275 data_blob_clear_free(&req->first_key);
277 if (req->last_key.length > 0) {
278 data_blob_clear_free(&req->last_key);
280 return 0;
283 void smb2_request_set_async_internal(struct smbd_smb2_request *req,
284 bool async_internal)
286 req->async_internal = async_internal;
289 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
291 TALLOC_CTX *mem_pool;
292 struct smbd_smb2_request *req;
294 #if 0
295 /* Enable this to find subtle valgrind errors. */
296 mem_pool = talloc_init("smbd_smb2_request_allocate");
297 #else
298 mem_pool = talloc_tos();
299 #endif
300 if (mem_pool == NULL) {
301 return NULL;
304 req = talloc_zero(mem_pool, struct smbd_smb2_request);
305 if (req == NULL) {
306 talloc_free(mem_pool);
307 return NULL;
309 talloc_reparent(mem_pool, mem_ctx, req);
310 #if 0
311 TALLOC_FREE(mem_pool);
312 #endif
314 req->last_session_id = UINT64_MAX;
315 req->last_tid = UINT32_MAX;
317 talloc_set_destructor(req, smbd_smb2_request_destructor);
319 return req;
322 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
323 NTTIME now,
324 uint8_t *buf,
325 size_t buflen,
326 struct smbd_smb2_request *req,
327 struct iovec **piov,
328 int *pnum_iov)
330 TALLOC_CTX *mem_ctx = req;
331 struct iovec *iov;
332 int num_iov = 1;
333 size_t taken = 0;
334 uint8_t *first_hdr = buf;
335 size_t verified_buflen = 0;
336 uint8_t *tf = NULL;
337 size_t tf_len = 0;
340 * Note: index '0' is reserved for the transport protocol
342 iov = req->in._vector;
344 while (taken < buflen) {
345 size_t len = buflen - taken;
346 uint8_t *hdr = first_hdr + taken;
347 struct iovec *cur;
348 size_t full_size;
349 size_t next_command_ofs;
350 uint16_t body_size;
351 uint8_t *body = NULL;
352 uint32_t dyn_size;
353 uint8_t *dyn = NULL;
354 struct iovec *iov_alloc = NULL;
356 if (iov != req->in._vector) {
357 iov_alloc = iov;
360 if (verified_buflen > taken) {
361 len = verified_buflen - taken;
362 } else {
363 tf = NULL;
364 tf_len = 0;
367 if (len < 4) {
368 DEBUG(10, ("%d bytes left, expected at least %d\n",
369 (int)len, 4));
370 goto inval;
372 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
373 struct smbXsrv_session *s = NULL;
374 uint64_t uid;
375 struct iovec tf_iov[2];
376 NTSTATUS status;
377 size_t enc_len;
379 if (xconn->protocol < PROTOCOL_SMB2_24) {
380 DEBUG(10, ("Got SMB2_TRANSFORM header, "
381 "but dialect[0x%04X] is used\n",
382 xconn->smb2.server.dialect));
383 goto inval;
386 if (xconn->smb2.server.cipher == 0) {
387 DEBUG(10, ("Got SMB2_TRANSFORM header, "
388 "but not negotiated "
389 "client[0x%08X] server[0x%08X]\n",
390 xconn->smb2.client.capabilities,
391 xconn->smb2.server.capabilities));
392 goto inval;
395 if (len < SMB2_TF_HDR_SIZE) {
396 DEBUG(1, ("%d bytes left, expected at least %d\n",
397 (int)len, SMB2_TF_HDR_SIZE));
398 goto inval;
400 tf = hdr;
401 tf_len = SMB2_TF_HDR_SIZE;
402 taken += tf_len;
404 hdr = first_hdr + taken;
405 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
406 uid = BVAL(tf, SMB2_TF_SESSION_ID);
408 if (len < SMB2_TF_HDR_SIZE + enc_len) {
409 DEBUG(1, ("%d bytes left, expected at least %d\n",
410 (int)len,
411 (int)(SMB2_TF_HDR_SIZE + enc_len)));
412 goto inval;
415 status = smb2srv_session_lookup_conn(xconn, uid, now,
416 &s);
417 if (s == NULL) {
418 DEBUG(1, ("invalid session[%llu] in "
419 "SMB2_TRANSFORM header\n",
420 (unsigned long long)uid));
421 TALLOC_FREE(iov_alloc);
422 return NT_STATUS_USER_SESSION_DELETED;
425 tf_iov[0].iov_base = (void *)tf;
426 tf_iov[0].iov_len = tf_len;
427 tf_iov[1].iov_base = (void *)hdr;
428 tf_iov[1].iov_len = enc_len;
430 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
431 xconn->smb2.server.cipher,
432 tf_iov, 2);
433 if (!NT_STATUS_IS_OK(status)) {
434 TALLOC_FREE(iov_alloc);
435 return status;
438 verified_buflen = taken + enc_len;
439 len = enc_len;
443 * We need the header plus the body length field
446 if (len < SMB2_HDR_BODY + 2) {
447 DEBUG(10, ("%d bytes left, expected at least %d\n",
448 (int)len, SMB2_HDR_BODY));
449 goto inval;
451 if (IVAL(hdr, 0) != SMB2_MAGIC) {
452 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
453 IVAL(hdr, 0)));
454 goto inval;
456 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
457 DEBUG(10, ("Got HDR len %d, expected %d\n",
458 SVAL(hdr, 4), SMB2_HDR_BODY));
459 goto inval;
462 full_size = len;
463 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
464 body_size = SVAL(hdr, SMB2_HDR_BODY);
466 if (next_command_ofs != 0) {
467 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
468 goto inval;
470 if (next_command_ofs > full_size) {
471 goto inval;
473 full_size = next_command_ofs;
475 if (body_size < 2) {
476 goto inval;
478 body_size &= 0xfffe;
480 if (body_size > (full_size - SMB2_HDR_BODY)) {
482 * let the caller handle the error
484 body_size = full_size - SMB2_HDR_BODY;
486 body = hdr + SMB2_HDR_BODY;
487 dyn = body + body_size;
488 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
490 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
491 struct iovec *iov_tmp = NULL;
493 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
494 struct iovec,
495 num_iov +
496 SMBD_SMB2_NUM_IOV_PER_REQ);
497 if (iov_tmp == NULL) {
498 TALLOC_FREE(iov_alloc);
499 return NT_STATUS_NO_MEMORY;
502 if (iov_alloc == NULL) {
503 memcpy(iov_tmp,
504 req->in._vector,
505 sizeof(req->in._vector));
508 iov = iov_tmp;
510 cur = &iov[num_iov];
511 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
513 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
514 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
515 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
516 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
517 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
518 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
519 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
520 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
522 taken += full_size;
525 *piov = iov;
526 *pnum_iov = num_iov;
527 return NT_STATUS_OK;
529 inval:
530 if (iov != req->in._vector) {
531 TALLOC_FREE(iov);
533 return NT_STATUS_INVALID_PARAMETER;
536 static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
537 const uint8_t *_inpdu, size_t size,
538 struct smbd_smb2_request **_req)
540 struct smbd_server_connection *sconn = xconn->client->sconn;
541 struct smbd_smb2_request *req;
542 uint32_t protocol_version;
543 uint8_t *inpdu = NULL;
544 const uint8_t *inhdr = NULL;
545 uint16_t cmd;
546 uint32_t next_command_ofs;
547 NTSTATUS status;
548 NTTIME now;
550 if (size < (SMB2_HDR_BODY + 2)) {
551 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
552 return NT_STATUS_INVALID_PARAMETER;
555 inhdr = _inpdu;
557 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
558 if (protocol_version != SMB2_MAGIC) {
559 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
560 protocol_version));
561 return NT_STATUS_INVALID_PARAMETER;
564 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
565 if (cmd != SMB2_OP_NEGPROT) {
566 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
567 cmd));
568 return NT_STATUS_INVALID_PARAMETER;
571 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
572 if (next_command_ofs != 0) {
573 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
574 next_command_ofs));
575 return NT_STATUS_INVALID_PARAMETER;
578 req = smbd_smb2_request_allocate(xconn);
579 if (req == NULL) {
580 return NT_STATUS_NO_MEMORY;
582 req->sconn = sconn;
583 req->xconn = xconn;
585 inpdu = talloc_memdup(req, _inpdu, size);
586 if (inpdu == NULL) {
587 return NT_STATUS_NO_MEMORY;
590 req->request_time = timeval_current();
591 now = timeval_to_nttime(&req->request_time);
593 status = smbd_smb2_inbuf_parse_compound(xconn,
594 now,
595 inpdu,
596 size,
597 req, &req->in.vector,
598 &req->in.vector_count);
599 if (!NT_STATUS_IS_OK(status)) {
600 TALLOC_FREE(req);
601 return status;
604 req->current_idx = 1;
606 *_req = req;
607 return NT_STATUS_OK;
610 static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
611 uint64_t message_id, uint64_t seq_id)
613 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
614 unsigned int offset;
615 uint64_t seq_tmp;
617 seq_tmp = xconn->smb2.credits.seq_low;
618 if (seq_id < seq_tmp) {
619 DBGC_ERR(DBGC_SMB2_CREDITS,
620 "smb2_validate_sequence_number: bad message_id "
621 "%llu (sequence id %llu) "
622 "(granted = %u, low = %llu, range = %u)\n",
623 (unsigned long long)message_id,
624 (unsigned long long)seq_id,
625 (unsigned int)xconn->smb2.credits.granted,
626 (unsigned long long)xconn->smb2.credits.seq_low,
627 (unsigned int)xconn->smb2.credits.seq_range);
628 return false;
631 seq_tmp += xconn->smb2.credits.seq_range;
632 if (seq_id >= seq_tmp) {
633 DBGC_ERR(DBGC_SMB2_CREDITS,
634 "smb2_validate_sequence_number: bad message_id "
635 "%llu (sequence id %llu) "
636 "(granted = %u, low = %llu, range = %u)\n",
637 (unsigned long long)message_id,
638 (unsigned long long)seq_id,
639 (unsigned int)xconn->smb2.credits.granted,
640 (unsigned long long)xconn->smb2.credits.seq_low,
641 (unsigned int)xconn->smb2.credits.seq_range);
642 return false;
645 offset = seq_id % xconn->smb2.credits.max;
647 if (bitmap_query(credits_bm, offset)) {
648 DBGC_ERR(DBGC_SMB2_CREDITS,
649 "smb2_validate_sequence_number: duplicate message_id "
650 "%llu (sequence id %llu) "
651 "(granted = %u, low = %llu, range = %u) "
652 "(bm offset %u)\n",
653 (unsigned long long)message_id,
654 (unsigned long long)seq_id,
655 (unsigned int)xconn->smb2.credits.granted,
656 (unsigned long long)xconn->smb2.credits.seq_low,
657 (unsigned int)xconn->smb2.credits.seq_range,
658 offset);
659 return false;
662 /* Mark the message_ids as seen in the bitmap. */
663 bitmap_set(credits_bm, offset);
665 if (seq_id != xconn->smb2.credits.seq_low) {
666 return true;
670 * Move the window forward by all the message_id's
671 * already seen.
673 while (bitmap_query(credits_bm, offset)) {
674 DBGC_DEBUG(DBGC_SMB2_CREDITS,
675 "smb2_validate_sequence_number: clearing "
676 "id %llu (position %u) from bitmap\n",
677 (unsigned long long)(xconn->smb2.credits.seq_low),
678 offset);
679 bitmap_clear(credits_bm, offset);
681 xconn->smb2.credits.seq_low += 1;
682 xconn->smb2.credits.seq_range -= 1;
683 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
686 return true;
689 static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
690 const uint8_t *inhdr)
692 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
693 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
694 uint16_t credit_charge = 1;
695 uint64_t i;
697 if (opcode == SMB2_OP_CANCEL) {
698 /* SMB2_CANCEL requests by definition resend messageids. */
699 return true;
702 if (xconn->smb2.credits.multicredit) {
703 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
704 credit_charge = MAX(credit_charge, 1);
707 DEBUGC(11,
708 DBGC_SMB2_CREDITS,
709 ("smb2_validate_message_id: mid %llu (charge %llu), "
710 "credits_granted %llu, "
711 "seqnum low/range: %llu/%llu\n",
712 (unsigned long long) message_id,
713 (unsigned long long) credit_charge,
714 (unsigned long long) xconn->smb2.credits.granted,
715 (unsigned long long) xconn->smb2.credits.seq_low,
716 (unsigned long long) xconn->smb2.credits.seq_range));
718 if (xconn->smb2.credits.granted < credit_charge) {
719 DBGC_ERR(DBGC_SMB2_CREDITS,
720 "smb2_validate_message_id: client used more "
721 "credits than granted, mid %llu, charge %llu, "
722 "credits_granted %llu, "
723 "seqnum low/range: %llu/%llu\n",
724 (unsigned long long) message_id,
725 (unsigned long long) credit_charge,
726 (unsigned long long) xconn->smb2.credits.granted,
727 (unsigned long long) xconn->smb2.credits.seq_low,
728 (unsigned long long) xconn->smb2.credits.seq_range);
729 return false;
733 * now check the message ids
735 * for multi-credit requests we need to check all current mid plus
736 * the implicit mids caused by the credit charge
737 * e.g. current mid = 15, charge 5 => mark 15-19 as used
740 for (i = 0; i <= (credit_charge-1); i++) {
741 uint64_t id = message_id + i;
742 bool ok;
744 DEBUGC(11,
745 DBGC_SMB2_CREDITS,
746 ("Iterating mid %llu charge %u (sequence %llu)\n",
747 (unsigned long long)message_id,
748 credit_charge,
749 (unsigned long long)id));
751 ok = smb2_validate_sequence_number(xconn, message_id, id);
752 if (!ok) {
753 return false;
757 /* substract used credits */
758 xconn->smb2.credits.granted -= credit_charge;
760 return true;
763 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
765 int count;
766 int idx;
768 count = req->in.vector_count;
770 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
771 /* It's not a SMB2 request */
772 return NT_STATUS_INVALID_PARAMETER;
775 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
776 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
777 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
778 const uint8_t *inhdr = NULL;
780 if (hdr->iov_len != SMB2_HDR_BODY) {
781 return NT_STATUS_INVALID_PARAMETER;
784 if (body->iov_len < 2) {
785 return NT_STATUS_INVALID_PARAMETER;
788 inhdr = (const uint8_t *)hdr->iov_base;
790 /* Check the SMB2 header */
791 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
792 return NT_STATUS_INVALID_PARAMETER;
795 if (!smb2_validate_message_id(req->xconn, inhdr)) {
796 return NT_STATUS_INVALID_PARAMETER;
800 return NT_STATUS_OK;
803 static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
804 const struct iovec *in_vector,
805 struct iovec *out_vector)
807 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
808 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
809 uint16_t credit_charge = 1;
810 uint16_t credits_requested;
811 uint32_t out_flags;
812 uint16_t cmd;
813 NTSTATUS out_status;
814 uint16_t credits_granted = 0;
815 uint64_t credits_possible;
816 uint16_t current_max_credits;
819 * first we grant only 1/16th of the max range.
821 * Windows also starts with the 1/16th and then grants
822 * more later. I was only able to trigger higher
823 * values, when using a very high credit charge.
825 * TODO: scale up depending on load, free memory
826 * or other stuff.
827 * Maybe also on the relationship between number
828 * of requests and the used sequence number.
829 * Which means we would grant more credits
830 * for client which use multi credit requests.
832 current_max_credits = xconn->smb2.credits.max / 16;
833 current_max_credits = MAX(current_max_credits, 1);
835 if (xconn->smb2.credits.multicredit) {
836 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
837 credit_charge = MAX(credit_charge, 1);
840 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
841 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
842 credits_requested = MAX(credits_requested, 1);
843 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
844 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
846 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
848 if (xconn->smb2.credits.max < credit_charge) {
849 smbd_server_connection_terminate(xconn,
850 "client error: credit charge > max credits\n");
851 return;
854 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
856 * In case we already send an async interim
857 * response, we should not grant
858 * credits on the final response.
860 credits_granted = 0;
861 } else {
862 uint16_t additional_possible =
863 xconn->smb2.credits.max - credit_charge;
864 uint16_t additional_max = 0;
865 uint16_t additional_credits = credits_requested - 1;
867 switch (cmd) {
868 case SMB2_OP_NEGPROT:
869 break;
870 case SMB2_OP_SESSSETUP:
872 * Windows 2012 RC1 starts to grant
873 * additional credits
874 * with a successful session setup
876 if (NT_STATUS_IS_OK(out_status)) {
877 additional_max = 32;
879 break;
880 default:
882 * We match windows and only grant additional credits
883 * in chunks of 32.
885 additional_max = 32;
886 break;
889 additional_max = MIN(additional_max, additional_possible);
890 additional_credits = MIN(additional_credits, additional_max);
892 credits_granted = credit_charge + additional_credits;
896 * sequence numbers should not wrap
898 * 1. calculate the possible credits until
899 * the sequence numbers start to wrap on 64-bit.
901 * 2. UINT64_MAX is used for Break Notifications.
903 * 2. truncate the possible credits to the maximum
904 * credits we want to grant to the client in total.
906 * 3. remove the range we'll already granted to the client
907 * this makes sure the client consumes the lowest sequence
908 * number, before we can grant additional credits.
910 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
911 if (credits_possible > 0) {
912 /* remove UINT64_MAX */
913 credits_possible -= 1;
915 credits_possible = MIN(credits_possible, current_max_credits);
916 credits_possible -= xconn->smb2.credits.seq_range;
918 credits_granted = MIN(credits_granted, credits_possible);
920 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
921 xconn->smb2.credits.granted += credits_granted;
922 xconn->smb2.credits.seq_range += credits_granted;
924 DBGC_DEBUG(DBGC_SMB2_CREDITS,
925 "smb2_set_operation_credit: requested %u, charge %u, "
926 "granted %u, current possible/max %u/%u, "
927 "total granted/max/low/range %u/%u/%llu/%u\n",
928 (unsigned int)credits_requested,
929 (unsigned int)credit_charge,
930 (unsigned int)credits_granted,
931 (unsigned int)credits_possible,
932 (unsigned int)current_max_credits,
933 (unsigned int)xconn->smb2.credits.granted,
934 (unsigned int)xconn->smb2.credits.max,
935 (unsigned long long)xconn->smb2.credits.seq_low,
936 (unsigned int)xconn->smb2.credits.seq_range);
939 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
940 struct smbd_smb2_request *outreq)
942 int count, idx;
943 uint16_t total_credits = 0;
945 count = outreq->out.vector_count;
947 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
948 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
949 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
950 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
952 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
954 /* To match Windows, count up what we
955 just granted. */
956 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
957 /* Set to zero in all but the last reply. */
958 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
959 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
960 } else {
961 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
966 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
968 if (req->current_idx <= 1) {
969 if (size <= sizeof(req->out._body)) {
970 return data_blob_const(req->out._body, size);
974 return data_blob_talloc(req, NULL, size);
977 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
979 struct smbXsrv_connection *xconn = req->xconn;
980 TALLOC_CTX *mem_ctx;
981 struct iovec *vector;
982 int count;
983 int idx;
984 bool ok;
986 count = req->in.vector_count;
987 if (count <= ARRAY_SIZE(req->out._vector)) {
988 mem_ctx = req;
989 vector = req->out._vector;
990 } else {
991 vector = talloc_zero_array(req, struct iovec, count);
992 if (vector == NULL) {
993 return NT_STATUS_NO_MEMORY;
995 mem_ctx = vector;
998 vector[0].iov_base = req->out.nbt_hdr;
999 vector[0].iov_len = 4;
1000 SIVAL(req->out.nbt_hdr, 0, 0);
1002 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
1003 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
1004 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
1005 uint8_t *outhdr = NULL;
1006 uint8_t *outbody = NULL;
1007 uint32_t next_command_ofs = 0;
1008 struct iovec *current = &vector[idx];
1010 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
1011 /* we have a next command -
1012 * setup for the error case. */
1013 next_command_ofs = SMB2_HDR_BODY + 9;
1016 if (idx == 1) {
1017 outhdr = req->out._hdr;
1018 } else {
1019 outhdr = talloc_zero_array(mem_ctx, uint8_t,
1020 OUTVEC_ALLOC_SIZE);
1021 if (outhdr == NULL) {
1022 return NT_STATUS_NO_MEMORY;
1026 outbody = outhdr + SMB2_HDR_BODY;
1029 * SMBD_SMB2_TF_IOV_OFS might be used later
1031 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1032 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1034 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
1035 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1037 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1038 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1040 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1041 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1043 /* setup the SMB2 header */
1044 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1045 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1046 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1047 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1048 SIVAL(outhdr, SMB2_HDR_STATUS,
1049 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1050 SSVAL(outhdr, SMB2_HDR_OPCODE,
1051 SVAL(inhdr, SMB2_HDR_OPCODE));
1052 SIVAL(outhdr, SMB2_HDR_FLAGS,
1053 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1054 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1055 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1056 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1057 SIVAL(outhdr, SMB2_HDR_PID,
1058 IVAL(inhdr, SMB2_HDR_PID));
1059 SIVAL(outhdr, SMB2_HDR_TID,
1060 IVAL(inhdr, SMB2_HDR_TID));
1061 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1062 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1063 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1064 inhdr + SMB2_HDR_SIGNATURE, 16);
1066 /* setup error body header */
1067 SSVAL(outbody, 0x00, 0x08 + 1);
1068 SSVAL(outbody, 0x02, 0);
1069 SIVAL(outbody, 0x04, 0);
1072 req->out.vector = vector;
1073 req->out.vector_count = count;
1075 /* setup the length of the NBT packet */
1076 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1077 if (!ok) {
1078 return NT_STATUS_INVALID_PARAMETER_MIX;
1081 DLIST_ADD_END(xconn->smb2.requests, req);
1083 return NT_STATUS_OK;
1086 void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
1087 const char *reason,
1088 const char *location)
1090 struct smbXsrv_client *client = xconn->client;
1092 DEBUG(10,("smbd_server_connection_terminate_ex: conn[%s] reason[%s] at %s\n",
1093 smbXsrv_connection_dbg(xconn), reason, location));
1095 if (client->connections->next != NULL) {
1096 /* TODO: cancel pending requests */
1097 DLIST_REMOVE(client->connections, xconn);
1098 TALLOC_FREE(xconn);
1099 return;
1103 * The last connection was disconnected
1105 exit_server_cleanly(reason);
1108 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1109 struct iovec *outvec,
1110 const struct iovec *srcvec)
1112 const uint8_t *srctf;
1113 size_t srctf_len;
1114 const uint8_t *srchdr;
1115 size_t srchdr_len;
1116 const uint8_t *srcbody;
1117 size_t srcbody_len;
1118 const uint8_t *expected_srcbody;
1119 const uint8_t *srcdyn;
1120 size_t srcdyn_len;
1121 const uint8_t *expected_srcdyn;
1122 uint8_t *dsttf;
1123 uint8_t *dsthdr;
1124 uint8_t *dstbody;
1125 uint8_t *dstdyn;
1127 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1128 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1129 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1130 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1131 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1132 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1133 expected_srcbody = srchdr + SMB2_HDR_BODY;
1134 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1135 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1136 expected_srcdyn = srcbody + 8;
1138 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1139 return false;
1142 if (srchdr_len != SMB2_HDR_BODY) {
1143 return false;
1146 if (srctf_len == SMB2_TF_HDR_SIZE) {
1147 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1148 if (dsttf == NULL) {
1149 return false;
1151 } else {
1152 dsttf = NULL;
1154 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1155 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1157 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1158 * be allocated with size OUTVEC_ALLOC_SIZE. */
1160 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1161 if (dsthdr == NULL) {
1162 return false;
1164 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1165 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1168 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1169 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1170 * then duplicate this. Else use talloc_memdup().
1173 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1174 dstbody = dsthdr + SMB2_HDR_BODY;
1175 } else {
1176 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1177 if (dstbody == NULL) {
1178 return false;
1181 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1182 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1185 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1186 * pointing to
1187 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1188 * then duplicate this. Else use talloc_memdup().
1191 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1192 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1193 } else if (srcdyn == NULL) {
1194 dstdyn = NULL;
1195 } else {
1196 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1197 if (dstdyn == NULL) {
1198 return false;
1201 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1202 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1204 return true;
1207 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1209 struct smbd_smb2_request *newreq = NULL;
1210 struct iovec *outvec = NULL;
1211 int count = req->out.vector_count;
1212 int i;
1213 bool ok;
1215 newreq = smbd_smb2_request_allocate(req->xconn);
1216 if (!newreq) {
1217 return NULL;
1220 newreq->sconn = req->sconn;
1221 newreq->xconn = req->xconn;
1222 newreq->session = req->session;
1223 newreq->do_encryption = req->do_encryption;
1224 newreq->do_signing = req->do_signing;
1225 newreq->current_idx = req->current_idx;
1227 outvec = talloc_zero_array(newreq, struct iovec, count);
1228 if (!outvec) {
1229 TALLOC_FREE(newreq);
1230 return NULL;
1232 newreq->out.vector = outvec;
1233 newreq->out.vector_count = count;
1235 /* Setup the outvec's identically to req. */
1236 outvec[0].iov_base = newreq->out.nbt_hdr;
1237 outvec[0].iov_len = 4;
1238 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1240 /* Setup the vectors identically to the ones in req. */
1241 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1242 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1243 break;
1247 if (i < count) {
1248 /* Alloc failed. */
1249 TALLOC_FREE(newreq);
1250 return NULL;
1253 ok = smb2_setup_nbt_length(newreq->out.vector,
1254 newreq->out.vector_count);
1255 if (!ok) {
1256 TALLOC_FREE(newreq);
1257 return NULL;
1260 return newreq;
1263 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1265 struct smbXsrv_connection *xconn = req->xconn;
1266 int first_idx = 1;
1267 struct iovec *firsttf = NULL;
1268 struct iovec *outhdr_v = NULL;
1269 uint8_t *outhdr = NULL;
1270 struct smbd_smb2_request *nreq = NULL;
1271 NTSTATUS status;
1272 bool ok;
1274 /* Create a new smb2 request we'll use
1275 for the interim return. */
1276 nreq = dup_smb2_req(req);
1277 if (!nreq) {
1278 return NT_STATUS_NO_MEMORY;
1281 /* Lose the last X out vectors. They're the
1282 ones we'll be using for the async reply. */
1283 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1285 ok = smb2_setup_nbt_length(nreq->out.vector,
1286 nreq->out.vector_count);
1287 if (!ok) {
1288 return NT_STATUS_INVALID_PARAMETER_MIX;
1291 /* Step back to the previous reply. */
1292 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1293 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1294 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1295 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1296 /* And end the chain. */
1297 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1299 /* Calculate outgoing credits */
1300 smb2_calculate_credits(req, nreq);
1302 if (DEBUGLEVEL >= 10) {
1303 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1304 (unsigned int)nreq->current_idx );
1305 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1306 (unsigned int)nreq->out.vector_count );
1307 print_req_vectors(nreq);
1311 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1312 * we need to sign/encrypt here with the last/first key we remembered
1314 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1315 status = smb2_signing_encrypt_pdu(req->first_key,
1316 xconn->smb2.server.cipher,
1317 firsttf,
1318 nreq->out.vector_count - first_idx);
1319 if (!NT_STATUS_IS_OK(status)) {
1320 return status;
1322 } else if (req->last_key.length > 0) {
1323 status = smb2_signing_sign_pdu(req->last_key,
1324 xconn->protocol,
1325 outhdr_v,
1326 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1327 if (!NT_STATUS_IS_OK(status)) {
1328 return status;
1332 nreq->queue_entry.mem_ctx = nreq;
1333 nreq->queue_entry.vector = nreq->out.vector;
1334 nreq->queue_entry.count = nreq->out.vector_count;
1335 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry);
1336 xconn->smb2.send_queue_len++;
1338 status = smbd_smb2_flush_send_queue(xconn);
1339 if (!NT_STATUS_IS_OK(status)) {
1340 return status;
1343 return NT_STATUS_OK;
1346 struct smbd_smb2_request_pending_state {
1347 struct smbd_smb2_send_queue queue_entry;
1348 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1349 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1352 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1353 struct tevent_timer *te,
1354 struct timeval current_time,
1355 void *private_data);
1357 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1358 struct tevent_req *subreq,
1359 uint32_t defer_time)
1361 NTSTATUS status;
1362 struct timeval defer_endtime;
1363 uint8_t *outhdr = NULL;
1364 uint32_t flags;
1366 if (!tevent_req_is_in_progress(subreq)) {
1368 * This is a performance optimization,
1369 * it avoids one tevent_loop iteration,
1370 * which means we avoid one
1371 * talloc_stackframe_pool/talloc_free pair.
1373 tevent_req_notify_callback(subreq);
1374 return NT_STATUS_OK;
1377 req->subreq = subreq;
1378 subreq = NULL;
1380 if (req->async_te) {
1381 /* We're already async. */
1382 return NT_STATUS_OK;
1385 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1386 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1387 if (flags & SMB2_HDR_FLAG_ASYNC) {
1388 /* We're already async. */
1389 return NT_STATUS_OK;
1392 if (req->async_internal) {
1394 * An SMB2 request implementation wants to handle the request
1395 * asynchronously "internally" while keeping synchronous
1396 * behaviour for the SMB2 request. This means we don't send an
1397 * interim response and we can allow processing of compound SMB2
1398 * requests (cf the subsequent check) for all cases.
1400 return NT_STATUS_OK;
1403 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1405 * We're trying to go async in a compound request
1406 * chain. This is only allowed for opens that cause an
1407 * oplock break or for the last operation in the
1408 * chain, otherwise it is not allowed. See
1409 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
1411 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1413 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1415 * Cancel the outstanding request.
1417 bool ok = tevent_req_cancel(req->subreq);
1418 if (ok) {
1419 return NT_STATUS_OK;
1421 TALLOC_FREE(req->subreq);
1422 return smbd_smb2_request_error(req,
1423 NT_STATUS_INTERNAL_ERROR);
1427 if (DEBUGLEVEL >= 10) {
1428 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1429 (unsigned int)req->current_idx );
1430 print_req_vectors(req);
1433 if (req->current_idx > 1) {
1435 * We're going async in a compound
1436 * chain after the first request has
1437 * already been processed. Send an
1438 * interim response containing the
1439 * set of replies already generated.
1441 int idx = req->current_idx;
1443 status = smb2_send_async_interim_response(req);
1444 if (!NT_STATUS_IS_OK(status)) {
1445 return status;
1447 if (req->first_key.length > 0) {
1448 data_blob_clear_free(&req->first_key);
1451 req->current_idx = 1;
1454 * Re-arrange the in.vectors to remove what
1455 * we just sent.
1457 memmove(&req->in.vector[1],
1458 &req->in.vector[idx],
1459 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1460 req->in.vector_count = 1 + (req->in.vector_count - idx);
1462 /* Re-arrange the out.vectors to match. */
1463 memmove(&req->out.vector[1],
1464 &req->out.vector[idx],
1465 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1466 req->out.vector_count = 1 + (req->out.vector_count - idx);
1468 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1470 * We only have one remaining request as
1471 * we've processed everything else.
1472 * This is no longer a compound request.
1474 req->compound_related = false;
1475 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1476 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1477 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1480 if (req->last_key.length > 0) {
1481 data_blob_clear_free(&req->last_key);
1484 defer_endtime = timeval_current_ofs_usec(defer_time);
1485 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1486 req, defer_endtime,
1487 smbd_smb2_request_pending_timer,
1488 req);
1489 if (req->async_te == NULL) {
1490 return NT_STATUS_NO_MEMORY;
1493 return NT_STATUS_OK;
1496 static DATA_BLOB smbd_smb2_signing_key(struct smbXsrv_session *session,
1497 struct smbXsrv_connection *xconn)
1499 struct smbXsrv_channel_global0 *c = NULL;
1500 NTSTATUS status;
1501 DATA_BLOB key = data_blob_null;
1503 status = smbXsrv_session_find_channel(session, xconn, &c);
1504 if (NT_STATUS_IS_OK(status)) {
1505 key = c->signing_key;
1508 if (key.length == 0) {
1509 key = session->global->signing_key;
1512 return key;
1515 static NTSTATUS smb2_get_new_nonce(struct smbXsrv_session *session,
1516 uint64_t *new_nonce_high,
1517 uint64_t *new_nonce_low)
1519 uint64_t nonce_high;
1520 uint64_t nonce_low;
1522 session->nonce_low += 1;
1523 if (session->nonce_low == 0) {
1524 session->nonce_low += 1;
1525 session->nonce_high += 1;
1529 * CCM and GCM algorithms must never have their
1530 * nonce wrap, or the security of the whole
1531 * communication and the keys is destroyed.
1532 * We must drop the connection once we have
1533 * transfered too much data.
1535 * NOTE: We assume nonces greater than 8 bytes.
1537 if (session->nonce_high >= session->nonce_high_max) {
1538 return NT_STATUS_ENCRYPTION_FAILED;
1541 nonce_high = session->nonce_high_random;
1542 nonce_high += session->nonce_high;
1543 nonce_low = session->nonce_low;
1545 *new_nonce_high = nonce_high;
1546 *new_nonce_low = nonce_low;
1547 return NT_STATUS_OK;
1550 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1551 struct tevent_timer *te,
1552 struct timeval current_time,
1553 void *private_data)
1555 struct smbd_smb2_request *req =
1556 talloc_get_type_abort(private_data,
1557 struct smbd_smb2_request);
1558 struct smbXsrv_connection *xconn = req->xconn;
1559 struct smbd_smb2_request_pending_state *state = NULL;
1560 uint8_t *outhdr = NULL;
1561 const uint8_t *inhdr = NULL;
1562 uint8_t *tf = NULL;
1563 size_t tf_len = 0;
1564 uint8_t *hdr = NULL;
1565 uint8_t *body = NULL;
1566 uint8_t *dyn = NULL;
1567 uint32_t flags = 0;
1568 uint64_t session_id = 0;
1569 uint64_t message_id = 0;
1570 uint64_t nonce_high = 0;
1571 uint64_t nonce_low = 0;
1572 uint64_t async_id = 0;
1573 NTSTATUS status;
1574 bool ok;
1576 TALLOC_FREE(req->async_te);
1578 /* Ensure our final reply matches the interim one. */
1579 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1580 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1581 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1582 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1583 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1585 async_id = message_id; /* keep it simple for now... */
1587 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1588 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1590 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1591 "going async\n",
1592 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1593 (unsigned long long)async_id ));
1596 * What we send is identical to a smbd_smb2_request_error
1597 * packet with an error status of STATUS_PENDING. Make use
1598 * of this fact sometime when refactoring. JRA.
1601 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
1602 if (state == NULL) {
1603 smbd_server_connection_terminate(xconn,
1604 nt_errstr(NT_STATUS_NO_MEMORY));
1605 return;
1608 tf = state->buf + NBT_HDR_SIZE;
1609 tf_len = SMB2_TF_HDR_SIZE;
1611 hdr = tf + SMB2_TF_HDR_SIZE;
1612 body = hdr + SMB2_HDR_BODY;
1613 dyn = body + 8;
1615 if (req->do_encryption) {
1616 status = smb2_get_new_nonce(req->session,
1617 &nonce_high,
1618 &nonce_low);
1619 if (!NT_STATUS_IS_OK(status)) {
1620 smbd_server_connection_terminate(xconn,
1621 nt_errstr(status));
1622 return;
1626 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1627 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1628 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1629 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1631 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1632 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1633 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1634 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1635 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1637 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1638 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1639 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1640 SBVAL(hdr, SMB2_HDR_PID, async_id);
1641 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1642 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1643 memcpy(hdr+SMB2_HDR_SIGNATURE,
1644 outhdr+SMB2_HDR_SIGNATURE, 16);
1646 SSVAL(body, 0x00, 0x08 + 1);
1648 SCVAL(body, 0x02, 0);
1649 SCVAL(body, 0x03, 0);
1650 SIVAL(body, 0x04, 0);
1651 /* Match W2K8R2... */
1652 SCVAL(dyn, 0x00, 0x21);
1654 state->vector[0].iov_base = (void *)state->buf;
1655 state->vector[0].iov_len = NBT_HDR_SIZE;
1657 if (req->do_encryption) {
1658 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1659 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1660 } else {
1661 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1662 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1665 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1666 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1668 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1669 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1671 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1672 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1674 ok = smb2_setup_nbt_length(state->vector,
1675 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1676 if (!ok) {
1677 smbd_server_connection_terminate(
1678 xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
1679 return;
1682 /* Ensure we correctly go through crediting. Grant
1683 the credits now, and zero credits on the final
1684 response. */
1685 smb2_set_operation_credit(req->xconn,
1686 SMBD_SMB2_IN_HDR_IOV(req),
1687 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1689 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1691 if (DEBUGLVL(10)) {
1692 int i;
1694 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1695 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1696 (unsigned int)i,
1697 (unsigned int)ARRAY_SIZE(state->vector),
1698 (unsigned int)state->vector[i].iov_len);
1702 if (req->do_encryption) {
1703 struct smbXsrv_session *x = req->session;
1704 DATA_BLOB encryption_key = x->global->encryption_key;
1706 status = smb2_signing_encrypt_pdu(encryption_key,
1707 xconn->smb2.server.cipher,
1708 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1709 SMBD_SMB2_NUM_IOV_PER_REQ);
1710 if (!NT_STATUS_IS_OK(status)) {
1711 smbd_server_connection_terminate(xconn,
1712 nt_errstr(status));
1713 return;
1715 } else if (req->do_signing) {
1716 struct smbXsrv_session *x = req->session;
1717 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
1719 status = smb2_signing_sign_pdu(signing_key,
1720 xconn->protocol,
1721 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1722 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1723 if (!NT_STATUS_IS_OK(status)) {
1724 smbd_server_connection_terminate(xconn,
1725 nt_errstr(status));
1726 return;
1730 state->queue_entry.mem_ctx = state;
1731 state->queue_entry.vector = state->vector;
1732 state->queue_entry.count = ARRAY_SIZE(state->vector);
1733 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
1734 xconn->smb2.send_queue_len++;
1736 status = smbd_smb2_flush_send_queue(xconn);
1737 if (!NT_STATUS_IS_OK(status)) {
1738 smbd_server_connection_terminate(xconn,
1739 nt_errstr(status));
1740 return;
1744 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1746 struct smbXsrv_connection *xconn = req->xconn;
1747 struct smbd_smb2_request *cur;
1748 const uint8_t *inhdr;
1749 uint32_t flags;
1750 uint64_t search_message_id;
1751 uint64_t search_async_id;
1752 uint64_t found_id;
1754 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1756 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1757 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1758 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1761 * We don't need the request anymore cancel requests never
1762 * have a response.
1764 * We defer the TALLOC_FREE(req) to the caller.
1766 DLIST_REMOVE(xconn->smb2.requests, req);
1768 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1769 const uint8_t *outhdr;
1770 uint64_t message_id;
1771 uint64_t async_id;
1773 if (cur->compound_related) {
1775 * Never cancel anything in a compound request.
1776 * Way too hard to deal with the result.
1778 continue;
1781 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1783 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1784 async_id = BVAL(outhdr, SMB2_HDR_PID);
1786 if (flags & SMB2_HDR_FLAG_ASYNC) {
1787 if (search_async_id == async_id) {
1788 found_id = async_id;
1789 break;
1791 } else {
1792 if (search_message_id == message_id) {
1793 found_id = message_id;
1794 break;
1799 if (cur && cur->subreq) {
1800 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1801 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1802 "cancel opcode[%s] mid %llu\n",
1803 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1804 (unsigned long long)found_id ));
1805 tevent_req_cancel(cur->subreq);
1808 return NT_STATUS_OK;
1811 /*************************************************************
1812 Ensure an incoming tid is a valid one for us to access.
1813 Change to the associated uid credentials and chdir to the
1814 valid tid directory.
1815 *************************************************************/
1817 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1819 const uint8_t *inhdr;
1820 uint32_t in_flags;
1821 uint32_t in_tid;
1822 struct smbXsrv_tcon *tcon;
1823 NTSTATUS status;
1824 NTTIME now = timeval_to_nttime(&req->request_time);
1826 req->tcon = NULL;
1828 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1830 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1831 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1833 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1834 in_tid = req->last_tid;
1837 req->last_tid = 0;
1839 status = smb2srv_tcon_lookup(req->session,
1840 in_tid, now, &tcon);
1841 if (!NT_STATUS_IS_OK(status)) {
1842 return status;
1845 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1846 return NT_STATUS_ACCESS_DENIED;
1849 if (!set_current_service(tcon->compat, 0, true)) {
1850 return NT_STATUS_ACCESS_DENIED;
1853 req->tcon = tcon;
1854 req->last_tid = in_tid;
1856 return NT_STATUS_OK;
1859 /*************************************************************
1860 Ensure an incoming session_id is a valid one for us to access.
1861 *************************************************************/
1863 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1865 const uint8_t *inhdr;
1866 uint32_t in_flags;
1867 uint16_t in_opcode;
1868 uint64_t in_session_id;
1869 struct smbXsrv_session *session = NULL;
1870 struct auth_session_info *session_info;
1871 NTSTATUS status;
1872 NTTIME now = timeval_to_nttime(&req->request_time);
1874 req->session = NULL;
1875 req->tcon = NULL;
1877 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1879 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1880 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1881 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1883 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1884 in_session_id = req->last_session_id;
1887 req->last_session_id = 0;
1889 /* look an existing session up */
1890 switch (in_opcode) {
1891 case SMB2_OP_SESSSETUP:
1893 * For a session bind request, we don't have the
1894 * channel set up at this point yet, so we defer
1895 * the verification that the connection belongs
1896 * to the session to the session setup code, which
1897 * can look at the session binding flags.
1899 status = smb2srv_session_lookup_client(req->xconn->client,
1900 in_session_id, now,
1901 &session);
1902 break;
1903 default:
1904 status = smb2srv_session_lookup_conn(req->xconn,
1905 in_session_id, now,
1906 &session);
1907 break;
1909 if (session) {
1910 req->session = session;
1911 req->last_session_id = in_session_id;
1913 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1914 switch (in_opcode) {
1915 case SMB2_OP_SESSSETUP:
1916 status = NT_STATUS_OK;
1917 break;
1918 case SMB2_OP_LOGOFF:
1919 case SMB2_OP_CLOSE:
1920 case SMB2_OP_LOCK:
1921 case SMB2_OP_CANCEL:
1922 case SMB2_OP_KEEPALIVE:
1924 * [MS-SMB2] 3.3.5.2.9 Verifying the Session
1925 * specifies that LOGOFF, CLOSE and (UN)LOCK
1926 * should always be processed even on expired sessions.
1928 * Also see the logic in
1929 * smbd_smb2_request_process_lock().
1931 * The smb2.session.expire2 test shows that
1932 * CANCEL and KEEPALIVE/ECHO should also
1933 * be processed.
1935 status = NT_STATUS_OK;
1936 break;
1937 default:
1938 break;
1941 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1942 switch (in_opcode) {
1943 case SMB2_OP_TCON:
1944 case SMB2_OP_CREATE:
1945 case SMB2_OP_GETINFO:
1946 case SMB2_OP_SETINFO:
1947 return NT_STATUS_INVALID_HANDLE;
1948 default:
1950 * Notice the check for
1951 * (session_info == NULL)
1952 * below.
1954 status = NT_STATUS_OK;
1955 break;
1958 if (!NT_STATUS_IS_OK(status)) {
1959 return status;
1962 session_info = session->global->auth_session_info;
1963 if (session_info == NULL) {
1964 return NT_STATUS_INVALID_HANDLE;
1967 if (in_session_id != req->xconn->client->last_session_id) {
1968 req->xconn->client->last_session_id = in_session_id;
1969 set_current_user_info(session_info->unix_info->sanitized_username,
1970 session_info->unix_info->unix_name,
1971 session_info->info->domain_name);
1974 return NT_STATUS_OK;
1977 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1978 uint32_t data_length)
1980 struct smbXsrv_connection *xconn = req->xconn;
1981 uint16_t needed_charge;
1982 uint16_t credit_charge = 1;
1983 const uint8_t *inhdr;
1985 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1987 if (xconn->smb2.credits.multicredit) {
1988 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1989 credit_charge = MAX(credit_charge, 1);
1992 needed_charge = (data_length - 1)/ 65536 + 1;
1994 DBGC_DEBUG(DBGC_SMB2_CREDITS,
1995 "mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1996 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1997 credit_charge, needed_charge);
1999 if (needed_charge > credit_charge) {
2000 DBGC_WARNING(DBGC_SMB2_CREDITS,
2001 "CreditCharge too low, given %d, needed %d\n",
2002 credit_charge, needed_charge);
2003 return NT_STATUS_INVALID_PARAMETER;
2006 return NT_STATUS_OK;
2009 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
2010 size_t expected_body_size)
2012 struct iovec *inhdr_v;
2013 const uint8_t *inhdr;
2014 uint16_t opcode;
2015 const uint8_t *inbody;
2016 size_t body_size;
2017 size_t min_dyn_size = expected_body_size & 0x00000001;
2018 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
2021 * The following should be checked already.
2023 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
2024 return NT_STATUS_INTERNAL_ERROR;
2026 if (req->current_idx > max_idx) {
2027 return NT_STATUS_INTERNAL_ERROR;
2030 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
2031 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
2032 return NT_STATUS_INTERNAL_ERROR;
2034 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
2035 return NT_STATUS_INTERNAL_ERROR;
2038 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2039 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2041 switch (opcode) {
2042 case SMB2_OP_IOCTL:
2043 case SMB2_OP_GETINFO:
2044 min_dyn_size = 0;
2045 break;
2046 case SMB2_OP_WRITE:
2047 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
2048 if (req->smb1req->unread_bytes < min_dyn_size) {
2049 return NT_STATUS_INVALID_PARAMETER;
2052 min_dyn_size = 0;
2054 break;
2058 * Now check the expected body size,
2059 * where the last byte might be in the
2060 * dynamic section..
2062 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
2063 return NT_STATUS_INVALID_PARAMETER;
2065 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
2066 return NT_STATUS_INVALID_PARAMETER;
2069 inbody = SMBD_SMB2_IN_BODY_PTR(req);
2071 body_size = SVAL(inbody, 0x00);
2072 if (body_size != expected_body_size) {
2073 return NT_STATUS_INVALID_PARAMETER;
2076 return NT_STATUS_OK;
2079 bool smbXsrv_is_encrypted(uint8_t encryption_flags)
2081 return (!(encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)
2083 (encryption_flags & (SMBXSRV_PROCESSED_ENCRYPTED_PACKET |
2084 SMBXSRV_ENCRYPTION_DESIRED |
2085 SMBXSRV_ENCRYPTION_REQUIRED)));
2088 bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags)
2090 return ((encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET) &&
2091 (encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET));
2094 /* Set a flag if not already set, return true if set */
2095 bool smbXsrv_set_crypto_flag(uint8_t *flags, uint8_t flag)
2097 if ((flag == 0) || (*flags & flag)) {
2098 return false;
2101 *flags |= flag;
2102 return true;
2106 * Update encryption state tracking flags, this can be used to
2107 * determine whether whether the session or tcon is "encrypted".
2109 static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
2110 uint16_t opcode,
2111 bool *update_session_globalp,
2112 bool *update_tcon_globalp)
2114 /* Default: assume unecrypted and unsigned */
2115 struct smbXsrv_session *session = req->session;
2116 struct smbXsrv_tcon *tcon = req->tcon;
2117 uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
2118 uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2119 bool update_session = false;
2120 bool update_tcon = false;
2122 if (req->was_encrypted && req->do_encryption) {
2123 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
2124 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2125 } else {
2126 /* Unencrypted packet, can be signed */
2127 if (req->do_signing) {
2128 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2129 } else if (opcode == SMB2_OP_CANCEL) {
2130 /* Cancel requests are allowed to skip signing */
2131 sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2135 update_session |= smbXsrv_set_crypto_flag(
2136 &session->global->encryption_flags, encrypt_flag);
2137 update_session |= smbXsrv_set_crypto_flag(
2138 &session->global->signing_flags, sign_flag);
2140 if (tcon) {
2141 update_tcon |= smbXsrv_set_crypto_flag(
2142 &tcon->global->encryption_flags, encrypt_flag);
2143 update_tcon |= smbXsrv_set_crypto_flag(
2144 &tcon->global->signing_flags, sign_flag);
2147 *update_session_globalp = update_session;
2148 *update_tcon_globalp = update_tcon;
2149 return;
2152 bool smbXsrv_is_signed(uint8_t signing_flags)
2155 * Signing is always enabled, so unless we got an unsigned
2156 * packet and at least one signed packet that was not
2157 * encrypted, the session or tcon is "signed".
2159 return (!(signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2160 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2163 bool smbXsrv_is_partially_signed(uint8_t signing_flags)
2165 return ((signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2166 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2169 static NTSTATUS smbd_smb2_request_dispatch_update_counts(
2170 struct smbd_smb2_request *req,
2171 bool modify_call)
2173 struct smbXsrv_connection *xconn = req->xconn;
2174 const uint8_t *inhdr;
2175 uint16_t channel_sequence;
2176 uint8_t generation_wrap = 0;
2177 uint32_t flags;
2178 int cmp;
2179 struct smbXsrv_open *op;
2180 bool update_open = false;
2181 NTSTATUS status = NT_STATUS_OK;
2183 SMB_ASSERT(!req->request_counters_updated);
2185 if (xconn->protocol < PROTOCOL_SMB2_22) {
2186 return NT_STATUS_OK;
2189 if (req->compat_chain_fsp == NULL) {
2190 return NT_STATUS_OK;
2193 op = req->compat_chain_fsp->op;
2194 if (op == NULL) {
2195 return NT_STATUS_OK;
2198 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2199 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2200 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2202 cmp = channel_sequence - op->global->channel_sequence;
2203 if (cmp < 0) {
2205 * csn wrap. We need to watch out for long-running
2206 * requests that are still sitting on a previously
2207 * used csn. SMB2_OP_NOTIFY can take VERY long.
2209 generation_wrap += 1;
2212 if (abs(cmp) > INT16_MAX) {
2214 * [MS-SMB2] 3.3.5.2.10 - Verifying the Channel Sequence Number:
2216 * If the channel sequence number of the request and the one
2217 * known to the server are not equal, the channel sequence
2218 * number and outstanding request counts are only updated
2219 * "... if the unsigned difference using 16-bit arithmetic
2220 * between ChannelSequence and Open.ChannelSequence is less than
2221 * or equal to 0x7FFF ...".
2222 * Otherwise, an error is returned for the modifying
2223 * calls write, set_info, and ioctl.
2225 * There are currently two issues with the description:
2227 * * For the other calls, the document seems to imply
2228 * that processing continues without adapting the
2229 * counters (if the sequence numbers are not equal).
2231 * TODO: This needs clarification!
2233 * * Also, the behaviour if the difference is larger
2234 * than 0x7FFF is not clear. The document seems to
2235 * imply that if such a difference is reached,
2236 * the server starts to ignore the counters or
2237 * in the case of the modifying calls, return errors.
2239 * TODO: This needs clarification!
2241 * At this point Samba tries to be a little more
2242 * clever than the description in the MS-SMB2 document
2243 * by heuristically detecting and properly treating
2244 * a 16 bit overflow of the client-submitted sequence
2245 * number:
2247 * If the stored channel sequence number is more than
2248 * 0x7FFF larger than the one from the request, then
2249 * the client-provided sequence number has likely
2250 * overflown. We treat this case as valid instead
2251 * of as failure.
2253 * The MS-SMB2 behaviour would be setting cmp = -1.
2255 cmp *= -1;
2258 if (flags & SMB2_HDR_FLAG_REPLAY_OPERATION) {
2259 if (cmp == 0 && op->pre_request_count == 0) {
2260 op->request_count += 1;
2261 req->request_counters_updated = true;
2262 } else if (cmp > 0 && op->pre_request_count == 0) {
2263 op->pre_request_count += op->request_count;
2264 op->request_count = 1;
2265 op->global->channel_sequence = channel_sequence;
2266 op->global->channel_generation += generation_wrap;
2267 update_open = true;
2268 req->request_counters_updated = true;
2269 } else if (modify_call) {
2270 return NT_STATUS_FILE_NOT_AVAILABLE;
2272 } else {
2273 if (cmp == 0) {
2274 op->request_count += 1;
2275 req->request_counters_updated = true;
2276 } else if (cmp > 0) {
2277 op->pre_request_count += op->request_count;
2278 op->request_count = 1;
2279 op->global->channel_sequence = channel_sequence;
2280 op->global->channel_generation += generation_wrap;
2281 update_open = true;
2282 req->request_counters_updated = true;
2283 } else if (modify_call) {
2284 return NT_STATUS_FILE_NOT_AVAILABLE;
2287 req->channel_generation = op->global->channel_generation;
2289 if (update_open) {
2290 status = smbXsrv_open_update(op);
2293 return status;
2296 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
2298 struct smbXsrv_connection *xconn = req->xconn;
2299 const struct smbd_smb2_dispatch_table *call = NULL;
2300 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
2301 const uint8_t *inhdr;
2302 uint16_t opcode;
2303 uint32_t flags;
2304 uint64_t mid;
2305 NTSTATUS status;
2306 NTSTATUS session_status;
2307 uint32_t allowed_flags;
2308 NTSTATUS return_value;
2309 struct smbXsrv_session *x = NULL;
2310 bool signing_required = false;
2311 bool encryption_desired = false;
2312 bool encryption_required = false;
2314 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2316 DO_PROFILE_INC(request);
2318 SMB_ASSERT(!req->request_counters_updated);
2320 /* TODO: verify more things */
2322 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2323 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2324 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2325 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
2326 smb2_opcode_name(opcode),
2327 (unsigned long long)mid));
2329 if (xconn->protocol >= PROTOCOL_SMB2_02) {
2331 * once the protocol is negotiated
2332 * SMB2_OP_NEGPROT is not allowed anymore
2334 if (opcode == SMB2_OP_NEGPROT) {
2335 /* drop the connection */
2336 return NT_STATUS_INVALID_PARAMETER;
2338 } else {
2340 * if the protocol is not negotiated yet
2341 * only SMB2_OP_NEGPROT is allowed.
2343 if (opcode != SMB2_OP_NEGPROT) {
2344 /* drop the connection */
2345 return NT_STATUS_INVALID_PARAMETER;
2350 * Check if the client provided a valid session id,
2351 * if so smbd_smb2_request_check_session() calls
2352 * set_current_user_info().
2354 * As some command don't require a valid session id
2355 * we defer the check of the session_status
2357 session_status = smbd_smb2_request_check_session(req);
2358 x = req->session;
2359 if (x != NULL) {
2360 signing_required = x->global->signing_flags & SMBXSRV_SIGNING_REQUIRED;
2361 encryption_desired = x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
2362 encryption_required = x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
2365 req->async_internal = false;
2366 req->do_signing = false;
2367 req->do_encryption = false;
2368 req->was_encrypted = false;
2369 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
2370 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
2371 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
2373 if (x != NULL && x->global->session_wire_id != tf_session_id) {
2374 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2375 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
2376 (unsigned long long)x->global->session_wire_id,
2377 (unsigned long long)tf_session_id));
2379 * TODO: windows allows this...
2380 * should we drop the connection?
2382 * For now we just return ACCESS_DENIED
2383 * (Windows clients never trigger this)
2384 * and wait for an update of [MS-SMB2].
2386 return smbd_smb2_request_error(req,
2387 NT_STATUS_ACCESS_DENIED);
2390 req->was_encrypted = true;
2393 if (encryption_required && !req->was_encrypted) {
2394 return smbd_smb2_request_error(req,
2395 NT_STATUS_ACCESS_DENIED);
2398 call = smbd_smb2_call(opcode);
2399 if (call == NULL) {
2400 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2403 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2404 SMB2_HDR_FLAG_SIGNED |
2405 SMB2_HDR_FLAG_DFS;
2406 if (xconn->protocol >= PROTOCOL_SMB3_11) {
2407 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2409 if (opcode == SMB2_OP_NEGPROT) {
2410 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11) {
2411 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2414 if (opcode == SMB2_OP_CANCEL) {
2415 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2417 if (xconn->protocol >= PROTOCOL_SMB2_22) {
2418 allowed_flags |= SMB2_HDR_FLAG_REPLAY_OPERATION;
2420 if ((flags & ~allowed_flags) != 0) {
2421 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2424 if (flags & SMB2_HDR_FLAG_CHAINED) {
2426 * This check is mostly for giving the correct error code
2427 * for compounded requests.
2429 if (!NT_STATUS_IS_OK(session_status)) {
2430 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2432 } else {
2433 req->compat_chain_fsp = NULL;
2436 if (req->was_encrypted) {
2437 signing_required = false;
2438 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2439 DATA_BLOB signing_key = data_blob_null;
2441 if (x == NULL) {
2443 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2444 * If the SMB2 header of the SMB2 NEGOTIATE
2445 * request has the SMB2_FLAGS_SIGNED bit set in the
2446 * Flags field, the server MUST fail the request
2447 * with STATUS_INVALID_PARAMETER.
2449 * Microsoft test tool checks this.
2452 if ((opcode == SMB2_OP_NEGPROT) &&
2453 (flags & SMB2_HDR_FLAG_SIGNED)) {
2454 status = NT_STATUS_INVALID_PARAMETER;
2455 } else {
2456 status = NT_STATUS_USER_SESSION_DELETED;
2458 return smbd_smb2_request_error(req, status);
2461 signing_key = smbd_smb2_signing_key(x, xconn);
2464 * If we have a signing key, we should
2465 * sign the response
2467 if (signing_key.length > 0) {
2468 req->do_signing = true;
2471 status = smb2_signing_check_pdu(signing_key,
2472 xconn->protocol,
2473 SMBD_SMB2_IN_HDR_IOV(req),
2474 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2475 if (!NT_STATUS_IS_OK(status)) {
2476 return smbd_smb2_request_error(req, status);
2480 * Now that we know the request was correctly signed
2481 * we have to sign the response too.
2483 req->do_signing = true;
2485 if (!NT_STATUS_IS_OK(session_status)) {
2486 return smbd_smb2_request_error(req, session_status);
2488 } else if (opcode == SMB2_OP_CANCEL) {
2489 /* Cancel requests are allowed to skip the signing */
2490 } else if (signing_required) {
2492 * If signing is required we try to sign
2493 * a possible error response
2495 req->do_signing = true;
2496 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2499 if (flags & SMB2_HDR_FLAG_CHAINED) {
2500 req->compound_related = true;
2503 if (call->need_session) {
2504 if (!NT_STATUS_IS_OK(session_status)) {
2505 return smbd_smb2_request_error(req, session_status);
2509 if (call->need_tcon) {
2510 SMB_ASSERT(call->need_session);
2513 * This call needs to be run as user.
2515 * smbd_smb2_request_check_tcon()
2516 * calls change_to_user() on success.
2518 status = smbd_smb2_request_check_tcon(req);
2519 if (!NT_STATUS_IS_OK(status)) {
2520 return smbd_smb2_request_error(req, status);
2522 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
2523 encryption_desired = true;
2525 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
2526 encryption_required = true;
2528 if (encryption_required && !req->was_encrypted) {
2529 return smbd_smb2_request_error(req,
2530 NT_STATUS_ACCESS_DENIED);
2534 if (req->was_encrypted || encryption_desired) {
2535 req->do_encryption = true;
2538 if (req->session) {
2539 bool update_session_global = false;
2540 bool update_tcon_global = false;
2542 smb2srv_update_crypto_flags(req, opcode,
2543 &update_session_global,
2544 &update_tcon_global);
2546 if (update_session_global) {
2547 status = smbXsrv_session_update(x);
2548 if (!NT_STATUS_IS_OK(status)) {
2549 return smbd_smb2_request_error(req, status);
2552 if (update_tcon_global) {
2553 status = smbXsrv_tcon_update(req->tcon);
2554 if (!NT_STATUS_IS_OK(status)) {
2555 return smbd_smb2_request_error(req, status);
2560 if (call->fileid_ofs != 0) {
2561 size_t needed = call->fileid_ofs + 16;
2562 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2563 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2564 uint64_t file_id_persistent;
2565 uint64_t file_id_volatile;
2566 struct files_struct *fsp;
2568 SMB_ASSERT(call->need_tcon);
2570 if (needed > body_size) {
2571 return smbd_smb2_request_error(req,
2572 NT_STATUS_INVALID_PARAMETER);
2575 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2576 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2578 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2579 if (fsp == NULL) {
2580 if (!call->allow_invalid_fileid) {
2581 return smbd_smb2_request_error(req,
2582 NT_STATUS_FILE_CLOSED);
2585 if (file_id_persistent != UINT64_MAX) {
2586 return smbd_smb2_request_error(req,
2587 NT_STATUS_FILE_CLOSED);
2589 if (file_id_volatile != UINT64_MAX) {
2590 return smbd_smb2_request_error(req,
2591 NT_STATUS_FILE_CLOSED);
2596 status = smbd_smb2_request_dispatch_update_counts(req, call->modify);
2597 if (!NT_STATUS_IS_OK(status)) {
2598 return smbd_smb2_request_error(req, status);
2601 if (call->as_root) {
2602 SMB_ASSERT(call->fileid_ofs == 0);
2603 /* This call needs to be run as root */
2604 change_to_root_user();
2605 } else {
2606 SMB_ASSERT(call->need_tcon);
2609 #define _INBYTES(_r) \
2610 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
2612 switch (opcode) {
2613 case SMB2_OP_NEGPROT:
2614 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
2615 req->profile, _INBYTES(req));
2616 return_value = smbd_smb2_request_process_negprot(req);
2617 break;
2619 case SMB2_OP_SESSSETUP:
2620 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
2621 req->profile, _INBYTES(req));
2622 return_value = smbd_smb2_request_process_sesssetup(req);
2623 break;
2625 case SMB2_OP_LOGOFF:
2626 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
2627 req->profile, _INBYTES(req));
2628 return_value = smbd_smb2_request_process_logoff(req);
2629 break;
2631 case SMB2_OP_TCON:
2632 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
2633 req->profile, _INBYTES(req));
2634 return_value = smbd_smb2_request_process_tcon(req);
2635 break;
2637 case SMB2_OP_TDIS:
2638 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
2639 req->profile, _INBYTES(req));
2640 return_value = smbd_smb2_request_process_tdis(req);
2641 break;
2643 case SMB2_OP_CREATE:
2644 if (req->subreq == NULL) {
2645 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
2646 req->profile, _INBYTES(req));
2647 } else {
2648 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
2650 return_value = smbd_smb2_request_process_create(req);
2651 break;
2653 case SMB2_OP_CLOSE:
2654 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
2655 req->profile, _INBYTES(req));
2656 return_value = smbd_smb2_request_process_close(req);
2657 break;
2659 case SMB2_OP_FLUSH:
2660 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
2661 req->profile, _INBYTES(req));
2662 return_value = smbd_smb2_request_process_flush(req);
2663 break;
2665 case SMB2_OP_READ:
2666 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
2667 req->profile, _INBYTES(req));
2668 return_value = smbd_smb2_request_process_read(req);
2669 break;
2671 case SMB2_OP_WRITE:
2672 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
2673 req->profile, _INBYTES(req));
2674 return_value = smbd_smb2_request_process_write(req);
2675 break;
2677 case SMB2_OP_LOCK:
2678 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
2679 req->profile, _INBYTES(req));
2680 return_value = smbd_smb2_request_process_lock(req);
2681 break;
2683 case SMB2_OP_IOCTL:
2684 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
2685 req->profile, _INBYTES(req));
2686 return_value = smbd_smb2_request_process_ioctl(req);
2687 break;
2689 case SMB2_OP_CANCEL:
2690 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
2691 req->profile, _INBYTES(req));
2692 return_value = smbd_smb2_request_process_cancel(req);
2693 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
2696 * We don't need the request anymore cancel requests never
2697 * have a response.
2699 * smbd_smb2_request_process_cancel() already called
2700 * DLIST_REMOVE(xconn->smb2.requests, req);
2702 TALLOC_FREE(req);
2704 break;
2706 case SMB2_OP_KEEPALIVE:
2707 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
2708 req->profile, _INBYTES(req));
2709 return_value = smbd_smb2_request_process_keepalive(req);
2710 break;
2712 case SMB2_OP_QUERY_DIRECTORY:
2713 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
2714 req->profile, _INBYTES(req));
2715 return_value = smbd_smb2_request_process_query_directory(req);
2716 break;
2718 case SMB2_OP_NOTIFY:
2719 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
2720 req->profile, _INBYTES(req));
2721 return_value = smbd_smb2_request_process_notify(req);
2722 break;
2724 case SMB2_OP_GETINFO:
2725 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
2726 req->profile, _INBYTES(req));
2727 return_value = smbd_smb2_request_process_getinfo(req);
2728 break;
2730 case SMB2_OP_SETINFO:
2731 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
2732 req->profile, _INBYTES(req));
2733 return_value = smbd_smb2_request_process_setinfo(req);
2734 break;
2736 case SMB2_OP_BREAK:
2737 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
2738 req->profile, _INBYTES(req));
2739 return_value = smbd_smb2_request_process_break(req);
2740 break;
2742 default:
2743 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2744 break;
2746 return return_value;
2749 static void smbd_smb2_request_reply_update_counts(struct smbd_smb2_request *req)
2751 struct smbXsrv_connection *xconn = req->xconn;
2752 const uint8_t *inhdr;
2753 uint16_t channel_sequence;
2754 struct smbXsrv_open *op;
2756 if (!req->request_counters_updated) {
2757 return;
2760 req->request_counters_updated = false;
2762 if (xconn->protocol < PROTOCOL_SMB2_22) {
2763 return;
2766 if (req->compat_chain_fsp == NULL) {
2767 return;
2770 op = req->compat_chain_fsp->op;
2771 if (op == NULL) {
2772 return;
2775 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2776 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2778 if ((op->global->channel_sequence == channel_sequence) &&
2779 (op->global->channel_generation == req->channel_generation)) {
2780 SMB_ASSERT(op->request_count > 0);
2781 op->request_count -= 1;
2782 } else {
2783 SMB_ASSERT(op->pre_request_count > 0);
2784 op->pre_request_count -= 1;
2788 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2790 struct smbXsrv_connection *xconn = req->xconn;
2791 int first_idx = 1;
2792 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2793 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2794 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2795 NTSTATUS status;
2796 bool ok;
2798 req->subreq = NULL;
2799 TALLOC_FREE(req->async_te);
2801 /* MS-SMB2: 3.3.4.1 Sending Any Outgoing Message */
2802 smbd_smb2_request_reply_update_counts(req);
2804 if (req->do_encryption &&
2805 (firsttf->iov_len == 0) &&
2806 (req->first_key.length == 0) &&
2807 (req->session != NULL) &&
2808 (req->session->global->encryption_key.length != 0))
2810 DATA_BLOB encryption_key = req->session->global->encryption_key;
2811 uint8_t *tf;
2812 uint64_t session_id = req->session->global->session_wire_id;
2813 uint64_t nonce_high;
2814 uint64_t nonce_low;
2816 status = smb2_get_new_nonce(req->session,
2817 &nonce_high,
2818 &nonce_low);
2819 if (!NT_STATUS_IS_OK(status)) {
2820 return status;
2824 * We need to place the SMB2_TRANSFORM header before the
2825 * first SMB2 header
2829 * we need to remember the encryption key
2830 * and defer the signing/encryption until
2831 * we are sure that we do not change
2832 * the header again.
2834 req->first_key = data_blob_dup_talloc(req, encryption_key);
2835 if (req->first_key.data == NULL) {
2836 return NT_STATUS_NO_MEMORY;
2839 tf = talloc_zero_array(req, uint8_t,
2840 SMB2_TF_HDR_SIZE);
2841 if (tf == NULL) {
2842 return NT_STATUS_NO_MEMORY;
2845 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2846 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2847 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2848 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2850 firsttf->iov_base = (void *)tf;
2851 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2854 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2855 (req->last_key.length > 0) &&
2856 (firsttf->iov_len == 0))
2858 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2859 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2862 * As we are sure the header of the last request in the
2863 * compound chain will not change, we can to sign here
2864 * with the last signing key we remembered.
2866 status = smb2_signing_sign_pdu(req->last_key,
2867 xconn->protocol,
2868 lasthdr,
2869 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2870 if (!NT_STATUS_IS_OK(status)) {
2871 return status;
2874 if (req->last_key.length > 0) {
2875 data_blob_clear_free(&req->last_key);
2878 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
2879 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
2881 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2883 if (req->current_idx < req->out.vector_count) {
2885 * We must process the remaining compound
2886 * SMB2 requests before any new incoming SMB2
2887 * requests. This is because incoming SMB2
2888 * requests may include a cancel for a
2889 * compound request we haven't processed
2890 * yet.
2892 struct tevent_immediate *im = tevent_create_immediate(req);
2893 if (!im) {
2894 return NT_STATUS_NO_MEMORY;
2897 if (req->do_signing && firsttf->iov_len == 0) {
2898 struct smbXsrv_session *x = req->session;
2899 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2902 * we need to remember the signing key
2903 * and defer the signing until
2904 * we are sure that we do not change
2905 * the header again.
2907 req->last_key = data_blob_dup_talloc(req, signing_key);
2908 if (req->last_key.data == NULL) {
2909 return NT_STATUS_NO_MEMORY;
2913 tevent_schedule_immediate(im,
2914 req->sconn->ev_ctx,
2915 smbd_smb2_request_dispatch_immediate,
2916 req);
2917 return NT_STATUS_OK;
2920 if (req->compound_related) {
2921 req->compound_related = false;
2924 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2925 if (!ok) {
2926 return NT_STATUS_INVALID_PARAMETER_MIX;
2929 /* Set credit for these operations (zero credits if this
2930 is a final reply for an async operation). */
2931 smb2_calculate_credits(req, req);
2934 * now check if we need to sign the current response
2936 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2937 status = smb2_signing_encrypt_pdu(req->first_key,
2938 xconn->smb2.server.cipher,
2939 firsttf,
2940 req->out.vector_count - first_idx);
2941 if (!NT_STATUS_IS_OK(status)) {
2942 return status;
2944 } else if (req->do_signing) {
2945 struct smbXsrv_session *x = req->session;
2946 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2948 status = smb2_signing_sign_pdu(signing_key,
2949 xconn->protocol,
2950 outhdr,
2951 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2952 if (!NT_STATUS_IS_OK(status)) {
2953 return status;
2956 if (req->first_key.length > 0) {
2957 data_blob_clear_free(&req->first_key);
2960 if (req->preauth != NULL) {
2961 struct hc_sha512state sctx;
2962 int i;
2964 samba_SHA512_Init(&sctx);
2965 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2966 sizeof(req->preauth->sha512_value));
2967 for (i = 1; i < req->in.vector_count; i++) {
2968 samba_SHA512_Update(&sctx,
2969 req->in.vector[i].iov_base,
2970 req->in.vector[i].iov_len);
2972 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2974 samba_SHA512_Init(&sctx);
2975 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2976 sizeof(req->preauth->sha512_value));
2977 for (i = 1; i < req->out.vector_count; i++) {
2978 samba_SHA512_Update(&sctx,
2979 req->out.vector[i].iov_base,
2980 req->out.vector[i].iov_len);
2982 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2984 req->preauth = NULL;
2987 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2988 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2989 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2990 /* Dynamic part is NULL. Chop it off,
2991 We're going to send it via sendfile. */
2992 req->out.vector_count -= 1;
2996 * We're done with this request -
2997 * move it off the "being processed" queue.
2999 DLIST_REMOVE(xconn->smb2.requests, req);
3001 req->queue_entry.mem_ctx = req;
3002 req->queue_entry.vector = req->out.vector;
3003 req->queue_entry.count = req->out.vector_count;
3004 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry);
3005 xconn->smb2.send_queue_len++;
3007 status = smbd_smb2_flush_send_queue(xconn);
3008 if (!NT_STATUS_IS_OK(status)) {
3009 return status;
3012 return NT_STATUS_OK;
3015 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
3017 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
3018 struct tevent_immediate *im,
3019 void *private_data)
3021 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
3022 struct smbd_smb2_request);
3023 struct smbXsrv_connection *xconn = req->xconn;
3024 NTSTATUS status;
3026 TALLOC_FREE(im);
3028 if (DEBUGLEVEL >= 10) {
3029 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
3030 req->current_idx, req->in.vector_count));
3031 print_req_vectors(req);
3034 status = smbd_smb2_request_dispatch(req);
3035 if (!NT_STATUS_IS_OK(status)) {
3036 smbd_server_connection_terminate(xconn, nt_errstr(status));
3037 return;
3040 status = smbd_smb2_request_next_incoming(xconn);
3041 if (!NT_STATUS_IS_OK(status)) {
3042 smbd_server_connection_terminate(xconn, nt_errstr(status));
3043 return;
3047 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
3048 NTSTATUS status,
3049 DATA_BLOB body, DATA_BLOB *dyn,
3050 const char *location)
3052 uint8_t *outhdr;
3053 struct iovec *outbody_v;
3054 struct iovec *outdyn_v;
3055 uint32_t next_command_ofs;
3057 DEBUG(10,("smbd_smb2_request_done_ex: "
3058 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
3059 req->current_idx, nt_errstr(status), (unsigned int)body.length,
3060 dyn ? "yes": "no",
3061 (unsigned int)(dyn ? dyn->length : 0),
3062 location));
3064 if (body.length < 2) {
3065 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3068 if ((body.length % 2) != 0) {
3069 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3072 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3073 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
3074 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
3076 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
3077 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
3079 outbody_v->iov_base = (void *)body.data;
3080 outbody_v->iov_len = body.length;
3082 if (dyn) {
3083 outdyn_v->iov_base = (void *)dyn->data;
3084 outdyn_v->iov_len = dyn->length;
3085 } else {
3086 outdyn_v->iov_base = NULL;
3087 outdyn_v->iov_len = 0;
3091 * See if we need to recalculate the offset to the next response
3093 * Note that all responses may require padding (including the very last
3094 * one).
3096 if (req->out.vector_count >= (2 * SMBD_SMB2_NUM_IOV_PER_REQ)) {
3097 next_command_ofs = SMB2_HDR_BODY;
3098 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
3099 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
3102 if ((next_command_ofs % 8) != 0) {
3103 size_t pad_size = 8 - (next_command_ofs % 8);
3104 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
3106 * if the dyn buffer is empty
3107 * we can use it to add padding
3109 uint8_t *pad;
3111 pad = talloc_zero_array(req,
3112 uint8_t, pad_size);
3113 if (pad == NULL) {
3114 return smbd_smb2_request_error(req,
3115 NT_STATUS_NO_MEMORY);
3118 outdyn_v->iov_base = (void *)pad;
3119 outdyn_v->iov_len = pad_size;
3120 } else {
3122 * For now we copy the dynamic buffer
3123 * and add the padding to the new buffer
3125 size_t old_size;
3126 uint8_t *old_dyn;
3127 size_t new_size;
3128 uint8_t *new_dyn;
3130 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
3131 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
3133 new_size = old_size + pad_size;
3134 new_dyn = talloc_zero_array(req,
3135 uint8_t, new_size);
3136 if (new_dyn == NULL) {
3137 return smbd_smb2_request_error(req,
3138 NT_STATUS_NO_MEMORY);
3141 memcpy(new_dyn, old_dyn, old_size);
3142 memset(new_dyn + old_size, 0, pad_size);
3144 outdyn_v->iov_base = (void *)new_dyn;
3145 outdyn_v->iov_len = new_size;
3147 next_command_ofs += pad_size;
3150 if ((req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) >= req->out.vector_count) {
3151 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
3152 } else {
3153 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
3155 return smbd_smb2_request_reply(req);
3158 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
3159 NTSTATUS status,
3160 DATA_BLOB *info,
3161 const char *location)
3163 struct smbXsrv_connection *xconn = req->xconn;
3164 DATA_BLOB body;
3165 DATA_BLOB _dyn;
3166 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3167 size_t unread_bytes = smbd_smb2_unread_bytes(req);
3169 DBG_NOTICE("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| "
3170 "at %s\n", req->current_idx, nt_errstr(status),
3171 info ? " +info" : "", location);
3173 if (unread_bytes) {
3174 /* Recvfile error. Drain incoming socket. */
3175 size_t ret;
3177 errno = 0;
3178 ret = drain_socket(xconn->transport.sock, unread_bytes);
3179 if (ret != unread_bytes) {
3180 NTSTATUS error;
3182 if (errno == 0) {
3183 error = NT_STATUS_IO_DEVICE_ERROR;
3184 } else {
3185 error = map_nt_error_from_unix_common(errno);
3188 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
3189 "ret[%u] errno[%d] => %s\n",
3190 (unsigned)unread_bytes,
3191 (unsigned)ret, errno, nt_errstr(error)));
3192 return error;
3196 body.data = outhdr + SMB2_HDR_BODY;
3197 body.length = 8;
3198 SSVAL(body.data, 0, 9);
3200 if (info) {
3201 SIVAL(body.data, 0x04, info->length);
3202 } else {
3203 /* Allocated size of req->out.vector[i].iov_base
3204 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
3205 * 1 byte without having to do an alloc.
3207 info = &_dyn;
3208 info->data = ((uint8_t *)outhdr) +
3209 OUTVEC_ALLOC_SIZE - 1;
3210 info->length = 1;
3211 SCVAL(info->data, 0, 0);
3215 * Note: Even if there is an error, continue to process the request.
3216 * per MS-SMB2.
3219 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
3223 struct smbd_smb2_send_break_state {
3224 struct smbd_smb2_send_queue queue_entry;
3225 uint8_t nbt_hdr[NBT_HDR_SIZE];
3226 uint8_t tf[SMB2_TF_HDR_SIZE];
3227 uint8_t hdr[SMB2_HDR_BODY];
3228 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
3229 uint8_t body[1];
3232 static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
3233 struct smbXsrv_session *session,
3234 struct smbXsrv_tcon *tcon,
3235 const uint8_t *body,
3236 size_t body_len)
3238 struct smbd_smb2_send_break_state *state;
3239 bool do_encryption = false;
3240 uint64_t session_wire_id = 0;
3241 uint64_t nonce_high = 0;
3242 uint64_t nonce_low = 0;
3243 NTSTATUS status;
3244 size_t statelen;
3245 bool ok;
3247 if (session != NULL) {
3248 session_wire_id = session->global->session_wire_id;
3249 do_encryption = session->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
3250 if (tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
3251 do_encryption = true;
3255 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
3256 body_len;
3258 state = talloc_zero_size(xconn, statelen);
3259 if (state == NULL) {
3260 return NT_STATUS_NO_MEMORY;
3262 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
3264 if (do_encryption) {
3265 status = smb2_get_new_nonce(session,
3266 &nonce_high,
3267 &nonce_low);
3268 if (!NT_STATUS_IS_OK(status)) {
3269 return status;
3273 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
3274 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
3275 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
3276 SBVAL(state->tf, SMB2_TF_SESSION_ID, session_wire_id);
3278 SIVAL(state->hdr, 0, SMB2_MAGIC);
3279 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
3280 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
3281 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
3282 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
3283 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
3284 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
3285 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
3286 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
3287 SIVAL(state->hdr, SMB2_HDR_PID, 0);
3288 SIVAL(state->hdr, SMB2_HDR_TID, 0);
3289 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
3290 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
3292 state->vector[0] = (struct iovec) {
3293 .iov_base = state->nbt_hdr,
3294 .iov_len = sizeof(state->nbt_hdr)
3297 if (do_encryption) {
3298 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3299 .iov_base = state->tf,
3300 .iov_len = sizeof(state->tf)
3302 } else {
3303 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3304 .iov_base = NULL,
3305 .iov_len = 0
3309 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
3310 .iov_base = state->hdr,
3311 .iov_len = sizeof(state->hdr)
3314 memcpy(state->body, body, body_len);
3316 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
3317 .iov_base = state->body,
3318 .iov_len = body_len /* no sizeof(state->body) .. :-) */
3322 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
3325 ok = smb2_setup_nbt_length(state->vector,
3326 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
3327 if (!ok) {
3328 return NT_STATUS_INVALID_PARAMETER_MIX;
3331 if (do_encryption) {
3332 DATA_BLOB encryption_key = session->global->encryption_key;
3334 status = smb2_signing_encrypt_pdu(encryption_key,
3335 xconn->smb2.server.cipher,
3336 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
3337 SMBD_SMB2_NUM_IOV_PER_REQ);
3338 if (!NT_STATUS_IS_OK(status)) {
3339 return status;
3343 state->queue_entry.mem_ctx = state;
3344 state->queue_entry.vector = state->vector;
3345 state->queue_entry.count = ARRAY_SIZE(state->vector);
3346 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
3347 xconn->smb2.send_queue_len++;
3349 status = smbd_smb2_flush_send_queue(xconn);
3350 if (!NT_STATUS_IS_OK(status)) {
3351 return status;
3354 return NT_STATUS_OK;
3357 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_connection *xconn,
3358 struct smbXsrv_session *session,
3359 struct smbXsrv_tcon *tcon,
3360 struct smbXsrv_open *op,
3361 uint8_t oplock_level)
3363 uint8_t body[0x18];
3365 SSVAL(body, 0x00, sizeof(body));
3366 SCVAL(body, 0x02, oplock_level);
3367 SCVAL(body, 0x03, 0); /* reserved */
3368 SIVAL(body, 0x04, 0); /* reserved */
3369 SBVAL(body, 0x08, op->global->open_persistent_id);
3370 SBVAL(body, 0x10, op->global->open_volatile_id);
3372 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3375 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_connection *xconn,
3376 uint16_t new_epoch,
3377 uint32_t lease_flags,
3378 struct smb2_lease_key *lease_key,
3379 uint32_t current_lease_state,
3380 uint32_t new_lease_state)
3382 uint8_t body[0x2c];
3384 SSVAL(body, 0x00, sizeof(body));
3385 SSVAL(body, 0x02, new_epoch);
3386 SIVAL(body, 0x04, lease_flags);
3387 SBVAL(body, 0x08, lease_key->data[0]);
3388 SBVAL(body, 0x10, lease_key->data[1]);
3389 SIVAL(body, 0x18, current_lease_state);
3390 SIVAL(body, 0x1c, new_lease_state);
3391 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
3392 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
3393 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
3395 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3398 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
3400 NTSTATUS status;
3401 uint32_t flags;
3402 uint64_t file_id_persistent;
3403 uint64_t file_id_volatile;
3404 struct smbXsrv_open *op = NULL;
3405 struct files_struct *fsp = NULL;
3406 const uint8_t *body = NULL;
3409 * This is only called with a pktbuf
3410 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
3411 * bytes
3414 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
3415 /* Transform header. Cannot recvfile. */
3416 return false;
3418 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
3419 /* Not SMB2. Normal error path will cope. */
3420 return false;
3422 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
3423 /* Not SMB2. Normal error path will cope. */
3424 return false;
3426 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
3427 /* Needs to be a WRITE. */
3428 return false;
3430 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
3431 /* Chained. Cannot recvfile. */
3432 return false;
3434 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
3435 if (flags & SMB2_HDR_FLAG_CHAINED) {
3436 /* Chained. Cannot recvfile. */
3437 return false;
3439 if (flags & SMB2_HDR_FLAG_SIGNED) {
3440 /* Signed. Cannot recvfile. */
3441 return false;
3444 body = &state->pktbuf[SMB2_HDR_BODY];
3446 file_id_persistent = BVAL(body, 0x10);
3447 file_id_volatile = BVAL(body, 0x18);
3449 status = smb2srv_open_lookup(state->req->xconn,
3450 file_id_persistent,
3451 file_id_volatile,
3452 0, /* now */
3453 &op);
3454 if (!NT_STATUS_IS_OK(status)) {
3455 return false;
3458 fsp = op->compat;
3459 if (fsp == NULL) {
3460 return false;
3462 if (fsp->conn == NULL) {
3463 return false;
3466 if (IS_IPC(fsp->conn)) {
3467 return false;
3469 if (IS_PRINT(fsp->conn)) {
3470 return false;
3473 DEBUG(10,("Doing recvfile write len = %u\n",
3474 (unsigned int)(state->pktfull - state->pktlen)));
3476 return true;
3479 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
3481 struct smbd_server_connection *sconn = xconn->client->sconn;
3482 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3483 size_t max_send_queue_len;
3484 size_t cur_send_queue_len;
3486 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3488 * we're not supposed to do any io
3490 return NT_STATUS_OK;
3493 if (state->req != NULL) {
3495 * if there is already a tstream_readv_pdu
3496 * pending, we are done.
3498 return NT_STATUS_OK;
3501 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
3502 cur_send_queue_len = xconn->smb2.send_queue_len;
3504 if (cur_send_queue_len > max_send_queue_len) {
3506 * if we have a lot of requests to send,
3507 * we wait until they are on the wire until we
3508 * ask for the next request.
3510 return NT_STATUS_OK;
3513 /* ask for the next request */
3514 ZERO_STRUCTP(state);
3515 state->req = smbd_smb2_request_allocate(xconn);
3516 if (state->req == NULL) {
3517 return NT_STATUS_NO_MEMORY;
3519 state->req->sconn = sconn;
3520 state->req->xconn = xconn;
3521 state->min_recv_size = lp_min_receive_file_size();
3523 TEVENT_FD_READABLE(xconn->transport.fde);
3525 return NT_STATUS_OK;
3528 void smbd_smb2_process_negprot(struct smbXsrv_connection *xconn,
3529 uint64_t expected_seq_low,
3530 const uint8_t *inpdu, size_t size)
3532 struct smbd_server_connection *sconn = xconn->client->sconn;
3533 NTSTATUS status;
3534 struct smbd_smb2_request *req = NULL;
3536 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3537 (unsigned int)size));
3539 status = smbd_initialize_smb2(xconn, expected_seq_low);
3540 if (!NT_STATUS_IS_OK(status)) {
3541 smbd_server_connection_terminate(xconn, nt_errstr(status));
3542 return;
3545 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
3546 if (!NT_STATUS_IS_OK(status)) {
3547 smbd_server_connection_terminate(xconn, nt_errstr(status));
3548 return;
3551 status = smbd_smb2_request_validate(req);
3552 if (!NT_STATUS_IS_OK(status)) {
3553 smbd_server_connection_terminate(xconn, nt_errstr(status));
3554 return;
3557 status = smbd_smb2_request_setup_out(req);
3558 if (!NT_STATUS_IS_OK(status)) {
3559 smbd_server_connection_terminate(xconn, nt_errstr(status));
3560 return;
3563 #ifdef WITH_PROFILE
3565 * this was already counted at the SMB1 layer =>
3566 * smbd_smb2_request_dispatch() should not count it twice.
3568 if (profile_p->values.request_stats.count > 0) {
3569 profile_p->values.request_stats.count--;
3571 #endif
3572 status = smbd_smb2_request_dispatch(req);
3573 if (!NT_STATUS_IS_OK(status)) {
3574 smbd_server_connection_terminate(xconn, nt_errstr(status));
3575 return;
3578 status = smbd_smb2_request_next_incoming(xconn);
3579 if (!NT_STATUS_IS_OK(status)) {
3580 smbd_server_connection_terminate(xconn, nt_errstr(status));
3581 return;
3584 sconn->num_requests++;
3587 static int socket_error_from_errno(int ret,
3588 int sys_errno,
3589 bool *retry)
3591 *retry = false;
3593 if (ret >= 0) {
3594 return 0;
3597 if (ret != -1) {
3598 return EIO;
3601 if (sys_errno == 0) {
3602 return EIO;
3605 if (sys_errno == EINTR) {
3606 *retry = true;
3607 return sys_errno;
3610 if (sys_errno == EINPROGRESS) {
3611 *retry = true;
3612 return sys_errno;
3615 if (sys_errno == EAGAIN) {
3616 *retry = true;
3617 return sys_errno;
3620 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3621 if (sys_errno == ENOMEM) {
3622 *retry = true;
3623 return sys_errno;
3626 #ifdef EWOULDBLOCK
3627 #if EWOULDBLOCK != EAGAIN
3628 if (sys_errno == EWOULDBLOCK) {
3629 *retry = true;
3630 return sys_errno;
3632 #endif
3633 #endif
3635 return sys_errno;
3638 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3640 int ret;
3641 int err;
3642 bool retry;
3643 NTSTATUS status;
3645 if (xconn->smb2.send_queue == NULL) {
3646 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3647 return NT_STATUS_OK;
3650 while (xconn->smb2.send_queue != NULL) {
3651 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3652 bool ok;
3654 if (e->sendfile_header != NULL) {
3655 size_t size = 0;
3656 size_t i = 0;
3657 uint8_t *buf;
3659 status = NT_STATUS_INTERNAL_ERROR;
3661 for (i=0; i < e->count; i++) {
3662 size += e->vector[i].iov_len;
3665 if (size <= e->sendfile_header->length) {
3666 buf = e->sendfile_header->data;
3667 } else {
3668 buf = talloc_array(e->mem_ctx, uint8_t, size);
3669 if (buf == NULL) {
3670 return NT_STATUS_NO_MEMORY;
3674 size = 0;
3675 for (i=0; i < e->count; i++) {
3676 memcpy(buf+size,
3677 e->vector[i].iov_base,
3678 e->vector[i].iov_len);
3679 size += e->vector[i].iov_len;
3682 e->sendfile_header->data = buf;
3683 e->sendfile_header->length = size;
3684 e->sendfile_status = &status;
3685 e->count = 0;
3687 xconn->smb2.send_queue_len--;
3688 DLIST_REMOVE(xconn->smb2.send_queue, e);
3690 * This triggers the sendfile path via
3691 * the destructor.
3693 talloc_free(e->mem_ctx);
3695 if (!NT_STATUS_IS_OK(status)) {
3696 return status;
3698 continue;
3701 ret = writev(xconn->transport.sock, e->vector, e->count);
3702 if (ret == 0) {
3703 /* propagate end of file */
3704 return NT_STATUS_INTERNAL_ERROR;
3706 err = socket_error_from_errno(ret, errno, &retry);
3707 if (retry) {
3708 /* retry later */
3709 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3710 return NT_STATUS_OK;
3712 if (err != 0) {
3713 return map_nt_error_from_unix_common(err);
3716 ok = iov_advance(&e->vector, &e->count, ret);
3717 if (!ok) {
3718 return NT_STATUS_INTERNAL_ERROR;
3721 if (e->count > 0) {
3722 /* we have more to write */
3723 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3724 return NT_STATUS_OK;
3727 xconn->smb2.send_queue_len--;
3728 DLIST_REMOVE(xconn->smb2.send_queue, e);
3729 talloc_free(e->mem_ctx);
3733 * Restart reads if we were blocked on
3734 * draining the send queue.
3737 status = smbd_smb2_request_next_incoming(xconn);
3738 if (!NT_STATUS_IS_OK(status)) {
3739 return status;
3742 return NT_STATUS_OK;
3745 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3746 uint16_t fde_flags)
3748 struct smbd_server_connection *sconn = xconn->client->sconn;
3749 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3750 struct smbd_smb2_request *req = NULL;
3751 size_t min_recvfile_size = UINT32_MAX;
3752 int ret;
3753 int err;
3754 bool retry;
3755 NTSTATUS status;
3756 NTTIME now;
3758 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3760 * we're not supposed to do any io
3762 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3763 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3764 return NT_STATUS_OK;
3767 if (fde_flags & TEVENT_FD_WRITE) {
3768 status = smbd_smb2_flush_send_queue(xconn);
3769 if (!NT_STATUS_IS_OK(status)) {
3770 return status;
3774 if (!(fde_flags & TEVENT_FD_READ)) {
3775 return NT_STATUS_OK;
3778 if (state->req == NULL) {
3779 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3780 return NT_STATUS_OK;
3783 again:
3784 if (!state->hdr.done) {
3785 state->hdr.done = true;
3787 state->vector.iov_base = (void *)state->hdr.nbt;
3788 state->vector.iov_len = NBT_HDR_SIZE;
3791 ret = readv(xconn->transport.sock, &state->vector, 1);
3792 if (ret == 0) {
3793 /* propagate end of file */
3794 return NT_STATUS_END_OF_FILE;
3796 err = socket_error_from_errno(ret, errno, &retry);
3797 if (retry) {
3798 /* retry later */
3799 TEVENT_FD_READABLE(xconn->transport.fde);
3800 return NT_STATUS_OK;
3802 if (err != 0) {
3803 return map_nt_error_from_unix_common(err);
3806 if (ret < state->vector.iov_len) {
3807 uint8_t *base;
3808 base = (uint8_t *)state->vector.iov_base;
3809 base += ret;
3810 state->vector.iov_base = (void *)base;
3811 state->vector.iov_len -= ret;
3812 /* we have more to read */
3813 TEVENT_FD_READABLE(xconn->transport.fde);
3814 return NT_STATUS_OK;
3817 if (state->pktlen > 0) {
3818 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3820 * Not a possible receivefile write.
3821 * Read the rest of the data.
3823 state->doing_receivefile = false;
3825 state->pktbuf = talloc_realloc(state->req,
3826 state->pktbuf,
3827 uint8_t,
3828 state->pktfull);
3829 if (state->pktbuf == NULL) {
3830 return NT_STATUS_NO_MEMORY;
3833 state->vector.iov_base = (void *)(state->pktbuf +
3834 state->pktlen);
3835 state->vector.iov_len = (state->pktfull -
3836 state->pktlen);
3838 state->pktlen = state->pktfull;
3839 goto again;
3843 * Either this is a receivefile write so we've
3844 * done a short read, or if not we have all the data.
3846 goto got_full;
3850 * Now we analyze the NBT header
3852 if (state->hdr.nbt[0] != 0x00) {
3853 state->min_recv_size = 0;
3855 state->pktfull = smb2_len(state->hdr.nbt);
3856 if (state->pktfull == 0) {
3857 goto got_full;
3860 if (state->min_recv_size != 0) {
3861 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3862 min_recvfile_size += state->min_recv_size;
3865 if (state->pktfull > min_recvfile_size) {
3867 * Might be a receivefile write. Read the SMB2 HEADER +
3868 * SMB2_WRITE header first. Set 'doing_receivefile'
3869 * as we're *attempting* receivefile write. If this
3870 * turns out not to be a SMB2_WRITE request or otherwise
3871 * not suitable then we'll just read the rest of the data
3872 * the next time this function is called.
3874 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3875 state->doing_receivefile = true;
3876 } else {
3877 state->pktlen = state->pktfull;
3880 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3881 if (state->pktbuf == NULL) {
3882 return NT_STATUS_NO_MEMORY;
3885 state->vector.iov_base = (void *)state->pktbuf;
3886 state->vector.iov_len = state->pktlen;
3888 goto again;
3890 got_full:
3892 if (state->hdr.nbt[0] != 0x00) {
3893 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3894 state->hdr.nbt[0]));
3896 req = state->req;
3897 ZERO_STRUCTP(state);
3898 state->req = req;
3899 state->min_recv_size = lp_min_receive_file_size();
3900 req = NULL;
3901 goto again;
3904 req = state->req;
3905 state->req = NULL;
3907 req->request_time = timeval_current();
3908 now = timeval_to_nttime(&req->request_time);
3910 status = smbd_smb2_inbuf_parse_compound(xconn,
3911 now,
3912 state->pktbuf,
3913 state->pktlen,
3914 req,
3915 &req->in.vector,
3916 &req->in.vector_count);
3917 if (!NT_STATUS_IS_OK(status)) {
3918 return status;
3921 if (state->doing_receivefile) {
3922 req->smb1req = talloc_zero(req, struct smb_request);
3923 if (req->smb1req == NULL) {
3924 return NT_STATUS_NO_MEMORY;
3926 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3929 ZERO_STRUCTP(state);
3931 req->current_idx = 1;
3933 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3934 req->current_idx, req->in.vector_count));
3936 status = smbd_smb2_request_validate(req);
3937 if (!NT_STATUS_IS_OK(status)) {
3938 return status;
3941 status = smbd_smb2_request_setup_out(req);
3942 if (!NT_STATUS_IS_OK(status)) {
3943 return status;
3946 status = smbd_smb2_request_dispatch(req);
3947 if (!NT_STATUS_IS_OK(status)) {
3948 return status;
3951 sconn->num_requests++;
3953 /* The timeout_processing function isn't run nearly
3954 often enough to implement 'max log size' without
3955 overrunning the size of the file by many megabytes.
3956 This is especially true if we are running at debug
3957 level 10. Checking every 50 SMB2s is a nice
3958 tradeoff of performance vs log file size overrun. */
3960 if ((sconn->num_requests % 50) == 0 &&
3961 need_to_check_log_size()) {
3962 change_to_root_user();
3963 check_log_size();
3966 status = smbd_smb2_request_next_incoming(xconn);
3967 if (!NT_STATUS_IS_OK(status)) {
3968 return status;
3971 return NT_STATUS_OK;
3974 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3975 struct tevent_fd *fde,
3976 uint16_t flags,
3977 void *private_data)
3979 struct smbXsrv_connection *xconn =
3980 talloc_get_type_abort(private_data,
3981 struct smbXsrv_connection);
3982 NTSTATUS status;
3984 status = smbd_smb2_io_handler(xconn, flags);
3985 if (!NT_STATUS_IS_OK(status)) {
3986 smbd_server_connection_terminate(xconn, nt_errstr(status));
3987 return;