dbchecker: improve verbose output of do_modify()
[Samba.git] / source3 / smbd / smb2_server.c
blobe36db1e55f5e3ce12b888927aac053e45e27e3e1
1 /*
2 Unix SMB/CIFS implementation.
3 Core SMB2 server
5 Copyright (C) Stefan Metzmacher 2009
6 Copyright (C) Jeremy Allison 2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../libcli/smb/smb_common.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "../lib/util/tevent_ntstatus.h"
28 #include "smbprofile.h"
29 #include "../lib/util/bitmap.h"
30 #include "../librpc/gen_ndr/krb5pac.h"
31 #include "lib/util/iov_buf.h"
32 #include "auth.h"
33 #include "lib/crypto/sha512.h"
35 #undef DBGC_CLASS
36 #define DBGC_CLASS DBGC_SMB2
38 static void smbd_smb2_connection_handler(struct tevent_context *ev,
39 struct tevent_fd *fde,
40 uint16_t flags,
41 void *private_data);
42 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn);
44 static const struct smbd_smb2_dispatch_table {
45 uint16_t opcode;
46 const char *name;
47 bool need_session;
48 bool need_tcon;
49 bool as_root;
50 uint16_t fileid_ofs;
51 bool allow_invalid_fileid;
52 bool modify;
53 } smbd_smb2_table[] = {
54 #define _OP(o) .opcode = o, .name = #o
56 _OP(SMB2_OP_NEGPROT),
57 .as_root = true,
58 },{
59 _OP(SMB2_OP_SESSSETUP),
60 .as_root = true,
61 },{
62 _OP(SMB2_OP_LOGOFF),
63 .need_session = true,
64 .as_root = true,
65 },{
66 _OP(SMB2_OP_TCON),
67 .need_session = true,
69 * This call needs to be run as root.
71 * smbd_smb2_request_process_tcon()
72 * calls make_connection_snum(), which will call
73 * change_to_user(), when needed.
75 .as_root = true,
76 },{
77 _OP(SMB2_OP_TDIS),
78 .need_session = true,
79 .need_tcon = true,
80 .as_root = true,
81 },{
82 _OP(SMB2_OP_CREATE),
83 .need_session = true,
84 .need_tcon = true,
85 },{
86 _OP(SMB2_OP_CLOSE),
87 .need_session = true,
88 .need_tcon = true,
89 .fileid_ofs = 0x08,
90 },{
91 _OP(SMB2_OP_FLUSH),
92 .need_session = true,
93 .need_tcon = true,
94 .fileid_ofs = 0x08,
95 },{
96 _OP(SMB2_OP_READ),
97 .need_session = true,
98 .need_tcon = true,
99 .fileid_ofs = 0x10,
101 _OP(SMB2_OP_WRITE),
102 .need_session = true,
103 .need_tcon = true,
104 .fileid_ofs = 0x10,
105 .modify = true,
107 _OP(SMB2_OP_LOCK),
108 .need_session = true,
109 .need_tcon = true,
110 .fileid_ofs = 0x08,
112 _OP(SMB2_OP_IOCTL),
113 .need_session = true,
114 .need_tcon = true,
115 .fileid_ofs = 0x08,
116 .allow_invalid_fileid = true,
117 .modify = true,
119 _OP(SMB2_OP_CANCEL),
120 .as_root = true,
122 _OP(SMB2_OP_KEEPALIVE),
123 .as_root = true,
125 _OP(SMB2_OP_QUERY_DIRECTORY),
126 .need_session = true,
127 .need_tcon = true,
128 .fileid_ofs = 0x08,
130 _OP(SMB2_OP_NOTIFY),
131 .need_session = true,
132 .need_tcon = true,
133 .fileid_ofs = 0x08,
135 _OP(SMB2_OP_GETINFO),
136 .need_session = true,
137 .need_tcon = true,
138 .fileid_ofs = 0x18,
140 _OP(SMB2_OP_SETINFO),
141 .need_session = true,
142 .need_tcon = true,
143 .fileid_ofs = 0x10,
144 .modify = true,
146 _OP(SMB2_OP_BREAK),
147 .need_session = true,
148 .need_tcon = true,
150 * we do not set
151 * .fileid_ofs here
152 * as LEASE breaks does not
153 * have a file id
158 const char *smb2_opcode_name(uint16_t opcode)
160 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
161 return "Bad SMB2 opcode";
163 return smbd_smb2_table[opcode].name;
166 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
168 const struct smbd_smb2_dispatch_table *ret = NULL;
170 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
171 return NULL;
174 ret = &smbd_smb2_table[opcode];
176 SMB_ASSERT(ret->opcode == opcode);
178 return ret;
181 static void print_req_vectors(const struct smbd_smb2_request *req)
183 int i;
185 for (i = 0; i < req->in.vector_count; i++) {
186 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
187 (unsigned int)i,
188 (unsigned int)req->in.vector[i].iov_len);
190 for (i = 0; i < req->out.vector_count; i++) {
191 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
192 (unsigned int)i,
193 (unsigned int)req->out.vector[i].iov_len);
197 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
199 if (size < (4 + SMB2_HDR_BODY)) {
200 return false;
203 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
204 return false;
207 return true;
210 bool smbd_smb2_is_compound(const struct smbd_smb2_request *req)
212 return req->in.vector_count >= (2*SMBD_SMB2_NUM_IOV_PER_REQ);
215 static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn,
216 uint64_t expected_seq_low)
218 TALLOC_FREE(xconn->transport.fde);
220 xconn->smb2.credits.seq_low = expected_seq_low;
221 xconn->smb2.credits.seq_range = 1;
222 xconn->smb2.credits.granted = 1;
223 xconn->smb2.credits.max = lp_smb2_max_credits();
224 xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
225 xconn->smb2.credits.max);
226 if (xconn->smb2.credits.bitmap == NULL) {
227 return NT_STATUS_NO_MEMORY;
230 xconn->transport.fde = tevent_add_fd(
231 xconn->client->raw_ev_ctx,
232 xconn,
233 xconn->transport.sock,
234 TEVENT_FD_READ,
235 smbd_smb2_connection_handler,
236 xconn);
237 if (xconn->transport.fde == NULL) {
238 return NT_STATUS_NO_MEMORY;
241 /* Ensure child is set to non-blocking mode */
242 set_blocking(xconn->transport.sock, false);
243 return NT_STATUS_OK;
246 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
247 #define _smb2_setlen(_buf,len) do { \
248 uint8_t *buf = (uint8_t *)_buf; \
249 buf[0] = 0; \
250 buf[1] = ((len)&0xFF0000)>>16; \
251 buf[2] = ((len)&0xFF00)>>8; \
252 buf[3] = (len)&0xFF; \
253 } while (0)
255 static bool smb2_setup_nbt_length(struct iovec *vector, int count)
257 ssize_t len;
259 if (count == 0) {
260 return false;
263 len = iov_buflen(vector+1, count-1);
265 if ((len == -1) || (len > 0xFFFFFF)) {
266 return false;
269 _smb2_setlen(vector[0].iov_base, len);
270 return true;
273 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
275 if (req->first_key.length > 0) {
276 data_blob_clear_free(&req->first_key);
278 if (req->last_key.length > 0) {
279 data_blob_clear_free(&req->last_key);
281 return 0;
284 void smb2_request_set_async_internal(struct smbd_smb2_request *req,
285 bool async_internal)
287 req->async_internal = async_internal;
290 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
292 TALLOC_CTX *mem_pool;
293 struct smbd_smb2_request *req;
295 #if 0
296 /* Enable this to find subtle valgrind errors. */
297 mem_pool = talloc_init("smbd_smb2_request_allocate");
298 #else
299 mem_pool = talloc_tos();
300 #endif
301 if (mem_pool == NULL) {
302 return NULL;
305 req = talloc_zero(mem_pool, struct smbd_smb2_request);
306 if (req == NULL) {
307 talloc_free(mem_pool);
308 return NULL;
310 talloc_reparent(mem_pool, mem_ctx, req);
311 #if 0
312 TALLOC_FREE(mem_pool);
313 #endif
315 req->last_session_id = UINT64_MAX;
316 req->last_tid = UINT32_MAX;
318 talloc_set_destructor(req, smbd_smb2_request_destructor);
320 return req;
323 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
324 NTTIME now,
325 uint8_t *buf,
326 size_t buflen,
327 struct smbd_smb2_request *req,
328 struct iovec **piov,
329 int *pnum_iov)
331 TALLOC_CTX *mem_ctx = req;
332 struct iovec *iov;
333 int num_iov = 1;
334 size_t taken = 0;
335 uint8_t *first_hdr = buf;
336 size_t verified_buflen = 0;
337 uint8_t *tf = NULL;
338 size_t tf_len = 0;
341 * Note: index '0' is reserved for the transport protocol
343 iov = req->in._vector;
345 while (taken < buflen) {
346 size_t len = buflen - taken;
347 uint8_t *hdr = first_hdr + taken;
348 struct iovec *cur;
349 size_t full_size;
350 size_t next_command_ofs;
351 uint16_t body_size;
352 uint8_t *body = NULL;
353 uint32_t dyn_size;
354 uint8_t *dyn = NULL;
355 struct iovec *iov_alloc = NULL;
357 if (iov != req->in._vector) {
358 iov_alloc = iov;
361 if (verified_buflen > taken) {
362 len = verified_buflen - taken;
363 } else {
364 tf = NULL;
365 tf_len = 0;
368 if (len < 4) {
369 DEBUG(10, ("%d bytes left, expected at least %d\n",
370 (int)len, 4));
371 goto inval;
373 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
374 struct smbXsrv_session *s = NULL;
375 uint64_t uid;
376 struct iovec tf_iov[2];
377 NTSTATUS status;
378 size_t enc_len;
380 if (xconn->protocol < PROTOCOL_SMB2_24) {
381 DEBUG(10, ("Got SMB2_TRANSFORM header, "
382 "but dialect[0x%04X] is used\n",
383 xconn->smb2.server.dialect));
384 goto inval;
387 if (xconn->smb2.server.cipher == 0) {
388 DEBUG(10, ("Got SMB2_TRANSFORM header, "
389 "but not negotiated "
390 "client[0x%08X] server[0x%08X]\n",
391 xconn->smb2.client.capabilities,
392 xconn->smb2.server.capabilities));
393 goto inval;
396 if (len < SMB2_TF_HDR_SIZE) {
397 DEBUG(1, ("%d bytes left, expected at least %d\n",
398 (int)len, SMB2_TF_HDR_SIZE));
399 goto inval;
401 tf = hdr;
402 tf_len = SMB2_TF_HDR_SIZE;
403 taken += tf_len;
405 hdr = first_hdr + taken;
406 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
407 uid = BVAL(tf, SMB2_TF_SESSION_ID);
409 if (len < SMB2_TF_HDR_SIZE + enc_len) {
410 DEBUG(1, ("%d bytes left, expected at least %d\n",
411 (int)len,
412 (int)(SMB2_TF_HDR_SIZE + enc_len)));
413 goto inval;
416 status = smb2srv_session_lookup_conn(xconn, uid, now,
417 &s);
418 if (s == NULL) {
419 DEBUG(1, ("invalid session[%llu] in "
420 "SMB2_TRANSFORM header\n",
421 (unsigned long long)uid));
422 TALLOC_FREE(iov_alloc);
423 return NT_STATUS_USER_SESSION_DELETED;
426 tf_iov[0].iov_base = (void *)tf;
427 tf_iov[0].iov_len = tf_len;
428 tf_iov[1].iov_base = (void *)hdr;
429 tf_iov[1].iov_len = enc_len;
431 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
432 xconn->smb2.server.cipher,
433 tf_iov, 2);
434 if (!NT_STATUS_IS_OK(status)) {
435 TALLOC_FREE(iov_alloc);
436 return status;
439 verified_buflen = taken + enc_len;
440 len = enc_len;
444 * We need the header plus the body length field
447 if (len < SMB2_HDR_BODY + 2) {
448 DEBUG(10, ("%d bytes left, expected at least %d\n",
449 (int)len, SMB2_HDR_BODY));
450 goto inval;
452 if (IVAL(hdr, 0) != SMB2_MAGIC) {
453 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
454 IVAL(hdr, 0)));
455 goto inval;
457 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
458 DEBUG(10, ("Got HDR len %d, expected %d\n",
459 SVAL(hdr, 4), SMB2_HDR_BODY));
460 goto inval;
463 full_size = len;
464 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
465 body_size = SVAL(hdr, SMB2_HDR_BODY);
467 if (next_command_ofs != 0) {
468 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
469 goto inval;
471 if (next_command_ofs > full_size) {
472 goto inval;
474 full_size = next_command_ofs;
476 if (body_size < 2) {
477 goto inval;
479 body_size &= 0xfffe;
481 if (body_size > (full_size - SMB2_HDR_BODY)) {
483 * let the caller handle the error
485 body_size = full_size - SMB2_HDR_BODY;
487 body = hdr + SMB2_HDR_BODY;
488 dyn = body + body_size;
489 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
491 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
492 struct iovec *iov_tmp = NULL;
494 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
495 struct iovec,
496 num_iov +
497 SMBD_SMB2_NUM_IOV_PER_REQ);
498 if (iov_tmp == NULL) {
499 TALLOC_FREE(iov_alloc);
500 return NT_STATUS_NO_MEMORY;
503 if (iov_alloc == NULL) {
504 memcpy(iov_tmp,
505 req->in._vector,
506 sizeof(req->in._vector));
509 iov = iov_tmp;
511 cur = &iov[num_iov];
512 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
514 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
515 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
516 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
517 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
518 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
519 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
520 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
521 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
523 taken += full_size;
526 *piov = iov;
527 *pnum_iov = num_iov;
528 return NT_STATUS_OK;
530 inval:
531 if (iov != req->in._vector) {
532 TALLOC_FREE(iov);
534 return NT_STATUS_INVALID_PARAMETER;
537 static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
538 const uint8_t *_inpdu, size_t size,
539 struct smbd_smb2_request **_req)
541 struct smbd_server_connection *sconn = xconn->client->sconn;
542 struct smbd_smb2_request *req;
543 uint32_t protocol_version;
544 uint8_t *inpdu = NULL;
545 const uint8_t *inhdr = NULL;
546 uint16_t cmd;
547 uint32_t next_command_ofs;
548 NTSTATUS status;
549 NTTIME now;
551 if (size < (SMB2_HDR_BODY + 2)) {
552 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
553 return NT_STATUS_INVALID_PARAMETER;
556 inhdr = _inpdu;
558 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
559 if (protocol_version != SMB2_MAGIC) {
560 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
561 protocol_version));
562 return NT_STATUS_INVALID_PARAMETER;
565 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
566 if (cmd != SMB2_OP_NEGPROT) {
567 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
568 cmd));
569 return NT_STATUS_INVALID_PARAMETER;
572 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
573 if (next_command_ofs != 0) {
574 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
575 next_command_ofs));
576 return NT_STATUS_INVALID_PARAMETER;
579 req = smbd_smb2_request_allocate(xconn);
580 if (req == NULL) {
581 return NT_STATUS_NO_MEMORY;
583 req->sconn = sconn;
584 req->xconn = xconn;
586 inpdu = talloc_memdup(req, _inpdu, size);
587 if (inpdu == NULL) {
588 return NT_STATUS_NO_MEMORY;
591 req->request_time = timeval_current();
592 now = timeval_to_nttime(&req->request_time);
594 status = smbd_smb2_inbuf_parse_compound(xconn,
595 now,
596 inpdu,
597 size,
598 req, &req->in.vector,
599 &req->in.vector_count);
600 if (!NT_STATUS_IS_OK(status)) {
601 TALLOC_FREE(req);
602 return status;
605 req->current_idx = 1;
607 *_req = req;
608 return NT_STATUS_OK;
611 static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
612 uint64_t message_id, uint64_t seq_id)
614 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
615 unsigned int offset;
616 uint64_t seq_tmp;
618 seq_tmp = xconn->smb2.credits.seq_low;
619 if (seq_id < seq_tmp) {
620 DBGC_ERR(DBGC_SMB2_CREDITS,
621 "smb2_validate_sequence_number: bad message_id "
622 "%llu (sequence id %llu) "
623 "(granted = %u, low = %llu, range = %u)\n",
624 (unsigned long long)message_id,
625 (unsigned long long)seq_id,
626 (unsigned int)xconn->smb2.credits.granted,
627 (unsigned long long)xconn->smb2.credits.seq_low,
628 (unsigned int)xconn->smb2.credits.seq_range);
629 return false;
632 seq_tmp += xconn->smb2.credits.seq_range;
633 if (seq_id >= seq_tmp) {
634 DBGC_ERR(DBGC_SMB2_CREDITS,
635 "smb2_validate_sequence_number: bad message_id "
636 "%llu (sequence id %llu) "
637 "(granted = %u, low = %llu, range = %u)\n",
638 (unsigned long long)message_id,
639 (unsigned long long)seq_id,
640 (unsigned int)xconn->smb2.credits.granted,
641 (unsigned long long)xconn->smb2.credits.seq_low,
642 (unsigned int)xconn->smb2.credits.seq_range);
643 return false;
646 offset = seq_id % xconn->smb2.credits.max;
648 if (bitmap_query(credits_bm, offset)) {
649 DBGC_ERR(DBGC_SMB2_CREDITS,
650 "smb2_validate_sequence_number: duplicate message_id "
651 "%llu (sequence id %llu) "
652 "(granted = %u, low = %llu, range = %u) "
653 "(bm offset %u)\n",
654 (unsigned long long)message_id,
655 (unsigned long long)seq_id,
656 (unsigned int)xconn->smb2.credits.granted,
657 (unsigned long long)xconn->smb2.credits.seq_low,
658 (unsigned int)xconn->smb2.credits.seq_range,
659 offset);
660 return false;
663 /* Mark the message_ids as seen in the bitmap. */
664 bitmap_set(credits_bm, offset);
666 if (seq_id != xconn->smb2.credits.seq_low) {
667 return true;
671 * Move the window forward by all the message_id's
672 * already seen.
674 while (bitmap_query(credits_bm, offset)) {
675 DBGC_DEBUG(DBGC_SMB2_CREDITS,
676 "smb2_validate_sequence_number: clearing "
677 "id %llu (position %u) from bitmap\n",
678 (unsigned long long)(xconn->smb2.credits.seq_low),
679 offset);
680 bitmap_clear(credits_bm, offset);
682 xconn->smb2.credits.seq_low += 1;
683 xconn->smb2.credits.seq_range -= 1;
684 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
687 return true;
690 static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
691 const uint8_t *inhdr)
693 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
694 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
695 uint16_t credit_charge = 1;
696 uint64_t i;
698 if (opcode == SMB2_OP_CANCEL) {
699 /* SMB2_CANCEL requests by definition resend messageids. */
700 return true;
703 if (xconn->smb2.credits.multicredit) {
704 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
705 credit_charge = MAX(credit_charge, 1);
708 DEBUGC(11,
709 DBGC_SMB2_CREDITS,
710 ("smb2_validate_message_id: mid %llu (charge %llu), "
711 "credits_granted %llu, "
712 "seqnum low/range: %llu/%llu\n",
713 (unsigned long long) message_id,
714 (unsigned long long) credit_charge,
715 (unsigned long long) xconn->smb2.credits.granted,
716 (unsigned long long) xconn->smb2.credits.seq_low,
717 (unsigned long long) xconn->smb2.credits.seq_range));
719 if (xconn->smb2.credits.granted < credit_charge) {
720 DBGC_ERR(DBGC_SMB2_CREDITS,
721 "smb2_validate_message_id: client used more "
722 "credits than granted, mid %llu, charge %llu, "
723 "credits_granted %llu, "
724 "seqnum low/range: %llu/%llu\n",
725 (unsigned long long) message_id,
726 (unsigned long long) credit_charge,
727 (unsigned long long) xconn->smb2.credits.granted,
728 (unsigned long long) xconn->smb2.credits.seq_low,
729 (unsigned long long) xconn->smb2.credits.seq_range);
730 return false;
734 * now check the message ids
736 * for multi-credit requests we need to check all current mid plus
737 * the implicit mids caused by the credit charge
738 * e.g. current mid = 15, charge 5 => mark 15-19 as used
741 for (i = 0; i <= (credit_charge-1); i++) {
742 uint64_t id = message_id + i;
743 bool ok;
745 DEBUGC(11,
746 DBGC_SMB2_CREDITS,
747 ("Iterating mid %llu charge %u (sequence %llu)\n",
748 (unsigned long long)message_id,
749 credit_charge,
750 (unsigned long long)id));
752 ok = smb2_validate_sequence_number(xconn, message_id, id);
753 if (!ok) {
754 return false;
758 /* substract used credits */
759 xconn->smb2.credits.granted -= credit_charge;
761 return true;
764 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
766 int count;
767 int idx;
769 count = req->in.vector_count;
771 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
772 /* It's not a SMB2 request */
773 return NT_STATUS_INVALID_PARAMETER;
776 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
777 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
778 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
779 const uint8_t *inhdr = NULL;
781 if (hdr->iov_len != SMB2_HDR_BODY) {
782 return NT_STATUS_INVALID_PARAMETER;
785 if (body->iov_len < 2) {
786 return NT_STATUS_INVALID_PARAMETER;
789 inhdr = (const uint8_t *)hdr->iov_base;
791 /* Check the SMB2 header */
792 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
793 return NT_STATUS_INVALID_PARAMETER;
796 if (!smb2_validate_message_id(req->xconn, inhdr)) {
797 return NT_STATUS_INVALID_PARAMETER;
801 return NT_STATUS_OK;
804 static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
805 const struct iovec *in_vector,
806 struct iovec *out_vector)
808 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
809 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
810 uint16_t credit_charge = 1;
811 uint16_t credits_requested;
812 uint32_t out_flags;
813 uint16_t cmd;
814 NTSTATUS out_status;
815 uint16_t credits_granted = 0;
816 uint64_t credits_possible;
817 uint16_t current_max_credits;
820 * first we grant only 1/16th of the max range.
822 * Windows also starts with the 1/16th and then grants
823 * more later. I was only able to trigger higher
824 * values, when using a very high credit charge.
826 * TODO: scale up depending on load, free memory
827 * or other stuff.
828 * Maybe also on the relationship between number
829 * of requests and the used sequence number.
830 * Which means we would grant more credits
831 * for client which use multi credit requests.
833 current_max_credits = xconn->smb2.credits.max / 16;
834 current_max_credits = MAX(current_max_credits, 1);
836 if (xconn->smb2.credits.multicredit) {
837 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
838 credit_charge = MAX(credit_charge, 1);
841 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
842 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
843 credits_requested = MAX(credits_requested, 1);
844 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
845 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
847 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
849 if (xconn->smb2.credits.max < credit_charge) {
850 smbd_server_connection_terminate(xconn,
851 "client error: credit charge > max credits\n");
852 return;
855 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
857 * In case we already send an async interim
858 * response, we should not grant
859 * credits on the final response.
861 credits_granted = 0;
862 } else {
863 uint16_t additional_possible =
864 xconn->smb2.credits.max - credit_charge;
865 uint16_t additional_max = 0;
866 uint16_t additional_credits = credits_requested - 1;
868 switch (cmd) {
869 case SMB2_OP_NEGPROT:
870 break;
871 case SMB2_OP_SESSSETUP:
873 * Windows 2012 RC1 starts to grant
874 * additional credits
875 * with a successful session setup
877 if (NT_STATUS_IS_OK(out_status)) {
878 additional_max = 32;
880 break;
881 default:
883 * We match windows and only grant additional credits
884 * in chunks of 32.
886 additional_max = 32;
887 break;
890 additional_max = MIN(additional_max, additional_possible);
891 additional_credits = MIN(additional_credits, additional_max);
893 credits_granted = credit_charge + additional_credits;
897 * sequence numbers should not wrap
899 * 1. calculate the possible credits until
900 * the sequence numbers start to wrap on 64-bit.
902 * 2. UINT64_MAX is used for Break Notifications.
904 * 2. truncate the possible credits to the maximum
905 * credits we want to grant to the client in total.
907 * 3. remove the range we'll already granted to the client
908 * this makes sure the client consumes the lowest sequence
909 * number, before we can grant additional credits.
911 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
912 if (credits_possible > 0) {
913 /* remove UINT64_MAX */
914 credits_possible -= 1;
916 credits_possible = MIN(credits_possible, current_max_credits);
917 credits_possible -= xconn->smb2.credits.seq_range;
919 credits_granted = MIN(credits_granted, credits_possible);
921 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
922 xconn->smb2.credits.granted += credits_granted;
923 xconn->smb2.credits.seq_range += credits_granted;
925 DBGC_DEBUG(DBGC_SMB2_CREDITS,
926 "smb2_set_operation_credit: requested %u, charge %u, "
927 "granted %u, current possible/max %u/%u, "
928 "total granted/max/low/range %u/%u/%llu/%u\n",
929 (unsigned int)credits_requested,
930 (unsigned int)credit_charge,
931 (unsigned int)credits_granted,
932 (unsigned int)credits_possible,
933 (unsigned int)current_max_credits,
934 (unsigned int)xconn->smb2.credits.granted,
935 (unsigned int)xconn->smb2.credits.max,
936 (unsigned long long)xconn->smb2.credits.seq_low,
937 (unsigned int)xconn->smb2.credits.seq_range);
940 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
941 struct smbd_smb2_request *outreq)
943 int count, idx;
944 uint16_t total_credits = 0;
946 count = outreq->out.vector_count;
948 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
949 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
950 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
951 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
953 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
955 /* To match Windows, count up what we
956 just granted. */
957 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
958 /* Set to zero in all but the last reply. */
959 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
960 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
961 } else {
962 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
967 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
969 if (req->current_idx <= 1) {
970 if (size <= sizeof(req->out._body)) {
971 return data_blob_const(req->out._body, size);
975 return data_blob_talloc(req, NULL, size);
978 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
980 struct smbXsrv_connection *xconn = req->xconn;
981 TALLOC_CTX *mem_ctx;
982 struct iovec *vector;
983 int count;
984 int idx;
985 bool ok;
987 count = req->in.vector_count;
988 if (count <= ARRAY_SIZE(req->out._vector)) {
989 mem_ctx = req;
990 vector = req->out._vector;
991 } else {
992 vector = talloc_zero_array(req, struct iovec, count);
993 if (vector == NULL) {
994 return NT_STATUS_NO_MEMORY;
996 mem_ctx = vector;
999 vector[0].iov_base = req->out.nbt_hdr;
1000 vector[0].iov_len = 4;
1001 SIVAL(req->out.nbt_hdr, 0, 0);
1003 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
1004 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
1005 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
1006 uint8_t *outhdr = NULL;
1007 uint8_t *outbody = NULL;
1008 uint32_t next_command_ofs = 0;
1009 struct iovec *current = &vector[idx];
1011 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
1012 /* we have a next command -
1013 * setup for the error case. */
1014 next_command_ofs = SMB2_HDR_BODY + 9;
1017 if (idx == 1) {
1018 outhdr = req->out._hdr;
1019 } else {
1020 outhdr = talloc_zero_array(mem_ctx, uint8_t,
1021 OUTVEC_ALLOC_SIZE);
1022 if (outhdr == NULL) {
1023 return NT_STATUS_NO_MEMORY;
1027 outbody = outhdr + SMB2_HDR_BODY;
1030 * SMBD_SMB2_TF_IOV_OFS might be used later
1032 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1033 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1035 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
1036 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1038 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1039 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1041 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1042 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1044 /* setup the SMB2 header */
1045 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1046 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1047 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1048 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1049 SIVAL(outhdr, SMB2_HDR_STATUS,
1050 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1051 SSVAL(outhdr, SMB2_HDR_OPCODE,
1052 SVAL(inhdr, SMB2_HDR_OPCODE));
1053 SIVAL(outhdr, SMB2_HDR_FLAGS,
1054 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1055 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1056 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1057 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1058 SIVAL(outhdr, SMB2_HDR_PID,
1059 IVAL(inhdr, SMB2_HDR_PID));
1060 SIVAL(outhdr, SMB2_HDR_TID,
1061 IVAL(inhdr, SMB2_HDR_TID));
1062 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1063 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1064 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1065 inhdr + SMB2_HDR_SIGNATURE, 16);
1067 /* setup error body header */
1068 SSVAL(outbody, 0x00, 0x08 + 1);
1069 SSVAL(outbody, 0x02, 0);
1070 SIVAL(outbody, 0x04, 0);
1073 req->out.vector = vector;
1074 req->out.vector_count = count;
1076 /* setup the length of the NBT packet */
1077 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1078 if (!ok) {
1079 return NT_STATUS_INVALID_PARAMETER_MIX;
1082 DLIST_ADD_END(xconn->smb2.requests, req);
1084 return NT_STATUS_OK;
1087 void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
1088 const char *reason,
1089 const char *location)
1091 struct smbXsrv_client *client = xconn->client;
1093 DEBUG(10,("smbd_server_connection_terminate_ex: conn[%s] reason[%s] at %s\n",
1094 smbXsrv_connection_dbg(xconn), reason, location));
1096 if (client->connections->next != NULL) {
1097 /* TODO: cancel pending requests */
1098 DLIST_REMOVE(client->connections, xconn);
1099 TALLOC_FREE(xconn);
1100 DO_PROFILE_INC(disconnect);
1101 return;
1105 * The last connection was disconnected
1107 exit_server_cleanly(reason);
1110 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1111 struct iovec *outvec,
1112 const struct iovec *srcvec)
1114 const uint8_t *srctf;
1115 size_t srctf_len;
1116 const uint8_t *srchdr;
1117 size_t srchdr_len;
1118 const uint8_t *srcbody;
1119 size_t srcbody_len;
1120 const uint8_t *expected_srcbody;
1121 const uint8_t *srcdyn;
1122 size_t srcdyn_len;
1123 const uint8_t *expected_srcdyn;
1124 uint8_t *dsttf;
1125 uint8_t *dsthdr;
1126 uint8_t *dstbody;
1127 uint8_t *dstdyn;
1129 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1130 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1131 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1132 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1133 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1134 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1135 expected_srcbody = srchdr + SMB2_HDR_BODY;
1136 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1137 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1138 expected_srcdyn = srcbody + 8;
1140 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1141 return false;
1144 if (srchdr_len != SMB2_HDR_BODY) {
1145 return false;
1148 if (srctf_len == SMB2_TF_HDR_SIZE) {
1149 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1150 if (dsttf == NULL) {
1151 return false;
1153 } else {
1154 dsttf = NULL;
1156 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1157 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1159 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1160 * be allocated with size OUTVEC_ALLOC_SIZE. */
1162 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1163 if (dsthdr == NULL) {
1164 return false;
1166 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1167 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1170 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1171 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1172 * then duplicate this. Else use talloc_memdup().
1175 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1176 dstbody = dsthdr + SMB2_HDR_BODY;
1177 } else {
1178 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1179 if (dstbody == NULL) {
1180 return false;
1183 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1184 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1187 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1188 * pointing to
1189 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1190 * then duplicate this. Else use talloc_memdup().
1193 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1194 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1195 } else if (srcdyn == NULL) {
1196 dstdyn = NULL;
1197 } else {
1198 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1199 if (dstdyn == NULL) {
1200 return false;
1203 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1204 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1206 return true;
1209 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1211 struct smbd_smb2_request *newreq = NULL;
1212 struct iovec *outvec = NULL;
1213 int count = req->out.vector_count;
1214 int i;
1215 bool ok;
1217 newreq = smbd_smb2_request_allocate(req->xconn);
1218 if (!newreq) {
1219 return NULL;
1222 newreq->sconn = req->sconn;
1223 newreq->xconn = req->xconn;
1224 newreq->session = req->session;
1225 newreq->do_encryption = req->do_encryption;
1226 newreq->do_signing = req->do_signing;
1227 newreq->current_idx = req->current_idx;
1229 outvec = talloc_zero_array(newreq, struct iovec, count);
1230 if (!outvec) {
1231 TALLOC_FREE(newreq);
1232 return NULL;
1234 newreq->out.vector = outvec;
1235 newreq->out.vector_count = count;
1237 /* Setup the outvec's identically to req. */
1238 outvec[0].iov_base = newreq->out.nbt_hdr;
1239 outvec[0].iov_len = 4;
1240 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1242 /* Setup the vectors identically to the ones in req. */
1243 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1244 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1245 break;
1249 if (i < count) {
1250 /* Alloc failed. */
1251 TALLOC_FREE(newreq);
1252 return NULL;
1255 ok = smb2_setup_nbt_length(newreq->out.vector,
1256 newreq->out.vector_count);
1257 if (!ok) {
1258 TALLOC_FREE(newreq);
1259 return NULL;
1262 return newreq;
1265 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1267 struct smbXsrv_connection *xconn = req->xconn;
1268 int first_idx = 1;
1269 struct iovec *firsttf = NULL;
1270 struct iovec *outhdr_v = NULL;
1271 uint8_t *outhdr = NULL;
1272 struct smbd_smb2_request *nreq = NULL;
1273 NTSTATUS status;
1274 bool ok;
1276 /* Create a new smb2 request we'll use
1277 for the interim return. */
1278 nreq = dup_smb2_req(req);
1279 if (!nreq) {
1280 return NT_STATUS_NO_MEMORY;
1283 /* Lose the last X out vectors. They're the
1284 ones we'll be using for the async reply. */
1285 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1287 ok = smb2_setup_nbt_length(nreq->out.vector,
1288 nreq->out.vector_count);
1289 if (!ok) {
1290 return NT_STATUS_INVALID_PARAMETER_MIX;
1293 /* Step back to the previous reply. */
1294 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1295 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1296 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1297 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1298 /* And end the chain. */
1299 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1301 /* Calculate outgoing credits */
1302 smb2_calculate_credits(req, nreq);
1304 if (DEBUGLEVEL >= 10) {
1305 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1306 (unsigned int)nreq->current_idx );
1307 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1308 (unsigned int)nreq->out.vector_count );
1309 print_req_vectors(nreq);
1313 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1314 * we need to sign/encrypt here with the last/first key we remembered
1316 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1317 status = smb2_signing_encrypt_pdu(req->first_key,
1318 xconn->smb2.server.cipher,
1319 firsttf,
1320 nreq->out.vector_count - first_idx);
1321 if (!NT_STATUS_IS_OK(status)) {
1322 return status;
1324 } else if (req->last_key.length > 0) {
1325 status = smb2_signing_sign_pdu(req->last_key,
1326 xconn->protocol,
1327 outhdr_v,
1328 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1329 if (!NT_STATUS_IS_OK(status)) {
1330 return status;
1334 nreq->queue_entry.mem_ctx = nreq;
1335 nreq->queue_entry.vector = nreq->out.vector;
1336 nreq->queue_entry.count = nreq->out.vector_count;
1337 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry);
1338 xconn->smb2.send_queue_len++;
1340 status = smbd_smb2_flush_send_queue(xconn);
1341 if (!NT_STATUS_IS_OK(status)) {
1342 return status;
1345 return NT_STATUS_OK;
1348 struct smbd_smb2_request_pending_state {
1349 struct smbd_smb2_send_queue queue_entry;
1350 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1351 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1354 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1355 struct tevent_timer *te,
1356 struct timeval current_time,
1357 void *private_data);
1359 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1360 struct tevent_req *subreq,
1361 uint32_t defer_time)
1363 NTSTATUS status;
1364 struct timeval defer_endtime;
1365 uint8_t *outhdr = NULL;
1366 uint32_t flags;
1368 if (!tevent_req_is_in_progress(subreq)) {
1370 * This is a performance optimization,
1371 * it avoids one tevent_loop iteration,
1372 * which means we avoid one
1373 * talloc_stackframe_pool/talloc_free pair.
1375 tevent_req_notify_callback(subreq);
1376 return NT_STATUS_OK;
1379 req->subreq = subreq;
1380 subreq = NULL;
1382 if (req->async_te) {
1383 /* We're already async. */
1384 return NT_STATUS_OK;
1387 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1388 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1389 if (flags & SMB2_HDR_FLAG_ASYNC) {
1390 /* We're already async. */
1391 return NT_STATUS_OK;
1394 if (req->async_internal) {
1396 * An SMB2 request implementation wants to handle the request
1397 * asynchronously "internally" while keeping synchronous
1398 * behaviour for the SMB2 request. This means we don't send an
1399 * interim response and we can allow processing of compound SMB2
1400 * requests (cf the subsequent check) for all cases.
1402 return NT_STATUS_OK;
1405 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1407 * We're trying to go async in a compound request
1408 * chain. This is only allowed for opens that cause an
1409 * oplock break or for the last operation in the
1410 * chain, otherwise it is not allowed. See
1411 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
1413 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1415 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1417 * Cancel the outstanding request.
1419 bool ok = tevent_req_cancel(req->subreq);
1420 if (ok) {
1421 return NT_STATUS_OK;
1423 TALLOC_FREE(req->subreq);
1424 return smbd_smb2_request_error(req,
1425 NT_STATUS_INTERNAL_ERROR);
1429 if (DEBUGLEVEL >= 10) {
1430 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1431 (unsigned int)req->current_idx );
1432 print_req_vectors(req);
1435 if (req->current_idx > 1) {
1437 * We're going async in a compound
1438 * chain after the first request has
1439 * already been processed. Send an
1440 * interim response containing the
1441 * set of replies already generated.
1443 int idx = req->current_idx;
1445 status = smb2_send_async_interim_response(req);
1446 if (!NT_STATUS_IS_OK(status)) {
1447 return status;
1449 if (req->first_key.length > 0) {
1450 data_blob_clear_free(&req->first_key);
1453 req->current_idx = 1;
1456 * Re-arrange the in.vectors to remove what
1457 * we just sent.
1459 memmove(&req->in.vector[1],
1460 &req->in.vector[idx],
1461 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1462 req->in.vector_count = 1 + (req->in.vector_count - idx);
1464 /* Re-arrange the out.vectors to match. */
1465 memmove(&req->out.vector[1],
1466 &req->out.vector[idx],
1467 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1468 req->out.vector_count = 1 + (req->out.vector_count - idx);
1470 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1472 * We only have one remaining request as
1473 * we've processed everything else.
1474 * This is no longer a compound request.
1476 req->compound_related = false;
1477 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1478 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1479 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1482 if (req->last_key.length > 0) {
1483 data_blob_clear_free(&req->last_key);
1487 * smbd_smb2_request_pending_timer() just send a packet
1488 * to the client and doesn't need any impersonation.
1489 * So we use req->xconn->client->raw_ev_ctx instead
1490 * of req->ev_ctx here.
1492 defer_endtime = timeval_current_ofs_usec(defer_time);
1493 req->async_te = tevent_add_timer(req->xconn->client->raw_ev_ctx,
1494 req, defer_endtime,
1495 smbd_smb2_request_pending_timer,
1496 req);
1497 if (req->async_te == NULL) {
1498 return NT_STATUS_NO_MEMORY;
1501 return NT_STATUS_OK;
1504 static DATA_BLOB smbd_smb2_signing_key(struct smbXsrv_session *session,
1505 struct smbXsrv_connection *xconn)
1507 struct smbXsrv_channel_global0 *c = NULL;
1508 NTSTATUS status;
1509 DATA_BLOB key = data_blob_null;
1511 status = smbXsrv_session_find_channel(session, xconn, &c);
1512 if (NT_STATUS_IS_OK(status)) {
1513 key = c->signing_key;
1516 if (key.length == 0) {
1517 key = session->global->signing_key;
1520 return key;
1523 static NTSTATUS smb2_get_new_nonce(struct smbXsrv_session *session,
1524 uint64_t *new_nonce_high,
1525 uint64_t *new_nonce_low)
1527 uint64_t nonce_high;
1528 uint64_t nonce_low;
1530 session->nonce_low += 1;
1531 if (session->nonce_low == 0) {
1532 session->nonce_low += 1;
1533 session->nonce_high += 1;
1537 * CCM and GCM algorithms must never have their
1538 * nonce wrap, or the security of the whole
1539 * communication and the keys is destroyed.
1540 * We must drop the connection once we have
1541 * transfered too much data.
1543 * NOTE: We assume nonces greater than 8 bytes.
1545 if (session->nonce_high >= session->nonce_high_max) {
1546 return NT_STATUS_ENCRYPTION_FAILED;
1549 nonce_high = session->nonce_high_random;
1550 nonce_high += session->nonce_high;
1551 nonce_low = session->nonce_low;
1553 *new_nonce_high = nonce_high;
1554 *new_nonce_low = nonce_low;
1555 return NT_STATUS_OK;
1558 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1559 struct tevent_timer *te,
1560 struct timeval current_time,
1561 void *private_data)
1563 struct smbd_smb2_request *req =
1564 talloc_get_type_abort(private_data,
1565 struct smbd_smb2_request);
1566 struct smbXsrv_connection *xconn = req->xconn;
1567 struct smbd_smb2_request_pending_state *state = NULL;
1568 uint8_t *outhdr = NULL;
1569 const uint8_t *inhdr = NULL;
1570 uint8_t *tf = NULL;
1571 size_t tf_len = 0;
1572 uint8_t *hdr = NULL;
1573 uint8_t *body = NULL;
1574 uint8_t *dyn = NULL;
1575 uint32_t flags = 0;
1576 uint64_t session_id = 0;
1577 uint64_t message_id = 0;
1578 uint64_t nonce_high = 0;
1579 uint64_t nonce_low = 0;
1580 uint64_t async_id = 0;
1581 NTSTATUS status;
1582 bool ok;
1584 TALLOC_FREE(req->async_te);
1586 /* Ensure our final reply matches the interim one. */
1587 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1588 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1589 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1590 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1591 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1593 async_id = message_id; /* keep it simple for now... */
1595 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1596 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1598 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1599 "going async\n",
1600 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1601 (unsigned long long)async_id ));
1604 * What we send is identical to a smbd_smb2_request_error
1605 * packet with an error status of STATUS_PENDING. Make use
1606 * of this fact sometime when refactoring. JRA.
1609 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
1610 if (state == NULL) {
1611 smbd_server_connection_terminate(xconn,
1612 nt_errstr(NT_STATUS_NO_MEMORY));
1613 return;
1616 tf = state->buf + NBT_HDR_SIZE;
1617 tf_len = SMB2_TF_HDR_SIZE;
1619 hdr = tf + SMB2_TF_HDR_SIZE;
1620 body = hdr + SMB2_HDR_BODY;
1621 dyn = body + 8;
1623 if (req->do_encryption) {
1624 status = smb2_get_new_nonce(req->session,
1625 &nonce_high,
1626 &nonce_low);
1627 if (!NT_STATUS_IS_OK(status)) {
1628 smbd_server_connection_terminate(xconn,
1629 nt_errstr(status));
1630 return;
1634 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1635 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1636 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1637 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1639 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1640 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1641 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1642 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1643 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1645 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1646 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1647 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1648 SBVAL(hdr, SMB2_HDR_PID, async_id);
1649 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1650 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1651 memcpy(hdr+SMB2_HDR_SIGNATURE,
1652 outhdr+SMB2_HDR_SIGNATURE, 16);
1654 SSVAL(body, 0x00, 0x08 + 1);
1656 SCVAL(body, 0x02, 0);
1657 SCVAL(body, 0x03, 0);
1658 SIVAL(body, 0x04, 0);
1659 /* Match W2K8R2... */
1660 SCVAL(dyn, 0x00, 0x21);
1662 state->vector[0].iov_base = (void *)state->buf;
1663 state->vector[0].iov_len = NBT_HDR_SIZE;
1665 if (req->do_encryption) {
1666 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1667 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1668 } else {
1669 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1670 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1673 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1674 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1676 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1677 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1679 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1680 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1682 ok = smb2_setup_nbt_length(state->vector,
1683 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1684 if (!ok) {
1685 smbd_server_connection_terminate(
1686 xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
1687 return;
1690 /* Ensure we correctly go through crediting. Grant
1691 the credits now, and zero credits on the final
1692 response. */
1693 smb2_set_operation_credit(req->xconn,
1694 SMBD_SMB2_IN_HDR_IOV(req),
1695 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1697 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1699 if (DEBUGLVL(10)) {
1700 int i;
1702 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1703 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1704 (unsigned int)i,
1705 (unsigned int)ARRAY_SIZE(state->vector),
1706 (unsigned int)state->vector[i].iov_len);
1710 if (req->do_encryption) {
1711 struct smbXsrv_session *x = req->session;
1712 DATA_BLOB encryption_key = x->global->encryption_key;
1714 status = smb2_signing_encrypt_pdu(encryption_key,
1715 xconn->smb2.server.cipher,
1716 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1717 SMBD_SMB2_NUM_IOV_PER_REQ);
1718 if (!NT_STATUS_IS_OK(status)) {
1719 smbd_server_connection_terminate(xconn,
1720 nt_errstr(status));
1721 return;
1723 } else if (req->do_signing) {
1724 struct smbXsrv_session *x = req->session;
1725 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
1727 status = smb2_signing_sign_pdu(signing_key,
1728 xconn->protocol,
1729 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1730 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1731 if (!NT_STATUS_IS_OK(status)) {
1732 smbd_server_connection_terminate(xconn,
1733 nt_errstr(status));
1734 return;
1738 state->queue_entry.mem_ctx = state;
1739 state->queue_entry.vector = state->vector;
1740 state->queue_entry.count = ARRAY_SIZE(state->vector);
1741 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
1742 xconn->smb2.send_queue_len++;
1744 status = smbd_smb2_flush_send_queue(xconn);
1745 if (!NT_STATUS_IS_OK(status)) {
1746 smbd_server_connection_terminate(xconn,
1747 nt_errstr(status));
1748 return;
1752 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1754 struct smbXsrv_connection *xconn = req->xconn;
1755 struct smbd_smb2_request *cur;
1756 const uint8_t *inhdr;
1757 uint32_t flags;
1758 uint64_t search_message_id;
1759 uint64_t search_async_id;
1760 uint64_t found_id;
1762 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1764 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1765 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1766 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1769 * We don't need the request anymore cancel requests never
1770 * have a response.
1772 * We defer the TALLOC_FREE(req) to the caller.
1774 DLIST_REMOVE(xconn->smb2.requests, req);
1776 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1777 const uint8_t *outhdr;
1778 uint64_t message_id;
1779 uint64_t async_id;
1781 if (cur->compound_related) {
1783 * Never cancel anything in a compound request.
1784 * Way too hard to deal with the result.
1786 continue;
1789 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1791 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1792 async_id = BVAL(outhdr, SMB2_HDR_PID);
1794 if (flags & SMB2_HDR_FLAG_ASYNC) {
1795 if (search_async_id == async_id) {
1796 found_id = async_id;
1797 break;
1799 } else {
1800 if (search_message_id == message_id) {
1801 found_id = message_id;
1802 break;
1807 if (cur && cur->subreq) {
1808 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1809 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1810 "cancel opcode[%s] mid %llu\n",
1811 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1812 (unsigned long long)found_id ));
1813 tevent_req_cancel(cur->subreq);
1816 return NT_STATUS_OK;
1819 /*************************************************************
1820 Ensure an incoming tid is a valid one for us to access.
1821 Change to the associated uid credentials and chdir to the
1822 valid tid directory.
1823 *************************************************************/
1825 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1827 const uint8_t *inhdr;
1828 uint32_t in_flags;
1829 uint32_t in_tid;
1830 struct smbXsrv_tcon *tcon;
1831 NTSTATUS status;
1832 NTTIME now = timeval_to_nttime(&req->request_time);
1834 req->tcon = NULL;
1836 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1838 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1839 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1841 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1842 in_tid = req->last_tid;
1845 req->last_tid = 0;
1847 status = smb2srv_tcon_lookup(req->session,
1848 in_tid, now, &tcon);
1849 if (!NT_STATUS_IS_OK(status)) {
1850 return status;
1853 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1854 return NT_STATUS_ACCESS_DENIED;
1857 req->tcon = tcon;
1858 req->last_tid = in_tid;
1860 return NT_STATUS_OK;
1863 /*************************************************************
1864 Ensure an incoming session_id is a valid one for us to access.
1865 *************************************************************/
1867 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1869 const uint8_t *inhdr;
1870 uint32_t in_flags;
1871 uint16_t in_opcode;
1872 uint64_t in_session_id;
1873 struct smbXsrv_session *session = NULL;
1874 struct auth_session_info *session_info;
1875 NTSTATUS status;
1876 NTTIME now = timeval_to_nttime(&req->request_time);
1878 req->session = NULL;
1879 req->tcon = NULL;
1881 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1883 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1884 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1885 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1887 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1888 in_session_id = req->last_session_id;
1891 req->last_session_id = 0;
1893 /* look an existing session up */
1894 switch (in_opcode) {
1895 case SMB2_OP_SESSSETUP:
1897 * For a session bind request, we don't have the
1898 * channel set up at this point yet, so we defer
1899 * the verification that the connection belongs
1900 * to the session to the session setup code, which
1901 * can look at the session binding flags.
1903 status = smb2srv_session_lookup_client(req->xconn->client,
1904 in_session_id, now,
1905 &session);
1906 break;
1907 default:
1908 status = smb2srv_session_lookup_conn(req->xconn,
1909 in_session_id, now,
1910 &session);
1911 break;
1913 if (session) {
1914 req->session = session;
1915 req->last_session_id = in_session_id;
1917 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1918 switch (in_opcode) {
1919 case SMB2_OP_SESSSETUP:
1920 status = NT_STATUS_OK;
1921 break;
1922 case SMB2_OP_LOGOFF:
1923 case SMB2_OP_CLOSE:
1924 case SMB2_OP_LOCK:
1925 case SMB2_OP_CANCEL:
1926 case SMB2_OP_KEEPALIVE:
1928 * [MS-SMB2] 3.3.5.2.9 Verifying the Session
1929 * specifies that LOGOFF, CLOSE and (UN)LOCK
1930 * should always be processed even on expired sessions.
1932 * Also see the logic in
1933 * smbd_smb2_request_process_lock().
1935 * The smb2.session.expire2 test shows that
1936 * CANCEL and KEEPALIVE/ECHO should also
1937 * be processed.
1939 status = NT_STATUS_OK;
1940 break;
1941 default:
1942 break;
1945 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1946 switch (in_opcode) {
1947 case SMB2_OP_TCON:
1948 case SMB2_OP_CREATE:
1949 case SMB2_OP_GETINFO:
1950 case SMB2_OP_SETINFO:
1951 return NT_STATUS_INVALID_HANDLE;
1952 default:
1954 * Notice the check for
1955 * (session_info == NULL)
1956 * below.
1958 status = NT_STATUS_OK;
1959 break;
1962 if (!NT_STATUS_IS_OK(status)) {
1963 return status;
1966 session_info = session->global->auth_session_info;
1967 if (session_info == NULL) {
1968 return NT_STATUS_INVALID_HANDLE;
1971 return NT_STATUS_OK;
1974 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1975 uint32_t data_length)
1977 struct smbXsrv_connection *xconn = req->xconn;
1978 uint16_t needed_charge;
1979 uint16_t credit_charge = 1;
1980 const uint8_t *inhdr;
1982 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1984 if (xconn->smb2.credits.multicredit) {
1985 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1986 credit_charge = MAX(credit_charge, 1);
1989 needed_charge = (data_length - 1)/ 65536 + 1;
1991 DBGC_DEBUG(DBGC_SMB2_CREDITS,
1992 "mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1993 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1994 credit_charge, needed_charge);
1996 if (needed_charge > credit_charge) {
1997 DBGC_WARNING(DBGC_SMB2_CREDITS,
1998 "CreditCharge too low, given %d, needed %d\n",
1999 credit_charge, needed_charge);
2000 return NT_STATUS_INVALID_PARAMETER;
2003 return NT_STATUS_OK;
2006 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
2007 size_t expected_body_size)
2009 struct iovec *inhdr_v;
2010 const uint8_t *inhdr;
2011 uint16_t opcode;
2012 const uint8_t *inbody;
2013 size_t body_size;
2014 size_t min_dyn_size = expected_body_size & 0x00000001;
2015 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
2018 * The following should be checked already.
2020 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
2021 return NT_STATUS_INTERNAL_ERROR;
2023 if (req->current_idx > max_idx) {
2024 return NT_STATUS_INTERNAL_ERROR;
2027 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
2028 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
2029 return NT_STATUS_INTERNAL_ERROR;
2031 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
2032 return NT_STATUS_INTERNAL_ERROR;
2035 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2036 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2038 switch (opcode) {
2039 case SMB2_OP_IOCTL:
2040 case SMB2_OP_GETINFO:
2041 min_dyn_size = 0;
2042 break;
2043 case SMB2_OP_WRITE:
2044 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
2045 if (req->smb1req->unread_bytes < min_dyn_size) {
2046 return NT_STATUS_INVALID_PARAMETER;
2049 min_dyn_size = 0;
2051 break;
2055 * Now check the expected body size,
2056 * where the last byte might be in the
2057 * dynamic section..
2059 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
2060 return NT_STATUS_INVALID_PARAMETER;
2062 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
2063 return NT_STATUS_INVALID_PARAMETER;
2066 inbody = SMBD_SMB2_IN_BODY_PTR(req);
2068 body_size = SVAL(inbody, 0x00);
2069 if (body_size != expected_body_size) {
2070 return NT_STATUS_INVALID_PARAMETER;
2073 return NT_STATUS_OK;
2076 bool smbXsrv_is_encrypted(uint8_t encryption_flags)
2078 return (!(encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)
2080 (encryption_flags & (SMBXSRV_PROCESSED_ENCRYPTED_PACKET |
2081 SMBXSRV_ENCRYPTION_DESIRED |
2082 SMBXSRV_ENCRYPTION_REQUIRED)));
2085 bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags)
2087 return ((encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET) &&
2088 (encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET));
2091 /* Set a flag if not already set, return true if set */
2092 bool smbXsrv_set_crypto_flag(uint8_t *flags, uint8_t flag)
2094 if ((flag == 0) || (*flags & flag)) {
2095 return false;
2098 *flags |= flag;
2099 return true;
2103 * Update encryption state tracking flags, this can be used to
2104 * determine whether whether the session or tcon is "encrypted".
2106 static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
2107 uint16_t opcode,
2108 bool *update_session_globalp,
2109 bool *update_tcon_globalp)
2111 /* Default: assume unecrypted and unsigned */
2112 struct smbXsrv_session *session = req->session;
2113 struct smbXsrv_tcon *tcon = req->tcon;
2114 uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
2115 uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2116 bool update_session = false;
2117 bool update_tcon = false;
2119 if (req->was_encrypted && req->do_encryption) {
2120 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
2121 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2122 } else {
2123 /* Unencrypted packet, can be signed */
2124 if (req->do_signing) {
2125 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2126 } else if (opcode == SMB2_OP_CANCEL) {
2127 /* Cancel requests are allowed to skip signing */
2128 sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2132 update_session |= smbXsrv_set_crypto_flag(
2133 &session->global->encryption_flags, encrypt_flag);
2134 update_session |= smbXsrv_set_crypto_flag(
2135 &session->global->signing_flags, sign_flag);
2137 if (tcon) {
2138 update_tcon |= smbXsrv_set_crypto_flag(
2139 &tcon->global->encryption_flags, encrypt_flag);
2140 update_tcon |= smbXsrv_set_crypto_flag(
2141 &tcon->global->signing_flags, sign_flag);
2144 *update_session_globalp = update_session;
2145 *update_tcon_globalp = update_tcon;
2146 return;
2149 bool smbXsrv_is_signed(uint8_t signing_flags)
2152 * Signing is always enabled, so unless we got an unsigned
2153 * packet and at least one signed packet that was not
2154 * encrypted, the session or tcon is "signed".
2156 return (!(signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2157 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2160 bool smbXsrv_is_partially_signed(uint8_t signing_flags)
2162 return ((signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2163 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2166 static NTSTATUS smbd_smb2_request_dispatch_update_counts(
2167 struct smbd_smb2_request *req,
2168 bool modify_call)
2170 struct smbXsrv_connection *xconn = req->xconn;
2171 const uint8_t *inhdr;
2172 uint16_t channel_sequence;
2173 uint8_t generation_wrap = 0;
2174 uint32_t flags;
2175 int cmp;
2176 struct smbXsrv_open *op;
2177 bool update_open = false;
2178 NTSTATUS status = NT_STATUS_OK;
2180 SMB_ASSERT(!req->request_counters_updated);
2182 if (xconn->protocol < PROTOCOL_SMB2_22) {
2183 return NT_STATUS_OK;
2186 if (req->compat_chain_fsp == NULL) {
2187 return NT_STATUS_OK;
2190 op = req->compat_chain_fsp->op;
2191 if (op == NULL) {
2192 return NT_STATUS_OK;
2195 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2196 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2197 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2199 cmp = channel_sequence - op->global->channel_sequence;
2200 if (cmp < 0) {
2202 * csn wrap. We need to watch out for long-running
2203 * requests that are still sitting on a previously
2204 * used csn. SMB2_OP_NOTIFY can take VERY long.
2206 generation_wrap += 1;
2209 if (abs(cmp) > INT16_MAX) {
2211 * [MS-SMB2] 3.3.5.2.10 - Verifying the Channel Sequence Number:
2213 * If the channel sequence number of the request and the one
2214 * known to the server are not equal, the channel sequence
2215 * number and outstanding request counts are only updated
2216 * "... if the unsigned difference using 16-bit arithmetic
2217 * between ChannelSequence and Open.ChannelSequence is less than
2218 * or equal to 0x7FFF ...".
2219 * Otherwise, an error is returned for the modifying
2220 * calls write, set_info, and ioctl.
2222 * There are currently two issues with the description:
2224 * * For the other calls, the document seems to imply
2225 * that processing continues without adapting the
2226 * counters (if the sequence numbers are not equal).
2228 * TODO: This needs clarification!
2230 * * Also, the behaviour if the difference is larger
2231 * than 0x7FFF is not clear. The document seems to
2232 * imply that if such a difference is reached,
2233 * the server starts to ignore the counters or
2234 * in the case of the modifying calls, return errors.
2236 * TODO: This needs clarification!
2238 * At this point Samba tries to be a little more
2239 * clever than the description in the MS-SMB2 document
2240 * by heuristically detecting and properly treating
2241 * a 16 bit overflow of the client-submitted sequence
2242 * number:
2244 * If the stored channel sequence number is more than
2245 * 0x7FFF larger than the one from the request, then
2246 * the client-provided sequence number has likely
2247 * overflown. We treat this case as valid instead
2248 * of as failure.
2250 * The MS-SMB2 behaviour would be setting cmp = -1.
2252 cmp *= -1;
2255 if (flags & SMB2_HDR_FLAG_REPLAY_OPERATION) {
2256 if (cmp == 0 && op->pre_request_count == 0) {
2257 op->request_count += 1;
2258 req->request_counters_updated = true;
2259 } else if (cmp > 0 && op->pre_request_count == 0) {
2260 op->pre_request_count += op->request_count;
2261 op->request_count = 1;
2262 op->global->channel_sequence = channel_sequence;
2263 op->global->channel_generation += generation_wrap;
2264 update_open = true;
2265 req->request_counters_updated = true;
2266 } else if (modify_call) {
2267 return NT_STATUS_FILE_NOT_AVAILABLE;
2269 } else {
2270 if (cmp == 0) {
2271 op->request_count += 1;
2272 req->request_counters_updated = true;
2273 } else if (cmp > 0) {
2274 op->pre_request_count += op->request_count;
2275 op->request_count = 1;
2276 op->global->channel_sequence = channel_sequence;
2277 op->global->channel_generation += generation_wrap;
2278 update_open = true;
2279 req->request_counters_updated = true;
2280 } else if (modify_call) {
2281 return NT_STATUS_FILE_NOT_AVAILABLE;
2284 req->channel_generation = op->global->channel_generation;
2286 if (update_open) {
2287 status = smbXsrv_open_update(op);
2290 return status;
2293 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
2295 struct smbXsrv_connection *xconn = req->xconn;
2296 const struct smbd_smb2_dispatch_table *call = NULL;
2297 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
2298 const uint8_t *inhdr;
2299 uint16_t opcode;
2300 uint32_t flags;
2301 uint64_t mid;
2302 NTSTATUS status;
2303 NTSTATUS session_status;
2304 uint32_t allowed_flags;
2305 NTSTATUS return_value;
2306 struct smbXsrv_session *x = NULL;
2307 bool signing_required = false;
2308 bool encryption_desired = false;
2309 bool encryption_required = false;
2311 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2313 DO_PROFILE_INC(request);
2315 SMB_ASSERT(!req->request_counters_updated);
2317 /* TODO: verify more things */
2319 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2320 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2321 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2322 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
2323 smb2_opcode_name(opcode),
2324 (unsigned long long)mid));
2326 if (xconn->protocol >= PROTOCOL_SMB2_02) {
2328 * once the protocol is negotiated
2329 * SMB2_OP_NEGPROT is not allowed anymore
2331 if (opcode == SMB2_OP_NEGPROT) {
2332 /* drop the connection */
2333 return NT_STATUS_INVALID_PARAMETER;
2335 } else {
2337 * if the protocol is not negotiated yet
2338 * only SMB2_OP_NEGPROT is allowed.
2340 if (opcode != SMB2_OP_NEGPROT) {
2341 /* drop the connection */
2342 return NT_STATUS_INVALID_PARAMETER;
2347 * Check if the client provided a valid session id.
2349 * As some command don't require a valid session id
2350 * we defer the check of the session_status
2352 session_status = smbd_smb2_request_check_session(req);
2353 x = req->session;
2354 if (x != NULL) {
2355 signing_required = x->global->signing_flags & SMBXSRV_SIGNING_REQUIRED;
2356 encryption_desired = x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
2357 encryption_required = x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
2360 req->async_internal = false;
2361 req->do_signing = false;
2362 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 req->ev_ctx = req->sconn->root_ev_ctx;
2624 } else {
2625 SMB_ASSERT(call->need_tcon);
2626 req->ev_ctx = req->tcon->compat->user_ev_ctx;
2629 #define _INBYTES(_r) \
2630 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
2632 switch (opcode) {
2633 case SMB2_OP_NEGPROT:
2634 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
2635 req->profile, _INBYTES(req));
2636 return_value = smbd_smb2_request_process_negprot(req);
2637 break;
2639 case SMB2_OP_SESSSETUP:
2640 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
2641 req->profile, _INBYTES(req));
2642 return_value = smbd_smb2_request_process_sesssetup(req);
2643 break;
2645 case SMB2_OP_LOGOFF:
2646 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
2647 req->profile, _INBYTES(req));
2648 return_value = smbd_smb2_request_process_logoff(req);
2649 break;
2651 case SMB2_OP_TCON:
2652 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
2653 req->profile, _INBYTES(req));
2654 return_value = smbd_smb2_request_process_tcon(req);
2655 break;
2657 case SMB2_OP_TDIS:
2658 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
2659 req->profile, _INBYTES(req));
2660 return_value = smbd_smb2_request_process_tdis(req);
2661 break;
2663 case SMB2_OP_CREATE:
2664 if (req->subreq == NULL) {
2665 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
2666 req->profile, _INBYTES(req));
2667 } else {
2668 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
2670 return_value = smbd_smb2_request_process_create(req);
2671 break;
2673 case SMB2_OP_CLOSE:
2674 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
2675 req->profile, _INBYTES(req));
2676 return_value = smbd_smb2_request_process_close(req);
2677 break;
2679 case SMB2_OP_FLUSH:
2680 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
2681 req->profile, _INBYTES(req));
2682 return_value = smbd_smb2_request_process_flush(req);
2683 break;
2685 case SMB2_OP_READ:
2686 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
2687 req->profile, _INBYTES(req));
2688 return_value = smbd_smb2_request_process_read(req);
2689 break;
2691 case SMB2_OP_WRITE:
2692 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
2693 req->profile, _INBYTES(req));
2694 return_value = smbd_smb2_request_process_write(req);
2695 break;
2697 case SMB2_OP_LOCK:
2698 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
2699 req->profile, _INBYTES(req));
2700 return_value = smbd_smb2_request_process_lock(req);
2701 break;
2703 case SMB2_OP_IOCTL:
2704 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
2705 req->profile, _INBYTES(req));
2706 return_value = smbd_smb2_request_process_ioctl(req);
2707 break;
2709 case SMB2_OP_CANCEL:
2710 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
2711 req->profile, _INBYTES(req));
2712 return_value = smbd_smb2_request_process_cancel(req);
2713 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
2716 * We don't need the request anymore cancel requests never
2717 * have a response.
2719 * smbd_smb2_request_process_cancel() already called
2720 * DLIST_REMOVE(xconn->smb2.requests, req);
2722 TALLOC_FREE(req);
2724 break;
2726 case SMB2_OP_KEEPALIVE:
2727 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
2728 req->profile, _INBYTES(req));
2729 return_value = smbd_smb2_request_process_keepalive(req);
2730 break;
2732 case SMB2_OP_QUERY_DIRECTORY:
2733 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
2734 req->profile, _INBYTES(req));
2735 return_value = smbd_smb2_request_process_query_directory(req);
2736 break;
2738 case SMB2_OP_NOTIFY:
2739 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
2740 req->profile, _INBYTES(req));
2741 return_value = smbd_smb2_request_process_notify(req);
2742 break;
2744 case SMB2_OP_GETINFO:
2745 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
2746 req->profile, _INBYTES(req));
2747 return_value = smbd_smb2_request_process_getinfo(req);
2748 break;
2750 case SMB2_OP_SETINFO:
2751 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
2752 req->profile, _INBYTES(req));
2753 return_value = smbd_smb2_request_process_setinfo(req);
2754 break;
2756 case SMB2_OP_BREAK:
2757 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
2758 req->profile, _INBYTES(req));
2759 return_value = smbd_smb2_request_process_break(req);
2760 break;
2762 default:
2763 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2764 break;
2766 return return_value;
2769 static void smbd_smb2_request_reply_update_counts(struct smbd_smb2_request *req)
2771 struct smbXsrv_connection *xconn = req->xconn;
2772 const uint8_t *inhdr;
2773 uint16_t channel_sequence;
2774 struct smbXsrv_open *op;
2776 if (!req->request_counters_updated) {
2777 return;
2780 req->request_counters_updated = false;
2782 if (xconn->protocol < PROTOCOL_SMB2_22) {
2783 return;
2786 if (req->compat_chain_fsp == NULL) {
2787 return;
2790 op = req->compat_chain_fsp->op;
2791 if (op == NULL) {
2792 return;
2795 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2796 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2798 if ((op->global->channel_sequence == channel_sequence) &&
2799 (op->global->channel_generation == req->channel_generation)) {
2800 SMB_ASSERT(op->request_count > 0);
2801 op->request_count -= 1;
2802 } else {
2803 SMB_ASSERT(op->pre_request_count > 0);
2804 op->pre_request_count -= 1;
2808 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2810 struct smbXsrv_connection *xconn = req->xconn;
2811 int first_idx = 1;
2812 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2813 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2814 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2815 NTSTATUS status;
2816 bool ok;
2818 req->subreq = NULL;
2819 TALLOC_FREE(req->async_te);
2821 /* MS-SMB2: 3.3.4.1 Sending Any Outgoing Message */
2822 smbd_smb2_request_reply_update_counts(req);
2824 if (req->do_encryption &&
2825 (firsttf->iov_len == 0) &&
2826 (req->first_key.length == 0) &&
2827 (req->session != NULL) &&
2828 (req->session->global->encryption_key.length != 0))
2830 DATA_BLOB encryption_key = req->session->global->encryption_key;
2831 uint8_t *tf;
2832 uint64_t session_id = req->session->global->session_wire_id;
2833 uint64_t nonce_high;
2834 uint64_t nonce_low;
2836 status = smb2_get_new_nonce(req->session,
2837 &nonce_high,
2838 &nonce_low);
2839 if (!NT_STATUS_IS_OK(status)) {
2840 return status;
2844 * We need to place the SMB2_TRANSFORM header before the
2845 * first SMB2 header
2849 * we need to remember the encryption key
2850 * and defer the signing/encryption until
2851 * we are sure that we do not change
2852 * the header again.
2854 req->first_key = data_blob_dup_talloc(req, encryption_key);
2855 if (req->first_key.data == NULL) {
2856 return NT_STATUS_NO_MEMORY;
2859 tf = talloc_zero_array(req, uint8_t,
2860 SMB2_TF_HDR_SIZE);
2861 if (tf == NULL) {
2862 return NT_STATUS_NO_MEMORY;
2865 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2866 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2867 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2868 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2870 firsttf->iov_base = (void *)tf;
2871 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2874 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2875 (req->last_key.length > 0) &&
2876 (firsttf->iov_len == 0))
2878 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2879 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2882 * As we are sure the header of the last request in the
2883 * compound chain will not change, we can to sign here
2884 * with the last signing key we remembered.
2886 status = smb2_signing_sign_pdu(req->last_key,
2887 xconn->protocol,
2888 lasthdr,
2889 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2890 if (!NT_STATUS_IS_OK(status)) {
2891 return status;
2894 if (req->last_key.length > 0) {
2895 data_blob_clear_free(&req->last_key);
2898 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
2899 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
2901 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2903 if (req->current_idx < req->out.vector_count) {
2905 * We must process the remaining compound
2906 * SMB2 requests before any new incoming SMB2
2907 * requests. This is because incoming SMB2
2908 * requests may include a cancel for a
2909 * compound request we haven't processed
2910 * yet.
2912 struct tevent_immediate *im = tevent_create_immediate(req);
2913 if (!im) {
2914 return NT_STATUS_NO_MEMORY;
2917 if (req->do_signing && firsttf->iov_len == 0) {
2918 struct smbXsrv_session *x = req->session;
2919 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2922 * we need to remember the signing key
2923 * and defer the signing until
2924 * we are sure that we do not change
2925 * the header again.
2927 req->last_key = data_blob_dup_talloc(req, signing_key);
2928 if (req->last_key.data == NULL) {
2929 return NT_STATUS_NO_MEMORY;
2934 * smbd_smb2_request_dispatch() will redo the impersonation.
2935 * So we use req->xconn->client->raw_ev_ctx instead
2936 * of req->ev_ctx here.
2938 tevent_schedule_immediate(im,
2939 req->xconn->client->raw_ev_ctx,
2940 smbd_smb2_request_dispatch_immediate,
2941 req);
2942 return NT_STATUS_OK;
2945 if (req->compound_related) {
2946 req->compound_related = false;
2949 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2950 if (!ok) {
2951 return NT_STATUS_INVALID_PARAMETER_MIX;
2954 /* Set credit for these operations (zero credits if this
2955 is a final reply for an async operation). */
2956 smb2_calculate_credits(req, req);
2959 * now check if we need to sign the current response
2961 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2962 status = smb2_signing_encrypt_pdu(req->first_key,
2963 xconn->smb2.server.cipher,
2964 firsttf,
2965 req->out.vector_count - first_idx);
2966 if (!NT_STATUS_IS_OK(status)) {
2967 return status;
2969 } else if (req->do_signing) {
2970 struct smbXsrv_session *x = req->session;
2971 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2973 status = smb2_signing_sign_pdu(signing_key,
2974 xconn->protocol,
2975 outhdr,
2976 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2977 if (!NT_STATUS_IS_OK(status)) {
2978 return status;
2981 if (req->first_key.length > 0) {
2982 data_blob_clear_free(&req->first_key);
2985 if (req->preauth != NULL) {
2986 struct hc_sha512state sctx;
2987 int i;
2989 samba_SHA512_Init(&sctx);
2990 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2991 sizeof(req->preauth->sha512_value));
2992 for (i = 1; i < req->in.vector_count; i++) {
2993 samba_SHA512_Update(&sctx,
2994 req->in.vector[i].iov_base,
2995 req->in.vector[i].iov_len);
2997 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2999 samba_SHA512_Init(&sctx);
3000 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
3001 sizeof(req->preauth->sha512_value));
3002 for (i = 1; i < req->out.vector_count; i++) {
3003 samba_SHA512_Update(&sctx,
3004 req->out.vector[i].iov_base,
3005 req->out.vector[i].iov_len);
3007 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
3009 req->preauth = NULL;
3012 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
3013 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
3014 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
3015 /* Dynamic part is NULL. Chop it off,
3016 We're going to send it via sendfile. */
3017 req->out.vector_count -= 1;
3021 * We're done with this request -
3022 * move it off the "being processed" queue.
3024 DLIST_REMOVE(xconn->smb2.requests, req);
3026 req->queue_entry.mem_ctx = req;
3027 req->queue_entry.vector = req->out.vector;
3028 req->queue_entry.count = req->out.vector_count;
3029 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry);
3030 xconn->smb2.send_queue_len++;
3032 status = smbd_smb2_flush_send_queue(xconn);
3033 if (!NT_STATUS_IS_OK(status)) {
3034 return status;
3037 return NT_STATUS_OK;
3040 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
3042 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
3043 struct tevent_immediate *im,
3044 void *private_data)
3046 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
3047 struct smbd_smb2_request);
3048 struct smbXsrv_connection *xconn = req->xconn;
3049 NTSTATUS status;
3051 TALLOC_FREE(im);
3053 if (DEBUGLEVEL >= 10) {
3054 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
3055 req->current_idx, req->in.vector_count));
3056 print_req_vectors(req);
3059 status = smbd_smb2_request_dispatch(req);
3060 if (!NT_STATUS_IS_OK(status)) {
3061 smbd_server_connection_terminate(xconn, nt_errstr(status));
3062 return;
3065 status = smbd_smb2_request_next_incoming(xconn);
3066 if (!NT_STATUS_IS_OK(status)) {
3067 smbd_server_connection_terminate(xconn, nt_errstr(status));
3068 return;
3072 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
3073 NTSTATUS status,
3074 DATA_BLOB body, DATA_BLOB *dyn,
3075 const char *location)
3077 uint8_t *outhdr;
3078 struct iovec *outbody_v;
3079 struct iovec *outdyn_v;
3080 uint32_t next_command_ofs;
3082 DEBUG(10,("smbd_smb2_request_done_ex: "
3083 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
3084 req->current_idx, nt_errstr(status), (unsigned int)body.length,
3085 dyn ? "yes": "no",
3086 (unsigned int)(dyn ? dyn->length : 0),
3087 location));
3089 if (body.length < 2) {
3090 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3093 if ((body.length % 2) != 0) {
3094 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3097 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3098 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
3099 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
3101 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
3102 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
3104 outbody_v->iov_base = (void *)body.data;
3105 outbody_v->iov_len = body.length;
3107 if (dyn) {
3108 outdyn_v->iov_base = (void *)dyn->data;
3109 outdyn_v->iov_len = dyn->length;
3110 } else {
3111 outdyn_v->iov_base = NULL;
3112 outdyn_v->iov_len = 0;
3116 * See if we need to recalculate the offset to the next response
3118 * Note that all responses may require padding (including the very last
3119 * one).
3121 if (req->out.vector_count >= (2 * SMBD_SMB2_NUM_IOV_PER_REQ)) {
3122 next_command_ofs = SMB2_HDR_BODY;
3123 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
3124 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
3127 if ((next_command_ofs % 8) != 0) {
3128 size_t pad_size = 8 - (next_command_ofs % 8);
3129 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
3131 * if the dyn buffer is empty
3132 * we can use it to add padding
3134 uint8_t *pad;
3136 pad = talloc_zero_array(req,
3137 uint8_t, pad_size);
3138 if (pad == NULL) {
3139 return smbd_smb2_request_error(req,
3140 NT_STATUS_NO_MEMORY);
3143 outdyn_v->iov_base = (void *)pad;
3144 outdyn_v->iov_len = pad_size;
3145 } else {
3147 * For now we copy the dynamic buffer
3148 * and add the padding to the new buffer
3150 size_t old_size;
3151 uint8_t *old_dyn;
3152 size_t new_size;
3153 uint8_t *new_dyn;
3155 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
3156 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
3158 new_size = old_size + pad_size;
3159 new_dyn = talloc_zero_array(req,
3160 uint8_t, new_size);
3161 if (new_dyn == NULL) {
3162 return smbd_smb2_request_error(req,
3163 NT_STATUS_NO_MEMORY);
3166 memcpy(new_dyn, old_dyn, old_size);
3167 memset(new_dyn + old_size, 0, pad_size);
3169 outdyn_v->iov_base = (void *)new_dyn;
3170 outdyn_v->iov_len = new_size;
3172 next_command_ofs += pad_size;
3175 if ((req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) >= req->out.vector_count) {
3176 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
3177 } else {
3178 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
3180 return smbd_smb2_request_reply(req);
3183 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
3184 NTSTATUS status,
3185 DATA_BLOB *info,
3186 const char *location)
3188 struct smbXsrv_connection *xconn = req->xconn;
3189 DATA_BLOB body;
3190 DATA_BLOB _dyn;
3191 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3192 size_t unread_bytes = smbd_smb2_unread_bytes(req);
3194 DBG_NOTICE("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| "
3195 "at %s\n", req->current_idx, nt_errstr(status),
3196 info ? " +info" : "", location);
3198 if (unread_bytes) {
3199 /* Recvfile error. Drain incoming socket. */
3200 size_t ret;
3202 errno = 0;
3203 ret = drain_socket(xconn->transport.sock, unread_bytes);
3204 if (ret != unread_bytes) {
3205 NTSTATUS error;
3207 if (errno == 0) {
3208 error = NT_STATUS_IO_DEVICE_ERROR;
3209 } else {
3210 error = map_nt_error_from_unix_common(errno);
3213 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
3214 "ret[%u] errno[%d] => %s\n",
3215 (unsigned)unread_bytes,
3216 (unsigned)ret, errno, nt_errstr(error)));
3217 return error;
3221 body.data = outhdr + SMB2_HDR_BODY;
3222 body.length = 8;
3223 SSVAL(body.data, 0, 9);
3225 if (info) {
3226 SIVAL(body.data, 0x04, info->length);
3227 } else {
3228 /* Allocated size of req->out.vector[i].iov_base
3229 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
3230 * 1 byte without having to do an alloc.
3232 info = &_dyn;
3233 info->data = ((uint8_t *)outhdr) +
3234 OUTVEC_ALLOC_SIZE - 1;
3235 info->length = 1;
3236 SCVAL(info->data, 0, 0);
3240 * Note: Even if there is an error, continue to process the request.
3241 * per MS-SMB2.
3244 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
3248 struct smbd_smb2_send_break_state {
3249 struct smbd_smb2_send_queue queue_entry;
3250 uint8_t nbt_hdr[NBT_HDR_SIZE];
3251 uint8_t tf[SMB2_TF_HDR_SIZE];
3252 uint8_t hdr[SMB2_HDR_BODY];
3253 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
3254 uint8_t body[1];
3257 static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
3258 struct smbXsrv_session *session,
3259 struct smbXsrv_tcon *tcon,
3260 const uint8_t *body,
3261 size_t body_len)
3263 struct smbd_smb2_send_break_state *state;
3264 bool do_encryption = false;
3265 uint64_t session_wire_id = 0;
3266 uint64_t nonce_high = 0;
3267 uint64_t nonce_low = 0;
3268 NTSTATUS status;
3269 size_t statelen;
3270 bool ok;
3272 if (session != NULL) {
3273 session_wire_id = session->global->session_wire_id;
3274 do_encryption = session->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
3275 if (tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
3276 do_encryption = true;
3280 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
3281 body_len;
3283 state = talloc_zero_size(xconn, statelen);
3284 if (state == NULL) {
3285 return NT_STATUS_NO_MEMORY;
3287 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
3289 if (do_encryption) {
3290 status = smb2_get_new_nonce(session,
3291 &nonce_high,
3292 &nonce_low);
3293 if (!NT_STATUS_IS_OK(status)) {
3294 return status;
3298 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
3299 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
3300 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
3301 SBVAL(state->tf, SMB2_TF_SESSION_ID, session_wire_id);
3303 SIVAL(state->hdr, 0, SMB2_MAGIC);
3304 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
3305 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
3306 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
3307 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
3308 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
3309 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
3310 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
3311 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
3312 SIVAL(state->hdr, SMB2_HDR_PID, 0);
3313 SIVAL(state->hdr, SMB2_HDR_TID, 0);
3314 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
3315 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
3317 state->vector[0] = (struct iovec) {
3318 .iov_base = state->nbt_hdr,
3319 .iov_len = sizeof(state->nbt_hdr)
3322 if (do_encryption) {
3323 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3324 .iov_base = state->tf,
3325 .iov_len = sizeof(state->tf)
3327 } else {
3328 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3329 .iov_base = NULL,
3330 .iov_len = 0
3334 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
3335 .iov_base = state->hdr,
3336 .iov_len = sizeof(state->hdr)
3339 memcpy(state->body, body, body_len);
3341 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
3342 .iov_base = state->body,
3343 .iov_len = body_len /* no sizeof(state->body) .. :-) */
3347 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
3350 ok = smb2_setup_nbt_length(state->vector,
3351 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
3352 if (!ok) {
3353 return NT_STATUS_INVALID_PARAMETER_MIX;
3356 if (do_encryption) {
3357 DATA_BLOB encryption_key = session->global->encryption_key;
3359 status = smb2_signing_encrypt_pdu(encryption_key,
3360 xconn->smb2.server.cipher,
3361 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
3362 SMBD_SMB2_NUM_IOV_PER_REQ);
3363 if (!NT_STATUS_IS_OK(status)) {
3364 return status;
3368 state->queue_entry.mem_ctx = state;
3369 state->queue_entry.vector = state->vector;
3370 state->queue_entry.count = ARRAY_SIZE(state->vector);
3371 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
3372 xconn->smb2.send_queue_len++;
3374 status = smbd_smb2_flush_send_queue(xconn);
3375 if (!NT_STATUS_IS_OK(status)) {
3376 return status;
3379 return NT_STATUS_OK;
3382 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_connection *xconn,
3383 struct smbXsrv_session *session,
3384 struct smbXsrv_tcon *tcon,
3385 struct smbXsrv_open *op,
3386 uint8_t oplock_level)
3388 uint8_t body[0x18];
3390 SSVAL(body, 0x00, sizeof(body));
3391 SCVAL(body, 0x02, oplock_level);
3392 SCVAL(body, 0x03, 0); /* reserved */
3393 SIVAL(body, 0x04, 0); /* reserved */
3394 SBVAL(body, 0x08, op->global->open_persistent_id);
3395 SBVAL(body, 0x10, op->global->open_volatile_id);
3397 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3400 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_connection *xconn,
3401 uint16_t new_epoch,
3402 uint32_t lease_flags,
3403 struct smb2_lease_key *lease_key,
3404 uint32_t current_lease_state,
3405 uint32_t new_lease_state)
3407 uint8_t body[0x2c];
3409 SSVAL(body, 0x00, sizeof(body));
3410 SSVAL(body, 0x02, new_epoch);
3411 SIVAL(body, 0x04, lease_flags);
3412 SBVAL(body, 0x08, lease_key->data[0]);
3413 SBVAL(body, 0x10, lease_key->data[1]);
3414 SIVAL(body, 0x18, current_lease_state);
3415 SIVAL(body, 0x1c, new_lease_state);
3416 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
3417 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
3418 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
3420 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3423 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
3425 NTSTATUS status;
3426 uint32_t flags;
3427 uint64_t file_id_persistent;
3428 uint64_t file_id_volatile;
3429 struct smbXsrv_open *op = NULL;
3430 struct files_struct *fsp = NULL;
3431 const uint8_t *body = NULL;
3434 * This is only called with a pktbuf
3435 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
3436 * bytes
3439 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
3440 /* Transform header. Cannot recvfile. */
3441 return false;
3443 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
3444 /* Not SMB2. Normal error path will cope. */
3445 return false;
3447 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
3448 /* Not SMB2. Normal error path will cope. */
3449 return false;
3451 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
3452 /* Needs to be a WRITE. */
3453 return false;
3455 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
3456 /* Chained. Cannot recvfile. */
3457 return false;
3459 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
3460 if (flags & SMB2_HDR_FLAG_CHAINED) {
3461 /* Chained. Cannot recvfile. */
3462 return false;
3464 if (flags & SMB2_HDR_FLAG_SIGNED) {
3465 /* Signed. Cannot recvfile. */
3466 return false;
3469 body = &state->pktbuf[SMB2_HDR_BODY];
3471 file_id_persistent = BVAL(body, 0x10);
3472 file_id_volatile = BVAL(body, 0x18);
3474 status = smb2srv_open_lookup(state->req->xconn,
3475 file_id_persistent,
3476 file_id_volatile,
3477 0, /* now */
3478 &op);
3479 if (!NT_STATUS_IS_OK(status)) {
3480 return false;
3483 fsp = op->compat;
3484 if (fsp == NULL) {
3485 return false;
3487 if (fsp->conn == NULL) {
3488 return false;
3491 if (IS_IPC(fsp->conn)) {
3492 return false;
3494 if (IS_PRINT(fsp->conn)) {
3495 return false;
3498 DEBUG(10,("Doing recvfile write len = %u\n",
3499 (unsigned int)(state->pktfull - state->pktlen)));
3501 return true;
3504 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
3506 struct smbd_server_connection *sconn = xconn->client->sconn;
3507 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3508 size_t max_send_queue_len;
3509 size_t cur_send_queue_len;
3511 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3513 * we're not supposed to do any io
3515 return NT_STATUS_OK;
3518 if (state->req != NULL) {
3520 * if there is already a tstream_readv_pdu
3521 * pending, we are done.
3523 return NT_STATUS_OK;
3526 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
3527 cur_send_queue_len = xconn->smb2.send_queue_len;
3529 if (cur_send_queue_len > max_send_queue_len) {
3531 * if we have a lot of requests to send,
3532 * we wait until they are on the wire until we
3533 * ask for the next request.
3535 return NT_STATUS_OK;
3538 /* ask for the next request */
3539 ZERO_STRUCTP(state);
3540 state->req = smbd_smb2_request_allocate(xconn);
3541 if (state->req == NULL) {
3542 return NT_STATUS_NO_MEMORY;
3544 state->req->sconn = sconn;
3545 state->req->xconn = xconn;
3546 state->min_recv_size = lp_min_receive_file_size();
3548 TEVENT_FD_READABLE(xconn->transport.fde);
3550 return NT_STATUS_OK;
3553 void smbd_smb2_process_negprot(struct smbXsrv_connection *xconn,
3554 uint64_t expected_seq_low,
3555 const uint8_t *inpdu, size_t size)
3557 struct smbd_server_connection *sconn = xconn->client->sconn;
3558 NTSTATUS status;
3559 struct smbd_smb2_request *req = NULL;
3561 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3562 (unsigned int)size));
3564 status = smbd_initialize_smb2(xconn, expected_seq_low);
3565 if (!NT_STATUS_IS_OK(status)) {
3566 smbd_server_connection_terminate(xconn, nt_errstr(status));
3567 return;
3570 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
3571 if (!NT_STATUS_IS_OK(status)) {
3572 smbd_server_connection_terminate(xconn, nt_errstr(status));
3573 return;
3576 status = smbd_smb2_request_validate(req);
3577 if (!NT_STATUS_IS_OK(status)) {
3578 smbd_server_connection_terminate(xconn, nt_errstr(status));
3579 return;
3582 status = smbd_smb2_request_setup_out(req);
3583 if (!NT_STATUS_IS_OK(status)) {
3584 smbd_server_connection_terminate(xconn, nt_errstr(status));
3585 return;
3588 #ifdef WITH_PROFILE
3590 * this was already counted at the SMB1 layer =>
3591 * smbd_smb2_request_dispatch() should not count it twice.
3593 if (profile_p->values.request_stats.count > 0) {
3594 profile_p->values.request_stats.count--;
3596 #endif
3597 status = smbd_smb2_request_dispatch(req);
3598 if (!NT_STATUS_IS_OK(status)) {
3599 smbd_server_connection_terminate(xconn, nt_errstr(status));
3600 return;
3603 status = smbd_smb2_request_next_incoming(xconn);
3604 if (!NT_STATUS_IS_OK(status)) {
3605 smbd_server_connection_terminate(xconn, nt_errstr(status));
3606 return;
3609 sconn->num_requests++;
3612 static int socket_error_from_errno(int ret,
3613 int sys_errno,
3614 bool *retry)
3616 *retry = false;
3618 if (ret >= 0) {
3619 return 0;
3622 if (ret != -1) {
3623 return EIO;
3626 if (sys_errno == 0) {
3627 return EIO;
3630 if (sys_errno == EINTR) {
3631 *retry = true;
3632 return sys_errno;
3635 if (sys_errno == EINPROGRESS) {
3636 *retry = true;
3637 return sys_errno;
3640 if (sys_errno == EAGAIN) {
3641 *retry = true;
3642 return sys_errno;
3645 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3646 if (sys_errno == ENOMEM) {
3647 *retry = true;
3648 return sys_errno;
3651 #ifdef EWOULDBLOCK
3652 #if EWOULDBLOCK != EAGAIN
3653 if (sys_errno == EWOULDBLOCK) {
3654 *retry = true;
3655 return sys_errno;
3657 #endif
3658 #endif
3660 return sys_errno;
3663 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3665 int ret;
3666 int err;
3667 bool retry;
3668 NTSTATUS status;
3670 if (xconn->smb2.send_queue == NULL) {
3671 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3672 return NT_STATUS_OK;
3675 while (xconn->smb2.send_queue != NULL) {
3676 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3677 bool ok;
3679 if (e->sendfile_header != NULL) {
3680 size_t size = 0;
3681 size_t i = 0;
3682 uint8_t *buf;
3684 status = NT_STATUS_INTERNAL_ERROR;
3686 for (i=0; i < e->count; i++) {
3687 size += e->vector[i].iov_len;
3690 if (size <= e->sendfile_header->length) {
3691 buf = e->sendfile_header->data;
3692 } else {
3693 buf = talloc_array(e->mem_ctx, uint8_t, size);
3694 if (buf == NULL) {
3695 return NT_STATUS_NO_MEMORY;
3699 size = 0;
3700 for (i=0; i < e->count; i++) {
3701 memcpy(buf+size,
3702 e->vector[i].iov_base,
3703 e->vector[i].iov_len);
3704 size += e->vector[i].iov_len;
3707 e->sendfile_header->data = buf;
3708 e->sendfile_header->length = size;
3709 e->sendfile_status = &status;
3710 e->count = 0;
3712 xconn->smb2.send_queue_len--;
3713 DLIST_REMOVE(xconn->smb2.send_queue, e);
3715 * This triggers the sendfile path via
3716 * the destructor.
3718 talloc_free(e->mem_ctx);
3720 if (!NT_STATUS_IS_OK(status)) {
3721 return status;
3723 continue;
3726 ret = writev(xconn->transport.sock, e->vector, e->count);
3727 if (ret == 0) {
3728 /* propagate end of file */
3729 return NT_STATUS_INTERNAL_ERROR;
3731 err = socket_error_from_errno(ret, errno, &retry);
3732 if (retry) {
3733 /* retry later */
3734 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3735 return NT_STATUS_OK;
3737 if (err != 0) {
3738 return map_nt_error_from_unix_common(err);
3741 ok = iov_advance(&e->vector, &e->count, ret);
3742 if (!ok) {
3743 return NT_STATUS_INTERNAL_ERROR;
3746 if (e->count > 0) {
3747 /* we have more to write */
3748 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3749 return NT_STATUS_OK;
3752 xconn->smb2.send_queue_len--;
3753 DLIST_REMOVE(xconn->smb2.send_queue, e);
3754 talloc_free(e->mem_ctx);
3758 * Restart reads if we were blocked on
3759 * draining the send queue.
3762 status = smbd_smb2_request_next_incoming(xconn);
3763 if (!NT_STATUS_IS_OK(status)) {
3764 return status;
3767 return NT_STATUS_OK;
3770 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3771 uint16_t fde_flags)
3773 struct smbd_server_connection *sconn = xconn->client->sconn;
3774 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3775 struct smbd_smb2_request *req = NULL;
3776 size_t min_recvfile_size = UINT32_MAX;
3777 int ret;
3778 int err;
3779 bool retry;
3780 NTSTATUS status;
3781 NTTIME now;
3783 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3785 * we're not supposed to do any io
3787 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3788 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3789 return NT_STATUS_OK;
3792 if (fde_flags & TEVENT_FD_WRITE) {
3793 status = smbd_smb2_flush_send_queue(xconn);
3794 if (!NT_STATUS_IS_OK(status)) {
3795 return status;
3799 if (!(fde_flags & TEVENT_FD_READ)) {
3800 return NT_STATUS_OK;
3803 if (state->req == NULL) {
3804 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3805 return NT_STATUS_OK;
3808 again:
3809 if (!state->hdr.done) {
3810 state->hdr.done = true;
3812 state->vector.iov_base = (void *)state->hdr.nbt;
3813 state->vector.iov_len = NBT_HDR_SIZE;
3816 ret = readv(xconn->transport.sock, &state->vector, 1);
3817 if (ret == 0) {
3818 /* propagate end of file */
3819 return NT_STATUS_END_OF_FILE;
3821 err = socket_error_from_errno(ret, errno, &retry);
3822 if (retry) {
3823 /* retry later */
3824 TEVENT_FD_READABLE(xconn->transport.fde);
3825 return NT_STATUS_OK;
3827 if (err != 0) {
3828 return map_nt_error_from_unix_common(err);
3831 if (ret < state->vector.iov_len) {
3832 uint8_t *base;
3833 base = (uint8_t *)state->vector.iov_base;
3834 base += ret;
3835 state->vector.iov_base = (void *)base;
3836 state->vector.iov_len -= ret;
3837 /* we have more to read */
3838 TEVENT_FD_READABLE(xconn->transport.fde);
3839 return NT_STATUS_OK;
3842 if (state->pktlen > 0) {
3843 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3845 * Not a possible receivefile write.
3846 * Read the rest of the data.
3848 state->doing_receivefile = false;
3850 state->pktbuf = talloc_realloc(state->req,
3851 state->pktbuf,
3852 uint8_t,
3853 state->pktfull);
3854 if (state->pktbuf == NULL) {
3855 return NT_STATUS_NO_MEMORY;
3858 state->vector.iov_base = (void *)(state->pktbuf +
3859 state->pktlen);
3860 state->vector.iov_len = (state->pktfull -
3861 state->pktlen);
3863 state->pktlen = state->pktfull;
3864 goto again;
3868 * Either this is a receivefile write so we've
3869 * done a short read, or if not we have all the data.
3871 goto got_full;
3875 * Now we analyze the NBT header
3877 if (state->hdr.nbt[0] != 0x00) {
3878 state->min_recv_size = 0;
3880 state->pktfull = smb2_len(state->hdr.nbt);
3881 if (state->pktfull == 0) {
3882 goto got_full;
3885 if (state->min_recv_size != 0) {
3886 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3887 min_recvfile_size += state->min_recv_size;
3890 if (state->pktfull > min_recvfile_size) {
3892 * Might be a receivefile write. Read the SMB2 HEADER +
3893 * SMB2_WRITE header first. Set 'doing_receivefile'
3894 * as we're *attempting* receivefile write. If this
3895 * turns out not to be a SMB2_WRITE request or otherwise
3896 * not suitable then we'll just read the rest of the data
3897 * the next time this function is called.
3899 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3900 state->doing_receivefile = true;
3901 } else {
3902 state->pktlen = state->pktfull;
3905 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3906 if (state->pktbuf == NULL) {
3907 return NT_STATUS_NO_MEMORY;
3910 state->vector.iov_base = (void *)state->pktbuf;
3911 state->vector.iov_len = state->pktlen;
3913 goto again;
3915 got_full:
3917 if (state->hdr.nbt[0] != 0x00) {
3918 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3919 state->hdr.nbt[0]));
3921 req = state->req;
3922 ZERO_STRUCTP(state);
3923 state->req = req;
3924 state->min_recv_size = lp_min_receive_file_size();
3925 req = NULL;
3926 goto again;
3929 req = state->req;
3930 state->req = NULL;
3932 req->request_time = timeval_current();
3933 now = timeval_to_nttime(&req->request_time);
3935 status = smbd_smb2_inbuf_parse_compound(xconn,
3936 now,
3937 state->pktbuf,
3938 state->pktlen,
3939 req,
3940 &req->in.vector,
3941 &req->in.vector_count);
3942 if (!NT_STATUS_IS_OK(status)) {
3943 return status;
3946 if (state->doing_receivefile) {
3947 req->smb1req = talloc_zero(req, struct smb_request);
3948 if (req->smb1req == NULL) {
3949 return NT_STATUS_NO_MEMORY;
3951 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3954 ZERO_STRUCTP(state);
3956 req->current_idx = 1;
3958 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3959 req->current_idx, req->in.vector_count));
3961 status = smbd_smb2_request_validate(req);
3962 if (!NT_STATUS_IS_OK(status)) {
3963 return status;
3966 status = smbd_smb2_request_setup_out(req);
3967 if (!NT_STATUS_IS_OK(status)) {
3968 return status;
3971 status = smbd_smb2_request_dispatch(req);
3972 if (!NT_STATUS_IS_OK(status)) {
3973 return status;
3976 sconn->num_requests++;
3978 /* The timeout_processing function isn't run nearly
3979 often enough to implement 'max log size' without
3980 overrunning the size of the file by many megabytes.
3981 This is especially true if we are running at debug
3982 level 10. Checking every 50 SMB2s is a nice
3983 tradeoff of performance vs log file size overrun. */
3985 if ((sconn->num_requests % 50) == 0 &&
3986 need_to_check_log_size()) {
3987 change_to_root_user();
3988 check_log_size();
3991 status = smbd_smb2_request_next_incoming(xconn);
3992 if (!NT_STATUS_IS_OK(status)) {
3993 return status;
3996 return NT_STATUS_OK;
3999 static void smbd_smb2_connection_handler(struct tevent_context *ev,
4000 struct tevent_fd *fde,
4001 uint16_t flags,
4002 void *private_data)
4004 struct smbXsrv_connection *xconn =
4005 talloc_get_type_abort(private_data,
4006 struct smbXsrv_connection);
4007 NTSTATUS status;
4009 status = smbd_smb2_io_handler(xconn, flags);
4010 if (!NT_STATUS_IS_OK(status)) {
4011 smbd_server_connection_terminate(xconn, nt_errstr(status));
4012 return;