smb2_server: grant all 8192 credits to clients
[Samba.git] / source3 / smbd / smb2_server.c
blobcfcc5c1354378e83127e84989b11039948ca49d6
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 * The above is what Windows Server < 2016 is doing,
834 * but new servers use all credits (8192 by default).
836 current_max_credits = xconn->smb2.credits.max;
837 current_max_credits = MAX(current_max_credits, 1);
839 if (xconn->smb2.credits.multicredit) {
840 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
841 credit_charge = MAX(credit_charge, 1);
844 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
845 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
846 credits_requested = MAX(credits_requested, 1);
847 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
848 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
850 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
852 if (xconn->smb2.credits.max < credit_charge) {
853 smbd_server_connection_terminate(xconn,
854 "client error: credit charge > max credits\n");
855 return;
858 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
860 * In case we already send an async interim
861 * response, we should not grant
862 * credits on the final response.
864 credits_granted = 0;
865 } else {
866 uint16_t additional_possible =
867 xconn->smb2.credits.max - credit_charge;
868 uint16_t additional_max = 0;
869 uint16_t additional_credits = credits_requested - 1;
871 switch (cmd) {
872 case SMB2_OP_NEGPROT:
873 break;
874 case SMB2_OP_SESSSETUP:
876 * Windows 2012 RC1 starts to grant
877 * additional credits
878 * with a successful session setup
880 if (NT_STATUS_IS_OK(out_status)) {
881 additional_max = xconn->smb2.credits.max;
883 break;
884 default:
886 * Windows Server < 2016 and older Samba versions
887 * used to only grant additional credits in
888 * chunks of 32 credits.
890 * But we match Windows Server 2016 and grant
891 * all credits as requested.
893 additional_max = xconn->smb2.credits.max;
894 break;
897 additional_max = MIN(additional_max, additional_possible);
898 additional_credits = MIN(additional_credits, additional_max);
900 credits_granted = credit_charge + additional_credits;
904 * sequence numbers should not wrap
906 * 1. calculate the possible credits until
907 * the sequence numbers start to wrap on 64-bit.
909 * 2. UINT64_MAX is used for Break Notifications.
911 * 2. truncate the possible credits to the maximum
912 * credits we want to grant to the client in total.
914 * 3. remove the range we'll already granted to the client
915 * this makes sure the client consumes the lowest sequence
916 * number, before we can grant additional credits.
918 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
919 if (credits_possible > 0) {
920 /* remove UINT64_MAX */
921 credits_possible -= 1;
923 credits_possible = MIN(credits_possible, current_max_credits);
924 credits_possible -= xconn->smb2.credits.seq_range;
926 credits_granted = MIN(credits_granted, credits_possible);
928 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
929 xconn->smb2.credits.granted += credits_granted;
930 xconn->smb2.credits.seq_range += credits_granted;
932 DBGC_DEBUG(DBGC_SMB2_CREDITS,
933 "smb2_set_operation_credit: requested %u, charge %u, "
934 "granted %u, current possible/max %u/%u, "
935 "total granted/max/low/range %u/%u/%llu/%u\n",
936 (unsigned int)credits_requested,
937 (unsigned int)credit_charge,
938 (unsigned int)credits_granted,
939 (unsigned int)credits_possible,
940 (unsigned int)current_max_credits,
941 (unsigned int)xconn->smb2.credits.granted,
942 (unsigned int)xconn->smb2.credits.max,
943 (unsigned long long)xconn->smb2.credits.seq_low,
944 (unsigned int)xconn->smb2.credits.seq_range);
947 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
948 struct smbd_smb2_request *outreq)
950 int count, idx;
951 uint16_t total_credits = 0;
953 count = outreq->out.vector_count;
955 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
956 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
957 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
958 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
960 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
962 /* To match Windows, count up what we
963 just granted. */
964 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
965 /* Set to zero in all but the last reply. */
966 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
967 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
968 } else {
969 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
974 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
976 if (req->current_idx <= 1) {
977 if (size <= sizeof(req->out._body)) {
978 return data_blob_const(req->out._body, size);
982 return data_blob_talloc(req, NULL, size);
985 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
987 struct smbXsrv_connection *xconn = req->xconn;
988 TALLOC_CTX *mem_ctx;
989 struct iovec *vector;
990 int count;
991 int idx;
992 bool ok;
994 count = req->in.vector_count;
995 if (count <= ARRAY_SIZE(req->out._vector)) {
996 mem_ctx = req;
997 vector = req->out._vector;
998 } else {
999 vector = talloc_zero_array(req, struct iovec, count);
1000 if (vector == NULL) {
1001 return NT_STATUS_NO_MEMORY;
1003 mem_ctx = vector;
1006 vector[0].iov_base = req->out.nbt_hdr;
1007 vector[0].iov_len = 4;
1008 SIVAL(req->out.nbt_hdr, 0, 0);
1010 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
1011 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
1012 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
1013 uint8_t *outhdr = NULL;
1014 uint8_t *outbody = NULL;
1015 uint32_t next_command_ofs = 0;
1016 struct iovec *current = &vector[idx];
1018 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
1019 /* we have a next command -
1020 * setup for the error case. */
1021 next_command_ofs = SMB2_HDR_BODY + 9;
1024 if (idx == 1) {
1025 outhdr = req->out._hdr;
1026 } else {
1027 outhdr = talloc_zero_array(mem_ctx, uint8_t,
1028 OUTVEC_ALLOC_SIZE);
1029 if (outhdr == NULL) {
1030 return NT_STATUS_NO_MEMORY;
1034 outbody = outhdr + SMB2_HDR_BODY;
1037 * SMBD_SMB2_TF_IOV_OFS might be used later
1039 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1040 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1042 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
1043 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1045 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1046 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1048 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1049 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1051 /* setup the SMB2 header */
1052 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1053 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1054 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1055 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1056 SIVAL(outhdr, SMB2_HDR_STATUS,
1057 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1058 SSVAL(outhdr, SMB2_HDR_OPCODE,
1059 SVAL(inhdr, SMB2_HDR_OPCODE));
1060 SIVAL(outhdr, SMB2_HDR_FLAGS,
1061 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1062 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1063 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1064 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1065 SIVAL(outhdr, SMB2_HDR_PID,
1066 IVAL(inhdr, SMB2_HDR_PID));
1067 SIVAL(outhdr, SMB2_HDR_TID,
1068 IVAL(inhdr, SMB2_HDR_TID));
1069 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1070 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1071 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1072 inhdr + SMB2_HDR_SIGNATURE, 16);
1074 /* setup error body header */
1075 SSVAL(outbody, 0x00, 0x08 + 1);
1076 SSVAL(outbody, 0x02, 0);
1077 SIVAL(outbody, 0x04, 0);
1080 req->out.vector = vector;
1081 req->out.vector_count = count;
1083 /* setup the length of the NBT packet */
1084 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1085 if (!ok) {
1086 return NT_STATUS_INVALID_PARAMETER_MIX;
1089 DLIST_ADD_END(xconn->smb2.requests, req);
1091 return NT_STATUS_OK;
1094 void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
1095 const char *reason,
1096 const char *location)
1098 struct smbXsrv_client *client = xconn->client;
1100 DEBUG(10,("smbd_server_connection_terminate_ex: conn[%s] reason[%s] at %s\n",
1101 smbXsrv_connection_dbg(xconn), reason, location));
1103 if (client->connections->next != NULL) {
1104 /* TODO: cancel pending requests */
1105 DLIST_REMOVE(client->connections, xconn);
1106 TALLOC_FREE(xconn);
1107 return;
1111 * The last connection was disconnected
1113 exit_server_cleanly(reason);
1116 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1117 struct iovec *outvec,
1118 const struct iovec *srcvec)
1120 const uint8_t *srctf;
1121 size_t srctf_len;
1122 const uint8_t *srchdr;
1123 size_t srchdr_len;
1124 const uint8_t *srcbody;
1125 size_t srcbody_len;
1126 const uint8_t *expected_srcbody;
1127 const uint8_t *srcdyn;
1128 size_t srcdyn_len;
1129 const uint8_t *expected_srcdyn;
1130 uint8_t *dsttf;
1131 uint8_t *dsthdr;
1132 uint8_t *dstbody;
1133 uint8_t *dstdyn;
1135 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1136 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1137 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1138 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1139 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1140 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1141 expected_srcbody = srchdr + SMB2_HDR_BODY;
1142 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1143 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1144 expected_srcdyn = srcbody + 8;
1146 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1147 return false;
1150 if (srchdr_len != SMB2_HDR_BODY) {
1151 return false;
1154 if (srctf_len == SMB2_TF_HDR_SIZE) {
1155 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1156 if (dsttf == NULL) {
1157 return false;
1159 } else {
1160 dsttf = NULL;
1162 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1163 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1165 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1166 * be allocated with size OUTVEC_ALLOC_SIZE. */
1168 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1169 if (dsthdr == NULL) {
1170 return false;
1172 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1173 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1176 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1177 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1178 * then duplicate this. Else use talloc_memdup().
1181 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1182 dstbody = dsthdr + SMB2_HDR_BODY;
1183 } else {
1184 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1185 if (dstbody == NULL) {
1186 return false;
1189 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1190 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1193 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1194 * pointing to
1195 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1196 * then duplicate this. Else use talloc_memdup().
1199 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1200 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1201 } else if (srcdyn == NULL) {
1202 dstdyn = NULL;
1203 } else {
1204 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1205 if (dstdyn == NULL) {
1206 return false;
1209 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1210 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1212 return true;
1215 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1217 struct smbd_smb2_request *newreq = NULL;
1218 struct iovec *outvec = NULL;
1219 int count = req->out.vector_count;
1220 int i;
1221 bool ok;
1223 newreq = smbd_smb2_request_allocate(req->xconn);
1224 if (!newreq) {
1225 return NULL;
1228 newreq->sconn = req->sconn;
1229 newreq->xconn = req->xconn;
1230 newreq->session = req->session;
1231 newreq->do_encryption = req->do_encryption;
1232 newreq->do_signing = req->do_signing;
1233 newreq->current_idx = req->current_idx;
1235 outvec = talloc_zero_array(newreq, struct iovec, count);
1236 if (!outvec) {
1237 TALLOC_FREE(newreq);
1238 return NULL;
1240 newreq->out.vector = outvec;
1241 newreq->out.vector_count = count;
1243 /* Setup the outvec's identically to req. */
1244 outvec[0].iov_base = newreq->out.nbt_hdr;
1245 outvec[0].iov_len = 4;
1246 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1248 /* Setup the vectors identically to the ones in req. */
1249 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1250 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1251 break;
1255 if (i < count) {
1256 /* Alloc failed. */
1257 TALLOC_FREE(newreq);
1258 return NULL;
1261 ok = smb2_setup_nbt_length(newreq->out.vector,
1262 newreq->out.vector_count);
1263 if (!ok) {
1264 TALLOC_FREE(newreq);
1265 return NULL;
1268 return newreq;
1271 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1273 struct smbXsrv_connection *xconn = req->xconn;
1274 int first_idx = 1;
1275 struct iovec *firsttf = NULL;
1276 struct iovec *outhdr_v = NULL;
1277 uint8_t *outhdr = NULL;
1278 struct smbd_smb2_request *nreq = NULL;
1279 NTSTATUS status;
1280 bool ok;
1282 /* Create a new smb2 request we'll use
1283 for the interim return. */
1284 nreq = dup_smb2_req(req);
1285 if (!nreq) {
1286 return NT_STATUS_NO_MEMORY;
1289 /* Lose the last X out vectors. They're the
1290 ones we'll be using for the async reply. */
1291 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1293 ok = smb2_setup_nbt_length(nreq->out.vector,
1294 nreq->out.vector_count);
1295 if (!ok) {
1296 return NT_STATUS_INVALID_PARAMETER_MIX;
1299 /* Step back to the previous reply. */
1300 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1301 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1302 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1303 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1304 /* And end the chain. */
1305 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1307 /* Calculate outgoing credits */
1308 smb2_calculate_credits(req, nreq);
1310 if (DEBUGLEVEL >= 10) {
1311 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1312 (unsigned int)nreq->current_idx );
1313 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1314 (unsigned int)nreq->out.vector_count );
1315 print_req_vectors(nreq);
1319 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1320 * we need to sign/encrypt here with the last/first key we remembered
1322 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1323 status = smb2_signing_encrypt_pdu(req->first_key,
1324 xconn->smb2.server.cipher,
1325 firsttf,
1326 nreq->out.vector_count - first_idx);
1327 if (!NT_STATUS_IS_OK(status)) {
1328 return status;
1330 } else if (req->last_key.length > 0) {
1331 status = smb2_signing_sign_pdu(req->last_key,
1332 xconn->protocol,
1333 outhdr_v,
1334 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1335 if (!NT_STATUS_IS_OK(status)) {
1336 return status;
1340 nreq->queue_entry.mem_ctx = nreq;
1341 nreq->queue_entry.vector = nreq->out.vector;
1342 nreq->queue_entry.count = nreq->out.vector_count;
1343 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry);
1344 xconn->smb2.send_queue_len++;
1346 status = smbd_smb2_flush_send_queue(xconn);
1347 if (!NT_STATUS_IS_OK(status)) {
1348 return status;
1351 return NT_STATUS_OK;
1354 struct smbd_smb2_request_pending_state {
1355 struct smbd_smb2_send_queue queue_entry;
1356 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1357 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1360 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1361 struct tevent_timer *te,
1362 struct timeval current_time,
1363 void *private_data);
1365 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1366 struct tevent_req *subreq,
1367 uint32_t defer_time)
1369 NTSTATUS status;
1370 struct timeval defer_endtime;
1371 uint8_t *outhdr = NULL;
1372 uint32_t flags;
1374 if (!tevent_req_is_in_progress(subreq)) {
1376 * This is a performance optimization,
1377 * it avoids one tevent_loop iteration,
1378 * which means we avoid one
1379 * talloc_stackframe_pool/talloc_free pair.
1381 tevent_req_notify_callback(subreq);
1382 return NT_STATUS_OK;
1385 req->subreq = subreq;
1386 subreq = NULL;
1388 if (req->async_te) {
1389 /* We're already async. */
1390 return NT_STATUS_OK;
1393 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1394 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1395 if (flags & SMB2_HDR_FLAG_ASYNC) {
1396 /* We're already async. */
1397 return NT_STATUS_OK;
1400 if (req->async_internal || defer_time == 0) {
1402 * An SMB2 request implementation wants to handle the request
1403 * asynchronously "internally" while keeping synchronous
1404 * behaviour for the SMB2 request. This means we don't send an
1405 * interim response and we can allow processing of compound SMB2
1406 * requests (cf the subsequent check) for all cases.
1408 return NT_STATUS_OK;
1411 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1413 * We're trying to go async in a compound request
1414 * chain. This is only allowed for opens that cause an
1415 * oplock break or for the last operation in the
1416 * chain, otherwise it is not allowed. See
1417 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
1419 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1421 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1423 * Cancel the outstanding request.
1425 bool ok = tevent_req_cancel(req->subreq);
1426 if (ok) {
1427 return NT_STATUS_OK;
1429 TALLOC_FREE(req->subreq);
1430 return smbd_smb2_request_error(req,
1431 NT_STATUS_INTERNAL_ERROR);
1435 if (DEBUGLEVEL >= 10) {
1436 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1437 (unsigned int)req->current_idx );
1438 print_req_vectors(req);
1441 if (req->current_idx > 1) {
1443 * We're going async in a compound
1444 * chain after the first request has
1445 * already been processed. Send an
1446 * interim response containing the
1447 * set of replies already generated.
1449 int idx = req->current_idx;
1451 status = smb2_send_async_interim_response(req);
1452 if (!NT_STATUS_IS_OK(status)) {
1453 return status;
1455 if (req->first_key.length > 0) {
1456 data_blob_clear_free(&req->first_key);
1459 req->current_idx = 1;
1462 * Re-arrange the in.vectors to remove what
1463 * we just sent.
1465 memmove(&req->in.vector[1],
1466 &req->in.vector[idx],
1467 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1468 req->in.vector_count = 1 + (req->in.vector_count - idx);
1470 /* Re-arrange the out.vectors to match. */
1471 memmove(&req->out.vector[1],
1472 &req->out.vector[idx],
1473 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1474 req->out.vector_count = 1 + (req->out.vector_count - idx);
1476 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1478 * We only have one remaining request as
1479 * we've processed everything else.
1480 * This is no longer a compound request.
1482 req->compound_related = false;
1483 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1484 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1485 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1488 if (req->last_key.length > 0) {
1489 data_blob_clear_free(&req->last_key);
1493 * smbd_smb2_request_pending_timer() just send a packet
1494 * to the client and doesn't need any impersonation.
1495 * So we use req->xconn->client->raw_ev_ctx instead
1496 * of req->ev_ctx here.
1498 defer_endtime = timeval_current_ofs_usec(defer_time);
1499 req->async_te = tevent_add_timer(req->xconn->client->raw_ev_ctx,
1500 req, defer_endtime,
1501 smbd_smb2_request_pending_timer,
1502 req);
1503 if (req->async_te == NULL) {
1504 return NT_STATUS_NO_MEMORY;
1507 return NT_STATUS_OK;
1510 static DATA_BLOB smbd_smb2_signing_key(struct smbXsrv_session *session,
1511 struct smbXsrv_connection *xconn)
1513 struct smbXsrv_channel_global0 *c = NULL;
1514 NTSTATUS status;
1515 DATA_BLOB key = data_blob_null;
1517 status = smbXsrv_session_find_channel(session, xconn, &c);
1518 if (NT_STATUS_IS_OK(status)) {
1519 key = c->signing_key;
1522 if (key.length == 0) {
1523 key = session->global->signing_key;
1526 return key;
1529 static NTSTATUS smb2_get_new_nonce(struct smbXsrv_session *session,
1530 uint64_t *new_nonce_high,
1531 uint64_t *new_nonce_low)
1533 uint64_t nonce_high;
1534 uint64_t nonce_low;
1536 session->nonce_low += 1;
1537 if (session->nonce_low == 0) {
1538 session->nonce_low += 1;
1539 session->nonce_high += 1;
1543 * CCM and GCM algorithms must never have their
1544 * nonce wrap, or the security of the whole
1545 * communication and the keys is destroyed.
1546 * We must drop the connection once we have
1547 * transfered too much data.
1549 * NOTE: We assume nonces greater than 8 bytes.
1551 if (session->nonce_high >= session->nonce_high_max) {
1552 return NT_STATUS_ENCRYPTION_FAILED;
1555 nonce_high = session->nonce_high_random;
1556 nonce_high += session->nonce_high;
1557 nonce_low = session->nonce_low;
1559 *new_nonce_high = nonce_high;
1560 *new_nonce_low = nonce_low;
1561 return NT_STATUS_OK;
1564 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1565 struct tevent_timer *te,
1566 struct timeval current_time,
1567 void *private_data)
1569 struct smbd_smb2_request *req =
1570 talloc_get_type_abort(private_data,
1571 struct smbd_smb2_request);
1572 struct smbXsrv_connection *xconn = req->xconn;
1573 struct smbd_smb2_request_pending_state *state = NULL;
1574 uint8_t *outhdr = NULL;
1575 const uint8_t *inhdr = NULL;
1576 uint8_t *tf = NULL;
1577 size_t tf_len = 0;
1578 uint8_t *hdr = NULL;
1579 uint8_t *body = NULL;
1580 uint8_t *dyn = NULL;
1581 uint32_t flags = 0;
1582 uint64_t session_id = 0;
1583 uint64_t message_id = 0;
1584 uint64_t nonce_high = 0;
1585 uint64_t nonce_low = 0;
1586 uint64_t async_id = 0;
1587 NTSTATUS status;
1588 bool ok;
1590 TALLOC_FREE(req->async_te);
1592 /* Ensure our final reply matches the interim one. */
1593 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1594 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1595 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1596 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1597 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1599 async_id = message_id; /* keep it simple for now... */
1601 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1602 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1604 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1605 "going async\n",
1606 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1607 (unsigned long long)async_id ));
1610 * What we send is identical to a smbd_smb2_request_error
1611 * packet with an error status of STATUS_PENDING. Make use
1612 * of this fact sometime when refactoring. JRA.
1615 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
1616 if (state == NULL) {
1617 smbd_server_connection_terminate(xconn,
1618 nt_errstr(NT_STATUS_NO_MEMORY));
1619 return;
1622 tf = state->buf + NBT_HDR_SIZE;
1623 tf_len = SMB2_TF_HDR_SIZE;
1625 hdr = tf + SMB2_TF_HDR_SIZE;
1626 body = hdr + SMB2_HDR_BODY;
1627 dyn = body + 8;
1629 if (req->do_encryption) {
1630 status = smb2_get_new_nonce(req->session,
1631 &nonce_high,
1632 &nonce_low);
1633 if (!NT_STATUS_IS_OK(status)) {
1634 smbd_server_connection_terminate(xconn,
1635 nt_errstr(status));
1636 return;
1640 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1641 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1642 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1643 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1645 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1646 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1647 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1648 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1649 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1651 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1652 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1653 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1654 SBVAL(hdr, SMB2_HDR_PID, async_id);
1655 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1656 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1657 memcpy(hdr+SMB2_HDR_SIGNATURE,
1658 outhdr+SMB2_HDR_SIGNATURE, 16);
1660 SSVAL(body, 0x00, 0x08 + 1);
1662 SCVAL(body, 0x02, 0);
1663 SCVAL(body, 0x03, 0);
1664 SIVAL(body, 0x04, 0);
1665 /* Match W2K8R2... */
1666 SCVAL(dyn, 0x00, 0x21);
1668 state->vector[0].iov_base = (void *)state->buf;
1669 state->vector[0].iov_len = NBT_HDR_SIZE;
1671 if (req->do_encryption) {
1672 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1673 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1674 } else {
1675 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1676 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1679 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1680 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1682 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1683 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1685 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1686 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1688 ok = smb2_setup_nbt_length(state->vector,
1689 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1690 if (!ok) {
1691 smbd_server_connection_terminate(
1692 xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
1693 return;
1696 /* Ensure we correctly go through crediting. Grant
1697 the credits now, and zero credits on the final
1698 response. */
1699 smb2_set_operation_credit(req->xconn,
1700 SMBD_SMB2_IN_HDR_IOV(req),
1701 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1703 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1705 if (DEBUGLVL(10)) {
1706 int i;
1708 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1709 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1710 (unsigned int)i,
1711 (unsigned int)ARRAY_SIZE(state->vector),
1712 (unsigned int)state->vector[i].iov_len);
1716 if (req->do_encryption) {
1717 struct smbXsrv_session *x = req->session;
1718 DATA_BLOB encryption_key = x->global->encryption_key;
1720 status = smb2_signing_encrypt_pdu(encryption_key,
1721 xconn->smb2.server.cipher,
1722 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1723 SMBD_SMB2_NUM_IOV_PER_REQ);
1724 if (!NT_STATUS_IS_OK(status)) {
1725 smbd_server_connection_terminate(xconn,
1726 nt_errstr(status));
1727 return;
1729 } else if (req->do_signing) {
1730 struct smbXsrv_session *x = req->session;
1731 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
1733 status = smb2_signing_sign_pdu(signing_key,
1734 xconn->protocol,
1735 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1736 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1737 if (!NT_STATUS_IS_OK(status)) {
1738 smbd_server_connection_terminate(xconn,
1739 nt_errstr(status));
1740 return;
1744 state->queue_entry.mem_ctx = state;
1745 state->queue_entry.vector = state->vector;
1746 state->queue_entry.count = ARRAY_SIZE(state->vector);
1747 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
1748 xconn->smb2.send_queue_len++;
1750 status = smbd_smb2_flush_send_queue(xconn);
1751 if (!NT_STATUS_IS_OK(status)) {
1752 smbd_server_connection_terminate(xconn,
1753 nt_errstr(status));
1754 return;
1758 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1760 struct smbXsrv_connection *xconn = req->xconn;
1761 struct smbd_smb2_request *cur;
1762 const uint8_t *inhdr;
1763 uint32_t flags;
1764 uint64_t search_message_id;
1765 uint64_t search_async_id;
1766 uint64_t found_id;
1768 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1770 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1771 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1772 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1775 * We don't need the request anymore cancel requests never
1776 * have a response.
1778 * We defer the TALLOC_FREE(req) to the caller.
1780 DLIST_REMOVE(xconn->smb2.requests, req);
1782 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1783 const uint8_t *outhdr;
1784 uint64_t message_id;
1785 uint64_t async_id;
1787 if (cur->compound_related) {
1789 * Never cancel anything in a compound request.
1790 * Way too hard to deal with the result.
1792 continue;
1795 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1797 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1798 async_id = BVAL(outhdr, SMB2_HDR_PID);
1800 if (flags & SMB2_HDR_FLAG_ASYNC) {
1801 if (search_async_id == async_id) {
1802 found_id = async_id;
1803 break;
1805 } else {
1806 if (search_message_id == message_id) {
1807 found_id = message_id;
1808 break;
1813 if (cur && cur->subreq) {
1814 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1815 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1816 "cancel opcode[%s] mid %llu\n",
1817 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1818 (unsigned long long)found_id ));
1819 tevent_req_cancel(cur->subreq);
1822 return NT_STATUS_OK;
1825 /*************************************************************
1826 Ensure an incoming tid is a valid one for us to access.
1827 Change to the associated uid credentials and chdir to the
1828 valid tid directory.
1829 *************************************************************/
1831 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1833 const uint8_t *inhdr;
1834 uint32_t in_flags;
1835 uint32_t in_tid;
1836 struct smbXsrv_tcon *tcon;
1837 NTSTATUS status;
1838 NTTIME now = timeval_to_nttime(&req->request_time);
1840 req->tcon = NULL;
1842 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1844 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1845 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1847 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1848 in_tid = req->last_tid;
1851 req->last_tid = 0;
1853 status = smb2srv_tcon_lookup(req->session,
1854 in_tid, now, &tcon);
1855 if (!NT_STATUS_IS_OK(status)) {
1856 return status;
1859 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1860 return NT_STATUS_ACCESS_DENIED;
1863 req->tcon = tcon;
1864 req->last_tid = in_tid;
1866 return NT_STATUS_OK;
1869 /*************************************************************
1870 Ensure an incoming session_id is a valid one for us to access.
1871 *************************************************************/
1873 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1875 const uint8_t *inhdr;
1876 uint32_t in_flags;
1877 uint16_t in_opcode;
1878 uint64_t in_session_id;
1879 struct smbXsrv_session *session = NULL;
1880 struct auth_session_info *session_info;
1881 NTSTATUS status;
1882 NTTIME now = timeval_to_nttime(&req->request_time);
1884 req->session = NULL;
1885 req->tcon = NULL;
1887 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1889 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1890 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1891 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1893 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1894 in_session_id = req->last_session_id;
1897 req->last_session_id = 0;
1899 /* look an existing session up */
1900 switch (in_opcode) {
1901 case SMB2_OP_SESSSETUP:
1903 * For a session bind request, we don't have the
1904 * channel set up at this point yet, so we defer
1905 * the verification that the connection belongs
1906 * to the session to the session setup code, which
1907 * can look at the session binding flags.
1909 status = smb2srv_session_lookup_client(req->xconn->client,
1910 in_session_id, now,
1911 &session);
1912 break;
1913 default:
1914 status = smb2srv_session_lookup_conn(req->xconn,
1915 in_session_id, now,
1916 &session);
1917 break;
1919 if (session) {
1920 req->session = session;
1921 req->last_session_id = in_session_id;
1923 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1924 switch (in_opcode) {
1925 case SMB2_OP_SESSSETUP:
1926 status = NT_STATUS_OK;
1927 break;
1928 case SMB2_OP_LOGOFF:
1929 case SMB2_OP_CLOSE:
1930 case SMB2_OP_LOCK:
1931 case SMB2_OP_CANCEL:
1932 case SMB2_OP_KEEPALIVE:
1934 * [MS-SMB2] 3.3.5.2.9 Verifying the Session
1935 * specifies that LOGOFF, CLOSE and (UN)LOCK
1936 * should always be processed even on expired sessions.
1938 * Also see the logic in
1939 * smbd_smb2_request_process_lock().
1941 * The smb2.session.expire2 test shows that
1942 * CANCEL and KEEPALIVE/ECHO should also
1943 * be processed.
1945 status = NT_STATUS_OK;
1946 break;
1947 default:
1948 break;
1951 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1952 switch (in_opcode) {
1953 case SMB2_OP_TCON:
1954 case SMB2_OP_CREATE:
1955 case SMB2_OP_GETINFO:
1956 case SMB2_OP_SETINFO:
1957 return NT_STATUS_INVALID_HANDLE;
1958 default:
1960 * Notice the check for
1961 * (session_info == NULL)
1962 * below.
1964 status = NT_STATUS_OK;
1965 break;
1968 if (!NT_STATUS_IS_OK(status)) {
1969 return status;
1972 session_info = session->global->auth_session_info;
1973 if (session_info == NULL) {
1974 return NT_STATUS_INVALID_HANDLE;
1977 return NT_STATUS_OK;
1980 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1981 uint32_t data_length)
1983 struct smbXsrv_connection *xconn = req->xconn;
1984 uint16_t needed_charge;
1985 uint16_t credit_charge = 1;
1986 const uint8_t *inhdr;
1988 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1990 if (xconn->smb2.credits.multicredit) {
1991 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1992 credit_charge = MAX(credit_charge, 1);
1995 needed_charge = (data_length - 1)/ 65536 + 1;
1997 DBGC_DEBUG(DBGC_SMB2_CREDITS,
1998 "mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1999 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
2000 credit_charge, needed_charge);
2002 if (needed_charge > credit_charge) {
2003 DBGC_WARNING(DBGC_SMB2_CREDITS,
2004 "CreditCharge too low, given %d, needed %d\n",
2005 credit_charge, needed_charge);
2006 return NT_STATUS_INVALID_PARAMETER;
2009 return NT_STATUS_OK;
2012 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
2013 size_t expected_body_size)
2015 struct iovec *inhdr_v;
2016 const uint8_t *inhdr;
2017 uint16_t opcode;
2018 const uint8_t *inbody;
2019 size_t body_size;
2020 size_t min_dyn_size = expected_body_size & 0x00000001;
2021 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
2024 * The following should be checked already.
2026 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
2027 return NT_STATUS_INTERNAL_ERROR;
2029 if (req->current_idx > max_idx) {
2030 return NT_STATUS_INTERNAL_ERROR;
2033 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
2034 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
2035 return NT_STATUS_INTERNAL_ERROR;
2037 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
2038 return NT_STATUS_INTERNAL_ERROR;
2041 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2042 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2044 switch (opcode) {
2045 case SMB2_OP_IOCTL:
2046 case SMB2_OP_GETINFO:
2047 min_dyn_size = 0;
2048 break;
2049 case SMB2_OP_WRITE:
2050 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
2051 if (req->smb1req->unread_bytes < min_dyn_size) {
2052 return NT_STATUS_INVALID_PARAMETER;
2055 min_dyn_size = 0;
2057 break;
2061 * Now check the expected body size,
2062 * where the last byte might be in the
2063 * dynamic section..
2065 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
2066 return NT_STATUS_INVALID_PARAMETER;
2068 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
2069 return NT_STATUS_INVALID_PARAMETER;
2072 inbody = SMBD_SMB2_IN_BODY_PTR(req);
2074 body_size = SVAL(inbody, 0x00);
2075 if (body_size != expected_body_size) {
2076 return NT_STATUS_INVALID_PARAMETER;
2079 return NT_STATUS_OK;
2082 bool smbXsrv_is_encrypted(uint8_t encryption_flags)
2084 return (!(encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)
2086 (encryption_flags & (SMBXSRV_PROCESSED_ENCRYPTED_PACKET |
2087 SMBXSRV_ENCRYPTION_DESIRED |
2088 SMBXSRV_ENCRYPTION_REQUIRED)));
2091 bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags)
2093 return ((encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET) &&
2094 (encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET));
2097 /* Set a flag if not already set, return true if set */
2098 bool smbXsrv_set_crypto_flag(uint8_t *flags, uint8_t flag)
2100 if ((flag == 0) || (*flags & flag)) {
2101 return false;
2104 *flags |= flag;
2105 return true;
2109 * Update encryption state tracking flags, this can be used to
2110 * determine whether whether the session or tcon is "encrypted".
2112 static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
2113 uint16_t opcode,
2114 bool *update_session_globalp,
2115 bool *update_tcon_globalp)
2117 /* Default: assume unecrypted and unsigned */
2118 struct smbXsrv_session *session = req->session;
2119 struct smbXsrv_tcon *tcon = req->tcon;
2120 uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
2121 uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2122 bool update_session = false;
2123 bool update_tcon = false;
2125 if (req->was_encrypted && req->do_encryption) {
2126 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
2127 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2128 } else {
2129 /* Unencrypted packet, can be signed */
2130 if (req->do_signing) {
2131 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2132 } else if (opcode == SMB2_OP_CANCEL) {
2133 /* Cancel requests are allowed to skip signing */
2134 sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2138 update_session |= smbXsrv_set_crypto_flag(
2139 &session->global->encryption_flags, encrypt_flag);
2140 update_session |= smbXsrv_set_crypto_flag(
2141 &session->global->signing_flags, sign_flag);
2143 if (tcon) {
2144 update_tcon |= smbXsrv_set_crypto_flag(
2145 &tcon->global->encryption_flags, encrypt_flag);
2146 update_tcon |= smbXsrv_set_crypto_flag(
2147 &tcon->global->signing_flags, sign_flag);
2150 *update_session_globalp = update_session;
2151 *update_tcon_globalp = update_tcon;
2152 return;
2155 bool smbXsrv_is_signed(uint8_t signing_flags)
2158 * Signing is always enabled, so unless we got an unsigned
2159 * packet and at least one signed packet that was not
2160 * encrypted, the session or tcon is "signed".
2162 return (!(signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2163 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2166 bool smbXsrv_is_partially_signed(uint8_t signing_flags)
2168 return ((signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2169 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2172 static NTSTATUS smbd_smb2_request_dispatch_update_counts(
2173 struct smbd_smb2_request *req,
2174 bool modify_call)
2176 struct smbXsrv_connection *xconn = req->xconn;
2177 const uint8_t *inhdr;
2178 uint16_t channel_sequence;
2179 uint8_t generation_wrap = 0;
2180 uint32_t flags;
2181 int cmp;
2182 struct smbXsrv_open *op;
2183 bool update_open = false;
2184 NTSTATUS status = NT_STATUS_OK;
2186 SMB_ASSERT(!req->request_counters_updated);
2188 if (xconn->protocol < PROTOCOL_SMB2_22) {
2189 return NT_STATUS_OK;
2192 if (req->compat_chain_fsp == NULL) {
2193 return NT_STATUS_OK;
2196 op = req->compat_chain_fsp->op;
2197 if (op == NULL) {
2198 return NT_STATUS_OK;
2201 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2202 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2203 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2205 cmp = channel_sequence - op->global->channel_sequence;
2206 if (cmp < 0) {
2208 * csn wrap. We need to watch out for long-running
2209 * requests that are still sitting on a previously
2210 * used csn. SMB2_OP_NOTIFY can take VERY long.
2212 generation_wrap += 1;
2215 if (abs(cmp) > INT16_MAX) {
2217 * [MS-SMB2] 3.3.5.2.10 - Verifying the Channel Sequence Number:
2219 * If the channel sequence number of the request and the one
2220 * known to the server are not equal, the channel sequence
2221 * number and outstanding request counts are only updated
2222 * "... if the unsigned difference using 16-bit arithmetic
2223 * between ChannelSequence and Open.ChannelSequence is less than
2224 * or equal to 0x7FFF ...".
2225 * Otherwise, an error is returned for the modifying
2226 * calls write, set_info, and ioctl.
2228 * There are currently two issues with the description:
2230 * * For the other calls, the document seems to imply
2231 * that processing continues without adapting the
2232 * counters (if the sequence numbers are not equal).
2234 * TODO: This needs clarification!
2236 * * Also, the behaviour if the difference is larger
2237 * than 0x7FFF is not clear. The document seems to
2238 * imply that if such a difference is reached,
2239 * the server starts to ignore the counters or
2240 * in the case of the modifying calls, return errors.
2242 * TODO: This needs clarification!
2244 * At this point Samba tries to be a little more
2245 * clever than the description in the MS-SMB2 document
2246 * by heuristically detecting and properly treating
2247 * a 16 bit overflow of the client-submitted sequence
2248 * number:
2250 * If the stored channel sequence number is more than
2251 * 0x7FFF larger than the one from the request, then
2252 * the client-provided sequence number has likely
2253 * overflown. We treat this case as valid instead
2254 * of as failure.
2256 * The MS-SMB2 behaviour would be setting cmp = -1.
2258 cmp *= -1;
2261 if (flags & SMB2_HDR_FLAG_REPLAY_OPERATION) {
2262 if (cmp == 0 && op->pre_request_count == 0) {
2263 op->request_count += 1;
2264 req->request_counters_updated = true;
2265 } else if (cmp > 0 && op->pre_request_count == 0) {
2266 op->pre_request_count += op->request_count;
2267 op->request_count = 1;
2268 op->global->channel_sequence = channel_sequence;
2269 op->global->channel_generation += generation_wrap;
2270 update_open = true;
2271 req->request_counters_updated = true;
2272 } else if (modify_call) {
2273 return NT_STATUS_FILE_NOT_AVAILABLE;
2275 } else {
2276 if (cmp == 0) {
2277 op->request_count += 1;
2278 req->request_counters_updated = true;
2279 } else if (cmp > 0) {
2280 op->pre_request_count += op->request_count;
2281 op->request_count = 1;
2282 op->global->channel_sequence = channel_sequence;
2283 op->global->channel_generation += generation_wrap;
2284 update_open = true;
2285 req->request_counters_updated = true;
2286 } else if (modify_call) {
2287 return NT_STATUS_FILE_NOT_AVAILABLE;
2290 req->channel_generation = op->global->channel_generation;
2292 if (update_open) {
2293 status = smbXsrv_open_update(op);
2296 return status;
2299 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
2301 struct smbXsrv_connection *xconn = req->xconn;
2302 const struct smbd_smb2_dispatch_table *call = NULL;
2303 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
2304 const uint8_t *inhdr;
2305 uint16_t opcode;
2306 uint32_t flags;
2307 uint64_t mid;
2308 NTSTATUS status;
2309 NTSTATUS session_status;
2310 uint32_t allowed_flags;
2311 NTSTATUS return_value;
2312 struct smbXsrv_session *x = NULL;
2313 bool signing_required = false;
2314 bool encryption_desired = false;
2315 bool encryption_required = false;
2317 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2319 DO_PROFILE_INC(request);
2321 SMB_ASSERT(!req->request_counters_updated);
2323 /* TODO: verify more things */
2325 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2326 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2327 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2328 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
2329 smb2_opcode_name(opcode),
2330 (unsigned long long)mid));
2332 if (xconn->protocol >= PROTOCOL_SMB2_02) {
2334 * once the protocol is negotiated
2335 * SMB2_OP_NEGPROT is not allowed anymore
2337 if (opcode == SMB2_OP_NEGPROT) {
2338 /* drop the connection */
2339 return NT_STATUS_INVALID_PARAMETER;
2341 } else {
2343 * if the protocol is not negotiated yet
2344 * only SMB2_OP_NEGPROT is allowed.
2346 if (opcode != SMB2_OP_NEGPROT) {
2347 /* drop the connection */
2348 return NT_STATUS_INVALID_PARAMETER;
2353 * Check if the client provided a valid session id.
2355 * As some command don't require a valid session id
2356 * we defer the check of the session_status
2358 session_status = smbd_smb2_request_check_session(req);
2359 x = req->session;
2360 if (x != NULL) {
2361 signing_required = x->global->signing_flags & SMBXSRV_SIGNING_REQUIRED;
2362 encryption_desired = x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
2363 encryption_required = x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
2366 req->async_internal = false;
2367 req->do_signing = false;
2368 if (opcode != SMB2_OP_SESSSETUP) {
2369 req->do_encryption = encryption_desired;
2370 } else {
2371 req->do_encryption = false;
2373 req->was_encrypted = false;
2374 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
2375 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
2376 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
2378 if (x != NULL && x->global->session_wire_id != tf_session_id) {
2379 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2380 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
2381 (unsigned long long)x->global->session_wire_id,
2382 (unsigned long long)tf_session_id));
2384 * TODO: windows allows this...
2385 * should we drop the connection?
2387 * For now we just return ACCESS_DENIED
2388 * (Windows clients never trigger this)
2389 * and wait for an update of [MS-SMB2].
2391 return smbd_smb2_request_error(req,
2392 NT_STATUS_ACCESS_DENIED);
2395 req->was_encrypted = true;
2396 req->do_encryption = true;
2399 if (encryption_required && !req->was_encrypted) {
2400 req->do_encryption = true;
2401 return smbd_smb2_request_error(req,
2402 NT_STATUS_ACCESS_DENIED);
2405 call = smbd_smb2_call(opcode);
2406 if (call == NULL) {
2407 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2410 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2411 SMB2_HDR_FLAG_SIGNED |
2412 SMB2_HDR_FLAG_DFS;
2413 if (xconn->protocol >= PROTOCOL_SMB3_11) {
2414 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2416 if (opcode == SMB2_OP_NEGPROT) {
2417 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11) {
2418 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2421 if (opcode == SMB2_OP_CANCEL) {
2422 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2424 if (xconn->protocol >= PROTOCOL_SMB2_22) {
2425 allowed_flags |= SMB2_HDR_FLAG_REPLAY_OPERATION;
2427 if ((flags & ~allowed_flags) != 0) {
2428 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2431 if (flags & SMB2_HDR_FLAG_CHAINED) {
2433 * This check is mostly for giving the correct error code
2434 * for compounded requests.
2436 if (!NT_STATUS_IS_OK(session_status)) {
2437 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2439 } else {
2440 req->compat_chain_fsp = NULL;
2443 if (req->was_encrypted) {
2444 signing_required = false;
2445 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2446 DATA_BLOB signing_key = data_blob_null;
2448 if (x == NULL) {
2450 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2451 * If the SMB2 header of the SMB2 NEGOTIATE
2452 * request has the SMB2_FLAGS_SIGNED bit set in the
2453 * Flags field, the server MUST fail the request
2454 * with STATUS_INVALID_PARAMETER.
2456 * Microsoft test tool checks this.
2459 if ((opcode == SMB2_OP_NEGPROT) &&
2460 (flags & SMB2_HDR_FLAG_SIGNED)) {
2461 status = NT_STATUS_INVALID_PARAMETER;
2462 } else {
2463 status = NT_STATUS_USER_SESSION_DELETED;
2465 return smbd_smb2_request_error(req, status);
2468 signing_key = smbd_smb2_signing_key(x, xconn);
2471 * If we have a signing key, we should
2472 * sign the response
2474 if (signing_key.length > 0) {
2475 req->do_signing = true;
2478 status = smb2_signing_check_pdu(signing_key,
2479 xconn->protocol,
2480 SMBD_SMB2_IN_HDR_IOV(req),
2481 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2482 if (!NT_STATUS_IS_OK(status)) {
2483 return smbd_smb2_request_error(req, status);
2487 * Now that we know the request was correctly signed
2488 * we have to sign the response too.
2490 req->do_signing = true;
2492 if (!NT_STATUS_IS_OK(session_status)) {
2493 return smbd_smb2_request_error(req, session_status);
2495 } else if (opcode == SMB2_OP_CANCEL) {
2496 /* Cancel requests are allowed to skip the signing */
2497 } else if (signing_required) {
2499 * If signing is required we try to sign
2500 * a possible error response
2502 req->do_signing = true;
2503 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2506 if (flags & SMB2_HDR_FLAG_CHAINED) {
2507 req->compound_related = true;
2510 if (call->need_session) {
2511 if (!NT_STATUS_IS_OK(session_status)) {
2512 return smbd_smb2_request_error(req, session_status);
2516 if (call->need_tcon) {
2517 SMB_ASSERT(call->need_session);
2520 * This call needs to be run as user.
2522 * smbd_smb2_request_check_tcon()
2523 * calls change_to_user() on success.
2524 * Which implies set_current_user_info()
2525 * and chdir_current_service().
2527 status = smbd_smb2_request_check_tcon(req);
2528 if (!NT_STATUS_IS_OK(status)) {
2529 return smbd_smb2_request_error(req, status);
2531 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
2532 encryption_desired = true;
2534 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
2535 encryption_required = true;
2537 if (encryption_required && !req->was_encrypted) {
2538 req->do_encryption = true;
2539 return smbd_smb2_request_error(req,
2540 NT_STATUS_ACCESS_DENIED);
2541 } else if (encryption_desired) {
2542 req->do_encryption = true;
2544 } else if (call->need_session) {
2545 struct auth_session_info *session_info = NULL;
2548 * Unless we also have need_tcon (see above),
2549 * we still need to call set_current_user_info().
2552 session_info = req->session->global->auth_session_info;
2553 if (session_info == NULL) {
2554 return NT_STATUS_INVALID_HANDLE;
2557 set_current_user_info(session_info->unix_info->sanitized_username,
2558 session_info->unix_info->unix_name,
2559 session_info->info->domain_name);
2562 if (req->session) {
2563 bool update_session_global = false;
2564 bool update_tcon_global = false;
2566 smb2srv_update_crypto_flags(req, opcode,
2567 &update_session_global,
2568 &update_tcon_global);
2570 if (update_session_global) {
2571 status = smbXsrv_session_update(x);
2572 if (!NT_STATUS_IS_OK(status)) {
2573 return smbd_smb2_request_error(req, status);
2576 if (update_tcon_global) {
2577 status = smbXsrv_tcon_update(req->tcon);
2578 if (!NT_STATUS_IS_OK(status)) {
2579 return smbd_smb2_request_error(req, status);
2584 if (call->fileid_ofs != 0) {
2585 size_t needed = call->fileid_ofs + 16;
2586 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2587 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2588 uint64_t file_id_persistent;
2589 uint64_t file_id_volatile;
2590 struct files_struct *fsp;
2592 SMB_ASSERT(call->need_tcon);
2594 if (needed > body_size) {
2595 return smbd_smb2_request_error(req,
2596 NT_STATUS_INVALID_PARAMETER);
2599 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2600 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2602 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2603 if (fsp == NULL) {
2604 if (!call->allow_invalid_fileid) {
2605 return smbd_smb2_request_error(req,
2606 NT_STATUS_FILE_CLOSED);
2609 if (file_id_persistent != UINT64_MAX) {
2610 return smbd_smb2_request_error(req,
2611 NT_STATUS_FILE_CLOSED);
2613 if (file_id_volatile != UINT64_MAX) {
2614 return smbd_smb2_request_error(req,
2615 NT_STATUS_FILE_CLOSED);
2620 status = smbd_smb2_request_dispatch_update_counts(req, call->modify);
2621 if (!NT_STATUS_IS_OK(status)) {
2622 return smbd_smb2_request_error(req, status);
2625 if (call->as_root) {
2626 SMB_ASSERT(call->fileid_ofs == 0);
2627 /* This call needs to be run as root */
2628 change_to_root_user();
2629 req->ev_ctx = req->sconn->root_ev_ctx;
2630 } else {
2631 SMB_ASSERT(call->need_tcon);
2632 req->ev_ctx = req->tcon->compat->user_ev_ctx;
2635 #define _INBYTES(_r) \
2636 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
2638 switch (opcode) {
2639 case SMB2_OP_NEGPROT:
2640 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
2641 req->profile, _INBYTES(req));
2642 return_value = smbd_smb2_request_process_negprot(req);
2643 break;
2645 case SMB2_OP_SESSSETUP:
2646 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
2647 req->profile, _INBYTES(req));
2648 return_value = smbd_smb2_request_process_sesssetup(req);
2649 break;
2651 case SMB2_OP_LOGOFF:
2652 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
2653 req->profile, _INBYTES(req));
2654 return_value = smbd_smb2_request_process_logoff(req);
2655 break;
2657 case SMB2_OP_TCON:
2658 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
2659 req->profile, _INBYTES(req));
2660 return_value = smbd_smb2_request_process_tcon(req);
2661 break;
2663 case SMB2_OP_TDIS:
2664 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
2665 req->profile, _INBYTES(req));
2666 return_value = smbd_smb2_request_process_tdis(req);
2667 break;
2669 case SMB2_OP_CREATE:
2670 if (req->subreq == NULL) {
2671 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
2672 req->profile, _INBYTES(req));
2673 } else {
2674 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
2676 return_value = smbd_smb2_request_process_create(req);
2677 break;
2679 case SMB2_OP_CLOSE:
2680 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
2681 req->profile, _INBYTES(req));
2682 return_value = smbd_smb2_request_process_close(req);
2683 break;
2685 case SMB2_OP_FLUSH:
2686 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
2687 req->profile, _INBYTES(req));
2688 return_value = smbd_smb2_request_process_flush(req);
2689 break;
2691 case SMB2_OP_READ:
2692 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
2693 req->profile, _INBYTES(req));
2694 return_value = smbd_smb2_request_process_read(req);
2695 break;
2697 case SMB2_OP_WRITE:
2698 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
2699 req->profile, _INBYTES(req));
2700 return_value = smbd_smb2_request_process_write(req);
2701 break;
2703 case SMB2_OP_LOCK:
2704 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
2705 req->profile, _INBYTES(req));
2706 return_value = smbd_smb2_request_process_lock(req);
2707 break;
2709 case SMB2_OP_IOCTL:
2710 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
2711 req->profile, _INBYTES(req));
2712 return_value = smbd_smb2_request_process_ioctl(req);
2713 break;
2715 case SMB2_OP_CANCEL:
2716 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
2717 req->profile, _INBYTES(req));
2718 return_value = smbd_smb2_request_process_cancel(req);
2719 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
2722 * We don't need the request anymore cancel requests never
2723 * have a response.
2725 * smbd_smb2_request_process_cancel() already called
2726 * DLIST_REMOVE(xconn->smb2.requests, req);
2728 TALLOC_FREE(req);
2730 break;
2732 case SMB2_OP_KEEPALIVE:
2733 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
2734 req->profile, _INBYTES(req));
2735 return_value = smbd_smb2_request_process_keepalive(req);
2736 break;
2738 case SMB2_OP_QUERY_DIRECTORY:
2739 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
2740 req->profile, _INBYTES(req));
2741 return_value = smbd_smb2_request_process_query_directory(req);
2742 break;
2744 case SMB2_OP_NOTIFY:
2745 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
2746 req->profile, _INBYTES(req));
2747 return_value = smbd_smb2_request_process_notify(req);
2748 break;
2750 case SMB2_OP_GETINFO:
2751 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
2752 req->profile, _INBYTES(req));
2753 return_value = smbd_smb2_request_process_getinfo(req);
2754 break;
2756 case SMB2_OP_SETINFO:
2757 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
2758 req->profile, _INBYTES(req));
2759 return_value = smbd_smb2_request_process_setinfo(req);
2760 break;
2762 case SMB2_OP_BREAK:
2763 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
2764 req->profile, _INBYTES(req));
2765 return_value = smbd_smb2_request_process_break(req);
2766 break;
2768 default:
2769 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2770 break;
2772 return return_value;
2775 static void smbd_smb2_request_reply_update_counts(struct smbd_smb2_request *req)
2777 struct smbXsrv_connection *xconn = req->xconn;
2778 const uint8_t *inhdr;
2779 uint16_t channel_sequence;
2780 struct smbXsrv_open *op;
2782 if (!req->request_counters_updated) {
2783 return;
2786 req->request_counters_updated = false;
2788 if (xconn->protocol < PROTOCOL_SMB2_22) {
2789 return;
2792 if (req->compat_chain_fsp == NULL) {
2793 return;
2796 op = req->compat_chain_fsp->op;
2797 if (op == NULL) {
2798 return;
2801 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2802 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2804 if ((op->global->channel_sequence == channel_sequence) &&
2805 (op->global->channel_generation == req->channel_generation)) {
2806 SMB_ASSERT(op->request_count > 0);
2807 op->request_count -= 1;
2808 } else {
2809 SMB_ASSERT(op->pre_request_count > 0);
2810 op->pre_request_count -= 1;
2814 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2816 struct smbXsrv_connection *xconn = req->xconn;
2817 int first_idx = 1;
2818 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2819 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2820 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2821 NTSTATUS status;
2822 bool ok;
2824 req->subreq = NULL;
2825 TALLOC_FREE(req->async_te);
2827 /* MS-SMB2: 3.3.4.1 Sending Any Outgoing Message */
2828 smbd_smb2_request_reply_update_counts(req);
2830 if (req->do_encryption &&
2831 (firsttf->iov_len == 0) &&
2832 (req->first_key.length == 0) &&
2833 (req->session != NULL) &&
2834 (req->session->global->encryption_key.length != 0))
2836 DATA_BLOB encryption_key = req->session->global->encryption_key;
2837 uint8_t *tf;
2838 uint64_t session_id = req->session->global->session_wire_id;
2839 uint64_t nonce_high;
2840 uint64_t nonce_low;
2842 status = smb2_get_new_nonce(req->session,
2843 &nonce_high,
2844 &nonce_low);
2845 if (!NT_STATUS_IS_OK(status)) {
2846 return status;
2850 * We need to place the SMB2_TRANSFORM header before the
2851 * first SMB2 header
2855 * we need to remember the encryption key
2856 * and defer the signing/encryption until
2857 * we are sure that we do not change
2858 * the header again.
2860 req->first_key = data_blob_dup_talloc(req, encryption_key);
2861 if (req->first_key.data == NULL) {
2862 return NT_STATUS_NO_MEMORY;
2865 tf = talloc_zero_array(req, uint8_t,
2866 SMB2_TF_HDR_SIZE);
2867 if (tf == NULL) {
2868 return NT_STATUS_NO_MEMORY;
2871 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2872 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2873 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2874 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2876 firsttf->iov_base = (void *)tf;
2877 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2880 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2881 (req->last_key.length > 0) &&
2882 (firsttf->iov_len == 0))
2884 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2885 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2888 * As we are sure the header of the last request in the
2889 * compound chain will not change, we can to sign here
2890 * with the last signing key we remembered.
2892 status = smb2_signing_sign_pdu(req->last_key,
2893 xconn->protocol,
2894 lasthdr,
2895 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2896 if (!NT_STATUS_IS_OK(status)) {
2897 return status;
2900 if (req->last_key.length > 0) {
2901 data_blob_clear_free(&req->last_key);
2904 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
2905 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
2907 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2909 if (req->current_idx < req->out.vector_count) {
2911 * We must process the remaining compound
2912 * SMB2 requests before any new incoming SMB2
2913 * requests. This is because incoming SMB2
2914 * requests may include a cancel for a
2915 * compound request we haven't processed
2916 * yet.
2918 struct tevent_immediate *im = tevent_create_immediate(req);
2919 if (!im) {
2920 return NT_STATUS_NO_MEMORY;
2923 if (req->do_signing && firsttf->iov_len == 0) {
2924 struct smbXsrv_session *x = req->session;
2925 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2928 * we need to remember the signing key
2929 * and defer the signing until
2930 * we are sure that we do not change
2931 * the header again.
2933 req->last_key = data_blob_dup_talloc(req, signing_key);
2934 if (req->last_key.data == NULL) {
2935 return NT_STATUS_NO_MEMORY;
2940 * smbd_smb2_request_dispatch() will redo the impersonation.
2941 * So we use req->xconn->client->raw_ev_ctx instead
2942 * of req->ev_ctx here.
2944 tevent_schedule_immediate(im,
2945 req->xconn->client->raw_ev_ctx,
2946 smbd_smb2_request_dispatch_immediate,
2947 req);
2948 return NT_STATUS_OK;
2951 if (req->compound_related) {
2952 req->compound_related = false;
2955 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2956 if (!ok) {
2957 return NT_STATUS_INVALID_PARAMETER_MIX;
2960 /* Set credit for these operations (zero credits if this
2961 is a final reply for an async operation). */
2962 smb2_calculate_credits(req, req);
2965 * now check if we need to sign the current response
2967 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2968 status = smb2_signing_encrypt_pdu(req->first_key,
2969 xconn->smb2.server.cipher,
2970 firsttf,
2971 req->out.vector_count - first_idx);
2972 if (!NT_STATUS_IS_OK(status)) {
2973 return status;
2975 } else if (req->do_signing) {
2976 struct smbXsrv_session *x = req->session;
2977 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2979 status = smb2_signing_sign_pdu(signing_key,
2980 xconn->protocol,
2981 outhdr,
2982 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2983 if (!NT_STATUS_IS_OK(status)) {
2984 return status;
2987 if (req->first_key.length > 0) {
2988 data_blob_clear_free(&req->first_key);
2991 if (req->preauth != NULL) {
2992 struct hc_sha512state sctx;
2993 int i;
2995 samba_SHA512_Init(&sctx);
2996 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2997 sizeof(req->preauth->sha512_value));
2998 for (i = 1; i < req->in.vector_count; i++) {
2999 samba_SHA512_Update(&sctx,
3000 req->in.vector[i].iov_base,
3001 req->in.vector[i].iov_len);
3003 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
3005 samba_SHA512_Init(&sctx);
3006 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
3007 sizeof(req->preauth->sha512_value));
3008 for (i = 1; i < req->out.vector_count; i++) {
3009 samba_SHA512_Update(&sctx,
3010 req->out.vector[i].iov_base,
3011 req->out.vector[i].iov_len);
3013 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
3015 req->preauth = NULL;
3018 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
3019 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
3020 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
3021 /* Dynamic part is NULL. Chop it off,
3022 We're going to send it via sendfile. */
3023 req->out.vector_count -= 1;
3027 * We're done with this request -
3028 * move it off the "being processed" queue.
3030 DLIST_REMOVE(xconn->smb2.requests, req);
3032 req->queue_entry.mem_ctx = req;
3033 req->queue_entry.vector = req->out.vector;
3034 req->queue_entry.count = req->out.vector_count;
3035 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry);
3036 xconn->smb2.send_queue_len++;
3038 status = smbd_smb2_flush_send_queue(xconn);
3039 if (!NT_STATUS_IS_OK(status)) {
3040 return status;
3043 return NT_STATUS_OK;
3046 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
3048 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
3049 struct tevent_immediate *im,
3050 void *private_data)
3052 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
3053 struct smbd_smb2_request);
3054 struct smbXsrv_connection *xconn = req->xconn;
3055 NTSTATUS status;
3057 TALLOC_FREE(im);
3059 if (DEBUGLEVEL >= 10) {
3060 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
3061 req->current_idx, req->in.vector_count));
3062 print_req_vectors(req);
3065 status = smbd_smb2_request_dispatch(req);
3066 if (!NT_STATUS_IS_OK(status)) {
3067 smbd_server_connection_terminate(xconn, nt_errstr(status));
3068 return;
3071 status = smbd_smb2_request_next_incoming(xconn);
3072 if (!NT_STATUS_IS_OK(status)) {
3073 smbd_server_connection_terminate(xconn, nt_errstr(status));
3074 return;
3078 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
3079 NTSTATUS status,
3080 DATA_BLOB body, DATA_BLOB *dyn,
3081 const char *location)
3083 uint8_t *outhdr;
3084 struct iovec *outbody_v;
3085 struct iovec *outdyn_v;
3086 uint32_t next_command_ofs;
3088 DEBUG(10,("smbd_smb2_request_done_ex: "
3089 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
3090 req->current_idx, nt_errstr(status), (unsigned int)body.length,
3091 dyn ? "yes": "no",
3092 (unsigned int)(dyn ? dyn->length : 0),
3093 location));
3095 if (body.length < 2) {
3096 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3099 if ((body.length % 2) != 0) {
3100 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3103 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3104 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
3105 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
3107 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
3108 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
3110 outbody_v->iov_base = (void *)body.data;
3111 outbody_v->iov_len = body.length;
3113 if (dyn) {
3114 outdyn_v->iov_base = (void *)dyn->data;
3115 outdyn_v->iov_len = dyn->length;
3116 } else {
3117 outdyn_v->iov_base = NULL;
3118 outdyn_v->iov_len = 0;
3122 * See if we need to recalculate the offset to the next response
3124 * Note that all responses may require padding (including the very last
3125 * one).
3127 if (req->out.vector_count >= (2 * SMBD_SMB2_NUM_IOV_PER_REQ)) {
3128 next_command_ofs = SMB2_HDR_BODY;
3129 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
3130 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
3133 if ((next_command_ofs % 8) != 0) {
3134 size_t pad_size = 8 - (next_command_ofs % 8);
3135 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
3137 * if the dyn buffer is empty
3138 * we can use it to add padding
3140 uint8_t *pad;
3142 pad = talloc_zero_array(req,
3143 uint8_t, pad_size);
3144 if (pad == NULL) {
3145 return smbd_smb2_request_error(req,
3146 NT_STATUS_NO_MEMORY);
3149 outdyn_v->iov_base = (void *)pad;
3150 outdyn_v->iov_len = pad_size;
3151 } else {
3153 * For now we copy the dynamic buffer
3154 * and add the padding to the new buffer
3156 size_t old_size;
3157 uint8_t *old_dyn;
3158 size_t new_size;
3159 uint8_t *new_dyn;
3161 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
3162 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
3164 new_size = old_size + pad_size;
3165 new_dyn = talloc_zero_array(req,
3166 uint8_t, new_size);
3167 if (new_dyn == NULL) {
3168 return smbd_smb2_request_error(req,
3169 NT_STATUS_NO_MEMORY);
3172 memcpy(new_dyn, old_dyn, old_size);
3173 memset(new_dyn + old_size, 0, pad_size);
3175 outdyn_v->iov_base = (void *)new_dyn;
3176 outdyn_v->iov_len = new_size;
3178 next_command_ofs += pad_size;
3181 if ((req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) >= req->out.vector_count) {
3182 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
3183 } else {
3184 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
3186 return smbd_smb2_request_reply(req);
3189 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
3190 NTSTATUS status,
3191 DATA_BLOB *info,
3192 const char *location)
3194 struct smbXsrv_connection *xconn = req->xconn;
3195 DATA_BLOB body;
3196 DATA_BLOB _dyn;
3197 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3198 size_t unread_bytes = smbd_smb2_unread_bytes(req);
3200 DBG_NOTICE("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| "
3201 "at %s\n", req->current_idx, nt_errstr(status),
3202 info ? " +info" : "", location);
3204 if (unread_bytes) {
3205 /* Recvfile error. Drain incoming socket. */
3206 size_t ret;
3208 errno = 0;
3209 ret = drain_socket(xconn->transport.sock, unread_bytes);
3210 if (ret != unread_bytes) {
3211 NTSTATUS error;
3213 if (errno == 0) {
3214 error = NT_STATUS_IO_DEVICE_ERROR;
3215 } else {
3216 error = map_nt_error_from_unix_common(errno);
3219 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
3220 "ret[%u] errno[%d] => %s\n",
3221 (unsigned)unread_bytes,
3222 (unsigned)ret, errno, nt_errstr(error)));
3223 return error;
3227 body.data = outhdr + SMB2_HDR_BODY;
3228 body.length = 8;
3229 SSVAL(body.data, 0, 9);
3231 if (info) {
3232 SIVAL(body.data, 0x04, info->length);
3233 } else {
3234 /* Allocated size of req->out.vector[i].iov_base
3235 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
3236 * 1 byte without having to do an alloc.
3238 info = &_dyn;
3239 info->data = ((uint8_t *)outhdr) +
3240 OUTVEC_ALLOC_SIZE - 1;
3241 info->length = 1;
3242 SCVAL(info->data, 0, 0);
3246 * Note: Even if there is an error, continue to process the request.
3247 * per MS-SMB2.
3250 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
3254 struct smbd_smb2_send_break_state {
3255 struct smbd_smb2_send_queue queue_entry;
3256 uint8_t nbt_hdr[NBT_HDR_SIZE];
3257 uint8_t tf[SMB2_TF_HDR_SIZE];
3258 uint8_t hdr[SMB2_HDR_BODY];
3259 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
3260 uint8_t body[1];
3263 static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
3264 struct smbXsrv_session *session,
3265 struct smbXsrv_tcon *tcon,
3266 const uint8_t *body,
3267 size_t body_len)
3269 struct smbd_smb2_send_break_state *state;
3270 bool do_encryption = false;
3271 uint64_t session_wire_id = 0;
3272 uint64_t nonce_high = 0;
3273 uint64_t nonce_low = 0;
3274 NTSTATUS status;
3275 size_t statelen;
3276 bool ok;
3278 if (session != NULL) {
3279 session_wire_id = session->global->session_wire_id;
3280 do_encryption = session->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
3281 if (tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
3282 do_encryption = true;
3286 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
3287 body_len;
3289 state = talloc_zero_size(xconn, statelen);
3290 if (state == NULL) {
3291 return NT_STATUS_NO_MEMORY;
3293 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
3295 if (do_encryption) {
3296 status = smb2_get_new_nonce(session,
3297 &nonce_high,
3298 &nonce_low);
3299 if (!NT_STATUS_IS_OK(status)) {
3300 return status;
3304 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
3305 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
3306 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
3307 SBVAL(state->tf, SMB2_TF_SESSION_ID, session_wire_id);
3309 SIVAL(state->hdr, 0, SMB2_MAGIC);
3310 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
3311 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
3312 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
3313 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
3314 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
3315 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
3316 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
3317 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
3318 SIVAL(state->hdr, SMB2_HDR_PID, 0);
3319 SIVAL(state->hdr, SMB2_HDR_TID, 0);
3320 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
3321 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
3323 state->vector[0] = (struct iovec) {
3324 .iov_base = state->nbt_hdr,
3325 .iov_len = sizeof(state->nbt_hdr)
3328 if (do_encryption) {
3329 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3330 .iov_base = state->tf,
3331 .iov_len = sizeof(state->tf)
3333 } else {
3334 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3335 .iov_base = NULL,
3336 .iov_len = 0
3340 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
3341 .iov_base = state->hdr,
3342 .iov_len = sizeof(state->hdr)
3345 memcpy(state->body, body, body_len);
3347 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
3348 .iov_base = state->body,
3349 .iov_len = body_len /* no sizeof(state->body) .. :-) */
3353 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
3356 ok = smb2_setup_nbt_length(state->vector,
3357 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
3358 if (!ok) {
3359 return NT_STATUS_INVALID_PARAMETER_MIX;
3362 if (do_encryption) {
3363 DATA_BLOB encryption_key = session->global->encryption_key;
3365 status = smb2_signing_encrypt_pdu(encryption_key,
3366 xconn->smb2.server.cipher,
3367 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
3368 SMBD_SMB2_NUM_IOV_PER_REQ);
3369 if (!NT_STATUS_IS_OK(status)) {
3370 return status;
3374 state->queue_entry.mem_ctx = state;
3375 state->queue_entry.vector = state->vector;
3376 state->queue_entry.count = ARRAY_SIZE(state->vector);
3377 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
3378 xconn->smb2.send_queue_len++;
3380 status = smbd_smb2_flush_send_queue(xconn);
3381 if (!NT_STATUS_IS_OK(status)) {
3382 return status;
3385 return NT_STATUS_OK;
3388 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_connection *xconn,
3389 struct smbXsrv_session *session,
3390 struct smbXsrv_tcon *tcon,
3391 struct smbXsrv_open *op,
3392 uint8_t oplock_level)
3394 uint8_t body[0x18];
3396 SSVAL(body, 0x00, sizeof(body));
3397 SCVAL(body, 0x02, oplock_level);
3398 SCVAL(body, 0x03, 0); /* reserved */
3399 SIVAL(body, 0x04, 0); /* reserved */
3400 SBVAL(body, 0x08, op->global->open_persistent_id);
3401 SBVAL(body, 0x10, op->global->open_volatile_id);
3403 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3406 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_connection *xconn,
3407 uint16_t new_epoch,
3408 uint32_t lease_flags,
3409 struct smb2_lease_key *lease_key,
3410 uint32_t current_lease_state,
3411 uint32_t new_lease_state)
3413 uint8_t body[0x2c];
3415 SSVAL(body, 0x00, sizeof(body));
3416 SSVAL(body, 0x02, new_epoch);
3417 SIVAL(body, 0x04, lease_flags);
3418 SBVAL(body, 0x08, lease_key->data[0]);
3419 SBVAL(body, 0x10, lease_key->data[1]);
3420 SIVAL(body, 0x18, current_lease_state);
3421 SIVAL(body, 0x1c, new_lease_state);
3422 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
3423 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
3424 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
3426 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3429 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
3431 NTSTATUS status;
3432 uint32_t flags;
3433 uint64_t file_id_persistent;
3434 uint64_t file_id_volatile;
3435 struct smbXsrv_open *op = NULL;
3436 struct files_struct *fsp = NULL;
3437 const uint8_t *body = NULL;
3440 * This is only called with a pktbuf
3441 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
3442 * bytes
3445 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
3446 /* Transform header. Cannot recvfile. */
3447 return false;
3449 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
3450 /* Not SMB2. Normal error path will cope. */
3451 return false;
3453 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
3454 /* Not SMB2. Normal error path will cope. */
3455 return false;
3457 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
3458 /* Needs to be a WRITE. */
3459 return false;
3461 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
3462 /* Chained. Cannot recvfile. */
3463 return false;
3465 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
3466 if (flags & SMB2_HDR_FLAG_CHAINED) {
3467 /* Chained. Cannot recvfile. */
3468 return false;
3470 if (flags & SMB2_HDR_FLAG_SIGNED) {
3471 /* Signed. Cannot recvfile. */
3472 return false;
3475 body = &state->pktbuf[SMB2_HDR_BODY];
3477 file_id_persistent = BVAL(body, 0x10);
3478 file_id_volatile = BVAL(body, 0x18);
3480 status = smb2srv_open_lookup(state->req->xconn,
3481 file_id_persistent,
3482 file_id_volatile,
3483 0, /* now */
3484 &op);
3485 if (!NT_STATUS_IS_OK(status)) {
3486 return false;
3489 fsp = op->compat;
3490 if (fsp == NULL) {
3491 return false;
3493 if (fsp->conn == NULL) {
3494 return false;
3497 if (IS_IPC(fsp->conn)) {
3498 return false;
3500 if (IS_PRINT(fsp->conn)) {
3501 return false;
3504 DEBUG(10,("Doing recvfile write len = %u\n",
3505 (unsigned int)(state->pktfull - state->pktlen)));
3507 return true;
3510 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
3512 struct smbd_server_connection *sconn = xconn->client->sconn;
3513 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3514 size_t max_send_queue_len;
3515 size_t cur_send_queue_len;
3517 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3519 * we're not supposed to do any io
3521 return NT_STATUS_OK;
3524 if (state->req != NULL) {
3526 * if there is already a tstream_readv_pdu
3527 * pending, we are done.
3529 return NT_STATUS_OK;
3532 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
3533 cur_send_queue_len = xconn->smb2.send_queue_len;
3535 if (cur_send_queue_len > max_send_queue_len) {
3537 * if we have a lot of requests to send,
3538 * we wait until they are on the wire until we
3539 * ask for the next request.
3541 return NT_STATUS_OK;
3544 /* ask for the next request */
3545 ZERO_STRUCTP(state);
3546 state->req = smbd_smb2_request_allocate(xconn);
3547 if (state->req == NULL) {
3548 return NT_STATUS_NO_MEMORY;
3550 state->req->sconn = sconn;
3551 state->req->xconn = xconn;
3552 state->min_recv_size = lp_min_receive_file_size();
3554 TEVENT_FD_READABLE(xconn->transport.fde);
3556 return NT_STATUS_OK;
3559 void smbd_smb2_process_negprot(struct smbXsrv_connection *xconn,
3560 uint64_t expected_seq_low,
3561 const uint8_t *inpdu, size_t size)
3563 struct smbd_server_connection *sconn = xconn->client->sconn;
3564 NTSTATUS status;
3565 struct smbd_smb2_request *req = NULL;
3567 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3568 (unsigned int)size));
3570 status = smbd_initialize_smb2(xconn, expected_seq_low);
3571 if (!NT_STATUS_IS_OK(status)) {
3572 smbd_server_connection_terminate(xconn, nt_errstr(status));
3573 return;
3576 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
3577 if (!NT_STATUS_IS_OK(status)) {
3578 smbd_server_connection_terminate(xconn, nt_errstr(status));
3579 return;
3582 status = smbd_smb2_request_validate(req);
3583 if (!NT_STATUS_IS_OK(status)) {
3584 smbd_server_connection_terminate(xconn, nt_errstr(status));
3585 return;
3588 status = smbd_smb2_request_setup_out(req);
3589 if (!NT_STATUS_IS_OK(status)) {
3590 smbd_server_connection_terminate(xconn, nt_errstr(status));
3591 return;
3594 #ifdef WITH_PROFILE
3596 * this was already counted at the SMB1 layer =>
3597 * smbd_smb2_request_dispatch() should not count it twice.
3599 if (profile_p->values.request_stats.count > 0) {
3600 profile_p->values.request_stats.count--;
3602 #endif
3603 status = smbd_smb2_request_dispatch(req);
3604 if (!NT_STATUS_IS_OK(status)) {
3605 smbd_server_connection_terminate(xconn, nt_errstr(status));
3606 return;
3609 status = smbd_smb2_request_next_incoming(xconn);
3610 if (!NT_STATUS_IS_OK(status)) {
3611 smbd_server_connection_terminate(xconn, nt_errstr(status));
3612 return;
3615 sconn->num_requests++;
3618 static int socket_error_from_errno(int ret,
3619 int sys_errno,
3620 bool *retry)
3622 *retry = false;
3624 if (ret >= 0) {
3625 return 0;
3628 if (ret != -1) {
3629 return EIO;
3632 if (sys_errno == 0) {
3633 return EIO;
3636 if (sys_errno == EINTR) {
3637 *retry = true;
3638 return sys_errno;
3641 if (sys_errno == EINPROGRESS) {
3642 *retry = true;
3643 return sys_errno;
3646 if (sys_errno == EAGAIN) {
3647 *retry = true;
3648 return sys_errno;
3651 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3652 if (sys_errno == ENOMEM) {
3653 *retry = true;
3654 return sys_errno;
3657 #ifdef EWOULDBLOCK
3658 #if EWOULDBLOCK != EAGAIN
3659 if (sys_errno == EWOULDBLOCK) {
3660 *retry = true;
3661 return sys_errno;
3663 #endif
3664 #endif
3666 return sys_errno;
3669 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3671 int ret;
3672 int err;
3673 bool retry;
3674 NTSTATUS status;
3676 if (xconn->smb2.send_queue == NULL) {
3677 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3678 return NT_STATUS_OK;
3681 while (xconn->smb2.send_queue != NULL) {
3682 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3683 bool ok;
3685 if (e->sendfile_header != NULL) {
3686 size_t size = 0;
3687 size_t i = 0;
3688 uint8_t *buf;
3690 status = NT_STATUS_INTERNAL_ERROR;
3692 for (i=0; i < e->count; i++) {
3693 size += e->vector[i].iov_len;
3696 if (size <= e->sendfile_header->length) {
3697 buf = e->sendfile_header->data;
3698 } else {
3699 buf = talloc_array(e->mem_ctx, uint8_t, size);
3700 if (buf == NULL) {
3701 return NT_STATUS_NO_MEMORY;
3705 size = 0;
3706 for (i=0; i < e->count; i++) {
3707 memcpy(buf+size,
3708 e->vector[i].iov_base,
3709 e->vector[i].iov_len);
3710 size += e->vector[i].iov_len;
3713 e->sendfile_header->data = buf;
3714 e->sendfile_header->length = size;
3715 e->sendfile_status = &status;
3716 e->count = 0;
3718 xconn->smb2.send_queue_len--;
3719 DLIST_REMOVE(xconn->smb2.send_queue, e);
3721 * This triggers the sendfile path via
3722 * the destructor.
3724 talloc_free(e->mem_ctx);
3726 if (!NT_STATUS_IS_OK(status)) {
3727 return status;
3729 continue;
3732 ret = writev(xconn->transport.sock, e->vector, e->count);
3733 if (ret == 0) {
3734 /* propagate end of file */
3735 return NT_STATUS_INTERNAL_ERROR;
3737 err = socket_error_from_errno(ret, errno, &retry);
3738 if (retry) {
3739 /* retry later */
3740 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3741 return NT_STATUS_OK;
3743 if (err != 0) {
3744 return map_nt_error_from_unix_common(err);
3747 ok = iov_advance(&e->vector, &e->count, ret);
3748 if (!ok) {
3749 return NT_STATUS_INTERNAL_ERROR;
3752 if (e->count > 0) {
3753 /* we have more to write */
3754 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3755 return NT_STATUS_OK;
3758 xconn->smb2.send_queue_len--;
3759 DLIST_REMOVE(xconn->smb2.send_queue, e);
3760 talloc_free(e->mem_ctx);
3764 * Restart reads if we were blocked on
3765 * draining the send queue.
3768 status = smbd_smb2_request_next_incoming(xconn);
3769 if (!NT_STATUS_IS_OK(status)) {
3770 return status;
3773 return NT_STATUS_OK;
3776 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3777 uint16_t fde_flags)
3779 struct smbd_server_connection *sconn = xconn->client->sconn;
3780 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3781 struct smbd_smb2_request *req = NULL;
3782 size_t min_recvfile_size = UINT32_MAX;
3783 int ret;
3784 int err;
3785 bool retry;
3786 NTSTATUS status;
3787 NTTIME now;
3789 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3791 * we're not supposed to do any io
3793 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3794 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3795 return NT_STATUS_OK;
3798 if (fde_flags & TEVENT_FD_WRITE) {
3799 status = smbd_smb2_flush_send_queue(xconn);
3800 if (!NT_STATUS_IS_OK(status)) {
3801 return status;
3805 if (!(fde_flags & TEVENT_FD_READ)) {
3806 return NT_STATUS_OK;
3809 if (state->req == NULL) {
3810 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3811 return NT_STATUS_OK;
3814 again:
3815 if (!state->hdr.done) {
3816 state->hdr.done = true;
3818 state->vector.iov_base = (void *)state->hdr.nbt;
3819 state->vector.iov_len = NBT_HDR_SIZE;
3822 ret = readv(xconn->transport.sock, &state->vector, 1);
3823 if (ret == 0) {
3824 /* propagate end of file */
3825 return NT_STATUS_END_OF_FILE;
3827 err = socket_error_from_errno(ret, errno, &retry);
3828 if (retry) {
3829 /* retry later */
3830 TEVENT_FD_READABLE(xconn->transport.fde);
3831 return NT_STATUS_OK;
3833 if (err != 0) {
3834 return map_nt_error_from_unix_common(err);
3837 if (ret < state->vector.iov_len) {
3838 uint8_t *base;
3839 base = (uint8_t *)state->vector.iov_base;
3840 base += ret;
3841 state->vector.iov_base = (void *)base;
3842 state->vector.iov_len -= ret;
3843 /* we have more to read */
3844 TEVENT_FD_READABLE(xconn->transport.fde);
3845 return NT_STATUS_OK;
3848 if (state->pktlen > 0) {
3849 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3851 * Not a possible receivefile write.
3852 * Read the rest of the data.
3854 state->doing_receivefile = false;
3856 state->pktbuf = talloc_realloc(state->req,
3857 state->pktbuf,
3858 uint8_t,
3859 state->pktfull);
3860 if (state->pktbuf == NULL) {
3861 return NT_STATUS_NO_MEMORY;
3864 state->vector.iov_base = (void *)(state->pktbuf +
3865 state->pktlen);
3866 state->vector.iov_len = (state->pktfull -
3867 state->pktlen);
3869 state->pktlen = state->pktfull;
3870 goto again;
3874 * Either this is a receivefile write so we've
3875 * done a short read, or if not we have all the data.
3877 goto got_full;
3881 * Now we analyze the NBT header
3883 if (state->hdr.nbt[0] != 0x00) {
3884 state->min_recv_size = 0;
3886 state->pktfull = smb2_len(state->hdr.nbt);
3887 if (state->pktfull == 0) {
3888 goto got_full;
3891 if (state->min_recv_size != 0) {
3892 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3893 min_recvfile_size += state->min_recv_size;
3896 if (state->pktfull > min_recvfile_size) {
3898 * Might be a receivefile write. Read the SMB2 HEADER +
3899 * SMB2_WRITE header first. Set 'doing_receivefile'
3900 * as we're *attempting* receivefile write. If this
3901 * turns out not to be a SMB2_WRITE request or otherwise
3902 * not suitable then we'll just read the rest of the data
3903 * the next time this function is called.
3905 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3906 state->doing_receivefile = true;
3907 } else {
3908 state->pktlen = state->pktfull;
3911 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3912 if (state->pktbuf == NULL) {
3913 return NT_STATUS_NO_MEMORY;
3916 state->vector.iov_base = (void *)state->pktbuf;
3917 state->vector.iov_len = state->pktlen;
3919 goto again;
3921 got_full:
3923 if (state->hdr.nbt[0] != 0x00) {
3924 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3925 state->hdr.nbt[0]));
3927 req = state->req;
3928 ZERO_STRUCTP(state);
3929 state->req = req;
3930 state->min_recv_size = lp_min_receive_file_size();
3931 req = NULL;
3932 goto again;
3935 req = state->req;
3936 state->req = NULL;
3938 req->request_time = timeval_current();
3939 now = timeval_to_nttime(&req->request_time);
3941 status = smbd_smb2_inbuf_parse_compound(xconn,
3942 now,
3943 state->pktbuf,
3944 state->pktlen,
3945 req,
3946 &req->in.vector,
3947 &req->in.vector_count);
3948 if (!NT_STATUS_IS_OK(status)) {
3949 return status;
3952 if (state->doing_receivefile) {
3953 req->smb1req = talloc_zero(req, struct smb_request);
3954 if (req->smb1req == NULL) {
3955 return NT_STATUS_NO_MEMORY;
3957 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3960 ZERO_STRUCTP(state);
3962 req->current_idx = 1;
3964 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3965 req->current_idx, req->in.vector_count));
3967 status = smbd_smb2_request_validate(req);
3968 if (!NT_STATUS_IS_OK(status)) {
3969 return status;
3972 status = smbd_smb2_request_setup_out(req);
3973 if (!NT_STATUS_IS_OK(status)) {
3974 return status;
3977 status = smbd_smb2_request_dispatch(req);
3978 if (!NT_STATUS_IS_OK(status)) {
3979 return status;
3982 sconn->num_requests++;
3984 /* The timeout_processing function isn't run nearly
3985 often enough to implement 'max log size' without
3986 overrunning the size of the file by many megabytes.
3987 This is especially true if we are running at debug
3988 level 10. Checking every 50 SMB2s is a nice
3989 tradeoff of performance vs log file size overrun. */
3991 if ((sconn->num_requests % 50) == 0 &&
3992 need_to_check_log_size()) {
3993 change_to_root_user();
3994 check_log_size();
3997 status = smbd_smb2_request_next_incoming(xconn);
3998 if (!NT_STATUS_IS_OK(status)) {
3999 return status;
4002 return NT_STATUS_OK;
4005 static void smbd_smb2_connection_handler(struct tevent_context *ev,
4006 struct tevent_fd *fde,
4007 uint16_t flags,
4008 void *private_data)
4010 struct smbXsrv_connection *xconn =
4011 talloc_get_type_abort(private_data,
4012 struct smbXsrv_connection);
4013 NTSTATUS status;
4015 status = smbd_smb2_io_handler(xconn, flags);
4016 if (!NT_STATUS_IS_OK(status)) {
4017 smbd_server_connection_terminate(xconn, nt_errstr(status));
4018 return;