smbd: add missing DO_PROFILE_INC(disconnect) to smbd_server_connection_terminate_ex()
[Samba.git] / source3 / smbd / smb2_server.c
blob229f8ab0e856beb86cdf3e5c32a608bb467919ac
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(
231 xconn->client->raw_ev_ctx,
232 xconn,
233 xconn->transport.sock,
234 TEVENT_FD_READ,
235 smbd_smb2_connection_handler,
236 xconn);
237 if (xconn->transport.fde == NULL) {
238 return NT_STATUS_NO_MEMORY;
241 /* Ensure child is set to non-blocking mode */
242 set_blocking(xconn->transport.sock, false);
243 return NT_STATUS_OK;
246 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
247 #define _smb2_setlen(_buf,len) do { \
248 uint8_t *buf = (uint8_t *)_buf; \
249 buf[0] = 0; \
250 buf[1] = ((len)&0xFF0000)>>16; \
251 buf[2] = ((len)&0xFF00)>>8; \
252 buf[3] = (len)&0xFF; \
253 } while (0)
255 static bool smb2_setup_nbt_length(struct iovec *vector, int count)
257 ssize_t len;
259 if (count == 0) {
260 return false;
263 len = iov_buflen(vector+1, count-1);
265 if ((len == -1) || (len > 0xFFFFFF)) {
266 return false;
269 _smb2_setlen(vector[0].iov_base, len);
270 return true;
273 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
275 if (req->first_key.length > 0) {
276 data_blob_clear_free(&req->first_key);
278 if (req->last_key.length > 0) {
279 data_blob_clear_free(&req->last_key);
281 return 0;
284 void smb2_request_set_async_internal(struct smbd_smb2_request *req,
285 bool async_internal)
287 req->async_internal = async_internal;
290 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
292 TALLOC_CTX *mem_pool;
293 struct smbd_smb2_request *req;
295 #if 0
296 /* Enable this to find subtle valgrind errors. */
297 mem_pool = talloc_init("smbd_smb2_request_allocate");
298 #else
299 mem_pool = talloc_tos();
300 #endif
301 if (mem_pool == NULL) {
302 return NULL;
305 req = talloc_zero(mem_pool, struct smbd_smb2_request);
306 if (req == NULL) {
307 talloc_free(mem_pool);
308 return NULL;
310 talloc_reparent(mem_pool, mem_ctx, req);
311 #if 0
312 TALLOC_FREE(mem_pool);
313 #endif
315 req->last_session_id = UINT64_MAX;
316 req->last_tid = UINT32_MAX;
318 talloc_set_destructor(req, smbd_smb2_request_destructor);
320 return req;
323 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
324 NTTIME now,
325 uint8_t *buf,
326 size_t buflen,
327 struct smbd_smb2_request *req,
328 struct iovec **piov,
329 int *pnum_iov)
331 TALLOC_CTX *mem_ctx = req;
332 struct iovec *iov;
333 int num_iov = 1;
334 size_t taken = 0;
335 uint8_t *first_hdr = buf;
336 size_t verified_buflen = 0;
337 uint8_t *tf = NULL;
338 size_t tf_len = 0;
341 * Note: index '0' is reserved for the transport protocol
343 iov = req->in._vector;
345 while (taken < buflen) {
346 size_t len = buflen - taken;
347 uint8_t *hdr = first_hdr + taken;
348 struct iovec *cur;
349 size_t full_size;
350 size_t next_command_ofs;
351 uint16_t body_size;
352 uint8_t *body = NULL;
353 uint32_t dyn_size;
354 uint8_t *dyn = NULL;
355 struct iovec *iov_alloc = NULL;
357 if (iov != req->in._vector) {
358 iov_alloc = iov;
361 if (verified_buflen > taken) {
362 len = verified_buflen - taken;
363 } else {
364 tf = NULL;
365 tf_len = 0;
368 if (len < 4) {
369 DEBUG(10, ("%d bytes left, expected at least %d\n",
370 (int)len, 4));
371 goto inval;
373 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
374 struct smbXsrv_session *s = NULL;
375 uint64_t uid;
376 struct iovec tf_iov[2];
377 NTSTATUS status;
378 size_t enc_len;
380 if (xconn->protocol < PROTOCOL_SMB2_24) {
381 DEBUG(10, ("Got SMB2_TRANSFORM header, "
382 "but dialect[0x%04X] is used\n",
383 xconn->smb2.server.dialect));
384 goto inval;
387 if (xconn->smb2.server.cipher == 0) {
388 DEBUG(10, ("Got SMB2_TRANSFORM header, "
389 "but not negotiated "
390 "client[0x%08X] server[0x%08X]\n",
391 xconn->smb2.client.capabilities,
392 xconn->smb2.server.capabilities));
393 goto inval;
396 if (len < SMB2_TF_HDR_SIZE) {
397 DEBUG(1, ("%d bytes left, expected at least %d\n",
398 (int)len, SMB2_TF_HDR_SIZE));
399 goto inval;
401 tf = hdr;
402 tf_len = SMB2_TF_HDR_SIZE;
403 taken += tf_len;
405 hdr = first_hdr + taken;
406 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
407 uid = BVAL(tf, SMB2_TF_SESSION_ID);
409 if (len < SMB2_TF_HDR_SIZE + enc_len) {
410 DEBUG(1, ("%d bytes left, expected at least %d\n",
411 (int)len,
412 (int)(SMB2_TF_HDR_SIZE + enc_len)));
413 goto inval;
416 status = smb2srv_session_lookup_conn(xconn, uid, now,
417 &s);
418 if (s == NULL) {
419 DEBUG(1, ("invalid session[%llu] in "
420 "SMB2_TRANSFORM header\n",
421 (unsigned long long)uid));
422 TALLOC_FREE(iov_alloc);
423 return NT_STATUS_USER_SESSION_DELETED;
426 tf_iov[0].iov_base = (void *)tf;
427 tf_iov[0].iov_len = tf_len;
428 tf_iov[1].iov_base = (void *)hdr;
429 tf_iov[1].iov_len = enc_len;
431 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
432 xconn->smb2.server.cipher,
433 tf_iov, 2);
434 if (!NT_STATUS_IS_OK(status)) {
435 TALLOC_FREE(iov_alloc);
436 return status;
439 verified_buflen = taken + enc_len;
440 len = enc_len;
444 * We need the header plus the body length field
447 if (len < SMB2_HDR_BODY + 2) {
448 DEBUG(10, ("%d bytes left, expected at least %d\n",
449 (int)len, SMB2_HDR_BODY));
450 goto inval;
452 if (IVAL(hdr, 0) != SMB2_MAGIC) {
453 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
454 IVAL(hdr, 0)));
455 goto inval;
457 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
458 DEBUG(10, ("Got HDR len %d, expected %d\n",
459 SVAL(hdr, 4), SMB2_HDR_BODY));
460 goto inval;
463 full_size = len;
464 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
465 body_size = SVAL(hdr, SMB2_HDR_BODY);
467 if (next_command_ofs != 0) {
468 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
469 goto inval;
471 if (next_command_ofs > full_size) {
472 goto inval;
474 full_size = next_command_ofs;
476 if (body_size < 2) {
477 goto inval;
479 body_size &= 0xfffe;
481 if (body_size > (full_size - SMB2_HDR_BODY)) {
483 * let the caller handle the error
485 body_size = full_size - SMB2_HDR_BODY;
487 body = hdr + SMB2_HDR_BODY;
488 dyn = body + body_size;
489 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
491 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
492 struct iovec *iov_tmp = NULL;
494 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
495 struct iovec,
496 num_iov +
497 SMBD_SMB2_NUM_IOV_PER_REQ);
498 if (iov_tmp == NULL) {
499 TALLOC_FREE(iov_alloc);
500 return NT_STATUS_NO_MEMORY;
503 if (iov_alloc == NULL) {
504 memcpy(iov_tmp,
505 req->in._vector,
506 sizeof(req->in._vector));
509 iov = iov_tmp;
511 cur = &iov[num_iov];
512 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
514 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
515 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
516 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
517 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
518 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
519 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
520 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
521 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
523 taken += full_size;
526 *piov = iov;
527 *pnum_iov = num_iov;
528 return NT_STATUS_OK;
530 inval:
531 if (iov != req->in._vector) {
532 TALLOC_FREE(iov);
534 return NT_STATUS_INVALID_PARAMETER;
537 static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
538 const uint8_t *_inpdu, size_t size,
539 struct smbd_smb2_request **_req)
541 struct smbd_server_connection *sconn = xconn->client->sconn;
542 struct smbd_smb2_request *req;
543 uint32_t protocol_version;
544 uint8_t *inpdu = NULL;
545 const uint8_t *inhdr = NULL;
546 uint16_t cmd;
547 uint32_t next_command_ofs;
548 NTSTATUS status;
549 NTTIME now;
551 if (size < (SMB2_HDR_BODY + 2)) {
552 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
553 return NT_STATUS_INVALID_PARAMETER;
556 inhdr = _inpdu;
558 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
559 if (protocol_version != SMB2_MAGIC) {
560 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
561 protocol_version));
562 return NT_STATUS_INVALID_PARAMETER;
565 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
566 if (cmd != SMB2_OP_NEGPROT) {
567 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
568 cmd));
569 return NT_STATUS_INVALID_PARAMETER;
572 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
573 if (next_command_ofs != 0) {
574 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
575 next_command_ofs));
576 return NT_STATUS_INVALID_PARAMETER;
579 req = smbd_smb2_request_allocate(xconn);
580 if (req == NULL) {
581 return NT_STATUS_NO_MEMORY;
583 req->sconn = sconn;
584 req->xconn = xconn;
586 inpdu = talloc_memdup(req, _inpdu, size);
587 if (inpdu == NULL) {
588 return NT_STATUS_NO_MEMORY;
591 req->request_time = timeval_current();
592 now = timeval_to_nttime(&req->request_time);
594 status = smbd_smb2_inbuf_parse_compound(xconn,
595 now,
596 inpdu,
597 size,
598 req, &req->in.vector,
599 &req->in.vector_count);
600 if (!NT_STATUS_IS_OK(status)) {
601 TALLOC_FREE(req);
602 return status;
605 req->current_idx = 1;
607 *_req = req;
608 return NT_STATUS_OK;
611 static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
612 uint64_t message_id, uint64_t seq_id)
614 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
615 unsigned int offset;
616 uint64_t seq_tmp;
618 seq_tmp = xconn->smb2.credits.seq_low;
619 if (seq_id < seq_tmp) {
620 DBGC_ERR(DBGC_SMB2_CREDITS,
621 "smb2_validate_sequence_number: bad message_id "
622 "%llu (sequence id %llu) "
623 "(granted = %u, low = %llu, range = %u)\n",
624 (unsigned long long)message_id,
625 (unsigned long long)seq_id,
626 (unsigned int)xconn->smb2.credits.granted,
627 (unsigned long long)xconn->smb2.credits.seq_low,
628 (unsigned int)xconn->smb2.credits.seq_range);
629 return false;
632 seq_tmp += xconn->smb2.credits.seq_range;
633 if (seq_id >= seq_tmp) {
634 DBGC_ERR(DBGC_SMB2_CREDITS,
635 "smb2_validate_sequence_number: bad message_id "
636 "%llu (sequence id %llu) "
637 "(granted = %u, low = %llu, range = %u)\n",
638 (unsigned long long)message_id,
639 (unsigned long long)seq_id,
640 (unsigned int)xconn->smb2.credits.granted,
641 (unsigned long long)xconn->smb2.credits.seq_low,
642 (unsigned int)xconn->smb2.credits.seq_range);
643 return false;
646 offset = seq_id % xconn->smb2.credits.max;
648 if (bitmap_query(credits_bm, offset)) {
649 DBGC_ERR(DBGC_SMB2_CREDITS,
650 "smb2_validate_sequence_number: duplicate message_id "
651 "%llu (sequence id %llu) "
652 "(granted = %u, low = %llu, range = %u) "
653 "(bm offset %u)\n",
654 (unsigned long long)message_id,
655 (unsigned long long)seq_id,
656 (unsigned int)xconn->smb2.credits.granted,
657 (unsigned long long)xconn->smb2.credits.seq_low,
658 (unsigned int)xconn->smb2.credits.seq_range,
659 offset);
660 return false;
663 /* Mark the message_ids as seen in the bitmap. */
664 bitmap_set(credits_bm, offset);
666 if (seq_id != xconn->smb2.credits.seq_low) {
667 return true;
671 * Move the window forward by all the message_id's
672 * already seen.
674 while (bitmap_query(credits_bm, offset)) {
675 DBGC_DEBUG(DBGC_SMB2_CREDITS,
676 "smb2_validate_sequence_number: clearing "
677 "id %llu (position %u) from bitmap\n",
678 (unsigned long long)(xconn->smb2.credits.seq_low),
679 offset);
680 bitmap_clear(credits_bm, offset);
682 xconn->smb2.credits.seq_low += 1;
683 xconn->smb2.credits.seq_range -= 1;
684 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
687 return true;
690 static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
691 const uint8_t *inhdr)
693 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
694 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
695 uint16_t credit_charge = 1;
696 uint64_t i;
698 if (opcode == SMB2_OP_CANCEL) {
699 /* SMB2_CANCEL requests by definition resend messageids. */
700 return true;
703 if (xconn->smb2.credits.multicredit) {
704 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
705 credit_charge = MAX(credit_charge, 1);
708 DEBUGC(11,
709 DBGC_SMB2_CREDITS,
710 ("smb2_validate_message_id: mid %llu (charge %llu), "
711 "credits_granted %llu, "
712 "seqnum low/range: %llu/%llu\n",
713 (unsigned long long) message_id,
714 (unsigned long long) credit_charge,
715 (unsigned long long) xconn->smb2.credits.granted,
716 (unsigned long long) xconn->smb2.credits.seq_low,
717 (unsigned long long) xconn->smb2.credits.seq_range));
719 if (xconn->smb2.credits.granted < credit_charge) {
720 DBGC_ERR(DBGC_SMB2_CREDITS,
721 "smb2_validate_message_id: client used more "
722 "credits than granted, mid %llu, charge %llu, "
723 "credits_granted %llu, "
724 "seqnum low/range: %llu/%llu\n",
725 (unsigned long long) message_id,
726 (unsigned long long) credit_charge,
727 (unsigned long long) xconn->smb2.credits.granted,
728 (unsigned long long) xconn->smb2.credits.seq_low,
729 (unsigned long long) xconn->smb2.credits.seq_range);
730 return false;
734 * now check the message ids
736 * for multi-credit requests we need to check all current mid plus
737 * the implicit mids caused by the credit charge
738 * e.g. current mid = 15, charge 5 => mark 15-19 as used
741 for (i = 0; i <= (credit_charge-1); i++) {
742 uint64_t id = message_id + i;
743 bool ok;
745 DEBUGC(11,
746 DBGC_SMB2_CREDITS,
747 ("Iterating mid %llu charge %u (sequence %llu)\n",
748 (unsigned long long)message_id,
749 credit_charge,
750 (unsigned long long)id));
752 ok = smb2_validate_sequence_number(xconn, message_id, id);
753 if (!ok) {
754 return false;
758 /* substract used credits */
759 xconn->smb2.credits.granted -= credit_charge;
761 return true;
764 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
766 int count;
767 int idx;
769 count = req->in.vector_count;
771 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
772 /* It's not a SMB2 request */
773 return NT_STATUS_INVALID_PARAMETER;
776 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
777 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
778 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
779 const uint8_t *inhdr = NULL;
781 if (hdr->iov_len != SMB2_HDR_BODY) {
782 return NT_STATUS_INVALID_PARAMETER;
785 if (body->iov_len < 2) {
786 return NT_STATUS_INVALID_PARAMETER;
789 inhdr = (const uint8_t *)hdr->iov_base;
791 /* Check the SMB2 header */
792 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
793 return NT_STATUS_INVALID_PARAMETER;
796 if (!smb2_validate_message_id(req->xconn, inhdr)) {
797 return NT_STATUS_INVALID_PARAMETER;
801 return NT_STATUS_OK;
804 static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
805 const struct iovec *in_vector,
806 struct iovec *out_vector)
808 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
809 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
810 uint16_t credit_charge = 1;
811 uint16_t credits_requested;
812 uint32_t out_flags;
813 uint16_t cmd;
814 NTSTATUS out_status;
815 uint16_t credits_granted = 0;
816 uint64_t credits_possible;
817 uint16_t current_max_credits;
820 * first we grant only 1/16th of the max range.
822 * Windows also starts with the 1/16th and then grants
823 * more later. I was only able to trigger higher
824 * values, when using a very high credit charge.
826 * TODO: scale up depending on load, free memory
827 * or other stuff.
828 * Maybe also on the relationship between number
829 * of requests and the used sequence number.
830 * Which means we would grant more credits
831 * for client which use multi credit requests.
833 current_max_credits = xconn->smb2.credits.max / 16;
834 current_max_credits = MAX(current_max_credits, 1);
836 if (xconn->smb2.credits.multicredit) {
837 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
838 credit_charge = MAX(credit_charge, 1);
841 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
842 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
843 credits_requested = MAX(credits_requested, 1);
844 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
845 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
847 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
849 if (xconn->smb2.credits.max < credit_charge) {
850 smbd_server_connection_terminate(xconn,
851 "client error: credit charge > max credits\n");
852 return;
855 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
857 * In case we already send an async interim
858 * response, we should not grant
859 * credits on the final response.
861 credits_granted = 0;
862 } else {
863 uint16_t additional_possible =
864 xconn->smb2.credits.max - credit_charge;
865 uint16_t additional_max = 0;
866 uint16_t additional_credits = credits_requested - 1;
868 switch (cmd) {
869 case SMB2_OP_NEGPROT:
870 break;
871 case SMB2_OP_SESSSETUP:
873 * Windows 2012 RC1 starts to grant
874 * additional credits
875 * with a successful session setup
877 if (NT_STATUS_IS_OK(out_status)) {
878 additional_max = 32;
880 break;
881 default:
883 * We match windows and only grant additional credits
884 * in chunks of 32.
886 additional_max = 32;
887 break;
890 additional_max = MIN(additional_max, additional_possible);
891 additional_credits = MIN(additional_credits, additional_max);
893 credits_granted = credit_charge + additional_credits;
897 * sequence numbers should not wrap
899 * 1. calculate the possible credits until
900 * the sequence numbers start to wrap on 64-bit.
902 * 2. UINT64_MAX is used for Break Notifications.
904 * 2. truncate the possible credits to the maximum
905 * credits we want to grant to the client in total.
907 * 3. remove the range we'll already granted to the client
908 * this makes sure the client consumes the lowest sequence
909 * number, before we can grant additional credits.
911 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
912 if (credits_possible > 0) {
913 /* remove UINT64_MAX */
914 credits_possible -= 1;
916 credits_possible = MIN(credits_possible, current_max_credits);
917 credits_possible -= xconn->smb2.credits.seq_range;
919 credits_granted = MIN(credits_granted, credits_possible);
921 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
922 xconn->smb2.credits.granted += credits_granted;
923 xconn->smb2.credits.seq_range += credits_granted;
925 DBGC_DEBUG(DBGC_SMB2_CREDITS,
926 "smb2_set_operation_credit: requested %u, charge %u, "
927 "granted %u, current possible/max %u/%u, "
928 "total granted/max/low/range %u/%u/%llu/%u\n",
929 (unsigned int)credits_requested,
930 (unsigned int)credit_charge,
931 (unsigned int)credits_granted,
932 (unsigned int)credits_possible,
933 (unsigned int)current_max_credits,
934 (unsigned int)xconn->smb2.credits.granted,
935 (unsigned int)xconn->smb2.credits.max,
936 (unsigned long long)xconn->smb2.credits.seq_low,
937 (unsigned int)xconn->smb2.credits.seq_range);
940 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
941 struct smbd_smb2_request *outreq)
943 int count, idx;
944 uint16_t total_credits = 0;
946 count = outreq->out.vector_count;
948 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
949 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
950 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
951 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
953 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
955 /* To match Windows, count up what we
956 just granted. */
957 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
958 /* Set to zero in all but the last reply. */
959 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
960 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
961 } else {
962 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
967 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
969 if (req->current_idx <= 1) {
970 if (size <= sizeof(req->out._body)) {
971 return data_blob_const(req->out._body, size);
975 return data_blob_talloc(req, NULL, size);
978 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
980 struct smbXsrv_connection *xconn = req->xconn;
981 TALLOC_CTX *mem_ctx;
982 struct iovec *vector;
983 int count;
984 int idx;
985 bool ok;
987 count = req->in.vector_count;
988 if (count <= ARRAY_SIZE(req->out._vector)) {
989 mem_ctx = req;
990 vector = req->out._vector;
991 } else {
992 vector = talloc_zero_array(req, struct iovec, count);
993 if (vector == NULL) {
994 return NT_STATUS_NO_MEMORY;
996 mem_ctx = vector;
999 vector[0].iov_base = req->out.nbt_hdr;
1000 vector[0].iov_len = 4;
1001 SIVAL(req->out.nbt_hdr, 0, 0);
1003 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
1004 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
1005 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
1006 uint8_t *outhdr = NULL;
1007 uint8_t *outbody = NULL;
1008 uint32_t next_command_ofs = 0;
1009 struct iovec *current = &vector[idx];
1011 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
1012 /* we have a next command -
1013 * setup for the error case. */
1014 next_command_ofs = SMB2_HDR_BODY + 9;
1017 if (idx == 1) {
1018 outhdr = req->out._hdr;
1019 } else {
1020 outhdr = talloc_zero_array(mem_ctx, uint8_t,
1021 OUTVEC_ALLOC_SIZE);
1022 if (outhdr == NULL) {
1023 return NT_STATUS_NO_MEMORY;
1027 outbody = outhdr + SMB2_HDR_BODY;
1030 * SMBD_SMB2_TF_IOV_OFS might be used later
1032 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1033 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1035 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
1036 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1038 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1039 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1041 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1042 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1044 /* setup the SMB2 header */
1045 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1046 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1047 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1048 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1049 SIVAL(outhdr, SMB2_HDR_STATUS,
1050 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1051 SSVAL(outhdr, SMB2_HDR_OPCODE,
1052 SVAL(inhdr, SMB2_HDR_OPCODE));
1053 SIVAL(outhdr, SMB2_HDR_FLAGS,
1054 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1055 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1056 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1057 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1058 SIVAL(outhdr, SMB2_HDR_PID,
1059 IVAL(inhdr, SMB2_HDR_PID));
1060 SIVAL(outhdr, SMB2_HDR_TID,
1061 IVAL(inhdr, SMB2_HDR_TID));
1062 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1063 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1064 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1065 inhdr + SMB2_HDR_SIGNATURE, 16);
1067 /* setup error body header */
1068 SSVAL(outbody, 0x00, 0x08 + 1);
1069 SSVAL(outbody, 0x02, 0);
1070 SIVAL(outbody, 0x04, 0);
1073 req->out.vector = vector;
1074 req->out.vector_count = count;
1076 /* setup the length of the NBT packet */
1077 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1078 if (!ok) {
1079 return NT_STATUS_INVALID_PARAMETER_MIX;
1082 DLIST_ADD_END(xconn->smb2.requests, req);
1084 return NT_STATUS_OK;
1087 void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
1088 const char *reason,
1089 const char *location)
1091 struct smbXsrv_client *client = xconn->client;
1093 DEBUG(10,("smbd_server_connection_terminate_ex: conn[%s] reason[%s] at %s\n",
1094 smbXsrv_connection_dbg(xconn), reason, location));
1096 if (client->connections->next != NULL) {
1097 /* TODO: cancel pending requests */
1098 DLIST_REMOVE(client->connections, xconn);
1099 TALLOC_FREE(xconn);
1100 DO_PROFILE_INC(disconnect);
1101 return;
1105 * The last connection was disconnected
1107 exit_server_cleanly(reason);
1110 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1111 struct iovec *outvec,
1112 const struct iovec *srcvec)
1114 const uint8_t *srctf;
1115 size_t srctf_len;
1116 const uint8_t *srchdr;
1117 size_t srchdr_len;
1118 const uint8_t *srcbody;
1119 size_t srcbody_len;
1120 const uint8_t *expected_srcbody;
1121 const uint8_t *srcdyn;
1122 size_t srcdyn_len;
1123 const uint8_t *expected_srcdyn;
1124 uint8_t *dsttf;
1125 uint8_t *dsthdr;
1126 uint8_t *dstbody;
1127 uint8_t *dstdyn;
1129 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1130 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1131 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1132 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1133 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1134 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1135 expected_srcbody = srchdr + SMB2_HDR_BODY;
1136 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1137 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1138 expected_srcdyn = srcbody + 8;
1140 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1141 return false;
1144 if (srchdr_len != SMB2_HDR_BODY) {
1145 return false;
1148 if (srctf_len == SMB2_TF_HDR_SIZE) {
1149 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1150 if (dsttf == NULL) {
1151 return false;
1153 } else {
1154 dsttf = NULL;
1156 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1157 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1159 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1160 * be allocated with size OUTVEC_ALLOC_SIZE. */
1162 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1163 if (dsthdr == NULL) {
1164 return false;
1166 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1167 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1170 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1171 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1172 * then duplicate this. Else use talloc_memdup().
1175 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1176 dstbody = dsthdr + SMB2_HDR_BODY;
1177 } else {
1178 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1179 if (dstbody == NULL) {
1180 return false;
1183 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1184 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1187 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1188 * pointing to
1189 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1190 * then duplicate this. Else use talloc_memdup().
1193 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1194 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1195 } else if (srcdyn == NULL) {
1196 dstdyn = NULL;
1197 } else {
1198 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1199 if (dstdyn == NULL) {
1200 return false;
1203 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1204 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1206 return true;
1209 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1211 struct smbd_smb2_request *newreq = NULL;
1212 struct iovec *outvec = NULL;
1213 int count = req->out.vector_count;
1214 int i;
1215 bool ok;
1217 newreq = smbd_smb2_request_allocate(req->xconn);
1218 if (!newreq) {
1219 return NULL;
1222 newreq->sconn = req->sconn;
1223 newreq->xconn = req->xconn;
1224 newreq->session = req->session;
1225 newreq->do_encryption = req->do_encryption;
1226 newreq->do_signing = req->do_signing;
1227 newreq->current_idx = req->current_idx;
1229 outvec = talloc_zero_array(newreq, struct iovec, count);
1230 if (!outvec) {
1231 TALLOC_FREE(newreq);
1232 return NULL;
1234 newreq->out.vector = outvec;
1235 newreq->out.vector_count = count;
1237 /* Setup the outvec's identically to req. */
1238 outvec[0].iov_base = newreq->out.nbt_hdr;
1239 outvec[0].iov_len = 4;
1240 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1242 /* Setup the vectors identically to the ones in req. */
1243 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1244 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1245 break;
1249 if (i < count) {
1250 /* Alloc failed. */
1251 TALLOC_FREE(newreq);
1252 return NULL;
1255 ok = smb2_setup_nbt_length(newreq->out.vector,
1256 newreq->out.vector_count);
1257 if (!ok) {
1258 TALLOC_FREE(newreq);
1259 return NULL;
1262 return newreq;
1265 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1267 struct smbXsrv_connection *xconn = req->xconn;
1268 int first_idx = 1;
1269 struct iovec *firsttf = NULL;
1270 struct iovec *outhdr_v = NULL;
1271 uint8_t *outhdr = NULL;
1272 struct smbd_smb2_request *nreq = NULL;
1273 NTSTATUS status;
1274 bool ok;
1276 /* Create a new smb2 request we'll use
1277 for the interim return. */
1278 nreq = dup_smb2_req(req);
1279 if (!nreq) {
1280 return NT_STATUS_NO_MEMORY;
1283 /* Lose the last X out vectors. They're the
1284 ones we'll be using for the async reply. */
1285 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1287 ok = smb2_setup_nbt_length(nreq->out.vector,
1288 nreq->out.vector_count);
1289 if (!ok) {
1290 return NT_STATUS_INVALID_PARAMETER_MIX;
1293 /* Step back to the previous reply. */
1294 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1295 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1296 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1297 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1298 /* And end the chain. */
1299 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1301 /* Calculate outgoing credits */
1302 smb2_calculate_credits(req, nreq);
1304 if (DEBUGLEVEL >= 10) {
1305 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1306 (unsigned int)nreq->current_idx );
1307 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1308 (unsigned int)nreq->out.vector_count );
1309 print_req_vectors(nreq);
1313 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1314 * we need to sign/encrypt here with the last/first key we remembered
1316 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1317 status = smb2_signing_encrypt_pdu(req->first_key,
1318 xconn->smb2.server.cipher,
1319 firsttf,
1320 nreq->out.vector_count - first_idx);
1321 if (!NT_STATUS_IS_OK(status)) {
1322 return status;
1324 } else if (req->last_key.length > 0) {
1325 status = smb2_signing_sign_pdu(req->last_key,
1326 xconn->protocol,
1327 outhdr_v,
1328 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1329 if (!NT_STATUS_IS_OK(status)) {
1330 return status;
1334 nreq->queue_entry.mem_ctx = nreq;
1335 nreq->queue_entry.vector = nreq->out.vector;
1336 nreq->queue_entry.count = nreq->out.vector_count;
1337 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry);
1338 xconn->smb2.send_queue_len++;
1340 status = smbd_smb2_flush_send_queue(xconn);
1341 if (!NT_STATUS_IS_OK(status)) {
1342 return status;
1345 return NT_STATUS_OK;
1348 struct smbd_smb2_request_pending_state {
1349 struct smbd_smb2_send_queue queue_entry;
1350 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1351 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1354 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1355 struct tevent_timer *te,
1356 struct timeval current_time,
1357 void *private_data);
1359 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1360 struct tevent_req *subreq,
1361 uint32_t defer_time)
1363 NTSTATUS status;
1364 struct timeval defer_endtime;
1365 uint8_t *outhdr = NULL;
1366 uint32_t flags;
1368 if (!tevent_req_is_in_progress(subreq)) {
1370 * This is a performance optimization,
1371 * it avoids one tevent_loop iteration,
1372 * which means we avoid one
1373 * talloc_stackframe_pool/talloc_free pair.
1375 tevent_req_notify_callback(subreq);
1376 return NT_STATUS_OK;
1379 req->subreq = subreq;
1380 subreq = NULL;
1382 if (req->async_te) {
1383 /* We're already async. */
1384 return NT_STATUS_OK;
1387 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1388 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1389 if (flags & SMB2_HDR_FLAG_ASYNC) {
1390 /* We're already async. */
1391 return NT_STATUS_OK;
1394 if (req->async_internal) {
1396 * An SMB2 request implementation wants to handle the request
1397 * asynchronously "internally" while keeping synchronous
1398 * behaviour for the SMB2 request. This means we don't send an
1399 * interim response and we can allow processing of compound SMB2
1400 * requests (cf the subsequent check) for all cases.
1402 return NT_STATUS_OK;
1405 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1407 * We're trying to go async in a compound request
1408 * chain. This is only allowed for opens that cause an
1409 * oplock break or for the last operation in the
1410 * chain, otherwise it is not allowed. See
1411 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
1413 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1415 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1417 * Cancel the outstanding request.
1419 bool ok = tevent_req_cancel(req->subreq);
1420 if (ok) {
1421 return NT_STATUS_OK;
1423 TALLOC_FREE(req->subreq);
1424 return smbd_smb2_request_error(req,
1425 NT_STATUS_INTERNAL_ERROR);
1429 if (DEBUGLEVEL >= 10) {
1430 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1431 (unsigned int)req->current_idx );
1432 print_req_vectors(req);
1435 if (req->current_idx > 1) {
1437 * We're going async in a compound
1438 * chain after the first request has
1439 * already been processed. Send an
1440 * interim response containing the
1441 * set of replies already generated.
1443 int idx = req->current_idx;
1445 status = smb2_send_async_interim_response(req);
1446 if (!NT_STATUS_IS_OK(status)) {
1447 return status;
1449 if (req->first_key.length > 0) {
1450 data_blob_clear_free(&req->first_key);
1453 req->current_idx = 1;
1456 * Re-arrange the in.vectors to remove what
1457 * we just sent.
1459 memmove(&req->in.vector[1],
1460 &req->in.vector[idx],
1461 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1462 req->in.vector_count = 1 + (req->in.vector_count - idx);
1464 /* Re-arrange the out.vectors to match. */
1465 memmove(&req->out.vector[1],
1466 &req->out.vector[idx],
1467 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1468 req->out.vector_count = 1 + (req->out.vector_count - idx);
1470 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1472 * We only have one remaining request as
1473 * we've processed everything else.
1474 * This is no longer a compound request.
1476 req->compound_related = false;
1477 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1478 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1479 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1482 if (req->last_key.length > 0) {
1483 data_blob_clear_free(&req->last_key);
1487 * smbd_smb2_request_pending_timer() just send a packet
1488 * to the client and doesn't need any impersonation.
1489 * So we use req->xconn->client->raw_ev_ctx instead
1490 * of req->ev_ctx here.
1492 defer_endtime = timeval_current_ofs_usec(defer_time);
1493 req->async_te = tevent_add_timer(req->xconn->client->raw_ev_ctx,
1494 req, defer_endtime,
1495 smbd_smb2_request_pending_timer,
1496 req);
1497 if (req->async_te == NULL) {
1498 return NT_STATUS_NO_MEMORY;
1501 return NT_STATUS_OK;
1504 static DATA_BLOB smbd_smb2_signing_key(struct smbXsrv_session *session,
1505 struct smbXsrv_connection *xconn)
1507 struct smbXsrv_channel_global0 *c = NULL;
1508 NTSTATUS status;
1509 DATA_BLOB key = data_blob_null;
1511 status = smbXsrv_session_find_channel(session, xconn, &c);
1512 if (NT_STATUS_IS_OK(status)) {
1513 key = c->signing_key;
1516 if (key.length == 0) {
1517 key = session->global->signing_key;
1520 return key;
1523 static NTSTATUS smb2_get_new_nonce(struct smbXsrv_session *session,
1524 uint64_t *new_nonce_high,
1525 uint64_t *new_nonce_low)
1527 uint64_t nonce_high;
1528 uint64_t nonce_low;
1530 session->nonce_low += 1;
1531 if (session->nonce_low == 0) {
1532 session->nonce_low += 1;
1533 session->nonce_high += 1;
1537 * CCM and GCM algorithms must never have their
1538 * nonce wrap, or the security of the whole
1539 * communication and the keys is destroyed.
1540 * We must drop the connection once we have
1541 * transfered too much data.
1543 * NOTE: We assume nonces greater than 8 bytes.
1545 if (session->nonce_high >= session->nonce_high_max) {
1546 return NT_STATUS_ENCRYPTION_FAILED;
1549 nonce_high = session->nonce_high_random;
1550 nonce_high += session->nonce_high;
1551 nonce_low = session->nonce_low;
1553 *new_nonce_high = nonce_high;
1554 *new_nonce_low = nonce_low;
1555 return NT_STATUS_OK;
1558 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1559 struct tevent_timer *te,
1560 struct timeval current_time,
1561 void *private_data)
1563 struct smbd_smb2_request *req =
1564 talloc_get_type_abort(private_data,
1565 struct smbd_smb2_request);
1566 struct smbXsrv_connection *xconn = req->xconn;
1567 struct smbd_smb2_request_pending_state *state = NULL;
1568 uint8_t *outhdr = NULL;
1569 const uint8_t *inhdr = NULL;
1570 uint8_t *tf = NULL;
1571 size_t tf_len = 0;
1572 uint8_t *hdr = NULL;
1573 uint8_t *body = NULL;
1574 uint8_t *dyn = NULL;
1575 uint32_t flags = 0;
1576 uint64_t session_id = 0;
1577 uint64_t message_id = 0;
1578 uint64_t nonce_high = 0;
1579 uint64_t nonce_low = 0;
1580 uint64_t async_id = 0;
1581 NTSTATUS status;
1582 bool ok;
1584 TALLOC_FREE(req->async_te);
1586 /* Ensure our final reply matches the interim one. */
1587 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1588 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1589 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1590 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1591 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1593 async_id = message_id; /* keep it simple for now... */
1595 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1596 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1598 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1599 "going async\n",
1600 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1601 (unsigned long long)async_id ));
1604 * What we send is identical to a smbd_smb2_request_error
1605 * packet with an error status of STATUS_PENDING. Make use
1606 * of this fact sometime when refactoring. JRA.
1609 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
1610 if (state == NULL) {
1611 smbd_server_connection_terminate(xconn,
1612 nt_errstr(NT_STATUS_NO_MEMORY));
1613 return;
1616 tf = state->buf + NBT_HDR_SIZE;
1617 tf_len = SMB2_TF_HDR_SIZE;
1619 hdr = tf + SMB2_TF_HDR_SIZE;
1620 body = hdr + SMB2_HDR_BODY;
1621 dyn = body + 8;
1623 if (req->do_encryption) {
1624 status = smb2_get_new_nonce(req->session,
1625 &nonce_high,
1626 &nonce_low);
1627 if (!NT_STATUS_IS_OK(status)) {
1628 smbd_server_connection_terminate(xconn,
1629 nt_errstr(status));
1630 return;
1634 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1635 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1636 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1637 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1639 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1640 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1641 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1642 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1643 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1645 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1646 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1647 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1648 SBVAL(hdr, SMB2_HDR_PID, async_id);
1649 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1650 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1651 memcpy(hdr+SMB2_HDR_SIGNATURE,
1652 outhdr+SMB2_HDR_SIGNATURE, 16);
1654 SSVAL(body, 0x00, 0x08 + 1);
1656 SCVAL(body, 0x02, 0);
1657 SCVAL(body, 0x03, 0);
1658 SIVAL(body, 0x04, 0);
1659 /* Match W2K8R2... */
1660 SCVAL(dyn, 0x00, 0x21);
1662 state->vector[0].iov_base = (void *)state->buf;
1663 state->vector[0].iov_len = NBT_HDR_SIZE;
1665 if (req->do_encryption) {
1666 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1667 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1668 } else {
1669 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1670 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1673 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1674 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1676 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1677 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1679 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1680 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1682 ok = smb2_setup_nbt_length(state->vector,
1683 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1684 if (!ok) {
1685 smbd_server_connection_terminate(
1686 xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
1687 return;
1690 /* Ensure we correctly go through crediting. Grant
1691 the credits now, and zero credits on the final
1692 response. */
1693 smb2_set_operation_credit(req->xconn,
1694 SMBD_SMB2_IN_HDR_IOV(req),
1695 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1697 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1699 if (DEBUGLVL(10)) {
1700 int i;
1702 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1703 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1704 (unsigned int)i,
1705 (unsigned int)ARRAY_SIZE(state->vector),
1706 (unsigned int)state->vector[i].iov_len);
1710 if (req->do_encryption) {
1711 struct smbXsrv_session *x = req->session;
1712 DATA_BLOB encryption_key = x->global->encryption_key;
1714 status = smb2_signing_encrypt_pdu(encryption_key,
1715 xconn->smb2.server.cipher,
1716 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1717 SMBD_SMB2_NUM_IOV_PER_REQ);
1718 if (!NT_STATUS_IS_OK(status)) {
1719 smbd_server_connection_terminate(xconn,
1720 nt_errstr(status));
1721 return;
1723 } else if (req->do_signing) {
1724 struct smbXsrv_session *x = req->session;
1725 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
1727 status = smb2_signing_sign_pdu(signing_key,
1728 xconn->protocol,
1729 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1730 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1731 if (!NT_STATUS_IS_OK(status)) {
1732 smbd_server_connection_terminate(xconn,
1733 nt_errstr(status));
1734 return;
1738 state->queue_entry.mem_ctx = state;
1739 state->queue_entry.vector = state->vector;
1740 state->queue_entry.count = ARRAY_SIZE(state->vector);
1741 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
1742 xconn->smb2.send_queue_len++;
1744 status = smbd_smb2_flush_send_queue(xconn);
1745 if (!NT_STATUS_IS_OK(status)) {
1746 smbd_server_connection_terminate(xconn,
1747 nt_errstr(status));
1748 return;
1752 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1754 struct smbXsrv_connection *xconn = req->xconn;
1755 struct smbd_smb2_request *cur;
1756 const uint8_t *inhdr;
1757 uint32_t flags;
1758 uint64_t search_message_id;
1759 uint64_t search_async_id;
1760 uint64_t found_id;
1762 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1764 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1765 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1766 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1769 * We don't need the request anymore cancel requests never
1770 * have a response.
1772 * We defer the TALLOC_FREE(req) to the caller.
1774 DLIST_REMOVE(xconn->smb2.requests, req);
1776 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1777 const uint8_t *outhdr;
1778 uint64_t message_id;
1779 uint64_t async_id;
1781 if (cur->compound_related) {
1783 * Never cancel anything in a compound request.
1784 * Way too hard to deal with the result.
1786 continue;
1789 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1791 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1792 async_id = BVAL(outhdr, SMB2_HDR_PID);
1794 if (flags & SMB2_HDR_FLAG_ASYNC) {
1795 if (search_async_id == async_id) {
1796 found_id = async_id;
1797 break;
1799 } else {
1800 if (search_message_id == message_id) {
1801 found_id = message_id;
1802 break;
1807 if (cur && cur->subreq) {
1808 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1809 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1810 "cancel opcode[%s] mid %llu\n",
1811 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1812 (unsigned long long)found_id ));
1813 tevent_req_cancel(cur->subreq);
1816 return NT_STATUS_OK;
1819 /*************************************************************
1820 Ensure an incoming tid is a valid one for us to access.
1821 Change to the associated uid credentials and chdir to the
1822 valid tid directory.
1823 *************************************************************/
1825 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1827 const uint8_t *inhdr;
1828 uint32_t in_flags;
1829 uint32_t in_tid;
1830 struct smbXsrv_tcon *tcon;
1831 NTSTATUS status;
1832 NTTIME now = timeval_to_nttime(&req->request_time);
1834 req->tcon = NULL;
1836 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1838 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1839 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1841 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1842 in_tid = req->last_tid;
1845 req->last_tid = 0;
1847 status = smb2srv_tcon_lookup(req->session,
1848 in_tid, now, &tcon);
1849 if (!NT_STATUS_IS_OK(status)) {
1850 return status;
1853 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1854 return NT_STATUS_ACCESS_DENIED;
1857 req->tcon = tcon;
1858 req->last_tid = in_tid;
1860 return NT_STATUS_OK;
1863 /*************************************************************
1864 Ensure an incoming session_id is a valid one for us to access.
1865 *************************************************************/
1867 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1869 const uint8_t *inhdr;
1870 uint32_t in_flags;
1871 uint16_t in_opcode;
1872 uint64_t in_session_id;
1873 struct smbXsrv_session *session = NULL;
1874 struct auth_session_info *session_info;
1875 NTSTATUS status;
1876 NTTIME now = timeval_to_nttime(&req->request_time);
1878 req->session = NULL;
1879 req->tcon = NULL;
1881 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1883 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1884 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1885 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1887 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1888 in_session_id = req->last_session_id;
1891 req->last_session_id = 0;
1893 /* look an existing session up */
1894 switch (in_opcode) {
1895 case SMB2_OP_SESSSETUP:
1897 * For a session bind request, we don't have the
1898 * channel set up at this point yet, so we defer
1899 * the verification that the connection belongs
1900 * to the session to the session setup code, which
1901 * can look at the session binding flags.
1903 status = smb2srv_session_lookup_client(req->xconn->client,
1904 in_session_id, now,
1905 &session);
1906 break;
1907 default:
1908 status = smb2srv_session_lookup_conn(req->xconn,
1909 in_session_id, now,
1910 &session);
1911 break;
1913 if (session) {
1914 req->session = session;
1915 req->last_session_id = in_session_id;
1917 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1918 switch (in_opcode) {
1919 case SMB2_OP_SESSSETUP:
1920 status = NT_STATUS_OK;
1921 break;
1922 case SMB2_OP_LOGOFF:
1923 case SMB2_OP_CLOSE:
1924 case SMB2_OP_LOCK:
1925 case SMB2_OP_CANCEL:
1926 case SMB2_OP_KEEPALIVE:
1928 * [MS-SMB2] 3.3.5.2.9 Verifying the Session
1929 * specifies that LOGOFF, CLOSE and (UN)LOCK
1930 * should always be processed even on expired sessions.
1932 * Also see the logic in
1933 * smbd_smb2_request_process_lock().
1935 * The smb2.session.expire2 test shows that
1936 * CANCEL and KEEPALIVE/ECHO should also
1937 * be processed.
1939 status = NT_STATUS_OK;
1940 break;
1941 default:
1942 break;
1945 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1946 switch (in_opcode) {
1947 case SMB2_OP_TCON:
1948 case SMB2_OP_CREATE:
1949 case SMB2_OP_GETINFO:
1950 case SMB2_OP_SETINFO:
1951 return NT_STATUS_INVALID_HANDLE;
1952 default:
1954 * Notice the check for
1955 * (session_info == NULL)
1956 * below.
1958 status = NT_STATUS_OK;
1959 break;
1962 if (!NT_STATUS_IS_OK(status)) {
1963 return status;
1966 session_info = session->global->auth_session_info;
1967 if (session_info == NULL) {
1968 return NT_STATUS_INVALID_HANDLE;
1971 return NT_STATUS_OK;
1974 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1975 uint32_t data_length)
1977 struct smbXsrv_connection *xconn = req->xconn;
1978 uint16_t needed_charge;
1979 uint16_t credit_charge = 1;
1980 const uint8_t *inhdr;
1982 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1984 if (xconn->smb2.credits.multicredit) {
1985 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1986 credit_charge = MAX(credit_charge, 1);
1989 needed_charge = (data_length - 1)/ 65536 + 1;
1991 DBGC_DEBUG(DBGC_SMB2_CREDITS,
1992 "mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1993 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1994 credit_charge, needed_charge);
1996 if (needed_charge > credit_charge) {
1997 DBGC_WARNING(DBGC_SMB2_CREDITS,
1998 "CreditCharge too low, given %d, needed %d\n",
1999 credit_charge, needed_charge);
2000 return NT_STATUS_INVALID_PARAMETER;
2003 return NT_STATUS_OK;
2006 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
2007 size_t expected_body_size)
2009 struct iovec *inhdr_v;
2010 const uint8_t *inhdr;
2011 uint16_t opcode;
2012 const uint8_t *inbody;
2013 size_t body_size;
2014 size_t min_dyn_size = expected_body_size & 0x00000001;
2015 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
2018 * The following should be checked already.
2020 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
2021 return NT_STATUS_INTERNAL_ERROR;
2023 if (req->current_idx > max_idx) {
2024 return NT_STATUS_INTERNAL_ERROR;
2027 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
2028 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
2029 return NT_STATUS_INTERNAL_ERROR;
2031 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
2032 return NT_STATUS_INTERNAL_ERROR;
2035 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2036 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2038 switch (opcode) {
2039 case SMB2_OP_IOCTL:
2040 case SMB2_OP_GETINFO:
2041 min_dyn_size = 0;
2042 break;
2043 case SMB2_OP_WRITE:
2044 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
2045 if (req->smb1req->unread_bytes < min_dyn_size) {
2046 return NT_STATUS_INVALID_PARAMETER;
2049 min_dyn_size = 0;
2051 break;
2055 * Now check the expected body size,
2056 * where the last byte might be in the
2057 * dynamic section..
2059 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
2060 return NT_STATUS_INVALID_PARAMETER;
2062 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
2063 return NT_STATUS_INVALID_PARAMETER;
2066 inbody = SMBD_SMB2_IN_BODY_PTR(req);
2068 body_size = SVAL(inbody, 0x00);
2069 if (body_size != expected_body_size) {
2070 return NT_STATUS_INVALID_PARAMETER;
2073 return NT_STATUS_OK;
2076 bool smbXsrv_is_encrypted(uint8_t encryption_flags)
2078 return (!(encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)
2080 (encryption_flags & (SMBXSRV_PROCESSED_ENCRYPTED_PACKET |
2081 SMBXSRV_ENCRYPTION_DESIRED |
2082 SMBXSRV_ENCRYPTION_REQUIRED)));
2085 bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags)
2087 return ((encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET) &&
2088 (encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET));
2091 /* Set a flag if not already set, return true if set */
2092 bool smbXsrv_set_crypto_flag(uint8_t *flags, uint8_t flag)
2094 if ((flag == 0) || (*flags & flag)) {
2095 return false;
2098 *flags |= flag;
2099 return true;
2103 * Update encryption state tracking flags, this can be used to
2104 * determine whether whether the session or tcon is "encrypted".
2106 static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
2107 uint16_t opcode,
2108 bool *update_session_globalp,
2109 bool *update_tcon_globalp)
2111 /* Default: assume unecrypted and unsigned */
2112 struct smbXsrv_session *session = req->session;
2113 struct smbXsrv_tcon *tcon = req->tcon;
2114 uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
2115 uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2116 bool update_session = false;
2117 bool update_tcon = false;
2119 if (req->was_encrypted && req->do_encryption) {
2120 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
2121 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2122 } else {
2123 /* Unencrypted packet, can be signed */
2124 if (req->do_signing) {
2125 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2126 } else if (opcode == SMB2_OP_CANCEL) {
2127 /* Cancel requests are allowed to skip signing */
2128 sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2132 update_session |= smbXsrv_set_crypto_flag(
2133 &session->global->encryption_flags, encrypt_flag);
2134 update_session |= smbXsrv_set_crypto_flag(
2135 &session->global->signing_flags, sign_flag);
2137 if (tcon) {
2138 update_tcon |= smbXsrv_set_crypto_flag(
2139 &tcon->global->encryption_flags, encrypt_flag);
2140 update_tcon |= smbXsrv_set_crypto_flag(
2141 &tcon->global->signing_flags, sign_flag);
2144 *update_session_globalp = update_session;
2145 *update_tcon_globalp = update_tcon;
2146 return;
2149 bool smbXsrv_is_signed(uint8_t signing_flags)
2152 * Signing is always enabled, so unless we got an unsigned
2153 * packet and at least one signed packet that was not
2154 * encrypted, the session or tcon is "signed".
2156 return (!(signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2157 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2160 bool smbXsrv_is_partially_signed(uint8_t signing_flags)
2162 return ((signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2163 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2166 static NTSTATUS smbd_smb2_request_dispatch_update_counts(
2167 struct smbd_smb2_request *req,
2168 bool modify_call)
2170 struct smbXsrv_connection *xconn = req->xconn;
2171 const uint8_t *inhdr;
2172 uint16_t channel_sequence;
2173 uint8_t generation_wrap = 0;
2174 uint32_t flags;
2175 int cmp;
2176 struct smbXsrv_open *op;
2177 bool update_open = false;
2178 NTSTATUS status = NT_STATUS_OK;
2180 SMB_ASSERT(!req->request_counters_updated);
2182 if (xconn->protocol < PROTOCOL_SMB2_22) {
2183 return NT_STATUS_OK;
2186 if (req->compat_chain_fsp == NULL) {
2187 return NT_STATUS_OK;
2190 op = req->compat_chain_fsp->op;
2191 if (op == NULL) {
2192 return NT_STATUS_OK;
2195 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2196 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2197 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2199 cmp = channel_sequence - op->global->channel_sequence;
2200 if (cmp < 0) {
2202 * csn wrap. We need to watch out for long-running
2203 * requests that are still sitting on a previously
2204 * used csn. SMB2_OP_NOTIFY can take VERY long.
2206 generation_wrap += 1;
2209 if (abs(cmp) > INT16_MAX) {
2211 * [MS-SMB2] 3.3.5.2.10 - Verifying the Channel Sequence Number:
2213 * If the channel sequence number of the request and the one
2214 * known to the server are not equal, the channel sequence
2215 * number and outstanding request counts are only updated
2216 * "... if the unsigned difference using 16-bit arithmetic
2217 * between ChannelSequence and Open.ChannelSequence is less than
2218 * or equal to 0x7FFF ...".
2219 * Otherwise, an error is returned for the modifying
2220 * calls write, set_info, and ioctl.
2222 * There are currently two issues with the description:
2224 * * For the other calls, the document seems to imply
2225 * that processing continues without adapting the
2226 * counters (if the sequence numbers are not equal).
2228 * TODO: This needs clarification!
2230 * * Also, the behaviour if the difference is larger
2231 * than 0x7FFF is not clear. The document seems to
2232 * imply that if such a difference is reached,
2233 * the server starts to ignore the counters or
2234 * in the case of the modifying calls, return errors.
2236 * TODO: This needs clarification!
2238 * At this point Samba tries to be a little more
2239 * clever than the description in the MS-SMB2 document
2240 * by heuristically detecting and properly treating
2241 * a 16 bit overflow of the client-submitted sequence
2242 * number:
2244 * If the stored channel sequence number is more than
2245 * 0x7FFF larger than the one from the request, then
2246 * the client-provided sequence number has likely
2247 * overflown. We treat this case as valid instead
2248 * of as failure.
2250 * The MS-SMB2 behaviour would be setting cmp = -1.
2252 cmp *= -1;
2255 if (flags & SMB2_HDR_FLAG_REPLAY_OPERATION) {
2256 if (cmp == 0 && op->pre_request_count == 0) {
2257 op->request_count += 1;
2258 req->request_counters_updated = true;
2259 } else if (cmp > 0 && op->pre_request_count == 0) {
2260 op->pre_request_count += op->request_count;
2261 op->request_count = 1;
2262 op->global->channel_sequence = channel_sequence;
2263 op->global->channel_generation += generation_wrap;
2264 update_open = true;
2265 req->request_counters_updated = true;
2266 } else if (modify_call) {
2267 return NT_STATUS_FILE_NOT_AVAILABLE;
2269 } else {
2270 if (cmp == 0) {
2271 op->request_count += 1;
2272 req->request_counters_updated = true;
2273 } else if (cmp > 0) {
2274 op->pre_request_count += op->request_count;
2275 op->request_count = 1;
2276 op->global->channel_sequence = channel_sequence;
2277 op->global->channel_generation += generation_wrap;
2278 update_open = true;
2279 req->request_counters_updated = true;
2280 } else if (modify_call) {
2281 return NT_STATUS_FILE_NOT_AVAILABLE;
2284 req->channel_generation = op->global->channel_generation;
2286 if (update_open) {
2287 status = smbXsrv_open_update(op);
2290 return status;
2293 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
2295 struct smbXsrv_connection *xconn = req->xconn;
2296 const struct smbd_smb2_dispatch_table *call = NULL;
2297 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
2298 const uint8_t *inhdr;
2299 uint16_t opcode;
2300 uint32_t flags;
2301 uint64_t mid;
2302 NTSTATUS status;
2303 NTSTATUS session_status;
2304 uint32_t allowed_flags;
2305 NTSTATUS return_value;
2306 struct smbXsrv_session *x = NULL;
2307 bool signing_required = false;
2308 bool encryption_desired = false;
2309 bool encryption_required = false;
2311 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2313 DO_PROFILE_INC(request);
2315 SMB_ASSERT(!req->request_counters_updated);
2317 /* TODO: verify more things */
2319 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2320 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2321 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2322 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
2323 smb2_opcode_name(opcode),
2324 (unsigned long long)mid));
2326 if (xconn->protocol >= PROTOCOL_SMB2_02) {
2328 * once the protocol is negotiated
2329 * SMB2_OP_NEGPROT is not allowed anymore
2331 if (opcode == SMB2_OP_NEGPROT) {
2332 /* drop the connection */
2333 return NT_STATUS_INVALID_PARAMETER;
2335 } else {
2337 * if the protocol is not negotiated yet
2338 * only SMB2_OP_NEGPROT is allowed.
2340 if (opcode != SMB2_OP_NEGPROT) {
2341 /* drop the connection */
2342 return NT_STATUS_INVALID_PARAMETER;
2347 * Check if the client provided a valid session id.
2349 * As some command don't require a valid session id
2350 * we defer the check of the session_status
2352 session_status = smbd_smb2_request_check_session(req);
2353 x = req->session;
2354 if (x != NULL) {
2355 signing_required = x->global->signing_flags & SMBXSRV_SIGNING_REQUIRED;
2356 encryption_desired = x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
2357 encryption_required = x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
2360 req->async_internal = false;
2361 req->do_signing = false;
2362 req->do_encryption = false;
2363 req->was_encrypted = false;
2364 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
2365 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
2366 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
2368 if (x != NULL && x->global->session_wire_id != tf_session_id) {
2369 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2370 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
2371 (unsigned long long)x->global->session_wire_id,
2372 (unsigned long long)tf_session_id));
2374 * TODO: windows allows this...
2375 * should we drop the connection?
2377 * For now we just return ACCESS_DENIED
2378 * (Windows clients never trigger this)
2379 * and wait for an update of [MS-SMB2].
2381 return smbd_smb2_request_error(req,
2382 NT_STATUS_ACCESS_DENIED);
2385 req->was_encrypted = true;
2388 if (encryption_required && !req->was_encrypted) {
2389 return smbd_smb2_request_error(req,
2390 NT_STATUS_ACCESS_DENIED);
2393 call = smbd_smb2_call(opcode);
2394 if (call == NULL) {
2395 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2398 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2399 SMB2_HDR_FLAG_SIGNED |
2400 SMB2_HDR_FLAG_DFS;
2401 if (xconn->protocol >= PROTOCOL_SMB3_11) {
2402 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2404 if (opcode == SMB2_OP_NEGPROT) {
2405 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11) {
2406 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2409 if (opcode == SMB2_OP_CANCEL) {
2410 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2412 if (xconn->protocol >= PROTOCOL_SMB2_22) {
2413 allowed_flags |= SMB2_HDR_FLAG_REPLAY_OPERATION;
2415 if ((flags & ~allowed_flags) != 0) {
2416 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2419 if (flags & SMB2_HDR_FLAG_CHAINED) {
2421 * This check is mostly for giving the correct error code
2422 * for compounded requests.
2424 if (!NT_STATUS_IS_OK(session_status)) {
2425 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2427 } else {
2428 req->compat_chain_fsp = NULL;
2431 if (req->was_encrypted) {
2432 signing_required = false;
2433 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2434 DATA_BLOB signing_key = data_blob_null;
2436 if (x == NULL) {
2438 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2439 * If the SMB2 header of the SMB2 NEGOTIATE
2440 * request has the SMB2_FLAGS_SIGNED bit set in the
2441 * Flags field, the server MUST fail the request
2442 * with STATUS_INVALID_PARAMETER.
2444 * Microsoft test tool checks this.
2447 if ((opcode == SMB2_OP_NEGPROT) &&
2448 (flags & SMB2_HDR_FLAG_SIGNED)) {
2449 status = NT_STATUS_INVALID_PARAMETER;
2450 } else {
2451 status = NT_STATUS_USER_SESSION_DELETED;
2453 return smbd_smb2_request_error(req, status);
2456 signing_key = smbd_smb2_signing_key(x, xconn);
2459 * If we have a signing key, we should
2460 * sign the response
2462 if (signing_key.length > 0) {
2463 req->do_signing = true;
2466 status = smb2_signing_check_pdu(signing_key,
2467 xconn->protocol,
2468 SMBD_SMB2_IN_HDR_IOV(req),
2469 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2470 if (!NT_STATUS_IS_OK(status)) {
2471 return smbd_smb2_request_error(req, status);
2475 * Now that we know the request was correctly signed
2476 * we have to sign the response too.
2478 req->do_signing = true;
2480 if (!NT_STATUS_IS_OK(session_status)) {
2481 return smbd_smb2_request_error(req, session_status);
2483 } else if (opcode == SMB2_OP_CANCEL) {
2484 /* Cancel requests are allowed to skip the signing */
2485 } else if (signing_required) {
2487 * If signing is required we try to sign
2488 * a possible error response
2490 req->do_signing = true;
2491 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2494 if (flags & SMB2_HDR_FLAG_CHAINED) {
2495 req->compound_related = true;
2498 if (call->need_session) {
2499 if (!NT_STATUS_IS_OK(session_status)) {
2500 return smbd_smb2_request_error(req, session_status);
2504 if (call->need_tcon) {
2505 SMB_ASSERT(call->need_session);
2508 * This call needs to be run as user.
2510 * smbd_smb2_request_check_tcon()
2511 * calls change_to_user() on success.
2512 * Which implies set_current_user_info()
2513 * and chdir_current_service().
2515 status = smbd_smb2_request_check_tcon(req);
2516 if (!NT_STATUS_IS_OK(status)) {
2517 return smbd_smb2_request_error(req, status);
2519 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
2520 encryption_desired = true;
2522 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
2523 encryption_required = true;
2525 if (encryption_required && !req->was_encrypted) {
2526 return smbd_smb2_request_error(req,
2527 NT_STATUS_ACCESS_DENIED);
2529 } else if (call->need_session) {
2530 struct auth_session_info *session_info = NULL;
2533 * Unless we also have need_tcon (see above),
2534 * we still need to call set_current_user_info().
2537 session_info = req->session->global->auth_session_info;
2538 if (session_info == NULL) {
2539 return NT_STATUS_INVALID_HANDLE;
2542 set_current_user_info(session_info->unix_info->sanitized_username,
2543 session_info->unix_info->unix_name,
2544 session_info->info->domain_name);
2547 if (req->was_encrypted || encryption_desired) {
2548 req->do_encryption = true;
2551 if (req->session) {
2552 bool update_session_global = false;
2553 bool update_tcon_global = false;
2555 smb2srv_update_crypto_flags(req, opcode,
2556 &update_session_global,
2557 &update_tcon_global);
2559 if (update_session_global) {
2560 status = smbXsrv_session_update(x);
2561 if (!NT_STATUS_IS_OK(status)) {
2562 return smbd_smb2_request_error(req, status);
2565 if (update_tcon_global) {
2566 status = smbXsrv_tcon_update(req->tcon);
2567 if (!NT_STATUS_IS_OK(status)) {
2568 return smbd_smb2_request_error(req, status);
2573 if (call->fileid_ofs != 0) {
2574 size_t needed = call->fileid_ofs + 16;
2575 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2576 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2577 uint64_t file_id_persistent;
2578 uint64_t file_id_volatile;
2579 struct files_struct *fsp;
2581 SMB_ASSERT(call->need_tcon);
2583 if (needed > body_size) {
2584 return smbd_smb2_request_error(req,
2585 NT_STATUS_INVALID_PARAMETER);
2588 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2589 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2591 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2592 if (fsp == NULL) {
2593 if (!call->allow_invalid_fileid) {
2594 return smbd_smb2_request_error(req,
2595 NT_STATUS_FILE_CLOSED);
2598 if (file_id_persistent != UINT64_MAX) {
2599 return smbd_smb2_request_error(req,
2600 NT_STATUS_FILE_CLOSED);
2602 if (file_id_volatile != UINT64_MAX) {
2603 return smbd_smb2_request_error(req,
2604 NT_STATUS_FILE_CLOSED);
2609 status = smbd_smb2_request_dispatch_update_counts(req, call->modify);
2610 if (!NT_STATUS_IS_OK(status)) {
2611 return smbd_smb2_request_error(req, status);
2614 if (call->as_root) {
2615 SMB_ASSERT(call->fileid_ofs == 0);
2616 /* This call needs to be run as root */
2617 change_to_root_user();
2618 req->ev_ctx = req->sconn->root_ev_ctx;
2619 } else {
2620 SMB_ASSERT(call->need_tcon);
2621 req->ev_ctx = req->tcon->compat->user_ev_ctx;
2624 #define _INBYTES(_r) \
2625 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
2627 switch (opcode) {
2628 case SMB2_OP_NEGPROT:
2629 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
2630 req->profile, _INBYTES(req));
2631 return_value = smbd_smb2_request_process_negprot(req);
2632 break;
2634 case SMB2_OP_SESSSETUP:
2635 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
2636 req->profile, _INBYTES(req));
2637 return_value = smbd_smb2_request_process_sesssetup(req);
2638 break;
2640 case SMB2_OP_LOGOFF:
2641 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
2642 req->profile, _INBYTES(req));
2643 return_value = smbd_smb2_request_process_logoff(req);
2644 break;
2646 case SMB2_OP_TCON:
2647 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
2648 req->profile, _INBYTES(req));
2649 return_value = smbd_smb2_request_process_tcon(req);
2650 break;
2652 case SMB2_OP_TDIS:
2653 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
2654 req->profile, _INBYTES(req));
2655 return_value = smbd_smb2_request_process_tdis(req);
2656 break;
2658 case SMB2_OP_CREATE:
2659 if (req->subreq == NULL) {
2660 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
2661 req->profile, _INBYTES(req));
2662 } else {
2663 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
2665 return_value = smbd_smb2_request_process_create(req);
2666 break;
2668 case SMB2_OP_CLOSE:
2669 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
2670 req->profile, _INBYTES(req));
2671 return_value = smbd_smb2_request_process_close(req);
2672 break;
2674 case SMB2_OP_FLUSH:
2675 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
2676 req->profile, _INBYTES(req));
2677 return_value = smbd_smb2_request_process_flush(req);
2678 break;
2680 case SMB2_OP_READ:
2681 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
2682 req->profile, _INBYTES(req));
2683 return_value = smbd_smb2_request_process_read(req);
2684 break;
2686 case SMB2_OP_WRITE:
2687 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
2688 req->profile, _INBYTES(req));
2689 return_value = smbd_smb2_request_process_write(req);
2690 break;
2692 case SMB2_OP_LOCK:
2693 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
2694 req->profile, _INBYTES(req));
2695 return_value = smbd_smb2_request_process_lock(req);
2696 break;
2698 case SMB2_OP_IOCTL:
2699 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
2700 req->profile, _INBYTES(req));
2701 return_value = smbd_smb2_request_process_ioctl(req);
2702 break;
2704 case SMB2_OP_CANCEL:
2705 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
2706 req->profile, _INBYTES(req));
2707 return_value = smbd_smb2_request_process_cancel(req);
2708 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
2711 * We don't need the request anymore cancel requests never
2712 * have a response.
2714 * smbd_smb2_request_process_cancel() already called
2715 * DLIST_REMOVE(xconn->smb2.requests, req);
2717 TALLOC_FREE(req);
2719 break;
2721 case SMB2_OP_KEEPALIVE:
2722 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
2723 req->profile, _INBYTES(req));
2724 return_value = smbd_smb2_request_process_keepalive(req);
2725 break;
2727 case SMB2_OP_QUERY_DIRECTORY:
2728 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
2729 req->profile, _INBYTES(req));
2730 return_value = smbd_smb2_request_process_query_directory(req);
2731 break;
2733 case SMB2_OP_NOTIFY:
2734 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
2735 req->profile, _INBYTES(req));
2736 return_value = smbd_smb2_request_process_notify(req);
2737 break;
2739 case SMB2_OP_GETINFO:
2740 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
2741 req->profile, _INBYTES(req));
2742 return_value = smbd_smb2_request_process_getinfo(req);
2743 break;
2745 case SMB2_OP_SETINFO:
2746 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
2747 req->profile, _INBYTES(req));
2748 return_value = smbd_smb2_request_process_setinfo(req);
2749 break;
2751 case SMB2_OP_BREAK:
2752 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
2753 req->profile, _INBYTES(req));
2754 return_value = smbd_smb2_request_process_break(req);
2755 break;
2757 default:
2758 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2759 break;
2761 return return_value;
2764 static void smbd_smb2_request_reply_update_counts(struct smbd_smb2_request *req)
2766 struct smbXsrv_connection *xconn = req->xconn;
2767 const uint8_t *inhdr;
2768 uint16_t channel_sequence;
2769 struct smbXsrv_open *op;
2771 if (!req->request_counters_updated) {
2772 return;
2775 req->request_counters_updated = false;
2777 if (xconn->protocol < PROTOCOL_SMB2_22) {
2778 return;
2781 if (req->compat_chain_fsp == NULL) {
2782 return;
2785 op = req->compat_chain_fsp->op;
2786 if (op == NULL) {
2787 return;
2790 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2791 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2793 if ((op->global->channel_sequence == channel_sequence) &&
2794 (op->global->channel_generation == req->channel_generation)) {
2795 SMB_ASSERT(op->request_count > 0);
2796 op->request_count -= 1;
2797 } else {
2798 SMB_ASSERT(op->pre_request_count > 0);
2799 op->pre_request_count -= 1;
2803 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2805 struct smbXsrv_connection *xconn = req->xconn;
2806 int first_idx = 1;
2807 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2808 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2809 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2810 NTSTATUS status;
2811 bool ok;
2813 req->subreq = NULL;
2814 TALLOC_FREE(req->async_te);
2816 /* MS-SMB2: 3.3.4.1 Sending Any Outgoing Message */
2817 smbd_smb2_request_reply_update_counts(req);
2819 if (req->do_encryption &&
2820 (firsttf->iov_len == 0) &&
2821 (req->first_key.length == 0) &&
2822 (req->session != NULL) &&
2823 (req->session->global->encryption_key.length != 0))
2825 DATA_BLOB encryption_key = req->session->global->encryption_key;
2826 uint8_t *tf;
2827 uint64_t session_id = req->session->global->session_wire_id;
2828 uint64_t nonce_high;
2829 uint64_t nonce_low;
2831 status = smb2_get_new_nonce(req->session,
2832 &nonce_high,
2833 &nonce_low);
2834 if (!NT_STATUS_IS_OK(status)) {
2835 return status;
2839 * We need to place the SMB2_TRANSFORM header before the
2840 * first SMB2 header
2844 * we need to remember the encryption key
2845 * and defer the signing/encryption until
2846 * we are sure that we do not change
2847 * the header again.
2849 req->first_key = data_blob_dup_talloc(req, encryption_key);
2850 if (req->first_key.data == NULL) {
2851 return NT_STATUS_NO_MEMORY;
2854 tf = talloc_zero_array(req, uint8_t,
2855 SMB2_TF_HDR_SIZE);
2856 if (tf == NULL) {
2857 return NT_STATUS_NO_MEMORY;
2860 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2861 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2862 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2863 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2865 firsttf->iov_base = (void *)tf;
2866 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2869 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2870 (req->last_key.length > 0) &&
2871 (firsttf->iov_len == 0))
2873 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2874 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2877 * As we are sure the header of the last request in the
2878 * compound chain will not change, we can to sign here
2879 * with the last signing key we remembered.
2881 status = smb2_signing_sign_pdu(req->last_key,
2882 xconn->protocol,
2883 lasthdr,
2884 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2885 if (!NT_STATUS_IS_OK(status)) {
2886 return status;
2889 if (req->last_key.length > 0) {
2890 data_blob_clear_free(&req->last_key);
2893 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
2894 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
2896 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2898 if (req->current_idx < req->out.vector_count) {
2900 * We must process the remaining compound
2901 * SMB2 requests before any new incoming SMB2
2902 * requests. This is because incoming SMB2
2903 * requests may include a cancel for a
2904 * compound request we haven't processed
2905 * yet.
2907 struct tevent_immediate *im = tevent_create_immediate(req);
2908 if (!im) {
2909 return NT_STATUS_NO_MEMORY;
2912 if (req->do_signing && firsttf->iov_len == 0) {
2913 struct smbXsrv_session *x = req->session;
2914 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2917 * we need to remember the signing key
2918 * and defer the signing until
2919 * we are sure that we do not change
2920 * the header again.
2922 req->last_key = data_blob_dup_talloc(req, signing_key);
2923 if (req->last_key.data == NULL) {
2924 return NT_STATUS_NO_MEMORY;
2929 * smbd_smb2_request_dispatch() will redo the impersonation.
2930 * So we use req->xconn->client->raw_ev_ctx instead
2931 * of req->ev_ctx here.
2933 tevent_schedule_immediate(im,
2934 req->xconn->client->raw_ev_ctx,
2935 smbd_smb2_request_dispatch_immediate,
2936 req);
2937 return NT_STATUS_OK;
2940 if (req->compound_related) {
2941 req->compound_related = false;
2944 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2945 if (!ok) {
2946 return NT_STATUS_INVALID_PARAMETER_MIX;
2949 /* Set credit for these operations (zero credits if this
2950 is a final reply for an async operation). */
2951 smb2_calculate_credits(req, req);
2954 * now check if we need to sign the current response
2956 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2957 status = smb2_signing_encrypt_pdu(req->first_key,
2958 xconn->smb2.server.cipher,
2959 firsttf,
2960 req->out.vector_count - first_idx);
2961 if (!NT_STATUS_IS_OK(status)) {
2962 return status;
2964 } else if (req->do_signing) {
2965 struct smbXsrv_session *x = req->session;
2966 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2968 status = smb2_signing_sign_pdu(signing_key,
2969 xconn->protocol,
2970 outhdr,
2971 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2972 if (!NT_STATUS_IS_OK(status)) {
2973 return status;
2976 if (req->first_key.length > 0) {
2977 data_blob_clear_free(&req->first_key);
2980 if (req->preauth != NULL) {
2981 struct hc_sha512state sctx;
2982 int i;
2984 samba_SHA512_Init(&sctx);
2985 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2986 sizeof(req->preauth->sha512_value));
2987 for (i = 1; i < req->in.vector_count; i++) {
2988 samba_SHA512_Update(&sctx,
2989 req->in.vector[i].iov_base,
2990 req->in.vector[i].iov_len);
2992 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2994 samba_SHA512_Init(&sctx);
2995 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2996 sizeof(req->preauth->sha512_value));
2997 for (i = 1; i < req->out.vector_count; i++) {
2998 samba_SHA512_Update(&sctx,
2999 req->out.vector[i].iov_base,
3000 req->out.vector[i].iov_len);
3002 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
3004 req->preauth = NULL;
3007 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
3008 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
3009 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
3010 /* Dynamic part is NULL. Chop it off,
3011 We're going to send it via sendfile. */
3012 req->out.vector_count -= 1;
3016 * We're done with this request -
3017 * move it off the "being processed" queue.
3019 DLIST_REMOVE(xconn->smb2.requests, req);
3021 req->queue_entry.mem_ctx = req;
3022 req->queue_entry.vector = req->out.vector;
3023 req->queue_entry.count = req->out.vector_count;
3024 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry);
3025 xconn->smb2.send_queue_len++;
3027 status = smbd_smb2_flush_send_queue(xconn);
3028 if (!NT_STATUS_IS_OK(status)) {
3029 return status;
3032 return NT_STATUS_OK;
3035 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
3037 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
3038 struct tevent_immediate *im,
3039 void *private_data)
3041 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
3042 struct smbd_smb2_request);
3043 struct smbXsrv_connection *xconn = req->xconn;
3044 NTSTATUS status;
3046 TALLOC_FREE(im);
3048 if (DEBUGLEVEL >= 10) {
3049 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
3050 req->current_idx, req->in.vector_count));
3051 print_req_vectors(req);
3054 status = smbd_smb2_request_dispatch(req);
3055 if (!NT_STATUS_IS_OK(status)) {
3056 smbd_server_connection_terminate(xconn, nt_errstr(status));
3057 return;
3060 status = smbd_smb2_request_next_incoming(xconn);
3061 if (!NT_STATUS_IS_OK(status)) {
3062 smbd_server_connection_terminate(xconn, nt_errstr(status));
3063 return;
3067 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
3068 NTSTATUS status,
3069 DATA_BLOB body, DATA_BLOB *dyn,
3070 const char *location)
3072 uint8_t *outhdr;
3073 struct iovec *outbody_v;
3074 struct iovec *outdyn_v;
3075 uint32_t next_command_ofs;
3077 DEBUG(10,("smbd_smb2_request_done_ex: "
3078 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
3079 req->current_idx, nt_errstr(status), (unsigned int)body.length,
3080 dyn ? "yes": "no",
3081 (unsigned int)(dyn ? dyn->length : 0),
3082 location));
3084 if (body.length < 2) {
3085 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3088 if ((body.length % 2) != 0) {
3089 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3092 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3093 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
3094 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
3096 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
3097 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
3099 outbody_v->iov_base = (void *)body.data;
3100 outbody_v->iov_len = body.length;
3102 if (dyn) {
3103 outdyn_v->iov_base = (void *)dyn->data;
3104 outdyn_v->iov_len = dyn->length;
3105 } else {
3106 outdyn_v->iov_base = NULL;
3107 outdyn_v->iov_len = 0;
3111 * See if we need to recalculate the offset to the next response
3113 * Note that all responses may require padding (including the very last
3114 * one).
3116 if (req->out.vector_count >= (2 * SMBD_SMB2_NUM_IOV_PER_REQ)) {
3117 next_command_ofs = SMB2_HDR_BODY;
3118 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
3119 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
3122 if ((next_command_ofs % 8) != 0) {
3123 size_t pad_size = 8 - (next_command_ofs % 8);
3124 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
3126 * if the dyn buffer is empty
3127 * we can use it to add padding
3129 uint8_t *pad;
3131 pad = talloc_zero_array(req,
3132 uint8_t, pad_size);
3133 if (pad == NULL) {
3134 return smbd_smb2_request_error(req,
3135 NT_STATUS_NO_MEMORY);
3138 outdyn_v->iov_base = (void *)pad;
3139 outdyn_v->iov_len = pad_size;
3140 } else {
3142 * For now we copy the dynamic buffer
3143 * and add the padding to the new buffer
3145 size_t old_size;
3146 uint8_t *old_dyn;
3147 size_t new_size;
3148 uint8_t *new_dyn;
3150 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
3151 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
3153 new_size = old_size + pad_size;
3154 new_dyn = talloc_zero_array(req,
3155 uint8_t, new_size);
3156 if (new_dyn == NULL) {
3157 return smbd_smb2_request_error(req,
3158 NT_STATUS_NO_MEMORY);
3161 memcpy(new_dyn, old_dyn, old_size);
3162 memset(new_dyn + old_size, 0, pad_size);
3164 outdyn_v->iov_base = (void *)new_dyn;
3165 outdyn_v->iov_len = new_size;
3167 next_command_ofs += pad_size;
3170 if ((req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) >= req->out.vector_count) {
3171 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
3172 } else {
3173 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
3175 return smbd_smb2_request_reply(req);
3178 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
3179 NTSTATUS status,
3180 DATA_BLOB *info,
3181 const char *location)
3183 struct smbXsrv_connection *xconn = req->xconn;
3184 DATA_BLOB body;
3185 DATA_BLOB _dyn;
3186 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3187 size_t unread_bytes = smbd_smb2_unread_bytes(req);
3189 DBG_NOTICE("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| "
3190 "at %s\n", req->current_idx, nt_errstr(status),
3191 info ? " +info" : "", location);
3193 if (unread_bytes) {
3194 /* Recvfile error. Drain incoming socket. */
3195 size_t ret;
3197 errno = 0;
3198 ret = drain_socket(xconn->transport.sock, unread_bytes);
3199 if (ret != unread_bytes) {
3200 NTSTATUS error;
3202 if (errno == 0) {
3203 error = NT_STATUS_IO_DEVICE_ERROR;
3204 } else {
3205 error = map_nt_error_from_unix_common(errno);
3208 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
3209 "ret[%u] errno[%d] => %s\n",
3210 (unsigned)unread_bytes,
3211 (unsigned)ret, errno, nt_errstr(error)));
3212 return error;
3216 body.data = outhdr + SMB2_HDR_BODY;
3217 body.length = 8;
3218 SSVAL(body.data, 0, 9);
3220 if (info) {
3221 SIVAL(body.data, 0x04, info->length);
3222 } else {
3223 /* Allocated size of req->out.vector[i].iov_base
3224 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
3225 * 1 byte without having to do an alloc.
3227 info = &_dyn;
3228 info->data = ((uint8_t *)outhdr) +
3229 OUTVEC_ALLOC_SIZE - 1;
3230 info->length = 1;
3231 SCVAL(info->data, 0, 0);
3235 * Note: Even if there is an error, continue to process the request.
3236 * per MS-SMB2.
3239 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
3243 struct smbd_smb2_send_break_state {
3244 struct smbd_smb2_send_queue queue_entry;
3245 uint8_t nbt_hdr[NBT_HDR_SIZE];
3246 uint8_t tf[SMB2_TF_HDR_SIZE];
3247 uint8_t hdr[SMB2_HDR_BODY];
3248 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
3249 uint8_t body[1];
3252 static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
3253 struct smbXsrv_session *session,
3254 struct smbXsrv_tcon *tcon,
3255 const uint8_t *body,
3256 size_t body_len)
3258 struct smbd_smb2_send_break_state *state;
3259 bool do_encryption = false;
3260 uint64_t session_wire_id = 0;
3261 uint64_t nonce_high = 0;
3262 uint64_t nonce_low = 0;
3263 NTSTATUS status;
3264 size_t statelen;
3265 bool ok;
3267 if (session != NULL) {
3268 session_wire_id = session->global->session_wire_id;
3269 do_encryption = session->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
3270 if (tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
3271 do_encryption = true;
3275 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
3276 body_len;
3278 state = talloc_zero_size(xconn, statelen);
3279 if (state == NULL) {
3280 return NT_STATUS_NO_MEMORY;
3282 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
3284 if (do_encryption) {
3285 status = smb2_get_new_nonce(session,
3286 &nonce_high,
3287 &nonce_low);
3288 if (!NT_STATUS_IS_OK(status)) {
3289 return status;
3293 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
3294 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
3295 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
3296 SBVAL(state->tf, SMB2_TF_SESSION_ID, session_wire_id);
3298 SIVAL(state->hdr, 0, SMB2_MAGIC);
3299 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
3300 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
3301 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
3302 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
3303 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
3304 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
3305 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
3306 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
3307 SIVAL(state->hdr, SMB2_HDR_PID, 0);
3308 SIVAL(state->hdr, SMB2_HDR_TID, 0);
3309 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
3310 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
3312 state->vector[0] = (struct iovec) {
3313 .iov_base = state->nbt_hdr,
3314 .iov_len = sizeof(state->nbt_hdr)
3317 if (do_encryption) {
3318 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3319 .iov_base = state->tf,
3320 .iov_len = sizeof(state->tf)
3322 } else {
3323 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3324 .iov_base = NULL,
3325 .iov_len = 0
3329 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
3330 .iov_base = state->hdr,
3331 .iov_len = sizeof(state->hdr)
3334 memcpy(state->body, body, body_len);
3336 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
3337 .iov_base = state->body,
3338 .iov_len = body_len /* no sizeof(state->body) .. :-) */
3342 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
3345 ok = smb2_setup_nbt_length(state->vector,
3346 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
3347 if (!ok) {
3348 return NT_STATUS_INVALID_PARAMETER_MIX;
3351 if (do_encryption) {
3352 DATA_BLOB encryption_key = session->global->encryption_key;
3354 status = smb2_signing_encrypt_pdu(encryption_key,
3355 xconn->smb2.server.cipher,
3356 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
3357 SMBD_SMB2_NUM_IOV_PER_REQ);
3358 if (!NT_STATUS_IS_OK(status)) {
3359 return status;
3363 state->queue_entry.mem_ctx = state;
3364 state->queue_entry.vector = state->vector;
3365 state->queue_entry.count = ARRAY_SIZE(state->vector);
3366 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
3367 xconn->smb2.send_queue_len++;
3369 status = smbd_smb2_flush_send_queue(xconn);
3370 if (!NT_STATUS_IS_OK(status)) {
3371 return status;
3374 return NT_STATUS_OK;
3377 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_connection *xconn,
3378 struct smbXsrv_session *session,
3379 struct smbXsrv_tcon *tcon,
3380 struct smbXsrv_open *op,
3381 uint8_t oplock_level)
3383 uint8_t body[0x18];
3385 SSVAL(body, 0x00, sizeof(body));
3386 SCVAL(body, 0x02, oplock_level);
3387 SCVAL(body, 0x03, 0); /* reserved */
3388 SIVAL(body, 0x04, 0); /* reserved */
3389 SBVAL(body, 0x08, op->global->open_persistent_id);
3390 SBVAL(body, 0x10, op->global->open_volatile_id);
3392 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3395 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_connection *xconn,
3396 uint16_t new_epoch,
3397 uint32_t lease_flags,
3398 struct smb2_lease_key *lease_key,
3399 uint32_t current_lease_state,
3400 uint32_t new_lease_state)
3402 uint8_t body[0x2c];
3404 SSVAL(body, 0x00, sizeof(body));
3405 SSVAL(body, 0x02, new_epoch);
3406 SIVAL(body, 0x04, lease_flags);
3407 SBVAL(body, 0x08, lease_key->data[0]);
3408 SBVAL(body, 0x10, lease_key->data[1]);
3409 SIVAL(body, 0x18, current_lease_state);
3410 SIVAL(body, 0x1c, new_lease_state);
3411 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
3412 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
3413 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
3415 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3418 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
3420 NTSTATUS status;
3421 uint32_t flags;
3422 uint64_t file_id_persistent;
3423 uint64_t file_id_volatile;
3424 struct smbXsrv_open *op = NULL;
3425 struct files_struct *fsp = NULL;
3426 const uint8_t *body = NULL;
3429 * This is only called with a pktbuf
3430 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
3431 * bytes
3434 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
3435 /* Transform header. Cannot recvfile. */
3436 return false;
3438 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
3439 /* Not SMB2. Normal error path will cope. */
3440 return false;
3442 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
3443 /* Not SMB2. Normal error path will cope. */
3444 return false;
3446 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
3447 /* Needs to be a WRITE. */
3448 return false;
3450 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
3451 /* Chained. Cannot recvfile. */
3452 return false;
3454 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
3455 if (flags & SMB2_HDR_FLAG_CHAINED) {
3456 /* Chained. Cannot recvfile. */
3457 return false;
3459 if (flags & SMB2_HDR_FLAG_SIGNED) {
3460 /* Signed. Cannot recvfile. */
3461 return false;
3464 body = &state->pktbuf[SMB2_HDR_BODY];
3466 file_id_persistent = BVAL(body, 0x10);
3467 file_id_volatile = BVAL(body, 0x18);
3469 status = smb2srv_open_lookup(state->req->xconn,
3470 file_id_persistent,
3471 file_id_volatile,
3472 0, /* now */
3473 &op);
3474 if (!NT_STATUS_IS_OK(status)) {
3475 return false;
3478 fsp = op->compat;
3479 if (fsp == NULL) {
3480 return false;
3482 if (fsp->conn == NULL) {
3483 return false;
3486 if (IS_IPC(fsp->conn)) {
3487 return false;
3489 if (IS_PRINT(fsp->conn)) {
3490 return false;
3493 DEBUG(10,("Doing recvfile write len = %u\n",
3494 (unsigned int)(state->pktfull - state->pktlen)));
3496 return true;
3499 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
3501 struct smbd_server_connection *sconn = xconn->client->sconn;
3502 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3503 size_t max_send_queue_len;
3504 size_t cur_send_queue_len;
3506 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3508 * we're not supposed to do any io
3510 return NT_STATUS_OK;
3513 if (state->req != NULL) {
3515 * if there is already a tstream_readv_pdu
3516 * pending, we are done.
3518 return NT_STATUS_OK;
3521 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
3522 cur_send_queue_len = xconn->smb2.send_queue_len;
3524 if (cur_send_queue_len > max_send_queue_len) {
3526 * if we have a lot of requests to send,
3527 * we wait until they are on the wire until we
3528 * ask for the next request.
3530 return NT_STATUS_OK;
3533 /* ask for the next request */
3534 ZERO_STRUCTP(state);
3535 state->req = smbd_smb2_request_allocate(xconn);
3536 if (state->req == NULL) {
3537 return NT_STATUS_NO_MEMORY;
3539 state->req->sconn = sconn;
3540 state->req->xconn = xconn;
3541 state->min_recv_size = lp_min_receive_file_size();
3543 TEVENT_FD_READABLE(xconn->transport.fde);
3545 return NT_STATUS_OK;
3548 void smbd_smb2_process_negprot(struct smbXsrv_connection *xconn,
3549 uint64_t expected_seq_low,
3550 const uint8_t *inpdu, size_t size)
3552 struct smbd_server_connection *sconn = xconn->client->sconn;
3553 NTSTATUS status;
3554 struct smbd_smb2_request *req = NULL;
3556 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3557 (unsigned int)size));
3559 status = smbd_initialize_smb2(xconn, expected_seq_low);
3560 if (!NT_STATUS_IS_OK(status)) {
3561 smbd_server_connection_terminate(xconn, nt_errstr(status));
3562 return;
3565 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
3566 if (!NT_STATUS_IS_OK(status)) {
3567 smbd_server_connection_terminate(xconn, nt_errstr(status));
3568 return;
3571 status = smbd_smb2_request_validate(req);
3572 if (!NT_STATUS_IS_OK(status)) {
3573 smbd_server_connection_terminate(xconn, nt_errstr(status));
3574 return;
3577 status = smbd_smb2_request_setup_out(req);
3578 if (!NT_STATUS_IS_OK(status)) {
3579 smbd_server_connection_terminate(xconn, nt_errstr(status));
3580 return;
3583 #ifdef WITH_PROFILE
3585 * this was already counted at the SMB1 layer =>
3586 * smbd_smb2_request_dispatch() should not count it twice.
3588 if (profile_p->values.request_stats.count > 0) {
3589 profile_p->values.request_stats.count--;
3591 #endif
3592 status = smbd_smb2_request_dispatch(req);
3593 if (!NT_STATUS_IS_OK(status)) {
3594 smbd_server_connection_terminate(xconn, nt_errstr(status));
3595 return;
3598 status = smbd_smb2_request_next_incoming(xconn);
3599 if (!NT_STATUS_IS_OK(status)) {
3600 smbd_server_connection_terminate(xconn, nt_errstr(status));
3601 return;
3604 sconn->num_requests++;
3607 static int socket_error_from_errno(int ret,
3608 int sys_errno,
3609 bool *retry)
3611 *retry = false;
3613 if (ret >= 0) {
3614 return 0;
3617 if (ret != -1) {
3618 return EIO;
3621 if (sys_errno == 0) {
3622 return EIO;
3625 if (sys_errno == EINTR) {
3626 *retry = true;
3627 return sys_errno;
3630 if (sys_errno == EINPROGRESS) {
3631 *retry = true;
3632 return sys_errno;
3635 if (sys_errno == EAGAIN) {
3636 *retry = true;
3637 return sys_errno;
3640 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3641 if (sys_errno == ENOMEM) {
3642 *retry = true;
3643 return sys_errno;
3646 #ifdef EWOULDBLOCK
3647 #if EWOULDBLOCK != EAGAIN
3648 if (sys_errno == EWOULDBLOCK) {
3649 *retry = true;
3650 return sys_errno;
3652 #endif
3653 #endif
3655 return sys_errno;
3658 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3660 int ret;
3661 int err;
3662 bool retry;
3663 NTSTATUS status;
3665 if (xconn->smb2.send_queue == NULL) {
3666 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3667 return NT_STATUS_OK;
3670 while (xconn->smb2.send_queue != NULL) {
3671 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3672 bool ok;
3674 if (e->sendfile_header != NULL) {
3675 size_t size = 0;
3676 size_t i = 0;
3677 uint8_t *buf;
3679 status = NT_STATUS_INTERNAL_ERROR;
3681 for (i=0; i < e->count; i++) {
3682 size += e->vector[i].iov_len;
3685 if (size <= e->sendfile_header->length) {
3686 buf = e->sendfile_header->data;
3687 } else {
3688 buf = talloc_array(e->mem_ctx, uint8_t, size);
3689 if (buf == NULL) {
3690 return NT_STATUS_NO_MEMORY;
3694 size = 0;
3695 for (i=0; i < e->count; i++) {
3696 memcpy(buf+size,
3697 e->vector[i].iov_base,
3698 e->vector[i].iov_len);
3699 size += e->vector[i].iov_len;
3702 e->sendfile_header->data = buf;
3703 e->sendfile_header->length = size;
3704 e->sendfile_status = &status;
3705 e->count = 0;
3707 xconn->smb2.send_queue_len--;
3708 DLIST_REMOVE(xconn->smb2.send_queue, e);
3710 * This triggers the sendfile path via
3711 * the destructor.
3713 talloc_free(e->mem_ctx);
3715 if (!NT_STATUS_IS_OK(status)) {
3716 return status;
3718 continue;
3721 ret = writev(xconn->transport.sock, e->vector, e->count);
3722 if (ret == 0) {
3723 /* propagate end of file */
3724 return NT_STATUS_INTERNAL_ERROR;
3726 err = socket_error_from_errno(ret, errno, &retry);
3727 if (retry) {
3728 /* retry later */
3729 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3730 return NT_STATUS_OK;
3732 if (err != 0) {
3733 return map_nt_error_from_unix_common(err);
3736 ok = iov_advance(&e->vector, &e->count, ret);
3737 if (!ok) {
3738 return NT_STATUS_INTERNAL_ERROR;
3741 if (e->count > 0) {
3742 /* we have more to write */
3743 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3744 return NT_STATUS_OK;
3747 xconn->smb2.send_queue_len--;
3748 DLIST_REMOVE(xconn->smb2.send_queue, e);
3749 talloc_free(e->mem_ctx);
3753 * Restart reads if we were blocked on
3754 * draining the send queue.
3757 status = smbd_smb2_request_next_incoming(xconn);
3758 if (!NT_STATUS_IS_OK(status)) {
3759 return status;
3762 return NT_STATUS_OK;
3765 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3766 uint16_t fde_flags)
3768 struct smbd_server_connection *sconn = xconn->client->sconn;
3769 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3770 struct smbd_smb2_request *req = NULL;
3771 size_t min_recvfile_size = UINT32_MAX;
3772 int ret;
3773 int err;
3774 bool retry;
3775 NTSTATUS status;
3776 NTTIME now;
3778 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3780 * we're not supposed to do any io
3782 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3783 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3784 return NT_STATUS_OK;
3787 if (fde_flags & TEVENT_FD_WRITE) {
3788 status = smbd_smb2_flush_send_queue(xconn);
3789 if (!NT_STATUS_IS_OK(status)) {
3790 return status;
3794 if (!(fde_flags & TEVENT_FD_READ)) {
3795 return NT_STATUS_OK;
3798 if (state->req == NULL) {
3799 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3800 return NT_STATUS_OK;
3803 again:
3804 if (!state->hdr.done) {
3805 state->hdr.done = true;
3807 state->vector.iov_base = (void *)state->hdr.nbt;
3808 state->vector.iov_len = NBT_HDR_SIZE;
3811 ret = readv(xconn->transport.sock, &state->vector, 1);
3812 if (ret == 0) {
3813 /* propagate end of file */
3814 return NT_STATUS_END_OF_FILE;
3816 err = socket_error_from_errno(ret, errno, &retry);
3817 if (retry) {
3818 /* retry later */
3819 TEVENT_FD_READABLE(xconn->transport.fde);
3820 return NT_STATUS_OK;
3822 if (err != 0) {
3823 return map_nt_error_from_unix_common(err);
3826 if (ret < state->vector.iov_len) {
3827 uint8_t *base;
3828 base = (uint8_t *)state->vector.iov_base;
3829 base += ret;
3830 state->vector.iov_base = (void *)base;
3831 state->vector.iov_len -= ret;
3832 /* we have more to read */
3833 TEVENT_FD_READABLE(xconn->transport.fde);
3834 return NT_STATUS_OK;
3837 if (state->pktlen > 0) {
3838 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3840 * Not a possible receivefile write.
3841 * Read the rest of the data.
3843 state->doing_receivefile = false;
3845 state->pktbuf = talloc_realloc(state->req,
3846 state->pktbuf,
3847 uint8_t,
3848 state->pktfull);
3849 if (state->pktbuf == NULL) {
3850 return NT_STATUS_NO_MEMORY;
3853 state->vector.iov_base = (void *)(state->pktbuf +
3854 state->pktlen);
3855 state->vector.iov_len = (state->pktfull -
3856 state->pktlen);
3858 state->pktlen = state->pktfull;
3859 goto again;
3863 * Either this is a receivefile write so we've
3864 * done a short read, or if not we have all the data.
3866 goto got_full;
3870 * Now we analyze the NBT header
3872 if (state->hdr.nbt[0] != 0x00) {
3873 state->min_recv_size = 0;
3875 state->pktfull = smb2_len(state->hdr.nbt);
3876 if (state->pktfull == 0) {
3877 goto got_full;
3880 if (state->min_recv_size != 0) {
3881 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3882 min_recvfile_size += state->min_recv_size;
3885 if (state->pktfull > min_recvfile_size) {
3887 * Might be a receivefile write. Read the SMB2 HEADER +
3888 * SMB2_WRITE header first. Set 'doing_receivefile'
3889 * as we're *attempting* receivefile write. If this
3890 * turns out not to be a SMB2_WRITE request or otherwise
3891 * not suitable then we'll just read the rest of the data
3892 * the next time this function is called.
3894 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3895 state->doing_receivefile = true;
3896 } else {
3897 state->pktlen = state->pktfull;
3900 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3901 if (state->pktbuf == NULL) {
3902 return NT_STATUS_NO_MEMORY;
3905 state->vector.iov_base = (void *)state->pktbuf;
3906 state->vector.iov_len = state->pktlen;
3908 goto again;
3910 got_full:
3912 if (state->hdr.nbt[0] != 0x00) {
3913 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3914 state->hdr.nbt[0]));
3916 req = state->req;
3917 ZERO_STRUCTP(state);
3918 state->req = req;
3919 state->min_recv_size = lp_min_receive_file_size();
3920 req = NULL;
3921 goto again;
3924 req = state->req;
3925 state->req = NULL;
3927 req->request_time = timeval_current();
3928 now = timeval_to_nttime(&req->request_time);
3930 status = smbd_smb2_inbuf_parse_compound(xconn,
3931 now,
3932 state->pktbuf,
3933 state->pktlen,
3934 req,
3935 &req->in.vector,
3936 &req->in.vector_count);
3937 if (!NT_STATUS_IS_OK(status)) {
3938 return status;
3941 if (state->doing_receivefile) {
3942 req->smb1req = talloc_zero(req, struct smb_request);
3943 if (req->smb1req == NULL) {
3944 return NT_STATUS_NO_MEMORY;
3946 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3949 ZERO_STRUCTP(state);
3951 req->current_idx = 1;
3953 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3954 req->current_idx, req->in.vector_count));
3956 status = smbd_smb2_request_validate(req);
3957 if (!NT_STATUS_IS_OK(status)) {
3958 return status;
3961 status = smbd_smb2_request_setup_out(req);
3962 if (!NT_STATUS_IS_OK(status)) {
3963 return status;
3966 status = smbd_smb2_request_dispatch(req);
3967 if (!NT_STATUS_IS_OK(status)) {
3968 return status;
3971 sconn->num_requests++;
3973 /* The timeout_processing function isn't run nearly
3974 often enough to implement 'max log size' without
3975 overrunning the size of the file by many megabytes.
3976 This is especially true if we are running at debug
3977 level 10. Checking every 50 SMB2s is a nice
3978 tradeoff of performance vs log file size overrun. */
3980 if ((sconn->num_requests % 50) == 0 &&
3981 need_to_check_log_size()) {
3982 change_to_root_user();
3983 check_log_size();
3986 status = smbd_smb2_request_next_incoming(xconn);
3987 if (!NT_STATUS_IS_OK(status)) {
3988 return status;
3991 return NT_STATUS_OK;
3994 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3995 struct tevent_fd *fde,
3996 uint16_t flags,
3997 void *private_data)
3999 struct smbXsrv_connection *xconn =
4000 talloc_get_type_abort(private_data,
4001 struct smbXsrv_connection);
4002 NTSTATUS status;
4004 status = smbd_smb2_io_handler(xconn, flags);
4005 if (!NT_STATUS_IS_OK(status)) {
4006 smbd_server_connection_terminate(xconn, nt_errstr(status));
4007 return;