smb2_server: allow smbd_smb2_request_pending_queue(0) to avoid STATUS_PENDING
[Samba.git] / source3 / smbd / smb2_server.c
blob174b906f8b6c5783fe3ec4e6f9aebd9fc0a9fd66
1 /*
2 Unix SMB/CIFS implementation.
3 Core SMB2 server
5 Copyright (C) Stefan Metzmacher 2009
6 Copyright (C) Jeremy Allison 2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../libcli/smb/smb_common.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "../lib/util/tevent_ntstatus.h"
28 #include "smbprofile.h"
29 #include "../lib/util/bitmap.h"
30 #include "../librpc/gen_ndr/krb5pac.h"
31 #include "lib/util/iov_buf.h"
32 #include "auth.h"
33 #include "lib/crypto/sha512.h"
35 #undef DBGC_CLASS
36 #define DBGC_CLASS DBGC_SMB2
38 static void smbd_smb2_connection_handler(struct tevent_context *ev,
39 struct tevent_fd *fde,
40 uint16_t flags,
41 void *private_data);
42 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn);
44 static const struct smbd_smb2_dispatch_table {
45 uint16_t opcode;
46 const char *name;
47 bool need_session;
48 bool need_tcon;
49 bool as_root;
50 uint16_t fileid_ofs;
51 bool allow_invalid_fileid;
52 bool modify;
53 } smbd_smb2_table[] = {
54 #define _OP(o) .opcode = o, .name = #o
56 _OP(SMB2_OP_NEGPROT),
57 .as_root = true,
58 },{
59 _OP(SMB2_OP_SESSSETUP),
60 .as_root = true,
61 },{
62 _OP(SMB2_OP_LOGOFF),
63 .need_session = true,
64 .as_root = true,
65 },{
66 _OP(SMB2_OP_TCON),
67 .need_session = true,
69 * This call needs to be run as root.
71 * smbd_smb2_request_process_tcon()
72 * calls make_connection_snum(), which will call
73 * change_to_user(), when needed.
75 .as_root = true,
76 },{
77 _OP(SMB2_OP_TDIS),
78 .need_session = true,
79 .need_tcon = true,
80 .as_root = true,
81 },{
82 _OP(SMB2_OP_CREATE),
83 .need_session = true,
84 .need_tcon = true,
85 },{
86 _OP(SMB2_OP_CLOSE),
87 .need_session = true,
88 .need_tcon = true,
89 .fileid_ofs = 0x08,
90 },{
91 _OP(SMB2_OP_FLUSH),
92 .need_session = true,
93 .need_tcon = true,
94 .fileid_ofs = 0x08,
95 },{
96 _OP(SMB2_OP_READ),
97 .need_session = true,
98 .need_tcon = true,
99 .fileid_ofs = 0x10,
101 _OP(SMB2_OP_WRITE),
102 .need_session = true,
103 .need_tcon = true,
104 .fileid_ofs = 0x10,
105 .modify = true,
107 _OP(SMB2_OP_LOCK),
108 .need_session = true,
109 .need_tcon = true,
110 .fileid_ofs = 0x08,
112 _OP(SMB2_OP_IOCTL),
113 .need_session = true,
114 .need_tcon = true,
115 .fileid_ofs = 0x08,
116 .allow_invalid_fileid = true,
117 .modify = true,
119 _OP(SMB2_OP_CANCEL),
120 .as_root = true,
122 _OP(SMB2_OP_KEEPALIVE),
123 .as_root = true,
125 _OP(SMB2_OP_QUERY_DIRECTORY),
126 .need_session = true,
127 .need_tcon = true,
128 .fileid_ofs = 0x08,
130 _OP(SMB2_OP_NOTIFY),
131 .need_session = true,
132 .need_tcon = true,
133 .fileid_ofs = 0x08,
135 _OP(SMB2_OP_GETINFO),
136 .need_session = true,
137 .need_tcon = true,
138 .fileid_ofs = 0x18,
140 _OP(SMB2_OP_SETINFO),
141 .need_session = true,
142 .need_tcon = true,
143 .fileid_ofs = 0x10,
144 .modify = true,
146 _OP(SMB2_OP_BREAK),
147 .need_session = true,
148 .need_tcon = true,
150 * we do not set
151 * .fileid_ofs here
152 * as LEASE breaks does not
153 * have a file id
158 const char *smb2_opcode_name(uint16_t opcode)
160 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
161 return "Bad SMB2 opcode";
163 return smbd_smb2_table[opcode].name;
166 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
168 const struct smbd_smb2_dispatch_table *ret = NULL;
170 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
171 return NULL;
174 ret = &smbd_smb2_table[opcode];
176 SMB_ASSERT(ret->opcode == opcode);
178 return ret;
181 static void print_req_vectors(const struct smbd_smb2_request *req)
183 int i;
185 for (i = 0; i < req->in.vector_count; i++) {
186 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
187 (unsigned int)i,
188 (unsigned int)req->in.vector[i].iov_len);
190 for (i = 0; i < req->out.vector_count; i++) {
191 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
192 (unsigned int)i,
193 (unsigned int)req->out.vector[i].iov_len);
197 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
199 if (size < (4 + SMB2_HDR_BODY)) {
200 return false;
203 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
204 return false;
207 return true;
210 bool smbd_smb2_is_compound(const struct smbd_smb2_request *req)
212 return req->in.vector_count >= (2*SMBD_SMB2_NUM_IOV_PER_REQ);
215 static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn,
216 uint64_t expected_seq_low)
218 TALLOC_FREE(xconn->transport.fde);
220 xconn->smb2.credits.seq_low = expected_seq_low;
221 xconn->smb2.credits.seq_range = 1;
222 xconn->smb2.credits.granted = 1;
223 xconn->smb2.credits.max = lp_smb2_max_credits();
224 xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
225 xconn->smb2.credits.max);
226 if (xconn->smb2.credits.bitmap == NULL) {
227 return NT_STATUS_NO_MEMORY;
230 xconn->transport.fde = tevent_add_fd(
231 xconn->client->raw_ev_ctx,
232 xconn,
233 xconn->transport.sock,
234 TEVENT_FD_READ,
235 smbd_smb2_connection_handler,
236 xconn);
237 if (xconn->transport.fde == NULL) {
238 return NT_STATUS_NO_MEMORY;
241 /* Ensure child is set to non-blocking mode */
242 set_blocking(xconn->transport.sock, false);
243 return NT_STATUS_OK;
246 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
247 #define _smb2_setlen(_buf,len) do { \
248 uint8_t *buf = (uint8_t *)_buf; \
249 buf[0] = 0; \
250 buf[1] = ((len)&0xFF0000)>>16; \
251 buf[2] = ((len)&0xFF00)>>8; \
252 buf[3] = (len)&0xFF; \
253 } while (0)
255 static bool smb2_setup_nbt_length(struct iovec *vector, int count)
257 ssize_t len;
259 if (count == 0) {
260 return false;
263 len = iov_buflen(vector+1, count-1);
265 if ((len == -1) || (len > 0xFFFFFF)) {
266 return false;
269 _smb2_setlen(vector[0].iov_base, len);
270 return true;
273 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
275 if (req->first_key.length > 0) {
276 data_blob_clear_free(&req->first_key);
278 if (req->last_key.length > 0) {
279 data_blob_clear_free(&req->last_key);
281 return 0;
284 void smb2_request_set_async_internal(struct smbd_smb2_request *req,
285 bool async_internal)
287 req->async_internal = async_internal;
290 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
292 TALLOC_CTX *mem_pool;
293 struct smbd_smb2_request *req;
295 #if 0
296 /* Enable this to find subtle valgrind errors. */
297 mem_pool = talloc_init("smbd_smb2_request_allocate");
298 #else
299 mem_pool = talloc_tos();
300 #endif
301 if (mem_pool == NULL) {
302 return NULL;
305 req = talloc_zero(mem_pool, struct smbd_smb2_request);
306 if (req == NULL) {
307 talloc_free(mem_pool);
308 return NULL;
310 talloc_reparent(mem_pool, mem_ctx, req);
311 #if 0
312 TALLOC_FREE(mem_pool);
313 #endif
315 req->last_session_id = UINT64_MAX;
316 req->last_tid = UINT32_MAX;
318 talloc_set_destructor(req, smbd_smb2_request_destructor);
320 return req;
323 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
324 NTTIME now,
325 uint8_t *buf,
326 size_t buflen,
327 struct smbd_smb2_request *req,
328 struct iovec **piov,
329 int *pnum_iov)
331 TALLOC_CTX *mem_ctx = req;
332 struct iovec *iov;
333 int num_iov = 1;
334 size_t taken = 0;
335 uint8_t *first_hdr = buf;
336 size_t verified_buflen = 0;
337 uint8_t *tf = NULL;
338 size_t tf_len = 0;
341 * Note: index '0' is reserved for the transport protocol
343 iov = req->in._vector;
345 while (taken < buflen) {
346 size_t len = buflen - taken;
347 uint8_t *hdr = first_hdr + taken;
348 struct iovec *cur;
349 size_t full_size;
350 size_t next_command_ofs;
351 uint16_t body_size;
352 uint8_t *body = NULL;
353 uint32_t dyn_size;
354 uint8_t *dyn = NULL;
355 struct iovec *iov_alloc = NULL;
357 if (iov != req->in._vector) {
358 iov_alloc = iov;
361 if (verified_buflen > taken) {
362 len = verified_buflen - taken;
363 } else {
364 tf = NULL;
365 tf_len = 0;
368 if (len < 4) {
369 DEBUG(10, ("%d bytes left, expected at least %d\n",
370 (int)len, 4));
371 goto inval;
373 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
374 struct smbXsrv_session *s = NULL;
375 uint64_t uid;
376 struct iovec tf_iov[2];
377 NTSTATUS status;
378 size_t enc_len;
380 if (xconn->protocol < PROTOCOL_SMB2_24) {
381 DEBUG(10, ("Got SMB2_TRANSFORM header, "
382 "but dialect[0x%04X] is used\n",
383 xconn->smb2.server.dialect));
384 goto inval;
387 if (xconn->smb2.server.cipher == 0) {
388 DEBUG(10, ("Got SMB2_TRANSFORM header, "
389 "but not negotiated "
390 "client[0x%08X] server[0x%08X]\n",
391 xconn->smb2.client.capabilities,
392 xconn->smb2.server.capabilities));
393 goto inval;
396 if (len < SMB2_TF_HDR_SIZE) {
397 DEBUG(1, ("%d bytes left, expected at least %d\n",
398 (int)len, SMB2_TF_HDR_SIZE));
399 goto inval;
401 tf = hdr;
402 tf_len = SMB2_TF_HDR_SIZE;
403 taken += tf_len;
405 hdr = first_hdr + taken;
406 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
407 uid = BVAL(tf, SMB2_TF_SESSION_ID);
409 if (len < SMB2_TF_HDR_SIZE + enc_len) {
410 DEBUG(1, ("%d bytes left, expected at least %d\n",
411 (int)len,
412 (int)(SMB2_TF_HDR_SIZE + enc_len)));
413 goto inval;
416 status = smb2srv_session_lookup_conn(xconn, uid, now,
417 &s);
418 if (s == NULL) {
419 DEBUG(1, ("invalid session[%llu] in "
420 "SMB2_TRANSFORM header\n",
421 (unsigned long long)uid));
422 TALLOC_FREE(iov_alloc);
423 return NT_STATUS_USER_SESSION_DELETED;
426 tf_iov[0].iov_base = (void *)tf;
427 tf_iov[0].iov_len = tf_len;
428 tf_iov[1].iov_base = (void *)hdr;
429 tf_iov[1].iov_len = enc_len;
431 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
432 xconn->smb2.server.cipher,
433 tf_iov, 2);
434 if (!NT_STATUS_IS_OK(status)) {
435 TALLOC_FREE(iov_alloc);
436 return status;
439 verified_buflen = taken + enc_len;
440 len = enc_len;
444 * We need the header plus the body length field
447 if (len < SMB2_HDR_BODY + 2) {
448 DEBUG(10, ("%d bytes left, expected at least %d\n",
449 (int)len, SMB2_HDR_BODY));
450 goto inval;
452 if (IVAL(hdr, 0) != SMB2_MAGIC) {
453 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
454 IVAL(hdr, 0)));
455 goto inval;
457 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
458 DEBUG(10, ("Got HDR len %d, expected %d\n",
459 SVAL(hdr, 4), SMB2_HDR_BODY));
460 goto inval;
463 full_size = len;
464 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
465 body_size = SVAL(hdr, SMB2_HDR_BODY);
467 if (next_command_ofs != 0) {
468 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
469 goto inval;
471 if (next_command_ofs > full_size) {
472 goto inval;
474 full_size = next_command_ofs;
476 if (body_size < 2) {
477 goto inval;
479 body_size &= 0xfffe;
481 if (body_size > (full_size - SMB2_HDR_BODY)) {
483 * let the caller handle the error
485 body_size = full_size - SMB2_HDR_BODY;
487 body = hdr + SMB2_HDR_BODY;
488 dyn = body + body_size;
489 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
491 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
492 struct iovec *iov_tmp = NULL;
494 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
495 struct iovec,
496 num_iov +
497 SMBD_SMB2_NUM_IOV_PER_REQ);
498 if (iov_tmp == NULL) {
499 TALLOC_FREE(iov_alloc);
500 return NT_STATUS_NO_MEMORY;
503 if (iov_alloc == NULL) {
504 memcpy(iov_tmp,
505 req->in._vector,
506 sizeof(req->in._vector));
509 iov = iov_tmp;
511 cur = &iov[num_iov];
512 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
514 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
515 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
516 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
517 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
518 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
519 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
520 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
521 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
523 taken += full_size;
526 *piov = iov;
527 *pnum_iov = num_iov;
528 return NT_STATUS_OK;
530 inval:
531 if (iov != req->in._vector) {
532 TALLOC_FREE(iov);
534 return NT_STATUS_INVALID_PARAMETER;
537 static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
538 const uint8_t *_inpdu, size_t size,
539 struct smbd_smb2_request **_req)
541 struct smbd_server_connection *sconn = xconn->client->sconn;
542 struct smbd_smb2_request *req;
543 uint32_t protocol_version;
544 uint8_t *inpdu = NULL;
545 const uint8_t *inhdr = NULL;
546 uint16_t cmd;
547 uint32_t next_command_ofs;
548 NTSTATUS status;
549 NTTIME now;
551 if (size < (SMB2_HDR_BODY + 2)) {
552 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
553 return NT_STATUS_INVALID_PARAMETER;
556 inhdr = _inpdu;
558 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
559 if (protocol_version != SMB2_MAGIC) {
560 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
561 protocol_version));
562 return NT_STATUS_INVALID_PARAMETER;
565 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
566 if (cmd != SMB2_OP_NEGPROT) {
567 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
568 cmd));
569 return NT_STATUS_INVALID_PARAMETER;
572 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
573 if (next_command_ofs != 0) {
574 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
575 next_command_ofs));
576 return NT_STATUS_INVALID_PARAMETER;
579 req = smbd_smb2_request_allocate(xconn);
580 if (req == NULL) {
581 return NT_STATUS_NO_MEMORY;
583 req->sconn = sconn;
584 req->xconn = xconn;
586 inpdu = talloc_memdup(req, _inpdu, size);
587 if (inpdu == NULL) {
588 return NT_STATUS_NO_MEMORY;
591 req->request_time = timeval_current();
592 now = timeval_to_nttime(&req->request_time);
594 status = smbd_smb2_inbuf_parse_compound(xconn,
595 now,
596 inpdu,
597 size,
598 req, &req->in.vector,
599 &req->in.vector_count);
600 if (!NT_STATUS_IS_OK(status)) {
601 TALLOC_FREE(req);
602 return status;
605 req->current_idx = 1;
607 *_req = req;
608 return NT_STATUS_OK;
611 static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
612 uint64_t message_id, uint64_t seq_id)
614 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
615 unsigned int offset;
616 uint64_t seq_tmp;
618 seq_tmp = xconn->smb2.credits.seq_low;
619 if (seq_id < seq_tmp) {
620 DBGC_ERR(DBGC_SMB2_CREDITS,
621 "smb2_validate_sequence_number: bad message_id "
622 "%llu (sequence id %llu) "
623 "(granted = %u, low = %llu, range = %u)\n",
624 (unsigned long long)message_id,
625 (unsigned long long)seq_id,
626 (unsigned int)xconn->smb2.credits.granted,
627 (unsigned long long)xconn->smb2.credits.seq_low,
628 (unsigned int)xconn->smb2.credits.seq_range);
629 return false;
632 seq_tmp += xconn->smb2.credits.seq_range;
633 if (seq_id >= seq_tmp) {
634 DBGC_ERR(DBGC_SMB2_CREDITS,
635 "smb2_validate_sequence_number: bad message_id "
636 "%llu (sequence id %llu) "
637 "(granted = %u, low = %llu, range = %u)\n",
638 (unsigned long long)message_id,
639 (unsigned long long)seq_id,
640 (unsigned int)xconn->smb2.credits.granted,
641 (unsigned long long)xconn->smb2.credits.seq_low,
642 (unsigned int)xconn->smb2.credits.seq_range);
643 return false;
646 offset = seq_id % xconn->smb2.credits.max;
648 if (bitmap_query(credits_bm, offset)) {
649 DBGC_ERR(DBGC_SMB2_CREDITS,
650 "smb2_validate_sequence_number: duplicate message_id "
651 "%llu (sequence id %llu) "
652 "(granted = %u, low = %llu, range = %u) "
653 "(bm offset %u)\n",
654 (unsigned long long)message_id,
655 (unsigned long long)seq_id,
656 (unsigned int)xconn->smb2.credits.granted,
657 (unsigned long long)xconn->smb2.credits.seq_low,
658 (unsigned int)xconn->smb2.credits.seq_range,
659 offset);
660 return false;
663 /* Mark the message_ids as seen in the bitmap. */
664 bitmap_set(credits_bm, offset);
666 if (seq_id != xconn->smb2.credits.seq_low) {
667 return true;
671 * Move the window forward by all the message_id's
672 * already seen.
674 while (bitmap_query(credits_bm, offset)) {
675 DBGC_DEBUG(DBGC_SMB2_CREDITS,
676 "smb2_validate_sequence_number: clearing "
677 "id %llu (position %u) from bitmap\n",
678 (unsigned long long)(xconn->smb2.credits.seq_low),
679 offset);
680 bitmap_clear(credits_bm, offset);
682 xconn->smb2.credits.seq_low += 1;
683 xconn->smb2.credits.seq_range -= 1;
684 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
687 return true;
690 static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
691 const uint8_t *inhdr)
693 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
694 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
695 uint16_t credit_charge = 1;
696 uint64_t i;
698 if (opcode == SMB2_OP_CANCEL) {
699 /* SMB2_CANCEL requests by definition resend messageids. */
700 return true;
703 if (xconn->smb2.credits.multicredit) {
704 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
705 credit_charge = MAX(credit_charge, 1);
708 DEBUGC(11,
709 DBGC_SMB2_CREDITS,
710 ("smb2_validate_message_id: mid %llu (charge %llu), "
711 "credits_granted %llu, "
712 "seqnum low/range: %llu/%llu\n",
713 (unsigned long long) message_id,
714 (unsigned long long) credit_charge,
715 (unsigned long long) xconn->smb2.credits.granted,
716 (unsigned long long) xconn->smb2.credits.seq_low,
717 (unsigned long long) xconn->smb2.credits.seq_range));
719 if (xconn->smb2.credits.granted < credit_charge) {
720 DBGC_ERR(DBGC_SMB2_CREDITS,
721 "smb2_validate_message_id: client used more "
722 "credits than granted, mid %llu, charge %llu, "
723 "credits_granted %llu, "
724 "seqnum low/range: %llu/%llu\n",
725 (unsigned long long) message_id,
726 (unsigned long long) credit_charge,
727 (unsigned long long) xconn->smb2.credits.granted,
728 (unsigned long long) xconn->smb2.credits.seq_low,
729 (unsigned long long) xconn->smb2.credits.seq_range);
730 return false;
734 * now check the message ids
736 * for multi-credit requests we need to check all current mid plus
737 * the implicit mids caused by the credit charge
738 * e.g. current mid = 15, charge 5 => mark 15-19 as used
741 for (i = 0; i <= (credit_charge-1); i++) {
742 uint64_t id = message_id + i;
743 bool ok;
745 DEBUGC(11,
746 DBGC_SMB2_CREDITS,
747 ("Iterating mid %llu charge %u (sequence %llu)\n",
748 (unsigned long long)message_id,
749 credit_charge,
750 (unsigned long long)id));
752 ok = smb2_validate_sequence_number(xconn, message_id, id);
753 if (!ok) {
754 return false;
758 /* substract used credits */
759 xconn->smb2.credits.granted -= credit_charge;
761 return true;
764 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
766 int count;
767 int idx;
769 count = req->in.vector_count;
771 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
772 /* It's not a SMB2 request */
773 return NT_STATUS_INVALID_PARAMETER;
776 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
777 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
778 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
779 const uint8_t *inhdr = NULL;
781 if (hdr->iov_len != SMB2_HDR_BODY) {
782 return NT_STATUS_INVALID_PARAMETER;
785 if (body->iov_len < 2) {
786 return NT_STATUS_INVALID_PARAMETER;
789 inhdr = (const uint8_t *)hdr->iov_base;
791 /* Check the SMB2 header */
792 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
793 return NT_STATUS_INVALID_PARAMETER;
796 if (!smb2_validate_message_id(req->xconn, inhdr)) {
797 return NT_STATUS_INVALID_PARAMETER;
801 return NT_STATUS_OK;
804 static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
805 const struct iovec *in_vector,
806 struct iovec *out_vector)
808 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
809 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
810 uint16_t credit_charge = 1;
811 uint16_t credits_requested;
812 uint32_t out_flags;
813 uint16_t cmd;
814 NTSTATUS out_status;
815 uint16_t credits_granted = 0;
816 uint64_t credits_possible;
817 uint16_t current_max_credits;
820 * first we grant only 1/16th of the max range.
822 * Windows also starts with the 1/16th and then grants
823 * more later. I was only able to trigger higher
824 * values, when using a very high credit charge.
826 * TODO: scale up depending on load, free memory
827 * or other stuff.
828 * Maybe also on the relationship between number
829 * of requests and the used sequence number.
830 * Which means we would grant more credits
831 * for client which use multi credit requests.
833 current_max_credits = xconn->smb2.credits.max / 16;
834 current_max_credits = MAX(current_max_credits, 1);
836 if (xconn->smb2.credits.multicredit) {
837 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
838 credit_charge = MAX(credit_charge, 1);
841 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
842 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
843 credits_requested = MAX(credits_requested, 1);
844 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
845 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
847 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
849 if (xconn->smb2.credits.max < credit_charge) {
850 smbd_server_connection_terminate(xconn,
851 "client error: credit charge > max credits\n");
852 return;
855 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
857 * In case we already send an async interim
858 * response, we should not grant
859 * credits on the final response.
861 credits_granted = 0;
862 } else {
863 uint16_t additional_possible =
864 xconn->smb2.credits.max - credit_charge;
865 uint16_t additional_max = 0;
866 uint16_t additional_credits = credits_requested - 1;
868 switch (cmd) {
869 case SMB2_OP_NEGPROT:
870 break;
871 case SMB2_OP_SESSSETUP:
873 * Windows 2012 RC1 starts to grant
874 * additional credits
875 * with a successful session setup
877 if (NT_STATUS_IS_OK(out_status)) {
878 additional_max = 32;
880 break;
881 default:
883 * We match windows and only grant additional credits
884 * in chunks of 32.
886 additional_max = 32;
887 break;
890 additional_max = MIN(additional_max, additional_possible);
891 additional_credits = MIN(additional_credits, additional_max);
893 credits_granted = credit_charge + additional_credits;
897 * sequence numbers should not wrap
899 * 1. calculate the possible credits until
900 * the sequence numbers start to wrap on 64-bit.
902 * 2. UINT64_MAX is used for Break Notifications.
904 * 2. truncate the possible credits to the maximum
905 * credits we want to grant to the client in total.
907 * 3. remove the range we'll already granted to the client
908 * this makes sure the client consumes the lowest sequence
909 * number, before we can grant additional credits.
911 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
912 if (credits_possible > 0) {
913 /* remove UINT64_MAX */
914 credits_possible -= 1;
916 credits_possible = MIN(credits_possible, current_max_credits);
917 credits_possible -= xconn->smb2.credits.seq_range;
919 credits_granted = MIN(credits_granted, credits_possible);
921 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
922 xconn->smb2.credits.granted += credits_granted;
923 xconn->smb2.credits.seq_range += credits_granted;
925 DBGC_DEBUG(DBGC_SMB2_CREDITS,
926 "smb2_set_operation_credit: requested %u, charge %u, "
927 "granted %u, current possible/max %u/%u, "
928 "total granted/max/low/range %u/%u/%llu/%u\n",
929 (unsigned int)credits_requested,
930 (unsigned int)credit_charge,
931 (unsigned int)credits_granted,
932 (unsigned int)credits_possible,
933 (unsigned int)current_max_credits,
934 (unsigned int)xconn->smb2.credits.granted,
935 (unsigned int)xconn->smb2.credits.max,
936 (unsigned long long)xconn->smb2.credits.seq_low,
937 (unsigned int)xconn->smb2.credits.seq_range);
940 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
941 struct smbd_smb2_request *outreq)
943 int count, idx;
944 uint16_t total_credits = 0;
946 count = outreq->out.vector_count;
948 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
949 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
950 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
951 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
953 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
955 /* To match Windows, count up what we
956 just granted. */
957 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
958 /* Set to zero in all but the last reply. */
959 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
960 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
961 } else {
962 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
967 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
969 if (req->current_idx <= 1) {
970 if (size <= sizeof(req->out._body)) {
971 return data_blob_const(req->out._body, size);
975 return data_blob_talloc(req, NULL, size);
978 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
980 struct smbXsrv_connection *xconn = req->xconn;
981 TALLOC_CTX *mem_ctx;
982 struct iovec *vector;
983 int count;
984 int idx;
985 bool ok;
987 count = req->in.vector_count;
988 if (count <= ARRAY_SIZE(req->out._vector)) {
989 mem_ctx = req;
990 vector = req->out._vector;
991 } else {
992 vector = talloc_zero_array(req, struct iovec, count);
993 if (vector == NULL) {
994 return NT_STATUS_NO_MEMORY;
996 mem_ctx = vector;
999 vector[0].iov_base = req->out.nbt_hdr;
1000 vector[0].iov_len = 4;
1001 SIVAL(req->out.nbt_hdr, 0, 0);
1003 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
1004 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
1005 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
1006 uint8_t *outhdr = NULL;
1007 uint8_t *outbody = NULL;
1008 uint32_t next_command_ofs = 0;
1009 struct iovec *current = &vector[idx];
1011 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
1012 /* we have a next command -
1013 * setup for the error case. */
1014 next_command_ofs = SMB2_HDR_BODY + 9;
1017 if (idx == 1) {
1018 outhdr = req->out._hdr;
1019 } else {
1020 outhdr = talloc_zero_array(mem_ctx, uint8_t,
1021 OUTVEC_ALLOC_SIZE);
1022 if (outhdr == NULL) {
1023 return NT_STATUS_NO_MEMORY;
1027 outbody = outhdr + SMB2_HDR_BODY;
1030 * SMBD_SMB2_TF_IOV_OFS might be used later
1032 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1033 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1035 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
1036 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1038 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1039 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1041 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1042 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1044 /* setup the SMB2 header */
1045 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1046 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1047 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1048 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1049 SIVAL(outhdr, SMB2_HDR_STATUS,
1050 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1051 SSVAL(outhdr, SMB2_HDR_OPCODE,
1052 SVAL(inhdr, SMB2_HDR_OPCODE));
1053 SIVAL(outhdr, SMB2_HDR_FLAGS,
1054 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1055 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1056 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1057 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1058 SIVAL(outhdr, SMB2_HDR_PID,
1059 IVAL(inhdr, SMB2_HDR_PID));
1060 SIVAL(outhdr, SMB2_HDR_TID,
1061 IVAL(inhdr, SMB2_HDR_TID));
1062 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1063 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1064 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1065 inhdr + SMB2_HDR_SIGNATURE, 16);
1067 /* setup error body header */
1068 SSVAL(outbody, 0x00, 0x08 + 1);
1069 SSVAL(outbody, 0x02, 0);
1070 SIVAL(outbody, 0x04, 0);
1073 req->out.vector = vector;
1074 req->out.vector_count = count;
1076 /* setup the length of the NBT packet */
1077 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1078 if (!ok) {
1079 return NT_STATUS_INVALID_PARAMETER_MIX;
1082 DLIST_ADD_END(xconn->smb2.requests, req);
1084 return NT_STATUS_OK;
1087 void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
1088 const char *reason,
1089 const char *location)
1091 struct smbXsrv_client *client = xconn->client;
1093 DEBUG(10,("smbd_server_connection_terminate_ex: conn[%s] reason[%s] at %s\n",
1094 smbXsrv_connection_dbg(xconn), reason, location));
1096 if (client->connections->next != NULL) {
1097 /* TODO: cancel pending requests */
1098 DLIST_REMOVE(client->connections, xconn);
1099 TALLOC_FREE(xconn);
1100 DO_PROFILE_INC(disconnect);
1101 return;
1105 * The last connection was disconnected
1107 exit_server_cleanly(reason);
1110 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1111 struct iovec *outvec,
1112 const struct iovec *srcvec)
1114 const uint8_t *srctf;
1115 size_t srctf_len;
1116 const uint8_t *srchdr;
1117 size_t srchdr_len;
1118 const uint8_t *srcbody;
1119 size_t srcbody_len;
1120 const uint8_t *expected_srcbody;
1121 const uint8_t *srcdyn;
1122 size_t srcdyn_len;
1123 const uint8_t *expected_srcdyn;
1124 uint8_t *dsttf;
1125 uint8_t *dsthdr;
1126 uint8_t *dstbody;
1127 uint8_t *dstdyn;
1129 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1130 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1131 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1132 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1133 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1134 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1135 expected_srcbody = srchdr + SMB2_HDR_BODY;
1136 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1137 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1138 expected_srcdyn = srcbody + 8;
1140 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1141 return false;
1144 if (srchdr_len != SMB2_HDR_BODY) {
1145 return false;
1148 if (srctf_len == SMB2_TF_HDR_SIZE) {
1149 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1150 if (dsttf == NULL) {
1151 return false;
1153 } else {
1154 dsttf = NULL;
1156 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1157 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1159 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1160 * be allocated with size OUTVEC_ALLOC_SIZE. */
1162 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1163 if (dsthdr == NULL) {
1164 return false;
1166 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1167 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1170 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1171 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1172 * then duplicate this. Else use talloc_memdup().
1175 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1176 dstbody = dsthdr + SMB2_HDR_BODY;
1177 } else {
1178 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1179 if (dstbody == NULL) {
1180 return false;
1183 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1184 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1187 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1188 * pointing to
1189 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1190 * then duplicate this. Else use talloc_memdup().
1193 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1194 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1195 } else if (srcdyn == NULL) {
1196 dstdyn = NULL;
1197 } else {
1198 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1199 if (dstdyn == NULL) {
1200 return false;
1203 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1204 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1206 return true;
1209 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1211 struct smbd_smb2_request *newreq = NULL;
1212 struct iovec *outvec = NULL;
1213 int count = req->out.vector_count;
1214 int i;
1215 bool ok;
1217 newreq = smbd_smb2_request_allocate(req->xconn);
1218 if (!newreq) {
1219 return NULL;
1222 newreq->sconn = req->sconn;
1223 newreq->xconn = req->xconn;
1224 newreq->session = req->session;
1225 newreq->do_encryption = req->do_encryption;
1226 newreq->do_signing = req->do_signing;
1227 newreq->current_idx = req->current_idx;
1229 outvec = talloc_zero_array(newreq, struct iovec, count);
1230 if (!outvec) {
1231 TALLOC_FREE(newreq);
1232 return NULL;
1234 newreq->out.vector = outvec;
1235 newreq->out.vector_count = count;
1237 /* Setup the outvec's identically to req. */
1238 outvec[0].iov_base = newreq->out.nbt_hdr;
1239 outvec[0].iov_len = 4;
1240 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1242 /* Setup the vectors identically to the ones in req. */
1243 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1244 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1245 break;
1249 if (i < count) {
1250 /* Alloc failed. */
1251 TALLOC_FREE(newreq);
1252 return NULL;
1255 ok = smb2_setup_nbt_length(newreq->out.vector,
1256 newreq->out.vector_count);
1257 if (!ok) {
1258 TALLOC_FREE(newreq);
1259 return NULL;
1262 return newreq;
1265 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1267 struct smbXsrv_connection *xconn = req->xconn;
1268 int first_idx = 1;
1269 struct iovec *firsttf = NULL;
1270 struct iovec *outhdr_v = NULL;
1271 uint8_t *outhdr = NULL;
1272 struct smbd_smb2_request *nreq = NULL;
1273 NTSTATUS status;
1274 bool ok;
1276 /* Create a new smb2 request we'll use
1277 for the interim return. */
1278 nreq = dup_smb2_req(req);
1279 if (!nreq) {
1280 return NT_STATUS_NO_MEMORY;
1283 /* Lose the last X out vectors. They're the
1284 ones we'll be using for the async reply. */
1285 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1287 ok = smb2_setup_nbt_length(nreq->out.vector,
1288 nreq->out.vector_count);
1289 if (!ok) {
1290 return NT_STATUS_INVALID_PARAMETER_MIX;
1293 /* Step back to the previous reply. */
1294 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1295 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1296 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1297 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1298 /* And end the chain. */
1299 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1301 /* Calculate outgoing credits */
1302 smb2_calculate_credits(req, nreq);
1304 if (DEBUGLEVEL >= 10) {
1305 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1306 (unsigned int)nreq->current_idx );
1307 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1308 (unsigned int)nreq->out.vector_count );
1309 print_req_vectors(nreq);
1313 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1314 * we need to sign/encrypt here with the last/first key we remembered
1316 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1317 status = smb2_signing_encrypt_pdu(req->first_key,
1318 xconn->smb2.server.cipher,
1319 firsttf,
1320 nreq->out.vector_count - first_idx);
1321 if (!NT_STATUS_IS_OK(status)) {
1322 return status;
1324 } else if (req->last_key.length > 0) {
1325 status = smb2_signing_sign_pdu(req->last_key,
1326 xconn->protocol,
1327 outhdr_v,
1328 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1329 if (!NT_STATUS_IS_OK(status)) {
1330 return status;
1334 nreq->queue_entry.mem_ctx = nreq;
1335 nreq->queue_entry.vector = nreq->out.vector;
1336 nreq->queue_entry.count = nreq->out.vector_count;
1337 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry);
1338 xconn->smb2.send_queue_len++;
1340 status = smbd_smb2_flush_send_queue(xconn);
1341 if (!NT_STATUS_IS_OK(status)) {
1342 return status;
1345 return NT_STATUS_OK;
1348 struct smbd_smb2_request_pending_state {
1349 struct smbd_smb2_send_queue queue_entry;
1350 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1351 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1354 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1355 struct tevent_timer *te,
1356 struct timeval current_time,
1357 void *private_data);
1359 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1360 struct tevent_req *subreq,
1361 uint32_t defer_time)
1363 NTSTATUS status;
1364 struct timeval defer_endtime;
1365 uint8_t *outhdr = NULL;
1366 uint32_t flags;
1368 if (!tevent_req_is_in_progress(subreq)) {
1370 * This is a performance optimization,
1371 * it avoids one tevent_loop iteration,
1372 * which means we avoid one
1373 * talloc_stackframe_pool/talloc_free pair.
1375 tevent_req_notify_callback(subreq);
1376 return NT_STATUS_OK;
1379 req->subreq = subreq;
1380 subreq = NULL;
1382 if (req->async_te) {
1383 /* We're already async. */
1384 return NT_STATUS_OK;
1387 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1388 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1389 if (flags & SMB2_HDR_FLAG_ASYNC) {
1390 /* We're already async. */
1391 return NT_STATUS_OK;
1394 if (req->async_internal || defer_time == 0) {
1396 * An SMB2 request implementation wants to handle the request
1397 * asynchronously "internally" while keeping synchronous
1398 * behaviour for the SMB2 request. This means we don't send an
1399 * interim response and we can allow processing of compound SMB2
1400 * requests (cf the subsequent check) for all cases.
1402 return NT_STATUS_OK;
1405 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1407 * We're trying to go async in a compound request
1408 * chain. This is only allowed for opens that cause an
1409 * oplock break or for the last operation in the
1410 * chain, otherwise it is not allowed. See
1411 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
1413 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1415 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1417 * Cancel the outstanding request.
1419 bool ok = tevent_req_cancel(req->subreq);
1420 if (ok) {
1421 return NT_STATUS_OK;
1423 TALLOC_FREE(req->subreq);
1424 return smbd_smb2_request_error(req,
1425 NT_STATUS_INTERNAL_ERROR);
1429 if (DEBUGLEVEL >= 10) {
1430 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1431 (unsigned int)req->current_idx );
1432 print_req_vectors(req);
1435 if (req->current_idx > 1) {
1437 * We're going async in a compound
1438 * chain after the first request has
1439 * already been processed. Send an
1440 * interim response containing the
1441 * set of replies already generated.
1443 int idx = req->current_idx;
1445 status = smb2_send_async_interim_response(req);
1446 if (!NT_STATUS_IS_OK(status)) {
1447 return status;
1449 if (req->first_key.length > 0) {
1450 data_blob_clear_free(&req->first_key);
1453 req->current_idx = 1;
1456 * Re-arrange the in.vectors to remove what
1457 * we just sent.
1459 memmove(&req->in.vector[1],
1460 &req->in.vector[idx],
1461 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1462 req->in.vector_count = 1 + (req->in.vector_count - idx);
1464 /* Re-arrange the out.vectors to match. */
1465 memmove(&req->out.vector[1],
1466 &req->out.vector[idx],
1467 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1468 req->out.vector_count = 1 + (req->out.vector_count - idx);
1470 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1472 * We only have one remaining request as
1473 * we've processed everything else.
1474 * This is no longer a compound request.
1476 req->compound_related = false;
1477 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1478 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1479 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1482 if (req->last_key.length > 0) {
1483 data_blob_clear_free(&req->last_key);
1487 * smbd_smb2_request_pending_timer() just send a packet
1488 * to the client and doesn't need any impersonation.
1489 * So we use req->xconn->client->raw_ev_ctx instead
1490 * of req->ev_ctx here.
1492 defer_endtime = timeval_current_ofs_usec(defer_time);
1493 req->async_te = tevent_add_timer(req->xconn->client->raw_ev_ctx,
1494 req, defer_endtime,
1495 smbd_smb2_request_pending_timer,
1496 req);
1497 if (req->async_te == NULL) {
1498 return NT_STATUS_NO_MEMORY;
1501 return NT_STATUS_OK;
1504 static DATA_BLOB smbd_smb2_signing_key(struct smbXsrv_session *session,
1505 struct smbXsrv_connection *xconn)
1507 struct smbXsrv_channel_global0 *c = NULL;
1508 NTSTATUS status;
1509 DATA_BLOB key = data_blob_null;
1511 status = smbXsrv_session_find_channel(session, xconn, &c);
1512 if (NT_STATUS_IS_OK(status)) {
1513 key = c->signing_key;
1516 if (key.length == 0) {
1517 key = session->global->signing_key;
1520 return key;
1523 static NTSTATUS smb2_get_new_nonce(struct smbXsrv_session *session,
1524 uint64_t *new_nonce_high,
1525 uint64_t *new_nonce_low)
1527 uint64_t nonce_high;
1528 uint64_t nonce_low;
1530 session->nonce_low += 1;
1531 if (session->nonce_low == 0) {
1532 session->nonce_low += 1;
1533 session->nonce_high += 1;
1537 * CCM and GCM algorithms must never have their
1538 * nonce wrap, or the security of the whole
1539 * communication and the keys is destroyed.
1540 * We must drop the connection once we have
1541 * transfered too much data.
1543 * NOTE: We assume nonces greater than 8 bytes.
1545 if (session->nonce_high >= session->nonce_high_max) {
1546 return NT_STATUS_ENCRYPTION_FAILED;
1549 nonce_high = session->nonce_high_random;
1550 nonce_high += session->nonce_high;
1551 nonce_low = session->nonce_low;
1553 *new_nonce_high = nonce_high;
1554 *new_nonce_low = nonce_low;
1555 return NT_STATUS_OK;
1558 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1559 struct tevent_timer *te,
1560 struct timeval current_time,
1561 void *private_data)
1563 struct smbd_smb2_request *req =
1564 talloc_get_type_abort(private_data,
1565 struct smbd_smb2_request);
1566 struct smbXsrv_connection *xconn = req->xconn;
1567 struct smbd_smb2_request_pending_state *state = NULL;
1568 uint8_t *outhdr = NULL;
1569 const uint8_t *inhdr = NULL;
1570 uint8_t *tf = NULL;
1571 size_t tf_len = 0;
1572 uint8_t *hdr = NULL;
1573 uint8_t *body = NULL;
1574 uint8_t *dyn = NULL;
1575 uint32_t flags = 0;
1576 uint64_t session_id = 0;
1577 uint64_t message_id = 0;
1578 uint64_t nonce_high = 0;
1579 uint64_t nonce_low = 0;
1580 uint64_t async_id = 0;
1581 NTSTATUS status;
1582 bool ok;
1584 TALLOC_FREE(req->async_te);
1586 /* Ensure our final reply matches the interim one. */
1587 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1588 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1589 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1590 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1591 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1593 async_id = message_id; /* keep it simple for now... */
1595 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1596 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1598 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1599 "going async\n",
1600 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1601 (unsigned long long)async_id ));
1604 * What we send is identical to a smbd_smb2_request_error
1605 * packet with an error status of STATUS_PENDING. Make use
1606 * of this fact sometime when refactoring. JRA.
1609 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
1610 if (state == NULL) {
1611 smbd_server_connection_terminate(xconn,
1612 nt_errstr(NT_STATUS_NO_MEMORY));
1613 return;
1616 tf = state->buf + NBT_HDR_SIZE;
1617 tf_len = SMB2_TF_HDR_SIZE;
1619 hdr = tf + SMB2_TF_HDR_SIZE;
1620 body = hdr + SMB2_HDR_BODY;
1621 dyn = body + 8;
1623 if (req->do_encryption) {
1624 status = smb2_get_new_nonce(req->session,
1625 &nonce_high,
1626 &nonce_low);
1627 if (!NT_STATUS_IS_OK(status)) {
1628 smbd_server_connection_terminate(xconn,
1629 nt_errstr(status));
1630 return;
1634 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1635 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1636 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1637 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1639 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1640 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1641 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1642 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1643 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1645 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1646 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1647 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1648 SBVAL(hdr, SMB2_HDR_PID, async_id);
1649 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1650 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1651 memcpy(hdr+SMB2_HDR_SIGNATURE,
1652 outhdr+SMB2_HDR_SIGNATURE, 16);
1654 SSVAL(body, 0x00, 0x08 + 1);
1656 SCVAL(body, 0x02, 0);
1657 SCVAL(body, 0x03, 0);
1658 SIVAL(body, 0x04, 0);
1659 /* Match W2K8R2... */
1660 SCVAL(dyn, 0x00, 0x21);
1662 state->vector[0].iov_base = (void *)state->buf;
1663 state->vector[0].iov_len = NBT_HDR_SIZE;
1665 if (req->do_encryption) {
1666 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1667 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1668 } else {
1669 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1670 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1673 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1674 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1676 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1677 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1679 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1680 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1682 ok = smb2_setup_nbt_length(state->vector,
1683 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1684 if (!ok) {
1685 smbd_server_connection_terminate(
1686 xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
1687 return;
1690 /* Ensure we correctly go through crediting. Grant
1691 the credits now, and zero credits on the final
1692 response. */
1693 smb2_set_operation_credit(req->xconn,
1694 SMBD_SMB2_IN_HDR_IOV(req),
1695 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1697 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1699 if (DEBUGLVL(10)) {
1700 int i;
1702 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1703 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1704 (unsigned int)i,
1705 (unsigned int)ARRAY_SIZE(state->vector),
1706 (unsigned int)state->vector[i].iov_len);
1710 if (req->do_encryption) {
1711 struct smbXsrv_session *x = req->session;
1712 DATA_BLOB encryption_key = x->global->encryption_key;
1714 status = smb2_signing_encrypt_pdu(encryption_key,
1715 xconn->smb2.server.cipher,
1716 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1717 SMBD_SMB2_NUM_IOV_PER_REQ);
1718 if (!NT_STATUS_IS_OK(status)) {
1719 smbd_server_connection_terminate(xconn,
1720 nt_errstr(status));
1721 return;
1723 } else if (req->do_signing) {
1724 struct smbXsrv_session *x = req->session;
1725 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
1727 status = smb2_signing_sign_pdu(signing_key,
1728 xconn->protocol,
1729 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1730 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1731 if (!NT_STATUS_IS_OK(status)) {
1732 smbd_server_connection_terminate(xconn,
1733 nt_errstr(status));
1734 return;
1738 state->queue_entry.mem_ctx = state;
1739 state->queue_entry.vector = state->vector;
1740 state->queue_entry.count = ARRAY_SIZE(state->vector);
1741 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
1742 xconn->smb2.send_queue_len++;
1744 status = smbd_smb2_flush_send_queue(xconn);
1745 if (!NT_STATUS_IS_OK(status)) {
1746 smbd_server_connection_terminate(xconn,
1747 nt_errstr(status));
1748 return;
1752 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1754 struct smbXsrv_connection *xconn = req->xconn;
1755 struct smbd_smb2_request *cur;
1756 const uint8_t *inhdr;
1757 uint32_t flags;
1758 uint64_t search_message_id;
1759 uint64_t search_async_id;
1760 uint64_t found_id;
1762 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1764 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1765 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1766 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1769 * We don't need the request anymore cancel requests never
1770 * have a response.
1772 * We defer the TALLOC_FREE(req) to the caller.
1774 DLIST_REMOVE(xconn->smb2.requests, req);
1776 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1777 const uint8_t *outhdr;
1778 uint64_t message_id;
1779 uint64_t async_id;
1781 if (cur->compound_related) {
1783 * Never cancel anything in a compound request.
1784 * Way too hard to deal with the result.
1786 continue;
1789 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1791 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1792 async_id = BVAL(outhdr, SMB2_HDR_PID);
1794 if (flags & SMB2_HDR_FLAG_ASYNC) {
1795 if (search_async_id == async_id) {
1796 found_id = async_id;
1797 break;
1799 } else {
1800 if (search_message_id == message_id) {
1801 found_id = message_id;
1802 break;
1807 if (cur && cur->subreq) {
1808 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1809 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1810 "cancel opcode[%s] mid %llu\n",
1811 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1812 (unsigned long long)found_id ));
1813 tevent_req_cancel(cur->subreq);
1816 return NT_STATUS_OK;
1819 /*************************************************************
1820 Ensure an incoming tid is a valid one for us to access.
1821 Change to the associated uid credentials and chdir to the
1822 valid tid directory.
1823 *************************************************************/
1825 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1827 const uint8_t *inhdr;
1828 uint32_t in_flags;
1829 uint32_t in_tid;
1830 struct smbXsrv_tcon *tcon;
1831 NTSTATUS status;
1832 NTTIME now = timeval_to_nttime(&req->request_time);
1834 req->tcon = NULL;
1836 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1838 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1839 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1841 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1842 in_tid = req->last_tid;
1845 req->last_tid = 0;
1847 status = smb2srv_tcon_lookup(req->session,
1848 in_tid, now, &tcon);
1849 if (!NT_STATUS_IS_OK(status)) {
1850 return status;
1853 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1854 return NT_STATUS_ACCESS_DENIED;
1857 req->tcon = tcon;
1858 req->last_tid = in_tid;
1860 return NT_STATUS_OK;
1863 /*************************************************************
1864 Ensure an incoming session_id is a valid one for us to access.
1865 *************************************************************/
1867 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1869 const uint8_t *inhdr;
1870 uint32_t in_flags;
1871 uint16_t in_opcode;
1872 uint64_t in_session_id;
1873 struct smbXsrv_session *session = NULL;
1874 struct auth_session_info *session_info;
1875 NTSTATUS status;
1876 NTTIME now = timeval_to_nttime(&req->request_time);
1878 req->session = NULL;
1879 req->tcon = NULL;
1881 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1883 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1884 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1885 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1887 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1888 in_session_id = req->last_session_id;
1891 req->last_session_id = 0;
1893 /* look an existing session up */
1894 switch (in_opcode) {
1895 case SMB2_OP_SESSSETUP:
1897 * For a session bind request, we don't have the
1898 * channel set up at this point yet, so we defer
1899 * the verification that the connection belongs
1900 * to the session to the session setup code, which
1901 * can look at the session binding flags.
1903 status = smb2srv_session_lookup_client(req->xconn->client,
1904 in_session_id, now,
1905 &session);
1906 break;
1907 default:
1908 status = smb2srv_session_lookup_conn(req->xconn,
1909 in_session_id, now,
1910 &session);
1911 break;
1913 if (session) {
1914 req->session = session;
1915 req->last_session_id = in_session_id;
1917 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1918 switch (in_opcode) {
1919 case SMB2_OP_SESSSETUP:
1920 status = NT_STATUS_OK;
1921 break;
1922 case SMB2_OP_LOGOFF:
1923 case SMB2_OP_CLOSE:
1924 case SMB2_OP_LOCK:
1925 case SMB2_OP_CANCEL:
1926 case SMB2_OP_KEEPALIVE:
1928 * [MS-SMB2] 3.3.5.2.9 Verifying the Session
1929 * specifies that LOGOFF, CLOSE and (UN)LOCK
1930 * should always be processed even on expired sessions.
1932 * Also see the logic in
1933 * smbd_smb2_request_process_lock().
1935 * The smb2.session.expire2 test shows that
1936 * CANCEL and KEEPALIVE/ECHO should also
1937 * be processed.
1939 status = NT_STATUS_OK;
1940 break;
1941 default:
1942 break;
1945 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1946 switch (in_opcode) {
1947 case SMB2_OP_TCON:
1948 case SMB2_OP_CREATE:
1949 case SMB2_OP_GETINFO:
1950 case SMB2_OP_SETINFO:
1951 return NT_STATUS_INVALID_HANDLE;
1952 default:
1954 * Notice the check for
1955 * (session_info == NULL)
1956 * below.
1958 status = NT_STATUS_OK;
1959 break;
1962 if (!NT_STATUS_IS_OK(status)) {
1963 return status;
1966 session_info = session->global->auth_session_info;
1967 if (session_info == NULL) {
1968 return NT_STATUS_INVALID_HANDLE;
1971 return NT_STATUS_OK;
1974 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1975 uint32_t data_length)
1977 struct smbXsrv_connection *xconn = req->xconn;
1978 uint16_t needed_charge;
1979 uint16_t credit_charge = 1;
1980 const uint8_t *inhdr;
1982 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1984 if (xconn->smb2.credits.multicredit) {
1985 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1986 credit_charge = MAX(credit_charge, 1);
1989 needed_charge = (data_length - 1)/ 65536 + 1;
1991 DBGC_DEBUG(DBGC_SMB2_CREDITS,
1992 "mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1993 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1994 credit_charge, needed_charge);
1996 if (needed_charge > credit_charge) {
1997 DBGC_WARNING(DBGC_SMB2_CREDITS,
1998 "CreditCharge too low, given %d, needed %d\n",
1999 credit_charge, needed_charge);
2000 return NT_STATUS_INVALID_PARAMETER;
2003 return NT_STATUS_OK;
2006 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
2007 size_t expected_body_size)
2009 struct iovec *inhdr_v;
2010 const uint8_t *inhdr;
2011 uint16_t opcode;
2012 const uint8_t *inbody;
2013 size_t body_size;
2014 size_t min_dyn_size = expected_body_size & 0x00000001;
2015 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
2018 * The following should be checked already.
2020 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
2021 return NT_STATUS_INTERNAL_ERROR;
2023 if (req->current_idx > max_idx) {
2024 return NT_STATUS_INTERNAL_ERROR;
2027 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
2028 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
2029 return NT_STATUS_INTERNAL_ERROR;
2031 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
2032 return NT_STATUS_INTERNAL_ERROR;
2035 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2036 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2038 switch (opcode) {
2039 case SMB2_OP_IOCTL:
2040 case SMB2_OP_GETINFO:
2041 min_dyn_size = 0;
2042 break;
2043 case SMB2_OP_WRITE:
2044 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
2045 if (req->smb1req->unread_bytes < min_dyn_size) {
2046 return NT_STATUS_INVALID_PARAMETER;
2049 min_dyn_size = 0;
2051 break;
2055 * Now check the expected body size,
2056 * where the last byte might be in the
2057 * dynamic section..
2059 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
2060 return NT_STATUS_INVALID_PARAMETER;
2062 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
2063 return NT_STATUS_INVALID_PARAMETER;
2066 inbody = SMBD_SMB2_IN_BODY_PTR(req);
2068 body_size = SVAL(inbody, 0x00);
2069 if (body_size != expected_body_size) {
2070 return NT_STATUS_INVALID_PARAMETER;
2073 return NT_STATUS_OK;
2076 bool smbXsrv_is_encrypted(uint8_t encryption_flags)
2078 return (!(encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)
2080 (encryption_flags & (SMBXSRV_PROCESSED_ENCRYPTED_PACKET |
2081 SMBXSRV_ENCRYPTION_DESIRED |
2082 SMBXSRV_ENCRYPTION_REQUIRED)));
2085 bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags)
2087 return ((encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET) &&
2088 (encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET));
2091 /* Set a flag if not already set, return true if set */
2092 bool smbXsrv_set_crypto_flag(uint8_t *flags, uint8_t flag)
2094 if ((flag == 0) || (*flags & flag)) {
2095 return false;
2098 *flags |= flag;
2099 return true;
2103 * Update encryption state tracking flags, this can be used to
2104 * determine whether whether the session or tcon is "encrypted".
2106 static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
2107 uint16_t opcode,
2108 bool *update_session_globalp,
2109 bool *update_tcon_globalp)
2111 /* Default: assume unecrypted and unsigned */
2112 struct smbXsrv_session *session = req->session;
2113 struct smbXsrv_tcon *tcon = req->tcon;
2114 uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
2115 uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2116 bool update_session = false;
2117 bool update_tcon = false;
2119 if (req->was_encrypted && req->do_encryption) {
2120 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
2121 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2122 } else {
2123 /* Unencrypted packet, can be signed */
2124 if (req->do_signing) {
2125 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2126 } else if (opcode == SMB2_OP_CANCEL) {
2127 /* Cancel requests are allowed to skip signing */
2128 sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2132 update_session |= smbXsrv_set_crypto_flag(
2133 &session->global->encryption_flags, encrypt_flag);
2134 update_session |= smbXsrv_set_crypto_flag(
2135 &session->global->signing_flags, sign_flag);
2137 if (tcon) {
2138 update_tcon |= smbXsrv_set_crypto_flag(
2139 &tcon->global->encryption_flags, encrypt_flag);
2140 update_tcon |= smbXsrv_set_crypto_flag(
2141 &tcon->global->signing_flags, sign_flag);
2144 *update_session_globalp = update_session;
2145 *update_tcon_globalp = update_tcon;
2146 return;
2149 bool smbXsrv_is_signed(uint8_t signing_flags)
2152 * Signing is always enabled, so unless we got an unsigned
2153 * packet and at least one signed packet that was not
2154 * encrypted, the session or tcon is "signed".
2156 return (!(signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2157 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2160 bool smbXsrv_is_partially_signed(uint8_t signing_flags)
2162 return ((signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2163 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2166 static NTSTATUS smbd_smb2_request_dispatch_update_counts(
2167 struct smbd_smb2_request *req,
2168 bool modify_call)
2170 struct smbXsrv_connection *xconn = req->xconn;
2171 const uint8_t *inhdr;
2172 uint16_t channel_sequence;
2173 uint8_t generation_wrap = 0;
2174 uint32_t flags;
2175 int cmp;
2176 struct smbXsrv_open *op;
2177 bool update_open = false;
2178 NTSTATUS status = NT_STATUS_OK;
2180 SMB_ASSERT(!req->request_counters_updated);
2182 if (xconn->protocol < PROTOCOL_SMB2_22) {
2183 return NT_STATUS_OK;
2186 if (req->compat_chain_fsp == NULL) {
2187 return NT_STATUS_OK;
2190 op = req->compat_chain_fsp->op;
2191 if (op == NULL) {
2192 return NT_STATUS_OK;
2195 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2196 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2197 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2199 cmp = channel_sequence - op->global->channel_sequence;
2200 if (cmp < 0) {
2202 * csn wrap. We need to watch out for long-running
2203 * requests that are still sitting on a previously
2204 * used csn. SMB2_OP_NOTIFY can take VERY long.
2206 generation_wrap += 1;
2209 if (abs(cmp) > INT16_MAX) {
2211 * [MS-SMB2] 3.3.5.2.10 - Verifying the Channel Sequence Number:
2213 * If the channel sequence number of the request and the one
2214 * known to the server are not equal, the channel sequence
2215 * number and outstanding request counts are only updated
2216 * "... if the unsigned difference using 16-bit arithmetic
2217 * between ChannelSequence and Open.ChannelSequence is less than
2218 * or equal to 0x7FFF ...".
2219 * Otherwise, an error is returned for the modifying
2220 * calls write, set_info, and ioctl.
2222 * There are currently two issues with the description:
2224 * * For the other calls, the document seems to imply
2225 * that processing continues without adapting the
2226 * counters (if the sequence numbers are not equal).
2228 * TODO: This needs clarification!
2230 * * Also, the behaviour if the difference is larger
2231 * than 0x7FFF is not clear. The document seems to
2232 * imply that if such a difference is reached,
2233 * the server starts to ignore the counters or
2234 * in the case of the modifying calls, return errors.
2236 * TODO: This needs clarification!
2238 * At this point Samba tries to be a little more
2239 * clever than the description in the MS-SMB2 document
2240 * by heuristically detecting and properly treating
2241 * a 16 bit overflow of the client-submitted sequence
2242 * number:
2244 * If the stored channel sequence number is more than
2245 * 0x7FFF larger than the one from the request, then
2246 * the client-provided sequence number has likely
2247 * overflown. We treat this case as valid instead
2248 * of as failure.
2250 * The MS-SMB2 behaviour would be setting cmp = -1.
2252 cmp *= -1;
2255 if (flags & SMB2_HDR_FLAG_REPLAY_OPERATION) {
2256 if (cmp == 0 && op->pre_request_count == 0) {
2257 op->request_count += 1;
2258 req->request_counters_updated = true;
2259 } else if (cmp > 0 && op->pre_request_count == 0) {
2260 op->pre_request_count += op->request_count;
2261 op->request_count = 1;
2262 op->global->channel_sequence = channel_sequence;
2263 op->global->channel_generation += generation_wrap;
2264 update_open = true;
2265 req->request_counters_updated = true;
2266 } else if (modify_call) {
2267 return NT_STATUS_FILE_NOT_AVAILABLE;
2269 } else {
2270 if (cmp == 0) {
2271 op->request_count += 1;
2272 req->request_counters_updated = true;
2273 } else if (cmp > 0) {
2274 op->pre_request_count += op->request_count;
2275 op->request_count = 1;
2276 op->global->channel_sequence = channel_sequence;
2277 op->global->channel_generation += generation_wrap;
2278 update_open = true;
2279 req->request_counters_updated = true;
2280 } else if (modify_call) {
2281 return NT_STATUS_FILE_NOT_AVAILABLE;
2284 req->channel_generation = op->global->channel_generation;
2286 if (update_open) {
2287 status = smbXsrv_open_update(op);
2290 return status;
2293 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
2295 struct smbXsrv_connection *xconn = req->xconn;
2296 const struct smbd_smb2_dispatch_table *call = NULL;
2297 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
2298 const uint8_t *inhdr;
2299 uint16_t opcode;
2300 uint32_t flags;
2301 uint64_t mid;
2302 NTSTATUS status;
2303 NTSTATUS session_status;
2304 uint32_t allowed_flags;
2305 NTSTATUS return_value;
2306 struct smbXsrv_session *x = NULL;
2307 bool signing_required = false;
2308 bool encryption_desired = false;
2309 bool encryption_required = false;
2311 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2313 DO_PROFILE_INC(request);
2315 SMB_ASSERT(!req->request_counters_updated);
2317 /* TODO: verify more things */
2319 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2320 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2321 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2322 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
2323 smb2_opcode_name(opcode),
2324 (unsigned long long)mid));
2326 if (xconn->protocol >= PROTOCOL_SMB2_02) {
2328 * once the protocol is negotiated
2329 * SMB2_OP_NEGPROT is not allowed anymore
2331 if (opcode == SMB2_OP_NEGPROT) {
2332 /* drop the connection */
2333 return NT_STATUS_INVALID_PARAMETER;
2335 } else {
2337 * if the protocol is not negotiated yet
2338 * only SMB2_OP_NEGPROT is allowed.
2340 if (opcode != SMB2_OP_NEGPROT) {
2341 /* drop the connection */
2342 return NT_STATUS_INVALID_PARAMETER;
2347 * Check if the client provided a valid session id.
2349 * As some command don't require a valid session id
2350 * we defer the check of the session_status
2352 session_status = smbd_smb2_request_check_session(req);
2353 x = req->session;
2354 if (x != NULL) {
2355 signing_required = x->global->signing_flags & SMBXSRV_SIGNING_REQUIRED;
2356 encryption_desired = x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
2357 encryption_required = x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
2360 req->async_internal = false;
2361 req->do_signing = false;
2362 if (opcode != SMB2_OP_SESSSETUP) {
2363 req->do_encryption = encryption_desired;
2364 } else {
2365 req->do_encryption = false;
2367 req->was_encrypted = false;
2368 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
2369 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
2370 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
2372 if (x != NULL && x->global->session_wire_id != tf_session_id) {
2373 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2374 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
2375 (unsigned long long)x->global->session_wire_id,
2376 (unsigned long long)tf_session_id));
2378 * TODO: windows allows this...
2379 * should we drop the connection?
2381 * For now we just return ACCESS_DENIED
2382 * (Windows clients never trigger this)
2383 * and wait for an update of [MS-SMB2].
2385 return smbd_smb2_request_error(req,
2386 NT_STATUS_ACCESS_DENIED);
2389 req->was_encrypted = true;
2390 req->do_encryption = true;
2393 if (encryption_required && !req->was_encrypted) {
2394 req->do_encryption = true;
2395 return smbd_smb2_request_error(req,
2396 NT_STATUS_ACCESS_DENIED);
2399 call = smbd_smb2_call(opcode);
2400 if (call == NULL) {
2401 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2404 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2405 SMB2_HDR_FLAG_SIGNED |
2406 SMB2_HDR_FLAG_DFS;
2407 if (xconn->protocol >= PROTOCOL_SMB3_11) {
2408 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2410 if (opcode == SMB2_OP_NEGPROT) {
2411 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11) {
2412 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2415 if (opcode == SMB2_OP_CANCEL) {
2416 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2418 if (xconn->protocol >= PROTOCOL_SMB2_22) {
2419 allowed_flags |= SMB2_HDR_FLAG_REPLAY_OPERATION;
2421 if ((flags & ~allowed_flags) != 0) {
2422 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2425 if (flags & SMB2_HDR_FLAG_CHAINED) {
2427 * This check is mostly for giving the correct error code
2428 * for compounded requests.
2430 if (!NT_STATUS_IS_OK(session_status)) {
2431 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2433 } else {
2434 req->compat_chain_fsp = NULL;
2437 if (req->was_encrypted) {
2438 signing_required = false;
2439 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2440 DATA_BLOB signing_key = data_blob_null;
2442 if (x == NULL) {
2444 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2445 * If the SMB2 header of the SMB2 NEGOTIATE
2446 * request has the SMB2_FLAGS_SIGNED bit set in the
2447 * Flags field, the server MUST fail the request
2448 * with STATUS_INVALID_PARAMETER.
2450 * Microsoft test tool checks this.
2453 if ((opcode == SMB2_OP_NEGPROT) &&
2454 (flags & SMB2_HDR_FLAG_SIGNED)) {
2455 status = NT_STATUS_INVALID_PARAMETER;
2456 } else {
2457 status = NT_STATUS_USER_SESSION_DELETED;
2459 return smbd_smb2_request_error(req, status);
2462 signing_key = smbd_smb2_signing_key(x, xconn);
2465 * If we have a signing key, we should
2466 * sign the response
2468 if (signing_key.length > 0) {
2469 req->do_signing = true;
2472 status = smb2_signing_check_pdu(signing_key,
2473 xconn->protocol,
2474 SMBD_SMB2_IN_HDR_IOV(req),
2475 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2476 if (!NT_STATUS_IS_OK(status)) {
2477 return smbd_smb2_request_error(req, status);
2481 * Now that we know the request was correctly signed
2482 * we have to sign the response too.
2484 req->do_signing = true;
2486 if (!NT_STATUS_IS_OK(session_status)) {
2487 return smbd_smb2_request_error(req, session_status);
2489 } else if (opcode == SMB2_OP_CANCEL) {
2490 /* Cancel requests are allowed to skip the signing */
2491 } else if (signing_required) {
2493 * If signing is required we try to sign
2494 * a possible error response
2496 req->do_signing = true;
2497 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2500 if (flags & SMB2_HDR_FLAG_CHAINED) {
2501 req->compound_related = true;
2504 if (call->need_session) {
2505 if (!NT_STATUS_IS_OK(session_status)) {
2506 return smbd_smb2_request_error(req, session_status);
2510 if (call->need_tcon) {
2511 SMB_ASSERT(call->need_session);
2514 * This call needs to be run as user.
2516 * smbd_smb2_request_check_tcon()
2517 * calls change_to_user() on success.
2518 * Which implies set_current_user_info()
2519 * and chdir_current_service().
2521 status = smbd_smb2_request_check_tcon(req);
2522 if (!NT_STATUS_IS_OK(status)) {
2523 return smbd_smb2_request_error(req, status);
2525 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
2526 encryption_desired = true;
2528 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
2529 encryption_required = true;
2531 if (encryption_required && !req->was_encrypted) {
2532 req->do_encryption = true;
2533 return smbd_smb2_request_error(req,
2534 NT_STATUS_ACCESS_DENIED);
2535 } else if (encryption_desired) {
2536 req->do_encryption = true;
2538 } else if (call->need_session) {
2539 struct auth_session_info *session_info = NULL;
2542 * Unless we also have need_tcon (see above),
2543 * we still need to call set_current_user_info().
2546 session_info = req->session->global->auth_session_info;
2547 if (session_info == NULL) {
2548 return NT_STATUS_INVALID_HANDLE;
2551 set_current_user_info(session_info->unix_info->sanitized_username,
2552 session_info->unix_info->unix_name,
2553 session_info->info->domain_name);
2556 if (req->session) {
2557 bool update_session_global = false;
2558 bool update_tcon_global = false;
2560 smb2srv_update_crypto_flags(req, opcode,
2561 &update_session_global,
2562 &update_tcon_global);
2564 if (update_session_global) {
2565 status = smbXsrv_session_update(x);
2566 if (!NT_STATUS_IS_OK(status)) {
2567 return smbd_smb2_request_error(req, status);
2570 if (update_tcon_global) {
2571 status = smbXsrv_tcon_update(req->tcon);
2572 if (!NT_STATUS_IS_OK(status)) {
2573 return smbd_smb2_request_error(req, status);
2578 if (call->fileid_ofs != 0) {
2579 size_t needed = call->fileid_ofs + 16;
2580 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2581 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2582 uint64_t file_id_persistent;
2583 uint64_t file_id_volatile;
2584 struct files_struct *fsp;
2586 SMB_ASSERT(call->need_tcon);
2588 if (needed > body_size) {
2589 return smbd_smb2_request_error(req,
2590 NT_STATUS_INVALID_PARAMETER);
2593 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2594 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2596 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2597 if (fsp == NULL) {
2598 if (!call->allow_invalid_fileid) {
2599 return smbd_smb2_request_error(req,
2600 NT_STATUS_FILE_CLOSED);
2603 if (file_id_persistent != UINT64_MAX) {
2604 return smbd_smb2_request_error(req,
2605 NT_STATUS_FILE_CLOSED);
2607 if (file_id_volatile != UINT64_MAX) {
2608 return smbd_smb2_request_error(req,
2609 NT_STATUS_FILE_CLOSED);
2614 status = smbd_smb2_request_dispatch_update_counts(req, call->modify);
2615 if (!NT_STATUS_IS_OK(status)) {
2616 return smbd_smb2_request_error(req, status);
2619 if (call->as_root) {
2620 SMB_ASSERT(call->fileid_ofs == 0);
2621 /* This call needs to be run as root */
2622 change_to_root_user();
2623 } else {
2624 SMB_ASSERT(call->need_tcon);
2627 #define _INBYTES(_r) \
2628 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
2630 switch (opcode) {
2631 case SMB2_OP_NEGPROT:
2632 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
2633 req->profile, _INBYTES(req));
2634 return_value = smbd_smb2_request_process_negprot(req);
2635 break;
2637 case SMB2_OP_SESSSETUP:
2638 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
2639 req->profile, _INBYTES(req));
2640 return_value = smbd_smb2_request_process_sesssetup(req);
2641 break;
2643 case SMB2_OP_LOGOFF:
2644 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
2645 req->profile, _INBYTES(req));
2646 return_value = smbd_smb2_request_process_logoff(req);
2647 break;
2649 case SMB2_OP_TCON:
2650 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
2651 req->profile, _INBYTES(req));
2652 return_value = smbd_smb2_request_process_tcon(req);
2653 break;
2655 case SMB2_OP_TDIS:
2656 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
2657 req->profile, _INBYTES(req));
2658 return_value = smbd_smb2_request_process_tdis(req);
2659 break;
2661 case SMB2_OP_CREATE:
2662 if (req->subreq == NULL) {
2663 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
2664 req->profile, _INBYTES(req));
2665 } else {
2666 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
2668 return_value = smbd_smb2_request_process_create(req);
2669 break;
2671 case SMB2_OP_CLOSE:
2672 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
2673 req->profile, _INBYTES(req));
2674 return_value = smbd_smb2_request_process_close(req);
2675 break;
2677 case SMB2_OP_FLUSH:
2678 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
2679 req->profile, _INBYTES(req));
2680 return_value = smbd_smb2_request_process_flush(req);
2681 break;
2683 case SMB2_OP_READ:
2684 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
2685 req->profile, _INBYTES(req));
2686 return_value = smbd_smb2_request_process_read(req);
2687 break;
2689 case SMB2_OP_WRITE:
2690 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
2691 req->profile, _INBYTES(req));
2692 return_value = smbd_smb2_request_process_write(req);
2693 break;
2695 case SMB2_OP_LOCK:
2696 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
2697 req->profile, _INBYTES(req));
2698 return_value = smbd_smb2_request_process_lock(req);
2699 break;
2701 case SMB2_OP_IOCTL:
2702 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
2703 req->profile, _INBYTES(req));
2704 return_value = smbd_smb2_request_process_ioctl(req);
2705 break;
2707 case SMB2_OP_CANCEL:
2708 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
2709 req->profile, _INBYTES(req));
2710 return_value = smbd_smb2_request_process_cancel(req);
2711 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
2714 * We don't need the request anymore cancel requests never
2715 * have a response.
2717 * smbd_smb2_request_process_cancel() already called
2718 * DLIST_REMOVE(xconn->smb2.requests, req);
2720 TALLOC_FREE(req);
2722 break;
2724 case SMB2_OP_KEEPALIVE:
2725 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
2726 req->profile, _INBYTES(req));
2727 return_value = smbd_smb2_request_process_keepalive(req);
2728 break;
2730 case SMB2_OP_QUERY_DIRECTORY:
2731 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
2732 req->profile, _INBYTES(req));
2733 return_value = smbd_smb2_request_process_query_directory(req);
2734 break;
2736 case SMB2_OP_NOTIFY:
2737 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
2738 req->profile, _INBYTES(req));
2739 return_value = smbd_smb2_request_process_notify(req);
2740 break;
2742 case SMB2_OP_GETINFO:
2743 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
2744 req->profile, _INBYTES(req));
2745 return_value = smbd_smb2_request_process_getinfo(req);
2746 break;
2748 case SMB2_OP_SETINFO:
2749 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
2750 req->profile, _INBYTES(req));
2751 return_value = smbd_smb2_request_process_setinfo(req);
2752 break;
2754 case SMB2_OP_BREAK:
2755 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
2756 req->profile, _INBYTES(req));
2757 return_value = smbd_smb2_request_process_break(req);
2758 break;
2760 default:
2761 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2762 break;
2764 return return_value;
2767 static void smbd_smb2_request_reply_update_counts(struct smbd_smb2_request *req)
2769 struct smbXsrv_connection *xconn = req->xconn;
2770 const uint8_t *inhdr;
2771 uint16_t channel_sequence;
2772 struct smbXsrv_open *op;
2774 if (!req->request_counters_updated) {
2775 return;
2778 req->request_counters_updated = false;
2780 if (xconn->protocol < PROTOCOL_SMB2_22) {
2781 return;
2784 if (req->compat_chain_fsp == NULL) {
2785 return;
2788 op = req->compat_chain_fsp->op;
2789 if (op == NULL) {
2790 return;
2793 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2794 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2796 if ((op->global->channel_sequence == channel_sequence) &&
2797 (op->global->channel_generation == req->channel_generation)) {
2798 SMB_ASSERT(op->request_count > 0);
2799 op->request_count -= 1;
2800 } else {
2801 SMB_ASSERT(op->pre_request_count > 0);
2802 op->pre_request_count -= 1;
2806 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2808 struct smbXsrv_connection *xconn = req->xconn;
2809 int first_idx = 1;
2810 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2811 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2812 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2813 NTSTATUS status;
2814 bool ok;
2816 req->subreq = NULL;
2817 TALLOC_FREE(req->async_te);
2819 /* MS-SMB2: 3.3.4.1 Sending Any Outgoing Message */
2820 smbd_smb2_request_reply_update_counts(req);
2822 if (req->do_encryption &&
2823 (firsttf->iov_len == 0) &&
2824 (req->first_key.length == 0) &&
2825 (req->session != NULL) &&
2826 (req->session->global->encryption_key.length != 0))
2828 DATA_BLOB encryption_key = req->session->global->encryption_key;
2829 uint8_t *tf;
2830 uint64_t session_id = req->session->global->session_wire_id;
2831 uint64_t nonce_high;
2832 uint64_t nonce_low;
2834 status = smb2_get_new_nonce(req->session,
2835 &nonce_high,
2836 &nonce_low);
2837 if (!NT_STATUS_IS_OK(status)) {
2838 return status;
2842 * We need to place the SMB2_TRANSFORM header before the
2843 * first SMB2 header
2847 * we need to remember the encryption key
2848 * and defer the signing/encryption until
2849 * we are sure that we do not change
2850 * the header again.
2852 req->first_key = data_blob_dup_talloc(req, encryption_key);
2853 if (req->first_key.data == NULL) {
2854 return NT_STATUS_NO_MEMORY;
2857 tf = talloc_zero_array(req, uint8_t,
2858 SMB2_TF_HDR_SIZE);
2859 if (tf == NULL) {
2860 return NT_STATUS_NO_MEMORY;
2863 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2864 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2865 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2866 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2868 firsttf->iov_base = (void *)tf;
2869 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2872 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2873 (req->last_key.length > 0) &&
2874 (firsttf->iov_len == 0))
2876 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2877 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2880 * As we are sure the header of the last request in the
2881 * compound chain will not change, we can to sign here
2882 * with the last signing key we remembered.
2884 status = smb2_signing_sign_pdu(req->last_key,
2885 xconn->protocol,
2886 lasthdr,
2887 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2888 if (!NT_STATUS_IS_OK(status)) {
2889 return status;
2892 if (req->last_key.length > 0) {
2893 data_blob_clear_free(&req->last_key);
2896 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
2897 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
2899 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2901 if (req->current_idx < req->out.vector_count) {
2903 * We must process the remaining compound
2904 * SMB2 requests before any new incoming SMB2
2905 * requests. This is because incoming SMB2
2906 * requests may include a cancel for a
2907 * compound request we haven't processed
2908 * yet.
2910 struct tevent_immediate *im = tevent_create_immediate(req);
2911 if (!im) {
2912 return NT_STATUS_NO_MEMORY;
2915 if (req->do_signing && firsttf->iov_len == 0) {
2916 struct smbXsrv_session *x = req->session;
2917 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2920 * we need to remember the signing key
2921 * and defer the signing until
2922 * we are sure that we do not change
2923 * the header again.
2925 req->last_key = data_blob_dup_talloc(req, signing_key);
2926 if (req->last_key.data == NULL) {
2927 return NT_STATUS_NO_MEMORY;
2932 * smbd_smb2_request_dispatch() will redo the impersonation.
2933 * So we use req->xconn->client->raw_ev_ctx instead
2934 * of req->ev_ctx here.
2936 tevent_schedule_immediate(im,
2937 req->xconn->client->raw_ev_ctx,
2938 smbd_smb2_request_dispatch_immediate,
2939 req);
2940 return NT_STATUS_OK;
2943 if (req->compound_related) {
2944 req->compound_related = false;
2947 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2948 if (!ok) {
2949 return NT_STATUS_INVALID_PARAMETER_MIX;
2952 /* Set credit for these operations (zero credits if this
2953 is a final reply for an async operation). */
2954 smb2_calculate_credits(req, req);
2957 * now check if we need to sign the current response
2959 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2960 status = smb2_signing_encrypt_pdu(req->first_key,
2961 xconn->smb2.server.cipher,
2962 firsttf,
2963 req->out.vector_count - first_idx);
2964 if (!NT_STATUS_IS_OK(status)) {
2965 return status;
2967 } else if (req->do_signing) {
2968 struct smbXsrv_session *x = req->session;
2969 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2971 status = smb2_signing_sign_pdu(signing_key,
2972 xconn->protocol,
2973 outhdr,
2974 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2975 if (!NT_STATUS_IS_OK(status)) {
2976 return status;
2979 if (req->first_key.length > 0) {
2980 data_blob_clear_free(&req->first_key);
2983 if (req->preauth != NULL) {
2984 struct hc_sha512state sctx;
2985 int i;
2987 samba_SHA512_Init(&sctx);
2988 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2989 sizeof(req->preauth->sha512_value));
2990 for (i = 1; i < req->in.vector_count; i++) {
2991 samba_SHA512_Update(&sctx,
2992 req->in.vector[i].iov_base,
2993 req->in.vector[i].iov_len);
2995 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2997 samba_SHA512_Init(&sctx);
2998 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2999 sizeof(req->preauth->sha512_value));
3000 for (i = 1; i < req->out.vector_count; i++) {
3001 samba_SHA512_Update(&sctx,
3002 req->out.vector[i].iov_base,
3003 req->out.vector[i].iov_len);
3005 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
3007 req->preauth = NULL;
3010 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
3011 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
3012 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
3013 /* Dynamic part is NULL. Chop it off,
3014 We're going to send it via sendfile. */
3015 req->out.vector_count -= 1;
3019 * We're done with this request -
3020 * move it off the "being processed" queue.
3022 DLIST_REMOVE(xconn->smb2.requests, req);
3024 req->queue_entry.mem_ctx = req;
3025 req->queue_entry.vector = req->out.vector;
3026 req->queue_entry.count = req->out.vector_count;
3027 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry);
3028 xconn->smb2.send_queue_len++;
3030 status = smbd_smb2_flush_send_queue(xconn);
3031 if (!NT_STATUS_IS_OK(status)) {
3032 return status;
3035 return NT_STATUS_OK;
3038 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
3040 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
3041 struct tevent_immediate *im,
3042 void *private_data)
3044 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
3045 struct smbd_smb2_request);
3046 struct smbXsrv_connection *xconn = req->xconn;
3047 NTSTATUS status;
3049 TALLOC_FREE(im);
3051 if (DEBUGLEVEL >= 10) {
3052 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
3053 req->current_idx, req->in.vector_count));
3054 print_req_vectors(req);
3057 status = smbd_smb2_request_dispatch(req);
3058 if (!NT_STATUS_IS_OK(status)) {
3059 smbd_server_connection_terminate(xconn, nt_errstr(status));
3060 return;
3063 status = smbd_smb2_request_next_incoming(xconn);
3064 if (!NT_STATUS_IS_OK(status)) {
3065 smbd_server_connection_terminate(xconn, nt_errstr(status));
3066 return;
3070 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
3071 NTSTATUS status,
3072 DATA_BLOB body, DATA_BLOB *dyn,
3073 const char *location)
3075 uint8_t *outhdr;
3076 struct iovec *outbody_v;
3077 struct iovec *outdyn_v;
3078 uint32_t next_command_ofs;
3080 DEBUG(10,("smbd_smb2_request_done_ex: "
3081 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
3082 req->current_idx, nt_errstr(status), (unsigned int)body.length,
3083 dyn ? "yes": "no",
3084 (unsigned int)(dyn ? dyn->length : 0),
3085 location));
3087 if (body.length < 2) {
3088 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3091 if ((body.length % 2) != 0) {
3092 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3095 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3096 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
3097 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
3099 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
3100 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
3102 outbody_v->iov_base = (void *)body.data;
3103 outbody_v->iov_len = body.length;
3105 if (dyn) {
3106 outdyn_v->iov_base = (void *)dyn->data;
3107 outdyn_v->iov_len = dyn->length;
3108 } else {
3109 outdyn_v->iov_base = NULL;
3110 outdyn_v->iov_len = 0;
3114 * See if we need to recalculate the offset to the next response
3116 * Note that all responses may require padding (including the very last
3117 * one).
3119 if (req->out.vector_count >= (2 * SMBD_SMB2_NUM_IOV_PER_REQ)) {
3120 next_command_ofs = SMB2_HDR_BODY;
3121 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
3122 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
3125 if ((next_command_ofs % 8) != 0) {
3126 size_t pad_size = 8 - (next_command_ofs % 8);
3127 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
3129 * if the dyn buffer is empty
3130 * we can use it to add padding
3132 uint8_t *pad;
3134 pad = talloc_zero_array(req,
3135 uint8_t, pad_size);
3136 if (pad == NULL) {
3137 return smbd_smb2_request_error(req,
3138 NT_STATUS_NO_MEMORY);
3141 outdyn_v->iov_base = (void *)pad;
3142 outdyn_v->iov_len = pad_size;
3143 } else {
3145 * For now we copy the dynamic buffer
3146 * and add the padding to the new buffer
3148 size_t old_size;
3149 uint8_t *old_dyn;
3150 size_t new_size;
3151 uint8_t *new_dyn;
3153 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
3154 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
3156 new_size = old_size + pad_size;
3157 new_dyn = talloc_zero_array(req,
3158 uint8_t, new_size);
3159 if (new_dyn == NULL) {
3160 return smbd_smb2_request_error(req,
3161 NT_STATUS_NO_MEMORY);
3164 memcpy(new_dyn, old_dyn, old_size);
3165 memset(new_dyn + old_size, 0, pad_size);
3167 outdyn_v->iov_base = (void *)new_dyn;
3168 outdyn_v->iov_len = new_size;
3170 next_command_ofs += pad_size;
3173 if ((req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) >= req->out.vector_count) {
3174 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
3175 } else {
3176 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
3178 return smbd_smb2_request_reply(req);
3181 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
3182 NTSTATUS status,
3183 DATA_BLOB *info,
3184 const char *location)
3186 struct smbXsrv_connection *xconn = req->xconn;
3187 DATA_BLOB body;
3188 DATA_BLOB _dyn;
3189 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3190 size_t unread_bytes = smbd_smb2_unread_bytes(req);
3192 DBG_NOTICE("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| "
3193 "at %s\n", req->current_idx, nt_errstr(status),
3194 info ? " +info" : "", location);
3196 if (unread_bytes) {
3197 /* Recvfile error. Drain incoming socket. */
3198 size_t ret;
3200 errno = 0;
3201 ret = drain_socket(xconn->transport.sock, unread_bytes);
3202 if (ret != unread_bytes) {
3203 NTSTATUS error;
3205 if (errno == 0) {
3206 error = NT_STATUS_IO_DEVICE_ERROR;
3207 } else {
3208 error = map_nt_error_from_unix_common(errno);
3211 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
3212 "ret[%u] errno[%d] => %s\n",
3213 (unsigned)unread_bytes,
3214 (unsigned)ret, errno, nt_errstr(error)));
3215 return error;
3219 body.data = outhdr + SMB2_HDR_BODY;
3220 body.length = 8;
3221 SSVAL(body.data, 0, 9);
3223 if (info) {
3224 SIVAL(body.data, 0x04, info->length);
3225 } else {
3226 /* Allocated size of req->out.vector[i].iov_base
3227 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
3228 * 1 byte without having to do an alloc.
3230 info = &_dyn;
3231 info->data = ((uint8_t *)outhdr) +
3232 OUTVEC_ALLOC_SIZE - 1;
3233 info->length = 1;
3234 SCVAL(info->data, 0, 0);
3238 * Note: Even if there is an error, continue to process the request.
3239 * per MS-SMB2.
3242 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
3246 struct smbd_smb2_send_break_state {
3247 struct smbd_smb2_send_queue queue_entry;
3248 uint8_t nbt_hdr[NBT_HDR_SIZE];
3249 uint8_t tf[SMB2_TF_HDR_SIZE];
3250 uint8_t hdr[SMB2_HDR_BODY];
3251 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
3252 uint8_t body[1];
3255 static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
3256 struct smbXsrv_session *session,
3257 struct smbXsrv_tcon *tcon,
3258 const uint8_t *body,
3259 size_t body_len)
3261 struct smbd_smb2_send_break_state *state;
3262 bool do_encryption = false;
3263 uint64_t session_wire_id = 0;
3264 uint64_t nonce_high = 0;
3265 uint64_t nonce_low = 0;
3266 NTSTATUS status;
3267 size_t statelen;
3268 bool ok;
3270 if (session != NULL) {
3271 session_wire_id = session->global->session_wire_id;
3272 do_encryption = session->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
3273 if (tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
3274 do_encryption = true;
3278 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
3279 body_len;
3281 state = talloc_zero_size(xconn, statelen);
3282 if (state == NULL) {
3283 return NT_STATUS_NO_MEMORY;
3285 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
3287 if (do_encryption) {
3288 status = smb2_get_new_nonce(session,
3289 &nonce_high,
3290 &nonce_low);
3291 if (!NT_STATUS_IS_OK(status)) {
3292 return status;
3296 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
3297 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
3298 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
3299 SBVAL(state->tf, SMB2_TF_SESSION_ID, session_wire_id);
3301 SIVAL(state->hdr, 0, SMB2_MAGIC);
3302 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
3303 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
3304 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
3305 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
3306 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
3307 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
3308 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
3309 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
3310 SIVAL(state->hdr, SMB2_HDR_PID, 0);
3311 SIVAL(state->hdr, SMB2_HDR_TID, 0);
3312 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
3313 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
3315 state->vector[0] = (struct iovec) {
3316 .iov_base = state->nbt_hdr,
3317 .iov_len = sizeof(state->nbt_hdr)
3320 if (do_encryption) {
3321 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3322 .iov_base = state->tf,
3323 .iov_len = sizeof(state->tf)
3325 } else {
3326 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3327 .iov_base = NULL,
3328 .iov_len = 0
3332 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
3333 .iov_base = state->hdr,
3334 .iov_len = sizeof(state->hdr)
3337 memcpy(state->body, body, body_len);
3339 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
3340 .iov_base = state->body,
3341 .iov_len = body_len /* no sizeof(state->body) .. :-) */
3345 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
3348 ok = smb2_setup_nbt_length(state->vector,
3349 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
3350 if (!ok) {
3351 return NT_STATUS_INVALID_PARAMETER_MIX;
3354 if (do_encryption) {
3355 DATA_BLOB encryption_key = session->global->encryption_key;
3357 status = smb2_signing_encrypt_pdu(encryption_key,
3358 xconn->smb2.server.cipher,
3359 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
3360 SMBD_SMB2_NUM_IOV_PER_REQ);
3361 if (!NT_STATUS_IS_OK(status)) {
3362 return status;
3366 state->queue_entry.mem_ctx = state;
3367 state->queue_entry.vector = state->vector;
3368 state->queue_entry.count = ARRAY_SIZE(state->vector);
3369 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
3370 xconn->smb2.send_queue_len++;
3372 status = smbd_smb2_flush_send_queue(xconn);
3373 if (!NT_STATUS_IS_OK(status)) {
3374 return status;
3377 return NT_STATUS_OK;
3380 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_connection *xconn,
3381 struct smbXsrv_session *session,
3382 struct smbXsrv_tcon *tcon,
3383 struct smbXsrv_open *op,
3384 uint8_t oplock_level)
3386 uint8_t body[0x18];
3388 SSVAL(body, 0x00, sizeof(body));
3389 SCVAL(body, 0x02, oplock_level);
3390 SCVAL(body, 0x03, 0); /* reserved */
3391 SIVAL(body, 0x04, 0); /* reserved */
3392 SBVAL(body, 0x08, op->global->open_persistent_id);
3393 SBVAL(body, 0x10, op->global->open_volatile_id);
3395 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3398 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_connection *xconn,
3399 uint16_t new_epoch,
3400 uint32_t lease_flags,
3401 struct smb2_lease_key *lease_key,
3402 uint32_t current_lease_state,
3403 uint32_t new_lease_state)
3405 uint8_t body[0x2c];
3407 SSVAL(body, 0x00, sizeof(body));
3408 SSVAL(body, 0x02, new_epoch);
3409 SIVAL(body, 0x04, lease_flags);
3410 SBVAL(body, 0x08, lease_key->data[0]);
3411 SBVAL(body, 0x10, lease_key->data[1]);
3412 SIVAL(body, 0x18, current_lease_state);
3413 SIVAL(body, 0x1c, new_lease_state);
3414 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
3415 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
3416 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
3418 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3421 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
3423 NTSTATUS status;
3424 uint32_t flags;
3425 uint64_t file_id_persistent;
3426 uint64_t file_id_volatile;
3427 struct smbXsrv_open *op = NULL;
3428 struct files_struct *fsp = NULL;
3429 const uint8_t *body = NULL;
3432 * This is only called with a pktbuf
3433 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
3434 * bytes
3437 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
3438 /* Transform header. Cannot recvfile. */
3439 return false;
3441 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
3442 /* Not SMB2. Normal error path will cope. */
3443 return false;
3445 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
3446 /* Not SMB2. Normal error path will cope. */
3447 return false;
3449 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
3450 /* Needs to be a WRITE. */
3451 return false;
3453 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
3454 /* Chained. Cannot recvfile. */
3455 return false;
3457 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
3458 if (flags & SMB2_HDR_FLAG_CHAINED) {
3459 /* Chained. Cannot recvfile. */
3460 return false;
3462 if (flags & SMB2_HDR_FLAG_SIGNED) {
3463 /* Signed. Cannot recvfile. */
3464 return false;
3467 body = &state->pktbuf[SMB2_HDR_BODY];
3469 file_id_persistent = BVAL(body, 0x10);
3470 file_id_volatile = BVAL(body, 0x18);
3472 status = smb2srv_open_lookup(state->req->xconn,
3473 file_id_persistent,
3474 file_id_volatile,
3475 0, /* now */
3476 &op);
3477 if (!NT_STATUS_IS_OK(status)) {
3478 return false;
3481 fsp = op->compat;
3482 if (fsp == NULL) {
3483 return false;
3485 if (fsp->conn == NULL) {
3486 return false;
3489 if (IS_IPC(fsp->conn)) {
3490 return false;
3492 if (IS_PRINT(fsp->conn)) {
3493 return false;
3496 DEBUG(10,("Doing recvfile write len = %u\n",
3497 (unsigned int)(state->pktfull - state->pktlen)));
3499 return true;
3502 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
3504 struct smbd_server_connection *sconn = xconn->client->sconn;
3505 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3506 size_t max_send_queue_len;
3507 size_t cur_send_queue_len;
3509 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3511 * we're not supposed to do any io
3513 return NT_STATUS_OK;
3516 if (state->req != NULL) {
3518 * if there is already a tstream_readv_pdu
3519 * pending, we are done.
3521 return NT_STATUS_OK;
3524 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
3525 cur_send_queue_len = xconn->smb2.send_queue_len;
3527 if (cur_send_queue_len > max_send_queue_len) {
3529 * if we have a lot of requests to send,
3530 * we wait until they are on the wire until we
3531 * ask for the next request.
3533 return NT_STATUS_OK;
3536 /* ask for the next request */
3537 ZERO_STRUCTP(state);
3538 state->req = smbd_smb2_request_allocate(xconn);
3539 if (state->req == NULL) {
3540 return NT_STATUS_NO_MEMORY;
3542 state->req->sconn = sconn;
3543 state->req->xconn = xconn;
3544 state->min_recv_size = lp_min_receive_file_size();
3546 TEVENT_FD_READABLE(xconn->transport.fde);
3548 return NT_STATUS_OK;
3551 void smbd_smb2_process_negprot(struct smbXsrv_connection *xconn,
3552 uint64_t expected_seq_low,
3553 const uint8_t *inpdu, size_t size)
3555 struct smbd_server_connection *sconn = xconn->client->sconn;
3556 NTSTATUS status;
3557 struct smbd_smb2_request *req = NULL;
3559 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3560 (unsigned int)size));
3562 status = smbd_initialize_smb2(xconn, expected_seq_low);
3563 if (!NT_STATUS_IS_OK(status)) {
3564 smbd_server_connection_terminate(xconn, nt_errstr(status));
3565 return;
3568 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
3569 if (!NT_STATUS_IS_OK(status)) {
3570 smbd_server_connection_terminate(xconn, nt_errstr(status));
3571 return;
3574 status = smbd_smb2_request_validate(req);
3575 if (!NT_STATUS_IS_OK(status)) {
3576 smbd_server_connection_terminate(xconn, nt_errstr(status));
3577 return;
3580 status = smbd_smb2_request_setup_out(req);
3581 if (!NT_STATUS_IS_OK(status)) {
3582 smbd_server_connection_terminate(xconn, nt_errstr(status));
3583 return;
3586 #ifdef WITH_PROFILE
3588 * this was already counted at the SMB1 layer =>
3589 * smbd_smb2_request_dispatch() should not count it twice.
3591 if (profile_p->values.request_stats.count > 0) {
3592 profile_p->values.request_stats.count--;
3594 #endif
3595 status = smbd_smb2_request_dispatch(req);
3596 if (!NT_STATUS_IS_OK(status)) {
3597 smbd_server_connection_terminate(xconn, nt_errstr(status));
3598 return;
3601 status = smbd_smb2_request_next_incoming(xconn);
3602 if (!NT_STATUS_IS_OK(status)) {
3603 smbd_server_connection_terminate(xconn, nt_errstr(status));
3604 return;
3607 sconn->num_requests++;
3610 static int socket_error_from_errno(int ret,
3611 int sys_errno,
3612 bool *retry)
3614 *retry = false;
3616 if (ret >= 0) {
3617 return 0;
3620 if (ret != -1) {
3621 return EIO;
3624 if (sys_errno == 0) {
3625 return EIO;
3628 if (sys_errno == EINTR) {
3629 *retry = true;
3630 return sys_errno;
3633 if (sys_errno == EINPROGRESS) {
3634 *retry = true;
3635 return sys_errno;
3638 if (sys_errno == EAGAIN) {
3639 *retry = true;
3640 return sys_errno;
3643 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3644 if (sys_errno == ENOMEM) {
3645 *retry = true;
3646 return sys_errno;
3649 #ifdef EWOULDBLOCK
3650 #if EWOULDBLOCK != EAGAIN
3651 if (sys_errno == EWOULDBLOCK) {
3652 *retry = true;
3653 return sys_errno;
3655 #endif
3656 #endif
3658 return sys_errno;
3661 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3663 int ret;
3664 int err;
3665 bool retry;
3666 NTSTATUS status;
3668 if (xconn->smb2.send_queue == NULL) {
3669 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3670 return NT_STATUS_OK;
3673 while (xconn->smb2.send_queue != NULL) {
3674 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3675 bool ok;
3677 if (e->sendfile_header != NULL) {
3678 size_t size = 0;
3679 size_t i = 0;
3680 uint8_t *buf;
3682 status = NT_STATUS_INTERNAL_ERROR;
3684 for (i=0; i < e->count; i++) {
3685 size += e->vector[i].iov_len;
3688 if (size <= e->sendfile_header->length) {
3689 buf = e->sendfile_header->data;
3690 } else {
3691 buf = talloc_array(e->mem_ctx, uint8_t, size);
3692 if (buf == NULL) {
3693 return NT_STATUS_NO_MEMORY;
3697 size = 0;
3698 for (i=0; i < e->count; i++) {
3699 memcpy(buf+size,
3700 e->vector[i].iov_base,
3701 e->vector[i].iov_len);
3702 size += e->vector[i].iov_len;
3705 e->sendfile_header->data = buf;
3706 e->sendfile_header->length = size;
3707 e->sendfile_status = &status;
3708 e->count = 0;
3710 xconn->smb2.send_queue_len--;
3711 DLIST_REMOVE(xconn->smb2.send_queue, e);
3713 * This triggers the sendfile path via
3714 * the destructor.
3716 talloc_free(e->mem_ctx);
3718 if (!NT_STATUS_IS_OK(status)) {
3719 return status;
3721 continue;
3724 ret = writev(xconn->transport.sock, e->vector, e->count);
3725 if (ret == 0) {
3726 /* propagate end of file */
3727 return NT_STATUS_INTERNAL_ERROR;
3729 err = socket_error_from_errno(ret, errno, &retry);
3730 if (retry) {
3731 /* retry later */
3732 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3733 return NT_STATUS_OK;
3735 if (err != 0) {
3736 return map_nt_error_from_unix_common(err);
3739 ok = iov_advance(&e->vector, &e->count, ret);
3740 if (!ok) {
3741 return NT_STATUS_INTERNAL_ERROR;
3744 if (e->count > 0) {
3745 /* we have more to write */
3746 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3747 return NT_STATUS_OK;
3750 xconn->smb2.send_queue_len--;
3751 DLIST_REMOVE(xconn->smb2.send_queue, e);
3752 talloc_free(e->mem_ctx);
3756 * Restart reads if we were blocked on
3757 * draining the send queue.
3760 status = smbd_smb2_request_next_incoming(xconn);
3761 if (!NT_STATUS_IS_OK(status)) {
3762 return status;
3765 return NT_STATUS_OK;
3768 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3769 uint16_t fde_flags)
3771 struct smbd_server_connection *sconn = xconn->client->sconn;
3772 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3773 struct smbd_smb2_request *req = NULL;
3774 size_t min_recvfile_size = UINT32_MAX;
3775 int ret;
3776 int err;
3777 bool retry;
3778 NTSTATUS status;
3779 NTTIME now;
3781 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3783 * we're not supposed to do any io
3785 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3786 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3787 return NT_STATUS_OK;
3790 if (fde_flags & TEVENT_FD_WRITE) {
3791 status = smbd_smb2_flush_send_queue(xconn);
3792 if (!NT_STATUS_IS_OK(status)) {
3793 return status;
3797 if (!(fde_flags & TEVENT_FD_READ)) {
3798 return NT_STATUS_OK;
3801 if (state->req == NULL) {
3802 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3803 return NT_STATUS_OK;
3806 again:
3807 if (!state->hdr.done) {
3808 state->hdr.done = true;
3810 state->vector.iov_base = (void *)state->hdr.nbt;
3811 state->vector.iov_len = NBT_HDR_SIZE;
3814 ret = readv(xconn->transport.sock, &state->vector, 1);
3815 if (ret == 0) {
3816 /* propagate end of file */
3817 return NT_STATUS_END_OF_FILE;
3819 err = socket_error_from_errno(ret, errno, &retry);
3820 if (retry) {
3821 /* retry later */
3822 TEVENT_FD_READABLE(xconn->transport.fde);
3823 return NT_STATUS_OK;
3825 if (err != 0) {
3826 return map_nt_error_from_unix_common(err);
3829 if (ret < state->vector.iov_len) {
3830 uint8_t *base;
3831 base = (uint8_t *)state->vector.iov_base;
3832 base += ret;
3833 state->vector.iov_base = (void *)base;
3834 state->vector.iov_len -= ret;
3835 /* we have more to read */
3836 TEVENT_FD_READABLE(xconn->transport.fde);
3837 return NT_STATUS_OK;
3840 if (state->pktlen > 0) {
3841 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3843 * Not a possible receivefile write.
3844 * Read the rest of the data.
3846 state->doing_receivefile = false;
3848 state->pktbuf = talloc_realloc(state->req,
3849 state->pktbuf,
3850 uint8_t,
3851 state->pktfull);
3852 if (state->pktbuf == NULL) {
3853 return NT_STATUS_NO_MEMORY;
3856 state->vector.iov_base = (void *)(state->pktbuf +
3857 state->pktlen);
3858 state->vector.iov_len = (state->pktfull -
3859 state->pktlen);
3861 state->pktlen = state->pktfull;
3862 goto again;
3866 * Either this is a receivefile write so we've
3867 * done a short read, or if not we have all the data.
3869 goto got_full;
3873 * Now we analyze the NBT header
3875 if (state->hdr.nbt[0] != 0x00) {
3876 state->min_recv_size = 0;
3878 state->pktfull = smb2_len(state->hdr.nbt);
3879 if (state->pktfull == 0) {
3880 goto got_full;
3883 if (state->min_recv_size != 0) {
3884 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3885 min_recvfile_size += state->min_recv_size;
3888 if (state->pktfull > min_recvfile_size) {
3890 * Might be a receivefile write. Read the SMB2 HEADER +
3891 * SMB2_WRITE header first. Set 'doing_receivefile'
3892 * as we're *attempting* receivefile write. If this
3893 * turns out not to be a SMB2_WRITE request or otherwise
3894 * not suitable then we'll just read the rest of the data
3895 * the next time this function is called.
3897 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3898 state->doing_receivefile = true;
3899 } else {
3900 state->pktlen = state->pktfull;
3903 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3904 if (state->pktbuf == NULL) {
3905 return NT_STATUS_NO_MEMORY;
3908 state->vector.iov_base = (void *)state->pktbuf;
3909 state->vector.iov_len = state->pktlen;
3911 goto again;
3913 got_full:
3915 if (state->hdr.nbt[0] != 0x00) {
3916 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3917 state->hdr.nbt[0]));
3919 req = state->req;
3920 ZERO_STRUCTP(state);
3921 state->req = req;
3922 state->min_recv_size = lp_min_receive_file_size();
3923 req = NULL;
3924 goto again;
3927 req = state->req;
3928 state->req = NULL;
3930 req->request_time = timeval_current();
3931 now = timeval_to_nttime(&req->request_time);
3933 status = smbd_smb2_inbuf_parse_compound(xconn,
3934 now,
3935 state->pktbuf,
3936 state->pktlen,
3937 req,
3938 &req->in.vector,
3939 &req->in.vector_count);
3940 if (!NT_STATUS_IS_OK(status)) {
3941 return status;
3944 if (state->doing_receivefile) {
3945 req->smb1req = talloc_zero(req, struct smb_request);
3946 if (req->smb1req == NULL) {
3947 return NT_STATUS_NO_MEMORY;
3949 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3952 ZERO_STRUCTP(state);
3954 req->current_idx = 1;
3956 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3957 req->current_idx, req->in.vector_count));
3959 status = smbd_smb2_request_validate(req);
3960 if (!NT_STATUS_IS_OK(status)) {
3961 return status;
3964 status = smbd_smb2_request_setup_out(req);
3965 if (!NT_STATUS_IS_OK(status)) {
3966 return status;
3969 status = smbd_smb2_request_dispatch(req);
3970 if (!NT_STATUS_IS_OK(status)) {
3971 return status;
3974 sconn->num_requests++;
3976 /* The timeout_processing function isn't run nearly
3977 often enough to implement 'max log size' without
3978 overrunning the size of the file by many megabytes.
3979 This is especially true if we are running at debug
3980 level 10. Checking every 50 SMB2s is a nice
3981 tradeoff of performance vs log file size overrun. */
3983 if ((sconn->num_requests % 50) == 0 &&
3984 need_to_check_log_size()) {
3985 change_to_root_user();
3986 check_log_size();
3989 status = smbd_smb2_request_next_incoming(xconn);
3990 if (!NT_STATUS_IS_OK(status)) {
3991 return status;
3994 return NT_STATUS_OK;
3997 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3998 struct tevent_fd *fde,
3999 uint16_t flags,
4000 void *private_data)
4002 struct smbXsrv_connection *xconn =
4003 talloc_get_type_abort(private_data,
4004 struct smbXsrv_connection);
4005 NTSTATUS status;
4007 status = smbd_smb2_io_handler(xconn, flags);
4008 if (!NT_STATUS_IS_OK(status)) {
4009 smbd_server_connection_terminate(xconn, nt_errstr(status));
4010 return;